// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart2js.js_emitter;

/// This class should morph into something that makes it easy to build
/// JavaScript representations of libraries, class-sides, and instance-sides.
/// Initially, it is just a placeholder for code that is moved from
/// [CodeEmitterTask].
class ContainerBuilder {
  final Map<Element, Element> staticGetters = new Map<Element, Element>();

  /// A cache of synthesized closures for top-level, static or
  /// instance methods.
  final Map<String, Element> methodClosures = <String, Element>{};

  CodeEmitterTask task;

  Namer get namer => task.namer;

  Compiler get compiler => task.compiler;

  String get N => task.N;

  JavaScriptBackend get backend => task.backend;

  /**
   * Generate stubs to handle invocation of methods with optional
   * arguments.
   *
   * A method like [: foo([x]) :] may be invoked by the following
   * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this
   * function for detailed examples.
   */
  void addParameterStub(FunctionElement member,
                        Selector selector,
                        DefineStubFunction defineStub,
                        Set<String> alreadyGenerated) {
    FunctionSignature parameters = member.computeSignature(compiler);
    int positionalArgumentCount = selector.positionalArgumentCount;
    if (positionalArgumentCount == parameters.parameterCount) {
      assert(selector.namedArgumentCount == 0);
      return;
    }
    if (parameters.optionalParametersAreNamed
        && selector.namedArgumentCount == parameters.optionalParameterCount) {
      // If the selector has the same number of named arguments as the element,
      // we don't need to add a stub. The call site will hit the method
      // directly.
      return;
    }
    ConstantHandler handler = compiler.constantHandler;
    List<SourceString> names = selector.getOrderedNamedArguments();

    String invocationName = namer.invocationName(selector);
    if (alreadyGenerated.contains(invocationName)) return;
    alreadyGenerated.add(invocationName);

    bool isInterceptedMethod = backend.isInterceptedMethod(member);

    // If the method is intercepted, we need to also pass the actual receiver.
    int extraArgumentCount = isInterceptedMethod ? 1 : 0;
    // Use '$receiver' to avoid clashes with other parameter names. Using
    // '$receiver' works because [:namer.safeName:] used for getting parameter
    // names never returns a name beginning with a single '$'.
    String receiverArgumentName = r'$receiver';

    // The parameters that this stub takes.
    List<jsAst.Parameter> parametersBuffer =
        new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
    // The arguments that will be passed to the real method.
    List<jsAst.Expression> argumentsBuffer =
        new List<jsAst.Expression>(
            parameters.parameterCount + extraArgumentCount);

    int count = 0;
    if (isInterceptedMethod) {
      count++;
      parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
      argumentsBuffer[0] = js(receiverArgumentName);
      task.interceptorInvocationNames.add(invocationName);
    }

    int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
    // Includes extra receiver argument when using interceptor convention
    int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;

    TreeElements elements =
        compiler.enqueuer.resolution.getCachedElements(member);

    int parameterIndex = 0;
    parameters.orderedForEachParameter((Element element) {
      // Use generic names for closures to facilitate code sharing.
      String jsName = member is ClosureInvocationElement
          ? 'p${parameterIndex++}'
          : backend.namer.safeName(element.name.slowToString());
      assert(jsName != receiverArgumentName);
      if (count < optionalParameterStart) {
        parametersBuffer[count] = new jsAst.Parameter(jsName);
        argumentsBuffer[count] = js(jsName);
      } else {
        int index = names.indexOf(element.name);
        if (index != -1) {
          indexOfLastOptionalArgumentInParameters = count;
          // The order of the named arguments is not the same as the
          // one in the real method (which is in Dart source order).
          argumentsBuffer[count] = js(jsName);
          parametersBuffer[optionalParameterStart + index] =
              new jsAst.Parameter(jsName);
        } else {
          Constant value = handler.initialVariableValues[element];
          if (value == null) {
            argumentsBuffer[count] = task.constantReference(new NullConstant());
          } else {
            if (!value.isNull()) {
              // If the value is the null constant, we should not pass it
              // down to the native method.
              indexOfLastOptionalArgumentInParameters = count;
            }
            argumentsBuffer[count] = task.constantReference(value);
          }
        }
      }
      count++;
    });

    List body;
    if (member.hasFixedBackendName()) {
      body = task.nativeEmitter.generateParameterStubStatements(
          member, isInterceptedMethod, invocationName,
          parametersBuffer, argumentsBuffer,
          indexOfLastOptionalArgumentInParameters);
    } else {
      body = [js.return_(
          js('this')[namer.getNameOfInstanceMember(member)](argumentsBuffer))];
    }

    jsAst.Fun function = js.fun(parametersBuffer, body);

    defineStub(invocationName, function);

    String reflectionName = task.getReflectionName(selector, invocationName);
    if (reflectionName != null) {
      var reflectable =
          js(backend.isAccessibleByReflection(member) ? '1' : '0');
      defineStub('+$reflectionName', reflectable);
    }
  }

  void addParameterStubs(FunctionElement member,
                         DefineStubFunction defineStub) {
    // We fill the lists depending on the selector. For example,
    // take method foo:
    //    foo(a, b, {c, d});
    //
    // We may have multiple ways of calling foo:
    // (1) foo(1, 2);
    // (2) foo(1, 2, c: 3);
    // (3) foo(1, 2, d: 4);
    // (4) foo(1, 2, c: 3, d: 4);
    // (5) foo(1, 2, d: 4, c: 3);
    //
    // What we generate at the call sites are:
    // (1) foo$2(1, 2);
    // (2) foo$3$c(1, 2, 3);
    // (3) foo$3$d(1, 2, 4);
    // (4) foo$4$c$d(1, 2, 3, 4);
    // (5) foo$4$c$d(1, 2, 3, 4);
    //
    // The stubs we generate are (expressed in Dart):
    // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null)
    // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null);
    // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d);
    // (4) No stub generated, call is direct.
    // (5) No stub generated, call is direct.

    // Keep a cache of which stubs have already been generated, to
    // avoid duplicates. Note that even if selectors are
    // canonicalized, we would still need this cache: a typed selector
    // on A and a typed selector on B could yield the same stub.
    Set<String> generatedStubNames = new Set<String>();
    bool isClosureInvocation =
        member.name == namer.closureInvocationSelectorName;
    if (backend.isNeededForReflection(member) ||
        (compiler.enabledFunctionApply && isClosureInvocation)) {
      // If [Function.apply] is called, we pessimistically compile all
      // possible stubs for this closure.
      FunctionSignature signature = member.computeSignature(compiler);
      Set<Selector> selectors = signature.optionalParametersAreNamed
          ? computeSeenNamedSelectors(member)
          : computeOptionalSelectors(signature, member);
      for (Selector selector in selectors) {
        addParameterStub(member, selector, defineStub, generatedStubNames);
      }
      if (signature.optionalParametersAreNamed && isClosureInvocation) {
        addCatchAllParameterStub(member, signature, defineStub);
      }
    } else {
      Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name];
      if (selectors == null) return;
      for (Selector selector in selectors) {
        if (!selector.applies(member, compiler)) continue;
        addParameterStub(member, selector, defineStub, generatedStubNames);
      }
    }
  }

  Set<Selector> computeSeenNamedSelectors(FunctionElement element) {
    Set<Selector> selectors = compiler.codegenWorld.invokedNames[element.name];
    Set<Selector> result = new Set<Selector>();
    if (selectors == null) return result;
    for (Selector selector in selectors) {
      if (!selector.applies(element, compiler)) continue;
      result.add(selector);
    }
    return result;
  }

  void addCatchAllParameterStub(FunctionElement member,
                                FunctionSignature signature,
                                DefineStubFunction defineStub) {
    // See Primities.applyFunction in js_helper.dart for details.
    List<jsAst.Property> properties = <jsAst.Property>[];
    for (Element element in signature.orderedOptionalParameters) {
      String jsName = backend.namer.safeName(element.name.slowToString());
      Constant value = compiler.constantHandler.initialVariableValues[element];
      jsAst.Expression reference = null;
      if (value == null) {
        reference = new jsAst.LiteralNull();
      } else {
        reference = task.constantReference(value);
      }
      properties.add(new jsAst.Property(js.string(jsName), reference));
    }
    defineStub(
        backend.namer.callCatchAllName,
        js.fun([], js.return_(new jsAst.ObjectInitializer(properties))));
  }

  /**
   * Compute the set of possible selectors in the presence of optional
   * non-named parameters.
   */
  Set<Selector> computeOptionalSelectors(FunctionSignature signature,
                                         FunctionElement element) {
    Set<Selector> selectors = new Set<Selector>();
    // Add the selector that does not have any optional argument.
    selectors.add(new Selector(SelectorKind.CALL,
                               element.name,
                               element.getLibrary(),
                               signature.requiredParameterCount,
                               <SourceString>[]));

    // For each optional parameter, we increment the number of passed
    // argument.
    for (int i = 1; i <= signature.optionalParameterCount; i++) {
      selectors.add(new Selector(SelectorKind.CALL,
                                 element.name,
                                 element.getLibrary(),
                                 signature.requiredParameterCount + i,
                                 <SourceString>[]));
    }
    return selectors;
  }

  void emitStaticFunctionGetters(CodeBuffer eagerBuffer) {
    task.addComment('Static function getters', task.mainBuffer);
    for (FunctionElement element in
             Elements.sortedByPosition(staticGetters.keys)) {
      Element closure = staticGetters[element];
      CodeBuffer buffer =
          task.isDeferred(element) ? task.deferredConstants : eagerBuffer;
      String closureClass = namer.isolateAccess(closure);
      String name = namer.getStaticClosureName(element);

      String closureName = namer.getStaticClosureName(element);
      jsAst.Node assignment = js(
          'init.globalFunctions["$closureName"] ='
          ' ${namer.globalObjectFor(element)}.$name ='
          ' new $closureClass(#, "$closureName")',
          namer.elementAccess(element));
      buffer.write(jsAst.prettyPrint(assignment, compiler));
      buffer.write('$N');
    }
  }

  void emitStaticFunctionClosures() {
    Set<FunctionElement> functionsNeedingGetter =
        compiler.codegenWorld.staticFunctionsNeedingGetter;
    for (FunctionElement element in
             Elements.sortedByPosition(functionsNeedingGetter)) {
      String superName = namer.getNameOfClass(compiler.closureClass);
      int parameterCount = element.functionSignature.parameterCount;
      String name = 'Closure\$$parameterCount';
      assert(task.instantiatedClasses.contains(compiler.closureClass));

      ClassElement closureClassElement = new ClosureClassElement(
          null, new SourceString(name), compiler, element,
          element.getCompilationUnit());
      // Now add the methods on the closure class. The instance method does not
      // have the correct name. Since [addParameterStubs] use the name to create
      // its stubs we simply create a fake element with the correct name.
      // Note: the callElement will not have any enclosingElement.
      FunctionElement callElement =
          new ClosureInvocationElement(namer.closureInvocationSelectorName,
                                       element);

      String invocationName = namer.instanceMethodName(callElement);
      String mangledName = namer.getNameOfClass(closureClassElement);

      // Define the constructor with a name so that Object.toString can
      // find the class name of the closure class.
      ClassBuilder closureBuilder = new ClassBuilder();
      // If a static function is used as a closure we need to add its name
      // in case it is used in spawnFunction.
      String methodName = namer.STATIC_CLOSURE_NAME_NAME;
      List<String> fieldNames = <String>[invocationName, methodName];
      closureBuilder.addProperty('',
          js.string("$superName;${fieldNames.join(',')}"));

      addParameterStubs(callElement, closureBuilder.addProperty);

      void emitFunctionTypeSignature(Element method, FunctionType methodType) {
        RuntimeTypes rti = backend.rti;
        // [:() => null:] is dummy encoding of [this] which is never needed for
        // the encoding of the type of the static [method].
        jsAst.Expression encoding =
            rti.getSignatureEncoding(methodType, js('null'));
        String operatorSignature = namer.operatorSignature();
        // TODO(johnniwinther): Make MiniJsParser support function expressions.
        closureBuilder.addProperty(operatorSignature, encoding);
      }

      void emitIsFunctionTypeTest(FunctionType functionType) {
        String operator = namer.operatorIsType(functionType);
        closureBuilder.addProperty(operator, js('true'));
      }

      FunctionType methodType = element.computeType(compiler);
      Map<FunctionType, bool> functionTypeChecks =
          task.getFunctionTypeChecksOn(methodType);
      task.generateFunctionTypeTests(element, methodType, functionTypeChecks,
          emitFunctionTypeSignature, emitIsFunctionTypeTest);

      closureClassElement =
          addClosureIfNew(closureBuilder, closureClassElement, fieldNames);
      staticGetters[element] = closureClassElement;

    }
  }

  ClassElement addClosureIfNew(ClassBuilder builder,
                               ClassElement closure,
                               List<String> fieldNames) {
    String key =
        jsAst.prettyPrint(builder.toObjectInitializer(), compiler).getText();
    return methodClosures.putIfAbsent(key, () {
      String mangledName = namer.getNameOfClass(closure);
      emitClosureInPrecompiledFunction(mangledName, fieldNames);
      return closure;
    });
  }

  void emitClosureInPrecompiledFunction(String mangledName,
                                        List<String> fieldNames) {
    List<String> fields = fieldNames;
    String constructorName = mangledName;
    task.precompiledFunction.add(new jsAst.FunctionDeclaration(
        new jsAst.VariableDeclaration(constructorName),
        js.fun(fields, fields.map(
            (name) => js('this.$name = $name')).toList())));
    task.precompiledFunction.addAll([
        js('$constructorName.builtin\$cls = "$constructorName"'),
        js('\$desc=\$collectedClasses.$constructorName'),
        js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')),
        js('$constructorName.prototype = \$desc'),
    ]);

    task.precompiledConstructorNames.add(js(constructorName));
  }

  /**
   * Documentation wanted -- johnniwinther
   *
   * Invariant: [member] must be a declaration element.
   */
  void emitDynamicFunctionGetter(FunctionElement member,
                                 DefineStubFunction defineStub) {
    assert(invariant(member, member.isDeclaration));
    assert(task.instantiatedClasses.contains(compiler.boundClosureClass));
    // For every method that has the same name as a property-get we create a
    // getter that returns a bound closure. Say we have a class 'A' with method
    // 'foo' and somewhere in the code there is a dynamic property get of
    // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript):
    //
    // class A {
    //    foo(x, y, z) { ... } // Original function.
    //    get foo { return new BoundClosure499(this, "foo"); }
    // }
    // class BoundClosure499 extends BoundClosure {
    //   BoundClosure499(this.self, this.name);
    //   $call3(x, y, z) { return self[name](x, y, z); }
    // }

    bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0;
    int parameterCount = member.parameterCount(compiler);

    // Intercepted methods take an extra parameter, which is the
    // receiver of the call.
    bool inInterceptor = backend.isInterceptedMethod(member);
    List<String> fieldNames = <String>[];
    compiler.boundClosureClass.forEachInstanceField((_, Element field) {
      fieldNames.add(namer.getNameOfInstanceMember(field));
    });

    ClassElement classElement = member.getEnclosingClass();
    String name = inInterceptor
        ? 'BoundClosure\$i${parameterCount}'
        : 'BoundClosure\$${parameterCount}';

    ClassElement closureClassElement = new ClosureClassElement(
        null, new SourceString(name), compiler, member,
        member.getCompilationUnit());
    String superName = namer.getNameOfClass(closureClassElement.superclass);

    // Define the constructor with a name so that Object.toString can
    // find the class name of the closure class.
    ClassBuilder boundClosureBuilder = new ClassBuilder();
    boundClosureBuilder.addProperty('',
        js.string("$superName;${fieldNames.join(',')}"));
    // Now add the methods on the closure class. The instance method does not
    // have the correct name. Since [addParameterStubs] use the name to create
    // its stubs we simply create a fake element with the correct name.
    // Note: the callElement will not have any enclosingElement.
    FunctionElement callElement = new ClosureInvocationElement(
        namer.closureInvocationSelectorName, member);

    String invocationName = namer.instanceMethodName(callElement);

    List<String> parameters = <String>[];
    List<jsAst.Expression> arguments =
        <jsAst.Expression>[js('this')[fieldNames[0]]];
    if (inInterceptor) {
      arguments.add(js('this')[fieldNames[2]]);
    }
    for (int i = 0; i < parameterCount; i++) {
      String name = 'p$i';
      parameters.add(name);
      arguments.add(js(name));
    }

    jsAst.Expression fun = js.fun(
        parameters,
        js.return_(
            js('this')[fieldNames[1]]['call'](arguments)));
    boundClosureBuilder.addProperty(invocationName, fun);

    addParameterStubs(callElement, boundClosureBuilder.addProperty);

    void emitFunctionTypeSignature(Element method, FunctionType methodType) {
      jsAst.Expression encoding = backend.rti.getSignatureEncoding(
          methodType, js('this')[fieldNames[0]]);
      String operatorSignature = namer.operatorSignature();
      boundClosureBuilder.addProperty(operatorSignature, encoding);
    }

    void emitIsFunctionTypeTest(FunctionType functionType) {
      String operator = namer.operatorIsType(functionType);
      boundClosureBuilder.addProperty(operator,
          new jsAst.LiteralBool(true));
    }

    DartType memberType = member.computeType(compiler);
    Map<FunctionType, bool> functionTypeChecks =
        task.getFunctionTypeChecksOn(memberType);

    task.generateFunctionTypeTests(member, memberType, functionTypeChecks,
        emitFunctionTypeSignature, emitIsFunctionTypeTest);

    closureClassElement =
        addClosureIfNew(boundClosureBuilder, closureClassElement, fieldNames);

    String closureClass = namer.isolateAccess(closureClassElement);

    // And finally the getter.
    String getterName = namer.getterName(member);
    String targetName = namer.instanceMethodName(member);

    parameters = <String>[];
    jsAst.PropertyAccess method =
        backend.namer.elementAccess(classElement)['prototype'][targetName];
    arguments = <jsAst.Expression>[js('this'), method];

    if (inInterceptor) {
      String receiverArg = fieldNames[2];
      parameters.add(receiverArg);
      arguments.add(js(receiverArg));
    } else {
      // Put null in the intercepted receiver field.
      arguments.add(new jsAst.LiteralNull());
    }

    arguments.add(js.string(targetName));

    jsAst.Expression getterFunction = js.fun(
        parameters, js.return_(js(closureClass).newWith(arguments)));

    defineStub(getterName, getterFunction);
  }

  /**
   * Documentation wanted -- johnniwinther
   *
   * Invariant: [member] must be a declaration element.
   */
  void emitCallStubForGetter(Element member,
                             Set<Selector> selectors,
                             DefineStubFunction defineStub) {
    assert(invariant(member, member.isDeclaration));
    LibraryElement memberLibrary = member.getLibrary();
    // If the method is intercepted, the stub gets the
    // receiver explicitely and we need to pass it to the getter call.
    bool isInterceptedMethod = backend.isInterceptedMethod(member);

    const String receiverArgumentName = r'$receiver';

    jsAst.Expression buildGetter() {
      if (member.isGetter()) {
        String getterName = namer.getterName(member);
        return js('this')[getterName](
            isInterceptedMethod
                ? <jsAst.Expression>[js(receiverArgumentName)]
                : <jsAst.Expression>[]);
      } else {
        String fieldName = member.hasFixedBackendName()
            ? member.fixedBackendName()
            : namer.instanceFieldName(member);
        return js('this')[fieldName];
      }
    }

    // Two selectors may match but differ only in type.  To avoid generating
    // identical stubs for each we track untyped selectors which already have
    // stubs.
    Set<Selector> generatedSelectors = new Set<Selector>();
    for (Selector selector in selectors) {
      if (selector.applies(member, compiler)) {
        selector = selector.asUntyped;
        if (generatedSelectors.contains(selector)) continue;
        generatedSelectors.add(selector);

        String invocationName = namer.invocationName(selector);
        Selector callSelector = new Selector.callClosureFrom(selector);
        String closureCallName = namer.invocationName(callSelector);

        List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
        List<jsAst.Expression> arguments = <jsAst.Expression>[];
        if (isInterceptedMethod) {
          parameters.add(new jsAst.Parameter(receiverArgumentName));
        }

        for (int i = 0; i < selector.argumentCount; i++) {
          String name = 'arg$i';
          parameters.add(new jsAst.Parameter(name));
          arguments.add(js(name));
        }

        jsAst.Fun function = js.fun(
            parameters,
            js.return_(buildGetter()[closureCallName](arguments)));

        defineStub(invocationName, function);
      }
    }
  }

  /**
   * Documentation wanted -- johnniwinther
   *
   * Invariant: [member] must be a declaration element.
   */
  void emitExtraAccessors(Element member, ClassBuilder builder) {
    assert(invariant(member, member.isDeclaration));
    if (member.isGetter() || member.isField()) {
      Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name];
      if (selectors != null && !selectors.isEmpty) {
        emitCallStubForGetter(member, selectors, builder.addProperty);
      }
    } else if (member.isFunction()) {
      if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) {
        emitDynamicFunctionGetter(member, builder.addProperty);
      }
    }
  }

  void addMember(Element member, ClassBuilder builder) {
    assert(invariant(member, member.isDeclaration));

    if (member.isField()) {
      addMemberField(member, builder);
    } else if (member.isFunction() ||
               member.isGenerativeConstructorBody() ||
               member.isGenerativeConstructor() ||
               member.isAccessor()) {
      addMemberMethod(member, builder);
    } else {
      compiler.internalErrorOnElement(
          member, 'unexpected kind: "${member.kind}"');
    }
    if (member.isInstanceMember()) emitExtraAccessors(member, builder);
  }

  void addMemberMethod(FunctionElement member, ClassBuilder builder) {
    if (member.isAbstract(compiler)) return;
    jsAst.Expression code = backend.generatedCode[member];
    if (code == null) return;
    String name = namer.getNameOfMember(member);
    if (backend.isInterceptedMethod(member)) {
      task.interceptorInvocationNames.add(name);
    }
    code = extendWithMetadata(member, code);
    builder.addProperty(name, code);
    String reflectionName = task.getReflectionName(member, name);
    if (reflectionName != null) {
      var reflectable =
          js(backend.isAccessibleByReflection(member) ? '1' : '0');
      builder.addProperty('+$reflectionName', reflectable);
      jsAst.Node defaultValues = task.reifyDefaultArguments(member);
      if (defaultValues != null) {
        String unmangledName = member.name.slowToString();
        builder.addProperty('*$unmangledName', defaultValues);
      }
    }
    code = backend.generatedBailoutCode[member];
    if (code != null) {
      builder.addProperty(namer.getBailoutName(member), code);
    }
    if (member.isInstanceMember()) {
      // TODO(ahe): Where is this done for static/top-level methods?
      FunctionSignature parameters = member.computeSignature(compiler);
      if (!parameters.optionalParameters.isEmpty) {
        addParameterStubs(member, builder.addProperty);
      }
    }
  }

  void addMemberField(VariableElement member, ClassBuilder builder) {
    // For now, do nothing.
  }

  jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) {
    if (!backend.retainMetadataOf(element)) return code;
    return compiler.withCurrentElement(element, () {
      List<int> metadata = <int>[];
      FunctionSignature signature = element.functionSignature;
      if (element.isConstructor()) {
        metadata.add(task.reifyType(element.getEnclosingClass().thisType));
      } else {
        metadata.add(task.reifyType(signature.returnType));
      }
      signature.forEachParameter((Element parameter) {
        metadata
            ..add(task.reifyName(parameter.name))
            ..add(task.reifyType(parameter.computeType(compiler)));
      });
      Link link = element.metadata;
      // TODO(ahe): Why is metadata sometimes null?
      if (link != null) {
        for (; !link.isEmpty; link = link.tail) {
          metadata.add(task.reifyMetadata(link.head));
        }
      }
      code.body.statements.add(js.string(metadata.join(',')).toStatement());
      return code;
    });
  }
}
