diff --git a/CHANGELOG.md b/CHANGELOG.md index f596e205a22e..f42b9e030349 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - `[jest-config]` Fix testing multiple projects with TypeScript config files ([#13099](https://github.com/facebook/jest/pull/13099)) - `[@jest/expect-utils]` Fix deep equality of ImmutableJS Record ([#13055](https://github.com/facebook/jest/pull/13055)) - `[jest-haste-map]` Increase the maximum possible file size that jest-haste-map can handle ([#13094](https://github.com/facebook/jest/pull/13094)) +- `[jest-runtime]` Properly support CJS re-exports from dual packages ([#13170](https://github.com/facebook/jest/pull/13170)) - `[jest-snapshot]` Make `prettierPath` optional in `SnapshotState` ([#13149](https://github.com/facebook/jest/pull/13149)) - `[jest-snapshot]` Fix parsing error from inline snapshot files with `JSX` ([#12760](https://github.com/facebook/jest/pull/12760)) - `[jest-worker]` When a process runs out of memory worker exits correctly and doesn't spin indefinitely ([#13054](https://github.com/facebook/jest/pull/13054)) diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap index d4cc559e7386..1e6cd80fa82e 100644 --- a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -1,5 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`on node >=16.9.0 support re-exports from CJS of dual packages 1`] = ` +"Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: <> +Ran all test suites matching /native-esm-deep-cjs-reexport.test.js/i." +`; + exports[`runs test with native ESM 1`] = ` "Test Suites: 1 passed, 1 total Tests: 33 passed, 33 total diff --git a/e2e/__tests__/nativeEsm.test.ts b/e2e/__tests__/nativeEsm.test.ts index a0a22af661e8..05b2ae06607b 100644 --- a/e2e/__tests__/nativeEsm.test.ts +++ b/e2e/__tests__/nativeEsm.test.ts @@ -6,11 +6,16 @@ */ import {resolve} from 'path'; -import {extractSummary} from '../Utils'; +import {onNodeVersions} from '@jest/test-utils'; +import {extractSummary, runYarnInstall} from '../Utils'; import runJest, {getConfig} from '../runJest'; const DIR = resolve(__dirname, '../native-esm'); +beforeAll(() => { + runYarnInstall(DIR); +}); + test('test config is without transform', () => { const {configs} = getConfig(DIR); @@ -41,3 +46,20 @@ test('supports top-level await', () => { expect(stdout).toBe(''); expect(exitCode).toBe(0); }); + +// minimum version supported by discord.js +onNodeVersions('>=16.9.0', () => { + test('support re-exports from CJS of dual packages', () => { + const {exitCode, stderr, stdout} = runJest( + DIR, + ['native-esm-deep-cjs-reexport.test.js'], + {nodeOptions: '--experimental-vm-modules --no-warnings'}, + ); + + const {summary} = extractSummary(stderr); + + expect(summary).toMatchSnapshot(); + expect(stdout).toBe(''); + expect(exitCode).toBe(0); + }); +}); diff --git a/e2e/native-esm/__tests__/native-esm-deep-cjs-reexport.test.js b/e2e/native-esm/__tests__/native-esm-deep-cjs-reexport.test.js new file mode 100644 index 000000000000..3df450fd1794 --- /dev/null +++ b/e2e/native-esm/__tests__/native-esm-deep-cjs-reexport.test.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {Constants} from '../deepReexport.js'; + +test('can reexport deep CJS requires', () => { + expect(Constants).toHaveProperty('NonSystemMessageTypes'); +}); diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js index d99607115780..aeac49331cb7 100644 --- a/e2e/native-esm/__tests__/native-esm.test.js +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -44,6 +44,9 @@ test('should support importing node core modules', () => { const packageJsonPath = resolve(dir, '../package.json'); expect(JSON.parse(readFileSync(packageJsonPath, 'utf8'))).toEqual({ + devDependencies: { + 'discord.js': '14.3.0', + }, jest: { testEnvironment: 'node', transform: {}, diff --git a/e2e/native-esm/deepReexport.js b/e2e/native-esm/deepReexport.js new file mode 100644 index 000000000000..f98c6ce8642b --- /dev/null +++ b/e2e/native-esm/deepReexport.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {Constants} from 'discord.js'; + +export {Constants}; diff --git a/e2e/native-esm/package.json b/e2e/native-esm/package.json index 5a90624bc1fe..7e5307b71f1d 100644 --- a/e2e/native-esm/package.json +++ b/e2e/native-esm/package.json @@ -1,5 +1,8 @@ { "type": "module", + "devDependencies": { + "discord.js": "14.3.0" + }, "jest": { "testEnvironment": "node", "transform": {} diff --git a/e2e/native-esm/yarn.lock b/e2e/native-esm/yarn.lock new file mode 100644 index 000000000000..737d96c077d9 --- /dev/null +++ b/e2e/native-esm/yarn.lock @@ -0,0 +1,274 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"@discordjs/builders@npm:^1.2.0": + version: 1.2.0 + resolution: "@discordjs/builders@npm:1.2.0" + dependencies: + "@sapphire/shapeshift": ^3.5.1 + discord-api-types: ^0.37.3 + fast-deep-equal: ^3.1.3 + ts-mixer: ^6.0.1 + tslib: ^2.4.0 + checksum: 19949a574496ff353ce4d6c00b7bd2be8e5f8a30b0cee817d8e8e9d83127adfecc1d18bf2ec0e73013cdfb8bbe6da2e3c234cf43a1c776a777efa128038c968f + languageName: node + linkType: hard + +"@discordjs/collection@npm:^1.0.1, @discordjs/collection@npm:^1.1.0": + version: 1.1.0 + resolution: "@discordjs/collection@npm:1.1.0" + checksum: 9a78763a181130d91b51d0d93553fd75d09d0aabd6556890a35404bbefe9c5112cb74c3b1e486a213607f6577f9d2d8ee94ee3177652116bac80516e7d3083d6 + languageName: node + linkType: hard + +"@discordjs/rest@npm:^1.1.0": + version: 1.1.0 + resolution: "@discordjs/rest@npm:1.1.0" + dependencies: + "@discordjs/collection": ^1.0.1 + "@sapphire/async-queue": ^1.5.0 + "@sapphire/snowflake": ^3.2.2 + discord-api-types: ^0.37.3 + file-type: ^17.1.6 + tslib: ^2.4.0 + undici: ^5.9.1 + checksum: b216d5b217bf70a713480738851a0e607cbed267a0ad60942268f9761c605aac6552fd9cdda56bcabe332f6e5ccb5b7ce9911645e24d3d9342ed6f18dccc6b94 + languageName: node + linkType: hard + +"@sapphire/async-queue@npm:^1.5.0": + version: 1.5.0 + resolution: "@sapphire/async-queue@npm:1.5.0" + checksum: 983dbd1fd1b1798496e5edb6a0db7e4d90015160e1028f20475eab0a92625513f1e8d938bc0305811a9cec461c94e01b1e4191615ff03ba49356f568f3255250 + languageName: node + linkType: hard + +"@sapphire/shapeshift@npm:^3.5.1": + version: 3.5.1 + resolution: "@sapphire/shapeshift@npm:3.5.1" + dependencies: + fast-deep-equal: ^3.1.3 + lodash.uniqwith: ^4.5.0 + checksum: caecfef844c9e43e921a5051da888fae7da8980bfd9f9bb4f7fee85931d40929ffb9b6dfae464c0dccee61e56f7698f998e4d9a54d25f35fad39a51ba1a4f391 + languageName: node + linkType: hard + +"@sapphire/snowflake@npm:^3.2.2": + version: 3.2.2 + resolution: "@sapphire/snowflake@npm:3.2.2" + checksum: 315fecef4738092c2a2f3509b132b811fcbfa6c98d5d45d951adaf3ca21608be69043bcc137cc6933a7c3e55cbdc066daa5bb484603e6575422b335445b59315 + languageName: node + linkType: hard + +"@tokenizer/token@npm:^0.3.0": + version: 0.3.0 + resolution: "@tokenizer/token@npm:0.3.0" + checksum: 1d575d02d2a9f0c5a4ca5180635ebd2ad59e0f18b42a65f3d04844148b49b3db35cf00b6012a1af2d59c2ab3caca59451c5689f747ba8667ee586ad717ee58e1 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 18.7.13 + resolution: "@types/node@npm:18.7.13" + checksum: 45431e7e89ecaf85c7d2c180d801c132a7c59e2f8ad578726b6d71cc74e3267c18f9ccdcad738bc0479790c078f0c79efb0e58da2c6be535c15995dbb19050c9 + languageName: node + linkType: hard + +"@types/ws@npm:^8.5.3": + version: 8.5.3 + resolution: "@types/ws@npm:8.5.3" + dependencies: + "@types/node": "*" + checksum: 0ce46f850d41383fcdc2149bcacc86d7232fa7a233f903d2246dff86e31701a02f8566f40af5f8b56d1834779255c04ec6ec78660fe0f9b2a69cf3d71937e4ae + languageName: node + linkType: hard + +"discord-api-types@npm:^0.37.3": + version: 0.37.4 + resolution: "discord-api-types@npm:0.37.4" + checksum: 18b74acfcd5f6c554668eb5cb31a5db9076dfb5cb6b5c538a342ab9d22816644bada22a66285468fe7dd9980287921d5d50ba3b11cc8e391fe4f09e761bcd179 + languageName: node + linkType: hard + +"discord.js@npm:14.3.0": + version: 14.3.0 + resolution: "discord.js@npm:14.3.0" + dependencies: + "@discordjs/builders": ^1.2.0 + "@discordjs/collection": ^1.1.0 + "@discordjs/rest": ^1.1.0 + "@sapphire/snowflake": ^3.2.2 + "@types/ws": ^8.5.3 + discord-api-types: ^0.37.3 + fast-deep-equal: ^3.1.3 + lodash.snakecase: ^4.1.1 + tslib: ^2.4.0 + undici: ^5.9.1 + ws: ^8.8.1 + checksum: e45117549d8d504eae958cb104a42dd3903f67ae0c3062fdc60c748a2a21da14a32ec3c9643edcebe568d82602f0b2efc3b9af59d1482ac1304ce4aaeda944a2 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d + languageName: node + linkType: hard + +"file-type@npm:^17.1.6": + version: 17.1.6 + resolution: "file-type@npm:17.1.6" + dependencies: + readable-web-to-node-stream: ^3.0.2 + strtok3: ^7.0.0-alpha.9 + token-types: ^5.0.0-alpha.2 + checksum: 797e0d155ecaf4b575d4569a0188bfed85af19d18cf3d93ec8bb66d797172a1fde9f13d56135c6a0b471cacd7ecc1adb0c9a45c6e3a19436f682a275d0be16cc + languageName: node + linkType: hard + +"ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e + languageName: node + linkType: hard + +"inherits@npm:^2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 + languageName: node + linkType: hard + +"lodash.snakecase@npm:^4.1.1": + version: 4.1.1 + resolution: "lodash.snakecase@npm:4.1.1" + checksum: 1685ed3e83dda6eae5a4dcaee161a51cd210aabb3e1c09c57150e7dd8feda19e4ca0d27d0631eabe8d0f4eaa51e376da64e8c018ae5415417c5890d42feb72a8 + languageName: node + linkType: hard + +"lodash.uniqwith@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.uniqwith@npm:4.5.0" + checksum: d49a4565ed64efd86674127d321622673c29cde3e060baebc0f30372f22886c61b2ead44709db8c890053db1b9660e8ed689689812c1a485eb5703caa94d1150 + languageName: node + linkType: hard + +"peek-readable@npm:^5.0.0": + version: 5.0.0 + resolution: "peek-readable@npm:5.0.0" + checksum: bef5ceb50586eb42e14efba274ac57ffe97f0ed272df9239ce029f688f495d9bf74b2886fa27847c706a9db33acda4b7d23bbd09a2d21eb4c2a54da915117414 + languageName: node + linkType: hard + +"readable-stream@npm:^3.6.0": + version: 3.6.0 + resolution: "readable-stream@npm:3.6.0" + dependencies: + inherits: ^2.0.3 + string_decoder: ^1.1.1 + util-deprecate: ^1.0.1 + checksum: d4ea81502d3799439bb955a3a5d1d808592cf3133350ed352aeaa499647858b27b1c4013984900238b0873ec8d0d8defce72469fb7a83e61d53f5ad61cb80dc8 + languageName: node + linkType: hard + +"readable-web-to-node-stream@npm:^3.0.2": + version: 3.0.2 + resolution: "readable-web-to-node-stream@npm:3.0.2" + dependencies: + readable-stream: ^3.6.0 + checksum: 8c56cc62c68513425ddfa721954875b382768f83fa20e6b31e365ee00cbe7a3d6296f66f7f1107b16cd3416d33aa9f1680475376400d62a081a88f81f0ea7f9c + languageName: node + linkType: hard + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + dependencies: + discord.js: 14.3.0 + languageName: unknown + linkType: soft + +"safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: ~5.2.0 + checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 + languageName: node + linkType: hard + +"strtok3@npm:^7.0.0-alpha.9": + version: 7.0.0 + resolution: "strtok3@npm:7.0.0" + dependencies: + "@tokenizer/token": ^0.3.0 + peek-readable: ^5.0.0 + checksum: 2ebe7ad8f2aea611dec6742cf6a42e82764892a362907f7ce493faf334501bf981ce21c828dcc300457e6d460dc9c34d644ededb3b01dcb9e37559203cf1748c + languageName: node + linkType: hard + +"token-types@npm:^5.0.0-alpha.2": + version: 5.0.1 + resolution: "token-types@npm:5.0.1" + dependencies: + "@tokenizer/token": ^0.3.0 + ieee754: ^1.2.1 + checksum: 32780123bc6ce8b6a2231d860445c994a02a720abf38df5583ea957aa6626873cd1c4dd8af62314da4cf16ede00c379a765707a3b06f04b8808c38efdae1c785 + languageName: node + linkType: hard + +"ts-mixer@npm:^6.0.1": + version: 6.0.1 + resolution: "ts-mixer@npm:6.0.1" + checksum: 7050f6e85a24155d18cecdcc0a098d1038991cc498317fcffa9d7a8654c776d417fb97e65de1ce8e7ed54ef4814abd8057d0efb9c3b24e9cc78ac3c0f48bbf53 + languageName: node + linkType: hard + +"tslib@npm:^2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: 8c4aa6a3c5a754bf76aefc38026134180c053b7bd2f81338cb5e5ebf96fefa0f417bff221592bf801077f5bf990562f6264fecbc42cd3309b33872cb6fc3b113 + languageName: node + linkType: hard + +"undici@npm:^5.9.1": + version: 5.10.0 + resolution: "undici@npm:5.10.0" + checksum: 7ba2b71dccc74cd2bdf645b83e9aaef374ae04855943d0a2f42a3d0b9e5556f37cc9b5156fb5288277a2fa95fd46a56f3ae0d5cf73db3f008d75ec41104b136c + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + languageName: node + linkType: hard + +"ws@npm:^8.8.1": + version: 8.8.1 + resolution: "ws@npm:8.8.1" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 2152cf862cae0693f3775bc688a6afb2e989d19d626d215e70f5fcd8eb55b1c3b0d3a6a4052905ec320e2d7734e20aeedbf9744496d62f15a26ad79cf4cf7dae + languageName: node + linkType: hard diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 00f36fe8272b..4541cd44d6e0 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -545,7 +545,6 @@ export default class Runtime { referencingIdentifier, specifier, this._explicitShouldMockModule, - {conditions: this.esmConditions}, ) ) { return this.importMock(referencingIdentifier, specifier, context); @@ -631,15 +630,12 @@ export default class Runtime { referencingIdentifier, path, this._explicitShouldMockModule, - {conditions: this.esmConditions}, ) ) { return this.importMock(referencingIdentifier, path, context); } - const resolved = await this._resolveModule(referencingIdentifier, path, { - conditions: this.esmConditions, - }); + const resolved = await this._resolveModule(referencingIdentifier, path); if ( this._resolver.isCoreModule(resolved) || @@ -697,9 +693,7 @@ export default class Runtime { const [path, query] = (moduleName ?? '').split('?'); - const modulePath = await this._resolveModule(from, path, { - conditions: this.esmConditions, - }); + const modulePath = await this._resolveModule(from, path); const module = await this.loadEsmModule(modulePath, query); @@ -792,9 +786,7 @@ export default class Runtime { const namedExports = new Set(exports); reexports.forEach(reexport => { - const resolved = this._resolveCjsModule(modulePath, reexport, { - conditions: this.esmConditions, - }); + const resolved = this._resolveCjsModule(modulePath, reexport); const exports = this.getExportsOfCjs(resolved); @@ -845,9 +837,7 @@ export default class Runtime { } if (!modulePath) { - modulePath = this._resolveCjsModule(from, moduleName, { - conditions: this.cjsConditions, - }); + modulePath = this._resolveCjsModule(from, moduleName); } if (this.unstable_shouldLoadAsEsm(modulePath)) { @@ -960,9 +950,7 @@ export default class Runtime { let modulePath = this._resolver.getMockModule(from, moduleName) || - this._resolveCjsModule(from, moduleName, { - conditions: this.cjsConditions, - }); + this._resolveCjsModule(from, moduleName); let isManualMock = manualMockOrStub && @@ -1066,11 +1054,7 @@ export default class Runtime { } try { - if ( - this._shouldMockCjs(from, moduleName, this._explicitShouldMock, { - conditions: this.cjsConditions, - }) - ) { + if (this._shouldMockCjs(from, moduleName, this._explicitShouldMock)) { return this.requireMock(from, moduleName); } else { return this.requireModule(from, moduleName); @@ -1305,20 +1289,20 @@ export default class Runtime { this.isTornDown = true; } - private _resolveCjsModule( - from: string, - to: string | undefined, - options?: ResolveModuleConfig, - ) { - return to ? this._resolver.resolveModule(from, to, options) : from; + private _resolveCjsModule(from: string, to: string | undefined) { + return to + ? this._resolver.resolveModule(from, to, { + conditions: this.cjsConditions, + }) + : from; } - private _resolveModule( - from: string, - to: string | undefined, - options?: ResolveModuleConfig, - ) { - return to ? this._resolver.resolveModuleAsync(from, to, options) : from; + private _resolveModule(from: string, to: string | undefined) { + return to + ? this._resolver.resolveModuleAsync(from, to, { + conditions: this.esmConditions, + }) + : from; } private _requireResolve( @@ -1366,9 +1350,7 @@ export default class Runtime { } try { - return this._resolveCjsModule(from, moduleName, { - conditions: this.cjsConditions, - }); + return this._resolveCjsModule(from, moduleName); } catch (err) { const module = this._resolver.getMockModule(from, moduleName); @@ -1731,9 +1713,7 @@ export default class Runtime { private _generateMock(from: string, moduleName: string) { const modulePath = this._resolver.resolveStubModuleName(from, moduleName) || - this._resolveCjsModule(from, moduleName, { - conditions: this.cjsConditions, - }); + this._resolveCjsModule(from, moduleName); if (!this._mockMetaDataCache.has(modulePath)) { // This allows us to handle circular dependencies while generating an // automock @@ -1777,8 +1757,8 @@ export default class Runtime { from: string, moduleName: string, explicitShouldMock: Map, - options: ResolveModuleConfig, ): boolean { + const options: ResolveModuleConfig = {conditions: this.cjsConditions}; const moduleID = this._resolver.getModuleID( this._virtualMocks, from, @@ -1807,7 +1787,7 @@ export default class Runtime { let modulePath; try { - modulePath = this._resolveCjsModule(from, moduleName, options); + modulePath = this._resolveCjsModule(from, moduleName); } catch (e) { const manualMock = this._resolver.getMockModule(from, moduleName); if (manualMock) { @@ -1848,8 +1828,8 @@ export default class Runtime { from: string, moduleName: string, explicitShouldMock: Map, - options: ResolveModuleConfig, ): Promise { + const options: ResolveModuleConfig = {conditions: this.esmConditions}; const moduleID = await this._resolver.getModuleIDAsync( this._virtualMocks, from, @@ -1878,7 +1858,7 @@ export default class Runtime { let modulePath; try { - modulePath = await this._resolveModule(from, moduleName, options); + modulePath = await this._resolveModule(from, moduleName); } catch (e) { const manualMock = await this._resolver.getMockModuleAsync( from,