visitCall method
dynamic
visitCall(
- CallExpression node
)
Implementation
@override
visitCall(CallExpression node) {
dynamic val;
try {
dynamic method;
if (node.callee is NameExpression) {
if (node.isNew) {
//a new object is being instantiated
final dynamic _class = getValue((node.callee as NameExpression).name);
if (_class == null) {
throw JSException(node.line ?? -1,
'Cannot instantiate object of class ${(node.callee as NameExpression).name} No definition found for class in code ${getCode(node)}.',
recovery: 'Check your syntax and try again.');
}
if (_class is JavascriptFunction) {
final Map<String, dynamic> instance = {};
InvokableController.setPrototype(instance, _class.prototype);
final dynamic constructed = _class.callWithThis(
computeArguments(node.arguments, resolveNames: true), instance);
val = constructed is Map ||
constructed is Invokable ||
constructed is List
? constructed
: instance;
return val;
}
if (!(_class is Invokable)) {
throw JSException(node.line ?? -1,
'Cannot instantiate object of class ${(node.callee as NameExpression).name} Class is not invokable in code ${getCode(node)}.',
recovery: 'Check your syntax and try again.');
}
if (_class.methods()['init'] == null) {
throw JSException(node.line ?? -1,
'Cannot instantiate object of class ${(node.callee as NameExpression).name} No init method found for class in code ${getCode(node)}. init method is called to construct an instance. It must take List<parms> as argument.',
recovery: 'Check your syntax and try again.');
}
method = _class.methods()['init'];
} else {
method = getValue((node.callee as NameExpression).name);
if (method == null) {
if (node.optional) return jsUndefined;
throw JSException(
node.line ?? -1, 'No definition found for ${getCode(node)}.',
recovery: 'Check your syntax and try again.');
}
}
val = executeMethod(method, node.arguments,
thisArg: getContextForScope(program).getContextMap());
} else if (node.callee is FunctionExpression) {
method = visitFunctionExpression(node.callee as FunctionExpression);
val = executeMethod(method, node.arguments,
thisArg: getContextForScope(program).getContextMap());
} else if (node.callee is MemberExpression ||
node.callee is IndexExpression) {
PropertyPattern? pattern;
dynamic method;
MethodExecutor? methodExecutor;
String? methodName;
if (node.callee is MemberExpression) {
pattern = visitMember(node.callee as MemberExpression,
computeAsPattern: true);
if (pattern == null) return jsUndefined;
if (pattern!.obj is MethodExecutor) {
methodExecutor = pattern!.obj as MethodExecutor;
methodName = pattern.property;
} else if ((pattern.obj is JavascriptFunction ||
pattern.obj is Function) &&
(pattern.property == 'call' ||
pattern.property == 'apply' ||
pattern.property == 'bind')) {
method = _functionMethod(pattern.obj, pattern.property);
} else {
method = InvokableController.methods(pattern.obj)[pattern.property];
}
method ??=
InvokableController.methods(pattern!.obj)[pattern.property];
method ??=
InvokableController.getProperty(pattern.obj, pattern.property);
} else if (node.callee is IndexExpression) {
pattern = visitIndex(node.callee as IndexExpression,
computeAsPattern: true);
if (pattern == null) return jsUndefined;
if ((pattern!.obj is JavascriptFunction || pattern.obj is Function) &&
(pattern.property == 'call' ||
pattern.property == 'apply' ||
pattern.property == 'bind')) {
method = _functionMethod(pattern.obj, pattern.property);
} else {
method =
InvokableController.getProperty(pattern.obj, pattern.property);
}
//old: method = pattern!.obj.getProperty(pattern.property);
}
if (method == null) {
if (node.optional) return jsUndefined;
throw JSException(
node.line ?? -1,
"cannot compute statement=" +
node.toString() +
" "
"as no method found for property=" +
((pattern != null) ? pattern.property.toString() : ''),
detailedError: 'Code: ${getCode(node)}');
}
try {
val = executeMethod(method, node.arguments,
methodName: methodName,
executor: methodExecutor,
thisArg: pattern?.obj);
} on JSException catch (e) {
rethrow;
} catch (e) {
throw JSException(node.line ?? -1,
'Error while executing method: ${getCode(node)}. Underlying error:${e.toString()}',
originalError: e);
}
}
} on JSException catch (e) {
rethrow;
} on InvalidPropertyException catch (e) {
throw JSException(node.line ?? 1, '${e.message}. Code: ${getCode(node)}');
}
return val;
}