Esempio n. 1
0
  wrapSuperCall(bareSuper, superRef, thisRef, body) {
    let bareSuperNode = bareSuper.node;

    if (this.isLoose) {
      bareSuperNode.arguments.unshift(t.thisExpression());
      if (bareSuperNode.arguments.length === 2 && t.isSpreadElement(bareSuperNode.arguments[1]) && t.isIdentifier(bareSuperNode.arguments[1].argument, { name: "arguments" })) {
        // special case single arguments spread
        bareSuperNode.arguments[1] = bareSuperNode.arguments[1].argument;
        bareSuperNode.callee = t.memberExpression(superRef, t.identifier("apply"));
      } else {
        bareSuperNode.callee = t.memberExpression(superRef, t.identifier("call"));
      }
    } else {
      bareSuperNode = optimiseCall(
        t.callExpression(
          t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
          [this.classRef]
        ),
        t.thisExpression(),
        bareSuperNode.arguments
      );
    }

    let call = t.callExpression(
      this.file.addHelper("possibleConstructorReturn"),
      [t.thisExpression(), bareSuperNode]
    );

    let bareSuperAfter = this.bareSuperAfter.map((fn) => fn(thisRef));

    if (bareSuper.parentPath.isExpressionStatement() && bareSuper.parentPath.container === body.node.body && body.node.body.length - 1 === bareSuper.parentPath.key) {
      // this super call is the last statement in the body so we can just straight up
      // turn it into a return

      if (this.superThises.length || bareSuperAfter.length) {
        bareSuper.scope.push({ id: thisRef });
        call = t.assignmentExpression("=", thisRef, call);
      }

      if (bareSuperAfter.length) {
        call = t.toSequenceExpression([call, ...bareSuperAfter, thisRef]);
      }

      bareSuper.parentPath.replaceWith(t.returnStatement(call));
    } else {
      bareSuper.replaceWithMultiple([
        t.variableDeclaration("var", [
          t.variableDeclarator(thisRef, call)
        ]),
        ...bareSuperAfter,
        t.expressionStatement(thisRef)
      ]);
    }

  }
Esempio n. 2
0
export function replaceExpressionWithStatements(nodes: Array<Object>) {
  this.resync();

  let toSequenceExpression = t.toSequenceExpression(nodes, this.scope);

  if (t.isSequenceExpression(toSequenceExpression)) {
    let exprs = toSequenceExpression.expressions;

    if (exprs.length >= 2 && this.parentPath.isExpressionStatement()) {
      this._maybePopFromStatements(exprs);
    }

    // could be just one element due to the previous maybe popping
    if (exprs.length === 1) {
      this.replaceWith(exprs[0]);
    } else {
      this.replaceWith(toSequenceExpression);
    }
  } else if (toSequenceExpression) {
    this.replaceWith(toSequenceExpression);
  } else {
    let container = t.functionExpression(null, [], t.blockStatement(nodes));
    container.shadow = true;

    this.replaceWith(t.callExpression(container, []));
    this.traverse(hoistVariablesVisitor);

    // add implicit returns to all ending expression statements
    let completionRecords: Array<NodePath> = this.get("callee").getCompletionRecords();
    for (let path of completionRecords) {
      if (!path.isExpressionStatement()) continue;

      let loop = path.findParent((path) => path.isLoop());
      if (loop) {
        let callee = this.get("callee");

        let uid = callee.scope.generateDeclaredUidIdentifier("ret");
        callee.get("body").pushContainer("body", t.returnStatement(uid));

        path.get("expression").replaceWith(
          t.assignmentExpression("=", uid, path.node.expression)
        );
      } else {
        path.replaceWith(t.returnStatement(path.node.expression));
      }
    }

    return this.node;
  }
}