fix: v2.5.2 — plugin bootstrap exports before it runs (v2.5.1 update crash)

v2.5.1's update died at "bootstrap" on every platform: boot.npmCommand is
not a function. Run as the entry, plugin-bootstrap.js calls bootstrap() →
plugin-open.js, which requires plugin-bootstrap back and got the module.exports
of that moment — {} — because it was assigned at the bottom, below the entry
block. plugin-open.js already exported first for the same reason.

- module.exports moved above the entry block in plugin-bootstrap.js
- A test checks both entry scripts assign module.exports before their entry
  block (it fails on v2.5.1's file); requiring the module, as the other tests
  do, never takes the entry path
This commit is contained in:
2026-10-06 19:17:52 +07:00
parent be75572977
commit f8acd5fc29
7 changed files with 53 additions and 32 deletions
+17
View File
@@ -693,3 +693,20 @@ describe("npmCommand", () => {
assert.deepEqual(npm.args, ["-v"]);
});
});
describe("entry scripts export before they run", () => {
// plugin-bootstrap.js run as the entry calls bootstrap() → plugin-open.js,
// which requires plugin-bootstrap back and gets whatever module.exports holds
// at that moment. Assigned after the entry block it was still {}, and v2.5.1's
// update died with "boot.npmCommand is not a function". Requiring the module
// (as every other test here does) never takes that path, hence this check.
for (const file of ["plugin-bootstrap.js", "plugin-open.js"]) {
it(file, () => {
const src = fs.readFileSync(path.join(__dirname, "..", "..", "scripts", file), "utf8");
const exportsAt = src.indexOf("\nmodule.exports = {");
const entryAt = src.indexOf("\nif (require.main === module)");
assert.ok(exportsAt > 0 && entryAt > 0, "both markers present");
assert.ok(exportsAt < entryAt, "module.exports must be assigned before the entry block");
});
}
});