Skip to content

Commit

Permalink
Automated g4 rollback of changelist 164306218.
Browse files Browse the repository at this point in the history
*** Reason for rollback ***

Rolling foward. The issue that caused the original rollback was fixed

*** Original change description ***

Automated g4 rollback of changelist 164281442.

*** Reason for rollback ***

Breaks target

*** Original change description ***

Separated Es6ToEs3Converter into two passes, one intended to run before NTI and the other
after. Currently both passes still run before NTI.

***

***

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=164778019
  • Loading branch information
EatingW authored and blickly committed Aug 10, 2017
1 parent 195945b commit cb88c48
Show file tree
Hide file tree
Showing 19 changed files with 425 additions and 270 deletions.
4 changes: 3 additions & 1 deletion src/com/google/javascript/jscomp/DefaultPassConfig.java
Expand Up @@ -184,6 +184,7 @@ protected List<PassFactory> getTranspileOnlyPasses() {
if (options.needsTranspilationFrom(ES6) || options.needsTranspilationFrom(ES7)) { if (options.needsTranspilationFrom(ES6) || options.needsTranspilationFrom(ES7)) {
TranspilationPasses.addEs6EarlyPasses(passes); TranspilationPasses.addEs6EarlyPasses(passes);
TranspilationPasses.addEs6LatePasses(passes); TranspilationPasses.addEs6LatePasses(passes);
TranspilationPasses.addEs6PassesAfterNTI(passes);
TranspilationPasses.addPostCheckPasses(passes); TranspilationPasses.addPostCheckPasses(passes);
if (options.rewritePolyfills) { if (options.rewritePolyfills) {
TranspilationPasses.addRewritePolyfillPass(passes); TranspilationPasses.addRewritePolyfillPass(passes);
Expand Down Expand Up @@ -373,6 +374,7 @@ protected List<PassFactory> getChecks() {


if (options.needsTranspilationFrom(ES6)) { if (options.needsTranspilationFrom(ES6)) {
TranspilationPasses.addEs6LatePasses(checks); TranspilationPasses.addEs6LatePasses(checks);
TranspilationPasses.addEs6PassesAfterNTI(checks);
if (options.rewritePolyfills) { if (options.rewritePolyfills) {
TranspilationPasses.addRewritePolyfillPass(checks); TranspilationPasses.addRewritePolyfillPass(checks);
} }
Expand All @@ -389,7 +391,7 @@ protected List<PassFactory> getChecks() {
checks.add(convertStaticInheritance); checks.add(convertStaticInheritance);
} }


// End of ES6 transpilation passes. // End of ES6 transpilation passes before NTI.


if (!options.skipNonTranspilationPasses) { if (!options.skipNonTranspilationPasses) {
addNonTranspilationCheckPasses(checks); addNonTranspilationCheckPasses(checks);
Expand Down
Expand Up @@ -17,9 +17,8 @@


import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;


import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode; import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import com.google.javascript.jscomp.NodeTraversal.Callback;
import com.google.javascript.rhino.IR; import com.google.javascript.rhino.IR;
import com.google.javascript.rhino.JSDocInfo; import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.JSDocInfoBuilder; import com.google.javascript.rhino.JSDocInfoBuilder;
Expand All @@ -28,33 +27,21 @@
import com.google.javascript.rhino.Token; import com.google.javascript.rhino.Token;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;


/** /**
* Converts ES6 code to valid ES5 code. This class does most of the transpilation, and * Converts ES6 code to valid ES5 code. This class does transpilation for Rest, Spread, and Symbols,
* https://github.com/google/closure-compiler/wiki/ECMAScript6 lists which ES6 features are * which should be transpiled before NTI.
* supported. Other classes that start with "Es6" do other parts of the transpilation. * Other classes that start with "Es6" do other parts of the transpilation.
* *
* <p>In most cases, the output is valid as ES3 (hence the class name) but in some cases, if * <p>In most cases, the output is valid as ES3 (hence the class name) but in some cases, if
* the output language is set to ES5, we rely on ES5 features such as getters, setters, * the output language is set to ES5, we rely on ES5 features such as getters, setters,
* and Object.defineProperties. * and Object.defineProperties.
* *
* @author tbreisacher@google.com (Tyler Breisacher) * @author tbreisacher@google.com (Tyler Breisacher)
*/ */
// TODO(tbreisacher): This class does too many things. Break it into smaller passes. public final class EarlyEs6ToEs3Converter implements Callback, HotSwapCompilerPass {
public final class Es6ToEs3Converter implements NodeTraversal.Callback, HotSwapCompilerPass {
private final AbstractCompiler compiler; private final AbstractCompiler compiler;


static final DiagnosticType CANNOT_CONVERT = DiagnosticType.error(
"JSC_CANNOT_CONVERT",
"This code cannot be converted from ES6. {0}");

// TODO(tbreisacher): Remove this once we have implemented transpilation for all the features
// we intend to support.
static final DiagnosticType CANNOT_CONVERT_YET = DiagnosticType.error(
"JSC_CANNOT_CONVERT_YET",
"ES6 transpilation of ''{0}'' is not yet implemented.");

static final DiagnosticType BAD_REST_PARAMETER_ANNOTATION = DiagnosticType.warning( static final DiagnosticType BAD_REST_PARAMETER_ANNOTATION = DiagnosticType.warning(
"BAD_REST_PARAMETER_ANNOTATION", "BAD_REST_PARAMETER_ANNOTATION",
"Missing \"...\" in type annotation for rest parameter."); "Missing \"...\" in type annotation for rest parameter.");
Expand All @@ -67,13 +54,7 @@ public final class Es6ToEs3Converter implements NodeTraversal.Callback, HotSwapC


private static final String FRESH_SPREAD_VAR = "$jscomp$spread$args"; private static final String FRESH_SPREAD_VAR = "$jscomp$spread$args";


private static final String FRESH_COMP_PROP_VAR = "$jscomp$compprop"; public EarlyEs6ToEs3Converter(AbstractCompiler compiler) {

private static final String ITER_BASE = "$jscomp$iter$";

private static final String ITER_RESULT = "$jscomp$key$";

public Es6ToEs3Converter(AbstractCompiler compiler) {
this.compiler = compiler; this.compiler = compiler;
} }


Expand Down Expand Up @@ -102,7 +83,8 @@ public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
case GETTER_DEF: case GETTER_DEF:
case SETTER_DEF: case SETTER_DEF:
if (compiler.getOptions().getLanguageOut() == LanguageMode.ECMASCRIPT3) { if (compiler.getOptions().getLanguageOut() == LanguageMode.ECMASCRIPT3) {
cannotConvert(n, "ES5 getters/setters (consider using --language_out=ES5)"); Es6ToEs3Util.cannotConvert(
compiler, n, "ES5 getters/setters (consider using --language_out=ES5)");
return false; return false;
} }
break; break;
Expand Down Expand Up @@ -130,20 +112,6 @@ public void visit(NodeTraversal t, Node n, Node parent) {
visitGetprop(t, n); visitGetprop(t, n);
} }
break; break;
case OBJECTLIT:
visitObject(n);
break;
case MEMBER_FUNCTION_DEF:
if (parent.isObjectLit()) {
visitMemberFunctionDefInObjectLit(n, parent);
}
break;
case FOR_OF:
visitForOf(n, parent);
break;
case STRING_KEY:
visitStringKey(n);
break;
case ARRAYLIT: case ARRAYLIT:
case NEW: case NEW:
case CALL: case CALL:
Expand All @@ -154,14 +122,6 @@ public void visit(NodeTraversal t, Node n, Node parent) {
} }
} }
break; break;
case TAGGED_TEMPLATELIT:
Es6TemplateLiterals.visitTaggedTemplateLiteral(t, n);
break;
case TEMPLATELIT:
if (!parent.isTaggedTemplateLit()) {
Es6TemplateLiterals.visitTemplateLiteral(t, n);
}
break;
default: default:
break; break;
} }
Expand Down Expand Up @@ -203,86 +163,6 @@ private void visitGetprop(NodeTraversal t, Node n) {
} }
} }


/**
* Converts a member definition in an object literal to an ES3 key/value pair.
* Member definitions in classes are handled in {@link #Es6RewriteClass}.
*/
private void visitMemberFunctionDefInObjectLit(Node n, Node parent) {
String name = n.getString();
Node nameNode = n.getFirstFirstChild();
Node stringKey = IR.stringKey(name, n.getFirstChild().detach());
stringKey.setJSDocInfo(n.getJSDocInfo());
parent.replaceChild(n, stringKey);
stringKey.useSourceInfoFrom(nameNode);
compiler.reportChangeToEnclosingScope(stringKey);
}

/**
* Converts extended object literal {a} to {a:a}.
*/
// TODO(blickly): Separate this so it can be part of the normalization early transpilation passes.
private void visitStringKey(Node n) {
if (!n.hasChildren()) {
Node name = IR.name(n.getString());
name.useSourceInfoIfMissingFrom(n);
n.addChildToBack(name);
compiler.reportChangeToEnclosingScope(name);
}
}

private void visitForOf(Node node, Node parent) {
Node variable = node.removeFirstChild();
Node iterable = node.removeFirstChild();
Node body = node.removeFirstChild();
JSDocInfo varJSDocInfo = variable.getJSDocInfo();

Node iterName = IR.name(ITER_BASE + compiler.getUniqueNameIdSupplier().get());
iterName.makeNonIndexable();
Node getNext = IR.call(IR.getprop(iterName.cloneTree(), IR.string("next")));
String variableName;
Token declType;
if (variable.isName()) {
declType = Token.NAME;
variableName = variable.getQualifiedName();
} else {
Preconditions.checkState(NodeUtil.isNameDeclaration(variable),
"Expected var, let, or const. Got %s", variable);
declType = variable.getToken();
variableName = variable.getFirstChild().getQualifiedName();
}
Node iterResult = IR.name(ITER_RESULT + variableName);
iterResult.makeNonIndexable();

Node init = IR.var(iterName.cloneTree(), makeIterator(compiler, iterable));
Node initIterResult = iterResult.cloneTree();
initIterResult.addChildToFront(getNext.cloneTree());
init.addChildToBack(initIterResult);

Node cond = IR.not(IR.getprop(iterResult.cloneTree(), IR.string("done")));
Node incr = IR.assign(iterResult.cloneTree(), getNext.cloneTree());

Node declarationOrAssign;
if (declType == Token.NAME) {
declarationOrAssign = IR.assign(
IR.name(variableName).useSourceInfoFrom(variable),
IR.getprop(iterResult.cloneTree(), IR.string("value")));
declarationOrAssign.setJSDocInfo(varJSDocInfo);
declarationOrAssign = IR.exprResult(declarationOrAssign);
} else {
declarationOrAssign = new Node(
declType,
IR.name(variableName).useSourceInfoFrom(variable.getFirstChild()));
declarationOrAssign.getFirstChild().addChildToBack(
IR.getprop(iterResult.cloneTree(), IR.string("value")));
declarationOrAssign.setJSDocInfo(varJSDocInfo);
}
Node newBody = IR.block(declarationOrAssign, body).useSourceInfoFrom(body);
Node newFor = IR.forNode(init, cond, incr, newBody);
newFor.useSourceInfoIfMissingFromForTree(node);
parent.replaceChild(node, newFor);
compiler.reportChangeToEnclosingScope(newFor);
}

/** /**
* Processes a rest parameter * Processes a rest parameter
*/ */
Expand Down Expand Up @@ -382,7 +262,7 @@ private void visitArrayLitOrCallWithSpread(Node node, Node parent) {
groups.add(currGroup); groups.add(currGroup);
currGroup = null; currGroup = null;
} }
groups.add(arrayFromIterable(compiler, currElement.removeFirstChild())); groups.add(Es6ToEs3Util.arrayFromIterable(compiler, currElement.removeFirstChild()));
} else { } else {
if (currGroup == null) { if (currGroup == null) {
currGroup = IR.arraylit(); currGroup = IR.arraylit();
Expand Down Expand Up @@ -422,7 +302,8 @@ private void visitArrayLitOrCallWithSpread(Node node, Node parent) {
} else { } else {
if (compiler.getOptions().getLanguageOut() == LanguageMode.ECMASCRIPT3) { if (compiler.getOptions().getLanguageOut() == LanguageMode.ECMASCRIPT3) {
// TODO(tbreisacher): Support this in ES3 too by not relying on Function.bind. // TODO(tbreisacher): Support this in ES3 too by not relying on Function.bind.
cannotConvert(node, "\"...\" passed to a constructor (consider using --language_out=ES5)"); Es6ToEs3Util.cannotConvert(
compiler, node, "\"...\" passed to a constructor (consider using --language_out=ES5)");
} }
Node bindApply = NodeUtil.newQName(compiler, Node bindApply = NodeUtil.newQName(compiler,
"Function.prototype.bind.apply"); "Function.prototype.bind.apply");
Expand All @@ -432,110 +313,4 @@ private void visitArrayLitOrCallWithSpread(Node node, Node parent) {
parent.replaceChild(node, result); parent.replaceChild(node, result);
compiler.reportChangeToEnclosingScope(result); compiler.reportChangeToEnclosingScope(result);
} }

private void visitObject(Node obj) {
for (Node child : obj.children()) {
if (child.isComputedProp()) {
visitObjectWithComputedProperty(obj);
return;
}
}
}

private void visitObjectWithComputedProperty(Node obj) {
checkArgument(obj.isObjectLit());
List<Node> props = new ArrayList<>();
Node currElement = obj.getFirstChild();

while (currElement != null) {
if (currElement.getBooleanProp(Node.COMPUTED_PROP_GETTER)
|| currElement.getBooleanProp(Node.COMPUTED_PROP_SETTER)) {
cannotConvertYet(currElement, "computed getter/setter in an object literal");
return;
} else if (currElement.isGetterDef() || currElement.isSetterDef()) {
currElement = currElement.getNext();
} else {
Node nextNode = currElement.getNext();
obj.removeChild(currElement);
props.add(currElement);
currElement = nextNode;
}
}

String objName = FRESH_COMP_PROP_VAR + compiler.getUniqueNameIdSupplier().get();

props = Lists.reverse(props);
Node result = IR.name(objName);
for (Node propdef : props) {
if (propdef.isComputedProp()) {
Node propertyExpression = propdef.removeFirstChild();
Node value = propdef.removeFirstChild();
result = IR.comma(
IR.assign(
IR.getelem(
IR.name(objName),
propertyExpression),
value),
result);
} else {
if (!propdef.hasChildren()) {
Node name = IR.name(propdef.getString()).useSourceInfoIfMissingFrom(propdef);
propdef.addChildToBack(name);
}
Node val = propdef.removeFirstChild();
propdef.setToken(Token.STRING);
Token type = propdef.isQuotedString() ? Token.GETELEM : Token.GETPROP;
Node access = new Node(type, IR.name(objName), propdef);
result = IR.comma(IR.assign(access, val), result);
}
}

Node statement = obj;
while (!NodeUtil.isStatement(statement)) {
statement = statement.getParent();
}

result.useSourceInfoIfMissingFromForTree(obj);
obj.replaceWith(result);

Node var = IR.var(IR.name(objName), obj);
var.useSourceInfoIfMissingFromForTree(statement);
statement.getParent().addChildBefore(var, statement);
compiler.reportChangeToEnclosingScope(var);
}

private void cannotConvert(Node n, String message) {
compiler.report(JSError.make(n, CANNOT_CONVERT, message));
}

/**
* Warns the user that the given ES6 feature cannot be converted to ES3
* because the transpilation is not yet implemented. A call to this method
* is essentially a "TODO(tbreisacher): Implement {@code feature}" comment.
*/
private void cannotConvertYet(Node n, String feature) {
compiler.report(JSError.make(n, CANNOT_CONVERT_YET, feature));
}

/**
* Returns a call to {@code $jscomp.makeIterator} with {@code iterable} as its argument.
*/
static Node makeIterator(AbstractCompiler compiler, Node iterable) {
return callEs6RuntimeFunction(compiler, iterable, "makeIterator");
}

/**
* Returns a call to $jscomp.arrayFromIterable with {@code iterable} as its argument.
*/
private static Node arrayFromIterable(AbstractCompiler compiler, Node iterable) {
return callEs6RuntimeFunction(compiler, iterable, "arrayFromIterable");
}

private static Node callEs6RuntimeFunction(
AbstractCompiler compiler, Node iterable, String function) {
compiler.ensureLibraryInjected("es6/util/" + function.toLowerCase(Locale.US), false);
return IR.call(
NodeUtil.newQName(compiler, "$jscomp." + function),
iterable);
}
} }
4 changes: 2 additions & 2 deletions src/com/google/javascript/jscomp/Es6ConvertSuper.java
Expand Up @@ -16,7 +16,7 @@
package com.google.javascript.jscomp; package com.google.javascript.jscomp;


import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.javascript.jscomp.Es6ToEs3Converter.CANNOT_CONVERT_YET; import static com.google.javascript.jscomp.Es6ToEs3Util.CANNOT_CONVERT_YET;


import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
Expand All @@ -30,7 +30,7 @@
/** /**
* Converts {@code super.method()} calls and adds constructors to any classes that lack them. * Converts {@code super.method()} calls and adds constructors to any classes that lack them.
* *
* <p>This has to run before the main {@link Es6ToEs3Converter} pass. The super() constructor calls * <p>This has to run before the main {@link Es6RewriteClass} pass. The super() constructor calls
* are not converted here, but rather in {@link Es6ConvertSuperConstructorCalls}, which runs later. * are not converted here, but rather in {@link Es6ConvertSuperConstructorCalls}, which runs later.
*/ */
public final class Es6ConvertSuper extends NodeTraversal.AbstractPostOrderCallback public final class Es6ConvertSuper extends NodeTraversal.AbstractPostOrderCallback
Expand Down
Expand Up @@ -18,7 +18,7 @@
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.javascript.jscomp.Es6ToEs3Converter.CANNOT_CONVERT; import static com.google.javascript.jscomp.Es6ToEs3Util.CANNOT_CONVERT;


import com.google.javascript.jscomp.GlobalNamespace.Name; import com.google.javascript.jscomp.GlobalNamespace.Name;
import com.google.javascript.jscomp.GlobalNamespace.Ref; import com.google.javascript.jscomp.GlobalNamespace.Ref;
Expand Down
4 changes: 2 additions & 2 deletions src/com/google/javascript/jscomp/Es6ExtractClasses.java
Expand Up @@ -17,7 +17,7 @@
package com.google.javascript.jscomp; package com.google.javascript.jscomp;


import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.javascript.jscomp.Es6ToEs3Converter.CANNOT_CONVERT; import static com.google.javascript.jscomp.Es6ToEs3Util.CANNOT_CONVERT;


import com.google.javascript.jscomp.ExpressionDecomposer.DecompositionType; import com.google.javascript.jscomp.ExpressionDecomposer.DecompositionType;
import com.google.javascript.jscomp.deps.ModuleNames; import com.google.javascript.jscomp.deps.ModuleNames;
Expand All @@ -42,7 +42,7 @@
* foo($jscomp$classdecl$var0); * foo($jscomp$classdecl$var0);
* </code> * </code>
* <p> * <p>
* This must be done before {@link Es6ToEs3Converter}, because that pass only handles classes * This must be done before {@link Es6RewriteClass}, because that pass only handles classes
* that are declarations or simple assignments. * that are declarations or simple assignments.
* @see Es6RewriteClass#visitClass(NodeTraversal, Node, Node) * @see Es6RewriteClass#visitClass(NodeTraversal, Node, Node)
*/ */
Expand Down

0 comments on commit cb88c48

Please sign in to comment.