Skip to content

[breaking] Change the API to choose which features to compile #49

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

Merged
merged 3 commits into from
Dec 21, 2021

Conversation

nicolo-ribaudo
Copy link
Collaborator

@nicolo-ribaudo nicolo-ribaudo commented Aug 13, 2021

The more we move into the future, the less users will need to compile old regular expression features. However, configuring regexpu-core to only compile some specific features is quite hard. This proposal aims to simplify how the options behave and interact.


Every new syntax feature could be handled in three possible ways:

  1. Compile it to older syntax
  2. Parse it and leave it as-is
  3. Don't parse it (throw an error)

Currently, every regexp feature is supported in a different way:

All these different options make it hard to configure regexpu-core. I propose a new options system, inspired by how Babel plugins work:

  • Stable ECMAScript features are parsed by default, and users can opt-in into the transform
  • ECMAScript proposals are not supported by default, and users can opt-in into parsing or transformation (Note: regexpu-core doesn't support any proposal at the moment)

This means that by default regexpu-core is a no-op (similarly to how Babel does nothing if there are no plugins), however it makes it easier to configure the expected transformation.


Closes #32, closes #37, closes #38, closes #39, closes #41, closes #42

cc @mathiasbynens @JLHwung opinions?

mathiasbynens
mathiasbynens previously approved these changes Aug 14, 2021
@mathiasbynens
Copy link
Owner

LGTM. This reminds me to spend some time automating the npm release process. I'll look into that next week.

@nicolo-ribaudo
Copy link
Collaborator Author

I'll start working on the implementation to see if there are any problems with this design

@nicolo-ribaudo nicolo-ribaudo dismissed mathiasbynens’s stale review August 15, 2021 16:19

I pushed the implementation to match the readme changed

update(characterClassItem, `(?!${set.toString(regenerateOptions)})[\\s\\S]`)
} else {
update(characterClassItem, set.toString(regenerateOptions));
if (transformed) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this check so that when not transforming the u flag, things like /[\uD806\uDCDF]/u are not modified.

tests/tests.js Outdated
@@ -588,14 +600,6 @@ describe('unicodePropertyEscapes', () => {
'(?:(?:\\uD838[\\uDEC0-\\uDEF9\\uDEFF]))'
);
});
it('throws without the `u` flag', () => {
assert.throws(() => {
rewritePattern('\\p{ASCII_Hex_Digit}', '', features);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/\p{ASCII_Hex_Digit}/ is a valid pattern, and it matches the string p{ASCII_Hex_Digit}.

@nicolo-ribaudo
Copy link
Collaborator Author

Uh I messed up singular/plural in options names. Do you prefer namedGroup/unicodePropertyEscape, or namedGroups/unicodePropertyEscapes?

@jridgewell
Copy link
Collaborator

I personally like plural names better, but as long as it's consistent either is fine.

demo.js Outdated
const processedPattern = rewritePattern(pattern, 'u', { useUnicodeFlag: true });
const processedPattern = rewritePattern(pattern, 'ui', {
'unicodeFlag': 'transform'
})
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
})
});

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want me to open a new PR to setup ESLint? Do you have a preferred config somewhere?

const validateOptions = (options) => {
if (!options) return;

for (const key of Object.keys(options)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about for (const [key, value] of Object.entries(options))?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package technically still supports Node.js 4. I wasn't going to propose to update it to Node.js 12 because Babel 7 still supports Node.js 6 too 😅

@mathiasbynens
Copy link
Owner

Uh I messed up singular/plural in options names. Do you prefer namedGroup/unicodePropertyEscape, or namedGroups/unicodePropertyEscapes?

Same answer as @jridgewell: plural names sound more natural IMHO but consistency is what matters most.

@nicolo-ribaudo
Copy link
Collaborator Author

I prefer plurals too 👍

@nicolo-ribaudo nicolo-ribaudo force-pushed the proposal-new-api branch 2 times, most recently from 8dd771d to 999bfaf Compare August 16, 2021 12:51
});
// → '[\\u{14400}-\\u{14646}]'
```
These options can be set to `false`, `'parse'` and `'transform'`. When using `'transform'`, the corresponding features are compiled to older syntax that can run in older browsers. When using `'parse'`, they are parsed and left as-is in the output pattern. When using `false` (the default), they result in a syntax error if used.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will become a breaking change when an experimental feature becomes stable. For example, let's say we have an imaginative option useSetNotation: boolean | 'parse' | 'transform' for RegExp Set Notation. Now if the proposal advanced to stage 4, regexpu-core will no longer throw for set notation syntax when people are using useSetNotation: false, because stable syntax are always parsed. But they may interpret useSetNotation: false as I want to target to a specific ecmascript version which does not support set notation and thus I disable the syntax. In this case I think it'd better to limit options to only 1) 'parse' and 'transform' or 2) false and transform, and when an experimental option is absent, we should not parse them at all. This approach is exactly how Babel handles features: when an experimental parser plugin is absent we assume users don't want to parse them at all. And when a feature materializes, the parser plugin becomes no-op.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, in Babel you can explicitly disable syntax plugins that are enabled somewhere else:

{
  "plugins": ["@babel/plugin-syntax-class-static-block"],
  "env": {
    "test": {
      "plugins": [
        ["@babel/plugin-syntax-class-static-block", false]
      ]
    }
  }
}

When running this with NODE_ENV=test, it will stop throwing in as soon as Babel enables parsing for static blocks by default.

In general, relaxing an error is never considered to be a breaking change. We might change the wording to be clear, but I think that the behavior is fine.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here. If it helps, I gotta admit that my initial reaction to the current three-value option was one of slight confusion -- I would have expected a simple binary switch (true/false) instead -- but then it made sense when I read the docs in this patch.

@mathiasbynens
Copy link
Owner

My LGTM still stands, so feel free to merge this whenever :) We can always iterate on the details later but let's not block on the options discussion.

@nicolo-ribaudo nicolo-ribaudo changed the title [breaking][proposal] Change the API to choose which features to compile [breaking] Change the API to choose which features to compile Dec 21, 2021
@nicolo-ribaudo nicolo-ribaudo merged commit c10651d into mathiasbynens:main Dec 21, 2021
@nicolo-ribaudo nicolo-ribaudo deleted the proposal-new-api branch December 21, 2021 18:53
ptomato added a commit to ptomato/test262 that referenced this pull request Nov 2, 2024
This code hasn't been touched in a while, so it's probably good to bring
in the newest versions of the dependencies. We can easily tell if there
was any incompatible effect on the output.

The latest version of filenamify requires using ES modules. We also have
to adapt to a breaking change in regexpu-core (see
mathiasbynens/regexpu-core#49).

Also convert the dependencies to devDependencies, since this tool is not
necessary for executing test262.
ptomato added a commit to ptomato/test262 that referenced this pull request Nov 12, 2024
This code hasn't been touched in a while, so it's probably good to bring
in the newest versions of the dependencies. We can easily tell if there
was any incompatible effect on the output.

The latest version of filenamify requires using ES modules. We also have
to adapt to a breaking change in regexpu-core (see
mathiasbynens/regexpu-core#49).

Also convert the dependencies to devDependencies, since this tool is not
necessary for executing test262.
ptomato added a commit to tc39/test262 that referenced this pull request Nov 12, 2024
This code hasn't been touched in a while, so it's probably good to bring
in the newest versions of the dependencies. We can easily tell if there
was any incompatible effect on the output.

The latest version of filenamify requires using ES modules. We also have
to adapt to a breaking change in regexpu-core (see
mathiasbynens/regexpu-core#49).

Also convert the dependencies to devDependencies, since this tool is not
necessary for executing test262.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

allow keep named group in pattern [breaking] Make "u" flag transformation opt-in rather than opt-out.
4 participants