Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Detect Feature.BLOCK_SCOPED_FUNCTION_DECLARATIONS correctly and set i…
…t as an ES6 feature. This change has two main consequences: 1. Some code that was previously considered to be ES5 will now be marked as ES6, resulting in transpilation occurring in test runners, bundlers, and debug loaders. If LANGUAGE_IN is explicitly set to ES5, or if ES6 externs are missing, it's possible that builds could break. 2. A possible behavior change for ambiguous block-scoped declarations. The code `function f(){return 1;} {function f(){return 2;}} console.log(f());` will print '2' in sloppy mode, but '1' in ES6 strict mode (and is an error in ES5 strict mode). Depending on a variety of other factors, the compiler may output ES5 code printing either result; this change will make it always obey the strict-mode behavior and print '1'. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=180607816
- Loading branch information
Showing
10 changed files
with
308 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
src/com/google/javascript/jscomp/Es6RewriteBlockScopedFunctionDeclaration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,100 @@ | |||
/* | |||
* Copyright 2017 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.NodeTraversal.AbstractPostOrderCallback; | |||
import com.google.javascript.jscomp.parsing.parser.FeatureSet; | |||
import com.google.javascript.jscomp.parsing.parser.FeatureSet.Feature; | |||
import com.google.javascript.rhino.IR; | |||
import com.google.javascript.rhino.Node; | |||
import com.google.javascript.rhino.Token; | |||
|
|||
/** | |||
* Rewrite block-scoped function declarations as "let"s. This pass must happen before | |||
* Es6RewriteBlockScopedDeclaration, which rewrites "let" to "var". | |||
*/ | |||
public final class Es6RewriteBlockScopedFunctionDeclaration extends AbstractPostOrderCallback | |||
implements HotSwapCompilerPass { | |||
|
|||
private final AbstractCompiler compiler; | |||
private static final FeatureSet transpiledFeatures = | |||
FeatureSet.BARE_MINIMUM.with(Feature.BLOCK_SCOPED_FUNCTION_DECLARATION); | |||
|
|||
public Es6RewriteBlockScopedFunctionDeclaration(AbstractCompiler compiler) { | |||
this.compiler = compiler; | |||
} | |||
|
|||
@Override | |||
public void process(Node externs, Node root) { | |||
TranspilationPasses.processTranspile(compiler, externs, transpiledFeatures, this); | |||
TranspilationPasses.processTranspile(compiler, root, transpiledFeatures, this); | |||
} | |||
|
|||
@Override | |||
public void hotSwapScript(Node scriptRoot, Node originalRoot) { | |||
TranspilationPasses.hotSwapTranspile(compiler, scriptRoot, transpiledFeatures, this); | |||
} | |||
|
|||
@Override | |||
public void visit(NodeTraversal t, Node n, Node parent) { | |||
if (n.isFunction() | |||
&& parent != null | |||
&& parent.isNormalBlock() | |||
&& !parent.getParent().isFunction()) { | |||
// Only consider declarations (all expressions have non-block parents) that are not directly | |||
// within a function or top-level. | |||
visitBlockScopedFunctionDeclaration(n, parent); | |||
} | |||
} | |||
|
|||
/** | |||
* Rewrite the function declaration from: | |||
* <pre> | |||
* function f() {} | |||
* FUNCTION | |||
* NAME x | |||
* PARAM_LIST | |||
* BLOCK | |||
* </pre> to <pre> | |||
* let f = function() {}; | |||
* LET | |||
* NAME f | |||
* FUNCTION | |||
* NAME (w/ empty string) | |||
* PARAM_LIST | |||
* BLOCK | |||
* </pre> | |||
* This is similar to {@link Normalize.NormalizeStatements#rewriteFunctionDeclaration} but | |||
* rewrites to "let" instead of "var". | |||
*/ | |||
private void visitBlockScopedFunctionDeclaration(Node n, Node parent) { | |||
// Prepare a spot for the function. | |||
Node oldNameNode = n.getFirstChild(); | |||
Node fnNameNode = oldNameNode.cloneNode(); | |||
Node let = IR.declaration(fnNameNode, Token.LET).srcref(n); | |||
|
|||
// Prepare the function. | |||
oldNameNode.setString(""); | |||
compiler.reportChangeToEnclosingScope(oldNameNode); | |||
|
|||
// Move the function to the front of the parent. | |||
parent.removeChild(n); | |||
parent.addChildToFront(let); | |||
compiler.reportChangeToEnclosingScope(let); | |||
fnNameNode.addChildToFront(n); | |||
} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.