node icon indicating copy to clipboard operation
node copied to clipboard

module: unflag detect-module

Open GeoffreyBooth opened this issue 1 year ago • 5 comments

This is a draft PR to unflag --experimental-detect-module. I’m labeling it as don’t land for all current lines unless and until we determine that this isn’t a semver-major change; it should be okay to release as part of 23.0.0, and after that we can decide whether or not to backport.

This PR specifically does two things:

  • It turns the --experimental-detect-module flag into a noop similar to --experimental-modules.
  • Per https://github.com/nodejs/node/pull/53044#issuecomment-2195881734 this PR changes the format hint returned by Node’s internal resolve for ambiguous (no package.json type field, no .mjs or .cjs extension) files from commonjs to undefined. This is more correct, as the format hasn’t yet been determined at the time of resolution, because with detection enabled we need to load the source and parse it to detect the format.

I also updated the tests (with one exception: https://github.com/nodejs/node/issues/53634) because of the unflagging:

Not breaking changes

  • test/es-module/test-esm-cjs-exports.js should error on invalid CJS exports: Previously this was testing for the error strings Warning: To load an ES module and Unexpected token \'export\'; now it tests for the error string SyntaxError: The requested module './invalid-cjs.js' does not provide an export named 'default'. Arguably the new version is more appropriate as it’s testing the actual thing the test describes rather than testing an error that was thrown before getting to the invalid CommonJS exports.

  • test/es-module/test-esm-import-flag.mjs should import when running --check fails: This test checks that an ESM file passed to --import is evaluated with a CommonJS entry passed to --check fails the syntax check. The file passed to --import is run in both cases, though the previous SyntaxError is now a success; but the point of the test is about the --import file being evaluated at all, not whether its evaluation was successful.

  • test/es-module/test-require-module-implicit.js: Some tests were attempting to require an ambiguous, extensionless ESM file and expecting an exception with Unexpected token 'export'. These tests were removed. This file is run via --experimental-require-module so this change shouldn’t be considered breaking.

Possibly breaking changes

  • test/es-module/test-esm-detect-ambiguous.mjs should not hint wrong format in resolve hook: Previously this expected a format hint of commonjs from a resolve hook, and now it expects undefined, an intentional change. The hooks are still experimental and the format hint from resolve is documented as optional, so hooks should be written to expect it not to be present; but the unflagging would cause some code that currently returns a hint to no longer do so.

  • test/es-module/test-esm-loader-hooks.mjs should use ESM loader to respond to require.resolve calls when opting in: The load hook in this test previously assumed that most files being imported got a format of commonjs, whereas now many of them are undefined, an intentional change. Same impact as previous.

  • test/es-module/test-esm-resolve-type.mjs: Some tests for a format hint of commonjs now check for a format hint of undefined. Same impact as previous.

  • test/es-module/test-esm-extensionless-esm-and-wasm.mjs: extensionless ES modules within no package scope: tests for ambiguous extensionless ESM running as the entry point and ambugious extensionless ESM running via import() used to test for exceptions being thrown; now they test for success. Anyone expecting exceptions on running or importing ambiguous or extensionless ESM (for example, to do detection themselves) will be broken by this change.

GeoffreyBooth avatar Jun 28 '24 05:06 GeoffreyBooth

Review requested:

  • [ ] @nodejs/loaders

nodejs-github-bot avatar Jun 28 '24 05:06 nodejs-github-bot

Regarding the module mocking - the mock loader (lib/test/mock_loader.js) uses that information to determine whether to generate source code in CJS or ESM. I think there are a few options to fix it:

  • Maybe it doesn't really matter and it can be removed?
  • Pick a default when the hint is undefined.
  • Make it an option that the user can provide as input.

cjihrig avatar Jun 28 '24 13:06 cjihrig

I wonder for hook users relying on the inaccurate context.format whether they should just do const format = context.format || 'commonjs' because that's normally how it goes. Or we could just maintain an "tentative format" internally in addition to the existing format which is more like "confirmed format" and maintain context.format as the "tentative format", while adding context.confirmedFormat or something that carries around format information that are confirmed by the previous resolution & won't incur any further detection in the default load step (and it would be undefined for format that are pending detection and can only be confirmed after the source code is final).

joyeecheung avatar Jun 28 '24 15:06 joyeecheung

Regarding the module mocking . . . I think there are a few options to fix it:

I think the mocking thing might need a change to the mocking feature itself, more than just a test update, so I created https://github.com/nodejs/node/issues/53634 to discuss the various approaches.

GeoffreyBooth avatar Jun 28 '24 21:06 GeoffreyBooth

Update: I figured out the require.resolve test. The load hook had an if (result.format === 'commonjs') condition that needed updating to allow for an undefined format. Now all that remains is https://github.com/nodejs/node/issues/53634.

I’ve updated the top post with a list of tests that were updated, grouped by whether I think they should be considered nonbreaking or might be considered breaking.

GeoffreyBooth avatar Jun 29 '24 03:06 GeoffreyBooth

With https://github.com/nodejs/node/pull/53642 landed, now all the tests pass. This is ready for review.

Assuming we think this is ready to land, the other question we need to answer is how to release it. I updated the top post with my analysis of each changed test and whether the change might be considered breaking or not; basically I think three are definitely not breaking and three are arguably breaking but possibly not. I’m curious to hear what others think. If we think that some of these arguably breaking ones are breaking, then detection can only be unflagged in >23; otherwise I think this should be acceptable to backport.

We can always land it in 23.0.0 first to see the reaction and only backport it afterward, at the cost of delaying the rollout to the <23 lines until November at the earliest.

GeoffreyBooth avatar Jul 04 '24 15:07 GeoffreyBooth

CI: https://ci.nodejs.org/job/node-test-pull-request/60079/

nodejs-github-bot avatar Jul 04 '24 15:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60154/

nodejs-github-bot avatar Jul 08 '24 06:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60161/

nodejs-github-bot avatar Jul 08 '24 12:07 nodejs-github-bot

  • It turns the --experimental-detect-module flag into a noop similar to --experimental-modules.

If we think that some of these arguably breaking ones are breaking, then detection can only be unflagged in >23; otherwise I think this should be acceptable to backport.

If we do decide this can be backported, instead of making the flag a noop, maybe swap the default so it defaults to being enabled but can still be disabled via --no-experimental-detect-module?

richardlau avatar Jul 08 '24 17:07 richardlau

If we do decide this can be backported, instead of making the flag a noop, maybe swap the default so it defaults to being enabled but can still be disabled via --no-experimental-detect-module?

It wouldn’t be experimental anymore, so I guess the flags would be --detect-module / --no-detect-module, but yes it’s an option. I’d need to redo this PR to preserve the references to the flag and just change the default, but I could do that.

The first three tests under “Possibly breaking changes” all concern the module customization hooks, which are themselves experimental, so I think that those changes are fair game. It’s the last one, where import(fixtures.fileURL('es-modules/noext-esm')) and node ./test/fixtures/es-modules/noext-esm would previously error and now they work, that is the one that I’m unsure about. Reading https://github.com/nodejs/node/blob/main/doc/contributing/collaborator-guide.md#breaking-changes, is something that used to error changing to no longer error considered a breaking change?

GeoffreyBooth avatar Jul 08 '24 17:07 GeoffreyBooth

It wouldn’t be experimental anymore, so I guess the flags would be --detect-module / --no-detect-module, but yes it’s an option.

You can keep the experimental alias and add a non-prefixed one, I think we did that for other experimental flags too.

joyeecheung avatar Jul 09 '24 13:07 joyeecheung

I’ve updated the docs. What are we thinking re backporting and flags?

  1. Unflag it in 23.0.0, wait a bit to see if anyone complains, then backport the unflagging.
  2. Unflag it in 22.x and hope for the best, wait for reaction and then continue backporting the unflagging.
  3. Unflag it in 23.0.0 and also create a new flag --no-detect-module to disable it; wait for reaction and then backport.
  4. Unflag it in 22.x and also create a new flag --no-detect-module to disable it; wait for reaction and then continue backporting.
  5. Rename the flag to --detect-module, land that in 22.x and below, flip the default in 23.0.0 (so >=23 would have --no-detect-module to disable).
  6. Other options?

GeoffreyBooth avatar Jul 09 '24 22:07 GeoffreyBooth

Per discussion in https://github.com/nodejs/TSC/issues/1592, adding this to the agenda to be discussed more in the next TSC meeting.

I think we have a tentative consensus to:

  • Keep the --experimental-detect-module / --no-experimental-detect-module flags, but flip the default from the current off by default to on by default. (So I’ll change this PR, which turns the flag into a noop, into just a change of default.)
  • Land on 22.

I’ll leave this open until next week’s TSC meeting.

GeoffreyBooth avatar Jul 10 '24 15:07 GeoffreyBooth

I’ll change this PR, which turns the flag into a noop, into just a change of default.

I’ve implemented this change, if folks would be so kind to review. I’ll leave this open until Wednesday regardless.

GeoffreyBooth avatar Jul 11 '24 22:07 GeoffreyBooth

CI: https://ci.nodejs.org/job/node-test-pull-request/60285/

nodejs-github-bot avatar Jul 13 '24 01:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60292/

nodejs-github-bot avatar Jul 14 '24 04:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60293/

nodejs-github-bot avatar Jul 14 '24 04:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60315/

nodejs-github-bot avatar Jul 14 '24 18:07 nodejs-github-bot

@aduh95 I moved the format refactoring into a separate commit on this PR’s branch. How about we land via commit-queue-rebase to put both commits on main, rather than splitting into two PRs?

If that’s okay with you, I think I’ve resolved all your notes.

GeoffreyBooth avatar Jul 15 '24 04:07 GeoffreyBooth

CI: https://ci.nodejs.org/job/node-test-pull-request/60322/

nodejs-github-bot avatar Jul 15 '24 04:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60468/

nodejs-github-bot avatar Jul 20 '24 10:07 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/60471/

nodejs-github-bot avatar Jul 20 '24 13:07 nodejs-github-bot

Landed in 604ce4cc666eb70df2697bab3e007815853b4b8f

nodejs-github-bot avatar Jul 20 '24 18:07 nodejs-github-bot

notable-change and/or semver-<minor/major>?

avivkeller avatar Jul 20 '24 18:07 avivkeller

The https://github.com/nodejs/node/labels/notable-change label has been added by @GeoffreyBooth.

Please suggest a text for the release notes if you'd like to include a more detailed summary, then proceed to update the PR description with the text or a link to the notable change suggested text comment. Otherwise, the commit will be placed in the Other Notable Changes section.

github-actions[bot] avatar Jul 20 '24 22:07 github-actions[bot]

I love to see this.

oliviertassinari avatar Aug 28 '24 17:08 oliviertassinari

Backport in https://github.com/nodejs/node/pull/56927

joyeecheung avatar Feb 06 '25 00:02 joyeecheung