webpack 5.99.6 → 5.99.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/AutomaticPrefetchPlugin.js +21 -22
- package/lib/BannerPlugin.js +31 -35
- package/lib/CleanPlugin.js +5 -3
- package/lib/Compilation.js +21 -15
- package/lib/Compiler.js +2 -1
- package/lib/ContextExclusionPlugin.js +4 -2
- package/lib/ContextModule.js +1 -1
- package/lib/ContextModuleFactory.js +1 -2
- package/lib/ContextReplacementPlugin.js +7 -4
- package/lib/DefinePlugin.js +2 -2
- package/lib/DelegatedModule.js +18 -8
- package/lib/DelegatedModuleFactoryPlugin.js +9 -7
- package/lib/DelegatedPlugin.js +4 -2
- package/lib/DllEntryPlugin.js +4 -2
- package/lib/DllPlugin.js +5 -3
- package/lib/DllReferencePlugin.js +56 -60
- package/lib/DynamicEntryPlugin.js +4 -2
- package/lib/EntryOptionPlugin.js +3 -1
- package/lib/EntryPlugin.js +4 -2
- package/lib/EnvironmentPlugin.js +4 -2
- package/lib/EvalDevToolModulePlugin.js +9 -7
- package/lib/EvalSourceMapDevToolPlugin.js +138 -139
- package/lib/ExportsInfo.js +35 -16
- package/lib/ExternalModule.js +6 -5
- package/lib/ExternalsPlugin.js +3 -1
- package/lib/FileSystemInfo.js +2 -2
- package/lib/FlagDependencyExportsPlugin.js +2 -1
- package/lib/IgnorePlugin.js +6 -4
- package/lib/IgnoreWarningsPlugin.js +4 -2
- package/lib/LibManifestPlugin.js +5 -6
- package/lib/LoaderOptionsPlugin.js +4 -2
- package/lib/LoaderTargetPlugin.js +4 -2
- package/lib/Module.js +19 -12
- package/lib/ModuleFilenameHelpers.js +8 -4
- package/lib/ModuleInfoHeaderPlugin.js +11 -12
- package/lib/MultiCompiler.js +5 -3
- package/lib/NoEmitOnErrorsPlugin.js +5 -3
- package/lib/NormalModule.js +13 -8
- package/lib/NormalModuleReplacementPlugin.js +33 -36
- package/lib/PlatformPlugin.js +3 -1
- package/lib/PrefetchPlugin.js +4 -2
- package/lib/ProgressPlugin.js +23 -26
- package/lib/RecordIdsPlugin.js +72 -102
- package/lib/RuntimePlugin.js +34 -32
- package/lib/SourceMapDevToolPlugin.js +9 -8
- package/lib/WarnCaseSensitiveModulesPlugin.js +36 -37
- package/lib/WarnNoModeSetPlugin.js +3 -1
- package/lib/WatchIgnorePlugin.js +3 -1
- package/lib/WebpackError.js +11 -3
- package/lib/WebpackOptionsApply.js +6 -7
- package/lib/asset/AssetGenerator.js +2 -2
- package/lib/async-modules/InferAsyncModulesPlugin.js +25 -26
- package/lib/cache/IdleFileCachePlugin.js +11 -12
- package/lib/cache/MemoryWithGcCachePlugin.js +7 -5
- package/lib/cache/ResolverCachePlugin.js +8 -6
- package/lib/cli.js +5 -1
- package/lib/config/defaults.js +10 -6
- package/lib/config/normalization.js +14 -8
- package/lib/container/ContainerReferencePlugin.js +24 -26
- package/lib/container/ModuleFederationPlugin.js +2 -1
- package/lib/css/CssGenerator.js +1 -1
- package/lib/css/CssModulesPlugin.js +8 -6
- package/lib/debug/ProfilingPlugin.js +18 -21
- package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -1
- package/lib/dependencies/ContextElementDependency.js +1 -1
- package/lib/dependencies/CssLocalIdentifierDependency.js +2 -2
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +9 -15
- package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +15 -15
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +4 -2
- package/lib/dependencies/LoaderPlugin.js +5 -3
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +46 -46
- package/lib/dependencies/RequireContextPlugin.js +2 -1
- package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +94 -100
- package/lib/dependencies/WorkerPlugin.js +2 -2
- package/lib/esm/ModuleChunkLoadingPlugin.js +72 -73
- package/lib/hmr/HotModuleReplacement.runtime.js +0 -1
- package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +0 -2
- package/lib/hmr/LazyCompilationPlugin.js +17 -18
- package/lib/ids/ChunkModuleIdRangePlugin.js +6 -6
- package/lib/ids/DeterministicModuleIdsPlugin.js +47 -48
- package/lib/ids/HashedModuleIdsPlugin.js +4 -2
- package/lib/ids/NamedChunkIdsPlugin.js +4 -2
- package/lib/ids/NamedModuleIdsPlugin.js +4 -2
- package/lib/ids/NaturalChunkIdsPlugin.js +4 -2
- package/lib/ids/NaturalModuleIdsPlugin.js +4 -2
- package/lib/ids/OccurrenceChunkIdsPlugin.js +4 -2
- package/lib/ids/OccurrenceModuleIdsPlugin.js +4 -2
- package/lib/index.js +11 -0
- package/lib/javascript/JavascriptModulesPlugin.js +2 -2
- package/lib/javascript/JavascriptParser.js +634 -656
- package/lib/json/JsonModulesPlugin.js +4 -4
- package/lib/library/AbstractLibraryPlugin.js +1 -1
- package/lib/library/ModuleLibraryPlugin.js +60 -42
- package/lib/node/CommonJsChunkLoadingPlugin.js +69 -73
- package/lib/node/NodeEnvironmentPlugin.js +3 -1
- package/lib/node/nodeConsole.js +3 -2
- package/lib/optimize/AggressiveSplittingPlugin.js +224 -232
- package/lib/optimize/ConcatenatedModule.js +15 -16
- package/lib/optimize/FlagIncludedChunksPlugin.js +92 -97
- package/lib/optimize/LimitChunkCountPlugin.js +4 -2
- package/lib/optimize/MangleExportsPlugin.js +15 -16
- package/lib/optimize/MinChunkSizePlugin.js +4 -2
- package/lib/optimize/ModuleConcatenationPlugin.js +6 -4
- package/lib/optimize/RealContentHashPlugin.js +4 -2
- package/lib/optimize/RemoveEmptyChunksPlugin.js +5 -3
- package/lib/optimize/RemoveParentModulesPlugin.js +4 -2
- package/lib/optimize/RuntimeChunkPlugin.js +21 -23
- package/lib/optimize/SideEffectsFlagPlugin.js +9 -6
- package/lib/optimize/SplitChunksPlugin.js +9 -7
- package/lib/performance/SizeLimitsPlugin.js +3 -1
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +61 -62
- package/lib/rules/BasicEffectRulePlugin.js +1 -2
- package/lib/rules/ObjectMatcherRulePlugin.js +2 -1
- package/lib/rules/RuleSetCompiler.js +19 -5
- package/lib/rules/UseEffectRulePlugin.js +4 -6
- package/lib/runtime/StartupChunkDependenciesPlugin.js +39 -42
- package/lib/schemes/DataUriPlugin.js +5 -3
- package/lib/schemes/FileUriPlugin.js +5 -3
- package/lib/schemes/HttpUriPlugin.js +186 -188
- package/lib/serialization/AggregateErrorSerializer.js +42 -0
- package/lib/serialization/ErrorObjectSerializer.js +7 -2
- package/lib/serialization/ObjectMiddleware.js +13 -0
- package/lib/sharing/ProvideSharedPlugin.js +6 -4
- package/lib/stats/DefaultStatsFactoryPlugin.js +89 -33
- package/lib/stats/DefaultStatsPresetPlugin.js +25 -20
- package/lib/stats/DefaultStatsPrinterPlugin.js +306 -341
- package/lib/util/concatenate.js +4 -2
- package/lib/util/createHash.js +3 -3
- package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +55 -57
- package/lib/web/JsonpChunkLoadingPlugin.js +73 -74
- package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +77 -78
- package/package.json +35 -30
- package/schemas/WebpackOptions.check.d.ts +1 -1
- package/schemas/WebpackOptions.check.js +2 -2
- package/schemas/WebpackOptions.json +267 -26
- package/schemas/plugins/BannerPlugin.check.d.ts +1 -1
- package/schemas/plugins/BannerPlugin.check.js +1 -1
- package/schemas/plugins/DllPlugin.check.d.ts +1 -1
- package/schemas/plugins/DllPlugin.check.js +1 -1
- package/schemas/plugins/DllReferencePlugin.check.d.ts +1 -1
- package/schemas/plugins/DllReferencePlugin.check.js +1 -1
- package/schemas/plugins/HashedModuleIdsPlugin.check.d.ts +1 -1
- package/schemas/plugins/HashedModuleIdsPlugin.check.js +1 -1
- package/schemas/plugins/IgnorePlugin.check.d.ts +1 -1
- package/schemas/plugins/IgnorePlugin.check.js +1 -1
- package/schemas/plugins/LoaderOptionsPlugin.check.d.ts +1 -1
- package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
- package/schemas/plugins/ProgressPlugin.check.d.ts +1 -1
- package/schemas/plugins/ProgressPlugin.check.js +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.d.ts +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.json +2 -2
- package/schemas/plugins/WatchIgnorePlugin.check.d.ts +1 -1
- package/schemas/plugins/WatchIgnorePlugin.check.js +1 -1
- package/schemas/plugins/asset/AssetGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetParserOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetParserOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.d.ts +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
- package/schemas/plugins/container/ContainerReferencePlugin.check.d.ts +1 -1
- package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
- package/schemas/plugins/container/ExternalsType.check.d.ts +1 -1
- package/schemas/plugins/container/ExternalsType.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.d.ts +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/css/CssAutoGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssAutoGeneratorOptions.check.js +1 -1
- package/schemas/plugins/css/CssAutoParserOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssGeneratorOptions.check.js +1 -1
- package/schemas/plugins/css/CssGlobalGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
- package/schemas/plugins/css/CssGlobalParserOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleGeneratorOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssParserOptions.check.d.ts +1 -1
- package/schemas/plugins/css/CssParserOptions.check.js +1 -1
- package/schemas/plugins/debug/ProfilingPlugin.check.d.ts +1 -1
- package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
- package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.d.ts +1 -1
- package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.js +1 -1
- package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.d.ts +1 -1
- package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js +1 -1
- package/schemas/plugins/json/JsonModulesPluginGenerator.check.d.ts +7 -0
- package/schemas/plugins/{JsonModulesPluginGenerator.check.js → json/JsonModulesPluginGenerator.check.js} +1 -1
- package/schemas/plugins/json/JsonModulesPluginGenerator.json +3 -0
- package/schemas/plugins/json/JsonModulesPluginParser.check.d.ts +7 -0
- package/schemas/plugins/{JsonModulesPluginParser.check.js → json/JsonModulesPluginParser.check.js} +1 -1
- package/schemas/plugins/json/JsonModulesPluginParser.json +3 -0
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +1 -1
- package/schemas/plugins/optimize/LimitChunkCountPlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +1 -1
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +1 -1
- package/schemas/plugins/optimize/MinChunkSizePlugin.check.d.ts +1 -1
- package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.check.d.ts +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
- package/schemas/plugins/sharing/ConsumeSharedPlugin.check.d.ts +1 -1
- package/schemas/plugins/sharing/ConsumeSharedPlugin.check.js +1 -1
- package/schemas/plugins/sharing/ProvideSharedPlugin.check.d.ts +1 -1
- package/schemas/plugins/sharing/ProvideSharedPlugin.check.js +1 -1
- package/schemas/plugins/sharing/SharePlugin.check.d.ts +1 -1
- package/schemas/plugins/sharing/SharePlugin.check.js +1 -1
- package/types.d.ts +587 -207
- package/schemas/plugins/JsonModulesPluginGenerator.check.d.ts +0 -7
- package/schemas/plugins/JsonModulesPluginGenerator.json +0 -11
- package/schemas/plugins/JsonModulesPluginParser.check.d.ts +0 -7
- package/schemas/plugins/JsonModulesPluginParser.json +0 -16
@@ -389,6 +389,8 @@ const EMPTY_COMMENT_OPTIONS = {
|
|
389
389
|
errors: null
|
390
390
|
};
|
391
391
|
|
392
|
+
const CLASS_NAME = "JavascriptParser";
|
393
|
+
|
392
394
|
class JavascriptParser extends Parser {
|
393
395
|
/**
|
394
396
|
* @param {"module" | "script" | "auto"} sourceType default source type
|
@@ -600,7 +602,7 @@ class JavascriptParser extends Parser {
|
|
600
602
|
}
|
601
603
|
|
602
604
|
_initializeEvaluating() {
|
603
|
-
this.hooks.evaluate.for("Literal").tap(
|
605
|
+
this.hooks.evaluate.for("Literal").tap(CLASS_NAME, _expr => {
|
604
606
|
const expr = /** @type {Literal} */ (_expr);
|
605
607
|
|
606
608
|
switch (typeof expr.value) {
|
@@ -632,7 +634,7 @@ class JavascriptParser extends Parser {
|
|
632
634
|
.setRange(/** @type {Range} */ (expr.range));
|
633
635
|
}
|
634
636
|
});
|
635
|
-
this.hooks.evaluate.for("NewExpression").tap(
|
637
|
+
this.hooks.evaluate.for("NewExpression").tap(CLASS_NAME, _expr => {
|
636
638
|
const expr = /** @type {NewExpression} */ (_expr);
|
637
639
|
const callee = expr.callee;
|
638
640
|
if (callee.type !== "Identifier") return;
|
@@ -695,52 +697,50 @@ class JavascriptParser extends Parser {
|
|
695
697
|
.setRegExp(flags ? new RegExp(regExp, flags) : new RegExp(regExp))
|
696
698
|
.setRange(/** @type {Range} */ (expr.range));
|
697
699
|
});
|
698
|
-
this.hooks.evaluate
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
if (
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
return right.setRange(/** @type {Range} */ (expr.range));
|
730
|
-
}
|
700
|
+
this.hooks.evaluate.for("LogicalExpression").tap(CLASS_NAME, _expr => {
|
701
|
+
const expr = /** @type {LogicalExpression} */ (_expr);
|
702
|
+
|
703
|
+
const left = this.evaluateExpression(expr.left);
|
704
|
+
let returnRight = false;
|
705
|
+
/** @type {boolean | undefined} */
|
706
|
+
let allowedRight;
|
707
|
+
if (expr.operator === "&&") {
|
708
|
+
const leftAsBool = left.asBool();
|
709
|
+
if (leftAsBool === false)
|
710
|
+
return left.setRange(/** @type {Range} */ (expr.range));
|
711
|
+
returnRight = leftAsBool === true;
|
712
|
+
allowedRight = false;
|
713
|
+
} else if (expr.operator === "||") {
|
714
|
+
const leftAsBool = left.asBool();
|
715
|
+
if (leftAsBool === true)
|
716
|
+
return left.setRange(/** @type {Range} */ (expr.range));
|
717
|
+
returnRight = leftAsBool === false;
|
718
|
+
allowedRight = true;
|
719
|
+
} else if (expr.operator === "??") {
|
720
|
+
const leftAsNullish = left.asNullish();
|
721
|
+
if (leftAsNullish === false)
|
722
|
+
return left.setRange(/** @type {Range} */ (expr.range));
|
723
|
+
if (leftAsNullish !== true) return;
|
724
|
+
returnRight = true;
|
725
|
+
} else return;
|
726
|
+
const right = this.evaluateExpression(expr.right);
|
727
|
+
if (returnRight) {
|
728
|
+
if (left.couldHaveSideEffects()) right.setSideEffects();
|
729
|
+
return right.setRange(/** @type {Range} */ (expr.range));
|
730
|
+
}
|
731
731
|
|
732
|
-
|
732
|
+
const asBool = right.asBool();
|
733
733
|
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
734
|
+
if (allowedRight === true && asBool === true) {
|
735
|
+
return new BasicEvaluatedExpression()
|
736
|
+
.setRange(/** @type {Range} */ (expr.range))
|
737
|
+
.setTruthy();
|
738
|
+
} else if (allowedRight === false && asBool === false) {
|
739
|
+
return new BasicEvaluatedExpression()
|
740
|
+
.setRange(/** @type {Range} */ (expr.range))
|
741
|
+
.setFalsy();
|
742
|
+
}
|
743
|
+
});
|
744
744
|
|
745
745
|
/**
|
746
746
|
* In simple logical cases, we can use valueAsExpression to assist us in evaluating the expression on
|
@@ -810,553 +810,539 @@ class JavascriptParser extends Parser {
|
|
810
810
|
}
|
811
811
|
};
|
812
812
|
|
813
|
-
this.hooks.evaluate
|
814
|
-
|
815
|
-
.tap("JavascriptParser", _expr => {
|
816
|
-
const expr = /** @type {BinaryExpression} */ (_expr);
|
813
|
+
this.hooks.evaluate.for("BinaryExpression").tap(CLASS_NAME, _expr => {
|
814
|
+
const expr = /** @type {BinaryExpression} */ (_expr);
|
817
815
|
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
const right = this.evaluateExpression(expr.right);
|
829
|
-
if (!right.isCompileTimeValue()) return;
|
816
|
+
/**
|
817
|
+
* Evaluates a binary expression if and only if it is a const operation (e.g. 1 + 2, "a" + "b", etc.).
|
818
|
+
* @template T
|
819
|
+
* @param {(leftOperand: T, rightOperand: T) => boolean | number | bigint | string} operandHandler the handler for the operation (e.g. (a, b) => a + b)
|
820
|
+
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
821
|
+
*/
|
822
|
+
const handleConstOperation = operandHandler => {
|
823
|
+
const left = this.evaluateExpression(expr.left);
|
824
|
+
if (!left.isCompileTimeValue()) return;
|
830
825
|
|
831
|
-
|
832
|
-
|
833
|
-
/** @type {T} */ (right.asCompileTimeValue())
|
834
|
-
);
|
835
|
-
return valueAsExpression(
|
836
|
-
result,
|
837
|
-
expr,
|
838
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
839
|
-
);
|
840
|
-
};
|
826
|
+
const right = this.evaluateExpression(expr.right);
|
827
|
+
if (!right.isCompileTimeValue()) return;
|
841
828
|
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
829
|
+
const result = operandHandler(
|
830
|
+
/** @type {T} */ (left.asCompileTimeValue()),
|
831
|
+
/** @type {T} */ (right.asCompileTimeValue())
|
832
|
+
);
|
833
|
+
return valueAsExpression(
|
834
|
+
result,
|
835
|
+
expr,
|
836
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
837
|
+
);
|
838
|
+
};
|
851
839
|
|
840
|
+
/**
|
841
|
+
* Helper function to determine if two booleans are always different. This is used in `handleStrictEqualityComparison`
|
842
|
+
* to determine if an expressions boolean or nullish conversion is equal or not.
|
843
|
+
* @param {boolean} a first boolean to compare
|
844
|
+
* @param {boolean} b second boolean to compare
|
845
|
+
* @returns {boolean} true if the two booleans are always different, false otherwise
|
846
|
+
*/
|
847
|
+
const isAlwaysDifferent = (a, b) =>
|
848
|
+
(a === true && b === false) || (a === false && b === true);
|
849
|
+
|
850
|
+
/**
|
851
|
+
* @param {BasicEvaluatedExpression} left left
|
852
|
+
* @param {BasicEvaluatedExpression} right right
|
853
|
+
* @param {BasicEvaluatedExpression} res res
|
854
|
+
* @param {boolean} eql true for "===" and false for "!=="
|
855
|
+
* @returns {BasicEvaluatedExpression | undefined} result
|
856
|
+
*/
|
857
|
+
const handleTemplateStringCompare = (left, right, res, eql) => {
|
852
858
|
/**
|
853
|
-
* @param {BasicEvaluatedExpression}
|
854
|
-
* @
|
855
|
-
* @param {BasicEvaluatedExpression} res res
|
856
|
-
* @param {boolean} eql true for "===" and false for "!=="
|
857
|
-
* @returns {BasicEvaluatedExpression | undefined} result
|
859
|
+
* @param {BasicEvaluatedExpression[]} parts parts
|
860
|
+
* @returns {string} value
|
858
861
|
*/
|
859
|
-
const
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
let value = "";
|
866
|
-
for (const p of parts) {
|
867
|
-
const v = p.asString();
|
868
|
-
if (v !== undefined) value += v;
|
869
|
-
else break;
|
870
|
-
}
|
871
|
-
return value;
|
872
|
-
};
|
873
|
-
/**
|
874
|
-
* @param {BasicEvaluatedExpression[]} parts parts
|
875
|
-
* @returns {string} value
|
876
|
-
*/
|
877
|
-
const getSuffix = parts => {
|
878
|
-
let value = "";
|
879
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
880
|
-
const v = parts[i].asString();
|
881
|
-
if (v !== undefined) value = v + value;
|
882
|
-
else break;
|
883
|
-
}
|
884
|
-
return value;
|
885
|
-
};
|
886
|
-
const leftPrefix = getPrefix(
|
887
|
-
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
888
|
-
);
|
889
|
-
const rightPrefix = getPrefix(
|
890
|
-
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
891
|
-
);
|
892
|
-
const leftSuffix = getSuffix(
|
893
|
-
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
894
|
-
);
|
895
|
-
const rightSuffix = getSuffix(
|
896
|
-
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
897
|
-
);
|
898
|
-
const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
|
899
|
-
const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
|
900
|
-
const prefixMismatch =
|
901
|
-
lenPrefix > 0 &&
|
902
|
-
leftPrefix.slice(0, lenPrefix) !== rightPrefix.slice(0, lenPrefix);
|
903
|
-
const suffixMismatch =
|
904
|
-
lenSuffix > 0 &&
|
905
|
-
leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix);
|
906
|
-
if (prefixMismatch || suffixMismatch) {
|
907
|
-
return res
|
908
|
-
.setBoolean(!eql)
|
909
|
-
.setSideEffects(
|
910
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
911
|
-
);
|
862
|
+
const getPrefix = parts => {
|
863
|
+
let value = "";
|
864
|
+
for (const p of parts) {
|
865
|
+
const v = p.asString();
|
866
|
+
if (v !== undefined) value += v;
|
867
|
+
else break;
|
912
868
|
}
|
869
|
+
return value;
|
913
870
|
};
|
914
|
-
|
915
871
|
/**
|
916
|
-
*
|
917
|
-
* @
|
918
|
-
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
872
|
+
* @param {BasicEvaluatedExpression[]} parts parts
|
873
|
+
* @returns {string} value
|
919
874
|
*/
|
920
|
-
const
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
const leftConst = left.isCompileTimeValue();
|
927
|
-
const rightConst = right.isCompileTimeValue();
|
928
|
-
|
929
|
-
if (leftConst && rightConst) {
|
930
|
-
return res
|
931
|
-
.setBoolean(
|
932
|
-
eql ===
|
933
|
-
(left.asCompileTimeValue() === right.asCompileTimeValue())
|
934
|
-
)
|
935
|
-
.setSideEffects(
|
936
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
937
|
-
);
|
875
|
+
const getSuffix = parts => {
|
876
|
+
let value = "";
|
877
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
878
|
+
const v = parts[i].asString();
|
879
|
+
if (v !== undefined) value = v + value;
|
880
|
+
else break;
|
938
881
|
}
|
882
|
+
return value;
|
883
|
+
};
|
884
|
+
const leftPrefix = getPrefix(
|
885
|
+
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
886
|
+
);
|
887
|
+
const rightPrefix = getPrefix(
|
888
|
+
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
889
|
+
);
|
890
|
+
const leftSuffix = getSuffix(
|
891
|
+
/** @type {BasicEvaluatedExpression[]} */ (left.parts)
|
892
|
+
);
|
893
|
+
const rightSuffix = getSuffix(
|
894
|
+
/** @type {BasicEvaluatedExpression[]} */ (right.parts)
|
895
|
+
);
|
896
|
+
const lenPrefix = Math.min(leftPrefix.length, rightPrefix.length);
|
897
|
+
const lenSuffix = Math.min(leftSuffix.length, rightSuffix.length);
|
898
|
+
const prefixMismatch =
|
899
|
+
lenPrefix > 0 &&
|
900
|
+
leftPrefix.slice(0, lenPrefix) !== rightPrefix.slice(0, lenPrefix);
|
901
|
+
const suffixMismatch =
|
902
|
+
lenSuffix > 0 &&
|
903
|
+
leftSuffix.slice(-lenSuffix) !== rightSuffix.slice(-lenSuffix);
|
904
|
+
if (prefixMismatch || suffixMismatch) {
|
905
|
+
return res
|
906
|
+
.setBoolean(!eql)
|
907
|
+
.setSideEffects(
|
908
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
909
|
+
);
|
910
|
+
}
|
911
|
+
};
|
939
912
|
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
913
|
+
/**
|
914
|
+
* Helper function to handle BinaryExpressions using strict equality comparisons (e.g. "===" and "!==").
|
915
|
+
* @param {boolean} eql true for "===" and false for "!=="
|
916
|
+
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
917
|
+
*/
|
918
|
+
const handleStrictEqualityComparison = eql => {
|
919
|
+
const left = this.evaluateExpression(expr.left);
|
920
|
+
const right = this.evaluateExpression(expr.right);
|
921
|
+
const res = new BasicEvaluatedExpression();
|
922
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
950
923
|
|
951
|
-
|
952
|
-
|
924
|
+
const leftConst = left.isCompileTimeValue();
|
925
|
+
const rightConst = right.isCompileTimeValue();
|
953
926
|
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
(leftConst || rightPrimitive === true)) ||
|
959
|
-
(rightPrimitive === false &&
|
960
|
-
(rightConst || leftPrimitive === true)) ||
|
961
|
-
// Different nullish or boolish status also means not equal
|
962
|
-
isAlwaysDifferent(
|
963
|
-
/** @type {boolean} */ (left.asBool()),
|
964
|
-
/** @type {boolean} */ (right.asBool())
|
965
|
-
) ||
|
966
|
-
isAlwaysDifferent(
|
967
|
-
/** @type {boolean} */ (left.asNullish()),
|
968
|
-
/** @type {boolean} */ (right.asNullish())
|
927
|
+
if (leftConst && rightConst) {
|
928
|
+
return res
|
929
|
+
.setBoolean(
|
930
|
+
eql === (left.asCompileTimeValue() === right.asCompileTimeValue())
|
969
931
|
)
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
975
|
-
);
|
976
|
-
}
|
977
|
-
};
|
932
|
+
.setSideEffects(
|
933
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
934
|
+
);
|
935
|
+
}
|
978
936
|
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
const leftConst = left.isCompileTimeValue();
|
991
|
-
const rightConst = right.isCompileTimeValue();
|
992
|
-
|
993
|
-
if (leftConst && rightConst) {
|
994
|
-
return res
|
995
|
-
.setBoolean(
|
996
|
-
eql ===
|
997
|
-
// eslint-disable-next-line eqeqeq
|
998
|
-
(left.asCompileTimeValue() == right.asCompileTimeValue())
|
999
|
-
)
|
1000
|
-
.setSideEffects(
|
1001
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
1002
|
-
);
|
1003
|
-
}
|
937
|
+
if (left.isArray() && right.isArray()) {
|
938
|
+
return res
|
939
|
+
.setBoolean(!eql)
|
940
|
+
.setSideEffects(
|
941
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
942
|
+
);
|
943
|
+
}
|
944
|
+
if (left.isTemplateString() && right.isTemplateString()) {
|
945
|
+
return handleTemplateStringCompare(left, right, res, eql);
|
946
|
+
}
|
1004
947
|
|
1005
|
-
|
1006
|
-
|
1007
|
-
.setBoolean(!eql)
|
1008
|
-
.setSideEffects(
|
1009
|
-
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
1010
|
-
);
|
1011
|
-
}
|
1012
|
-
if (left.isTemplateString() && right.isTemplateString()) {
|
1013
|
-
return handleTemplateStringCompare(left, right, res, eql);
|
1014
|
-
}
|
1015
|
-
};
|
948
|
+
const leftPrimitive = left.isPrimitiveType();
|
949
|
+
const rightPrimitive = right.isPrimitiveType();
|
1016
950
|
|
1017
|
-
if (
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
}
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
)
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
951
|
+
if (
|
952
|
+
// Primitive !== Object or
|
953
|
+
// compile-time object types are never equal to something at runtime
|
954
|
+
(leftPrimitive === false && (leftConst || rightPrimitive === true)) ||
|
955
|
+
(rightPrimitive === false &&
|
956
|
+
(rightConst || leftPrimitive === true)) ||
|
957
|
+
// Different nullish or boolish status also means not equal
|
958
|
+
isAlwaysDifferent(
|
959
|
+
/** @type {boolean} */ (left.asBool()),
|
960
|
+
/** @type {boolean} */ (right.asBool())
|
961
|
+
) ||
|
962
|
+
isAlwaysDifferent(
|
963
|
+
/** @type {boolean} */ (left.asNullish()),
|
964
|
+
/** @type {boolean} */ (right.asNullish())
|
965
|
+
)
|
966
|
+
) {
|
967
|
+
return res
|
968
|
+
.setBoolean(!eql)
|
969
|
+
.setSideEffects(
|
970
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
971
|
+
);
|
972
|
+
}
|
973
|
+
};
|
974
|
+
|
975
|
+
/**
|
976
|
+
* Helper function to handle BinaryExpressions using abstract equality comparisons (e.g. "==" and "!=").
|
977
|
+
* @param {boolean} eql true for "==" and false for "!="
|
978
|
+
* @returns {BasicEvaluatedExpression | undefined} the evaluated expression
|
979
|
+
*/
|
980
|
+
const handleAbstractEqualityComparison = eql => {
|
981
|
+
const left = this.evaluateExpression(expr.left);
|
982
|
+
const right = this.evaluateExpression(expr.right);
|
983
|
+
const res = new BasicEvaluatedExpression();
|
984
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
985
|
+
|
986
|
+
const leftConst = left.isCompileTimeValue();
|
987
|
+
const rightConst = right.isCompileTimeValue();
|
988
|
+
|
989
|
+
if (leftConst && rightConst) {
|
990
|
+
return res
|
991
|
+
.setBoolean(
|
992
|
+
eql ===
|
993
|
+
// eslint-disable-next-line eqeqeq
|
994
|
+
(left.asCompileTimeValue() == right.asCompileTimeValue())
|
995
|
+
)
|
996
|
+
.setSideEffects(
|
997
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
998
|
+
);
|
999
|
+
}
|
1000
|
+
|
1001
|
+
if (left.isArray() && right.isArray()) {
|
1002
|
+
return res
|
1003
|
+
.setBoolean(!eql)
|
1004
|
+
.setSideEffects(
|
1005
|
+
left.couldHaveSideEffects() || right.couldHaveSideEffects()
|
1006
|
+
);
|
1007
|
+
}
|
1008
|
+
if (left.isTemplateString() && right.isTemplateString()) {
|
1009
|
+
return handleTemplateStringCompare(left, right, res, eql);
|
1010
|
+
}
|
1011
|
+
};
|
1012
|
+
|
1013
|
+
if (expr.operator === "+") {
|
1014
|
+
const left = this.evaluateExpression(expr.left);
|
1015
|
+
const right = this.evaluateExpression(expr.right);
|
1016
|
+
const res = new BasicEvaluatedExpression();
|
1017
|
+
if (left.isString()) {
|
1018
|
+
if (right.isString()) {
|
1019
|
+
res.setString(
|
1020
|
+
/** @type {string} */ (left.string) +
|
1021
|
+
/** @type {string} */ (right.string)
|
1022
|
+
);
|
1023
|
+
} else if (right.isNumber()) {
|
1024
|
+
res.setString(/** @type {string} */ (left.string) + right.number);
|
1025
|
+
} else if (
|
1026
|
+
right.isWrapped() &&
|
1027
|
+
right.prefix &&
|
1028
|
+
right.prefix.isString()
|
1029
|
+
) {
|
1030
|
+
// "left" + ("prefix" + inner + "postfix")
|
1031
|
+
// => ("leftPrefix" + inner + "postfix")
|
1032
|
+
res.setWrapped(
|
1033
|
+
new BasicEvaluatedExpression()
|
1034
|
+
.setString(
|
1035
|
+
/** @type {string} */ (left.string) +
|
1036
|
+
/** @type {string} */ (right.prefix.string)
|
1037
|
+
)
|
1038
|
+
.setRange(
|
1039
|
+
joinRanges(
|
1040
|
+
/** @type {Range} */ (left.range),
|
1041
|
+
/** @type {Range} */ (right.prefix.range)
|
1092
1042
|
)
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1043
|
+
),
|
1044
|
+
right.postfix,
|
1045
|
+
right.wrappedInnerExpressions
|
1046
|
+
);
|
1047
|
+
} else if (right.isWrapped()) {
|
1048
|
+
// "left" + ([null] + inner + "postfix")
|
1049
|
+
// => ("left" + inner + "postfix")
|
1050
|
+
res.setWrapped(left, right.postfix, right.wrappedInnerExpressions);
|
1051
|
+
} else {
|
1052
|
+
// "left" + expr
|
1053
|
+
// => ("left" + expr + "")
|
1054
|
+
res.setWrapped(left, null, [right]);
|
1055
|
+
}
|
1056
|
+
} else if (left.isNumber()) {
|
1057
|
+
if (right.isString()) {
|
1058
|
+
res.setString(left.number + /** @type {string} */ (right.string));
|
1059
|
+
} else if (right.isNumber()) {
|
1060
|
+
res.setNumber(
|
1061
|
+
/** @type {number} */ (left.number) +
|
1062
|
+
/** @type {number} */ (right.number)
|
1063
|
+
);
|
1064
|
+
} else {
|
1065
|
+
return;
|
1066
|
+
}
|
1067
|
+
} else if (left.isBigInt()) {
|
1068
|
+
if (right.isBigInt()) {
|
1069
|
+
res.setBigInt(
|
1070
|
+
/** @type {bigint} */ (left.bigint) +
|
1071
|
+
/** @type {bigint} */ (right.bigint)
|
1072
|
+
);
|
1073
|
+
}
|
1074
|
+
} else if (left.isWrapped()) {
|
1075
|
+
if (left.postfix && left.postfix.isString() && right.isString()) {
|
1076
|
+
// ("prefix" + inner + "postfix") + "right"
|
1077
|
+
// => ("prefix" + inner + "postfixRight")
|
1078
|
+
res.setWrapped(
|
1079
|
+
left.prefix,
|
1080
|
+
new BasicEvaluatedExpression()
|
1081
|
+
.setString(
|
1082
|
+
/** @type {string} */ (left.postfix.string) +
|
1083
|
+
/** @type {string} */ (right.string)
|
1084
|
+
)
|
1085
|
+
.setRange(
|
1086
|
+
joinRanges(
|
1087
|
+
/** @type {Range} */ (left.postfix.range),
|
1088
|
+
/** @type {Range} */ (right.range)
|
1114
1089
|
)
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
);
|
1137
|
-
} else if (right.isWrapped()) {
|
1138
|
-
// ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2")
|
1139
|
-
// ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2")
|
1140
|
-
res.setWrapped(
|
1141
|
-
left.prefix,
|
1142
|
-
right.postfix,
|
1143
|
-
left.wrappedInnerExpressions &&
|
1144
|
-
right.wrappedInnerExpressions &&
|
1145
|
-
left.wrappedInnerExpressions
|
1146
|
-
.concat(left.postfix ? [left.postfix] : [])
|
1147
|
-
.concat(right.prefix ? [right.prefix] : [])
|
1148
|
-
.concat(right.wrappedInnerExpressions)
|
1149
|
-
);
|
1150
|
-
} else {
|
1151
|
-
// ("prefix" + inner + postfix) + expr
|
1152
|
-
// => ("prefix" + inner + postfix + expr + [null])
|
1153
|
-
res.setWrapped(
|
1154
|
-
left.prefix,
|
1155
|
-
null,
|
1156
|
-
left.wrappedInnerExpressions &&
|
1157
|
-
left.wrappedInnerExpressions.concat(
|
1158
|
-
left.postfix ? [left.postfix, right] : [right]
|
1090
|
+
),
|
1091
|
+
left.wrappedInnerExpressions
|
1092
|
+
);
|
1093
|
+
} else if (
|
1094
|
+
left.postfix &&
|
1095
|
+
left.postfix.isString() &&
|
1096
|
+
right.isNumber()
|
1097
|
+
) {
|
1098
|
+
// ("prefix" + inner + "postfix") + 123
|
1099
|
+
// => ("prefix" + inner + "postfix123")
|
1100
|
+
res.setWrapped(
|
1101
|
+
left.prefix,
|
1102
|
+
new BasicEvaluatedExpression()
|
1103
|
+
.setString(
|
1104
|
+
/** @type {string} */ (left.postfix.string) +
|
1105
|
+
/** @type {number} */ (right.number)
|
1106
|
+
)
|
1107
|
+
.setRange(
|
1108
|
+
joinRanges(
|
1109
|
+
/** @type {Range} */ (left.postfix.range),
|
1110
|
+
/** @type {Range} */ (right.range)
|
1159
1111
|
)
|
1160
|
-
|
1161
|
-
|
1112
|
+
),
|
1113
|
+
left.wrappedInnerExpressions
|
1114
|
+
);
|
1162
1115
|
} else if (right.isString()) {
|
1163
|
-
//
|
1164
|
-
// => (
|
1165
|
-
res.setWrapped(
|
1116
|
+
// ("prefix" + inner + [null]) + "right"
|
1117
|
+
// => ("prefix" + inner + "right")
|
1118
|
+
res.setWrapped(left.prefix, right, left.wrappedInnerExpressions);
|
1119
|
+
} else if (right.isNumber()) {
|
1120
|
+
// ("prefix" + inner + [null]) + 123
|
1121
|
+
// => ("prefix" + inner + "123")
|
1122
|
+
res.setWrapped(
|
1123
|
+
left.prefix,
|
1124
|
+
new BasicEvaluatedExpression()
|
1125
|
+
.setString(String(right.number))
|
1126
|
+
.setRange(/** @type {Range} */ (right.range)),
|
1127
|
+
left.wrappedInnerExpressions
|
1128
|
+
);
|
1166
1129
|
} else if (right.isWrapped()) {
|
1167
|
-
//
|
1168
|
-
//
|
1130
|
+
// ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2")
|
1131
|
+
// ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2")
|
1169
1132
|
res.setWrapped(
|
1170
|
-
|
1133
|
+
left.prefix,
|
1171
1134
|
right.postfix,
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1135
|
+
left.wrappedInnerExpressions &&
|
1136
|
+
right.wrappedInnerExpressions &&
|
1137
|
+
left.wrappedInnerExpressions
|
1138
|
+
.concat(left.postfix ? [left.postfix] : [])
|
1139
|
+
.concat(right.prefix ? [right.prefix] : [])
|
1140
|
+
.concat(right.wrappedInnerExpressions)
|
1176
1141
|
);
|
1177
1142
|
} else {
|
1178
|
-
|
1143
|
+
// ("prefix" + inner + postfix) + expr
|
1144
|
+
// => ("prefix" + inner + postfix + expr + [null])
|
1145
|
+
res.setWrapped(
|
1146
|
+
left.prefix,
|
1147
|
+
null,
|
1148
|
+
left.wrappedInnerExpressions &&
|
1149
|
+
left.wrappedInnerExpressions.concat(
|
1150
|
+
left.postfix ? [left.postfix, right] : [right]
|
1151
|
+
)
|
1152
|
+
);
|
1179
1153
|
}
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
} else if (
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
} else if (expr.operator === "==") {
|
1195
|
-
return handleAbstractEqualityComparison(true);
|
1196
|
-
} else if (expr.operator === "!==") {
|
1197
|
-
return handleStrictEqualityComparison(false);
|
1198
|
-
} else if (expr.operator === "!=") {
|
1199
|
-
return handleAbstractEqualityComparison(false);
|
1200
|
-
} else if (expr.operator === "&") {
|
1201
|
-
return handleConstOperation((l, r) => l & r);
|
1202
|
-
} else if (expr.operator === "|") {
|
1203
|
-
return handleConstOperation((l, r) => l | r);
|
1204
|
-
} else if (expr.operator === "^") {
|
1205
|
-
return handleConstOperation((l, r) => l ^ r);
|
1206
|
-
} else if (expr.operator === ">>>") {
|
1207
|
-
return handleConstOperation((l, r) => l >>> r);
|
1208
|
-
} else if (expr.operator === ">>") {
|
1209
|
-
return handleConstOperation((l, r) => l >> r);
|
1210
|
-
} else if (expr.operator === "<<") {
|
1211
|
-
return handleConstOperation((l, r) => l << r);
|
1212
|
-
} else if (expr.operator === "<") {
|
1213
|
-
return handleConstOperation((l, r) => l < r);
|
1214
|
-
} else if (expr.operator === ">") {
|
1215
|
-
return handleConstOperation((l, r) => l > r);
|
1216
|
-
} else if (expr.operator === "<=") {
|
1217
|
-
return handleConstOperation((l, r) => l <= r);
|
1218
|
-
} else if (expr.operator === ">=") {
|
1219
|
-
return handleConstOperation((l, r) => l >= r);
|
1220
|
-
}
|
1221
|
-
});
|
1222
|
-
this.hooks.evaluate
|
1223
|
-
.for("UnaryExpression")
|
1224
|
-
.tap("JavascriptParser", _expr => {
|
1225
|
-
const expr = /** @type {UnaryExpression} */ (_expr);
|
1226
|
-
|
1227
|
-
/**
|
1228
|
-
* Evaluates a UnaryExpression if and only if it is a basic const operator (e.g. +a, -a, ~a).
|
1229
|
-
* @template T
|
1230
|
-
* @param {(operand: T) => boolean | number | bigint | string} operandHandler handler for the operand
|
1231
|
-
* @returns {BasicEvaluatedExpression | undefined} evaluated expression
|
1232
|
-
*/
|
1233
|
-
const handleConstOperation = operandHandler => {
|
1234
|
-
const argument = this.evaluateExpression(expr.argument);
|
1235
|
-
if (!argument.isCompileTimeValue()) return;
|
1236
|
-
const result = operandHandler(
|
1237
|
-
/** @type {T} */ (argument.asCompileTimeValue())
|
1238
|
-
);
|
1239
|
-
return valueAsExpression(
|
1240
|
-
result,
|
1241
|
-
expr,
|
1242
|
-
argument.couldHaveSideEffects()
|
1154
|
+
} else if (right.isString()) {
|
1155
|
+
// left + "right"
|
1156
|
+
// => ([null] + left + "right")
|
1157
|
+
res.setWrapped(null, right, [left]);
|
1158
|
+
} else if (right.isWrapped()) {
|
1159
|
+
// left + (prefix + inner + "postfix")
|
1160
|
+
// => ([null] + left + prefix + inner + "postfix")
|
1161
|
+
res.setWrapped(
|
1162
|
+
null,
|
1163
|
+
right.postfix,
|
1164
|
+
right.wrappedInnerExpressions &&
|
1165
|
+
(right.prefix ? [left, right.prefix] : [left]).concat(
|
1166
|
+
right.wrappedInnerExpressions
|
1167
|
+
)
|
1243
1168
|
);
|
1244
|
-
}
|
1169
|
+
} else {
|
1170
|
+
return;
|
1171
|
+
}
|
1172
|
+
if (left.couldHaveSideEffects() || right.couldHaveSideEffects())
|
1173
|
+
res.setSideEffects();
|
1174
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
1175
|
+
return res;
|
1176
|
+
} else if (expr.operator === "-") {
|
1177
|
+
return handleConstOperation((l, r) => l - r);
|
1178
|
+
} else if (expr.operator === "*") {
|
1179
|
+
return handleConstOperation((l, r) => l * r);
|
1180
|
+
} else if (expr.operator === "/") {
|
1181
|
+
return handleConstOperation((l, r) => l / r);
|
1182
|
+
} else if (expr.operator === "**") {
|
1183
|
+
return handleConstOperation((l, r) => l ** r);
|
1184
|
+
} else if (expr.operator === "===") {
|
1185
|
+
return handleStrictEqualityComparison(true);
|
1186
|
+
} else if (expr.operator === "==") {
|
1187
|
+
return handleAbstractEqualityComparison(true);
|
1188
|
+
} else if (expr.operator === "!==") {
|
1189
|
+
return handleStrictEqualityComparison(false);
|
1190
|
+
} else if (expr.operator === "!=") {
|
1191
|
+
return handleAbstractEqualityComparison(false);
|
1192
|
+
} else if (expr.operator === "&") {
|
1193
|
+
return handleConstOperation((l, r) => l & r);
|
1194
|
+
} else if (expr.operator === "|") {
|
1195
|
+
return handleConstOperation((l, r) => l | r);
|
1196
|
+
} else if (expr.operator === "^") {
|
1197
|
+
return handleConstOperation((l, r) => l ^ r);
|
1198
|
+
} else if (expr.operator === ">>>") {
|
1199
|
+
return handleConstOperation((l, r) => l >>> r);
|
1200
|
+
} else if (expr.operator === ">>") {
|
1201
|
+
return handleConstOperation((l, r) => l >> r);
|
1202
|
+
} else if (expr.operator === "<<") {
|
1203
|
+
return handleConstOperation((l, r) => l << r);
|
1204
|
+
} else if (expr.operator === "<") {
|
1205
|
+
return handleConstOperation((l, r) => l < r);
|
1206
|
+
} else if (expr.operator === ">") {
|
1207
|
+
return handleConstOperation((l, r) => l > r);
|
1208
|
+
} else if (expr.operator === "<=") {
|
1209
|
+
return handleConstOperation((l, r) => l <= r);
|
1210
|
+
} else if (expr.operator === ">=") {
|
1211
|
+
return handleConstOperation((l, r) => l >= r);
|
1212
|
+
}
|
1213
|
+
});
|
1214
|
+
this.hooks.evaluate.for("UnaryExpression").tap(CLASS_NAME, _expr => {
|
1215
|
+
const expr = /** @type {UnaryExpression} */ (_expr);
|
1216
|
+
|
1217
|
+
/**
|
1218
|
+
* Evaluates a UnaryExpression if and only if it is a basic const operator (e.g. +a, -a, ~a).
|
1219
|
+
* @template T
|
1220
|
+
* @param {(operand: T) => boolean | number | bigint | string} operandHandler handler for the operand
|
1221
|
+
* @returns {BasicEvaluatedExpression | undefined} evaluated expression
|
1222
|
+
*/
|
1223
|
+
const handleConstOperation = operandHandler => {
|
1224
|
+
const argument = this.evaluateExpression(expr.argument);
|
1225
|
+
if (!argument.isCompileTimeValue()) return;
|
1226
|
+
const result = operandHandler(
|
1227
|
+
/** @type {T} */ (argument.asCompileTimeValue())
|
1228
|
+
);
|
1229
|
+
return valueAsExpression(result, expr, argument.couldHaveSideEffects());
|
1230
|
+
};
|
1245
1231
|
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
}
|
1257
|
-
case "MetaProperty": {
|
1258
|
-
const res = this.callHooksForName(
|
1259
|
-
this.hooks.evaluateTypeof,
|
1260
|
-
/** @type {string} */
|
1261
|
-
(getRootName(expr.argument)),
|
1262
|
-
expr
|
1263
|
-
);
|
1264
|
-
if (res !== undefined) return res;
|
1265
|
-
break;
|
1266
|
-
}
|
1267
|
-
case "MemberExpression": {
|
1268
|
-
const res = this.callHooksForExpression(
|
1269
|
-
this.hooks.evaluateTypeof,
|
1270
|
-
expr.argument,
|
1271
|
-
expr
|
1272
|
-
);
|
1273
|
-
if (res !== undefined) return res;
|
1274
|
-
break;
|
1275
|
-
}
|
1276
|
-
case "ChainExpression": {
|
1277
|
-
const res = this.callHooksForExpression(
|
1278
|
-
this.hooks.evaluateTypeof,
|
1279
|
-
expr.argument.expression,
|
1280
|
-
expr
|
1281
|
-
);
|
1282
|
-
if (res !== undefined) return res;
|
1283
|
-
break;
|
1284
|
-
}
|
1285
|
-
case "FunctionExpression": {
|
1286
|
-
return new BasicEvaluatedExpression()
|
1287
|
-
.setString("function")
|
1288
|
-
.setRange(/** @type {Range} */ (expr.range));
|
1289
|
-
}
|
1290
|
-
}
|
1291
|
-
const arg = this.evaluateExpression(expr.argument);
|
1292
|
-
if (arg.isUnknown()) return;
|
1293
|
-
if (arg.isString()) {
|
1294
|
-
return new BasicEvaluatedExpression()
|
1295
|
-
.setString("string")
|
1296
|
-
.setRange(/** @type {Range} */ (expr.range));
|
1297
|
-
}
|
1298
|
-
if (arg.isWrapped()) {
|
1299
|
-
return new BasicEvaluatedExpression()
|
1300
|
-
.setString("string")
|
1301
|
-
.setSideEffects()
|
1302
|
-
.setRange(/** @type {Range} */ (expr.range));
|
1303
|
-
}
|
1304
|
-
if (arg.isUndefined()) {
|
1305
|
-
return new BasicEvaluatedExpression()
|
1306
|
-
.setString("undefined")
|
1307
|
-
.setRange(/** @type {Range} */ (expr.range));
|
1308
|
-
}
|
1309
|
-
if (arg.isNumber()) {
|
1310
|
-
return new BasicEvaluatedExpression()
|
1311
|
-
.setString("number")
|
1312
|
-
.setRange(/** @type {Range} */ (expr.range));
|
1232
|
+
if (expr.operator === "typeof") {
|
1233
|
+
switch (expr.argument.type) {
|
1234
|
+
case "Identifier": {
|
1235
|
+
const res = this.callHooksForName(
|
1236
|
+
this.hooks.evaluateTypeof,
|
1237
|
+
expr.argument.name,
|
1238
|
+
expr
|
1239
|
+
);
|
1240
|
+
if (res !== undefined) return res;
|
1241
|
+
break;
|
1313
1242
|
}
|
1314
|
-
|
1315
|
-
|
1316
|
-
.
|
1317
|
-
|
1243
|
+
case "MetaProperty": {
|
1244
|
+
const res = this.callHooksForName(
|
1245
|
+
this.hooks.evaluateTypeof,
|
1246
|
+
/** @type {string} */
|
1247
|
+
(getRootName(expr.argument)),
|
1248
|
+
expr
|
1249
|
+
);
|
1250
|
+
if (res !== undefined) return res;
|
1251
|
+
break;
|
1318
1252
|
}
|
1319
|
-
|
1320
|
-
|
1321
|
-
.
|
1322
|
-
|
1253
|
+
case "MemberExpression": {
|
1254
|
+
const res = this.callHooksForExpression(
|
1255
|
+
this.hooks.evaluateTypeof,
|
1256
|
+
expr.argument,
|
1257
|
+
expr
|
1258
|
+
);
|
1259
|
+
if (res !== undefined) return res;
|
1260
|
+
break;
|
1323
1261
|
}
|
1324
|
-
|
1325
|
-
|
1326
|
-
.
|
1327
|
-
|
1262
|
+
case "ChainExpression": {
|
1263
|
+
const res = this.callHooksForExpression(
|
1264
|
+
this.hooks.evaluateTypeof,
|
1265
|
+
expr.argument.expression,
|
1266
|
+
expr
|
1267
|
+
);
|
1268
|
+
if (res !== undefined) return res;
|
1269
|
+
break;
|
1328
1270
|
}
|
1329
|
-
|
1271
|
+
case "FunctionExpression": {
|
1330
1272
|
return new BasicEvaluatedExpression()
|
1331
|
-
.setString("
|
1332
|
-
.setSideEffects(arg.couldHaveSideEffects())
|
1273
|
+
.setString("function")
|
1333
1274
|
.setRange(/** @type {Range} */ (expr.range));
|
1334
1275
|
}
|
1335
|
-
}
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1276
|
+
}
|
1277
|
+
const arg = this.evaluateExpression(expr.argument);
|
1278
|
+
if (arg.isUnknown()) return;
|
1279
|
+
if (arg.isString()) {
|
1339
1280
|
return new BasicEvaluatedExpression()
|
1340
|
-
.
|
1341
|
-
.setSideEffects(argument.couldHaveSideEffects())
|
1281
|
+
.setString("string")
|
1342
1282
|
.setRange(/** @type {Range} */ (expr.range));
|
1343
|
-
} else if (expr.operator === "~") {
|
1344
|
-
return handleConstOperation(v => ~v);
|
1345
|
-
} else if (expr.operator === "+") {
|
1346
|
-
// eslint-disable-next-line no-implicit-coercion
|
1347
|
-
return handleConstOperation(v => +v);
|
1348
|
-
} else if (expr.operator === "-") {
|
1349
|
-
return handleConstOperation(v => -v);
|
1350
1283
|
}
|
1351
|
-
|
1284
|
+
if (arg.isWrapped()) {
|
1285
|
+
return new BasicEvaluatedExpression()
|
1286
|
+
.setString("string")
|
1287
|
+
.setSideEffects()
|
1288
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1289
|
+
}
|
1290
|
+
if (arg.isUndefined()) {
|
1291
|
+
return new BasicEvaluatedExpression()
|
1292
|
+
.setString("undefined")
|
1293
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1294
|
+
}
|
1295
|
+
if (arg.isNumber()) {
|
1296
|
+
return new BasicEvaluatedExpression()
|
1297
|
+
.setString("number")
|
1298
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1299
|
+
}
|
1300
|
+
if (arg.isBigInt()) {
|
1301
|
+
return new BasicEvaluatedExpression()
|
1302
|
+
.setString("bigint")
|
1303
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1304
|
+
}
|
1305
|
+
if (arg.isBoolean()) {
|
1306
|
+
return new BasicEvaluatedExpression()
|
1307
|
+
.setString("boolean")
|
1308
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1309
|
+
}
|
1310
|
+
if (arg.isConstArray() || arg.isRegExp() || arg.isNull()) {
|
1311
|
+
return new BasicEvaluatedExpression()
|
1312
|
+
.setString("object")
|
1313
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1314
|
+
}
|
1315
|
+
if (arg.isArray()) {
|
1316
|
+
return new BasicEvaluatedExpression()
|
1317
|
+
.setString("object")
|
1318
|
+
.setSideEffects(arg.couldHaveSideEffects())
|
1319
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1320
|
+
}
|
1321
|
+
} else if (expr.operator === "!") {
|
1322
|
+
const argument = this.evaluateExpression(expr.argument);
|
1323
|
+
const bool = argument.asBool();
|
1324
|
+
if (typeof bool !== "boolean") return;
|
1325
|
+
return new BasicEvaluatedExpression()
|
1326
|
+
.setBoolean(!bool)
|
1327
|
+
.setSideEffects(argument.couldHaveSideEffects())
|
1328
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1329
|
+
} else if (expr.operator === "~") {
|
1330
|
+
return handleConstOperation(v => ~v);
|
1331
|
+
} else if (expr.operator === "+") {
|
1332
|
+
// eslint-disable-next-line no-implicit-coercion
|
1333
|
+
return handleConstOperation(v => +v);
|
1334
|
+
} else if (expr.operator === "-") {
|
1335
|
+
return handleConstOperation(v => -v);
|
1336
|
+
}
|
1337
|
+
});
|
1352
1338
|
this.hooks.evaluateTypeof
|
1353
1339
|
.for("undefined")
|
1354
|
-
.tap(
|
1340
|
+
.tap(CLASS_NAME, expr =>
|
1355
1341
|
new BasicEvaluatedExpression()
|
1356
1342
|
.setString("undefined")
|
1357
1343
|
.setRange(/** @type {Range} */ (expr.range))
|
1358
1344
|
);
|
1359
|
-
this.hooks.evaluate.for("Identifier").tap(
|
1345
|
+
this.hooks.evaluate.for("Identifier").tap(CLASS_NAME, expr => {
|
1360
1346
|
if (/** @type {Identifier} */ (expr).name === "undefined") {
|
1361
1347
|
return new BasicEvaluatedExpression()
|
1362
1348
|
.setUndefined()
|
@@ -1373,7 +1359,7 @@ class JavascriptParser extends Parser {
|
|
1373
1359
|
let cachedExpression;
|
1374
1360
|
/** @type {GetInfoResult | undefined} */
|
1375
1361
|
let cachedInfo;
|
1376
|
-
this.hooks.evaluate.for(exprType).tap(
|
1362
|
+
this.hooks.evaluate.for(exprType).tap(CLASS_NAME, expr => {
|
1377
1363
|
const expression =
|
1378
1364
|
/** @type {Identifier | ThisExpression | MemberExpression} */ (expr);
|
1379
1365
|
|
@@ -1398,7 +1384,7 @@ class JavascriptParser extends Parser {
|
|
1398
1384
|
});
|
1399
1385
|
this.hooks.evaluate
|
1400
1386
|
.for(exprType)
|
1401
|
-
.tap({ name:
|
1387
|
+
.tap({ name: CLASS_NAME, stage: 100 }, expr => {
|
1402
1388
|
const expression =
|
1403
1389
|
/** @type {Identifier | ThisExpression | MemberExpression} */
|
1404
1390
|
(expr);
|
@@ -1416,7 +1402,7 @@ class JavascriptParser extends Parser {
|
|
1416
1402
|
.setRange(/** @type {Range} */ (expression.range));
|
1417
1403
|
}
|
1418
1404
|
});
|
1419
|
-
this.hooks.finish.tap(
|
1405
|
+
this.hooks.finish.tap(CLASS_NAME, () => {
|
1420
1406
|
// Cleanup for GC
|
1421
1407
|
cachedExpression = cachedInfo = undefined;
|
1422
1408
|
});
|
@@ -1451,7 +1437,7 @@ class JavascriptParser extends Parser {
|
|
1451
1437
|
};
|
1452
1438
|
}
|
1453
1439
|
});
|
1454
|
-
this.hooks.evaluate.for("MetaProperty").tap(
|
1440
|
+
this.hooks.evaluate.for("MetaProperty").tap(CLASS_NAME, expr => {
|
1455
1441
|
const metaProperty = /** @type {MetaProperty} */ (expr);
|
1456
1442
|
|
1457
1443
|
return this.callHooksForName(
|
@@ -1468,7 +1454,7 @@ class JavascriptParser extends Parser {
|
|
1468
1454
|
)
|
1469
1455
|
);
|
1470
1456
|
|
1471
|
-
this.hooks.evaluate.for("CallExpression").tap(
|
1457
|
+
this.hooks.evaluate.for("CallExpression").tap(CLASS_NAME, _expr => {
|
1472
1458
|
const expr = /** @type {CallExpression} */ (_expr);
|
1473
1459
|
if (
|
1474
1460
|
expr.callee.type === "MemberExpression" &&
|
@@ -1497,7 +1483,7 @@ class JavascriptParser extends Parser {
|
|
1497
1483
|
});
|
1498
1484
|
this.hooks.evaluateCallExpressionMember
|
1499
1485
|
.for("indexOf")
|
1500
|
-
.tap(
|
1486
|
+
.tap(CLASS_NAME, (expr, param) => {
|
1501
1487
|
if (!param.isString()) return;
|
1502
1488
|
if (expr.arguments.length === 0) return;
|
1503
1489
|
const [arg1, arg2] = expr.arguments;
|
@@ -1525,7 +1511,7 @@ class JavascriptParser extends Parser {
|
|
1525
1511
|
});
|
1526
1512
|
this.hooks.evaluateCallExpressionMember
|
1527
1513
|
.for("replace")
|
1528
|
-
.tap(
|
1514
|
+
.tap(CLASS_NAME, (expr, param) => {
|
1529
1515
|
if (!param.isString()) return;
|
1530
1516
|
if (expr.arguments.length !== 2) return;
|
1531
1517
|
if (expr.arguments[0].type === "SpreadElement") return;
|
@@ -1548,7 +1534,7 @@ class JavascriptParser extends Parser {
|
|
1548
1534
|
for (const fn of ["substr", "substring", "slice"]) {
|
1549
1535
|
this.hooks.evaluateCallExpressionMember
|
1550
1536
|
.for(fn)
|
1551
|
-
.tap(
|
1537
|
+
.tap(CLASS_NAME, (expr, param) => {
|
1552
1538
|
if (!param.isString()) return;
|
1553
1539
|
let arg1;
|
1554
1540
|
let result;
|
@@ -1640,22 +1626,20 @@ class JavascriptParser extends Parser {
|
|
1640
1626
|
};
|
1641
1627
|
};
|
1642
1628
|
|
1643
|
-
this.hooks.evaluate
|
1644
|
-
|
1645
|
-
.tap("JavascriptParser", _node => {
|
1646
|
-
const node = /** @type {TemplateLiteral} */ (_node);
|
1629
|
+
this.hooks.evaluate.for("TemplateLiteral").tap(CLASS_NAME, _node => {
|
1630
|
+
const node = /** @type {TemplateLiteral} */ (_node);
|
1647
1631
|
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1632
|
+
const { quasis, parts } = getSimplifiedTemplateResult("cooked", node);
|
1633
|
+
if (parts.length === 1) {
|
1634
|
+
return parts[0].setRange(/** @type {Range} */ (node.range));
|
1635
|
+
}
|
1636
|
+
return new BasicEvaluatedExpression()
|
1637
|
+
.setTemplateString(quasis, parts, "cooked")
|
1638
|
+
.setRange(/** @type {Range} */ (node.range));
|
1639
|
+
});
|
1656
1640
|
this.hooks.evaluate
|
1657
1641
|
.for("TaggedTemplateExpression")
|
1658
|
-
.tap(
|
1642
|
+
.tap(CLASS_NAME, _node => {
|
1659
1643
|
const node = /** @type {TaggedTemplateExpression} */ (_node);
|
1660
1644
|
const tag = this.evaluateExpression(node.tag);
|
1661
1645
|
|
@@ -1672,7 +1656,7 @@ class JavascriptParser extends Parser {
|
|
1672
1656
|
|
1673
1657
|
this.hooks.evaluateCallExpressionMember
|
1674
1658
|
.for("concat")
|
1675
|
-
.tap(
|
1659
|
+
.tap(CLASS_NAME, (expr, param) => {
|
1676
1660
|
if (!param.isString() && !param.isWrapped()) return;
|
1677
1661
|
let stringSuffix = null;
|
1678
1662
|
let hasUnknownParams = false;
|
@@ -1742,7 +1726,7 @@ class JavascriptParser extends Parser {
|
|
1742
1726
|
});
|
1743
1727
|
this.hooks.evaluateCallExpressionMember
|
1744
1728
|
.for("split")
|
1745
|
-
.tap(
|
1729
|
+
.tap(CLASS_NAME, (expr, param) => {
|
1746
1730
|
if (!param.isString()) return;
|
1747
1731
|
if (expr.arguments.length !== 1) return;
|
1748
1732
|
if (expr.arguments[0].type === "SpreadElement") return;
|
@@ -1764,101 +1748,95 @@ class JavascriptParser extends Parser {
|
|
1764
1748
|
.setSideEffects(param.couldHaveSideEffects())
|
1765
1749
|
.setRange(/** @type {Range} */ (expr.range));
|
1766
1750
|
});
|
1767
|
-
this.hooks.evaluate
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
res
|
1779
|
-
|
1780
|
-
|
1781
|
-
/** @type {BasicEvaluatedExpression[]} */ (consequent.options)
|
1782
|
-
);
|
1783
|
-
} else {
|
1784
|
-
res.setOptions([consequent]);
|
1785
|
-
}
|
1786
|
-
if (alternate.isConditional()) {
|
1787
|
-
res.addOptions(
|
1788
|
-
/** @type {BasicEvaluatedExpression[]} */ (alternate.options)
|
1789
|
-
);
|
1790
|
-
} else {
|
1791
|
-
res.addOptions([alternate]);
|
1792
|
-
}
|
1751
|
+
this.hooks.evaluate.for("ConditionalExpression").tap(CLASS_NAME, _expr => {
|
1752
|
+
const expr = /** @type {ConditionalExpression} */ (_expr);
|
1753
|
+
|
1754
|
+
const condition = this.evaluateExpression(expr.test);
|
1755
|
+
const conditionValue = condition.asBool();
|
1756
|
+
let res;
|
1757
|
+
if (conditionValue === undefined) {
|
1758
|
+
const consequent = this.evaluateExpression(expr.consequent);
|
1759
|
+
const alternate = this.evaluateExpression(expr.alternate);
|
1760
|
+
res = new BasicEvaluatedExpression();
|
1761
|
+
if (consequent.isConditional()) {
|
1762
|
+
res.setOptions(
|
1763
|
+
/** @type {BasicEvaluatedExpression[]} */ (consequent.options)
|
1764
|
+
);
|
1793
1765
|
} else {
|
1794
|
-
res
|
1795
|
-
|
1766
|
+
res.setOptions([consequent]);
|
1767
|
+
}
|
1768
|
+
if (alternate.isConditional()) {
|
1769
|
+
res.addOptions(
|
1770
|
+
/** @type {BasicEvaluatedExpression[]} */ (alternate.options)
|
1796
1771
|
);
|
1797
|
-
|
1772
|
+
} else {
|
1773
|
+
res.addOptions([alternate]);
|
1798
1774
|
}
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
this.hooks.evaluate
|
1803
|
-
.for("ArrayExpression")
|
1804
|
-
.tap("JavascriptParser", _expr => {
|
1805
|
-
const expr = /** @type {ArrayExpression} */ (_expr);
|
1806
|
-
|
1807
|
-
const items = expr.elements.map(
|
1808
|
-
element =>
|
1809
|
-
element !== null &&
|
1810
|
-
element.type !== "SpreadElement" &&
|
1811
|
-
this.evaluateExpression(element)
|
1775
|
+
} else {
|
1776
|
+
res = this.evaluateExpression(
|
1777
|
+
conditionValue ? expr.consequent : expr.alternate
|
1812
1778
|
);
|
1813
|
-
if (
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
this.hooks.evaluate
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1779
|
+
if (condition.couldHaveSideEffects()) res.setSideEffects();
|
1780
|
+
}
|
1781
|
+
res.setRange(/** @type {Range} */ (expr.range));
|
1782
|
+
return res;
|
1783
|
+
});
|
1784
|
+
this.hooks.evaluate.for("ArrayExpression").tap(CLASS_NAME, _expr => {
|
1785
|
+
const expr = /** @type {ArrayExpression} */ (_expr);
|
1786
|
+
|
1787
|
+
const items = expr.elements.map(
|
1788
|
+
element =>
|
1789
|
+
element !== null &&
|
1790
|
+
element.type !== "SpreadElement" &&
|
1791
|
+
this.evaluateExpression(element)
|
1792
|
+
);
|
1793
|
+
if (!items.every(Boolean)) return;
|
1794
|
+
return new BasicEvaluatedExpression()
|
1795
|
+
.setItems(/** @type {BasicEvaluatedExpression[]} */ (items))
|
1796
|
+
.setRange(/** @type {Range} */ (expr.range));
|
1797
|
+
});
|
1798
|
+
this.hooks.evaluate.for("ChainExpression").tap(CLASS_NAME, _expr => {
|
1799
|
+
const expr = /** @type {ChainExpression} */ (_expr);
|
1800
|
+
/** @type {Expression[]} */
|
1801
|
+
const optionalExpressionsStack = [];
|
1802
|
+
/** @type {Expression|Super} */
|
1803
|
+
let next = expr.expression;
|
1804
|
+
|
1805
|
+
while (
|
1806
|
+
next.type === "MemberExpression" ||
|
1807
|
+
next.type === "CallExpression"
|
1808
|
+
) {
|
1809
|
+
if (next.type === "MemberExpression") {
|
1810
|
+
if (next.optional) {
|
1811
|
+
// SuperNode can not be optional
|
1812
|
+
optionalExpressionsStack.push(
|
1813
|
+
/** @type {Expression} */ (next.object)
|
1814
|
+
);
|
1815
|
+
}
|
1816
|
+
next = next.object;
|
1817
|
+
} else {
|
1818
|
+
if (next.optional) {
|
1819
|
+
// SuperNode can not be optional
|
1820
|
+
optionalExpressionsStack.push(
|
1821
|
+
/** @type {Expression} */ (next.callee)
|
1822
|
+
);
|
1847
1823
|
}
|
1824
|
+
next = next.callee;
|
1848
1825
|
}
|
1826
|
+
}
|
1849
1827
|
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1828
|
+
while (optionalExpressionsStack.length > 0) {
|
1829
|
+
const expression =
|
1830
|
+
/** @type {Expression} */
|
1831
|
+
(optionalExpressionsStack.pop());
|
1832
|
+
const evaluated = this.evaluateExpression(expression);
|
1855
1833
|
|
1856
|
-
|
1857
|
-
|
1858
|
-
}
|
1834
|
+
if (evaluated.asNullish()) {
|
1835
|
+
return evaluated.setRange(/** @type {Range} */ (_expr.range));
|
1859
1836
|
}
|
1860
|
-
|
1861
|
-
|
1837
|
+
}
|
1838
|
+
return this.evaluateExpression(expr.expression);
|
1839
|
+
});
|
1862
1840
|
}
|
1863
1841
|
|
1864
1842
|
/**
|