Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow JSON imports in NodeJS 16.15 #1792

Merged
merged 5 commits into from Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions dist-raw/node-internal-modules-esm-get_format.js
Expand Up @@ -12,6 +12,7 @@ const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(s => parseIn
const experimentalJsonModules =
nodeMajor > 17
|| (nodeMajor === 17 && nodeMinor >= 5)
|| (nodeMajor === 16 && nodeMinor >= 15)
|| getOptionValue('--experimental-json-modules');
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
const { URL, fileURLToPath } = require('url');
Expand Down
64 changes: 33 additions & 31 deletions src/test/esm-loader.spec.ts
Expand Up @@ -15,10 +15,13 @@ import {
EXPERIMENTAL_MODULES_FLAG,
nodeSupportsEsmHooks,
nodeSupportsImportAssertions,
nodeSupportsUnflaggedJsonImports,
nodeSupportsSpawningChildProcess,
nodeUsesNewHooksApi,
resetNodeEnvironment,
TEST_DIR,
tsSupportsImportAssertions,
tsSupportsResolveJsonModule,
} from './helpers';
import { createExec, createSpawn, ExecReturn } from './exec-helpers';
import { join, resolve } from 'path';
Expand Down Expand Up @@ -268,40 +271,39 @@ test.suite('esm', (test) => {
});

test.suite('supports import assertions', (test) => {
test.runIf(nodeSupportsImportAssertions);

test.suite('node >=17.5.0', (test) => {
test.runIf(semver.gte(process.version, '17.5.0'));
test.runIf(
nodeSupportsImportAssertions &&
tsSupportsImportAssertions &&
tsSupportsResolveJsonModule
);

test('Can import JSON modules with appropriate assertion', async (t) => {
const { err, stdout } = await exec(
`${CMD_ESM_LOADER_WITHOUT_PROJECT} ./importJson.ts`,
{
cwd: resolve(TEST_DIR, 'esm-import-assertions'),
}
);
expect(err).toBe(null);
expect(stdout.trim()).toBe(
'A fuchsia car has 2 seats and the doors are open.\nDone!'
);
});
const macro = test.macro((flags: string) => async (t) => {
const { err, stdout } = await exec(
`${CMD_ESM_LOADER_WITHOUT_PROJECT} ${flags} ./importJson.ts`,
{
cwd: resolve(TEST_DIR, 'esm-import-assertions'),
}
);
expect(err).toBe(null);
expect(stdout.trim()).toBe(
'A fuchsia car has 2 seats and the doors are open.\nDone!'
);
});

test.suite('node <17.5.0', (test) => {
test.runIf(semver.lt(process.version, '17.5.0'));

test('Can import JSON using the appropriate flag and assertion', async (t) => {
const { err, stdout } = await exec(
`${CMD_ESM_LOADER_WITHOUT_PROJECT} --experimental-json-modules ./importJson.ts`,
{
cwd: resolve(TEST_DIR, 'esm-import-assertions'),
}
);
expect(err).toBe(null);
expect(stdout.trim()).toBe(
'A fuchsia car has 2 seats and the doors are open.\nDone!'
);
});
test.suite(
'when node does not require --experimental-json-modules',
(test) => {
test.runIf(nodeSupportsUnflaggedJsonImports);
test('Can import JSON modules with appropriate assertion', macro, '');
}
);
test.suite('when node requires --experimental-json-modules', (test) => {
test.runIf(!nodeSupportsUnflaggedJsonImports);
test(
'Can import JSON using the appropriate flag and assertion',
macro,
'--experimental-json-modules'
);
});
});

Expand Down
19 changes: 15 additions & 4 deletions src/test/helpers.ts
Expand Up @@ -64,10 +64,19 @@ export const nodeSupportsSpawningChildProcess = semver.gte(
'12.17.0'
);
export const nodeUsesNewHooksApi = semver.gte(process.version, '16.12.0');
export const nodeSupportsImportAssertions = semver.gte(
process.version,
'17.1.0'
);
// 16.14.0: https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V16.md#notable-changes-4
// 17.1.0: https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V17.md#2021-11-09-version-1710-current-targos
export const nodeSupportsImportAssertions =
(semver.gte(process.version, '16.14.0') &&
semver.lt(process.version, '17.0.0')) ||
semver.gte(process.version, '17.1.0');
// These versions do not require `--experimental-json-modules`
// 16.15.0: https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V16.md#2022-04-26-version-16150-gallium-lts-danielleadams
// 17.5.0: https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V17.md#2022-02-10-version-1750-current-ruyadorno
export const nodeSupportsUnflaggedJsonImports =
(semver.gte(process.version, '16.15.0') &&
semver.lt(process.version, '17.0.0')) ||
semver.gte(process.version, '17.5.0');
// Node 14.13.0 has a bug where it tries to lex CJS files to discover named exports *before*
// we transform the code.
// In other words, it tries to parse raw TS as CJS and balks at `export const foo =`, expecting to see `exports.foo =`
Expand All @@ -76,6 +85,7 @@ export const nodeSupportsImportingTransformedCjsFromEsm = semver.gte(
process.version,
'14.13.1'
);
export const tsSupportsResolveJsonModule = semver.gte(ts.version, '2.9.0');
/** Supports tsconfig "extends" >= v3.2.0 */
export const tsSupportsTsconfigInheritanceViaNodePackages = semver.gte(
ts.version,
Expand All @@ -88,6 +98,7 @@ export const tsSupportsStableNodeNextNode16 =
ts.version.startsWith('4.7.') || semver.gte(ts.version, '4.7.0');
// TS 4.5 is first version to understand .cts, .mts, .cjs, and .mjs extensions
export const tsSupportsMtsCtsExtensions = semver.gte(ts.version, '4.5.0');
export const tsSupportsImportAssertions = semver.gte(ts.version, '4.5.0');
//#endregion

export const xfs = new NodeFS(fs);
Expand Down