From 613a5ada7e676573758e4714d2e345df81c1270d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 15:18:24 +0300 Subject: [PATCH 1/9] chore(deps-dev): bump @babel/core in the dependencies group (#19807) Bumps the dependencies group with 1 update: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core). Updates `@babel/core` from 7.28.0 to 7.28.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.3/packages/babel-core) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 7.28.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/yarn.lock b/yarn.lock index 28bff95d441..e393367d746 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,33 +35,33 @@ integrity sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw== "@babel/core@^7.23.9", "@babel/core@^7.27.1", "@babel/core@^7.27.4": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.0.tgz#55dad808d5bf3445a108eefc88ea3fdf034749a4" - integrity sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ== + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.3.tgz#aceddde69c5d1def69b839d09efa3e3ff59c97cb" + integrity sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.28.0" + "@babel/generator" "^7.28.3" "@babel/helper-compilation-targets" "^7.27.2" - "@babel/helper-module-transforms" "^7.27.3" - "@babel/helpers" "^7.27.6" - "@babel/parser" "^7.28.0" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.3" + "@babel/parser" "^7.28.3" "@babel/template" "^7.27.2" - "@babel/traverse" "^7.28.0" - "@babel/types" "^7.28.0" + "@babel/traverse" "^7.28.3" + "@babel/types" "^7.28.2" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.27.5", "@babel/generator@^7.28.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" - integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== +"@babel/generator@^7.27.5", "@babel/generator@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.3.tgz#9626c1741c650cbac39121694a0f2d7451b8ef3e" + integrity sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw== dependencies: - "@babel/parser" "^7.28.0" - "@babel/types" "^7.28.0" + "@babel/parser" "^7.28.3" + "@babel/types" "^7.28.2" "@jridgewell/gen-mapping" "^0.3.12" "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" @@ -97,14 +97,14 @@ "@babel/traverse" "^7.27.1" "@babel/types" "^7.27.1" -"@babel/helper-module-transforms@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz#db0bbcfba5802f9ef7870705a7ef8788508ede02" - integrity sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg== +"@babel/helper-module-transforms@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" + integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== dependencies: "@babel/helper-module-imports" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" - "@babel/traverse" "^7.27.3" + "@babel/traverse" "^7.28.3" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": version "7.27.1" @@ -126,20 +126,20 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== -"@babel/helpers@^7.27.6": - version "7.27.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.6.tgz#6456fed15b2cb669d2d1fabe84b66b34991d812c" - integrity sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug== +"@babel/helpers@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.3.tgz#b83156c0a2232c133d1b535dd5d3452119c7e441" + integrity sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw== dependencies: "@babel/template" "^7.27.2" - "@babel/types" "^7.27.6" + "@babel/types" "^7.28.2" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.2", "@babel/parser@^7.28.0", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e" - integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.27.2", "@babel/parser@^7.28.3", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.3.tgz#d2d25b814621bca5fe9d172bc93792547e7a2a71" + integrity sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA== dependencies: - "@babel/types" "^7.28.0" + "@babel/types" "^7.28.2" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -314,23 +314,23 @@ "@babel/parser" "^7.27.2" "@babel/types" "^7.27.1" -"@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b" - integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg== +"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.3.tgz#6911a10795d2cce43ec6a28cffc440cca2593434" + integrity sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ== dependencies: "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.28.0" + "@babel/generator" "^7.28.3" "@babel/helper-globals" "^7.28.0" - "@babel/parser" "^7.28.0" + "@babel/parser" "^7.28.3" "@babel/template" "^7.27.2" - "@babel/types" "^7.28.0" + "@babel/types" "^7.28.2" debug "^4.3.1" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.6.1", "@babel/types@^7.9.6": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.0.tgz#2fd0159a6dc7353933920c43136335a9b264d950" - integrity sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.6.1", "@babel/types@^7.9.6": + version "7.28.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.2.tgz#da9db0856a9a88e0a13b019881d7513588cf712b" + integrity sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ== dependencies: "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" From c50930b3be80285b1a53b64a8cfb4c58aa17a409 Mon Sep 17 00:00:00 2001 From: Xiao <784487301@qq.com> Date: Sun, 17 Aug 2025 23:04:46 +0800 Subject: [PATCH 2/9] refactor(test): correct the value retrieval --- test/runner/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runner/index.js b/test/runner/index.js index b9f4e3bc610..0a8ef5c8404 100644 --- a/test/runner/index.js +++ b/test/runner/index.js @@ -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"); From c92deaf02c4d0507b11c3e34d766f1d06d584055 Mon Sep 17 00:00:00 2001 From: Ryuya Date: Sun, 17 Aug 2025 08:04:57 -0700 Subject: [PATCH 3/9] ci: pin Node.js 24.x to 24.5.0 in CI workflow (#19813) --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 455440cb7f0..ff1edb3598a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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 From 8db97f863fb5cf55dfcf0634d0f127b27bcf43a4 Mon Sep 17 00:00:00 2001 From: Xiao <784487301@qq.com> Date: Sun, 17 Aug 2025 23:05:52 +0800 Subject: [PATCH 4/9] fix: resolve execution order issue from extra await in async modules --- lib/async-modules/AwaitDependenciesInitFragment.js | 5 ++++- test/configCases/async-module/issue-19803/a.js | 2 ++ test/configCases/async-module/issue-19803/b.js | 2 ++ test/configCases/async-module/issue-19803/c.js | 4 ++++ test/configCases/async-module/issue-19803/d.js | 3 +++ test/configCases/async-module/issue-19803/index.js | 5 +++++ .../async-module/issue-19803/webpack.config.js | 10 ++++++++++ 7 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 test/configCases/async-module/issue-19803/a.js create mode 100644 test/configCases/async-module/issue-19803/b.js create mode 100644 test/configCases/async-module/issue-19803/c.js create mode 100644 test/configCases/async-module/issue-19803/d.js create mode 100644 test/configCases/async-module/issue-19803/index.js create mode 100644 test/configCases/async-module/issue-19803/webpack.config.js diff --git a/lib/async-modules/AwaitDependenciesInitFragment.js b/lib/async-modules/AwaitDependenciesInitFragment.js index 0928d59271e..a0a25a8e832 100644 --- a/lib/async-modules/AwaitDependenciesInitFragment.js +++ b/lib/async-modules/AwaitDependenciesInitFragment.js @@ -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 { diff --git a/test/configCases/async-module/issue-19803/a.js b/test/configCases/async-module/issue-19803/a.js new file mode 100644 index 00000000000..9cfe94a72a9 --- /dev/null +++ b/test/configCases/async-module/issue-19803/a.js @@ -0,0 +1,2 @@ +await 1; +export const a = "a" \ No newline at end of file diff --git a/test/configCases/async-module/issue-19803/b.js b/test/configCases/async-module/issue-19803/b.js new file mode 100644 index 00000000000..100314f82ec --- /dev/null +++ b/test/configCases/async-module/issue-19803/b.js @@ -0,0 +1,2 @@ +await 1; +export const b = "b" \ No newline at end of file diff --git a/test/configCases/async-module/issue-19803/c.js b/test/configCases/async-module/issue-19803/c.js new file mode 100644 index 00000000000..db512b57507 --- /dev/null +++ b/test/configCases/async-module/issue-19803/c.js @@ -0,0 +1,4 @@ +import {a} from "./a"; +import {b} from "./b"; + +export const c = a + b \ No newline at end of file diff --git a/test/configCases/async-module/issue-19803/d.js b/test/configCases/async-module/issue-19803/d.js new file mode 100644 index 00000000000..860f9255cb6 --- /dev/null +++ b/test/configCases/async-module/issue-19803/d.js @@ -0,0 +1,3 @@ +import {c} from "./c"; + +export const d = c \ No newline at end of file diff --git a/test/configCases/async-module/issue-19803/index.js b/test/configCases/async-module/issue-19803/index.js new file mode 100644 index 00000000000..c921c625432 --- /dev/null +++ b/test/configCases/async-module/issue-19803/index.js @@ -0,0 +1,5 @@ +it("should work", () => { + return import("./d").then(d => { + expect(d.d).toBe("ab"); + }); +}); \ No newline at end of file diff --git a/test/configCases/async-module/issue-19803/webpack.config.js b/test/configCases/async-module/issue-19803/webpack.config.js new file mode 100644 index 00000000000..ae2274e3b22 --- /dev/null +++ b/test/configCases/async-module/issue-19803/webpack.config.js @@ -0,0 +1,10 @@ +"use strict"; + +/** @type {import("../../../../").Configuration} */ +module.exports = { + output: { + environment: { + destructuring: false + } + } +}; From 90ae8af3d19b964728a9e7f5f9350ead71d3ad61 Mon Sep 17 00:00:00 2001 From: hai-x <98948357+hai-x@users.noreply.github.com> Date: Sun, 17 Aug 2025 23:07:04 +0800 Subject: [PATCH 5/9] fix: avoid empty block for unused statement --- lib/ConstPlugin.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/ConstPlugin.js b/lib/ConstPlugin.js index 82ac18cac93..5efb75a45e6 100644 --- a/lib/ConstPlugin.js +++ b/lib/ConstPlugin.js @@ -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) From dc79e95022b8b726ac0a7c474be1dca0fef8fafe Mon Sep 17 00:00:00 2001 From: Gengkun Date: Sun, 17 Aug 2025 23:10:08 +0800 Subject: [PATCH 6/9] fix: collect only specific expressions for destructuring assignment --- lib/DefinePlugin.js | 14 ++++ .../HarmonyImportDependencyParserPlugin.js | 19 ++++- lib/dependencies/ImportMetaPlugin.js | 6 ++ lib/dependencies/ImportParserPlugin.js | 6 ++ lib/javascript/JavascriptParser.js | 81 ++++++++++--------- test/cases/esm/import-meta/index.js | 8 +- types.d.ts | 46 +++++++++-- 7 files changed, 133 insertions(+), 47 deletions(-) diff --git a/lib/DefinePlugin.js b/lib/DefinePlugin.js index e3d75973f82..b3270f75d67 100644 --- a/lib/DefinePlugin.js +++ b/lib/DefinePlugin.js @@ -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( diff --git a/lib/dependencies/HarmonyImportDependencyParserPlugin.js b/lib/dependencies/HarmonyImportDependencyParserPlugin.js index a54a4542c07..7eaba5ed70e 100644 --- a/lib/dependencies/HarmonyImportDependencyParserPlugin.js +++ b/lib/dependencies/HarmonyImportDependencyParserPlugin.js @@ -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) => { diff --git a/lib/dependencies/ImportMetaPlugin.js b/lib/dependencies/ImportMetaPlugin.js index 17817f7de21..e904a526ce3 100644 --- a/lib/dependencies/ImportMetaPlugin.js +++ b/lib/dependencies/ImportMetaPlugin.js @@ -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) => { diff --git a/lib/dependencies/ImportParserPlugin.js b/lib/dependencies/ImportParserPlugin.js index 8ad5da34b24..7b9904a4ef5 100644 --- a/lib/dependencies/ImportParserPlugin.js +++ b/lib/dependencies/ImportParserPlugin.js @@ -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); diff --git a/lib/javascript/JavascriptParser.js b/lib/javascript/JavascriptParser.js index f6741b03bd9..995a45bee0f 100644 --- a/lib/javascript/JavascriptParser.js +++ b/lib/javascript/JavascriptParser.js @@ -522,6 +522,10 @@ class JavascriptParser extends Parser { varDeclarationVar: new HookMap(() => new SyncBailHook(["declaration"])), /** @type {HookMap>} */ pattern: new HookMap(() => new SyncBailHook(["pattern"])), + /** @type {SyncBailHook<[Expression], boolean | void>} */ + collectDestructuringAssignmentProperties: new SyncBailHook([ + "expression" + ]), /** @type {HookMap>} */ canRename: new HookMap(() => new SyncBailHook(["initExpression"])), /** @type {HookMap>} */ @@ -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); - if (!keys) return; - - // check multiple assignments - if (this.destructuringAssignmentProperties.has(expression)) { - const set = - /** @type {Set} */ - (this.destructuringAssignmentProperties.get(expression)); - this.destructuringAssignmentProperties.delete(expression); - for (const id of set) keys.add(id); - } - this.destructuringAssignmentProperties.set( - expression.right.type === "AwaitExpression" - ? expression.right.argument - : expression.right, - keys - ); + 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; - if (expression.right.type === "AssignmentExpression") { - this.preWalkAssignmentExpression(expression.right); + // check multiple assignments + if (this.destructuringAssignmentProperties.has(destructuring)) { + const set = + /** @type {Set} */ + (this.destructuringAssignmentProperties.get(destructuring)); + for (const id of keys) set.add(id); + } else { + this.destructuringAssignmentProperties.set(destructuring, keys); + } } + + 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) { diff --git a/test/cases/esm/import-meta/index.js b/test/cases/esm/import-meta/index.js index 97fea14af75..0cbd61d00cc 100644 --- a/test/cases/esm/import-meta/index.js +++ b/test/cases/esm/import-meta/index.js @@ -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); }); diff --git a/types.d.ts b/types.d.ts index b92f4495170..a13716678ae 100644 --- a/types.d.ts +++ b/types.d.ts @@ -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>; varDeclarationVar: HookMap>; pattern: HookMap>; + collectDestructuringAssignmentProperties: SyncBailHook< + [Expression], + boolean | void + >; canRename: HookMap>; rename: HookMap>; assign: HookMap>; @@ -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 | { From 935cbd8552d89b9bcafea66ad08db034c1897ab1 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Sun, 17 Aug 2025 18:11:00 +0300 Subject: [PATCH 7/9] docs: update examples (#19812) --- examples/persistent-caching/README.md | 12 ++++++------ examples/virtual-modules/README.md | 17 ++++++++++------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/persistent-caching/README.md b/examples/persistent-caching/README.md index 4c471076a24..9fcfa804204 100644 --- a/examples/persistent-caching/README.md +++ b/examples/persistent-caching/README.md @@ -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: diff --git a/examples/virtual-modules/README.md b/examples/virtual-modules/README.md index 9413ee0b4b4..9afd3f6b782 100644 --- a/examples/virtual-modules/README.md +++ b/examples/virtual-modules/README.md @@ -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] From 8d7efb8b0421a3a132d3aa71c265e2862771c3b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:28:37 +0300 Subject: [PATCH 8/9] chore(deps-dev): bump the dependencies group with 2 updates (#19816) Bumps the dependencies group with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tinybench](https://github.com/tinylibs/tinybench). Updates `@types/node` from 24.2.1 to 24.3.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `tinybench` from 4.1.0 to 5.0.0 - [Release notes](https://github.com/tinylibs/tinybench/releases) - [Commits](https://github.com/tinylibs/tinybench/compare/v4.1.0...v5.0.0) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 24.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: tinybench dependency-version: 5.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 414d0f2feb2..2c76aea16ef 100644 --- a/package.json +++ b/package.json @@ -180,7 +180,7 @@ "style-loader": "^4.0.0", "terser": "^5.43.1", "three": "^0.179.1", - "tinybench": "^4.0.1", + "tinybench": "^5.0.0", "toml": "^3.0.0", "tooling": "webpack/tooling#v1.24.3", "ts-loader": "^9.5.1", diff --git a/yarn.lock b/yarn.lock index e393367d746..0981180b7f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1466,9 +1466,9 @@ integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== "@types/node@*", "@types/node@^24.1.0": - version "24.2.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.2.1.tgz#83e41543f0a518e006594bb394e2cd961de56727" - integrity sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ== + version "24.3.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.3.0.tgz#89b09f45cb9a8ee69466f18ee5864e4c3eb84dec" + integrity sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow== dependencies: undici-types "~7.10.0" @@ -7744,10 +7744,10 @@ timers-ext@^0.1.7: es5-ext "^0.10.64" next-tick "^1.1.0" -tinybench@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-4.1.0.tgz#090118e51159eb105f3cc2ef5cf371f3f8adc7bf" - integrity sha512-8JZoQRJgWWEIIeAmpiNmMHIREmUY3oGX8GRmlmNapLr/qtgMe+K76vM2qabh85hNScnE2lqTVTajVETjuD9Ixg== +tinybench@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-5.0.0.tgz#bb0b7141f84d8917b5d95951d05e0e8db570be04" + integrity sha512-iqp7HhNk6IQXuE5fyJsX4ENpnWcw9k+QS5hsLXZq47J8hH/cL/WjNr6Fr9kXMqCGYMhFSLX8xwoJl6rgB0Pz/A== tinyglobby@^0.2.12, tinyglobby@^0.2.14: version "0.2.14" From 07b1ac0213bcf9591a8dd5633535a43ecd248192 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Mon, 18 Aug 2025 15:53:06 +0300 Subject: [PATCH 9/9] chore(release): 5.101.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c76aea16ef..d0814a6a39d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webpack", - "version": "5.101.2", + "version": "5.101.3", "description": "Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.", "homepage": "https://github.com/webpack/webpack", "bugs": "https://github.com/webpack/webpack/issues",