visitFunctionNode method

  1. @override
dynamic visitFunctionNode(
  1. FunctionNode node, {
  2. bool? inheritContext,
})

Implementation

@override
visitFunctionNode(FunctionNode node, {bool? inheritContext}) {
  final List<dynamic> args = computeArguments(node.params);
  final capturedLexicalContexts =
      List<_LexicalContext>.from(_lexicalContexts);
  late JavascriptFunction fn;
  fn = JavascriptFunction((List<dynamic>? _params, [dynamic thisArg]) {
    /*
      1. create a map, parmValueMap
      2. go through params and create a args[i]: parm[i] entry in the map
      3. push the map to the context stack
      4. execute the blockstatement or expression
     */
    List<dynamic> params = _params ?? [];
    Map<String, dynamic> ctx = {};

    if (node.params != null) {
      for (int i = 0; i < node.params.length; i++) {
        final param = node.params[i];
        if (param is RestParameter) {
          _bindParameter(ctx, param.name, params.skip(i).toList(),
              line: param.line ?? node.line ?? 1);
          break;
        }
        dynamic value = i < params.length ? params[i] : null;
        if (param is DefaultParameter && value == null) {
          value = getValueFromExpression(param.defaultValue);
        }
        _bindParameter(
            ctx, param is DefaultParameter ? param.name : param, value,
            line: param.line ?? node.line ?? 1);
      }
    }
    ctx['arguments'] = _buildArgumentsObject(params, fn);
    ctx['this'] = thisArg ?? getContextForScope(program).getContextMap();
    Context context = SimpleContext(ctx);
    // Inherit parent contexts so nested functions can see outer declarations.
    JSInterpreter i = cloneForContext(node, context, inheritContext ?? true);
    i._lexicalContexts
      ..clear()
      ..addAll(capturedLexicalContexts);
    if (node.isAsync) {
      return JSPromise.fromFuture(i._executeAsyncBody(node.body));
    }
    dynamic rtn;
    try {
      if (node.body != null) {
        rtn = node.body.visitBy(i);
      }
    } on ControlFlowReturnException catch (e) {
      rtn = e.returnValue;
    }
    if (rtn is Node) {
      rtn = i.getValueFromNode(rtn);
    }
    return rtn;
  }, code.substring(node.start!, node.end));
  return fn;
}