|
16 | 16 |
|
17 | 17 | package com.google.javascript.jscomp;
|
18 | 18 |
|
| 19 | +import static com.google.common.base.Preconditions.checkState; |
19 | 20 |
|
20 | 21 | import com.google.javascript.jscomp.CompilerOptions.ChunkOutputType;
|
21 | 22 | import com.google.javascript.jscomp.Es6RewriteDestructuring.ObjectDestructuringRewriteMode;
|
@@ -62,7 +63,12 @@ public static void addEs6RewriteImportPathPass(PassListBuilder passes) {
|
62 | 63 | passes.maybeAdd(es6RelativizeImportPaths);
|
63 | 64 | }
|
64 | 65 |
|
65 |
| - /** Adds transpilation passes that should run at the beginning of the optimization phase */ |
| 66 | + /** |
| 67 | + * Adds transpilation passes that should run at the beginning of the optimization phase. Passes |
| 68 | + * added in this method either use {@code TranspilationPasses.processTranspile} or early-exit by |
| 69 | + * checking their feature in the script's featureset. So they will only get run if the feature |
| 70 | + * they're responsible for removing exists in the script. |
| 71 | + */ |
66 | 72 | public static void addEarlyOptimizationTranspilationPasses(
|
67 | 73 | PassListBuilder passes, CompilerOptions options) {
|
68 | 74 |
|
@@ -224,14 +230,21 @@ public static void addEarlyOptimizationTranspilationPasses(
|
224 | 230 | }
|
225 | 231 | }
|
226 | 232 |
|
227 |
| - /** Adds transpilation passes that should not be run until after normalization has been done. */ |
| 233 | + /** |
| 234 | + * Adds transpilation passes that should not be run until after normalization has been done. |
| 235 | + * Passes added in this method either use {@code TranspilationPasses.processTranspile} or |
| 236 | + * early-exit by checking their feature in the script's featureset. So they will only get run if |
| 237 | + * the feature they're responsible for removing exists in the script. |
| 238 | + */ |
228 | 239 | public static void addPostNormalizationTranspilationPasses(
|
229 | 240 | PassListBuilder passes, CompilerOptions options) {
|
230 | 241 | // TODO(b/197349249): Move passes from `addEarlyOptimizationTranspilationPasses()` to here
|
231 | 242 | // until that method can be deleted as a no-op.
|
232 | 243 | if (options.needsTranspilationOf(Feature.GENERATORS)) {
|
233 | 244 | passes.maybeAdd(rewriteGenerators);
|
234 | 245 | }
|
| 246 | + // This pass must run at the end of all transpiler passes. It validates that only supported |
| 247 | + // features remain in the compiler's featureSet |
235 | 248 | passes.maybeAdd(
|
236 | 249 | TranspilationPasses.createPostTranspileUnsupportedFeaturesRemovedCheck(
|
237 | 250 | "postTranspileUnsupportedFeaturesRemovedCheck"));
|
@@ -441,44 +454,46 @@ static final PassFactory getEs6RewriteDestructuring(ObjectDestructuringRewriteMo
|
441 | 454 | .build();
|
442 | 455 |
|
443 | 456 | /**
|
444 |
| - * @param script The SCRIPT node representing a JS file |
445 |
| - * @return If the file has any features not in {@code supportedFeatures} |
| 457 | + * Returns true if the script's featureSet contains any feature from the given featureSet. |
| 458 | + * |
| 459 | + * <p>The script's featureSet gets accurately maintained during transpile. It can be relied upon |
| 460 | + * to check if a feature exists in the AST or not. |
446 | 461 | */
|
447 |
| - static boolean doesScriptHaveUnsupportedFeatures(Node script, FeatureSet supportedFeatures) { |
| 462 | + static boolean doesScriptHaveAnyOfTheseFeatures(Node script, FeatureSet featureSet) { |
448 | 463 | FeatureSet features = NodeUtil.getFeatureSetOfScript(script);
|
449 |
| - return features != null && !supportedFeatures.contains(features); |
| 464 | + return features != null && features.containsAtLeastOneOf(featureSet); |
450 | 465 | }
|
451 | 466 |
|
452 | 467 | /**
|
453 |
| - * Process transpilations if the input language needs transpilation from certain features, on any |
454 |
| - * JS file that has features not present in the compiler's output language mode. |
| 468 | + * Runs the given transpilation callbacks on every source script if the given {@code |
| 469 | + * featuresToRunFor} are unsupported in the output language and exist in that script. |
455 | 470 | *
|
456 | 471 | * @param compiler An AbstractCompiler
|
457 |
| - * @param combinedRoot The combined root for all JS files. |
458 |
| - * @param featureSet Ignored |
459 |
| - * @param callbacks The callbacks that should be invoked if a file has ES2015 features. |
| 472 | + * @param combinedRoot The combined root for all JS files |
| 473 | + * @param featuresToRunFor features for which these callbacks run |
| 474 | + * @param callbacks The callbacks that should be invoked if a file has output-unsupported |
| 475 | + * features. |
460 | 476 | * @deprecated Please use a regular NodeTraversal object directly, using `shouldTraverse` to skip
|
461 | 477 | * SCRIPT node if desired.
|
462 | 478 | */
|
463 | 479 | @Deprecated
|
464 | 480 | static void processTranspile(
|
465 | 481 | AbstractCompiler compiler,
|
466 | 482 | Node combinedRoot,
|
467 |
| - FeatureSet featureSet, |
| 483 | + FeatureSet featuresToRunFor, |
468 | 484 | NodeTraversal.Callback... callbacks) {
|
469 | 485 | FeatureSet languageOutFeatures = compiler.getOptions().getOutputFeatureSet();
|
| 486 | + if (languageOutFeatures.contains(featuresToRunFor)) { |
| 487 | + // all featuresToRunFor are supported by languageOut and don't need to get transpiled. |
| 488 | + return; |
| 489 | + } |
| 490 | + |
470 | 491 | for (Node singleRoot = combinedRoot.getFirstChild();
|
471 | 492 | singleRoot != null;
|
472 | 493 | singleRoot = singleRoot.getNext()) {
|
473 |
| - |
474 |
| - // Only run the transpilation if this file has features not in the compiler's target output |
475 |
| - // language. For example, if this file is purely ES6 and the output language is ES6, don't |
476 |
| - // run any transpilation passes on it. |
477 |
| - // TODO(lharker): We could save time by being more selective about what files we transpile. |
478 |
| - // e.g. if a file has async functions but not `**`, don't run `**` transpilation on it. |
479 |
| - // Right now we know what features were in a file at parse time, but not what features were |
480 |
| - // added to that file by other transpilation passes. |
481 |
| - if (doesScriptHaveUnsupportedFeatures(singleRoot, languageOutFeatures)) { |
| 494 | + checkState(singleRoot.isScript()); |
| 495 | + // only run the callbacks if any feature from the given featureSet exists in the script |
| 496 | + if (doesScriptHaveAnyOfTheseFeatures(singleRoot, featuresToRunFor)) { |
482 | 497 | for (NodeTraversal.Callback callback : callbacks) {
|
483 | 498 | NodeTraversal.traverse(compiler, singleRoot, callback);
|
484 | 499 | }
|
|
0 commit comments