mirror of https://github.com/webpack/webpack.git
Merge branch 'main' into fix/esm-library-dynamic-import-new-url
This commit is contained in:
commit
90d15f96ee
|
@ -173,7 +173,8 @@ jobs:
|
|||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
# TODO: Remove version override when https://github.com/nodejs/node/issues/59480 is fixed
|
||||
node-version: ${{ matrix.node-version == '24.x' && '24.5.0' || matrix.node-version }}
|
||||
architecture: ${{ steps.calculate_architecture.outputs.result }}
|
||||
cache: "yarn"
|
||||
# Install old `jest` version and deps for legacy node versions
|
||||
|
|
|
@ -59,28 +59,28 @@ module.exports = (env = "development") => ({
|
|||
|
||||
```
|
||||
asset output.js 3.61 MiB [emitted] (name: main)
|
||||
chunk (runtime: main) output.js (main) 2.24 MiB (javascript) 1.29 KiB (runtime) [entry]
|
||||
chunk (runtime: main) output.js (main) 2.25 MiB (javascript) 1.29 KiB (runtime) [entry]
|
||||
> ./example.js main
|
||||
cached modules 2.24 MiB (javascript) 1.29 KiB (runtime) [cached] 1516 modules
|
||||
cached modules 2.25 MiB (javascript) 1.29 KiB (runtime) [cached] 1523 modules
|
||||
webpack X.X.X compiled successfully
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
asset output.js 548 KiB [emitted] [minimized] [big] (name: main) 1 related asset
|
||||
asset output.js 549 KiB [emitted] [minimized] [big] (name: main) 1 related asset
|
||||
chunk (runtime: main) output.js (main) 2.19 MiB (javascript) 1.29 KiB (runtime) [entry]
|
||||
> ./example.js main
|
||||
cached modules 2.19 MiB (javascript) 1.29 KiB (runtime) [cached] 893 modules
|
||||
cached modules 2.19 MiB (javascript) 1.29 KiB (runtime) [cached] 900 modules
|
||||
|
||||
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
|
||||
This can impact web performance.
|
||||
Assets:
|
||||
output.js (548 KiB)
|
||||
output.js (549 KiB)
|
||||
|
||||
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
|
||||
Entrypoints:
|
||||
main (548 KiB)
|
||||
main (549 KiB)
|
||||
output.js
|
||||
|
||||
WARNING in webpack performance recommendations:
|
||||
|
|
|
@ -539,7 +539,10 @@ const msg = "from virtual module with custom scheme";
|
|||
/******/ // "1" is the signal for "already loaded"
|
||||
/******/ if(!installedChunks[chunkId]) {
|
||||
/******/ if(true) { // all chunks have JS
|
||||
/******/ installChunk(require("./" + __webpack_require__.u(chunkId)));
|
||||
/******/ var installedChunk = require("./" + __webpack_require__.u(chunkId));
|
||||
/******/ if (!installedChunks[chunkId]) {
|
||||
/******/ installChunk(installedChunk);
|
||||
/******/ }
|
||||
/******/ } else installedChunks[chunkId] = 1;
|
||||
/******/ }
|
||||
/******/ };
|
||||
|
@ -572,13 +575,13 @@ const msg = "from virtual module with custom scheme";
|
|||
## Unoptimized
|
||||
|
||||
```
|
||||
asset output.js 16.3 KiB [emitted] (name: main)
|
||||
asset output.js 16.4 KiB [emitted] (name: main)
|
||||
asset 2.output.js 815 bytes [emitted]
|
||||
asset 1.output.js 814 bytes [emitted]
|
||||
chunk (runtime: main) output.js (main) 1.46 KiB (javascript) 4.13 KiB (runtime) [entry] [rendered]
|
||||
chunk (runtime: main) output.js (main) 1.46 KiB (javascript) 4.21 KiB (runtime) [entry] [rendered]
|
||||
> ./example.js main
|
||||
dependent modules 514 bytes [dependent] 8 modules
|
||||
runtime modules 4.13 KiB 7 modules
|
||||
runtime modules 4.21 KiB 7 modules
|
||||
./example.js 977 bytes [built] [code generated]
|
||||
[no exports]
|
||||
[used exports unknown]
|
||||
|
@ -601,7 +604,7 @@ webpack X.X.X compiled successfully
|
|||
## Production mode
|
||||
|
||||
```
|
||||
asset output.js 2.5 KiB [emitted] [minimized] (name: main)
|
||||
asset output.js 2.52 KiB [emitted] [minimized] (name: main)
|
||||
asset 263.output.js 121 bytes [emitted] [minimized]
|
||||
asset 722.output.js 121 bytes [emitted] [minimized]
|
||||
chunk (runtime: main) 263.output.js 20 bytes [rendered]
|
||||
|
@ -614,10 +617,10 @@ chunk (runtime: main) 722.output.js 20 bytes [rendered]
|
|||
./routes/b.js 20 bytes [built] [code generated]
|
||||
[exports: default]
|
||||
import() ./routes/b.js virtual:routes 2:9-32
|
||||
chunk (runtime: main) output.js (main) 1.46 KiB (javascript) 4.13 KiB (runtime) [entry] [rendered]
|
||||
chunk (runtime: main) output.js (main) 1.46 KiB (javascript) 4.21 KiB (runtime) [entry] [rendered]
|
||||
> ./example.js main
|
||||
dependent modules 514 bytes [dependent] 8 modules
|
||||
runtime modules 4.13 KiB 7 modules
|
||||
runtime modules 4.21 KiB 7 modules
|
||||
./example.js 977 bytes [built] [code generated]
|
||||
[no exports]
|
||||
[no exports used]
|
||||
|
|
|
@ -180,7 +180,7 @@ class ConstPlugin {
|
|||
? statement.alternate
|
||||
: statement.consequent;
|
||||
if (branchToRemove) {
|
||||
this.eliminateUnusedStatement(parser, branchToRemove);
|
||||
this.eliminateUnusedStatement(parser, branchToRemove, true);
|
||||
}
|
||||
return bool;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ class ConstPlugin {
|
|||
) {
|
||||
return;
|
||||
}
|
||||
this.eliminateUnusedStatement(parser, statement);
|
||||
this.eliminateUnusedStatement(parser, statement, false);
|
||||
return true;
|
||||
});
|
||||
parser.hooks.expressionConditionalOperator.tap(
|
||||
|
@ -509,9 +509,10 @@ class ConstPlugin {
|
|||
* Eliminate an unused statement.
|
||||
* @param {JavascriptParser} parser the parser
|
||||
* @param {Statement} statement the statement to remove
|
||||
* @param {boolean} alwaysInBlock whether to always generate curly brackets
|
||||
* @returns {void}
|
||||
*/
|
||||
eliminateUnusedStatement(parser, statement) {
|
||||
eliminateUnusedStatement(parser, statement, alwaysInBlock) {
|
||||
// Before removing the unused branch, the hoisted declarations
|
||||
// must be collected.
|
||||
//
|
||||
|
@ -545,8 +546,14 @@ class ConstPlugin {
|
|||
const declarations = parser.scope.isStrict
|
||||
? getHoistedDeclarations(statement, false)
|
||||
: getHoistedDeclarations(statement, true);
|
||||
const replacement =
|
||||
declarations.length > 0 ? `{ var ${declarations.join(", ")}; }` : "{}";
|
||||
|
||||
const inBlock = alwaysInBlock || statement.type === "BlockStatement";
|
||||
|
||||
let replacement = inBlock ? "{" : "";
|
||||
replacement +=
|
||||
declarations.length > 0 ? ` var ${declarations.join(", ")}; ` : "";
|
||||
replacement += inBlock ? "}" : "";
|
||||
|
||||
const dep = new ConstDependency(
|
||||
`// removed by dead control flow\n${replacement}`,
|
||||
/** @type {Range} */ (statement.range)
|
||||
|
|
|
@ -489,6 +489,13 @@ class DefinePlugin {
|
|||
if (nested && !hooked.has(nested)) {
|
||||
// only detect the same nested key once
|
||||
hooked.add(nested);
|
||||
parser.hooks.collectDestructuringAssignmentProperties.tap(
|
||||
PLUGIN_NAME,
|
||||
(expr) => {
|
||||
const nameInfo = parser.getNameForExpression(expr);
|
||||
if (nameInfo && nameInfo.name === nested) return true;
|
||||
}
|
||||
);
|
||||
parser.hooks.expression.for(nested).tap(
|
||||
{
|
||||
name: PLUGIN_NAME,
|
||||
|
@ -687,6 +694,13 @@ class DefinePlugin {
|
|||
PLUGIN_NAME,
|
||||
withValueDependency(key, evaluateToString("object"))
|
||||
);
|
||||
parser.hooks.collectDestructuringAssignmentProperties.tap(
|
||||
PLUGIN_NAME,
|
||||
(expr) => {
|
||||
const nameInfo = parser.getNameForExpression(expr);
|
||||
if (nameInfo && nameInfo.name === key) return true;
|
||||
}
|
||||
);
|
||||
parser.hooks.expression.for(key).tap(PLUGIN_NAME, (expr) => {
|
||||
addValueDependency(key);
|
||||
let strCode = stringifyObj(
|
||||
|
|
|
@ -62,9 +62,12 @@ class AwaitDependenciesInitFragment extends InitFragment {
|
|||
this.dependencies.size === 1 ||
|
||||
!runtimeTemplate.supportsDestructuring()
|
||||
) {
|
||||
templateInput.push(
|
||||
"var __webpack_async_dependencies_result__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);"
|
||||
);
|
||||
for (const [index, importVar] of importVars.entries()) {
|
||||
templateInput.push(
|
||||
`${importVar} = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[${index}];`
|
||||
`${importVar} = __webpack_async_dependencies_result__[${index}];`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
const CommentCompilationWarning = require("../CommentCompilationWarning");
|
||||
const HotModuleReplacementPlugin = require("../HotModuleReplacementPlugin");
|
||||
const WebpackError = require("../WebpackError");
|
||||
const { getImportAttributes } = require("../javascript/JavascriptParser");
|
||||
const {
|
||||
VariableInfo,
|
||||
getImportAttributes
|
||||
} = require("../javascript/JavascriptParser");
|
||||
const InnerGraph = require("../optimize/InnerGraph");
|
||||
const ConstDependency = require("./ConstDependency");
|
||||
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
|
||||
|
@ -211,6 +214,20 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
|||
InnerGraph.onUsage(parser.state, (e) => (dep.usedByExports = e));
|
||||
return true;
|
||||
});
|
||||
parser.hooks.collectDestructuringAssignmentProperties.tap(
|
||||
PLUGIN_NAME,
|
||||
(expr) => {
|
||||
const nameInfo = parser.getNameForExpression(expr);
|
||||
if (
|
||||
nameInfo &&
|
||||
nameInfo.rootInfo instanceof VariableInfo &&
|
||||
nameInfo.rootInfo.name &&
|
||||
parser.getTagData(nameInfo.rootInfo.name, harmonySpecifierTag)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
parser.hooks.expression
|
||||
.for(harmonySpecifierTag)
|
||||
.tap(PLUGIN_NAME, (expr) => {
|
||||
|
|
|
@ -96,6 +96,12 @@ class ImportMetaPlugin {
|
|||
PLUGIN_NAME,
|
||||
toConstantDependency(parser, JSON.stringify("object"))
|
||||
);
|
||||
parser.hooks.collectDestructuringAssignmentProperties.tap(
|
||||
PLUGIN_NAME,
|
||||
(expr) => {
|
||||
if (expr.type === "MetaProperty") return true;
|
||||
}
|
||||
);
|
||||
parser.hooks.expression
|
||||
.for("import.meta")
|
||||
.tap(PLUGIN_NAME, (metaProperty) => {
|
||||
|
|
|
@ -46,6 +46,12 @@ class ImportParserPlugin {
|
|||
*/
|
||||
const exportsFromEnumerable = (enumerable) =>
|
||||
Array.from(enumerable, (e) => [e]);
|
||||
parser.hooks.collectDestructuringAssignmentProperties.tap(
|
||||
PLUGIN_NAME,
|
||||
(expr) => {
|
||||
if (expr.type === "ImportExpression") return true;
|
||||
}
|
||||
);
|
||||
parser.hooks.importCall.tap(PLUGIN_NAME, (expr) => {
|
||||
const param = parser.evaluateExpression(expr.source);
|
||||
|
||||
|
|
|
@ -522,6 +522,10 @@ class JavascriptParser extends Parser {
|
|||
varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])),
|
||||
/** @type {HookMap<SyncBailHook<[Identifier], boolean | void>>} */
|
||||
pattern: new HookMap(() => new SyncBailHook(["pattern"])),
|
||||
/** @type {SyncBailHook<[Expression], boolean | void>} */
|
||||
collectDestructuringAssignmentProperties: new SyncBailHook([
|
||||
"expression"
|
||||
]),
|
||||
/** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
|
||||
canRename: new HookMap(() => new SyncBailHook(["initExpression"])),
|
||||
/** @type {HookMap<SyncBailHook<[Expression], boolean | void>>} */
|
||||
|
@ -2607,34 +2611,48 @@ class JavascriptParser extends Parser {
|
|||
* @param {AssignmentExpression} expression assignment expression
|
||||
*/
|
||||
preWalkAssignmentExpression(expression) {
|
||||
this.enterDestructuringAssignment(expression.left, expression.right);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Pattern} pattern pattern
|
||||
* @param {Expression} expression assignment expression
|
||||
* @returns {Expression | undefined} destructuring expression
|
||||
*/
|
||||
enterDestructuringAssignment(pattern, expression) {
|
||||
if (
|
||||
expression.left.type !== "ObjectPattern" ||
|
||||
pattern.type !== "ObjectPattern" ||
|
||||
!this.destructuringAssignmentProperties
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const keys = this._preWalkObjectPattern(expression.left);
|
||||
|
||||
const expr =
|
||||
expression.type === "AwaitExpression" ? expression.argument : expression;
|
||||
|
||||
const destructuring =
|
||||
expr.type === "AssignmentExpression"
|
||||
? this.enterDestructuringAssignment(expr.left, expr.right)
|
||||
: this.hooks.collectDestructuringAssignmentProperties.call(expr)
|
||||
? expr
|
||||
: undefined;
|
||||
|
||||
if (destructuring) {
|
||||
const keys = this._preWalkObjectPattern(pattern);
|
||||
if (!keys) return;
|
||||
|
||||
// check multiple assignments
|
||||
if (this.destructuringAssignmentProperties.has(expression)) {
|
||||
if (this.destructuringAssignmentProperties.has(destructuring)) {
|
||||
const set =
|
||||
/** @type {Set<DestructuringAssignmentProperty>} */
|
||||
(this.destructuringAssignmentProperties.get(expression));
|
||||
this.destructuringAssignmentProperties.delete(expression);
|
||||
for (const id of set) keys.add(id);
|
||||
(this.destructuringAssignmentProperties.get(destructuring));
|
||||
for (const id of keys) set.add(id);
|
||||
} else {
|
||||
this.destructuringAssignmentProperties.set(destructuring, keys);
|
||||
}
|
||||
}
|
||||
|
||||
this.destructuringAssignmentProperties.set(
|
||||
expression.right.type === "AwaitExpression"
|
||||
? expression.right.argument
|
||||
: expression.right,
|
||||
keys
|
||||
);
|
||||
|
||||
if (expression.right.type === "AssignmentExpression") {
|
||||
this.preWalkAssignmentExpression(expression.right);
|
||||
}
|
||||
return destructuring;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2995,25 +3013,8 @@ class JavascriptParser extends Parser {
|
|||
* @param {VariableDeclarator} declarator variable declarator
|
||||
*/
|
||||
preWalkVariableDeclarator(declarator) {
|
||||
if (
|
||||
!declarator.init ||
|
||||
declarator.id.type !== "ObjectPattern" ||
|
||||
!this.destructuringAssignmentProperties
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const keys = this._preWalkObjectPattern(declarator.id);
|
||||
|
||||
if (!keys) return;
|
||||
this.destructuringAssignmentProperties.set(
|
||||
declarator.init.type === "AwaitExpression"
|
||||
? declarator.init.argument
|
||||
: declarator.init,
|
||||
keys
|
||||
);
|
||||
|
||||
if (declarator.init.type === "AssignmentExpression") {
|
||||
this.preWalkAssignmentExpression(declarator.init);
|
||||
if (declarator.init) {
|
||||
this.enterDestructuringAssignment(declarator.id, declarator.init);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5179,7 +5180,7 @@ class JavascriptParser extends Parser {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {MemberExpression} expression an expression
|
||||
* @param {Expression} expression an expression
|
||||
* @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]} | undefined} name info
|
||||
*/
|
||||
getNameForExpression(expression) {
|
||||
|
|
|
@ -48,10 +48,16 @@ it("should add warning on direct import.meta usage", () => {
|
|||
expect(Object.keys(import.meta)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should support destructuring assignment", () => {
|
||||
it("should support destructuring assignment", async () => {
|
||||
let version, url2, c;
|
||||
({ webpack: version } = { url: url2 } = { c } = import.meta);
|
||||
expect(version).toBeTypeOf("number");
|
||||
expect(url2).toBe(url);
|
||||
expect(c).toBe(undefined);
|
||||
|
||||
let version2, url3, d;
|
||||
({ webpack: version2 } = await ({ url: url3 } = ({ d } = await import.meta)));
|
||||
expect(version2).toBeTypeOf("number");
|
||||
expect(url3).toBe(url);
|
||||
expect(d).toBe(undefined);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
await 1;
|
||||
export const a = "a"
|
|
@ -0,0 +1,2 @@
|
|||
await 1;
|
||||
export const b = "b"
|
|
@ -0,0 +1,4 @@
|
|||
import {a} from "./a";
|
||||
import {b} from "./b";
|
||||
|
||||
export const c = a + b
|
|
@ -0,0 +1,3 @@
|
|||
import {c} from "./c";
|
||||
|
||||
export const d = c
|
|
@ -0,0 +1,5 @@
|
|||
it("should work", () => {
|
||||
return import("./d").then(d => {
|
||||
expect(d.d).toBe("ab");
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
output: {
|
||||
environment: {
|
||||
destructuring: false
|
||||
}
|
||||
}
|
||||
};
|
|
@ -402,7 +402,7 @@ class TestRunner {
|
|||
);
|
||||
const esmCache = new Map();
|
||||
const { category, name, round } = this.testMeta;
|
||||
const esmIdentifier = `${category.name}-${name}-${round || 0}`;
|
||||
const esmIdentifier = `${category}-${name}-${round || 0}`;
|
||||
let esmContext = null;
|
||||
return (moduleInfo, context) => {
|
||||
const asModule = require("../helpers/asModule");
|
||||
|
|
|
@ -663,12 +663,12 @@ declare abstract class BasicEvaluatedExpression {
|
|||
| MethodDefinition
|
||||
| PropertyDefinition
|
||||
| VariableDeclarator
|
||||
| SwitchCase
|
||||
| CatchClause
|
||||
| ObjectPattern
|
||||
| ArrayPattern
|
||||
| RestElement
|
||||
| AssignmentPattern
|
||||
| SwitchCase
|
||||
| CatchClause
|
||||
| Property
|
||||
| AssignmentProperty
|
||||
| ClassBody
|
||||
|
@ -894,12 +894,12 @@ declare abstract class BasicEvaluatedExpression {
|
|||
| MethodDefinition
|
||||
| PropertyDefinition
|
||||
| VariableDeclarator
|
||||
| SwitchCase
|
||||
| CatchClause
|
||||
| ObjectPattern
|
||||
| ArrayPattern
|
||||
| RestElement
|
||||
| AssignmentPattern
|
||||
| SwitchCase
|
||||
| CatchClause
|
||||
| Property
|
||||
| AssignmentProperty
|
||||
| ClassBody
|
||||
|
@ -6855,6 +6855,10 @@ declare class JavascriptParser extends ParserClass {
|
|||
varDeclarationUsing: HookMap<SyncBailHook<[Identifier], boolean | void>>;
|
||||
varDeclarationVar: HookMap<SyncBailHook<[Identifier], boolean | void>>;
|
||||
pattern: HookMap<SyncBailHook<[Identifier], boolean | void>>;
|
||||
collectDestructuringAssignmentProperties: SyncBailHook<
|
||||
[Expression],
|
||||
boolean | void
|
||||
>;
|
||||
canRename: HookMap<SyncBailHook<[Expression], boolean | void>>;
|
||||
rename: HookMap<SyncBailHook<[Expression], boolean | void>>;
|
||||
assign: HookMap<SyncBailHook<[AssignmentExpression], boolean | void>>;
|
||||
|
@ -7329,6 +7333,38 @@ declare class JavascriptParser extends ParserClass {
|
|||
): void;
|
||||
blockPreWalkExpressionStatement(statement: ExpressionStatement): void;
|
||||
preWalkAssignmentExpression(expression: AssignmentExpression): void;
|
||||
enterDestructuringAssignment(
|
||||
pattern: Pattern,
|
||||
expression: Expression
|
||||
):
|
||||
| undefined
|
||||
| ImportExpressionImport
|
||||
| UnaryExpression
|
||||
| ArrayExpression
|
||||
| ArrowFunctionExpression
|
||||
| AssignmentExpression
|
||||
| AwaitExpression
|
||||
| BinaryExpression
|
||||
| SimpleCallExpression
|
||||
| NewExpression
|
||||
| ChainExpression
|
||||
| ClassExpression
|
||||
| ConditionalExpression
|
||||
| FunctionExpression
|
||||
| Identifier
|
||||
| SimpleLiteral
|
||||
| RegExpLiteral
|
||||
| BigIntLiteral
|
||||
| LogicalExpression
|
||||
| MemberExpression
|
||||
| MetaProperty
|
||||
| ObjectExpression
|
||||
| SequenceExpression
|
||||
| TaggedTemplateExpression
|
||||
| TemplateLiteral
|
||||
| ThisExpression
|
||||
| UpdateExpression
|
||||
| YieldExpression;
|
||||
modulePreWalkImportDeclaration(
|
||||
statement: ImportDeclarationJavascriptParser
|
||||
): void;
|
||||
|
@ -7874,7 +7910,7 @@ declare class JavascriptParser extends ParserClass {
|
|||
allowedTypes: number
|
||||
): undefined | CallExpressionInfo | ExpressionExpressionInfo;
|
||||
getNameForExpression(
|
||||
expression: MemberExpression
|
||||
expression: Expression
|
||||
):
|
||||
| undefined
|
||||
| {
|
||||
|
|
Loading…
Reference in New Issue