-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Describe the bug
_interopRequireWildcard's implementation works by using a for(var key in obj) loop over the required module's export to build up a new object with the same keys. This strategy does not cooperate with modules whose exports expose other types of capabilities. For example, it does not support commonjs modules whose exports are:
Proxyobjects which supportgetoperations of dynamic, non-enumerable properties (eg,identity-obj-proxy)- Classes which support being constructed (eg,
enzyme-adapter-react-16)
The specific motivating module in our case is identity-obj-proxy, which the Jest docs suggest as the recommended way to mock CSS modules. Its implementation is essentially:
idObj = new Proxy({}, {
get: function getter(target, key) {
if (key === '__esModule') {
return false;
}
return key;
}
});
module.exports = idObj;We found this issue while experimenting with migrating an existing React codebase (microsoft/accessibility-insights-web) from ts-jest to @swc/jest. Our project uses identity-obj-proxy per the Jest docs' suggestion of how to mock CSS modules, like this:
// jest.config.js
{
moduleNameMapper: {
'\\.(scss)$': 'identity-obj-proxy',
},
transform: {
// works
// '^.+\\.(ts|tsx)$': 'ts-jest',
// breaks
'^.+\\.(ts|tsx)$': ['@swc/jest'],
},
}// my-component.tsx
import * as styles from './footer-section.scss';
export const MyComponent = () => {
return <button className={styles.myCoolButton} />;
};With ts-jest, this strategy results in the component seeing styles.myCoolButton as "myCoolButton"; with @swc/jest, this results in the component seeing styles.myCoolButton as undefined, because _interopRequireWildcard' doesn't know to add a myCoolButton property to the synthetic export it creates.
The second motivating case we ran into was with the enzyme-adapter-react-16 module, which exports a class and expects you to construct an instance of it. The synthetic export from _interopRequireWildcard does not support having new instances constructed from it.
Input code
repro-proxy-export.ts:
import * as identityObjProxy from 'identity-obj-proxy';
console.log(`identityObjProxy.testVar: ${identityObjProxy.testVar}`);repro-class-export.ts:
import * as EnzymeAdapter from 'enzyme-adapter-react-16';
new EnzymeAdapter(); // shouldn't throw
console.log('Test passed!');.swcrc:
> npm install @swc/core @swc/cli identity-obj-proxy enzyme-adapter-react-16 enzyme react@16 react-dom@16
> npx swc -d dist ./repro-class-export.ts ./repro-proxy-export.ts
> # should print identityObjProxy.testVar: testVar
> node ./dist/repro-proxy-export.js
identityObjProxy.testVar: undefined
> # should run without throwing
> node ./dist/repro-class-export.js
C:\repos\swc-repro\dist\repro-class-export.js:26
new EnzymeAdapter(); // shouldn't throw
^
TypeError: EnzymeAdapter is not a constructor
at Object.<anonymous> (C:\repos\swc-repro\dist\repro-class-export.js:26:1)
at Module._compile (internal/modules/cjs/loader.js:1068:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1097:10)
at Module.load (internal/modules/cjs/loader.js:933:32)
at Function.Module._load (internal/modules/cjs/loader.js:774:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47Config
With @swc/jest, default configuration (no .swcrc file) repros. For standalone repro:
{ "module": { "type": "commonjs" } }Expected behavior
The two repros from the "Input code" section above should respectively:
- print
identityObjProxy.testVar: testVar - not emit an error
Version
- @swc/core:
1.2.59 - @swc/jest:
0.1.2
Additional context
n/a
{ "module": { "type": "commonjs" } }