Skip to content

Commit e072fe6

Browse files
committed
Merge main to resolve the already-landed E2E stack changes
2 parents 79a54ab + 8ca22ca commit e072fe6

24 files changed

Lines changed: 310 additions & 334 deletions

File tree

‎.github/workflows/maestro-cloud-rntester.yml‎

Lines changed: 0 additions & 99 deletions
This file was deleted.

‎.github/workflows/test-all.yml‎

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -170,34 +170,6 @@ jobs:
170170
use-prebuilds: true
171171
flavor: ${{ matrix.flavor }}
172172

173-
test_maestro_cloud_ios:
174-
needs: test_ios_rntester
175-
# test_ios_rntester is continue-on-error. If its Release artifact is missing,
176-
# the reusable workflow fails explicitly while downloading or validating it.
177-
# Maestro Cloud tests are temporarily disabled. Remove `false &&` to re-enable.
178-
if: |
179-
false &&
180-
needs.test_ios_rntester.result == 'success' &&
181-
(
182-
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
183-
(
184-
github.event_name == 'pull_request' &&
185-
github.event.pull_request.head.repo.full_name == github.repository &&
186-
github.actor != 'dependabot[bot]'
187-
)
188-
)
189-
uses: ./.github/workflows/maestro-cloud-rntester.yml
190-
with:
191-
platform: iOS
192-
artifact-name: RNTesterApp-NewArch-Release
193-
download-path: /tmp/RNTesterBuild/RNTester.app
194-
app-file: /tmp/RNTesterBuild/RNTester.app
195-
app-id: com.meta.RNTester.localDevelopment
196-
device-model: iPhone-17-Pro
197-
device-os: iOS-26-2
198-
exclude-tags: android-only,local-screenshot-baseline
199-
secrets: inherit
200-
201173
test_e2e_ios_rntester:
202174
needs: test_ios_rntester
203175
if: ${{ needs.test_ios_rntester.result == 'success' }}
@@ -384,30 +356,6 @@ jobs:
384356
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
385357
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
386358

387-
test_maestro_cloud_android:
388-
needs: build_android
389-
# Maestro Cloud tests are temporarily disabled. Remove `false &&` to re-enable.
390-
if: |
391-
false &&
392-
needs.build_android.result == 'success' &&
393-
(
394-
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
395-
(
396-
github.event_name == 'pull_request' &&
397-
github.event.pull_request.head.repo.full_name == github.repository &&
398-
github.actor != 'dependabot[bot]'
399-
)
400-
)
401-
uses: ./.github/workflows/maestro-cloud-rntester.yml
402-
with:
403-
platform: Android
404-
artifact-name: rntester-release
405-
download-path: /tmp/rntester-android
406-
app-file: /tmp/rntester-android/app-arm64-v8a-release.apk
407-
app-id: com.facebook.react.uiapp
408-
exclude-tags: ios-only,local-screenshot-baseline
409-
secrets: inherit
410-
411359
test_e2e_android_rntester:
412360
needs: build_android
413361
if: ${{ needs.build_android.result == 'success' }}

‎AGENTS.md‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ JavaScript CI is the `lint`, `test_js`, and `build_js_types` jobs in [`.github/w
4343

4444
The formatting command uses pinned npm packages for Kotlin and Java and installs pinned Ruff through Python. To format every language, install a JDK with Java 17 or newer, Python 3 with pip, and a Swift 6.3 or newer toolchain in addition to Node and Yarn. Each language wrapper checks its own requirements and prints installation guidance when something is missing; `yarn format` then skips that language and continues formatting the others. Swift formatting accepts either `swift-format` or `swift format` from the installed toolchain.
4545

46-
### Verification: Running RNTester
47-
48-
Needed only for changes that have to be seen running, such as user interface behavior.
49-
50-
`yarn start` serves [RNTester](packages/rn-tester/README.md) over Metro at `http://localhost:8081`; `yarn android` builds and installs it on Android. Check the bundler with `curl "http://localhost:8081/js/RNTesterApp.bundle?platform=ios&dev=true"`.
51-
5246
## Gotchas
5347

5448
- `yarn install` dirties the working tree: a `preinstall` hook (`scripts/try-set-hermes-compiler-prebuilt.js`) resolves the `hermes-compiler` placeholder in `packages/react-native/package.json` (`0.0.0` → a real version) and touches `yarn.lock`. Expected — do not commit it.
5549
- Metro cannot bundle until codegen is built once — `yarn --cwd packages/react-native-codegen build`. Without it, bundling fails with `Cannot find module '@react-native/codegen/lib/parsers/flow/parser'`. Every other package runs from source — `yarn build` is not needed for development (see [`scripts/build/README.md`](scripts/build/README.md)).
5650

51+
## Verification: Running RNTester
52+
53+
Needed only for changes that have to be seen running, such as user interface behavior.
54+
55+
`yarn start` serves [RNTester](packages/rn-tester/README.md) over Metro at `http://localhost:8081`; `yarn android` builds and installs it on Android. Check the bundler with `curl "http://localhost:8081/js/RNTesterApp.bundle?platform=ios&dev=true"`.
56+
5757
## Generated code
5858

5959
Never hand-edit generated output — change the source and regenerate. CI validates the committed snapshots.
@@ -64,6 +64,14 @@ Never hand-edit generated output — change the source and regenerate. CI valida
6464
- The public native API is snapshotted as well: C++ under `scripts/cxx-api` (`yarn cxx-api-build`), and Android in `packages/react-native/ReactAndroid/api/ReactAndroid.api`.
6565
- `CHANGELOG.md` is compiled at release time from pull request descriptions.
6666

67+
## Flow types for npm packages
68+
69+
`node_modules` is a `[declarations]` path in `.flowconfig`: Flow reads a package's own Flow types when it ships them (`metro` does), and otherwise the import is untyped, which `@flow strict` and `strict-local` files reject with `untyped-import`. A package used from Flow source for the first time needs a libdef in `flow-typed/npm/`, which overrides anything in `node_modules`:
70+
71+
- Name it `<package>_v<major>.x.x.js` for the major in `package.json`, under `@<scope>/` for a scoped package.
72+
- Copy the shape of a neighbor: the license header, `@flow strict`, and `declare module '<package>' { … }` with `declare module.exports` or `declare export`. Declare only the surface the repo calls, typed as the package documents it, never `any`.
73+
- Check with `yarn flow-check`, and drop the libdef with the last use of the package.
74+
6775
## Contributing guidelines
6876

6977
- Keep each change focused — no unrelated refactors, formatting, or dependency updates.

‎flow-typed/environment/node.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,8 +2422,8 @@ declare module 'fs' {
24222422
options?: GlobOptions<WithFileTypes>,
24232423
): Node$Conditional<
24242424
WithFileTypes,
2425-
AsyncIterator<Dirent>,
2426-
AsyncIterator<string>,
2425+
AsyncIteratorObject<Dirent>,
2426+
AsyncIteratorObject<string>,
24272427
>,
24282428
lchmod(path: FSPromisePath, mode: number): Promise<void>,
24292429
lchown(path: FSPromisePath, uid: number, guid: number): Promise<void>,
@@ -2533,7 +2533,7 @@ declare module 'fs' {
25332533
maxQueue?: number,
25342534
overflow?: 'ignore' | 'throw',
25352535
}>,
2536-
): AsyncIterator<{eventType: string, filename: ?string}>,
2536+
): AsyncIteratorObject<{eventType: string, filename: ?string}>,
25372537
write<T extends Buffer | Uint8Array>(
25382538
filehandle: FileHandle,
25392539
buffer: T,
@@ -4271,7 +4271,7 @@ declare module 'timers/promises' {
42714271
delay?: number,
42724272
value?: T,
42734273
options?: TimerOptions,
4274-
): AsyncIterator<T>;
4274+
): AsyncIteratorObject<T>;
42754275

42764276
declare export var scheduler: Readonly<{
42774277
wait(delay: number, options?: TimerOptions): Promise<void>,

‎packages/normalize-color/__tests__/normalizeColor-test.js‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ it('handles rgb properly', () => {
9696
expect(normalizeColor('rgb(0 0 0 / 0.5)')).toBe(0x00000080);
9797
expect(normalizeColor('rgb(0 0 0 / 1)')).toBe(0x000000ff);
9898
expect(normalizeColor('rgb(0, 0, 0, 0.5)')).toBe(0x00000080);
99+
expect(normalizeColor('rgb(0 0 0 / 50%)')).toBe(0x00000080);
99100
});
100101

101102
it('handles rgba properly', () => {
@@ -110,6 +111,8 @@ it('handles rgba properly', () => {
110111
expect(normalizeColor('rgba(0 0 0 / 1)')).toBe(0x000000ff);
111112
expect(normalizeColor('rgba(100 15 69 / 0.5)')).toBe(0x640f4580);
112113
expect(normalizeColor('rgba(0, 0, 0)')).toBe(0x000000ff);
114+
expect(normalizeColor('rgba(0, 0, 0, 50%)')).toBe(0x00000080);
115+
expect(normalizeColor('rgba(0 0 0 / 100%)')).toBe(0x000000ff);
113116
});
114117

115118
it('handles hsl properly', () => {
@@ -125,6 +128,9 @@ it('handles hsl properly', () => {
125128
expect(normalizeColor('hsl(0 0% 0%)')).toBe(0x000000ff);
126129
expect(normalizeColor('hsl(360 100% 100%)')).toBe(0xffffffff);
127130
expect(normalizeColor('hsl(180 50% 50%)')).toBe(0x40bfbfff);
131+
expect(normalizeColor('hsl(180 50% 50% / 0.2)')).toBe(0x40bfbf33);
132+
expect(normalizeColor('hsl(180 50% 50% / 20%)')).toBe(0x40bfbf33);
133+
expect(normalizeColor('hsl(180, 50%, 50%, 0.2)')).toBe(0x40bfbf33);
128134
});
129135

130136
it('handles hsla properly', () => {
@@ -136,6 +142,8 @@ it('handles hsla properly', () => {
136142
expect(normalizeColor('hsla(360 100% 100% / 1)')).toBe(0xffffffff);
137143
expect(normalizeColor('hsla(360 100% 100% / 0)')).toBe(0xffffff00);
138144
expect(normalizeColor('hsla(180 50% 50% / 0.2)')).toBe(0x40bfbf33);
145+
expect(normalizeColor('hsla(180, 50%, 50%, 20%)')).toBe(0x40bfbf33);
146+
expect(normalizeColor('hsla(180, 50%, 50%)')).toBe(0x40bfbfff);
139147
});
140148

141149
it('handles hwb properly', () => {
@@ -149,6 +157,7 @@ it('handles hwb properly', () => {
149157
expect(normalizeColor('hwb(70 50% 0%)')).toBe(0xeaff80ff);
150158
expect(normalizeColor('hwb(0, 0%, 100%)')).toBe(null);
151159
expect(normalizeColor('hwb(200 30% 20% / 0.5)')).toBe(0x4da1cc80);
160+
expect(normalizeColor('hwb(200 30% 20% / 50%)')).toBe(0x4da1cc80);
152161
});
153162

154163
it('handles named colors properly', () => {

‎packages/normalize-color/index.js‎

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -123,40 +123,39 @@ function parseColorString(color) {
123123
);
124124
}
125125

126-
if ((match = matchers.hsl.exec(color))) {
127-
return (
128-
(hslToRgb(
129-
parse360(match[1]), // h
130-
parsePercentage(match[2]), // s
131-
parsePercentage(match[3]), // l
132-
) |
133-
0x000000ff) >>> // a
134-
0
135-
);
136-
}
137-
138-
if ((match = matchers.hsla.exec(color))) {
139-
// hsla(H S L / A) notation
140-
if (match[6] !== undefined) {
126+
if ((match = matchers.hsla.exec(color) || matchers.hsl.exec(color))) {
127+
// hsl(H S L / A) / hsla(H S L / A) notation
128+
if (match[9] !== undefined) {
141129
return (
142130
(hslToRgb(
143-
parse360(match[6]), // h
144-
parsePercentage(match[7]), // s
145-
parsePercentage(match[8]), // l
131+
parse360(match[9]), // h
132+
parsePercentage(match[10]), // s
133+
parsePercentage(match[11]), // l
146134
) |
147-
parse1(match[9])) >>> // a
135+
parse1(match[12])) >>> // a
148136
0
149137
);
150138
}
151-
152-
// hsla(H, S, L, A) notation
139+
// hsl(H, S, L, A) / hsla(H, S, L, A) notation
140+
else if (match[5] !== undefined) {
141+
return (
142+
(hslToRgb(
143+
parse360(match[5]), // h
144+
parsePercentage(match[6]), // s
145+
parsePercentage(match[7]), // l
146+
) |
147+
parse1(match[8])) >>> // a
148+
0
149+
);
150+
}
151+
// hsl(H, S, L) / hsla(H, S, L) notation
153152
return (
154153
(hslToRgb(
155154
parse360(match[2]), // h
156155
parsePercentage(match[3]), // s
157156
parsePercentage(match[4]), // l
158157
) |
159-
parse1(match[5])) >>> // a
158+
0x000000ff) >>> // a
160159
0
161160
);
162161
}
@@ -242,6 +241,7 @@ function hwbToRgb(h, w, b) {
242241

243242
const NUMBER = '[-+]?\\d*\\.?\\d+';
244243
const PERCENTAGE = NUMBER + '%';
244+
const ALPHA = NUMBER + '%?';
245245

246246
function call(...args) {
247247
return '\\(\\s*(' + args.join(')\\s*,?\\s*(') + ')\\s*\\)';
@@ -272,26 +272,26 @@ function getMatchers() {
272272
const rgbRegexPattern =
273273
call(NUMBER, NUMBER, NUMBER) +
274274
'|' +
275-
commaSeparatedCall(NUMBER, NUMBER, NUMBER, NUMBER) +
275+
commaSeparatedCall(NUMBER, NUMBER, NUMBER, ALPHA) +
276+
'|' +
277+
callWithSlashSeparator(NUMBER, NUMBER, NUMBER, ALPHA);
278+
const hslRegexPattern =
279+
call(NUMBER, PERCENTAGE, PERCENTAGE) +
280+
'|' +
281+
commaSeparatedCall(NUMBER, PERCENTAGE, PERCENTAGE, ALPHA) +
276282
'|' +
277-
callWithSlashSeparator(NUMBER, NUMBER, NUMBER, NUMBER);
283+
callWithSlashSeparator(NUMBER, PERCENTAGE, PERCENTAGE, ALPHA);
278284

279285
cachedMatchers = {
280286
rgb: new RegExp('^rgb(' + rgbRegexPattern + ')$'),
281287
rgba: new RegExp('^rgba(' + rgbRegexPattern + ')$'),
282-
hsl: new RegExp('^hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE) + '$'),
283-
hsla: new RegExp(
284-
'^hsla(' +
285-
commaSeparatedCall(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER) +
286-
'|' +
287-
callWithSlashSeparator(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER) +
288-
')$',
289-
),
288+
hsl: new RegExp('^hsl(' + hslRegexPattern + ')$'),
289+
hsla: new RegExp('^hsla(' + hslRegexPattern + ')$'),
290290
hwb: new RegExp(
291291
'^hwb(' +
292292
callModern(NUMBER, PERCENTAGE, PERCENTAGE) +
293293
'|' +
294-
callWithSlashSeparator(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER) +
294+
callWithSlashSeparator(NUMBER, PERCENTAGE, PERCENTAGE, ALPHA) +
295295
')$',
296296
),
297297
hex3: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
@@ -320,7 +320,7 @@ function parse360(str) {
320320
}
321321

322322
function parse1(str) {
323-
const num = parseFloat(str);
323+
const num = str.endsWith('%') ? parseFloat(str) / 100 : parseFloat(str);
324324
if (num < 0) {
325325
return 0;
326326
}

0 commit comments

Comments
 (0)