Skip to content

Commit

Permalink
Separate Es7 to Es6 transpilation into its own pass.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=163361753
  • Loading branch information
EatingW authored and brad4d committed Jul 28, 2017
1 parent b6c9eed commit 36feddf
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 34 deletions.
12 changes: 11 additions & 1 deletion src/com/google/javascript/jscomp/DefaultPassConfig.java
Expand Up @@ -172,6 +172,11 @@ protected List<PassFactory> getTranspileOnlyPasses() {
passes.add(setFeatureSet(ES7));
}

if (options.needsTranspilationFrom(ES7)) {
TranspilationPasses.addEs2016Passes(passes);
passes.add(setFeatureSet(ES6));
}

// If the user has specified an input language of ES7 and an output language of ES6 or lower,
// we still need to run these "ES6" passes, because they do the transpilation of the ES7 **
// operator. If we split that into its own pass then the needsTranspilationFrom(ES7) call here
Expand Down Expand Up @@ -356,7 +361,12 @@ protected List<PassFactory> getChecks() {
checks.add(setFeatureSet(ES7));
}

if (options.needsTranspilationFrom(ES6) || options.needsTranspilationFrom(ES7)) {
if (options.needsTranspilationFrom(ES7)) {
TranspilationPasses.addEs2016Passes(checks);
checks.add(setFeatureSet(ES6));
}

if (options.needsTranspilationFrom(ES6)) {
checks.add(es6ExternsCheck);
TranspilationPasses.addEs6EarlyPasses(checks);
}
Expand Down
25 changes: 0 additions & 25 deletions src/com/google/javascript/jscomp/Es6ToEs3Converter.java
Expand Up @@ -162,12 +162,6 @@ public void visit(NodeTraversal t, Node n, Node parent) {
Es6TemplateLiterals.visitTemplateLiteral(t, n);
}
break;
case EXPONENT:
visitExponentiationExpression(n, parent);
break;
case ASSIGN_EXPONENT:
visitExponentiationAssignmentExpression(n, parent);
break;
default:
break;
}
Expand Down Expand Up @@ -195,25 +189,6 @@ private void initSymbolBefore(Node n) {
compiler.reportChangeToEnclosingScope(initSymbol);
}

private void visitExponentiationExpression(Node n, Node parent) {
Node left = n.removeFirstChild();
Node right = n.removeFirstChild();
Node mathDotPowCall =
IR.call(NodeUtil.newQName(compiler, "Math.pow"), left, right)
.useSourceInfoIfMissingFromForTree(n);
parent.replaceChild(n, mathDotPowCall);
compiler.reportChangeToEnclosingScope(mathDotPowCall);
}

private void visitExponentiationAssignmentExpression(Node n, Node parent) {
Node left = n.removeFirstChild();
Node right = n.removeFirstChild();
Node mathDotPowCall = IR.call(NodeUtil.newQName(compiler, "Math.pow"), left.cloneTree(), right);
Node assign = IR.assign(left, mathDotPowCall).useSourceInfoIfMissingFromForTree(n);
parent.replaceChild(n, assign);
compiler.reportChangeToEnclosingScope(assign);
}

// TODO(tbreisacher): Do this for all well-known symbols.
private void visitGetprop(NodeTraversal t, Node n) {
if (!n.matchesQualifiedName("Symbol.iterator")) {
Expand Down
81 changes: 81 additions & 0 deletions src/com/google/javascript/jscomp/Es7ToEs6Converter.java
@@ -0,0 +1,81 @@
/*
* Copyright 2014 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;

import com.google.javascript.rhino.IR;
import com.google.javascript.rhino.Node;

/**
* Converts ES7 code to valid ES6 code.
*
* Currently this class converts ** and **= operators to calling Math.pow
*/
public final class Es7ToEs6Converter implements NodeTraversal.Callback, HotSwapCompilerPass {
private final AbstractCompiler compiler;

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

@Override
public void process(Node externs, Node root) {
TranspilationPasses.processTranspile(compiler, externs, this);
TranspilationPasses.processTranspile(compiler, root, this);
}

@Override
public void hotSwapScript(Node scriptRoot, Node originalRoot) {
TranspilationPasses.hotSwapTranspile(compiler, scriptRoot, this);
}

@Override
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
return true;
}

@Override
public void visit(NodeTraversal t, Node n, Node parent) {
switch (n.getToken()) {
case EXPONENT:
visitExponentiationExpression(n, parent);
break;
case ASSIGN_EXPONENT:
visitExponentiationAssignmentExpression(n, parent);
break;
default:
break;
}
}

private void visitExponentiationExpression(Node n, Node parent) {
Node left = n.removeFirstChild();
Node right = n.removeFirstChild();
Node mathDotPowCall =
IR.call(NodeUtil.newQName(compiler, "Math.pow"), left, right)
.useSourceInfoIfMissingFromForTree(n);
parent.replaceChild(n, mathDotPowCall);
compiler.reportChangeToEnclosingScope(mathDotPowCall);
}

private void visitExponentiationAssignmentExpression(Node n, Node parent) {
Node left = n.removeFirstChild();
Node right = n.removeFirstChild();
Node mathDotPowCall = IR.call(NodeUtil.newQName(compiler, "Math.pow"), left.cloneTree(), right);
Node assign = IR.assign(left, mathDotPowCall).useSourceInfoIfMissingFromForTree(n);
parent.replaceChild(n, assign);
compiler.reportChangeToEnclosingScope(assign);
}
}
17 changes: 17 additions & 0 deletions src/com/google/javascript/jscomp/TranspilationPasses.java
Expand Up @@ -38,6 +38,10 @@ public static void addEs2017Passes(List<PassFactory> passes) {
passes.add(rewriteAsyncFunctions);
}

public static void addEs2016Passes(List<PassFactory> passes) {
passes.add(convertEs7ToEs6);
}

/**
* Adds all the early ES6 transpilation passes, which go before the Dart pass.
*
Expand Down Expand Up @@ -104,6 +108,19 @@ protected FeatureSet featureSet() {
}
};

private static final PassFactory convertEs7ToEs6 =
new PassFactory("convertEs7ToEs6", true) {
@Override
protected CompilerPass create(final AbstractCompiler compiler) {
return new Es7ToEs6Converter(compiler);
}

@Override
protected FeatureSet featureSet() {
return ES8;
}
};

private static final PassFactory es6SuperCheck =
new PassFactory("es6SuperCheck", true) {
@Override
Expand Down
1 change: 1 addition & 0 deletions test/com/google/javascript/jscomp/CompilerTestCase.java
Expand Up @@ -1684,6 +1684,7 @@ private static void transpileToEs5(AbstractCompiler compiler, Node externsRoot,
List<PassFactory> factories = new ArrayList<>();
TranspilationPasses.addEs6ModulePass(factories);
TranspilationPasses.addEs2017Passes(factories);
TranspilationPasses.addEs2016Passes(factories);
TranspilationPasses.addEs6EarlyPasses(factories);
TranspilationPasses.addEs6LatePasses(factories);
TranspilationPasses.addRewritePolyfillPass(factories);
Expand Down
8 changes: 0 additions & 8 deletions test/com/google/javascript/jscomp/Es6ToEs3ConverterTest.java
Expand Up @@ -262,14 +262,6 @@ public void testAnonymousSuper() {
"f(testcode$classdecl$var0)"));
}

public void testExponentiationOperator() {
test("2 ** 2;", "Math.pow(2,2)");
}

public void testExponentiationAssignmentOperator() {
test("x **= 2;", "x=Math.pow(x,2)");
}

public void testNewTarget() {
testError("function Foo() { new.target; }", CANNOT_CONVERT_YET);
}
Expand Down
56 changes: 56 additions & 0 deletions test/com/google/javascript/jscomp/Es7ToEs6ConverterTest.java
@@ -0,0 +1,56 @@
/*
* Copyright 2014 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;

import com.google.javascript.jscomp.CompilerOptions.LanguageMode;

/**
* Test cases for ES6 transpilation. Despite the name, this isn't just testing {@link
* Es6ToEs3Converter}, but also some other ES6 transpilation passes. See #getProcessor.
*/
public final class Es7ToEs6ConverterTest extends TypeICompilerTestCase {

public Es7ToEs6ConverterTest() {
super(MINIMAL_EXTERNS);
}

@Override
protected void setUp() throws Exception {
super.setUp();
setAcceptedLanguage(LanguageMode.ECMASCRIPT_2016);
setLanguageOut(LanguageMode.ECMASCRIPT5);
enableRunTypeCheckAfterProcessing();
this.mode = TypeInferenceMode.NEITHER;
}

@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new Es7ToEs6Converter(compiler);
}

@Override
protected int getNumRepetitions() {
return 1;
}

public void testExponentiationOperator() {
test("2 ** 2;", "Math.pow(2,2)");
}

public void testExponentiationAssignmentOperator() {
test("x **= 2;", "x=Math.pow(x,2)");
}
}
Expand Up @@ -247,6 +247,7 @@ private final void parseAndTypeCheck(String externs, String js) {
}
if (compilerOptions.needsTranspilationFrom(FeatureSet.ES6)) {
TranspilationPasses.addEs2017Passes(passes);
TranspilationPasses.addEs2016Passes(passes);
TranspilationPasses.addEs6EarlyPasses(passes);
TranspilationPasses.addEs6LatePasses(passes);
TranspilationPasses.addRewritePolyfillPass(passes);
Expand Down
1 change: 1 addition & 0 deletions test/com/google/javascript/jscomp/TypeCheckTest.java
Expand Up @@ -17987,6 +17987,7 @@ private TypeCheckResult parseAndTypeCheckWithScope(String externs, String js) {
List<PassFactory> passes = new ArrayList<>();
TranspilationPasses.addEs6ModulePass(passes);
TranspilationPasses.addEs2017Passes(passes);
TranspilationPasses.addEs2016Passes(passes);
TranspilationPasses.addEs6EarlyPasses(passes);
TranspilationPasses.addEs6LatePasses(passes);
TranspilationPasses.addRewritePolyfillPass(passes);
Expand Down

0 comments on commit 36feddf

Please sign in to comment.