-
Notifications
You must be signed in to change notification settings - Fork 15
TypeError when accessing exported member with "circular" dependency on barrel file #96
Description
Issue
Note that module.type in the swc config is set to commonjs for this issue.
When a member (in this case, a TS enum) is re-exported in a barrel file and a sub-dependency of the barrel file imports that enum through the barrel file and tries to access it, a TypeError is thrown:
TypeError: Cannot read properties of undefined (reading 'A')
This is due to how swc_mut_cjs_exports groups all the require calls at the top of the transpiled file and then adds the keys to the exports object after all of those require.
// task.js
var _enumDep = /*#__PURE__*/ _interop_require_wildcard(require("./enumDep"));
var _anotherDep = /*#__PURE__*/ _interop_require_wildcard(require("./anotherDep"));
/* ...helper functions... */
Object.keys(_enumDep).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(exports, key)) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _enumDep[key];
},
configurable: true
});
});
Object.keys(_anotherDep).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(exports, key)) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _anotherDep[key];
},
configurable: true
});
});./enumDep exports SomeEnum, and ./anotherDep eventually imports SomeEnum from the task.js barrel file. But since the keys for ./enumDep haven't been added to exports by the time ./anotherDep is required, the SomeEnum ends up being undefined.
Reproduction
I've set up a small repo with the reproduction of this and the README has info on the structure:
https://github.com/wadjoh/swc_mut_cjs_exports_debug_ts_enum
This is the structure of the TS code that causes an error when the transpiled code is executed:

Potential Fix
When swc_mut_cjs_exports transpiles star exports, this issue can be avoided by adding the keys to the exports object immediately after the associated require call:
// task.js
// moved helper function definitions to the top
/* ...helper functions... */
// `exports` is populated with module keys immediately after the module's `require` call
var _enumDep = /*#__PURE__*/ _interop_require_wildcard(require("./enumDep"));
Object.keys(_enumDep).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(exports, key)) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _enumDep[key];
},
configurable: true
});
});
var _anotherDep = /*#__PURE__*/ _interop_require_wildcard(require("./anotherDep"));
Object.keys(_anotherDep).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(exports, key)) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _anotherDep[key];
},
configurable: true
});
});I have manually modified output code in the linked reproduction repo that works fine when executed: https://github.com/wadjoh/swc_mut_cjs_exports_debug_ts_enum/blob/main/results/fixed_output_with_plugin/task.js