silphius/app/astride/evaluators/call.js
2024-06-30 14:29:10 -05:00

54 lines
1.4 KiB
JavaScript

import fastCall from '@/util/fast-call.js';
export default function(node, {evaluate, scope}) {
let asyncArgs = false;
const args = [];
for (let i = 0; i < node.arguments.length; i++) {
const arg = node.arguments[i];
const {async, value} = evaluate(arg, {scope});
asyncArgs ||= async;
args.push(value);
}
const {callee} = node;
const {
computed,
object,
property,
} = callee;
const invoke = (fn, holder, args) => {
if (node.optional && !fn) {
return undefined;
}
return fastCall(fn, holder, args);
};
if (!('MemberExpression' === callee.type)) {
const {async, value} = evaluate(callee, {scope});
if (asyncArgs || async) {
return {
async: true,
value: Promise
.all([value, Promise.all(args)])
.then(([callee, args]) => invoke(callee, undefined, args)),
};
}
return {value: invoke(value, undefined, args)};
}
const O = evaluate(object, {scope});
const P = computed
? evaluate(property, {scope})
// Otherwise, identifier.
: {value: property.name};
if (asyncArgs || O.async || P.async) {
return {
async: true,
value: Promise
.all([O.value, P.value, Promise.all(args)])
.then(([O, P, args]) => invoke(callee.optional ? O?.[P] : O[P], O, args)),
};
}
return {
async: false,
value: invoke(callee.optional ? O.value?.[P.value] : O.value[P.value], O.value, args),
};
}