diff --git a/CHANGELOG.md b/CHANGELOG.md index cf6b87098..1de4b3bf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # rollup changelog +## 4.41.1 + +_2025-05-24_ + +### Bug Fixes + +- If a plugin calls `this.resolve` with `skipSelf: true`, subsequent calls when handling this by the same plugin with same parameters will return `null` to avoid infinite recursions (#5945) + +### Pull Requests + +- [#5945](https://github.com/rollup/rollup/pull/5945): Avoid recursively calling a plugin's resolveId hook with same id and importer (@younggglcy, @lukastaegert) +- [#5963](https://github.com/rollup/rollup/pull/5963): fix(deps): update swc monorepo (major) (@renovate[bot]) +- [#5964](https://github.com/rollup/rollup/pull/5964): fix(deps): lock file maintenance minor/patch updates (@renovate[bot]) + ## 4.41.0 _2025-05-18_ diff --git a/browser/package.json b/browser/package.json index 44611e891..6d6934fe0 100644 --- a/browser/package.json +++ b/browser/package.json @@ -1,6 +1,6 @@ { "name": "@rollup/browser", - "version": "4.41.0", + "version": "4.41.1", "description": "Next-generation ES module bundler browser build", "main": "dist/rollup.browser.js", "module": "dist/es/rollup.browser.js", diff --git a/docs/plugin-development/index.md b/docs/plugin-development/index.md index 3d9669db6..f5962df8b 100644 --- a/docs/plugin-development/index.md +++ b/docs/plugin-development/index.md @@ -1901,7 +1901,7 @@ type Resolve = ( attributes?: { [key: string]: string }; custom?: { [plugin: string]: any }; } -) => ResolvedId; +) => Promise; ``` ::: tip @@ -1910,7 +1910,7 @@ type Resolve = ( ::: -使用 Rollup 使用的相同插件解析导入到模块 id(即文件名),并确定导入是否应为外部。如果 Rollup 或任何插件无法解析导入,但用户未明确将其标记为外部,则返回 `null`。如果返回绝对外部 id,则应通过 [`makeAbsoluteExternalsRelative`](../configuration-options/index.md#makeabsoluteexternalsrelative) 选项或在 [`resolveId`](#resolveid) 钩子中进行显式插件选择,将其保持为绝对输出,`external` 将是 `"absolute"` 而不是 `true`。 +使用 Rollup 使用的相同插件解析导入到模块 id(即文件名),并确定导入是否应为外部。如果 Rollup 或任何插件无法解析导入,但用户未明确将其标记为外部,则返回 `Promise`。如果返回绝对外部 id,则应通过 [`makeAbsoluteExternalsRelative`](../configuration-options/index.md#makeabsoluteexternalsrelative) 选项或在 [`resolveId`](#resolveid) 钩子中进行显式插件选择,将其保持为绝对输出,`external` 将是 `"absolute"` 而不是 `true`。 `skipSelf` 的默认值是 `true`,因此在解析时将跳过调用 `this.resolve` 的插件的 `resolveId` 钩子。当其他插件在处理原始 `this.resolve` 调用时,也使用 _完全相同的 `source` 和 `importer`_ 在其 `resolveId` 钩子中调用 `this.resolve` 时,原始插件的 `resolveId` 钩子也将跳过这些调用。这里的原理是,插件已经声明它在此时点上“不知道”如何解析这个特定的 `source` 和 `importer` 组合。如果你不想要这种行为,将 `skipSelf` 设置为 `false`,并在必要时实现自己的无限循环预防机制。 diff --git a/package-lock.json b/package-lock.json index 7b486dc71..862eded04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rollup", - "version": "4.41.0", + "version": "4.41.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rollup", - "version": "4.41.0", + "version": "4.41.1", "license": "MIT", "dependencies": { "@types/estree": "1.0.7" diff --git a/package.json b/package.json index 4068a4452..713dbfda4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "4.41.0", + "version": "4.41.1", "description": "Next-generation ES module bundler", "main": "dist/rollup.js", "module": "dist/es/rollup.js", diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 879c3664f..26acebbd3 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1134,9 +1134,9 @@ dependencies = [ [[package]] name = "swc_common" -version = "9.2.0" +version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56b6f5a8e5affa271b56757a93badee6f44defcd28f3ba106bb2603afe40d3d" +checksum = "209e700a12f0fccd72db3bac7a751e631ef777d543c9e86247e9366b11e30a27" dependencies = [ "anyhow", "ast_node", @@ -1163,9 +1163,9 @@ dependencies = [ [[package]] name = "swc_compiler_base" -version = "20.0.0" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0042d7baa47bfcd95c165a2e2f03384825ab6bcf525692361894c8105d60ec1c" +checksum = "3aef98ee955eac3339cb3a8152c64746196bd14919b41afdf2cc410c06e6cfee" dependencies = [ "anyhow", "base64", @@ -1220,9 +1220,9 @@ dependencies = [ [[package]] name = "swc_ecma_ast" -version = "9.0.0" +version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0613d84468a6bb6d45d13c5a3368b37bd21f3067a089f69adac630dcb462a018" +checksum = "d2313360a518a37c4b9ee50030d189222927a3af902903cc70c50f6929e402dc" dependencies = [ "bitflags", "is-macro", @@ -1241,9 +1241,9 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "11.0.0" +version = "13.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01b3de365a86b8f982cc162f257c82f84bda31d61084174a3be37e8ab15c0f4" +checksum = "c6f929a62c96d50fc87fb54cf2135ecaec2d343d6df461f82462b8aed12da8cb" dependencies = [ "ascii", "compact_str", @@ -1252,6 +1252,7 @@ dependencies = [ "once_cell", "regex", "rustc-hash", + "ryu-js", "serde", "sourcemap", "swc_allocator", @@ -1276,9 +1277,9 @@ dependencies = [ [[package]] name = "swc_ecma_lexer" -version = "12.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d11c8e71901401b9aae2ece4946eeb7674b14b8301a53768afbbeeb0e48b599" +checksum = "602a6a5190cbb4adc134bdf9a525b845912a86039130c2b476ff20123b1aacd5" dependencies = [ "arrayvec", "bitflags", @@ -1301,9 +1302,9 @@ dependencies = [ [[package]] name = "swc_ecma_minifier" -version = "18.0.0" +version = "20.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084389cc2cd71d643de71b6f1b758a509a36d5ca319954b3a6e0be9359c9309d" +checksum = "879d5f44a9d7480710dadbcd33e8b8d436132f92d668999061d52b5f211a6d3b" dependencies = [ "arrayvec", "bitflags", @@ -1339,9 +1340,9 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "12.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250786944fbc05f6484eda9213df129ccfe17226ae9ad51b62fce2f72135dbee" +checksum = "bebfd62dc0ffe6b80bedcd049f1c949133de6d524d12d2edbb0b6fb64896cefb" dependencies = [ "arrayvec", "bitflags", @@ -1365,9 +1366,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "13.0.0" +version = "15.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6856da3da598f4da001b7e4ce225ee8970bc9d5cbaafcaf580190cf0a6031ec5" +checksum = "bb01eeec1de9e2cfd089e3afcf3db60df10c812f97a42d953d094eba32e9d26f" dependencies = [ "better_scoped_tls", "bitflags", @@ -1401,9 +1402,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "14.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b14c8f6c1c82b7556d7534de44714401901fcb9b618f817172015565ce7d47" +checksum = "1e184bf675c5c9111e1b155e49fc267bc2971b732ac22d80887cc46973a782b7" dependencies = [ "dashmap", "indexmap", @@ -1425,9 +1426,9 @@ dependencies = [ [[package]] name = "swc_ecma_usage_analyzer" -version = "14.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d7858f1eccac3c8a85b97ba3820020583efa28bc766d253f0a93d7bbc54c985" +checksum = "4b1f2dccff9c6cde3f72a86babcc34b1213e0cef8c6e2f1a1da75eca7f5bbe73" dependencies = [ "bitflags", "indexmap", @@ -1443,9 +1444,9 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "13.1.0" +version = "15.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ed837406d5dbbfbf5792b1dc90964245a0cf659753d4745fe177ffebe8598b9" +checksum = "199e2f048c1998d550ebe5296e0876a3e5b2f963d75a925c2208466071edb9d8" dependencies = [ "indexmap", "num_cpus", @@ -1464,9 +1465,9 @@ dependencies = [ [[package]] name = "swc_ecma_visit" -version = "9.0.0" +version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249dc9eede1a4ad59a038f9cfd61ce67845bd2c1392ade3586d714e7181f3c1a" +checksum = "8227d1d2d76a9ccfd190ec06bb4a4720bf3edb9f954c69816b2bca5f5aa43887" dependencies = [ "new_debug_unreachable", "num-bigint", diff --git a/rust/parse_ast/Cargo.toml b/rust/parse_ast/Cargo.toml index 6b2880312..937800751 100644 --- a/rust/parse_ast/Cargo.toml +++ b/rust/parse_ast/Cargo.toml @@ -8,9 +8,9 @@ edition = "2021" [dependencies] anyhow = "1.0.98" swc_atoms = "5.0.0" -swc_compiler_base = "20.0.0" +swc_compiler_base = "22.0.0" swc_config = "3.0.0" -swc_common = { version = "9.2.0", features = ["parking_lot"] } -swc_ecma_ast = "9.0.0" -swc_ecma_parser = "12.0.0" +swc_common = { version = "11.0.0", features = ["parking_lot"] } +swc_ecma_ast = "11.0.0" +swc_ecma_parser = "14.0.0" parking_lot = "0.12.3" diff --git a/src/utils/resolveIdViaPlugins.ts b/src/utils/resolveIdViaPlugins.ts index d33a9ed39..0473a6a55 100644 --- a/src/utils/resolveIdViaPlugins.ts +++ b/src/utils/resolveIdViaPlugins.ts @@ -26,6 +26,20 @@ export function resolveIdViaPlugins( ...pluginContext, resolve: (source, importer, { attributes, custom, isEntry, skipSelf } = BLANK) => { skipSelf ??= true; + if ( + skipSelf && + skip.findIndex(skippedCall => { + return ( + skippedCall.plugin === plugin && + skippedCall.source === source && + skippedCall.importer === importer + ); + }) !== -1 + ) { + // This means that the plugin recursively called itself + // Thus returning Promise.resolve(null) in purpose of fallback to default behavior of `resolveId` plugin hook. + return Promise.resolve(null); + } return moduleLoaderResolveId( source, importer, diff --git a/test/function/samples/resolveid-recursive-call/_config.js b/test/function/samples/resolveid-recursive-call/_config.js new file mode 100644 index 000000000..68f2be786 --- /dev/null +++ b/test/function/samples/resolveid-recursive-call/_config.js @@ -0,0 +1,27 @@ +module.exports = defineTest({ + description: + 'skipSelf: true option in resolveId hook option should skip the plugin if it has been called before with the same id and importer, see #5768 for more details', + options: { + plugins: [ + { + name: 'r1', + async resolveId(id) { + const importer = 'foo'; + return (await this.resolve(id, importer)) ?? 'success'; + }, + load(id) { + if (id === 'success') { + return { code: 'export default 1' }; + } + } + }, + { + name: 'r2', + resolveId(id) { + const importer = 'bar'; + return this.resolve(id, importer); + } + } + ] + } +}); diff --git a/test/function/samples/resolveid-recursive-call/main.js b/test/function/samples/resolveid-recursive-call/main.js new file mode 100644 index 000000000..545a30f67 --- /dev/null +++ b/test/function/samples/resolveid-recursive-call/main.js @@ -0,0 +1,3 @@ +import val from 'virtual' + +assert.strictEqual(val, 1)