import fastCall from '@/util/fast-call.js'; import { isMemberExpression, } from '@/astride/types.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 (!isMemberExpression(callee)) { 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 {value: invoke(callee.optional ? O.value?.[P.value] : O.value[P.value], O.value, args)}; }