Skip to content

Commit 9eb9642

Browse files
authored
perf: extend importPhasesPlugin only when enable deferImport (#19689)
1 parent 0a98446 commit 9eb9642

File tree

9 files changed

+37
-64
lines changed

9 files changed

+37
-64
lines changed

lib/WebpackOptionsApply.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,13 @@ class WebpackOptionsApply extends OptionsApply {
438438
new HttpUriPlugin(httpOptions).apply(compiler);
439439
}
440440

441+
if (options.experiments.deferImport) {
442+
const JavascriptParser = require("./javascript/JavascriptParser");
443+
const importPhases = require("acorn-import-phases");
444+
445+
JavascriptParser.extend(importPhases({ source: false }));
446+
}
447+
441448
new EntryOptionPlugin().apply(compiler);
442449
compiler.hooks.entryOption.call(
443450
/** @type {string} */

lib/dependencies/HarmonyExportDependencyParserPlugin.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
7777
clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
7878
clearDep.loc.index = -1;
7979
parser.state.module.addPresentationalDependency(clearDep);
80-
const { defer } = getImportMode(
81-
parser,
82-
statement,
83-
this.deferImport,
84-
true
85-
);
80+
const { defer } = getImportMode(parser, statement);
8681
if (defer) {
8782
const error = new WebpackError(
8883
"Deferred re-export (`export defer * as namespace from '...'`) is not a part of the Import Defer proposal.\nUse the following code instead:\n import defer * as namespace from '...';\n export { namespace };"
@@ -207,12 +202,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
207202
parser.state.harmonyStarExports || new HarmonyStarExportsList();
208203
}
209204
const attributes = getImportAttributes(statement);
210-
const { defer } = getImportMode(
211-
parser,
212-
statement,
213-
this.deferImport,
214-
false
215-
);
205+
const { defer } = getImportMode(parser, statement);
216206
const dep = new HarmonyExportImportedSpecifierDependency(
217207
/** @type {string} */
218208
(source),

lib/dependencies/HarmonyImportDependencyParserPlugin.js

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
const CommentCompilationWarning = require("../CommentCompilationWarning");
99
const HotModuleReplacementPlugin = require("../HotModuleReplacementPlugin");
10-
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
1110
const WebpackError = require("../WebpackError");
1211
const { getImportAttributes } = require("../javascript/JavascriptParser");
1312
const InnerGraph = require("../optimize/InnerGraph");
@@ -125,12 +124,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
125124
parser.state.module.addPresentationalDependency(clearDep);
126125
parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]);
127126
const attributes = getImportAttributes(statement);
128-
const { defer } = getImportMode(
129-
parser,
130-
statement,
131-
this.deferImport,
132-
true
133-
);
127+
const { defer } = getImportMode(parser, statement);
134128
if (
135129
defer &&
136130
(statement.specifiers.length !== 1 ||
@@ -156,12 +150,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
156150
PLUGIN_NAME,
157151
(statement, source, id, name) => {
158152
const ids = id === null ? [] : [id];
159-
const { defer } = getImportMode(
160-
parser,
161-
statement,
162-
this.deferImport,
163-
false
164-
);
153+
const { defer } = getImportMode(parser, statement);
165154
parser.tagVariable(name, harmonySpecifierTag, {
166155
name,
167156
source,
@@ -398,23 +387,10 @@ module.exports = class HarmonyImportDependencyParserPlugin {
398387
/**
399388
* @param {JavascriptParser} parser parser
400389
* @param {ExportNamedDeclaration | ExportAllDeclaration | ImportDeclaration} node node
401-
* @param {boolean | undefined} deferImportEnabled defer import enabled
402-
* @param {boolean} reportSyntaxError report syntax error
403390
* @returns {{defer: boolean}} import attributes
404391
*/
405-
function getImportMode(parser, node, deferImportEnabled, reportSyntaxError) {
406-
const result = { defer: false };
407-
if ("phase" in node && node.phase === "defer") {
408-
if (deferImportEnabled) {
409-
result.defer = true;
410-
} else if (reportSyntaxError) {
411-
const error = new WebpackError(
412-
"Deferred import syntax (`import defer * as namespace from '...'`) cannot be used unless experimental.deferImport is true."
413-
);
414-
error.loc = node.loc || undefined;
415-
parser.state.current.addError(error);
416-
}
417-
}
392+
function getImportMode(parser, node) {
393+
const result = { defer: "phase" in node && node.phase === "defer" };
418394
if (!node.range) {
419395
return result;
420396
}
@@ -437,7 +413,7 @@ function getImportMode(parser, node, deferImportEnabled, reportSyntaxError) {
437413
result.defer = options.webpackDefer;
438414
} else if (node.loc) {
439415
parser.state.module.addWarning(
440-
new UnsupportedFeatureWarning(
416+
new CommentCompilationWarning(
441417
"webpackDefer magic comment expected a boolean value.",
442418
node.loc
443419
)

lib/javascript/JavascriptParser.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
const vm = require("vm");
99
const { Parser: AcornParser, tokTypes } = require("acorn");
10-
const acornImportPhases = require("acorn-import-phases");
1110
const { HookMap, SyncBailHook } = require("tapable");
1211
const Parser = require("../Parser");
1312
const StackedMap = require("../util/StackedMap");
@@ -182,10 +181,7 @@ const importAssertions = Parser =>
182181
};
183182

184183
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
185-
const parser = AcornParser.extend(
186-
importAssertions,
187-
acornImportPhases({ source: false })
188-
);
184+
let parser = AcornParser.extend(importAssertions);
189185

190186
/** @typedef {Record<string, string> & { _isLegacyAssert?: boolean }} ImportAttributes */
191187

@@ -5135,6 +5131,15 @@ class JavascriptParser extends Parser {
51355131

51365132
return /** @type {Program} */ (ast);
51375133
}
5134+
5135+
/**
5136+
* @param {((BaseParser: typeof AcornParser) => typeof AcornParser)[]} plugins parser plugin
5137+
* @returns {typeof JavascriptParser} parser
5138+
*/
5139+
static extend(...plugins) {
5140+
parser = parser.extend(...plugins);
5141+
return JavascriptParser;
5142+
}
51385143
}
51395144

51405145
module.exports = JavascriptParser;

test/configCases/defer-import/syntax-error-if-experiment-not-enabled/errors.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/configCases/defer-import/syntax-error-if-experiment-not-enabled/index.js

Lines changed: 0 additions & 2 deletions
This file was deleted.

test/configCases/defer-import/syntax-error-if-experiment-not-enabled/mod.js

Lines changed: 0 additions & 2 deletions
This file was deleted.

test/configCases/defer-import/syntax-error-if-experiment-not-enabled/webpack.config.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

types.d.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Run `yarn fix:special` to update
55
*/
66

7+
import { Parser as ParserImport } from "acorn";
78
import { Buffer } from "buffer";
89
import { Scope } from "eslint-scope";
910
import {
@@ -6431,7 +6432,7 @@ declare class JavascriptModulesPlugin {
64316432
): TemplatePath;
64326433
static chunkHasJs: (chunk: Chunk, chunkGraph: ChunkGraph) => boolean;
64336434
}
6434-
declare class JavascriptParser extends Parser {
6435+
declare class JavascriptParser extends ParserClass {
64356436
constructor(sourceType?: "module" | "auto" | "script");
64366437
hooks: Readonly<{
64376438
evaluateTypeof: HookMap<
@@ -7759,6 +7760,9 @@ declare class JavascriptParser extends Parser {
77597760
rootInfo: ExportedVariableInfo;
77607761
getMembers: () => string[];
77617762
};
7763+
static extend(
7764+
...plugins: ((BaseParser: typeof ParserImport) => typeof ParserImport)[]
7765+
): typeof JavascriptParser;
77627766
static ALLOWED_MEMBER_TYPES_ALL: 3;
77637767
static ALLOWED_MEMBER_TYPES_CALL_EXPRESSION: 1;
77647768
static ALLOWED_MEMBER_TYPES_EXPRESSION: 2;
@@ -10555,7 +10559,7 @@ declare class NormalModule extends Module {
1055510559
userRequest: string;
1055610560
rawRequest: string;
1055710561
binary: boolean;
10558-
parser?: Parser;
10562+
parser?: ParserClass;
1055910563
parserOptions?: ParserOptions;
1056010564
generator?: Generator;
1056110565
generatorOptions?: GeneratorOptions;
@@ -10686,7 +10690,7 @@ declare interface NormalModuleCreateData {
1068610690
/**
1068710691
* the parser used
1068810692
*/
10689-
parser: Parser;
10693+
parser: ParserClass;
1069010694

1069110695
/**
1069210696
* the options of the parser used
@@ -10734,7 +10738,7 @@ declare abstract class NormalModuleFactory extends ModuleFactory {
1073410738
ResolveData
1073510739
]
1073610740
>;
10737-
createParser: HookMap<SyncBailHook<[ParserOptions], void | Parser>>;
10741+
createParser: HookMap<SyncBailHook<[ParserOptions], void | ParserClass>>;
1073810742
parser: HookMap<SyncBailHook<[any, ParserOptions], void>>;
1073910743
createGenerator: HookMap<
1074010744
SyncBailHook<[GeneratorOptions], void | Generator>
@@ -10754,7 +10758,7 @@ declare abstract class NormalModuleFactory extends ModuleFactory {
1075410758
ruleSet: RuleSet;
1075510759
context: string;
1075610760
fs: InputFileSystem;
10757-
parserCache: Map<string, WeakMap<ParserOptions, Parser>>;
10761+
parserCache: Map<string, WeakMap<ParserOptions, ParserClass>>;
1075810762
generatorCache: Map<string, WeakMap<GeneratorOptions, Generator>>;
1075910763
cleanupForCache(): void;
1076010764
resolveResource(
@@ -10777,8 +10781,8 @@ declare abstract class NormalModuleFactory extends ModuleFactory {
1077710781
resolveContext: ResolveContext,
1077810782
callback: CallbackNormalModuleFactory<LoaderItem[]>
1077910783
): void;
10780-
getParser(type: string, parserOptions?: ParserOptions): Parser;
10781-
createParser(type: string, parserOptions?: ParserOptions): Parser;
10784+
getParser(type: string, parserOptions?: ParserOptions): ParserClass;
10785+
createParser(type: string, parserOptions?: ParserOptions): ParserClass;
1078210786
getGenerator(type: string, generatorOptions?: GeneratorOptions): Generator;
1078310787
createGenerator(type: string, generatorOptions?: GeneratorOptions): Generator;
1078410788
getResolver(
@@ -12244,7 +12248,7 @@ declare interface ParsedIdentifier {
1224412248
*/
1224512249
internal: boolean;
1224612250
}
12247-
declare class Parser {
12251+
declare class ParserClass {
1224812252
constructor();
1224912253
parse(
1225012254
source: string | Buffer | PreparsedAst,
@@ -18031,7 +18035,7 @@ declare namespace exports {
1803118035
NormalModule,
1803218036
NormalModuleReplacementPlugin,
1803318037
MultiCompiler,
18034-
Parser,
18038+
ParserClass as Parser,
1803518039
PlatformPlugin,
1803618040
PrefetchPlugin,
1803718041
ProgressPlugin,

0 commit comments

Comments
 (0)