Skip to content

Commit 0c0e9f0

Browse files
OskarEichlermeta-codesync[bot]
authored andcommitted
Guard private syntax preservation by transform profile (#58253)
Summary: `customTransformOptions.unstable_preserveClassPrivate` currently disables private-field and private-method transforms for every profile. With `hermes-legacy`, the preset still lowers the surrounding class syntax, and Babel then aborts because its class transform requires the private transforms. Only preserve private syntax when the selected profile also preserves class syntax. Stable and canary Hermes profiles keep their existing experimental behavior; legacy profiles continue lowering private fields and methods together with classes instead of crashing. ## Changelog: [GENERAL] [FIXED] - Keep private class transforms enabled for profiles that lower classes. Pull Request resolved: #58253 Test Plan: - Added a focused `hermes-legacy` regression containing both a private field and private method with the preservation option enabled. - Exact baseline throws Babel's private-method transform error; the fixed preset compiles and emits the normal private-field helpers. - Full preset Jest passes: 4/4 suites, 111/111 tests, 16 snapshots. - Fresh Flow check reports 0 errors. - Targeted no-ignore ESLint, Prettier, and `git diff --check` pass. No breaking change: stable/canary preservation is unchanged, while an invalid legacy configuration now compiles correctly. Reviewed By: javache Differential Revision: D118438778 Pulled By: vzaidman fbshipit-source-id: 650a70d8759b135cb06f9bd3f2b45b0ee766762b
1 parent bbdeb7d commit 0c0e9f0

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

packages/react-native-babel-preset/src/__tests__/transform-snapshot-test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,25 @@ describe('react-native-babel-preset transform snapshots', () => {
490490
expect(result).toContain('_classPrivateFieldLooseKey');
491491
});
492492

493+
it('transforms private class fields when the profile lowers classes', () => {
494+
const code = `
495+
class Counter {
496+
#count = 0;
497+
#privateMethod() { return this.#count; }
498+
}
499+
`;
500+
const result = transformCode(code, {
501+
dev: false,
502+
unstable_transformProfile: 'hermes-legacy',
503+
customTransformOptions: {
504+
unstable_preserveClassPrivate: true,
505+
},
506+
});
507+
expect(result).not.toContain('#count');
508+
expect(result).not.toContain('#privateMethod');
509+
expect(result).toContain('_classPrivateFieldLooseKey');
510+
});
511+
493512
it('preserves async/await with unstable_preserveAsync', () => {
494513
const code = `
495514
async function fetchData() {

packages/react-native-babel-preset/src/configs/main.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,13 @@ const getPreset = (src, options, babel) => {
9898
// Preserve class syntax and related features for Hermes V1 profiles.
9999
const preserveClasses = isHermesProfile;
100100

101-
// Preserve private class fields and methods if the experiment is enabled.
102-
const preserveClassPrivate = TRUE_VALS.has(
103-
options.customTransformOptions?.unstable_preserveClassPrivate,
104-
);
101+
// Private fields can only be preserved when the surrounding class syntax is
102+
// also preserved. Babel's class transform requires the private transforms.
103+
const preserveClassPrivate =
104+
preserveClasses &&
105+
TRUE_VALS.has(
106+
options.customTransformOptions?.unstable_preserveClassPrivate,
107+
);
105108

106109
// Preserve async/await syntax if the experiment is enabled.
107110
const preserveAsync = TRUE_VALS.has(

0 commit comments

Comments
 (0)