示例
@rollup/plugin-commonjs 28.0.2: In @rollup/plugin-commonjs v28, strictRequires defaults to true, wrapping CommonJS modules in function closures so that conditional requires execute lazily rather than eagerly at bundle load time, and circular dependencies resolve in-progress exports.
已验证示例 — npm @rollup/plugin-commonjs 28.0.2: In @rollup/plugin-commonjs v28, strictRequires defaults to true, wrapping CommonJS modules in function closures…
sha256:381e948e0e9b076d1fffab3daaab1dae9e66fe23763eae90d5f3587880733271
本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。
提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。
MIT-0
执行证据
声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。
- 证据依据
- 签名契约通过
- 验证回执
- 2
- 构建过它的签名密钥
- 2
声明的环境
node linux x64 node node npm
验证运行环境
| 环境 | 契约 | 阶段 | 运行日期 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
案例
HOW- 目标
- In @rollup/plugin-commonjs v28, strictRequires defaults to true, wrapping CommonJS modules in function closures so that conditional requires execute lazily rather than eagerly at bundle load time, and circular dependencies resolve in-progress exports.
- 符号
-
- commonjs
- strictRequires
- 环境
- node
- 创建时间
- 2026-08-16T16:01:16Z
契约
- assert @rollup/plugin-commonjs with default strictRequires wraps CommonJS modules in lazy function closures, preventing top-level side effects of conditionally required modules from executing at bundle evaluation time until the function is invoked
- assert setting strictRequires: false hoists all CommonJS requires to the bundle top-level, causing side effects of lazy requires to execute immediately upon module evaluation
- assert strictRequires: true resolves circular CommonJS dependencies at runtime by providing the in-progress exports object, whereas strictRequires: false leaves circular references uninitialized as undefined
- assert strictRequires accepts picomatch glob patterns to selectively wrap only targeted circular modules while hoisting all other CommonJS files
文件
- NOTES.md
- csx.json
- package-lock.json
- package.json
- test/contract.mjs
源代码
# Rollup CommonJS Plugin Module Wrapping and Lazy Execution Semantics
## Search Result
`search_known_solution` returned existing samples `sha256:7d74520bd3cbe8b4027fdaefc8257db0bff3f5ebbd8644dd0d7d9f76b692bcdb` (covering `transformMixedEsModules`), `sha256:6bd9e4aeb00bbe86cb0245f6c6955ae8ec7421dba24da3b8401f6307646e0ad8` (covering `output.interop` with external dependencies), and `sha256:0f0a334613ed1e80698698742c1c0c7560186235330f4dee0a2daaa6025e2bf2` (covering `.cjs` extension handling). This sample demonstrates a distinct trap: the default `strictRequires: true` behavior in major version 28, function wrapping closures, and execution timing for conditional and circular CommonJS dependencies.
## Naive Model Assumption
A developer or coding model assumes that Rollup processes CommonJS modules by statically hoisting all `require()` statements to the top level of the bundle (like ES module static imports). Under this assumption, all bundled CommonJS modules execute their top-level code and side effects immediately upon bundle import, even if a `require()` was placed inside an exported function or conditional branch.
## Failure Mode
It fails silently with a green build: Rollup compiles without errors or warnings, but code expecting eager top-level side effects from bundled CommonJS dependencies does not run until the wrapping function is explicitly called. Conversely, disabling strict requires (`strictRequires: false`) silently breaks circular CommonJS dependencies by returning `undefined` for intermediate exports during cyclic module evaluation.
{"case":{"believed":"Bundling CommonJS modules with Rollup statically hoists and eagerly executes all module top-level code on bundle import regardless of whether a require call is nested inside a function or conditional branch.","caseId":"case:sha256:e022914de5a3133762dad12d8f8e91dc7b3c77b70a296eef36db67424faf8ab8","contract":["assert @rollup/plugin-commonjs with default strictRequires wraps CommonJS modules in lazy function closures, preventing top-level side effects of conditionally required modules from executing at bundle evaluation time until the function is invoked","assert setting strictRequires: false hoists all CommonJS requires to the bundle top-level, causing side effects of lazy requires to execute immediately upon module evaluation","assert strictRequires: true resolves circular CommonJS dependencies at runtime by providing the in-progress exports object, whereas strictRequires: false leaves circular references uninitialized as undefined","assert strictRequires accepts picomatch glob patterns to selectively wrap only targeted circular modules while hoisting all other CommonJS files"],"goal":"In @rollup/plugin-commonjs v28, strictRequires defaults to true, wrapping CommonJS modules in function closures so that conditional requires execute lazily rather than eagerly at bundle load time, and circular dependencies resolve in-progress exports.","kind":"HOW","packages":["pkg:npm/@rollup/plugin-commonjs@28.0.2","pkg:npm/rollup@4.34.8"],"schemaVersion":1,"symbols":["commonjs","strictRequires"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/@rollup/plugin-commonjs@28.0.2","pkg:npm/rollup@4.34.8"],"schemaVersion":1,"symbols":["commonjs","strictRequires"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-rollup-plugin-commonjs-v28",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-rollup-plugin-commonjs-v28",
"version": "1.0.0",
"dependencies": {
"@rollup/plugin-commonjs": "28.0.2",
"rollup": "4.34.8"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"license": "MIT"
},
"node_modules/@rollup/plugin-commonjs": {
"version": "28.0.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz",
"integrity": "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==",
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"commondir": "^1.0.1",
"estree-walker": "^2.0.2",
"fdir": "^6.2.0",
"is-reference": "1.2.1",
"magic-string": "^0.30.3",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=16.0.0 || 14 >= 14.17"
},
"peerDependencies": {
"rollup": "^2.68.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz",
"integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==",
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
"integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz",
"integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz",
"integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz",
"integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz",
"integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz",
"integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz",
"integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz",
"integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz",
"integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz",
"integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz",
"integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==",
"cpu": [
"loong64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz",
"integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==",
"cpu": [
"ppc64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz",
"integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz",
"integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==",
"cpu": [
"s390x"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
"integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz",
"integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz",
"integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz",
"integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
"integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
"integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
"license": "MIT"
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"license": "MIT"
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT"
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"license": "MIT",
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/picomatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
"integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/rollup": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
"integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.6"
},
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.34.8",
"@rollup/rollup-android-arm64": "4.34.8",
"@rollup/rollup-darwin-arm64": "4.34.8",
"@rollup/rollup-darwin-x64": "4.34.8",
"@rollup/rollup-freebsd-arm64": "4.34.8",
"@rollup/rollup-freebsd-x64": "4.34.8",
"@rollup/rollup-linux-arm-gnueabihf": "4.34.8",
"@rollup/rollup-linux-arm-musleabihf": "4.34.8",
"@rollup/rollup-linux-arm64-gnu": "4.34.8",
"@rollup/rollup-linux-arm64-musl": "4.34.8",
"@rollup/rollup-linux-loongarch64-gnu": "4.34.8",
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.8",
"@rollup/rollup-linux-riscv64-gnu": "4.34.8",
"@rollup/rollup-linux-s390x-gnu": "4.34.8",
"@rollup/rollup-linux-x64-gnu": "4.34.8",
"@rollup/rollup-linux-x64-musl": "4.34.8",
"@rollup/rollup-win32-arm64-msvc": "4.34.8",
"@rollup/rollup-win32-ia32-msvc": "4.34.8",
"@rollup/rollup-win32-x64-msvc": "4.34.8",
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"license": "MIT"
}
}
}
{
"name": "npm-rollup-plugin-commonjs-v28",
"version": "1.0.0",
"type": "module",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"@rollup/plugin-commonjs": "28.0.2",
"rollup": "4.34.8"
}
}
import assert from 'node:assert/strict';
import { rollup } from 'rollup';
import commonjs from '@rollup/plugin-commonjs';
import fs from 'node:fs';
async function runContract() {
const fileEntry = 'test/entry.cjs';
const fileEager = 'test/eager-feature.cjs';
const fileLazy = 'test/lazy-feature.cjs';
// ---------------------------------------------------------------------------
// Contract Line 1 (Core Finding):
// @rollup/plugin-commonjs v28 defaults strictRequires to true.
// CommonJS modules required inside functions or conditional blocks are wrapped
// in lazy function closures, preventing side effects from executing at bundle import.
// ---------------------------------------------------------------------------
const lazyPlugin = {
name: 'virtual-lazy-modules',
resolveId(id) {
if (id === 'test/entry.cjs' || id === fileEntry) return fileEntry;
if (id === './eager-feature.cjs' || id === fileEager) return fileEager;
if (id === './lazy-feature.cjs' || id === fileLazy) return fileLazy;
},
load(id) {
if (id === fileEntry) {
return `
const eager = require('./eager-feature.cjs');
function getLazyFeature() {
return require('./lazy-feature.cjs');
}
module.exports = { eager, getLazyFeature };
`;
}
if (id === fileEager) {
return `
globalThis.__executionTrail = globalThis.__executionTrail || [];
globalThis.__executionTrail.push('eager-evaluated');
module.exports = { type: 'eager' };
`;
}
if (id === fileLazy) {
return `
globalThis.__executionTrail = globalThis.__executionTrail || [];
globalThis.__executionTrail.push('lazy-evaluated');
module.exports = { type: 'lazy' };
`;
}
}
};
// Build with default options (strictRequires: true in v28)
const defaultBundle = await rollup({
input: fileEntry,
plugins: [lazyPlugin, commonjs()],
onwarn: () => {}
});
const { output: defaultOutput } = await defaultBundle.generate({ format: 'es' });
const defaultCode = defaultOutput[0].code;
// The generated code must contain wrapped require functions for lazy modules
assert.match(
defaultCode,
/function requireLazyFeature\s*\(\)/,
'lazy module is wrapped in a function closure under default strictRequires'
);
// Evaluate default bundle
globalThis.__executionTrail = [];
const tmpDefaultUri = new URL('./tmp-contract-default.mjs', import.meta.url);
fs.writeFileSync(tmpDefaultUri, defaultCode);
const defaultMod = (await import(tmpDefaultUri.href)).default;
fs.unlinkSync(tmpDefaultUri);
// At bundle import time, eager-feature ran, but lazy-feature has NOT run yet
assert.deepEqual(
globalThis.__executionTrail,
['eager-evaluated'],
'assert @rollup/plugin-commonjs with default strictRequires wraps CommonJS modules in lazy function closures, preventing top-level side effects of conditionally required modules from executing at bundle evaluation time until the function is invoked'
);
// Calling getLazyFeature() triggers the lazy execution on demand
const lazyResult = defaultMod.getLazyFeature();
assert.equal(lazyResult.type, 'lazy');
assert.deepEqual(
globalThis.__executionTrail,
['eager-evaluated', 'lazy-evaluated'],
'lazy module executes on demand when getter function is called'
);
// ---------------------------------------------------------------------------
// Contract Line 2:
// strictRequires: false hoists all requires to top-level, executing eagerly.
// ---------------------------------------------------------------------------
const hoistedBundle = await rollup({
input: fileEntry,
plugins: [lazyPlugin, commonjs({ strictRequires: false })],
onwarn: () => {}
});
const { output: hoistedOutput } = await hoistedBundle.generate({ format: 'es' });
const hoistedCode = hoistedOutput[0].code;
// No function wrapping for lazy module
assert.doesNotMatch(
hoistedCode,
/function requireLazyFeature/,
'strictRequires: false eliminates function wrapping closures'
);
globalThis.__executionTrail = [];
const tmpHoistedUri = new URL('./tmp-contract-hoisted.mjs', import.meta.url);
fs.writeFileSync(tmpHoistedUri, hoistedCode);
await import(tmpHoistedUri.href);
fs.unlinkSync(tmpHoistedUri);
// Under strictRequires: false, both eager AND lazy modules execute immediately on bundle load
assert.deepEqual(
globalThis.__executionTrail,
['eager-evaluated', 'lazy-evaluated'],
'assert setting strictRequires: false hoists all CommonJS requires to the bundle top-level, causing side effects of lazy requires to execute immediately upon module evaluation'
);
// ---------------------------------------------------------------------------
// Contract Line 3:
// Circular CommonJS dependencies resolve in-progress exports under strictRequires: true,
// but evaluate as undefined under strictRequires: false due to static hoisting order.
// ---------------------------------------------------------------------------
const fileCycleEntry = 'test/entry-cycle.cjs';
const fileCycleA = 'test/cycle-a.cjs';
const fileCycleB = 'test/cycle-b.cjs';
const circularPlugin = {
name: 'virtual-circular-modules',
resolveId(id) {
if (id === 'test/entry-cycle.cjs' || id === fileCycleEntry) return fileCycleEntry;
if (id === './cycle-a.cjs' || id === fileCycleA) return fileCycleA;
if (id === './cycle-b.cjs' || id === fileCycleB) return fileCycleB;
},
load(id) {
if (id === fileCycleEntry) {
return `
const a = require('./cycle-a.cjs');
module.exports = { a };
`;
}
if (id === fileCycleA) {
return `
exports.name = 'cycle-a-name';
const b = require('./cycle-b.cjs');
exports.readFromB = () => b.readFromA;
exports.bCapturedFromA = b.readFromA;
`;
}
if (id === fileCycleB) {
return `
const a = require('./cycle-a.cjs');
exports.name = 'cycle-b-name';
exports.readFromA = a.name;
`;
}
}
};
// Build circular modules with strictRequires: true (default)
const circularStrictBundle = await rollup({
input: fileCycleEntry,
plugins: [circularPlugin, commonjs({ strictRequires: true })],
onwarn: () => {}
});
const { output: circularStrictOutput } = await circularStrictBundle.generate({ format: 'es' });
const tmpCycleStrictUri = new URL('./tmp-cycle-strict.mjs', import.meta.url);
fs.writeFileSync(tmpCycleStrictUri, circularStrictOutput[0].code);
const cycleStrictMod = (await import(tmpCycleStrictUri.href)).default;
fs.unlinkSync(tmpCycleStrictUri);
// In strictRequires: true, cycle-b successfully captured cycle-a's intermediate exports.name
assert.equal(
cycleStrictMod.a.bCapturedFromA,
'cycle-a-name',
'assert strictRequires: true resolves circular CommonJS dependencies at runtime by providing the in-progress exports object, whereas strictRequires: false leaves circular references uninitialized as undefined'
);
// Build circular modules with strictRequires: false
const circularFalseBundle = await rollup({
input: fileCycleEntry,
plugins: [circularPlugin, commonjs({ strictRequires: false })],
onwarn: () => {}
});
const { output: circularFalseOutput } = await circularFalseBundle.generate({ format: 'es' });
const tmpCycleFalseUri = new URL('./tmp-cycle-false.mjs', import.meta.url);
fs.writeFileSync(tmpCycleFalseUri, circularFalseOutput[0].code);
const cycleFalseMod = (await import(tmpCycleFalseUri.href)).default;
fs.unlinkSync(tmpCycleFalseUri);
// In strictRequires: false, cycle-b was evaluated before cycle-a assigned exports.name, giving undefined
assert.equal(
cycleFalseMod.a.bCapturedFromA,
undefined,
'Under strictRequires: false circular dependency reads uninitialized undefined'
);
// ---------------------------------------------------------------------------
// Contract Line 4:
// strictRequires accepts picomatch glob patterns to selectively wrap only targeted circular modules.
// ---------------------------------------------------------------------------
const selectiveBundle = await rollup({
input: fileEntry,
plugins: [lazyPlugin, commonjs({ strictRequires: ['**/lazy-feature.cjs'] })],
onwarn: () => {}
});
const { output: selectiveOutput } = await selectiveBundle.generate({ format: 'es' });
const selectiveCode = selectiveOutput[0].code;
// lazy-feature is wrapped in a function closure, eager-feature is hoisted without wrapping
assert.match(selectiveCode, /function requireLazyFeature\s*\(\)/);
assert.doesNotMatch(
selectiveCode,
/function requireEagerFeature\s*\(\)/,
'assert strictRequires accepts picomatch glob patterns to selectively wrap only targeted circular modules while hoisting all other CommonJS files'
);
console.log('All contract assertions passed successfully.');
}
runContract().catch((err) => {
console.error('Contract failed:', err);
process.exit(1);
});