Skip to content

Babel preset: Stop lowering Unicode regexes for Hermes V1 - #59580

Merged
javache merged 1 commit into
mainfrom
robhogan/babel-preset-hermes-unicode-regex
Oct 28, 2026
Merged

javache merged 1 commit into
mainfrom
robhogan/babel-preset-hermes-unicode-regex

Conversation

@robhogan

Copy link
Copy Markdown
Collaborator

Summary

The Hermes profiles still run @babel/plugin-transform-unicode-regex, which rewrites every u-flag regex into one without the flag. For Unicode property escapes, that means expanding a \p{L} into kilobytes of explicit ranges and surrogate pairs. Hermes V1 compiles u regexes natively, so the expansion only costs bytecode size, memory and speed.

The hermes-legacy and default (JSC) profiles keep the transform.

Impact

Entirely dependent on use of these regexs, many apps won't use them, some libraries use them extensively. The snapshot changes in this PR illustrate the difference.

  • Bytecode: -75 KB (-0.30%) in Mattermost mobile. Hermes keeps each regex's source text for RegExp.prototype.source, so an expanded pattern is paid for in string storage as well as in regex bytecode.
  • Memory: -584 KB of live JS heap and -205 KB of native regex bytecode (copied into every RegExp object) after loading highlight.js, fuse.js, path-to-regexp and zod, which build regexes from \p{...} classes.
  • Speed: regex-bound library code is faster natively, by up to 17% (fuse.js index build -16%, zod's unicodeEmail -13%, first highlight.js highlight 12.5 ms -> 8 ms). The one slower case was path-to-regexp route compilation, at +1.0-1.3%.

Test plan

  • Aligns with Expo's existing behaviour
  • Every \p{...} spelling the transform accepts (1,647 property names, values and aliases from regenerate-unicode-properties) compiles and runs in Hermes active stable (260318099.0.4) .
  • Launched and tested Mattermost's use.

Note: natively compiled property escapes follow the engine's Unicode data rather than Babel's, so results can differ only for characters assigned in one Unicode version and not the other.

Changelog

[General][Changed] - Babel preset: Hermes V1 profiles no longer lower u-flag regexes, which Hermes compiles natively

The Hermes profiles still run `@babel/plugin-transform-unicode-regex`, which rewrites every `u`-flag regex into one without the flag. For Unicode property escapes, that means expanding a `\p{L}` into kilobytes of explicit ranges and surrogate pairs. Hermes V1 compiles `u` regexes natively, so the expansion only costs bytecode size, memory and speed:

- Bytecode: -64 KB (-0.67%) in a 9.5 MB RN 0.88 test app, and -75 KB (-0.30%) in Mattermost mobile. Hermes keeps each regex's source text for `RegExp.prototype.source`, so an expanded pattern is paid for in string storage as well as in regex bytecode.
- Memory: -584 KB of live JS heap and -205 KB of native regex bytecode (copied into every `RegExp` object) after loading highlight.js, fuse.js, path-to-regexp and zod, which build regexes from `\p{...}` classes.
- Speed: regex-bound library code is faster natively, by up to 17% (fuse.js index build -16%, zod's `unicodeEmail` -13%, first highlight.js highlight 12.5 ms -> 8 ms). The one slower case was path-to-regexp route compilation, at +1.0-1.3%.

Every `\p{...}` spelling the transform accepts (1,647 property names, values and aliases from `regenerate-unicode-properties`) compiles with the hermesc that RN 0.88 ships (260318099.0.4) and runs in Hermes V1. Natively compiled property escapes follow the engine's Unicode data rather than Babel's, so results can differ only for characters assigned in one Unicode version and not the other. The `hermes-legacy` and `default` profiles keep the transform.

Full analysis: https://robhogan.github.io/reports/react-native-babel-preset-hbc-size/

Changelog: [General][Changed] - Babel preset: Hermes V1 profiles no longer lower `u`-flag regexes, which Hermes compiles natively
@robhogan
robhogan requested review from javache and vzaidman October 28, 2026 16:44
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 28, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 28, 2026
@meta-codesync

meta-codesync Bot commented Oct 28, 2026

Copy link
Copy Markdown

@javache has imported this pull request. If you are a Meta employee, you can view this in D128117415.

@javache
javache merged commit 92629fd into main Oct 28, 2026
63 of 65 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants