Context: corpus — blocks winston, localized via #5274 to @colors/colors/lib/custom/trap.js:1: module['exports'] = function runTheTrap(...) {...}. perry recognizes module.exports = ... / exports.foo = ... (dot) as CJS export assignments, but not the bracket / computed-string-literal forms module['exports'] = ... / exports['foo'] = .... The bracket form isn't treated as CJS → the module's default export isn't registered (and/or module isn't bound), so consumers fail.
Minimal repro (confirmed)
node_modules/mb/package.json: { "name":"mb","version":"1.0.0","main":"index.js" }
node_modules/mb/index.js: module['exports'] = function greet(n) { return "hi " + n; };
package.json: { "type":"module","perry":{"compilePackages":["*"],"allow":{"compilePackages":["*"]}} }
main.ts: import mb from "mb"; console.log(mb("x"));
module['exports'] = fn → Error: package 'mb' does not provide an export named 'default'.
module.exports = fn (dot) → works (hi x). Node → hi x for both.
Fix direction
In perry's CJS detection + export-assignment handling (cjs_wrap / wrap.rs and wherever module.exports/exports.<name> assignments are recognized), treat a string-literal computed member the same as the dot form:
module['exports'] / module["exports"] ≡ module.exports
exports['name'] / exports["name"] ≡ exports.name
Only string-literal keys (a genuinely dynamic module[k] stays as-is). Make sure both the CJS-module detection (so the file gets wrapped / module bound) and the default-export registration honor the bracket form.
Impact
@colors/colors → winston; broadly, any package using bracket module['exports']/exports['x'] (a common minifier/style variant).
Context: corpus — blocks winston, localized via #5274 to
@colors/colors/lib/custom/trap.js:1:module['exports'] = function runTheTrap(...) {...}. perry recognizesmodule.exports = .../exports.foo = ...(dot) as CJS export assignments, but not the bracket / computed-string-literal formsmodule['exports'] = .../exports['foo'] = .... The bracket form isn't treated as CJS → the module's default export isn't registered (and/ormoduleisn't bound), so consumers fail.Minimal repro (confirmed)
module['exports'] = fn→Error: package 'mb' does not provide an export named 'default'.module.exports = fn(dot) → works (hi x). Node →hi xfor both.Fix direction
In perry's CJS detection + export-assignment handling (cjs_wrap /
wrap.rsand wherevermodule.exports/exports.<name>assignments are recognized), treat a string-literal computed member the same as the dot form:module['exports']/module["exports"]≡module.exportsexports['name']/exports["name"]≡exports.nameOnly string-literal keys (a genuinely dynamic
module[k]stays as-is). Make sure both the CJS-module detection (so the file gets wrapped /modulebound) and the default-export registration honor the bracket form.Impact
@colors/colors → winston; broadly, any package using bracket
module['exports']/exports['x'](a common minifier/style variant).