From a6b862d427232b5dc94cb4c0c69c3de680b8aa72 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Mon, 17 Jun 2024 06:51:24 -0700 Subject: [PATCH 001/968] clean up systrace for systrace View preallocation (#44956) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44956 changelog: [internal] do not show systrace logs for flattened views. Reviewed By: rubennorte Differential Revision: D58587946 fbshipit-source-id: 6ef12feb352b9c79db6b91767c2d77906bba9cdc --- .../ReactAndroid/src/main/jni/react/fabric/Binding.cpp | 4 ---- .../src/main/jni/react/fabric/FabricMountingManager.cpp | 6 ++++++ .../ReactCommon/react/renderer/scheduler/Scheduler.cpp | 2 -- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp index 280ae463d33c84..b1d443cc26537e 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp @@ -509,10 +509,6 @@ void Binding::schedulerShouldRenderTransactions( void Binding::schedulerDidRequestPreliminaryViewAllocation( const ShadowNode& shadowNode) { - if (!shadowNode.getTraits().check(ShadowNodeTraits::Trait::FormsView)) { - return; - } - auto mountingManager = getMountingManager("preallocateView"); if (!mountingManager) { return; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index ca1937640658a8..ab08744f65e0db 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -786,6 +786,12 @@ void FabricMountingManager::executeMount( void FabricMountingManager::preallocateShadowView( const ShadowNode& shadowNode) { + if (!shadowNode.getTraits().check(ShadowNodeTraits::Trait::FormsView)) { + return; + } + + SystraceSection section("FabricMountingManager::preallocateShadowView"); + { std::lock_guard lock(allocatedViewsMutex_); auto allocatedViewsIterator = diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index a806d1e9f07545..8469db758205b4 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -310,8 +310,6 @@ void Scheduler::uiManagerDidFinishTransaction( } void Scheduler::uiManagerDidCreateShadowNode(const ShadowNode& shadowNode) { - SystraceSection s("Scheduler::uiManagerDidCreateShadowNode"); - if (delegate_ != nullptr) { delegate_->schedulerDidRequestPreliminaryViewAllocation(shadowNode); } From 16380aa167f31017d4d44331b6e64fdd2993ff35 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 17 Jun 2024 07:47:15 -0700 Subject: [PATCH 002/968] Fix tests for React 19 (#45007) Summary: Qhile landing the changes for React19 in 0.75, we missed one test that needs to be updated ## Changelog: [Internal] - Fix Jest tests in React 19 Pull Request resolved: https://github.com/facebook/react-native/pull/45007 Test Plan: CircleCI is green Reviewed By: robhogan Differential Revision: D58671824 Pulled By: cipolleschi fbshipit-source-id: 48a72f5cdc4d03201cb1778915ed3519759cf017 --- packages/react-native/template/__tests__/App.test.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/react-native/template/__tests__/App.test.tsx b/packages/react-native/template/__tests__/App.test.tsx index 9eac6fbc87d2c3..a26d1ec09a48b5 100644 --- a/packages/react-native/template/__tests__/App.test.tsx +++ b/packages/react-native/template/__tests__/App.test.tsx @@ -10,8 +10,10 @@ import App from '../App'; import {it} from '@jest/globals'; // Note: test renderer must be required after react-native. -import renderer from 'react-test-renderer'; +import ReactTestRenderer from 'react-test-renderer'; -it('renders correctly', () => { - renderer.create(); +it('renders correctly', async () => { + await ReactTestRenderer.act(() => { + ReactTestRenderer.create(); + }); }); From 9491deda7a7470deacfa5bd13cbc34d46613918e Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 17 Jun 2024 08:02:27 -0700 Subject: [PATCH 003/968] disable run-ci-e2e-tests which depend on template (#45009) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45009 This script dependes on the template existing in react-native/template. We're removing this, but can't land that until we disable this test. Future work could move this test into the react-native-community/template project to validate against RN release candidates to support releases. Changelog: [Internal] Reviewed By: huntie Differential Revision: D58672744 fbshipit-source-id: c1500aebb0b21afd1ba37785e73dd6a0e1d6020e --- .circleci/configurations/commands.yml | 16 ---------------- .circleci/configurations/jobs.yml | 2 -- .github/actions/run_e2e/action.yml | 2 ++ 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/.circleci/configurations/commands.yml b/.circleci/configurations/commands.yml index faef8484725969..344ffd452b0fee 100644 --- a/.circleci/configurations/commands.yml +++ b/.circleci/configurations/commands.yml @@ -157,22 +157,6 @@ commands: - packages/react-native/ReactAndroid/build/third-party-ndk key: *gradle_cache_key - run_e2e: - parameters: - platform: - description: Target platform - type: enum - enum: ["android", "ios", "js"] - default: "js" - retries: - description: How many times the job should try to run these tests - type: integer - default: 3 - steps: - - run: - name: "Run Tests: << parameters.platform >> End-to-End Tests" - command: node ./scripts/e2e/run-ci-e2e-tests.js --<< parameters.platform >> --retries << parameters.retries >> - report_bundle_size: parameters: platform: diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml index fbd50935d5663c..6845ff6c49063b 100644 --- a/.circleci/configurations/jobs.yml +++ b/.circleci/configurations/jobs.yml @@ -96,8 +96,6 @@ jobs: - run: name: "Run Tests: JavaScript Tests" command: node ./scripts/run-ci-javascript-tests.js --maxWorkers 2 - - run_e2e: - platform: js # Optionally, run disabled tests - when: diff --git a/.github/actions/run_e2e/action.yml b/.github/actions/run_e2e/action.yml index 5e479ce668d9a6..f90a98b976476b 100644 --- a/.github/actions/run_e2e/action.yml +++ b/.github/actions/run_e2e/action.yml @@ -13,5 +13,7 @@ runs: using: composite steps: - name: "Run Tests: ${{ inputs.platform }} End-to-End Tests" + # Disabled to remove the template from react-native + if: false run: node ./scripts/e2e/run-ci-e2e-tests.js --${{ inputs.platform }} --retries ${{ inputs.retries }} shell: bash From 4c6bff01b384d7d899dd9d3beef12b878918704e Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Mon, 17 Jun 2024 09:56:14 -0700 Subject: [PATCH 004/968] Fix bug in device ID collision handling, add tests (#45010) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45010 D46482492 added logic for handing off state across "device" connections that have the same ID. This logic currently has no test coverage. It also contains a bug whereby the new device's pages are removed from the target listing endpoint (`/json`) when the *old* device's socket is closed. This diff adds tests and fixes the bug. Changelog: [General][Fixed] inspector-proxy no longer accidentally detaches connected devices. ## Next steps It seems that the device ID handoff logic exists to paper over a deeper problem with the inspector proxy protocol (or its implementation in React Native): The React Native runtime should not routinely be creating new "device" connections without tearing down previous ones. In followup diffs, I'll explore changing this behaviour for Fusebox, based on the new test coverage. Reviewed By: robhogan Differential Revision: D51013056 fbshipit-source-id: e0c17678cc747366a3b75cef18ca2a722fc93acd --- .../src/__tests__/InspectorDeviceUtils.js | 6 + .../src/__tests__/InspectorProtocolUtils.js | 5 +- .../InspectorProxyCdpTransport-test.js | 7 +- .../InspectorProxyDeviceHandoff-test.js | 342 ++++++++++++++++++ .../src/inspector-proxy/InspectorProxy.js | 4 +- 5 files changed, 360 insertions(+), 4 deletions(-) create mode 100644 packages/dev-middleware/src/__tests__/InspectorProxyDeviceHandoff-test.js diff --git a/packages/dev-middleware/src/__tests__/InspectorDeviceUtils.js b/packages/dev-middleware/src/__tests__/InspectorDeviceUtils.js index 0ccf1f39712747..2f4d5d69d8abf7 100644 --- a/packages/dev-middleware/src/__tests__/InspectorDeviceUtils.js +++ b/packages/dev-middleware/src/__tests__/InspectorDeviceUtils.js @@ -20,6 +20,7 @@ import type { WrappedEvent, } from '../inspector-proxy/types'; +import nullthrows from 'nullthrows'; import WebSocket from 'ws'; export class DeviceAgent { @@ -82,6 +83,11 @@ export class DeviceAgent { }, }); } + + // $FlowIgnore[unsafe-getters-setters] + get socket(): WebSocket { + return nullthrows(this.#ws); + } } export class DeviceMock extends DeviceAgent { diff --git a/packages/dev-middleware/src/__tests__/InspectorProtocolUtils.js b/packages/dev-middleware/src/__tests__/InspectorProtocolUtils.js index b537323e7f4731..f3ab1e3bfccc5b 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProtocolUtils.js +++ b/packages/dev-middleware/src/__tests__/InspectorProtocolUtils.js @@ -126,12 +126,15 @@ export async function createAndConnectTarget( }>, signal: AbortSignal, page: PageFromDevice, + deviceId: ?string = null, ): Promise<{device: DeviceMock, debugger_: DebuggerMock}> { let device; let debugger_; try { device = await createDeviceMock( - `${serverRef.serverBaseWsUrl}/inspector/device?device=device&name=foo&app=bar`, + `${serverRef.serverBaseWsUrl}/inspector/device?device=${ + deviceId ?? 'device' + Date.now() + }&name=foo&app=bar`, signal, ); device.getPages.mockImplementation(() => [page]); diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js index 6d76d304e84677..1f287971b58811 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js @@ -9,7 +9,10 @@ * @oncall react_native */ -import type {PageDescription} from '../inspector-proxy/types'; +import type { + JsonPagesListResponse, + PageDescription, +} from '../inspector-proxy/types'; import {fetchJson} from './FetchUtils'; import {createDebuggerMock} from './InspectorDebuggerUtils'; @@ -51,7 +54,7 @@ describe.each(['HTTP', 'HTTPS'])( }, ]); - let pageList: Array = []; + let pageList: JsonPagesListResponse = []; await until(async () => { pageList = (await fetchJson( `${serverRef.serverBaseUrl}/json`, diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyDeviceHandoff-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyDeviceHandoff-test.js new file mode 100644 index 00000000000000..23961457ad042a --- /dev/null +++ b/packages/dev-middleware/src/__tests__/InspectorProxyDeviceHandoff-test.js @@ -0,0 +1,342 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import type { + GetPagesResponse, + JsonPagesListResponse, +} from '../inspector-proxy/types'; +import type {DeviceMock} from './InspectorDeviceUtils'; + +import {fetchJson} from './FetchUtils'; +import {createDebuggerMock} from './InspectorDebuggerUtils'; +import {createDeviceMock} from './InspectorDeviceUtils'; +import {sendFromDebuggerToTarget} from './InspectorProtocolUtils'; +import {withAbortSignalForEachTest} from './ResourceUtils'; +import {withServerForEachTest} from './ServerUtils'; +import until from 'wait-for-expect'; + +// WebSocket is unreliable when using fake timers. +jest.useRealTimers(); + +jest.setTimeout(10000); + +const PAGE_DEFAULTS = { + app: 'bar-app', + id: 'page1', + title: 'bar-title', + vm: 'bar-vm', +}; + +describe('inspector-proxy device socket handoff', () => { + const serverRef = withServerForEachTest({ + logger: undefined, + projectRoot: '', + }); + const autoCleanup = withAbortSignalForEachTest(); + afterEach(() => { + jest.clearAllMocks(); + }); + + test('device ID collision with no debugger connected', async () => { + let device1, device2; + try { + ({device: device1} = await connectDevice( + '/inspector/device?device=device&name=foo&app=bar', + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm', + }, + ], + )); + + ({device: device2} = await connectDevice( + '/inspector/device?device=device&name=foo&app=bar', + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm-updated', + }, + ], + )); + + // There's no debugger-->page connection to disconnect. + expect(device1.disconnect).not.toBeCalled(); + + // NOTE: It seems arbitrary that we don't close device1's socket here, + // but that is the current behavior. + expect(device1.socket.readyState).toBe(/* OPEN */ 1); + } finally { + device1?.close(); + device2?.close(); + } + }); + + test('device ID collision with a debugger connected', async () => { + let device1, device2, debugger_, webSocketDebuggerUrl; + try { + ({ + device: device1, + pageList: [{webSocketDebuggerUrl}], + } = await connectDevice( + '/inspector/device?device=device&name=foo&app=bar', + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm', + }, + ], + )); + + debugger_ = await createDebuggerMock( + webSocketDebuggerUrl, + autoCleanup.signal, + ); + + ({device: device2} = await connectDevice( + '/inspector/device?device=device&name=foo&app=bar', + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm-updated', + }, + ], + )); + + // Even having handed off the debugger connection to device2, we don't + // send a `disconnect` event for it to device1. We may want to change + // this behavior in the future. + expect(device1.disconnect).not.toBeCalled(); + + expect([ + // CLOSING + 3, + // CLOSED + 4, + ]).toContain(device1.socket.readyState); + + // We can successfully send a message from the debugger to device2, even + // though the initial debugger connection was to device1. + device1.wrappedEventParsed.mockClear(); + const receivedByDevice2 = await sendFromDebuggerToTarget( + debugger_, + device2, + 'page1', + { + method: 'Console.enable', + id: 0, + }, + ); + expect(receivedByDevice2).toEqual({ + method: 'Console.enable', + id: 0, + }); + expect(device1.wrappedEventParsed).not.toBeCalled(); + } finally { + device1?.close(); + device2?.close(); + debugger_?.close(); + } + }); + + test.each([ + ['app', 'name'], + ['name', 'app'], + ])( + 'device ID collision with no debugger connected, same %s and differing %s', + async (sameParam, differingParam) => { + let device1, device2, debugger_, webSocketDebuggerUrl; + try { + ({device: device1} = await connectDevice( + `/inspector/device?device=device&${sameParam}=foo&${differingParam}=bar`, + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm', + }, + ], + )); + + ({ + device: device2, + pageList: [{webSocketDebuggerUrl}], + } = await connectDevice( + `/inspector/device?device=device&${sameParam}=foo&${differingParam}=BAZ`, + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm-updated', + }, + ], + )); + + expect([ + // CLOSING + 3, + // CLOSED + 4, + ]).toContain(device1.socket.readyState); + + debugger_ = await createDebuggerMock( + webSocketDebuggerUrl, + autoCleanup.signal, + ); + + device1.wrappedEventParsed.mockClear(); + const receivedByDevice2 = await sendFromDebuggerToTarget( + debugger_, + device2, + 'page1', + { + method: 'Console.enable', + id: 0, + }, + ); + expect(receivedByDevice2).toEqual({ + method: 'Console.enable', + id: 0, + }); + expect(device1.wrappedEventParsed).not.toBeCalled(); + } finally { + device1?.close(); + device2?.close(); + debugger_?.close(); + } + }, + ); + + test.each([ + ['app', 'name'], + ['name', 'app'], + ])( + 'device ID collision with a debugger connected, same %s and differing %s', + async (sameParam, differingParam) => { + let device1, device2, debugger_, webSocketDebuggerUrl; + try { + ({ + device: device1, + pageList: [{webSocketDebuggerUrl}], + } = await connectDevice( + `/inspector/device?device=device&${sameParam}=foo&${differingParam}=bar`, + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm', + }, + ], + )); + debugger_ = await createDebuggerMock( + webSocketDebuggerUrl, + autoCleanup.signal, + ); + ({ + device: device2, + pageList: [{webSocketDebuggerUrl}], + } = await connectDevice( + `/inspector/device?device=device&${sameParam}=foo&${differingParam}=BAZ`, + [ + { + ...PAGE_DEFAULTS, + vm: 'bar-vm-updated', + }, + ], + )); + + expect([ + // CLOSING + 3, + // CLOSED + 4, + ]).toContain(debugger_.socket.readyState); + + // NOTE: It seems arbitrary that we don't send a `disconnect` message to + // device1. + expect(device1.disconnect).not.toBeCalled(); + + expect([ + // CLOSING + 3, + // CLOSED + 4, + ]).toContain(device1.socket.readyState); + + debugger_ = await createDebuggerMock( + webSocketDebuggerUrl, + autoCleanup.signal, + ); + device1.wrappedEventParsed.mockClear(); + const receivedByDevice2 = await sendFromDebuggerToTarget( + debugger_, + device2, + 'page1', + { + method: 'Console.enable', + id: 0, + }, + ); + expect(receivedByDevice2).toEqual({ + method: 'Console.enable', + id: 0, + }); + expect(device1.wrappedEventParsed).not.toBeCalled(); + } finally { + device1?.close(); + device2?.close(); + debugger_?.close(); + } + }, + ); + + // Helper function to create a DeviceMock and wait for its pages to be + // reported by /json. + async function connectDevice( + wsUrlPath: string, + pageListSpec: GetPagesResponse['payload'], + ): Promise<{ + device: DeviceMock, + pageList: JsonPagesListResponse, + }> { + let device; + try { + device = await createDeviceMock( + serverRef.serverBaseWsUrl + wsUrlPath, + autoCleanup.signal, + ); + device.getPages.mockImplementation(() => pageListSpec); + let pageList: JsonPagesListResponse = []; + await until(async () => { + pageList = (await fetchJson( + `${serverRef.serverBaseUrl}/json`, + // $FlowIgnore[unclear-type] + ): any); + expect(pageList).toEqual( + expect.arrayContaining( + pageListSpec.map(pageSpec => + expect.objectContaining({ + description: pageSpec.app, + id: expect.stringContaining(pageSpec.id), + title: pageSpec.title, + vm: pageSpec.vm, + }), + ), + ), + ); + }); + return { + device, + pageList, + }; + } catch (e) { + device?.close(); + throw e; + } + } +}); diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index 293f47c9183235..717cc8c298775b 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -230,7 +230,9 @@ export default class InspectorProxy implements InspectorProxyQueries { ); socket.on('close', () => { - this.#devices.delete(deviceId); + if (this.#devices.get(deviceId) === newDevice) { + this.#devices.delete(deviceId); + } debug(`Device ${deviceName} disconnected.`); }); } catch (e) { From fe7e7a015f30697c4ccffb2ba6474611efb4c08a Mon Sep 17 00:00:00 2001 From: Alan Lee Date: Mon, 17 Jun 2024 10:39:22 -0700 Subject: [PATCH 005/968] add default early JS error handler (#44884) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44884 Removing JavaScript error handler supplied to ReactHostImpl.java which is just a stub and creating a default handler in ReactInstance.java which uses NativeExceptionHandler TurboModule to handle error. Changelog: [Android][BREAKING] Removing `ReactJsExceptionHandler` param from ReactHostImpl() constructor and providing a default private implementation Reviewed By: javache, cortinico Differential Revision: D58385767 fbshipit-source-id: 46548677df936b7c2f584084a2c9769c27e6a963 --- .../ReactAndroid/api/ReactAndroid.api | 4 +- .../react/defaults/DefaultReactHost.kt | 4 -- .../facebook/react/runtime/ReactHostImpl.java | 7 --- .../facebook/react/runtime/ReactInstance.java | 52 ++++++++++++++++++- .../facebook/react/runtime/ReactHostTest.kt | 7 +-- 5 files changed, 53 insertions(+), 21 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index cad0f20e2ba377..8029d80ed207b5 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -3779,8 +3779,8 @@ public abstract class com/facebook/react/runtime/JSRuntimeFactory { } public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/ReactHost { - public fun (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Lcom/facebook/react/interfaces/exceptionmanager/ReactJsExceptionHandler;ZZ)V - public fun (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;ZLcom/facebook/react/interfaces/exceptionmanager/ReactJsExceptionHandler;Z)V + public fun (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;ZZ)V + public fun (Landroid/content/Context;Lcom/facebook/react/runtime/ReactHostDelegate;Lcom/facebook/react/fabric/ComponentFactory;ZZ)V public fun addBeforeDestroyListener (Lkotlin/jvm/functions/Function0;)V public fun addReactInstanceEventListener (Lcom/facebook/react/ReactInstanceEventListener;)V public fun createSurface (Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Lcom/facebook/react/interfaces/fabric/ReactSurface; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt index b32e79c61cc6ba..06452e525015b4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHost.kt @@ -17,7 +17,6 @@ import com.facebook.react.bridge.ReactContext import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.common.build.ReactBuildConfig import com.facebook.react.fabric.ComponentFactory -import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler import com.facebook.react.runtime.JSCInstance import com.facebook.react.runtime.ReactHostImpl import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage @@ -74,8 +73,6 @@ public object DefaultReactHost { reactPackages = packageList, jsRuntimeFactory = jsRuntimeFactory, turboModuleManagerDelegateBuilder = defaultTmmDelegateBuilder) - // TODO: T180971255 Improve default exception handler - val reactJsExceptionHandler = ReactJsExceptionHandler { _ -> } val componentFactory = ComponentFactory() DefaultComponentsRegistry.register(componentFactory) // TODO: T164788699 find alternative of accessing ReactHostImpl for initialising reactHost @@ -85,7 +82,6 @@ public object DefaultReactHost { defaultReactHostDelegate, componentFactory, true /* allowPackagerServerAccess */, - reactJsExceptionHandler, useDevSupport, ) .apply { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 64ac33f7d93919..28c266a64c4e96 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -57,7 +57,6 @@ import com.facebook.react.fabric.ComponentFactory; import com.facebook.react.fabric.FabricUIManager; import com.facebook.react.interfaces.TaskInterface; -import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler; import com.facebook.react.interfaces.fabric.ReactSurface; import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.modules.appearance.AppearanceModule; @@ -102,7 +101,6 @@ public class ReactHostImpl implements ReactHost { private final Context mContext; private final ReactHostDelegate mReactHostDelegate; private final ComponentFactory mComponentFactory; - private final ReactJsExceptionHandler mReactJsExceptionHandler; private final DevSupportManager mDevSupportManager; private final Executor mBGExecutor; private final Executor mUIExecutor; @@ -145,7 +143,6 @@ public ReactHostImpl( ReactHostDelegate delegate, ComponentFactory componentFactory, boolean allowPackagerServerAccess, - ReactJsExceptionHandler reactJsExceptionHandler, boolean useDevSupport) { this( context, @@ -153,7 +150,6 @@ public ReactHostImpl( componentFactory, Executors.newSingleThreadExecutor(), Task.UI_THREAD_EXECUTOR, - reactJsExceptionHandler, allowPackagerServerAccess, useDevSupport); } @@ -164,7 +160,6 @@ public ReactHostImpl( ComponentFactory componentFactory, Executor bgExecutor, Executor uiExecutor, - ReactJsExceptionHandler reactJsExceptionHandler, boolean allowPackagerServerAccess, boolean useDevSupport) { mContext = context; @@ -172,7 +167,6 @@ public ReactHostImpl( mComponentFactory = componentFactory; mBGExecutor = bgExecutor; mUIExecutor = uiExecutor; - mReactJsExceptionHandler = reactJsExceptionHandler; mQueueThreadExceptionHandler = ReactHostImpl.this::handleHostException; mMemoryPressureRouter = new MemoryPressureRouter(context); mAllowPackagerServerAccess = allowPackagerServerAccess; @@ -1074,7 +1068,6 @@ private Task getOrCreateReactInstanceTask() { mComponentFactory, devSupportManager, mQueueThreadExceptionHandler, - mReactJsExceptionHandler, mUseDevSupport, getOrCreateReactHostInspectorTarget()); mReactInstance = instance; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 7ab1ab6952833b..723e8ed039dbff 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -7,9 +7,16 @@ package com.facebook.react.runtime; +import static com.facebook.react.util.JSStackTrace.COLUMN_KEY; +import static com.facebook.react.util.JSStackTrace.FILE_KEY; +import static com.facebook.react.util.JSStackTrace.LINE_NUMBER_KEY; +import static com.facebook.react.util.JSStackTrace.METHOD_NAME_KEY; + import android.content.res.AssetManager; import android.view.View; import com.facebook.common.logging.FLog; +import com.facebook.fbreact.specs.NativeExceptionsManagerSpec; +import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.infer.annotation.ThreadConfined; import com.facebook.infer.annotation.ThreadSafe; @@ -21,12 +28,15 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.JSBundleLoader; import com.facebook.react.bridge.JSBundleLoaderDelegate; +import com.facebook.react.bridge.JavaOnlyArray; +import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.RuntimeScheduler; import com.facebook.react.bridge.queue.MessageQueueThread; @@ -110,7 +120,6 @@ final class ReactInstance { ComponentFactory componentFactory, DevSupportManager devSupportManager, QueueThreadExceptionHandler exceptionHandler, - ReactJsExceptionHandler reactExceptionManager, boolean useDevSupport, @Nullable ReactHostInspectorTarget reactHostInspectorTarget) { mBridgelessReactContext = bridgelessReactContext; @@ -154,6 +163,7 @@ final class ReactInstance { // Notify JS if profiling is enabled boolean isProfiling = Systrace.isTracing(Systrace.TRACE_TAG_REACT_APPS | Systrace.TRACE_TAG_REACT_JS_VM_CALLS); + mHybridData = initHybrid( jsRuntimeFactory, @@ -161,7 +171,7 @@ final class ReactInstance { nativeModulesMessageQueueThread, mJavaTimerManager, jsTimerExecutor, - reactExceptionManager, + new ReactJsExceptionHandlerImpl(nativeModulesMessageQueueThread), bindingsInstaller, isProfiling, reactHostInspectorTarget); @@ -313,6 +323,44 @@ public ReactQueueConfiguration getReactQueueConfiguration() { return mQueueConfiguration; } + private class ReactJsExceptionHandlerImpl implements ReactJsExceptionHandler { + private final MessageQueueThread mNativemodulesmessagequeuethread; + + ReactJsExceptionHandlerImpl(MessageQueueThread nativeModulesMessageQueueThread) { + this.mNativemodulesmessagequeuethread = nativeModulesMessageQueueThread; + } + + @Override + public void reportJsException(ParsedError error) { + List frames = error.getFrames(); + List readableMapList = new ArrayList<>(); + for (ReactJsExceptionHandler.ParsedError.StackFrame frame : frames) { + JavaOnlyMap map = new JavaOnlyMap(); + map.putDouble(COLUMN_KEY, frame.getColumnNumber()); + map.putDouble(LINE_NUMBER_KEY, frame.getLineNumber()); + map.putString(FILE_KEY, (String) frame.getFileName()); + map.putString(METHOD_NAME_KEY, (String) frame.getMethodName()); + readableMapList.add(map); + } + + JavaOnlyMap data = new JavaOnlyMap(); + data.putString("message", error.getMessage()); + data.putArray("stack", JavaOnlyArray.from(readableMapList)); + data.putInt("id", error.getExceptionId()); + data.putBoolean("isFatal", error.isFatal()); + + // Simulate async native module method call + mNativemodulesmessagequeuethread.runOnQueue( + () -> { + NativeExceptionsManagerSpec exceptionsManager = + (NativeExceptionsManagerSpec) + Assertions.assertNotNull( + mTurboModuleManager.getModule(NativeExceptionsManagerSpec.NAME)); + exceptionsManager.reportException(data); + }); + } + } + public void loadJSBundle(JSBundleLoader bundleLoader) { // Load the JS bundle Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstance.loadJSBundle"); diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt index 07d770eef585f3..ef83a8690b1c29 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt @@ -84,12 +84,7 @@ class ReactHostTest { Mockito.doReturn(jSBundleLoader).`when`(reactHostDelegate).jsBundleLoader reactHost = ReactHostImpl( - activityController.get().application, - reactHostDelegate, - componentFactory, - false, - {}, - false) + activityController.get().application, reactHostDelegate, componentFactory, false, false) val taskCompletionSource = TaskCompletionSource().apply { setResult(true) } mockedTaskCompletionSourceCtor = Mockito.mockConstruction( From 4792671e4dd5b5056294a3620166dc569b94877a Mon Sep 17 00:00:00 2001 From: Alan Lee Date: Mon, 17 Jun 2024 10:39:22 -0700 Subject: [PATCH 006/968] extract ParsedError handling to helper (#44922) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44922 extract ParsedError handling code into `StackTraceHelperTest`. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D58512611 fbshipit-source-id: 959978d80907f2afba96ef249c2fddd351d099ff --- .../ReactAndroid/api/ReactAndroid.api | 7 +++ .../react/devsupport/StackTraceHelper.java | 37 ++++++++++- .../facebook/react/runtime/ReactInstance.java | 25 +------- .../react/devsupport/StackTraceHelperTest.kt | 63 +++++++++++++++++++ 4 files changed, 107 insertions(+), 25 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 8029d80ed207b5..d0336cdacb2e10 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -2323,12 +2323,19 @@ public class com/facebook/react/devsupport/ReleaseDevSupportManager : com/facebo public class com/facebook/react/devsupport/StackTraceHelper { public static final field COLUMN_KEY Ljava/lang/String; + public static final field FILE_KEY Ljava/lang/String; + public static final field ID_KEY Ljava/lang/String; + public static final field IS_FATAL_KEY Ljava/lang/String; public static final field LINE_NUMBER_KEY Ljava/lang/String; + public static final field MESSAGE_KEY Ljava/lang/String; + public static final field METHOD_NAME_KEY Ljava/lang/String; + public static final field STACK_KEY Ljava/lang/String; public fun ()V public static fun convertJavaStackTrace (Ljava/lang/Throwable;)[Lcom/facebook/react/devsupport/interfaces/StackFrame; public static fun convertJsStackTrace (Lcom/facebook/react/bridge/ReadableArray;)[Lcom/facebook/react/devsupport/interfaces/StackFrame; public static fun convertJsStackTrace (Ljava/lang/String;)[Lcom/facebook/react/devsupport/interfaces/StackFrame; public static fun convertJsStackTrace (Lorg/json/JSONArray;)[Lcom/facebook/react/devsupport/interfaces/StackFrame; + public static fun convertParsedError (Lcom/facebook/react/interfaces/exceptionmanager/ReactJsExceptionHandler$ParsedError;)Lcom/facebook/react/bridge/JavaOnlyMap; public static fun formatFrameSource (Lcom/facebook/react/devsupport/interfaces/StackFrame;)Ljava/lang/String; public static fun formatStackTrace (Ljava/lang/String;[Lcom/facebook/react/devsupport/interfaces/StackFrame;)Ljava/lang/String; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java index a40b0c1209548a..70b779a8dc8e10 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/StackTraceHelper.java @@ -8,12 +8,17 @@ package com.facebook.react.devsupport; import androidx.annotation.Nullable; +import com.facebook.react.bridge.JavaOnlyArray; +import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableType; import com.facebook.react.common.MapBuilder; import com.facebook.react.devsupport.interfaces.StackFrame; +import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler.ParsedError; import java.io.File; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.json.JSONArray; @@ -23,8 +28,15 @@ /** Helper class converting JS and Java stack traces into arrays of {@link StackFrame} objects. */ public class StackTraceHelper { - public static final java.lang.String COLUMN_KEY = "column"; - public static final java.lang.String LINE_NUMBER_KEY = "lineNumber"; + public static final String COLUMN_KEY = "column"; + public static final String LINE_NUMBER_KEY = "lineNumber"; + public static final String FILE_KEY = "file"; + public static final String METHOD_NAME_KEY = "methodName"; + + public static final String MESSAGE_KEY = "message"; + public static final String STACK_KEY = "stack"; + public static final String ID_KEY = "id"; + public static final String IS_FATAL_KEY = "isFatal"; private static final Pattern STACK_FRAME_PATTERN1 = Pattern.compile("^(?:(.*?)@)?(.*?)\\:([0-9]+)\\:([0-9]+)$"); @@ -246,4 +258,25 @@ public static String formatStackTrace(String title, StackFrame[] stack) { return stackTrace.toString(); } + + public static JavaOnlyMap convertParsedError(ParsedError error) { + List frames = error.getFrames(); + List readableMapList = new ArrayList<>(); + for (ParsedError.StackFrame frame : frames) { + JavaOnlyMap map = new JavaOnlyMap(); + map.putDouble(COLUMN_KEY, frame.getColumnNumber()); + map.putDouble(LINE_NUMBER_KEY, frame.getLineNumber()); + map.putString(FILE_KEY, (String) frame.getFileName()); + map.putString(METHOD_NAME_KEY, (String) frame.getMethodName()); + readableMapList.add(map); + } + + JavaOnlyMap data = new JavaOnlyMap(); + data.putString(MESSAGE_KEY, error.getMessage()); + data.putArray(STACK_KEY, JavaOnlyArray.from(readableMapList)); + data.putInt(ID_KEY, error.getExceptionId()); + data.putBoolean(IS_FATAL_KEY, error.isFatal()); + + return data; + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 723e8ed039dbff..beb6bbcdab5aa3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -7,11 +7,6 @@ package com.facebook.react.runtime; -import static com.facebook.react.util.JSStackTrace.COLUMN_KEY; -import static com.facebook.react.util.JSStackTrace.FILE_KEY; -import static com.facebook.react.util.JSStackTrace.LINE_NUMBER_KEY; -import static com.facebook.react.util.JSStackTrace.METHOD_NAME_KEY; - import android.content.res.AssetManager; import android.view.View; import com.facebook.common.logging.FLog; @@ -28,7 +23,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.JSBundleLoader; import com.facebook.react.bridge.JSBundleLoaderDelegate; -import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.bridge.NativeArray; @@ -36,7 +30,6 @@ import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; -import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.RuntimeScheduler; import com.facebook.react.bridge.queue.MessageQueueThread; @@ -45,6 +38,7 @@ import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.bridge.queue.ReactQueueConfigurationImpl; import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec; +import com.facebook.react.devsupport.StackTraceHelper; import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.fabric.Binding; import com.facebook.react.fabric.BindingImpl; @@ -332,22 +326,7 @@ private class ReactJsExceptionHandlerImpl implements ReactJsExceptionHandler { @Override public void reportJsException(ParsedError error) { - List frames = error.getFrames(); - List readableMapList = new ArrayList<>(); - for (ReactJsExceptionHandler.ParsedError.StackFrame frame : frames) { - JavaOnlyMap map = new JavaOnlyMap(); - map.putDouble(COLUMN_KEY, frame.getColumnNumber()); - map.putDouble(LINE_NUMBER_KEY, frame.getLineNumber()); - map.putString(FILE_KEY, (String) frame.getFileName()); - map.putString(METHOD_NAME_KEY, (String) frame.getMethodName()); - readableMapList.add(map); - } - - JavaOnlyMap data = new JavaOnlyMap(); - data.putString("message", error.getMessage()); - data.putArray("stack", JavaOnlyArray.from(readableMapList)); - data.putInt("id", error.getExceptionId()); - data.putBoolean("isFatal", error.isFatal()); + JavaOnlyMap data = StackTraceHelper.convertParsedError(error); // Simulate async native module method call mNativemodulesmessagequeuethread.runOnQueue( diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt index 8a0c3d8d869d77..5e19da6b688908 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/devsupport/StackTraceHelperTest.kt @@ -7,11 +7,15 @@ package com.facebook.react.devsupport +import com.facebook.react.bridge.ReadableMap +import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler.* import org.assertj.core.api.Assertions.assertThat import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +@OptIn(UnstableReactNativeAPI::class) @RunWith(RobolectricTestRunner::class) class StackTraceHelperTest { @Test @@ -58,4 +62,63 @@ class StackTraceHelperTest { assertThat(frame.line).isEqualTo(-1) assertThat(frame.column).isEqualTo(-1) } + + @Test + fun testConvertParsedError() { + val error = getParsedErrorTestData() + + val data = StackTraceHelper.convertParsedError(error) + assertThat(data.getString("message")).isEqualTo("error message") + assertThat(data.getInt("id")).isEqualTo(123) + assertThat(data.getBoolean("isFatal")).isEqualTo(true) + + val stack = data.getArray("stack") + assertThat(stack).isNotNull() + stack?.let { + assertThat(stack.size()).isEqualTo(2) + assertStackFrameMap(stack.getMap(0), "file1", "method1", 1, 10) + assertStackFrameMap(stack.getMap(1), "file2", "method2", 2, 20) + } + } + + private fun assertStackFrameMap( + map: ReadableMap, + filename: String, + methodName: String, + lineNumber: Int, + columnNumber: Int + ) { + + assertThat(map.getString("file")).isEqualTo(filename) + assertThat(map.getString("methodName")).isEqualTo(methodName) + assertThat(map.getDouble("lineNumber").toInt()).isEqualTo(lineNumber) + assertThat(map.getDouble("column").toInt()).isEqualTo(columnNumber) + } + + private fun getParsedErrorTestData(): ParsedError { + val frame1 = + object : ParsedError.StackFrame { + override val fileName = "file1" + override val methodName = "method1" + override val lineNumber = 1 + override val columnNumber = 10 + } + + val frame2 = + object : ParsedError.StackFrame { + override val fileName = "file2" + override val methodName = "method2" + override val lineNumber = 2 + override val columnNumber = 20 + } + + val frames = listOf(frame1, frame2) + + return object : ParsedError { + override val frames = frames + override val message = "error message" + override val exceptionId = 123 + override val isFatal = true + } + } } From 8c7c6f35e35663e2c796d94b3921ad85c9cfd085 Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Mon, 17 Jun 2024 12:09:00 -0700 Subject: [PATCH 007/968] Add unit tests for BorderRadiusStyle (#44964) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44964 Testing property priority and correct setting percentages for business logic of `BorderRadiusStyle.kt` To prevent issues like the one fixed by D57473482 Changelog: [Internal] Reviewed By: javache Differential Revision: D58602799 fbshipit-source-id: 605bc384267d9f4ae5a051e76c1a4d862fe54039 --- .../uimanager/style/ComputedBorderRadius.kt | 17 ++ .../react/uimanager/BorderRadiusStyleTest.kt | 186 ++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt index d337e80ba35143..292b66c5b4dfbc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt @@ -7,6 +7,14 @@ package com.facebook.react.uimanager.style +/** Represents the collection of possible computed border radius style properties. */ +public enum class ComputedBorderRadiusProp { + COMPUTED_BORDER_TOP_LEFT_RADIUS, + COMPUTED_BORDER_TOP_RIGHT_RADIUS, + COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS, + COMPUTED_BORDER_BOTTOM_LEFT_RADIUS, +} + /** Phsysical edge lengths (in DIPs) for a border-radius. */ public data class ComputedBorderRadius( val topLeft: Float, @@ -18,5 +26,14 @@ public data class ComputedBorderRadius( return topLeft > 0f || topRight > 0f || bottomLeft > 0f || bottomRight > 0f } + public fun get(property: ComputedBorderRadiusProp): Float { + return when (property) { + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS -> topLeft + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS -> topRight + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS -> bottomLeft + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS -> bottomRight + } + } + public constructor() : this(0f, 0f, 0f, 0f) } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt new file mode 100644 index 00000000000000..81f48635b4b1ee --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt @@ -0,0 +1,186 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager + +import android.content.Context +import com.facebook.react.uimanager.style.BorderRadiusProp +import com.facebook.react.uimanager.style.BorderRadiusStyle +import com.facebook.react.uimanager.style.ComputedBorderRadiusProp +import org.assertj.core.api.Assertions.* +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +/** Tests for [BorderRadiusStyle] */ +@RunWith(RobolectricTestRunner::class) +class BorderRadiusStyleTest { + + private val ctx: Context = RuntimeEnvironment.getApplication() + + @Test + fun testCorrectPriorityLTR() { + val propertyOrderMap = + mapOf( + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, + BorderRadiusProp.BORDER_TOP_START_RADIUS, + BorderRadiusProp.BORDER_START_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, + BorderRadiusProp.BORDER_TOP_END_RADIUS, + BorderRadiusProp.BORDER_END_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, + BorderRadiusProp.BORDER_START_END_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, + BorderRadiusProp.BORDER_END_END_RADIUS), + ) + + propertyOrderMap.forEach { order -> + val borderRadiusStyle = BorderRadiusStyle() + // Starting count on 3 to test 0 override + var count = 3f + for (prop in order.value) { + borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) + val resolved = borderRadiusStyle.resolve(0, context = ctx, width = 100f, height = 100f) + assertThat(resolved.get(order.key)).isEqualTo(count) + count -= 1f + } + } + } + + @Test + fun testCorrectPriorityRTL() { + setContextLeftAndRightSwap(ctx, true) + val propertyOrderMap = + mapOf( + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, + BorderRadiusProp.BORDER_TOP_END_RADIUS, + BorderRadiusProp.BORDER_END_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, + BorderRadiusProp.BORDER_TOP_START_RADIUS, + BorderRadiusProp.BORDER_START_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, + BorderRadiusProp.BORDER_END_END_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, + BorderRadiusProp.BORDER_START_END_RADIUS), + ) + + propertyOrderMap.forEach { order -> + val borderRadiusStyle = BorderRadiusStyle() + // Starting count on 3 to test 0 override + var count = 3f + for (prop in order.value) { + borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) + val resolved = borderRadiusStyle.resolve(1, context = ctx, width = 100f, height = 100f) + assertThat(resolved.get(order.key)).isEqualTo(count) + count -= 1f + } + } + } + + @Test + fun testCorrectPriorityRTLNoSwap() { + setContextLeftAndRightSwap(ctx, false) + val propertyOrderMap = + mapOf( + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, + BorderRadiusProp.BORDER_TOP_END_RADIUS, + BorderRadiusProp.BORDER_END_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, + BorderRadiusProp.BORDER_TOP_START_RADIUS, + BorderRadiusProp.BORDER_START_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, + BorderRadiusProp.BORDER_END_END_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, + BorderRadiusProp.BORDER_START_END_RADIUS), + ) + + propertyOrderMap.forEach { order -> + val borderRadiusStyle = BorderRadiusStyle() + // Starting count on 3 to test 0 override + var count = 3f + for (prop in order.value) { + borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) + val resolved = borderRadiusStyle.resolve(1, context = ctx, width = 100f, height = 100f) + assertThat(resolved.get(order.key)).isEqualTo(count) + count -= 1f + } + } + } + + @Test + fun testBorderRadiusPercentages() { + val borderRadiusStyle = + BorderRadiusStyle( + topLeft = LengthPercentage(0f, LengthPercentageType.PERCENT), + topRight = LengthPercentage(10f, LengthPercentageType.PERCENT), + bottomLeft = LengthPercentage(20f, LengthPercentageType.PERCENT), + bottomRight = LengthPercentage(30f, LengthPercentageType.PERCENT), + ) + val resolved = borderRadiusStyle.resolve(0, context = ctx, width = 1000f, height = 1000f) + + assertThat(resolved.topLeft).isEqualTo(0f) + assertThat(resolved.topRight).isEqualTo(100f) + assertThat(resolved.bottomLeft).isEqualTo(200f) + assertThat(resolved.bottomRight).isEqualTo(300f) + } + + /* + * Make I18nUtil.instance.doLeftAndRightSwapInRTL(context) return false + * by setting context preference + */ + private fun setContextLeftAndRightSwap(context: Context, leftAndRightSwap: Boolean) { + val sharedPrefs = + context.getSharedPreferences( + "com.facebook.react.modules.i18nmanager.I18nUtil", Context.MODE_PRIVATE) + val editor = sharedPrefs.edit() + editor.putBoolean("RCTI18nUtil_makeRTLFlipLeftAndRightStyles", leftAndRightSwap) + editor.apply() + } +} From 36a04055d8b5e1cad0c32762d3fe2ceb8b6ae0a9 Mon Sep 17 00:00:00 2001 From: Pieter Vanderwerff Date: Mon, 17 Jun 2024 12:11:45 -0700 Subject: [PATCH 008/968] Create TextOptimized component to performance test changes to Text (#44962) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44962 Add a short term fork of `Text` for the purpose of performance testing. Specific differences from `Text`: - Lazy init Pressability via a nested component. - Skip children context wrapper when safe. - Move props destructuring to function param. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D58601810 fbshipit-source-id: 988bac6100287705fb1bf8dc48cb2cfae56343df --- .../Libraries/Text/TextNativeComponent.js | 2 +- .../Libraries/Text/TextOptimized.js | 538 ++++++++++++++++++ .../__snapshots__/public-api-test.js.snap | 11 +- 3 files changed, 549 insertions(+), 2 deletions(-) create mode 100644 packages/react-native/Libraries/Text/TextOptimized.js diff --git a/packages/react-native/Libraries/Text/TextNativeComponent.js b/packages/react-native/Libraries/Text/TextNativeComponent.js index 7ab0e270e99d53..db354707320cfa 100644 --- a/packages/react-native/Libraries/Text/TextNativeComponent.js +++ b/packages/react-native/Libraries/Text/TextNativeComponent.js @@ -17,7 +17,7 @@ import {createViewConfig} from '../NativeComponent/ViewConfig'; import UIManager from '../ReactNative/UIManager'; import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass'; -type NativeTextProps = $ReadOnly<{ +export type NativeTextProps = $ReadOnly<{ ...TextProps, isHighlighted?: ?boolean, selectionColor?: ?ProcessedColorValue, diff --git a/packages/react-native/Libraries/Text/TextOptimized.js b/packages/react-native/Libraries/Text/TextOptimized.js new file mode 100644 index 00000000000000..615badd9ad6758 --- /dev/null +++ b/packages/react-native/Libraries/Text/TextOptimized.js @@ -0,0 +1,538 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {PressEvent} from '../Types/CoreEventTypes'; +import type {NativeTextProps} from './TextNativeComponent'; +import type {PressRetentionOffset, TextProps} from './TextProps'; + +import * as PressabilityDebug from '../Pressability/PressabilityDebug'; +import usePressability from '../Pressability/usePressability'; +import flattenStyle from '../StyleSheet/flattenStyle'; +import processColor from '../StyleSheet/processColor'; +import Platform from '../Utilities/Platform'; +import TextAncestor from './TextAncestor'; +import {NativeText, NativeVirtualText} from './TextNativeComponent'; +import * as React from 'react'; +import {useContext, useMemo, useState} from 'react'; + +type TextForwardRef = React.ElementRef< + typeof NativeText | typeof NativeVirtualText, +>; + +/** + * Text is the fundamental component for displaying text. + * + * @see https://reactnative.dev/docs/text + * + * NOTE: This file is a short term fork of `Text` for the purpose of performance + * testing. Any changes to either this component or `Text` should be avoided + * while this file exists. + * + * Specific differences from `Text`: + * - Lazy init Pressability via a nested component + * - Skip children context wrapper when safe. + * - Move props destructuring to function param. + */ +const TextOptimized: React.AbstractComponent = + React.forwardRef( + ( + { + accessible, + accessibilityLabel, + accessibilityState, + allowFontScaling, + 'aria-busy': ariaBusy, + 'aria-checked': ariaChecked, + 'aria-disabled': ariaDisabled, + 'aria-expanded': ariaExpanded, + 'aria-label': ariaLabel, + 'aria-selected': ariaSelected, + children, + ellipsizeMode, + disabled, + id, + nativeID, + numberOfLines, + onLongPress, + onPress, + onPressIn, + onPressOut, + onResponderGrant, + onResponderMove, + onResponderRelease, + onResponderTerminate, + onResponderTerminationRequest, + onStartShouldSetResponder, + pressRetentionOffset, + selectable, + selectionColor, + suppressHighlighting, + style, + ...restProps + }: TextProps, + forwardedRef, + ) => { + const _accessibilityLabel = ariaLabel ?? accessibilityLabel; + + let _accessibilityState: ?TextProps['accessibilityState'] = + accessibilityState; + if ( + ariaBusy != null || + ariaChecked != null || + ariaDisabled != null || + ariaExpanded != null || + ariaSelected != null + ) { + if (_accessibilityState != null) { + _accessibilityState = { + busy: ariaBusy ?? _accessibilityState.busy, + checked: ariaChecked ?? _accessibilityState.checked, + disabled: ariaDisabled ?? _accessibilityState.disabled, + expanded: ariaExpanded ?? _accessibilityState.expanded, + selected: ariaSelected ?? _accessibilityState.selected, + }; + } else { + _accessibilityState = { + busy: ariaBusy, + checked: ariaChecked, + disabled: ariaDisabled, + expanded: ariaExpanded, + selected: ariaSelected, + }; + } + } + + const _accessibilityStateDisabled = _accessibilityState?.disabled; + const _disabled = disabled ?? _accessibilityStateDisabled; + + const isPressable = + (onPress != null || + onLongPress != null || + onStartShouldSetResponder != null) && + _disabled !== true; + + // TODO: Move this processing to the view configuration. + const _selectionColor = + selectionColor == null ? null : processColor(selectionColor); + + let _style = style; + if (__DEV__) { + if (PressabilityDebug.isEnabled() && onPress != null) { + _style = [style, {color: 'magenta'}]; + } + } + + let _numberOfLines = numberOfLines; + if (_numberOfLines != null && !(_numberOfLines >= 0)) { + if (__DEV__) { + console.error( + `'numberOfLines' in must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`, + ); + } + _numberOfLines = 0; + } + + let _selectable = selectable; + + const processedStyle = flattenStyle(_style); + if (processedStyle != null) { + if (typeof processedStyle.fontWeight === 'number') { + // $FlowFixMe[cannot-write] + processedStyle.fontWeight = processedStyle.fontWeight.toString(); + } + + if (processedStyle.userSelect != null) { + _selectable = userSelectToSelectableMap[processedStyle.userSelect]; + // $FlowFixMe[cannot-write] + delete processedStyle.userSelect; + } + + if (processedStyle.verticalAlign != null) { + // $FlowFixMe[cannot-write] + processedStyle.textAlignVertical = + verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign]; + // $FlowFixMe[cannot-write] + delete processedStyle.verticalAlign; + } + } + + const _nativeID = id ?? nativeID; + + const hasTextAncestor = useContext(TextAncestor); + if (hasTextAncestor) { + if (isPressable) { + return ( + + ); + } + + return ( + + {children} + + ); + } + + // If the disabled prop and accessibilityState.disabled are out of sync but not both in + // falsy states we need to update the accessibilityState object to use the disabled prop. + if ( + _disabled !== _accessibilityStateDisabled && + ((_disabled != null && _disabled !== false) || + (_accessibilityStateDisabled != null && + _accessibilityStateDisabled !== false)) + ) { + _accessibilityState = {..._accessibilityState, disabled: _disabled}; + } + + const _accessible = Platform.select({ + ios: accessible !== false, + android: + accessible == null + ? onPress != null || onLongPress != null + : accessible, + default: accessible, + }); + + let nativeText = null; + if (isPressable) { + nativeText = ( + + ); + } else { + nativeText = ( + + {children} + + ); + } + + if (children == null) { + return nativeText; + } + + // If the children do not contain a JSX element it would not be possible to have a + // nested `Text` component so we can skip adding the `TextAncestor` context wrapper + // which has a performance overhead. Since we do this for performance reasons we need + // to keep the check simple to avoid regressing overall perf. For this reason the + // `children.length` constant is set to `3`, this should be a reasonable tradeoff + // to capture the majority of `Text` uses but also not make this check too expensive. + if (Array.isArray(children) && children.length <= 3) { + let hasNonTextChild = false; + for (let child of children) { + if (child != null && typeof child === 'object') { + hasNonTextChild = true; + break; + } + } + if (!hasNonTextChild) { + return nativeText; + } + } else if (typeof children !== 'object') { + return nativeText; + } + + return ( + {nativeText} + ); + }, + ); + +TextOptimized.displayName = 'TextOptimized'; + +type TextPressabilityProps = $ReadOnly<{ + onLongPress?: ?(event: PressEvent) => mixed, + onPress?: ?(event: PressEvent) => mixed, + onPressIn?: ?(event: PressEvent) => mixed, + onPressOut?: ?(event: PressEvent) => mixed, + onResponderGrant?: ?(event: PressEvent) => void, + onResponderMove?: ?(event: PressEvent) => void, + onResponderRelease?: ?(event: PressEvent) => void, + onResponderTerminate?: ?(event: PressEvent) => void, + onResponderTerminationRequest?: ?() => boolean, + onStartShouldSetResponder?: ?() => boolean, + pressRetentionOffset?: ?PressRetentionOffset, + suppressHighlighting?: ?boolean, +}>; + +/** + * Hook that handles setting up Pressability of Text components. + * + * NOTE: This hook is relatively expensive so it should only be used absolutely necessary. + */ +function useTextPressability({ + onLongPress, + onPress, + onPressIn, + onPressOut, + onResponderGrant, + onResponderMove, + onResponderRelease, + onResponderTerminate, + onResponderTerminationRequest, + onStartShouldSetResponder, + pressRetentionOffset, + suppressHighlighting, +}: TextPressabilityProps) { + const [isHighlighted, setHighlighted] = useState(false); + + // Setup pressability config and wrap callbacks needs to track the highlight state. + const config = useMemo(() => { + let _onPressIn = onPressIn; + let _onPressOut = onPressOut; + + // Updating isHighlighted causes unnecessary re-renders for platforms that don't use it + // in the best case, and cause issues with text selection in the worst case. Forcing + // the isHighlighted prop to false on all platforms except iOS. + if (Platform.OS === 'ios') { + _onPressIn = (event: PressEvent) => { + setHighlighted(suppressHighlighting == null || !suppressHighlighting); + onPressIn?.(event); + }; + + _onPressOut = (event: PressEvent) => { + setHighlighted(false); + onPressOut?.(event); + }; + } + + return { + disabled: false, + pressRectOffset: pressRetentionOffset, + onLongPress, + onPress, + onPressIn: _onPressIn, + onPressOut: _onPressOut, + }; + }, [ + pressRetentionOffset, + onLongPress, + onPress, + onPressIn, + onPressOut, + suppressHighlighting, + ]); + + // Init the pressability class + const eventHandlers = usePressability(config); + + // Create NativeText event handlers which proxy events to pressability + const eventHandlersForText = useMemo( + () => + eventHandlers == null + ? null + : { + onResponderGrant(event: PressEvent) { + eventHandlers.onResponderGrant(event); + if (onResponderGrant != null) { + onResponderGrant(event); + } + }, + onResponderMove(event: PressEvent) { + eventHandlers.onResponderMove(event); + if (onResponderMove != null) { + onResponderMove(event); + } + }, + onResponderRelease(event: PressEvent) { + eventHandlers.onResponderRelease(event); + if (onResponderRelease != null) { + onResponderRelease(event); + } + }, + onResponderTerminate(event: PressEvent) { + eventHandlers.onResponderTerminate(event); + if (onResponderTerminate != null) { + onResponderTerminate(event); + } + }, + onClick: eventHandlers.onClick, + onResponderTerminationRequest: + onResponderTerminationRequest != null + ? onResponderTerminationRequest + : eventHandlers.onResponderTerminationRequest, + onStartShouldSetResponder: + onStartShouldSetResponder != null + ? onStartShouldSetResponder + : eventHandlers.onStartShouldSetResponder, + }, + [ + eventHandlers, + onResponderGrant, + onResponderMove, + onResponderRelease, + onResponderTerminate, + onResponderTerminationRequest, + onStartShouldSetResponder, + ], + ); + + // Return the highlight state and NativeText event handlers + return useMemo( + () => [isHighlighted, eventHandlersForText], + [isHighlighted, eventHandlersForText], + ); +} + +type NativePressableTextProps = $ReadOnly<{ + textProps: NativeTextProps, + textPressabilityProps: TextPressabilityProps, +}>; + +/** + * Wrap the NativeVirtualText component and initialize pressability. + * + * This logic is split out from the main Text component to enable the more + * expensive pressability logic to be only initialized when needed. + */ +const NativePressableVirtualText: React.AbstractComponent< + NativePressableTextProps, + TextForwardRef, +> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => { + const [isHighlighted, eventHandlersForText] = useTextPressability( + textPressabilityProps, + ); + + return ( + + ); +}); + +/** + * Wrap the NativeText component and initialize pressability. + * + * This logic is split out from the main Text component to enable the more + * expensive pressability logic to be only initialized when needed. + */ +const NativePressableText: React.AbstractComponent< + NativePressableTextProps, + TextForwardRef, +> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => { + const [isHighlighted, eventHandlersForText] = useTextPressability( + textPressabilityProps, + ); + + return ( + + ); +}); + +const userSelectToSelectableMap = { + auto: true, + text: true, + none: false, + contain: true, + all: true, +}; + +const verticalAlignToTextAlignVerticalMap = { + auto: 'auto', + top: 'top', + bottom: 'bottom', + middle: 'center', +}; + +module.exports = TextOptimized; diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 58e73cf5d90486..6269e4e9bc2e32 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -8059,7 +8059,7 @@ declare module.exports: TextAncestorContext; `; exports[`public API should not change unintentionally Libraries/Text/TextNativeComponent.js 1`] = ` -"type NativeTextProps = $ReadOnly<{ +"export type NativeTextProps = $ReadOnly<{ ...TextProps, isHighlighted?: ?boolean, selectionColor?: ?ProcessedColorValue, @@ -8071,6 +8071,15 @@ declare export const NativeVirtualText: HostComponent; " `; +exports[`public API should not change unintentionally Libraries/Text/TextOptimized.js 1`] = ` +"type TextForwardRef = React.ElementRef< + typeof NativeText | typeof NativeVirtualText, +>; +declare const TextOptimized: React.AbstractComponent; +declare module.exports: TextOptimized; +" +`; + exports[`public API should not change unintentionally Libraries/Text/TextProps.js 1`] = ` "export type PressRetentionOffset = $ReadOnly<{ top: number, From bc1735f014707306f1ee935dec75b7f2ccf068ff Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 17 Jun 2024 15:11:08 -0700 Subject: [PATCH 009/968] =?UTF-8?q?test=5Fandroid=5Ftemplate=20=E2=86=92?= =?UTF-8?q?=20test=5Fandroid=5Fhelloworld=20but=20disabled=20until=20templ?= =?UTF-8?q?ate=20is=20removed=20(#44908)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44908 Changelog: [General] [Changed] - CircleCI test to Helloworld, but disabled for now until we remove the template Reviewed By: cipolleschi Differential Revision: D58469912 fbshipit-source-id: 718a774946bd70347697f18bbfc470b2897d2f87 --- .circleci/configurations/jobs.yml | 36 ++++----- .../configurations/test_workflows/testAll.yml | 18 +++-- .../test_workflows/testAndroid.yml | 25 +++--- .../releases/__tests__/set-rn-version-test.js | 11 --- scripts/releases/set-rn-version.js | 5 -- .../__snapshots__/set-version-test.js.snap | 76 ------------------- 6 files changed, 41 insertions(+), 130 deletions(-) diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml index 6845ff6c49063b..fc15c96f7b8263 100644 --- a/.circleci/configurations/jobs.yml +++ b/.circleci/configurations/jobs.yml @@ -325,9 +325,9 @@ jobs: destination: rntester-apk # ------------------------- - # JOBS: Test Android Template + # JOBS: Test Android HelloWorld # ------------------------- - test_android_template: + test_android_helloworld: executor: reactnativeandroid-large parameters: flavor: @@ -346,37 +346,37 @@ jobs: type: enum enum: ["Hermes", "JSC"] environment: + - LC_ALL: C.UTF8 - PROJECT_NAME: "AndroidTemplateProject" - YARN_ENABLE_IMMUTABLE_INSTALLS: false + - TARGET_ARCHITECTURE: "arm64-v8a" steps: - checkout_code_with_cache - run_yarn - attach_workspace: at: . - run: - name: Create Android template project + name: Build codegen js scripts from flow -> JS command: | - REPO_ROOT=$(pwd) - node ./scripts/releases/update-template-package.js "{\"react-native\":\"file:$REPO_ROOT/build/$(cat build/react-native-package-version)\"}" - node ./scripts/e2e/init-template-e2e.js --projectName $PROJECT_NAME --templatePath "$REPO_ROOT/packages/react-native" --directory "/tmp/$PROJECT_NAME" --verbose + cd packages/react-native-codegen + yarn run build - with_gradle_cache: steps: - run: - name: Build the template application for << parameters.flavor >> with Architecture set to << parameters.architecture >>, and using the << parameters.jsengine>> JS engine. + name: Build the Helloworld application for << parameters.flavor >> with Architecture set to << parameters.architecture >>, and using the << parameters.jsengine>> JS engine. command: | - cd /tmp/$PROJECT_NAME/android/ - if [[ << parameters.architecture >> == "NewArch" ]]; then - export ORG_GRADLE_PROJECT_newArchEnabled=true - else - export ORG_GRADLE_PROJECT_newArchEnabled=false + cd packages/helloworld/android + args=() + if [[ << parameters.architecture >> == "OldArch" ]]; then + args+=(--arch old) fi - if [[ << parameters.jsengine >> == "Hermes" ]]; then - export ORG_GRADLE_PROJECT_hermesEnabled=true - else - export ORG_GRADLE_PROJECT_hermesEnabled=false + if [[ << parameters.jsengine >> == "JSC" ]]; then + args+=(--jsvm jsc) fi - ./gradlew assemble<< parameters.flavor >> -Preact.internal.mavenLocalRepo=/root/react-native/maven-local - + if [[ << parameters.flavor >> == "Release" ]]; then + args+=(--prod) + fi + yarn build android "${args[@]}" -P reactNativeArchitectures="$TARGET_ARCHITECTURE" - store_artifacts: path: /tmp/AndroidTemplateProject/android/app/build/outputs/apk/ destination: template-apk diff --git a/.circleci/configurations/test_workflows/testAll.yml b/.circleci/configurations/test_workflows/testAll.yml index 8286628e69dab6..67dcf3c09d7db5 100644 --- a/.circleci/configurations/test_workflows/testAll.yml +++ b/.circleci/configurations/test_workflows/testAll.yml @@ -46,14 +46,16 @@ - test_android: requires: - build_android - - test_android_template: - requires: - - build_npm_package - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - jsengine: ["Hermes", "JSC"] - flavor: ["Debug", "Release"] + ## Disabled to land removing react-native/template. Re-enable once switched over + ## to Helloworld. + # - test_android_template: + # requires: + # - build_npm_package + # matrix: + # parameters: + # architecture: ["NewArch", "OldArch"] + # jsengine: ["Hermes", "JSC"] + # flavor: ["Debug", "Release"] - test_ios_helloworld: requires: - build_hermes_macos diff --git a/.circleci/configurations/test_workflows/testAndroid.yml b/.circleci/configurations/test_workflows/testAndroid.yml index 9a29ead21ad835..5f14bc096402e4 100644 --- a/.circleci/configurations/test_workflows/testAndroid.yml +++ b/.circleci/configurations/test_workflows/testAndroid.yml @@ -43,15 +43,16 @@ - build_hermesc_linux - build_hermes_macos - build_hermesc_windows - - test_android: - requires: - - build_android - # - test_e2e_android - - test_android_template: - requires: - - build_npm_package - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - jsengine: ["Hermes", "JSC"] - flavor: ["Debug", "Release"] + ## Disabled to land removing react-native/template. Re-enable once switched over + ## to Helloworld. + # - test_android: + # requires: + # - build_android + # - test_android_template: + # requires: + # - build_npm_package + # matrix: + # parameters: + # architecture: ["NewArch", "OldArch"] + # jsengine: ["Hermes", "JSC"] + # flavor: ["Debug", "Release"] diff --git a/scripts/releases/__tests__/set-rn-version-test.js b/scripts/releases/__tests__/set-rn-version-test.js index 26e9bfbee710e0..d78317b130d293 100644 --- a/scripts/releases/__tests__/set-rn-version-test.js +++ b/scripts/releases/__tests__/set-rn-version-test.js @@ -11,7 +11,6 @@ const readFileMock = jest.fn(); const writeFileMock = jest.fn(); -const updateTemplatePackageMock = jest.fn(); jest.mock('fs', () => ({ ...jest.requireActual<$FlowFixMe>('fs'), @@ -21,7 +20,6 @@ jest.mock('fs', () => ({ writeFile: writeFileMock, }, })); -jest.mock('./../update-template-package', () => updateTemplatePackageMock); const {REPO_ROOT} = require('../../consts'); const {setReactNativeVersion} = require('../set-rn-version'); @@ -64,11 +62,6 @@ describe('setReactNativeVersion', () => { }; await setReactNativeVersion(version, dependencyVersions, 'nightly'); - expect(updateTemplatePackageMock).toHaveBeenCalledWith({ - '@react-native/package-a': version, - 'react-native': version, - }); - for (const [filePath, contents] of writeFileMock.mock.calls) { // Make snapshot names resilient to platform path sep differences expect(formatGeneratedFile(contents)).toMatchSnapshot( @@ -81,10 +74,6 @@ describe('setReactNativeVersion', () => { const version = '0.81.0'; await setReactNativeVersion(version, null, 'release'); - expect(updateTemplatePackageMock).toHaveBeenCalledWith({ - 'react-native': version, - }); - for (const [filePath, contents] of writeFileMock.mock.calls) { // Make snapshot names resilient to platform path sep differences expect(formatGeneratedFile(contents)).toMatchSnapshot( diff --git a/scripts/releases/set-rn-version.js b/scripts/releases/set-rn-version.js index 52ea23b183f412..d4f663b36aa394 100755 --- a/scripts/releases/set-rn-version.js +++ b/scripts/releases/set-rn-version.js @@ -16,7 +16,6 @@ import type {BuildType, Version} from './utils/version-utils'; const {REPO_ROOT} = require('../consts'); const {applyPackageVersions} = require('../npm-utils'); const {getNpmInfo} = require('../npm-utils'); -const updateTemplatePackage = require('./update-template-package'); const {parseVersion, validateBuildType} = require('./utils/version-utils'); const {parseArgs} = require('@pkgjs/parseargs'); const {promises: fs} = require('fs'); @@ -82,10 +81,6 @@ async function setReactNativeVersion( ) { const versionInfo = parseVersion(version, buildType); - updateTemplatePackage({ - ...(dependencyVersions ?? {}), - 'react-native': versionInfo.version, - }); await updateSourceFiles(versionInfo); await setReactNativePackageVersion(versionInfo.version, dependencyVersions); await updateGradleFile(versionInfo.version); diff --git a/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap b/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap index 3291d9af2796fc..0759b660e58f95 100644 --- a/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap +++ b/scripts/releases/set-version/__tests__/__snapshots__/set-version-test.js.snap @@ -81,25 +81,6 @@ exports[`setVersion updates monorepo for nightly: packages/react-native/package. " `; -exports[`setVersion updates monorepo for nightly: packages/react-native/template/package.json 1`] = ` -"{ - \\"name\\": \\"react-native-test-template\\", - \\"version\\": \\"0.0.1\\", - \\"private\\": true, - \\"dependencies\\": { - \\"react\\": \\"19.0.0-rc-fb9a90fa48-20240614\\", - \\"react-native\\": \\"0.81.0-nightly-29282302-abcd1234\\" - }, - \\"devDependencies\\": { - \\"@monorepo/pkg-a\\": \\"0.81.0-nightly-29282302-abcd1234\\", - \\"@monorepo/pkg-c\\": \\"0.81.0-nightly-29282302-abcd1234\\", - \\"@types/react\\": \\"^18.2.6\\", - \\"@types/react-test-renderer\\": \\"^18.0.0\\" - } -} -" -`; - exports[`setVersion updates monorepo for release-candidate: package.json 1`] = ` "{ \\"name\\": \\"@react-native/monorepo\\", @@ -181,25 +162,6 @@ exports[`setVersion updates monorepo for release-candidate: packages/react-nativ " `; -exports[`setVersion updates monorepo for release-candidate: packages/react-native/template/package.json 1`] = ` -"{ - \\"name\\": \\"react-native-test-template\\", - \\"version\\": \\"0.0.1\\", - \\"private\\": true, - \\"dependencies\\": { - \\"react\\": \\"19.0.0-rc-fb9a90fa48-20240614\\", - \\"react-native\\": \\"0.80.0-rc.3\\" - }, - \\"devDependencies\\": { - \\"@monorepo/pkg-a\\": \\"0.80.0-rc.3\\", - \\"@monorepo/pkg-c\\": \\"0.80.0-rc.3\\", - \\"@types/react\\": \\"^18.2.6\\", - \\"@types/react-test-renderer\\": \\"^18.0.0\\" - } -} -" -`; - exports[`setVersion updates monorepo for stable version: package.json 1`] = ` "{ \\"name\\": \\"@react-native/monorepo\\", @@ -281,25 +243,6 @@ exports[`setVersion updates monorepo for stable version: packages/react-native/p " `; -exports[`setVersion updates monorepo for stable version: packages/react-native/template/package.json 1`] = ` -"{ - \\"name\\": \\"react-native-test-template\\", - \\"version\\": \\"0.0.1\\", - \\"private\\": true, - \\"dependencies\\": { - \\"react\\": \\"19.0.0-rc-fb9a90fa48-20240614\\", - \\"react-native\\": \\"0.80.1\\" - }, - \\"devDependencies\\": { - \\"@monorepo/pkg-a\\": \\"0.80.1\\", - \\"@monorepo/pkg-c\\": \\"0.80.1\\", - \\"@types/react\\": \\"^18.2.6\\", - \\"@types/react-test-renderer\\": \\"^18.0.0\\" - } -} -" -`; - exports[`setVersion updates monorepo on main after release cut: package.json 1`] = ` "{ \\"name\\": \\"@react-native/monorepo\\", @@ -380,22 +323,3 @@ exports[`setVersion updates monorepo on main after release cut: packages/react-n } " `; - -exports[`setVersion updates monorepo on main after release cut: packages/react-native/template/package.json 1`] = ` -"{ - \\"name\\": \\"react-native-test-template\\", - \\"version\\": \\"0.0.1\\", - \\"private\\": true, - \\"dependencies\\": { - \\"react\\": \\"19.0.0-rc-fb9a90fa48-20240614\\", - \\"react-native\\": \\"1000.0.0\\" - }, - \\"devDependencies\\": { - \\"@monorepo/pkg-a\\": \\"0.82.0-main\\", - \\"@monorepo/pkg-c\\": \\"0.82.0-main\\", - \\"@types/react\\": \\"^18.2.6\\", - \\"@types/react-test-renderer\\": \\"^18.0.0\\" - } -} -" -`; From 07abfceae117edc8ed205fe1ebaef89ce3041386 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 17 Jun 2024 15:48:09 -0700 Subject: [PATCH 010/968] remove the template from react-native package (#45008) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45008 As part of RFC0759, we are moving the template into it's own repository. ## Useful Links: - [Section in RFC0759](https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md#evolving-the-react-native-community-template--cli) - [Template's new home](https://github.com/react-native-community/template) - [Versioning discussion](https://github.com/react-native-community/cli/issues/2345) Changelog: [General][Breaking] removed the template from react-native into react-native-community/template Reviewed By: cortinico Differential Revision: D58184276 fbshipit-source-id: 5e52320af55495488587accbe144d11164cea4fd --- packages/react-native/README.md | 8 + packages/react-native/template.config.js | 12 - packages/react-native/template/App.tsx | 118 --- packages/react-native/template/Gemfile | 8 - packages/react-native/template/README.md | 79 -- .../template/__tests__/App.test.tsx | 19 - packages/react-native/template/_bundle/config | 2 - packages/react-native/template/_eslintrc.js | 4 - packages/react-native/template/_gitignore | 74 -- packages/react-native/template/_prettierrc.js | 7 - .../react-native/template/_watchmanconfig | 1 - .../template/android/app/build.gradle | 119 --- .../template/android/app/debug.keystore | Bin 2257 -> 0 bytes .../template/android/app/proguard-rules.pro | 10 - .../android/app/src/debug/AndroidManifest.xml | 9 - .../android/app/src/main/AndroidManifest.xml | 26 - .../main/java/com/helloworld/MainActivity.kt | 22 - .../java/com/helloworld/MainApplication.kt | 43 -- .../res/drawable/rn_edit_text_material.xml | 37 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3056 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5024 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2096 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2858 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4569 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7098 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6464 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 10676 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9250 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 15523 -> 0 bytes .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/styles.xml | 9 - .../template/android/build.gradle | 21 - .../template/android/gradle.properties | 39 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - .../react-native/template/android/gradlew | 249 ------- .../react-native/template/android/gradlew.bat | 92 --- .../template/android/settings.gradle | 6 - packages/react-native/template/app.json | 4 - .../react-native/template/babel.config.js | 3 - packages/react-native/template/index.js | 9 - .../ios/HelloWorld.xcodeproj/project.pbxproj | 688 ------------------ .../xcschemes/HelloWorld.xcscheme | 88 --- .../template/ios/HelloWorld/AppDelegate.h | 6 - .../template/ios/HelloWorld/AppDelegate.mm | 31 - .../AppIcon.appiconset/Contents.json | 53 -- .../HelloWorld/Images.xcassets/Contents.json | 6 - .../template/ios/HelloWorld/Info.plist | 52 -- .../ios/HelloWorld/LaunchScreen.storyboard | 47 -- .../ios/HelloWorld/PrivacyInfo.xcprivacy | 38 - .../template/ios/HelloWorld/main.m | 10 - .../ios/HelloWorldTests/HelloWorldTests.m | 66 -- .../template/ios/HelloWorldTests/Info.plist | 24 - packages/react-native/template/ios/Podfile | 40 - packages/react-native/template/ios/_xcode.env | 11 - packages/react-native/template/jest.config.js | 3 - .../react-native/template/metro.config.js | 11 - packages/react-native/template/package.json | 36 - packages/react-native/template/tsconfig.json | 3 - 59 files changed, 8 insertions(+), 2245 deletions(-) create mode 100644 packages/react-native/README.md delete mode 100644 packages/react-native/template.config.js delete mode 100644 packages/react-native/template/App.tsx delete mode 100644 packages/react-native/template/Gemfile delete mode 100644 packages/react-native/template/README.md delete mode 100644 packages/react-native/template/__tests__/App.test.tsx delete mode 100644 packages/react-native/template/_bundle/config delete mode 100644 packages/react-native/template/_eslintrc.js delete mode 100644 packages/react-native/template/_gitignore delete mode 100644 packages/react-native/template/_prettierrc.js delete mode 100644 packages/react-native/template/_watchmanconfig delete mode 100644 packages/react-native/template/android/app/build.gradle delete mode 100644 packages/react-native/template/android/app/debug.keystore delete mode 100644 packages/react-native/template/android/app/proguard-rules.pro delete mode 100644 packages/react-native/template/android/app/src/debug/AndroidManifest.xml delete mode 100644 packages/react-native/template/android/app/src/main/AndroidManifest.xml delete mode 100644 packages/react-native/template/android/app/src/main/java/com/helloworld/MainActivity.kt delete mode 100644 packages/react-native/template/android/app/src/main/java/com/helloworld/MainApplication.kt delete mode 100644 packages/react-native/template/android/app/src/main/res/drawable/rn_edit_text_material.xml delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 packages/react-native/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 packages/react-native/template/android/app/src/main/res/values/strings.xml delete mode 100644 packages/react-native/template/android/app/src/main/res/values/styles.xml delete mode 100644 packages/react-native/template/android/build.gradle delete mode 100644 packages/react-native/template/android/gradle.properties delete mode 100644 packages/react-native/template/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 packages/react-native/template/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 packages/react-native/template/android/gradlew delete mode 100644 packages/react-native/template/android/gradlew.bat delete mode 100644 packages/react-native/template/android/settings.gradle delete mode 100644 packages/react-native/template/app.json delete mode 100644 packages/react-native/template/babel.config.js delete mode 100644 packages/react-native/template/index.js delete mode 100644 packages/react-native/template/ios/HelloWorld.xcodeproj/project.pbxproj delete mode 100644 packages/react-native/template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme delete mode 100644 packages/react-native/template/ios/HelloWorld/AppDelegate.h delete mode 100644 packages/react-native/template/ios/HelloWorld/AppDelegate.mm delete mode 100644 packages/react-native/template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 packages/react-native/template/ios/HelloWorld/Images.xcassets/Contents.json delete mode 100644 packages/react-native/template/ios/HelloWorld/Info.plist delete mode 100644 packages/react-native/template/ios/HelloWorld/LaunchScreen.storyboard delete mode 100644 packages/react-native/template/ios/HelloWorld/PrivacyInfo.xcprivacy delete mode 100644 packages/react-native/template/ios/HelloWorld/main.m delete mode 100644 packages/react-native/template/ios/HelloWorldTests/HelloWorldTests.m delete mode 100644 packages/react-native/template/ios/HelloWorldTests/Info.plist delete mode 100644 packages/react-native/template/ios/Podfile delete mode 100644 packages/react-native/template/ios/_xcode.env delete mode 100644 packages/react-native/template/jest.config.js delete mode 100644 packages/react-native/template/metro.config.js delete mode 100644 packages/react-native/template/package.json delete mode 100644 packages/react-native/template/tsconfig.json diff --git a/packages/react-native/README.md b/packages/react-native/README.md new file mode 100644 index 00000000000000..83322bfa66ae0d --- /dev/null +++ b/packages/react-native/README.md @@ -0,0 +1,8 @@ +# Where is the template? +The React Native Template has moved from being shipping inside the [react-native](https://www.npmjs.com/package/react-native) package to it's own package: [@react-native-community/template](https://github.com/react-native-community/template). + +## Why has it moved? +The [React Native Frameworks RFC0759](https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md#evolving-the-react-native-community-template--cli) provides background information. + +## When was it moved? +The 0.75 release. diff --git a/packages/react-native/template.config.js b/packages/react-native/template.config.js deleted file mode 100644 index c075f1d2fd951f..00000000000000 --- a/packages/react-native/template.config.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -module.exports = { - placeholderName: 'HelloWorld', - titlePlaceholder: 'Hello App Display Name', - templateDir: './template', -}; diff --git a/packages/react-native/template/App.tsx b/packages/react-native/template/App.tsx deleted file mode 100644 index 125fe1b98eb3be..00000000000000 --- a/packages/react-native/template/App.tsx +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Sample React Native App - * https://github.com/facebook/react-native - * - * @format - */ - -import React from 'react'; -import type {PropsWithChildren} from 'react'; -import { - SafeAreaView, - ScrollView, - StatusBar, - StyleSheet, - Text, - useColorScheme, - View, -} from 'react-native'; - -import { - Colors, - DebugInstructions, - Header, - LearnMoreLinks, - ReloadInstructions, -} from 'react-native/Libraries/NewAppScreen'; - -type SectionProps = PropsWithChildren<{ - title: string; -}>; - -function Section({children, title}: SectionProps): React.JSX.Element { - const isDarkMode = useColorScheme() === 'dark'; - return ( - - - {title} - - - {children} - - - ); -} - -function App(): React.JSX.Element { - const isDarkMode = useColorScheme() === 'dark'; - - const backgroundStyle = { - backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, - }; - - return ( - - - -
- -
- Edit App.tsx to change this - screen and then come back to see your edits. -
-
- -
-
- -
-
- Read the docs to discover what to do next: -
- -
- - - ); -} - -const styles = StyleSheet.create({ - sectionContainer: { - marginTop: 32, - paddingHorizontal: 24, - }, - sectionTitle: { - fontSize: 24, - fontWeight: '600', - }, - sectionDescription: { - marginTop: 8, - fontSize: 18, - fontWeight: '400', - }, - highlight: { - fontWeight: '700', - }, -}); - -export default App; diff --git a/packages/react-native/template/Gemfile b/packages/react-native/template/Gemfile deleted file mode 100644 index 2a7ce357c5b2ab..00000000000000 --- a/packages/react-native/template/Gemfile +++ /dev/null @@ -1,8 +0,0 @@ -source 'https://rubygems.org' - -# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version -ruby ">= 2.6.10" - -# Exclude problematic versions of cocoapods and activesupport that causes build failures. -gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' -gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' diff --git a/packages/react-native/template/README.md b/packages/react-native/template/README.md deleted file mode 100644 index 12470c30ecb5a2..00000000000000 --- a/packages/react-native/template/README.md +++ /dev/null @@ -1,79 +0,0 @@ -This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). - -# Getting Started - ->**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. - -## Step 1: Start the Metro Server - -First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native. - -To start Metro, run the following command from the _root_ of your React Native project: - -```bash -# using npm -npm start - -# OR using Yarn -yarn start -``` - -## Step 2: Start your Application - -Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app: - -### For Android - -```bash -# using npm -npm run android - -# OR using Yarn -yarn android -``` - -### For iOS - -```bash -# using npm -npm run ios - -# OR using Yarn -yarn ios -``` - -If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly. - -This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively. - -## Step 3: Modifying your App - -Now that you have successfully run the app, let's modify it. - -1. Open `App.tsx` in your text editor of choice and edit some lines. -2. For **Android**: Press the R key twice or select **"Reload"** from the **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd ⌘ + M (on macOS)) to see your changes! - - For **iOS**: Hit Cmd ⌘ + R in your iOS Simulator to reload the app and see your changes! - -## Congratulations! :tada: - -You've successfully run and modified your React Native App. :partying_face: - -### Now what? - -- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps). -- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started). - -# Troubleshooting - -If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page. - -# Learn More - -To learn more about React Native, take a look at the following resources: - -- [React Native Website](https://reactnative.dev) - learn more about React Native. -- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment. -- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. -- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. -- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. diff --git a/packages/react-native/template/__tests__/App.test.tsx b/packages/react-native/template/__tests__/App.test.tsx deleted file mode 100644 index a26d1ec09a48b5..00000000000000 --- a/packages/react-native/template/__tests__/App.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @format - */ - -import 'react-native'; -import React from 'react'; -import App from '../App'; - -// Note: import explicitly to use the types shipped with jest. -import {it} from '@jest/globals'; - -// Note: test renderer must be required after react-native. -import ReactTestRenderer from 'react-test-renderer'; - -it('renders correctly', async () => { - await ReactTestRenderer.act(() => { - ReactTestRenderer.create(); - }); -}); diff --git a/packages/react-native/template/_bundle/config b/packages/react-native/template/_bundle/config deleted file mode 100644 index 848943bb5274b1..00000000000000 --- a/packages/react-native/template/_bundle/config +++ /dev/null @@ -1,2 +0,0 @@ -BUNDLE_PATH: "vendor/bundle" -BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/packages/react-native/template/_eslintrc.js b/packages/react-native/template/_eslintrc.js deleted file mode 100644 index 187894b6af25ee..00000000000000 --- a/packages/react-native/template/_eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: '@react-native', -}; diff --git a/packages/react-native/template/_gitignore b/packages/react-native/template/_gitignore deleted file mode 100644 index d5ae456695e5fc..00000000000000 --- a/packages/react-native/template/_gitignore +++ /dev/null @@ -1,74 +0,0 @@ -# OSX -# -.DS_Store - -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate -**/.xcode.env.local - -# Android/IntelliJ -# -build/ -.idea -.gradle -local.properties -*.iml -*.hprof -.cxx/ -*.keystore -!debug.keystore - -# node.js -# -node_modules/ -npm-debug.log -yarn-error.log - -# fastlane -# -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/ - -**/fastlane/report.xml -**/fastlane/Preview.html -**/fastlane/screenshots -**/fastlane/test_output - -# Bundle artifact -*.jsbundle - -# Ruby / CocoaPods -**/Pods/ -/vendor/bundle/ - -# Temporary files created by Metro to check the health of the file watcher -.metro-health-check* - -# testing -/coverage - -# Yarn -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions diff --git a/packages/react-native/template/_prettierrc.js b/packages/react-native/template/_prettierrc.js deleted file mode 100644 index 2b540746a7575e..00000000000000 --- a/packages/react-native/template/_prettierrc.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - arrowParens: 'avoid', - bracketSameLine: true, - bracketSpacing: false, - singleQuote: true, - trailingComma: 'all', -}; diff --git a/packages/react-native/template/_watchmanconfig b/packages/react-native/template/_watchmanconfig deleted file mode 100644 index 0967ef424bce67..00000000000000 --- a/packages/react-native/template/_watchmanconfig +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/react-native/template/android/app/build.gradle b/packages/react-native/template/android/app/build.gradle deleted file mode 100644 index 4fd5d93f9e33f3..00000000000000 --- a/packages/react-native/template/android/app/build.gradle +++ /dev/null @@ -1,119 +0,0 @@ -apply plugin: "com.android.application" -apply plugin: "org.jetbrains.kotlin.android" -apply plugin: "com.facebook.react" - -/** - * This is the configuration block to customize your React Native Android app. - * By default you don't need to apply any configuration, just uncomment the lines you need. - */ -react { - /* Folders */ - // The root of your project, i.e. where "package.json" lives. Default is '../..' - // root = file("../../") - // The folder where the react-native NPM package is. Default is ../../node_modules/react-native - // reactNativeDir = file("../../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen - // codegenDir = file("../../node_modules/@react-native/codegen") - // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js - // cliFile = file("../../node_modules/react-native/cli.js") - - /* Variants */ - // The list of variants to that are debuggable. For those we're going to - // skip the bundling of the JS bundle and the assets. By default is just 'debug'. - // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. - // debuggableVariants = ["liteDebug", "prodDebug"] - - /* Bundling */ - // A list containing the node command and its flags. Default is just 'node'. - // nodeExecutableAndArgs = ["node"] - // - // The command to run when bundling. By default is 'bundle' - // bundleCommand = "ram-bundle" - // - // The path to the CLI configuration file. Default is empty. - // bundleConfig = file(../rn-cli.config.js) - // - // The name of the generated asset file containing your JS bundle - // bundleAssetName = "MyApplication.android.bundle" - // - // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' - // entryFile = file("../js/MyApplication.android.js") - // - // A list of extra flags to pass to the 'bundle' commands. - // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle - // extraPackagerArgs = [] - - /* Hermes Commands */ - // The hermes compiler command to run. By default it is 'hermesc' - // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" - // - // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" - // hermesFlags = ["-O", "-output-source-map"] - - /* Autolinking */ - autolinkLibrariesWithApp() -} - -/** - * Set this to true to Run Proguard on Release builds to minify the Java bytecode. - */ -def enableProguardInReleaseBuilds = false - -/** - * The preferred build flavor of JavaScriptCore (JSC) - * - * For example, to use the international variant, you can use: - * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` - * - * The international variant includes ICU i18n library and necessary data - * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that - * give correct results when using with locales other than en-US. Note that - * this variant is about 6MiB larger per architecture than default. - */ -def jscFlavor = 'org.webkit:android-jsc:+' - -android { - ndkVersion rootProject.ext.ndkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - compileSdk rootProject.ext.compileSdkVersion - - namespace "com.helloworld" - defaultConfig { - applicationId "com.helloworld" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 - versionName "1.0" - } - signingConfigs { - debug { - storeFile file('debug.keystore') - storePassword 'android' - keyAlias 'androiddebugkey' - keyPassword 'android' - } - } - buildTypes { - debug { - signingConfig signingConfigs.debug - } - release { - // Caution! In production, you need to generate your own keystore file. - // see https://reactnative.dev/docs/signed-apk-android. - signingConfig signingConfigs.debug - minifyEnabled enableProguardInReleaseBuilds - proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" - } - } -} - -dependencies { - // The version of react-native is set by the React Native Gradle Plugin - implementation("com.facebook.react:react-android") - - if (hermesEnabled.toBoolean()) { - implementation("com.facebook.react:hermes-android") - } else { - implementation jscFlavor - } -} diff --git a/packages/react-native/template/android/app/debug.keystore b/packages/react-native/template/android/app/debug.keystore deleted file mode 100644 index 364e105ed39fbfd62001429a68140672b06ec0de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2257 zcmchYXEfYt8;7T1^dLH$VOTZ%2NOdOH5j5LYLtZ0q7x-V8_6gU5)#7dkq{HTmsfNq zB3ZqcAxeY^G10@?efK?Q&)M(qInVv!xjx+IKEL}p*K@LYvIzo#AZG>st5|P)KF1_Z;y){W{<7K{nl!CPuE z_^(!C(Ol0n8 zK13*rzAtW>(wULKPRYLd7G18F8#1P`V*9`(Poj26eOXYyBVZPno~Cvvhx7vPjAuZo zF?VD!zB~QG(!zbw#qsxT8%BSpqMZ4f70ZPn-3y$L8{EVbbN9$H`B&Z1quk9tgp5FM zuxp3pJ0b8u|3+#5bkJ4SRnCF2l7#DyLYXYY8*?OuAwK4E6J{0N=O3QNVzQ$L#FKkR zi-c@&!nDvezOV$i$Lr}iF$XEcwnybQ6WZrMKuw8gCL^U#D;q3t&HpTbqyD%vG=TeDlzCT~MXUPC|Leb-Uk+ z=vnMd(|>ld?Fh>V8poP;q;;nc@en$|rnP0ytzD&fFkCeUE^kG9Kx4wUh!!rpjwKDP zyw_e|a^x_w3E zP}}@$g>*LLJ4i0`Gx)qltL}@;mDv}D*xR^oeWcWdPkW@Uu)B^X&4W1$p6}ze!zudJ zyiLg@uggoMIArBr*27EZV7djDg@W1MaL+rcZ-lrANJQ%%>u8)ZMWU@R2qtnmG(acP z0d_^!t>}5W zpT`*2NR+0+SpTHb+6Js4b;%LJB;B_-ChhnU5py}iJtku*hm5F0!iql8Hrpcy1aYbT z1*dKC5ua6pMX@@iONI?Hpr%h;&YaXp9n!ND7-=a%BD7v&g zOO41M6EbE24mJ#S$Ui0-brR5ML%@|ndz^)YLMMV1atna{Fw<;TF@>d&F|!Z>8eg>>hkFrV)W+uv=`^F9^e zzzM2*oOjT9%gLoub%(R57p-`TXFe#oh1_{&N-YN z<}artH|m=d8TQuKSWE)Z%puU|g|^^NFwC#N=@dPhasyYjoy(fdEVfKR@cXKHZV-`06HsP`|Ftx;8(YD$fFXumLWbGnu$GMqRncXYY9mwz9$ap zQtfZB^_BeNYITh^hA7+(XNFox5WMeG_LtJ%*Q}$8VKDI_p8^pqX)}NMb`0e|wgF7D zuQACY_Ua<1ri{;Jwt@_1sW9zzdgnyh_O#8y+C;LcZq6=4e^cs6KvmK@$vVpKFGbQ= z$)Eux5C|Fx;Gtmv9^#Y-g@7Rt7*eLp5n!gJmn7&B_L$G?NCN`AP>cXQEz}%F%K;vUs{+l4Q{}eWW;ATe2 zqvXzxoIDy(u;F2q1JH7Sf;{jy_j})F+cKlIOmNfjBGHoG^CN zM|Ho&&X|L-36f}Q-obEACz`sI%2f&k>z5c$2TyTSj~vmO)BW~+N^kt`Jt@R|s!){H ze1_eCrlNaPkJQhL$WG&iRvF*YG=gXd1IyYQ9ew|iYn7r~g!wOnw;@n42>enAxBv*A zEmV*N#sxdicyNM=A4|yaOC5MByts}s_Hpfj|y<6G=o=!3S@eIFKDdpR7|FY>L&Wat&oW&cm&X~ z5Bt>Fcq(fgnvlvLSYg&o6>&fY`ODg4`V^lWWD=%oJ#Kbad2u~! zLECFS*??>|vDsNR&pH=Ze0Eo`sC_G`OjoEKVHY|wmwlX&(XBE<@sx3Hd^gtd-fNwUHsylg06p`U2y_={u}Bc - - - - diff --git a/packages/react-native/template/android/app/src/main/AndroidManifest.xml b/packages/react-native/template/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index e1892528b8d0b0..00000000000000 --- a/packages/react-native/template/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - diff --git a/packages/react-native/template/android/app/src/main/java/com/helloworld/MainActivity.kt b/packages/react-native/template/android/app/src/main/java/com/helloworld/MainActivity.kt deleted file mode 100644 index d7a3dee1a87bb3..00000000000000 --- a/packages/react-native/template/android/app/src/main/java/com/helloworld/MainActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.helloworld - -import com.facebook.react.ReactActivity -import com.facebook.react.ReactActivityDelegate -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled -import com.facebook.react.defaults.DefaultReactActivityDelegate - -class MainActivity : ReactActivity() { - - /** - * Returns the name of the main component registered from JavaScript. This is used to schedule - * rendering of the component. - */ - override fun getMainComponentName(): String = "HelloWorld" - - /** - * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] - * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] - */ - override fun createReactActivityDelegate(): ReactActivityDelegate = - DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) -} diff --git a/packages/react-native/template/android/app/src/main/java/com/helloworld/MainApplication.kt b/packages/react-native/template/android/app/src/main/java/com/helloworld/MainApplication.kt deleted file mode 100644 index cdcd0d332184db..00000000000000 --- a/packages/react-native/template/android/app/src/main/java/com/helloworld/MainApplication.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.helloworld - -import android.app.Application -import com.facebook.react.PackageList -import com.facebook.react.ReactApplication -import com.facebook.react.ReactHost -import com.facebook.react.ReactNativeHost -import com.facebook.react.ReactPackage -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load -import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost -import com.facebook.react.defaults.DefaultReactNativeHost -import com.facebook.soloader.SoLoader - -class MainApplication : Application(), ReactApplication { - - override val reactNativeHost: ReactNativeHost = - object : DefaultReactNativeHost(this) { - override fun getPackages(): List = - PackageList(this).packages.apply { - // Packages that cannot be autolinked yet can be added manually here, for example: - // add(MyReactNativePackage()) - } - - override fun getJSMainModuleName(): String = "index" - - override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG - - override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED - override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED - } - - override val reactHost: ReactHost - get() = getDefaultReactHost(applicationContext, reactNativeHost) - - override fun onCreate() { - super.onCreate() - SoLoader.init(this, false) - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for this app. - load() - } - } -} diff --git a/packages/react-native/template/android/app/src/main/res/drawable/rn_edit_text_material.xml b/packages/react-native/template/android/app/src/main/res/drawable/rn_edit_text_material.xml deleted file mode 100644 index 5c25e728ea2ce7..00000000000000 --- a/packages/react-native/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - diff --git a/packages/react-native/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/react-native/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f5908281d070150700378b64a84c7db1f97aa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3056 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 axPAxe%7rDusX+w*00006jj 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⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu`csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT+00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U%bv zkg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4`B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZCCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQpGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C#%M;Yf_*pI^};h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* diff --git a/packages/react-native/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/packages/react-native/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d3ae0d3943ab44cdc27feef9256dc6d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7098 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 diff --git a/packages/react-native/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/react-native/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe024be86e868d14e91120a6902f8e88ac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6464 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 B0*L?s diff --git a/packages/react-native/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/packages/react-native/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a1b15ff180f3dacac19395fe3046cdec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10676 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 diff --git a/packages/react-native/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/packages/react-native/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c239cb67b8a2134ddd5f325db1d2d5bee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15523 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 BIP(Ai diff --git a/packages/react-native/template/android/app/src/main/res/values/strings.xml b/packages/react-native/template/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 0c79c4bad47cb7..00000000000000 --- a/packages/react-native/template/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Hello App Display Name - diff --git a/packages/react-native/template/android/app/src/main/res/values/styles.xml b/packages/react-native/template/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 7ba83a2ad5a2c9..00000000000000 --- a/packages/react-native/template/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/packages/react-native/template/android/build.gradle b/packages/react-native/template/android/build.gradle deleted file mode 100644 index df1ce4db3b1bfb..00000000000000 --- a/packages/react-native/template/android/build.gradle +++ /dev/null @@ -1,21 +0,0 @@ -buildscript { - ext { - buildToolsVersion = "34.0.0" - minSdkVersion = 23 - compileSdkVersion = 34 - targetSdkVersion = 34 - ndkVersion = "26.1.10909125" - kotlinVersion = "1.9.24" - } - repositories { - google() - mavenCentral() - } - dependencies { - classpath("com.android.tools.build:gradle") - classpath("com.facebook.react:react-native-gradle-plugin") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") - } -} - -apply plugin: "com.facebook.react.rootproject" diff --git a/packages/react-native/template/android/gradle.properties b/packages/react-native/template/android/gradle.properties deleted file mode 100644 index 5e24e3aa8db431..00000000000000 --- a/packages/react-native/template/android/gradle.properties +++ /dev/null @@ -1,39 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m -org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true - -# Use this property to specify which architecture you want to build. -# You can also override it from the CLI using -# ./gradlew -PreactNativeArchitectures=x86_64 -reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 - -# Use this property to enable support to the new architecture. -# This will allow you to use TurboModules and the Fabric render in -# your application. You should enable this flag either if you want -# to write custom TurboModules/Fabric components OR use libraries that -# are providing them. -newArchEnabled=true - -# Use this property to enable or disable the Hermes JS engine. -# If set to false, you will be using JSC instead. -hermesEnabled=true diff --git a/packages/react-native/template/android/gradle/wrapper/gradle-wrapper.jar b/packages/react-native/template/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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¬tdC8(rI2H@4vKB$!PNG?wnZ5a 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%0A#v8`o;2BB#4Ms<{ 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

;igAI9{S@!E?YOgr?vDe5R=(F%x2Z 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 z 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
;9`E_aAmd{@evN$-A_^V2WcuRpMR zAxdDLl@{J1Jz!o~TO<2G9tcBFQKb?5gog%p$92XrrYSQ`P%-A??=a0rtUgBiNFt3& zZ%VgD4NiD;%#?>J(Gnq6QgF7%M&EbnAoGFlJEji~`V3Y0@+eq5)3-L*fze=VSQlKJ z%>$1;(Y<0)2qdC9IekRgvF5luWBrECN5ngIclzHmv3kJSuwJkdnDUv^aUs&iAX33< zqt%fzT%@yA8)jECI+4TEN4(DTdKp!}$5{6G6lv{-*$V1pQ?Nv9WenUVq3;=4BAznI zI{jf31CI>5YZc11A!blI(mN6+yf|r^>EXb-7W#f6_KCbCn0ML(YE`DQFg<}pq4!FN zuml;RArH)p5XEp?#+*$uqB3fU=L2*bpMfT5$h6k*sAz;aDJazLWO0ZU_lnR7OG9*| zi_8lWhSA$xuwIDr1TJV4B+bLhjR3Oa_dh*6!;DyUYV;~~=sq_A^JK$>Xl_-=@? z;B_J#&j=HQinIvoOexW7qt+Eou*@?=V}D!_Kai)7EX(uY>m?!NKx=|qpw+^*33E`S zjv@0dGr83taNGAcWSM4HcI0c4rI?!;uo zBjcX&XhQ~*=F$4;1?w9@6tgpRtFTujPACG?IMdmEd?qBr6qS&^8CC8W(C~z&!GsLa zFkLttzs0;zUOuy5JA_PLX5!(%?hP#se{@_R#6YzPqM)VX-RKPDP>+F1XPyTuvaVkc zgb)woek;({8)dtq;f`z@?3J8OXgILscTDj_&XGAQiXowZj76AGaU$KERv!d>EUR=P zPA8^xARiQ$2WkF}$riL3Yf0lh&z&?0aX#U3NQ}nWXfXJCg>{dF@C$UB@wSrsc~ph7 zB7H25xw6y*E^Vw-+?{w8nJd5XE`&1DyqjZyhkv-p%mi8`13`PG^58z5b(Vd(oD<~_&g+S ze~%+h8P)W<6I^jMG(V8ohW6b8qTe8@qsBWOh%tb42Jm*rn-X#+EC-?pVHV<~h=eyp zLqbuq211M+-z_9&QZjND2mz5J^Yb$rhWT3BSQ4d0K>~3)qq>j}M~>gVBcCHtSFAO( z7Rq&)x=Xvzwn%<{=J??kr1=9R$kRmBOimy9#h?5~|K`_!{P+K<`A8J_Fvpy{=L8O`01~4|NMph^|$Qn4Uvtu z{fh1Tzk$8{5ik3hwQhJ(>T3lN^l*lLXVZ?R%x#-!cZlhU9)A~0zaT&Tk}eB1zN3an z>jv>Vnq1hb5#BvBzx#-2qV1pQ>y02^QNxPNaGJj+&Oe}!JN9V9j5>GnB!v5g5bvaL zh1;3>qV)PgJnbCPipT;|30;YKBE&}M6X~GDC4x`%{Xz0ODP8enhr2Q08Vk}CixKaQ z_T>jyUkNfedFBa9r<;-W49A&hg6NIyr4fo@qAS%e1kQR^%YMCQhE<; z^!kFgGM0M^dz%q5L0<_A*nKBi1TkzrppQaae?ZeloD;qWh>4z`$pmEkLndi-1I-5_ zH$*de67Wuq0c@d*g1-=~(fSc~WAYouj_E|{Gu{&A9+CZq%8lL&t*=-*(QBbxzEE9; zQSuO|+XbG+a7jPD@#;|WyNGQgLDyp@O^rBhWNm2r8lQzMgSVkQ4#rR~RLL~!xL%0q zgr#rBrhX|*s%UdGRxro5LV4Lh1&fhDqst9V#(ulv_a6vS(Ez<&a5*!mI)&H^geOWD zLN-!x<`D3Q;Th8Mk$S&V$_6c9`${L``zxZ*T4afVfU~cLgpHDc_Vzx}?}*bC)h{Ex z5e07rbj7pddSZRt;NI{)VRa`kw&wM6!NVDx7`x%?NxNmQ$G! zPxKDnc0364JSyz410Ns^2)XZ|+;Caxn_>MGD;+OKGzz9h4+)hC4N7^*SbC41PxNv{ zyCC7ne0UFY#BGDy6`l|9xDrBtd$_B(XOjDn20R%&>kDxBjA0-wogzdsvkfq zT{3%hgo(J!xSa4u#Wc`s#(XftgaD->zEih5y(*G?3>N%EeRO&kj0x*D7j4F9QxK{B4^?t|gN_S)13n|pW z1oVwOo$$J`wZS0typZC7W$BoMha=Q09&RWRJkyHcQ4xdCN18h>XcY;m$V#N7Dh$}iT=rL2uJL-0& z-#2^@h?nucA3p)z??iQa?WjZKfVxvH((KCSLvj(LpuN(!SDYIX8vAbSRyiyM{6;Gq ztBql6(#&fQL|f@@9K(bl+-yfh2BTAiX))aI-0u)Gr1VVD$l5E!nRGnSi_$~E_Ck5A z-1mlf<1h!}e84TUOqu(3C4@$)#@-FG+Onj;L`szbA)++m26> z947*aS|gr>X-;(M%pN$-CtN!7ymPr!?)QrMokKVi74}jnrUW(Y?deh|l!vfnIL$|< zBzRqMi)=l;r6Qr<3bk#x1_bD_6VH))*(r77oFXDSO&fg=$TT5gCxk|BD|@ZDRKy2& zD8>w;oKhnkI;x4fIUWR&jB11;Y_~R~NosGE=}2d!@AlVMYJVV25E>E-WI^{ZmNGG+ zyO8u9x*X6Y;;v&!*3S?(V8eGPw~Bg#XyAR|PiXXR^tEDUh&c0nz&%iUrIt>Zgd76( z-YFZTm=Toq-pRp11Lh~N2lPfj2r;1@tT)o}`Hd%+&^LTX-vi!ZnnC=8zvB4r7i1pPx{ms(Rd9$=37vti3B%77@4IUu!j-S0i6ZS5%Gx}48jRa*vlQw6>A-P>{JnKuR}=nr0A0I-M}|Q z`dfoJ5En9&CgQ5&T*hK#O6Pi(hF^YL2B*03hrwuXjj zeE0Srv0{YyjG*IwjL>RfZ-E$gnndE^H0}$%lhBczv&)d?)CcWWk>G^%jM+qx6T*c` zChF6Wlc@lT=|b-tF?T*ZEiC82Z8y9a>D-2Z5P`6R2;IO+MZDvp_}-8NY0iX$LJwGt zqYYJV(04R{Lk#1r(`_uuRRd;%1|cwy-;+87MW=$qJemOgf!GGU5Do!}0em9p2f`vq zp3xM?QmP1U(-@wW@A0O1t7s~i7c_uq!OMfH4UK1(^Lw720xpfVH}DUb45#==oUTX^ zBpt?r-x`n+d3&AbuSxkGl6E9Lkhp^=8V_h%U|K*TB7r!chJZ+4u)1M;B_BUB9R?x> z{Xz`sEd^P}AU=n;WW1mOVj9d&pDN1%vL|*cguLP2u%4L~n4g6ZpULxqe0)Z8XE~&S zhB{9KH=0F4dOz5i8i?^gI=@3t04vpQ9HyNZ-}C(KKUBW?y}$7P`07u5`+q(B!{7YN zf8}5JU$&p889xsIf4+Xc{v%)Y4`2SVe);iVpx*!NU;ZEc<-hws`KSNM|5AJW=AXTO z|F8e!k01Yad8|L+j~@yA3ek78T3GLYjsB&x+Qzmu%KD(~nO09sQyT}FRwyfUdxz`| zvxPnWDYhvihi}mQfodOUVIG@isSr+-`iT%S^9Lt%rPVLE{2H}8+vO8;`a`B%2?+J& zCqnrQW=0aJuT?zNXTbmIKqC1$0wxU!8W3F!dXy>a1nOD z5N$`TB2i)AF>_#sa-%;k@OZFYE72+;c7mR8eSW*~Iq8@vdM30Dr%_)r3W#Ua8#z18 zH$ZWji7`QV(4-(Z`_!oI8TBK@oy`^79qxr!NyvQV{fNMH=hU(yLAqd~C}Q4_=~VY#E} z3F3*;&R95MR^C!iLWmD+>$K|`8pOkla3A85-ErH24O&GWJ1)N^%qOxr(q2e;Bg7Lr z{q7LM*b5d;NctLoyb#(2N+hgzT=uaAyfu8PxOQ~;0Eh2JJzMSVb-#lu#F^Ng^hj9F zkRp?vvG@VCL}aC@(L_f5SqpPI;-x}Ng&eWmMrV*VPJNWDGa z{{67@ZU>@fdV{tV)E>|(bpzEM(T$iuG!tV&`Wqi89nfCkaYe+&K__;&ZrC1iGit5G z<2&RII?qT1yT9VLqssw_M$&I7eZ%#YZackibX`eNhE%`|vx)8zUlMWqEh=qP9^wwC z2a+1@J6?|ThvTBGuR9@t_n8vM!Jb}ud@|IG{FDdW+J&}dg8xMAJ3(I2e86y`tptRw z2hfcoH+m9H^dL$B7MQ`7i_KQdT0CcAlOcb?{H6epXs(BQy+4TEx>jn z)2~b4tbXL48Qu7#eSVbCGD?G}#G>^ay zry)%2?TDKqNlCHOYschF4_B-Q+I}U?6M9@Av{5TuH+FT>l&JkW?2)BWA3~na1YIa@ zI6@t_zwDvJAtNk_;?E|@tQXT*hGE2Rq}Mq5{O zj(Gfl#}8OJ($)a!fwT#$9a{^^8N1K8uXxPVbsr{Vt*8e2`u(WT?v?fOBis5wdl;Z} zyV6U=B|;xb;lY4>5M^brqh>pWG%VKE2JC!#Pu*8!f6%syTOo%hya#$UBrTY9f?US$ zr$uZzV0NN!nJ`t<4BLlrfoMp*j|aaH2@dt%M%Buk{j$?IjOy^Z4Qpv{Omo2fg!MCd zdO+K0^-K@OJO#Wvp+uD{iQ5CGA}yn2+>dOx3)&%OB?qPS!MaSkU@kZh+OFVA zcSAXF+X@6BL`ZUEdrVk&*8PU>x4}x2i4Zbt$oRHnv9g4TW%`OBl`rc~cOgh7r)6LV zdM8LE=T7Q_oAziMMJjFkLRc#<2U-vGuB70giFpzxsZ7g4%qQwL_<%9YNSjF^aPyUv zW^&l^ZNq|6%FJ$oBu3QEz1%T(rjSr|#2Tx0rj*FV2@%wdoeCk+#MsIV7^;QCB$RFC zUY)3cpiXosIK`DQ4jcnl>Bb(~V8Qk~hiFt2+Gg}9_@txG+8uF2tfAsGiF6VkMn+o1 z06|-$RV78|5CcLQ_G)RU49n?Wfto3sQ$uH--Z4p}mWIyH%pV0w6;!d-@Yqlh=mTRg ztgm1z)J+N5nKXjTcv+dWquS_ur(F$9MveOV;9d-~K12yNBoGoEuO01y9y)dGnnsm2 z2D};fTcx+av`nN)p*SrVaS^bH_X?Iq?T-X(NL4f$Ef(AgzWGQ_%MNCEPi)sAP4KBP zz0Y`@&`CKRXC`~Fm57_rtRq2)IWZk(T8U^_k#J#qy+PXv^F%lZw(oeYgy`4Ah zWD891zDBcAx6hOknGa8N>!=2zX6S`{P~ue45J|@~Pp9AIGzHe}6$>2)A`2cO?a?XL znR7xV;w*$1$HF{hLL0VZONwa5dn0%t1|=n@)&To3#}=z2aTR93QIysVx2HWeCtRE^u3@d6Uex~b$fLi?T@Bta5PPXJVUUtK(&q4hU`ODXVXr~ zh8CeZh$<}vGVSdgx{#+6b3Rl3PVYWgjGPEeBzpahmt)_9Gl`;&-@`~+_mCN{i=o4Z3hWY(B^!*Crw$Oqgv zypGzwrURm&Qc>g0UO$cVkQQ`;DD&Xx=?vwLZEaL%+gt5d44(w=9qSGHgxDD&l9tGP zc*lA9!0CCWua(+t*nxb=i&TKLAxXebqu$$Z7z&=qhXc#>j`K0G)mKC#-oWc&RD44o zLYVfzOQGx!0(U~3FqC+BPdYte2xg$71PRPxw9HgGOB$aEkqTDH>03gW$Ff6|tz0lh z3bs{2gK~II=y4){^#Se5VM$DL9I483WyDH5K@X#f9||Enqv@IX`5k6AQm9CPIef$W z@BZQX?LY7r{_5BNx!?cq=Woyd>d%vmp9g?HUq4@e-`79?-~I3Xk8eNzYyZvm`1}{^ z`sKg6z5cC#`tjo*{Q3Krzb@q8hao|* zMyxwo6c=MV{waEUkK`4yQ`(JoeWlBdUK%03BjtBAZA@XKy+FE6R1i*SRwv8q+(Y_CSgSPldL3yjHLy<;!PW1>c-gY3w;BV0G3fVx;wVL(r!wR6TCs0-6~qkNGMst(;d6Npmswn(hGPg$n$|#7usXT z@=V{K>DKUA5TCHs=oTO!2A2s2n?nq}HCnsV`h&2p^fJS$SkKsc#Y@8vZ*>h3IvvUd znG(x!CLI!d`~_}Llv^JV{Qz(zNT<~R3xp*g?CAMGNZ;Yonf!)ZAB>f|VS5^fU{PdO z)V@XO^f2S$Tc`!KFIalp%muL8iDY)&XxfSEO5KE(BYo?%bV6`W$7g!^jO_*68tM1} zriJW*s35b_^c^mZ;CFWW0enZ+3Svk9_GZmd62F#weJ-Bk_@5I`#DnWnYO*)Sl5$X^$JN z0aGI!XL_kQsep2`hP2?3M|C7{Qdbbs`V^z7zbFZl_V3 zyZwl3WVe7fNBRo!L68j12V*H$wzaX=hNL6LjI<}(I{wV0<2}r2rj-qE1I42Kj#xz1 zaXBOHK@a<=+gN9-PKtR{?54)nR`UBNmUqugUf6%TqV|f16W$8ZoRAWpPIwLUQb9Ue zHtNG*uebzCy~6@nqOKcWHtHU^yxfu2u#~VO^ya8FtX2qts^5Ve;{?E_ZdkCJcLo-@h?y-nU(4tx`Iu3o~Y|}yf?KFpFTqSOuY_-ftV0_!qbk5 zlQh3QtQz<$ftjW!V0(K{J&;)N(&@A@OfL+!&|XFos2z|r2A08gT(2~}6Js8mbxs6- zBA5dUF*(SJ#0_^vww;~|-61b8xV;RXmiu6)#zamNI!#~|A!EI>^@j8rsRt-GT3w+Y zh-rq0)Av`b*D(~-2x-RRsNo{-XpaYJPLy8Bu@S-nwZOc9xAexlyrZt9xS`f*w}sdH zimQxzrZ#%(v@M~`L=}RLL0L#MF$@cLoMu{7f+#A>5D85iL3XI;Hx8@QgAM6GZ}g_5 zEVL2^ZzwAg!PAf&v~7URZQq8iJV6VA-7~cWQjK^!v281%HJpv^6LlFf9<80=5W3K0 zV{H#a8d2ZD^bNh-X`g=}6sLwGf#DeF3?`&RMN>ql6{M1R$KE=Xjz}kKph+M9E;F=_ zG-M4K+Y%N&&?S)kPG|$O5F#WuWKyDl+D5AlDLePR;y{;5E{;s^$l)F07t|OJaWN9w z;5mi7pdN|Z=^E+nK<{^sOQeSiAz`JnULUv(Y=DNZ@o8o26MbLFal<9yDzNVKn7G+W ztqZ+7=2vJNdk@S}$lB<4<9acC7g`r$8!5X=hupB;Fy7O}F@Ml@fnz1)QIo3|#~9DX zJt}I-Q#48wT366Eglfhxi({;t(wYnoUg{ikpqEI$HuT_cOuQLGaqAp&A_v1$AI8{l zVvY%m;8Vf%K$T|_sa7m~R!>-7T z)7UB?ft;0T?o=Ahgtc#MmocPBNjV&!Xx-RuJ8F?QJ&l3P1RBB^ve?Z2Wmu8jY}i26 zhb^>@ifWQ!*zC2BKU0=l#GhtWu~L#<3jfv>ox=$%P|6x?M<+f(?UGVRLa|O zI-<#keKs6G-+?rI8`W=7A*P9L`{3YJ8~3Xa#(>ui-yC`yX4W_nBoYkb;XS?f!N07X zlmv8Ue)!`rTv1D(py)B#yB0@-jZ}fHt616Jc3n?6jb=!BmFfbG*%!i5Y zg&YLiD(h~f6q(Nxt_!MnQjDZLzg1F?^j3J3&bB%s7#?AsCPXu~2SOAyY*^R_SJh`! z55(o^&E}jz6RtzR6Uj(Y^5Mw&uu$uwV5|F#h+zG|@ig)E zw;wSv+P045WPHNoOg_v^hXZA6^j?T6WF110=65nXQ5zvFv>M-JS($2`ki(D+rUTAQ zTsm`bQaF+36EROjJri{crsbzW?|CrKiV_|4v*# z{lVAQ@BcNa>y_d!lr57ubKkDqEOyVHlH z;ua%JGje++Ety&$Y?nVk*1w6gJEbam`GVcPM^V^*O~3BMz2W~DpP*Jk zyc74rW=`WhR=%*zPCiFO6QMc20x}WA>GcNtWx&7JEAFqvq^S8|cd@YFZkRbijTn?J z6`eBChf&HnB6Gmndt4`co{6e7pXvJK`+7OR&{@xD;*6_pp}InfRiHV0%g#Aosm`m2GJk!ooJx}HD&S>mFI zenuWQ%IyoZ4b2No4v+6~@7S8?{YblRBX;g%qc7**eKYC3pg9koUikrge4>{pq*jtd zdd<{BhvPTkPQCtw|M(kPdqp{*6l50qJ`E{HZJVf9YE<4tQJQsS(_&RC^O&d~;6dR%J#J}tOlHf)If?GaXM3W;nN@ffG>i+`x-Ah@vx(lft+zRrul{D8S8?o zL5$e;6H#B0X~G^G+m}x~ZdV?kZg@M9PZO}?a>oxd-9J)GLM@?oCiFn}&-j$ExDjHa znBm=Nwh`k(XgZj5Q>JR5IitGID}Ar@-I3#abcuxW1ImID~h8&*gQSYc%GOJgO74Fp0;L!@LQp%~+WPVb4`h<*So*mfnFBOzkgn~^k8whiov_ff-S z6T0TXp{xzJiPv6922wlI)W>JLO!Ud|UXj)jeK)F6cZYr4YeH~L+7ND7C3Hb*$6`aJ zBRY7T+5)XXv1g)egl?D{m7O5M{qjQZJ9|{DPLy&ZdSFiPQB~G$*s^nc#yL~_D-ttN z-ywXBER_@j+9G?q<2ZSCnjcvX0diq_e#UI3yu4u3#QfDS5PNXnE1f$jC}~>gQt=Je z3%EGqyrr}|Y71^cqElTkI%#R3^IPJ2N9qmjLY|e)4Hw~%j2zA+6TEHgZ44DQiNu~q zlHUtc8biM(oiM{96J9bJp`|>Q4E2iPtSHhqmROki1^c#Pw$p0mu{)juDL6tMmiSt! zxsA`Q1!^s9k4_0rl8B3AsZk0fHI~CWPLe5Q@PwPH`veOf{ifBLqde6Eq_IIMP0QLl$V8 zFzK6-Rs&OnJb#Pjgy_amC%W$3S16@XZ%(9B+7OeNG~#JOmyAjo7>g*lKXHHgfpxEA z5!IELMq&}#Tav4T&V!HE8CBg$D0(8G*y@DMAVZ9uG&zUULb1TQJLOSHX$+`R7=~L& zAWBH{Sa_y_4anj3XXNOGb)5he&}rj=KMcVbTTrXw{UKw`q$VDcq7 zB8(xa>ifZ1lfvQrk=VYB0c^?!8B&E&}bR$xz`$TA?n!D~pF3~NM z<|Dmsq)Dh%=;owl#v~K76PNeIsA#`adZ4GkG@nrIG=C7Jy)CC0Xb1zWalIBaC@PV) zjg)AP!d@GyamZ)9VXYw^k-VYlO{Sp}nvaBOCdf3t>%$GPE5c|GSP8@GUMhxhIDI7Q zO6hF~x$FSRAqPUrh{QL8bVBnPh-kPDDNGDVT96>*a6s)r*?&#lu7q>~T}E)iDiYq) z+KSqQOC0~^+R5RBCc#?(t3xakBD$Q3S<%>u={>Er!Aee;2jfA)`Yh>88>C(8C9E#DwP2=<_^4M&+{=DqAh8G@2#oj@n0g*oRB&)47oWxu)o z|-{*Pe2vETn)tX`=vch>8j)*@RuaI=}R zt#pe7J<`8iD0idxgv%NCLY))Me>tpU<&O}(BFhoEJZP^gp|13`!CH{@C*<*k?ezt- z!rqTGb37#Gup<(Q^Mp&H-ygK?f@BD}GjSl!$6?%ZCw%x_Wco;d{S{^#>Y2Ka)ROy# zrWxiV^>`SdV=-t@UpJ)P2v3bJkm_|DvRYw(c_5`?SJpuZrTDdmhW zGqj3pLqms22@)xfVQr%YaA<3xeQ8*$tY5yzZ$`g#^3;jx?ctR|2#I#9U`j}e#)#Dm zQZw;*#*at5HQHL~+XD>=IV&wMw9Ai!FSXCG?}WA?#9@woT#z#1Vn|;p5)qkL-hW4p z-{Eq_Z9$m^Ps;Ad6lpIBJ$yh->HP~H9&gF2m3mpB@5Ek7+Gse|R@hdO7$GHkSNw9p zUamkQ93mP5^ZALOJFOYLRYFj#D?U|XHR=u8b;s|Wq!sTA@#}BVwqwo41CSJquaL*z zLF|g_ky%&!bi#Wrz}<-xEX${U=DHzO3to z%O9?&I`jL8Oz+t1SCrjoHp9N*Wy0;mUdGSX*_ltBuw+~Ue($(L-<{@x)(_0-8BJHV z`zw?U*(V!8*NwpHR4eMY9i602sN%2NLe@8keh*wO99o*KRsA)VHrj+sbPpqE{ z_uss*-#?AI^YTnsucLg`S^VC{rGZtQ)>Lu5HTbN+hN zMcVz9v^XjK0@F;iJMNt(7qVWcS}?n_q>&V9+VSYf&G5ccvW+4B;{hSExg!>t(mvQa zDG`=$u>J$B+?djd?i)SyQ4j5nISX}flx;=h9p5|Vw_*Q9MxxgmzAvMJ<~D{|(%CK* zl>yFfmqK3VQR)729Y)9$(dC5Ih;J)BHm0c(!bC5H(r#EZL>20h=I`*wgAg~WLS0uT zYiK)Q>09CiQ3B<08HZ^VWO~PxpRw(g(oXD;JGU=C(bCrhJ`8(lSFjnjl`7+R9D-m; z-b4q5bU2fyBPN2`aqy#x4@Own=~hO1&>HtIuc)pNzQg-Ye&?j`&UpO+DTcb^DYKR~ z5`=CLHhS2o_l^)oqP5oX9oQRP71OWK?HM7XhXWxtd|C&SbULwn9}jsA+$R(x1)%j& zc@rg`0@#VZZ8$p`&f`AEozR_LS3Ct`>+C=>M|v1(uGG<-z!$_1m@C4BrcS3bp)@fp zM%r4TWugjgf5DRz(@ZdB?K`5KBnMQVY5mTuccKP79niia`$}zJ2*HT5!NCaf_n315 z2sC?u2X3D?db)FZpXgU5vLYt9H#&|*A@zwp95H?76m}$T1Ts^cP+gefm?t!MsDZuT zk*p+}iSdDXWe0N1=rkiiF&8%5FbDPXFutcq$_YGUx-(DXJEQf$yd3Fm<6a}1cB%-E zdZ)I5p3qi73K|dGiy#6qG)w{(Cvwc(>)=&cg#!WW4Q+|iz?V$1f(nQpFx{~tXffi` znd9L^4TVQ-cGu-Jy+$OCaYAyVmed@hU*9cu4**|54(TBq(t zZ!^KCfv(7ouY=7tozBQ~qFqK5@p;YJ4jG8jG6>|vx-T2`|KF4J8{}jbKH*vHj*|zuS`M`R zg6&^W%HZqv`He$%#Wi47=vrtc4xEcl&=sSy-d4=psOU0;J~0)J=Wl4c)9VEhM_h0z zxNWE=oR0S^x7$YdeWbh_$dr+o5fQK}7VcPW2p}SeA82bCVvD#z-Kf>b#}gqAR-+_g z+wRn2AR8Jttc-Suo8o&!Wu)jdO-K_`&eYOKaV2P_T^sI^?n3W<*ryMPI4u}EGBwC2 zCJhALF?qWOdVNciO}Ka54C{puGsojIDrYQQNntF0QdaWxOvsLxjkRXN6j4iH3lazO z(1h`s3qI_3J>Wc#d)>a`lE#@b3EpoIJJ?S&H+s2adxGF7`!EaJI%17&RJ_er`hLO7 z4eUtD6D~XAiM>2V#lDTSrYOT~%V9hhh$8AkBx5Uq37x(}mkE&$Z6ePzK4rWsed`c} z#6;U(urLOlnSe|IkrzBvye5z{^I=A{qdL6}CU;On!ix7BkI%nm`|))&jAX(4gts=D zP%Q%yw~ox)c-><{vVuE77-GaQjr#+jRIC>y8pq|phd(~S67Wx-d0dmk@b~{ahd=k#|NG|& z#?RN!1HhlJzptzR=JwV9{Ga*f{;~h*U-}>Zm&?n)^S`@)`Ga5HKK~uoPrqU>FSNCc z$B2AJ^LMBOw)V=puarK~NN2FUlzD?(k;@eQsoW_RDTa?N9z5B zx|dPw3ySqXd1>fwgm9y?Qw1QCL!$1$F{9^?NYC`yNm-D-4`z#OOv`a>G1mv&@7TkU zdZnr2hlI35@Cmnw%m*}`X`YeVi2~d%c)ik#q45Arcy;#s3bzZrHEg{g6uggA4)zs& zPpAmGIdxN#HP{OrBg=8Z2!oT69nplX0g;N)sWr3za38#v`6EF)9wJ^h)}Ou%246mr z@93A+`-v4Jko-)g(d5o-{1C4bck^+??(c)SooMpDIPMQexqjix`~B4q9a zGQ9~NXDkOSMU0MGp~=%2#BO&?XWH^acBuY$Xaa=iaTsl2TOh{EIH)?*Pj?=d4T&@H z>1#9|spWyUh}DAaH@u(8%P(;0^oOu{BR_wQtPd_f7>`dQ!RQ~qL*_&xV#|W*iGF!O zB=LA%V0TnHt*lttu=_p^5jd@$@%w{vU2&ce6SlezvnUfGe2Y%+pk2WqVDD&;nPxA9 zQ0e8y-YPMlhqOXxdI8E$)cuCsuTX{imx^m9F7GhkaaG!544i8j75;v^(%sSJfJ-FY z@5ERLDZcSr6vy!Xpw|sg2SPjn3tI`atut#wpT1>!I$`yJZrk|&U>!z4gwBL>r`H{I zK}w;TqZl2bl}4!>Xd=!>{OLgX^dmp~>Nh;Bkxz;Eh^*@;A`!bcu8#|eL~V(XM#Wwf zbo)$eCrpl5e<2oUS0hT`>Dz^H+~5KAwi6^1rW2t}G#;esKwc*DbVsN}dB@6!VVnel zbd*fr8?`p3yp!L5M8Y?8yP&e82)%wp;sa|HdsJ#qs0VJ3EBob@^J#-9h{3*Z-0#j5 z1PK{S%P>k>9$S79;D{B6Jd@u)u{|!d$3{%gpoukBVy~zr3hStl+QjtKvG#=+&S(c( zBI?AAourDIv7{ruD{f^}u~TQ;E6FFKKM_vv$XRLo7ZM=7AqFW6!33!*yYG}>cuLG> zOv_4$1+3H8OyG~ClYd*)FZdtDI;NEntu%a!}}N;MhZ!|c=s9y^%_ zA=Hrs$`h@v`0b9{kwPI6a5d5)j+%add%rW%J+*CgS!vUb6djh@zGA)O-e|o*iztzY z7lJOtKExKmjh1#wKM}Pd))Dbx>(!3znUtOg`Hc9)y4~q|WOf~r1y`1wSr#Me<88<~ zYSbEF)j*fZz8ew`?Cn4z&?aT?3whg+X(seYG^5^OFBh;zT4q8Vc4*;1?Gsaq2vDLD z5cd5}ZIu)adZEb!(Fm@D5SikFdZBtD^@5ki+Lb6D5rb$eH94Cb{a(=ohddE`MAJl4 z<$Mr?OfkiLC2$&P?r0Rhv2J(P^+CB6LVSW*3DHQN*xP}X0J%U$zfPJJ4=Xu8aY_^O zG!k3dS88`UN?#ofuoDPj8_UG*w9l3G-idQ%$`CAI<%L}{6Eo2q^^Ch?oJKlka%%0w zd?e2Am{R1iZqyRT04qU?jj}3R2|V_V-eF0?5;H*^%|`PE-Y9LN6v4wt#L^wHg+V50 zcnl1}-!RbXJSu^PzlqWsk&X4zAPem=>fJJp1zwyo+cv(h&4h$wi%|QWa;|B`qu0-La+(#q3#!g^GJ4&yK9&nsE9Q>-J6fHYkINWz>>wDD zo|!q)J<|iUe#0HG9Sx_!Q`>iB5v&wqnn>q~a_?^guZ|Ki6~w|=OdO1y$0EZmF&}5F z7V4#=xiXzc!rZJ-T6(jq&$L#Mc|y93R?WK6`-QM%%p&2CQ5nGe3N`rlzJJ2(RkGi%hBAMF9fI7s?beOPS zu_iPzqKsvXsNta!5dte_53E6o3n3;fbi|w(7NiXmtJ_ZJtrnUOJiq@X$KyxhG9$hc zLPA0z%ivJ4!jRzuc(!AIR{-DViIBJ_<`I_m#ThCn(jU%9;5p5^d z`wP>tBRr1}y#g5Ecqqu8a8`PALX5Z+kO%Hz4DLdr*M#jpQivLn_(YIKYn`l0&I2`I z-tbxxpQv`kd?9E;bY?ldL$qV0F(@@a70q#sJwhg^AQB-BOSeQ&>C7P#^_dvI0*S;B zXnW!F-~N&NPgnNtXb4PRKm{So+&Mr6a~z5Is}VgGEgeEOUJ zOu7BxKfk?vFOM&Oz+MHv{0*f4fb5QtXyGII^yhK=%=Y*J-FKpV?nVN*buS#N>BD{E}bw$jT1|IOdVY@;`2PBZ<`@c0pFhKYc@ zqWgw?u0(l3(~jAKNyXZkxUb}NB7Atp%K=`#uzZ{eG1Kael;5#`IbgkT{JIVsW;vnU z2}>l-&*WvL+XbN`@kqVxXnl|mUtuLvA0UfB540czQMw&blyrO$PT#<`A^lEYJFP9~ z_5=DZAyw(yMtgi2ypQlid)%;E@pPaR$j#}#jKs)UkmPXrG`LaQgD+tgvHe;>nmyBsGH%_1h*^oI?=!X%=UONfA=+VNYwI$l);uG*l_^s=QB0T)axI; zRYK3`{u#=hvVS5>0%_rX`)O=Xmjj(L4nEf5a3Wbj4tG3M(v;clnf7==yi>$T>yd*1JgT!<%#(?;rC9x{zS?SQ)YgCN3=22_E)9x%KcI~$P3+JZ;V79g?lOFG&3C` zAD#$ODWC7ON5Nx&w<<>63$a59f;=LJLn6zSwl(7N6|HBi?1Uop3TYX9n`u@gOthQ9 z9C+LUY8$mZ2znrR$3uX0pzAZiURn3bq#HS9)>k9;j(H*JPKe++;nM(DTRRdDcQiCY zoLRR7^-c&1@qp?A;Yf;~!2^9$OdXw`M>1e5D2{oh1*ol(F|0H^t~C9Q_4NzbgA(tk zpGnJvr3=l=VCJY$@11nH6Q_xS(n})5Ol?09tRZcs_&h3B%R=?rn~~74^<^ZNrW2?1 z6|avC0}gXW_KjW-P%Eun(4ai_D^FX({7frXa#loU)@z_vAsl_AAJ)bsJ6Q#_j{`(M z3-Ku+EcCK5b)#xz=R`~ixmuZ@-uusX3-vW_|^ArafgG95^#NL?qIykes4 z`9PG09dEQfBKsNNPt>pxJHu9P!lSJO*%5!>x4|M60!A8!z`n61NXZDca9@8*+cw%} zgmxfFM$YdkBBYp@W}&v75>CXh{)Z1$ltwFsIzx|%6a<;CXcHtl#4L1=)S5@lla*4TAg)$<(w9#(78#X z%9&6r`?fKM!Z9wGH-bg1p7F4<_@s%!FwH zTk){sQ$Tvg?9Rg~-j0|B!kma+xs^s;8`=!H2;F2P*%u*7BUz{POs~Q@Z*YHrIFhfJ z494(Oh0+!GPMrdKjfB(?U-7HK?5GQ+3mV4o%F;q_owYRF3ftZ| zJS>pM@TA!`gc^I}`D@`cE!=MpnslrOr0ZbrJ#{=N={e$FK>Dbjw~5!iBe#xeLd~i1 zL0AlJg7=BoL1QHxGxfUTbaVo0!7t7_Lud|7AVj*#NV`!+Dl1ONNeF!iH~OW~S{;=> z8HkV48N-+|BvBzM+it`lc(1(P3-6MQfj<$>8Izs5c6|N`Yl3fq^zjV02fl5HC1NlL zMmQN#D}7h|vJ+0w;!G$Ff!0Xt z1L}}!)rMv#93ixbcIej7(-mzMK}LJS0DBr~$Pf`fB7Vf%9b+S?p>#aXV9LIIff$G( zqJ2l?9YHph#b7Ihlvr1RFcarHF@iTCu@FS@7T8zEdmQO9KZE{Azd6hEM|vB>It>%u z9vG1vBAOzu52|g{UWU}7U+6uu5r798M-rJj7BU_U`md4OGZq!g`&e4pd-NFaIwtFG zN}S@5TRDS0&4SB>(kSIf-4;AIL?Y@D@e|b>DJ%#^nx8l=-%xcO*d~9B`-Xo2EvT(< z4umk_eW#TT;f!WRD?vswZ_;nkIMUDl7ADYXLeqHeX?h{$6EQAWx(;DbRJ5frkQT#x zAT0|*q^p7owS)J}TJJ2YARD>Ttj=?5f6Tmpm*;ewO{ zhafx{Dc>AAn?-b5C^gc%k#u6+@7%5%^mi=BOo|V(#JB%nCN&}S2g-t5!m1!^BAoviVVS{&d^|8M9i0pJFHrB9aMKM+Hfpq(M? zn9qQ}$~^Z(BezyHgB<@D#i`9F%t&%D2%ub&5iKVScU27kLp`*i(B z>fipG{{;5>&o?7(Z{bSC93h^~=g-{{)LbZA@OM2e7iSlPP*+ij8h7lQ!!1Les_^6>dt6??=m4BRL7Rc3S6564pl7-y=>pJR4Dt_~U`yKhnq?^oF&Sy(CzTW>4sTrF$KU_~(VT-BFFm`FANV ze?*+mkd{%G=wGmwv7%VH5R#$lSX~L}h~VIkYNM8I)N9zN_Z9#AAkKmGE|Bt(yY_Ji z%3&M|O|Wn#d8Jn&Ed`N=wG9g|=zJz@N9=J!KTPy^!sbYtuE?)mx!rbRoX{p*|L{tC ze5R~tLfq-MPsFqUMwsv53jA@j{~Aw5+dA@q_*gMNQSWzJT?aR2-v}wAbH*<}QrZ*Z ziQ<*4XKcN|(*->|(M#oV8ObxR6~vjLzI02j5IOxgNkj zv)`Sd(90d^J0@pHV6JGG2AtjtzBN`+Br9#5>0ODMh-#QO?k^Y4r!%d8hjW8=r_rc; z=X{!pKI00C)BCWR#yNtGP46^SLY%3$m9pIs|0QM*s;($c!`|xaNK6{^aDygXZiT}P zCBUPPdgJsA{kpILyH4cwPJR}SUmr*ku~w0N9|z`rCo={Sr59ugh&-`0Zy@mUCc$wsRz~V>kqgxdd2b`B`7}`!`9dN=Bp_P|Q2-=M{v!|+5EwZrWW{Minv^RPuH-6`B}!Bf z1%xY01{rCI6 zZD40cb3{~W-3aMHh@CtP$Z*}rTLe$EUFdBgtxlq2FOBw9wh>u4o*LRZi|^F45s1|N zmE?((-r?6s9Cyai8HaPoMsJm280AkG@gOyu2SgG}?u2*G)KU4>ShK4SDa3F;f{M4w5ML7_`Tav@PJ_6V)P@{>EyRxAe-= zB9WEa9ZfHYpHuXCch2$!w;O{8TN;F?6&c$!imGw!oh*fgOpw5NFF1Er-cRG`@<4__ zIXJ^gw-X%Fh&=ioAB7a3(0VfTWcVQM&d^Lu3TMUHC{{eB?L}E)-T*&SgM^tL;c|L|>?!jF1SuQbH%S1Sw!+(29IL07p6F>9gm!0aQ1=B{6W3_ih}3%UHad10Ec(K^J04FK ztE_tEd{hAgU{zyzf?S{+2Ing&8aV`Nfs_Z%{?!N_8C}t^Ve0@6LUK}H=smK; z!Qz=>fsz8)iH6Sl!5K+e^Ez#{a?nPkz8$0-*^_b&ogoF|0&>ELeAo*2akB45aL6d( z=H%Or(gL+Dr00cLPZ~x}5MAh!XYIKTTsp;-PD5ot7ktZfZ;ZV`nryxy2T=ssd{%O! z;6tz?)1aFJ?g_lZ8L$nKT&6fD8X*j}>xLwmEY-834dQ6{Mdy1N=Fl(NN|zH$GZi?B z!o`T9XbBugN0xykN4HE2m42_B4~W4K1&JqdGgyTBc4FqlDAeB$EZm7tEBdt3cq4{L zHwXhpEu0Uq2V7K%?^oJ6PzH7x+<*LIdKtv!f%i!7fnZ7saWd(+GHRff7orDfv!WYR zX7jQ)+?AMNNC5__vr0+5GV0__hoCUP)W}*nk7*bc8LT-X;|I)t&3H^pw1;iVGoo|s zM!q#-a_q59Yyq9~^|wfHG|sdz>0tC%#(p3np!pX_Yqa_sLMkAc(JPEJWj(c!7M)Tq zab$&H>(`VWjC#zJxdy~LOHPEdvKmM* zL<0Faqy7n9UKmz!eul;ZoJiUrE~HNh+g}NCpJF8qQ!r#kNbj(AXS5#~W8l_^o8VoL z7?I%IJ`U2SmE-=x9Xl5gSk^n;AlU_zMACryhIvIik~LtQ9NkEH5WSO8s9ORarUqFZ;x{bAASUHXum+HG%K`jm{pL=3^BM*4)n5oWvQQe?G4)@teFuzc7H{}Gi|@(?FVG}g4BlQ8(t2) zzmfDA#(OR?(T+STZQ~2QE4nCMGDmwOUxb*SAy<-SqB|`=0fqGA4=hiKbN!ZBzn=qU#;&5#t?{g0vmg0{4zC z2i{&OO}ITzbJg*im2i0je#DmdwEYJdcgp!p3?Lk|8gSXD_H&Q}&6QD{=}P=#Bo?y# z9Eo>)Ge$p=TDbd)+5%dT`~#{BW*ac@%X_xxKSS(q*yF%*#NZ zKME;t^dbcP0QsbRDTJ_KTqa}c+*vOtDLX@+aoyPOk-Qbcn%LgYTVhF*>!MlU_)NPu zJgnIGfYb-@8^Y7dXb;dA>SG}+4SV~-ITZI_l5Rf`n_%N>Z6LJC-1zVwe|y7ToDr`a zs}W>H!mk)X&;vLdcIq^#+26x`p?8Oo=@gQ`v8+3?7}1n*e?_*4GY!xESTL>l7a@9^ zH>eccotzfro50)g8|d#jkCpfmNbBc$xRV73&c_cJ8%q~V8pJ?I@7Pu+rZAt#E5x*O zzChJL-hM_ogr0xIA1^e{S$94*(1fHXMsT(i>5q!hkPPLmGDapx#arg|C$8avEP<>> zdF(TN*CQ#<`lX}9@IumoH}K<)C_;>iXs4e-^8_Ig66|}y{0kxdf_(F7a6J^0f!Bob z11bCtt$)X8C&&IEUtbxnjM7-f1HTN0D|RF-?`Sk!6M|6&XelhV62p~LR|sFQkh#^# z0}5R5?H5RYAuUcvCm*eMhHjXhoa0V*PG>W5YiirGAg!zL1_bq$plH!)NtG&nU z8PIz{gD~7lN1HXW<(X~=K2F*rQ_qvz$AuOQ_rQqXVLAx*nQpI$L?mTOfnYm_e4*8y z=b-a@F*br;u(WbU$L}36gYhFF!%>}J2d#aWeAfELnQy3OB6o7w(Qsi8gL9AM_C&24 zq(ZP08Ic^nP{)bbig@DXhc9fGC!UjG{-4si6J*0(NV#z~$NVvoXr3mgN;_E=?1W5% z=PO}=HNIAop7C`flm#xo!E0u;#{H!u?c`|%@5Wi3%z{2S7{lFg!DLyDZNU_hPJjyXDb`D0|X}r?S2!6pGyxymM za(%+;3w|~{UYWF~%0(5zOazH$V)#sVC8a=!C+XbT_l;_abo&wSmAnop&s0^?>R8>W zUjzwG0LDm^)>zmex5-z^0S}7CotQ5y%U~PNcz1TMyuH4n<78LJ$A+Ucd7=18&hHU> z=B*@}IBWk$;EKLxnw--hJsNck5|OYRT+%1r$`3?0%5iXx%6dy=g@n*$MM7pB9jw!- zY!mm$UKG=nGy?nUiCznVjD`!D0wq%0gAylHJ*~#lAa4+pvu5Ysh5H!@ajk$9S;h zoveztMjsCxqg4KH&kf`JM9TP5`bv6EKETSm2F zC|$k|Uzfo+oN??_oK+(G?ugDy3zvk|LTj+ylz#5CUC6hLq%sY)b+Q2S8t_Mi0S>F1L*2j<})nglfj)Hf3u4f%_97%zrkNkA#aL^_852A;$1KA%aQAi!&aDc%3MW z5O1J{pHHZPTqE8p)(j)zwGqMxrol+!AugzFjPXF^z*-@tjD=Za6(95StSiV1es%~AKLuTW4*CPOCxm6T zqin(ZGV9~HPG+CYy;UUQInsN<9!hmVN|1IuJvgiQ=IX(I8-cAiCl0AdSq_bp&$SNNJ=`!=L5- zFaF%)_Wr~F`T3XM{F~`d-+p5K{j~lIt)Ccx|9`sv`oH`?{a5SjKlr!K&;QAP<%j?D z|8{-(C;tI&zy90opa1c@*Wdifd-wY<;v(N!{SA-LiN}{WtlG58QVH#WxKqw!8Z@64 ze2w(}jN80{Thm~pwU-Znz8S;-p}_d8&uP>A|M9D#AnDESZv8EhZk!|e&XzahQAk{}$k@k&fj#QZz> zSYW^70m9WO`w12%JpA?7NIfAb(HmL@lArMqP=O#qeH^%TR9949=51gz>T%M}H%x?n z9utkRDOiO(NYBem4weE2F4HQ9CB!PD7m$M`AB=31&*6hU243!*`+>xPo)xjLx3n>% zu~GY-uv`f7!YD?5ZuEG=wBT3ec9JMLyhp-~__VR4_w@S@vzAlB+$5P`##g|1#k9}*Ry%0j zai8*my*DI35n7~Sm>8o9Jv!QUg1*inn>lYUcUs+P$H2yKX`!Ju$Rcnx|7lyg-R`zv)%D=kk-g~_xYadM_e7H(OcxKD^Uh*KyX8nQ(8k= z@qHoWXL1Up)DSHY=jJ$!IKRJQv*unpHD|0;f-2$}mrT&WXcdu#S`wBkDc$hHIESGG z$b;bpRO#u76qk9}hy^c&5aUb(_kc2xF=*{QML_Hs?JF?_g1|V9Y75H+5{hI&hO=H4 zgm=^qts3!OsUA@=a$FdTP%HC!6gq@BE$bD6+^~Kj!~->>_dpDW%b-8{Bx+MY&V+f@OXqofvpgj)SdE)gXhM82bE+C4RJKdCZo16UOekZM! zxPlo*&ysjk%W zLe@8&Kn;l=7JA#kpODLy<+>1-1B(KUqZI%EfB;EEK~xY$Y0=PgBUwlE0KX7|vgDO` znMo&EzZ(C#;Q15P8$KS`5Y}ZQZ68oOhy+TT@{M31IA?c8H+n6MpcFdiUa+x~d*}6Z znj}OojNwxr<*O&yEo>If=;# zvQW7aMqy>8w21Z>${FzHh%F3HpjVW)Y2(y|VV$nRCXvktS+CeFQ~Z_BpFh*?2jz?; zH^gR2ubUHcn)XP2kTXOPzSNVzPFgY?AL%q|nqYIIFv68~Humyc#wY|`*}D-)xD~{l z-i1CILZR24VTMSdnNz$G^ak5?TI5S3#+4XXWGGq-yC;-EjtTLKSSAhwQ)0-ocC60o z3UQ!M&ah0|2g*rOLom(=`~AevfU6*M+E^LYXf={zBj{jQLzji9@1VfZ52P=2eV)>n z^8_1&#nH3@Ph3*wQFr$H;Nf5{sBTDhygFfVx;th!;^LGSr`3wJfVtAuXUb}HxKF`C z&R2+v6(Oq-E;VzfI_bIG88rUxMMc6)MFhg9?WatP4H&SkxpR*b}1T-L; z$x_jC&@G`M64Eo?jJh{eg`E8>hfwA~GezQd0S`DQeh#F--W^FsKcVbk1#+4U*q9^M z6YVfGDJoynitdwz_D|(!LmAAvY3Kn9k>luWE3B7{YN4G*dcG3V#%NOj7cLiKcB}&y zaD}uaG`~Ya<~Uv%Op&P&OXI<%#S2N1POv#L845{ZHa`-H-zOqA*`e=5OM}G!=H(|K&Xgj?AR%F$494k z*R0xKKJEqObJHX z(6qqFlZPtD6us!juRQJnu1JW`g_sNpk?tK09}x|N>odaKm-W$sg<&fp-pKjWG-La; zE{8CanuHt6^$FjW&miYUzl;T+yd@5;4H(meL|H=RG zU;Oe9|F3`j`+xB7J-`0;SKNR5_Zgr6V@4lnyb|Iw)(=`)@$x;#>lcofU(xqBjEbBa zB`DkN6LNPv8@^rf7#T8%%Snuik2_;IX?9{SFH;WC9P?+~LF^#fD;gTAAjg5NGEJ`P z@c7KRE2At}TevI*)kJ!)m<_D{304)_jqbuY6IqqkKGMtN)8)l6c|~uL7~gUHP_TGF zzo2G_K$16_ciJPt_J%Hz(uG!(mCD$^;PFn{X3dczm~AY#3Vw1w-jI8z^<@qsG!f%L zt)1r2EOa>UgtQ?0D=EVDn;YgG8&CL9blK4LhIhx^30tQ3h!iKJ&%}$-&3IaGEJ@Ml zcc>@Yz9U0uhmrD%dBWNoJ_;6}P!mGDW5tjr5O(Z5>2HcXnC3p_5A0|sj2*K``|_CS zOB5m#dRz<3O<~z^J<#Zg7hDS3=Agl3W3+>Qz7e?3T6cT;YJyC-ZZm4Lte9;?ZCsuc zF;xfwxhXMJbWCeo%mMdp-iBLdACsp-yrJtd`IGj7l*WkfX=lP*uxlWsi0qaA_L<~` z_T^4*&v<*CtU^hI5D2Nz2zYtm;{rV(&5<6cr&Hvl$Bvwi-3Lzj`tVeQE7pYl^8=?c z`bv~WTK?%ExZ+%9Ee8eJX2m3TNIuQI1A6b1ui`>G8hdYSS@1*P@j@8qd|IagN1L3; zMZdCeptVYrNX!OxrTIZ#j2KSh^@8_;$!{=CSY5F5m0?EPg&~8UK5`a=zLVpuNkore zl?EKAaJ*Jhd}du%itU8;J*yTx1Y{god7%D@yPb@)Q%a-6PNtxHL;3}m>r72{C2Qpf zK2wk(PEd7o{E_jI$@v|reW8!nY5CJkwZcM#aN!&YT?(NIL*Az8ufGt~2)2_(otwd` zV3Fw|WDVMzs%2C*_U;sRY)qFyl%*uAoDPxPUTQpgJ08#)^BgpWq$ zAc%7g$5UXjz^H{bc0_)c^sE#5|M|opmAENtiu4DjJ`)siT1CC?Q)aUUmgR{aW@RN^ z-Vv5>$=7d)*MYPH@1X60^p%uAx6FAz@ic+cjYgJ86rEy_+(|C;l&k|?9QB#%Dt(Yr zrR*oCHj?io95-jg_h3f$j?)SG9Svg*8|oWfJ26${4D{DGFrUeTQ_!KP8Zlo9*TACC zG?A7MgnFQUP~7ld3B!p5vKxeoD+nuir_-?Ol^8bey>X7hyR@)UX|@v8IpaH&NHqt) z5aR-I;PEjBn?46Ffyv&o>d4X1K2V&n4s?9sd=w-GhF7F@OhBu#sFSV zMjs3hSl^NHgoc&ol{?pI;T^B2DM6MC6DaUekuccdS)_KD!p2t)D3(2^L3lhVN4K<|@R+-*t`bb)4=4>VPJAB-kn z_dQDQ5BlMp`@q9O&N_LBCJ+oan-hg_M}SeL{H05R>V)o;0GH>5AP~Ybbs?hoSJ{T3 zGzBCORIy=%WufmzND$XdzNE=j&L=rd>55sKcIOSeo>VGP9g#*Y1Mfgjgwau;k4{Jv zZ4%=EbAom>89_2$JDh?^Bx;)G-jMNXpch({X{B$9bs?>@dV8KudsH-L@_Hj*6B3z% zHEAe$iVfr)r9S3gdx72%i@0}Z(RdJ*YUY*(lRFfrd5a@HfhQ{d@s!Xl_%O15*}ZigV6^ zq>z81A&5koB3ASER$R&-eho%7-+=l0Tqf!EE5+Ya1sz z!#^S66S`CeCqWY`#$}C2cw!;p;ekb^m6McrmUtoNz_3ipPei@W#zhb`38T%>fP2Ho z6vC)q@eCplf(LTUc!w17tS2v-6e^j*o<^QeF>|54JTDLZF8y94EvBnwcneT}q&^1m@(29#pZjn4@BW3qa{usqzxPM){_-#X zmGEx)JAdPE{Ehz8gyX06(*W?N_5XAIFaO%V{?8mg{@?$1zy5#xJHL1TlYf`;<%QmM zyx$2=AGv+}J#Ih$uOTDSzx+M+?_YWS<9~p?eUDn0R>cqrMDlGTzRR@q4UcxmjuX{} zxG}O~=_BKK!$1Fq{`yK37(HWN31OWB$)lrn@|enfC+3VY2$c#*8G4}C4PN5BQ4h*E_i4wojOUH^veP?Q@2nw1xzPL-^~XHy zdZO1#TpT-h7!lE(^Kr*LAQmQYHYcn$Fu{(7*@N+VGJ2hi!2F&r7tW)Rc&6kJkeqH0LW-oNGVVUP zM6%F*BZ}ZQfHww8e>sRtgRchXeIJ}(-iU9nh-Xq5$mK%42kh-f=sV}RaU475H~iSA zY@|-cqAZD84+ugOWqbuz#}!--`h7>ep?*TB^jjdfqD?7#K>91r3q5Dbq1Z^QDIxKO zYGag@I!=OT@C%Gih@H>BIT-glBFDU~4TAN8xL`aG8=wnr4Nn2z68HNXy$tlSqEQGb z;Kc}17^xF`WFN}gc}M(Y(+e^J)e4WXVf7u?@P=ND+7t7bMasdu71z%mJ?IK*(F_9xEbjMLF3Jjxp`ku1)6f1yhteX@CA+^!7GNPMEGl2nlX z38!ENrYB2oxHWpM^e$Kr*m>Zwf^;6eQ_F%^u=+|)0ka3aHzFGiMfJq3vTP2;rW8+~ z2y&&$Jb+$SXG_fCqeD=iwqlF)<%y_rzVErIIDfz<(fKnav_9|R2-+(C62m8n*RZMoOpDZZnuHb_AeI~iqiCW0aiv6-dNMPll1!J5* zTDUxa#OsgHU%)RkDlUV>tZWW!ayQ+uQReg5l}e)bF_~17uvm!ON?0$9v9f#R@XThN zDh~)Np}j-K_tQRX!s!dFfn_y9ywG@HS_w3~6)$RToi##$!Y!BIQKBegm1oxNTNx^TTV>``#7gbZOQwPboPI8ILsDs6s`q#{cu zq)rP32_27-lmo@*z$@`J^_8b&Vzf+a2cZ-+XJ|_5fu>5g1#KO7rDY*&Am%|Y;2iAc zoYgtY0j3Ouz4&}yXCZk+RHke~R<`wt5REYgHVjFE1G)_2dPCv`8wz7qcAM=4huV#> zF`04eh4=3-Tt59ix8MKsk`^bF&gciM%(|TnqEv<%(*!SQaM%s$ zj-)_XB3lf&T#2LeI6o6YpF@XOrl{v`oIWeH5HSyMI4w9)WOCp7nBTkNh;)3*1bxQt z1xRQLsPs8N(rK$Thn72e8Prm#K6rkgNO{AfqQ21YmE#B~;LJUjhLwu2ZO8{!Ua z*38ElnG^F2y`pM#29JHv&x0H~Y6*-A&=FndWztc|*TlM9>GlD1MYBwC(N{h#9F9#qv36`8_UpnKgNIDP(nj#__wH>qK92df};{N@V zr@1mlr<<^>3o#EOCm~P!aVvx14I3xJcSIVaDPfIt)47-GuiUI*rP1hUa5P;f6UH){ z8oCGs!TlsI8NOaT#SE8}Se6en0iQQ~D71nu3lbM<0oB2vvfM6&0Ie$C=RUKKfpdOs z%5>BR*fDV-VW8;=^oE4Y?cFoc2h9&e2O<0tq7qV?>E5qK-4p|Pabg^ls+jFm?`RB^ z2edLcOm}3oH|km0Kfht^K*EN~hsiwE2WtvAJ3$g_I0;K&f17QW zWlLx-L(PXoZ8 z)_?YDfA??wtRKJqn_vFXfArsa`$zwt=>8j!L5dKTjpg0%aQpO!v zeEuz*Fd?ydrj)Ezy29a&djAt_uY~$a>>z$)7MXs)_Z8Vsz|pt>D@g}>excu2tP7(% z7KMC^SZVZo$HKz+4CmpvMfTI#;z>x3Tf(gp!iGktv%=XRR2UH(k%Z97n6}2TjK%j(zI=i)Cewu*5}#Sa!l{Y&_F$Ys%sAW(7a)C^yiL_;F(PD@Od5u-#CZ z?3{Kq`td@L#PxPVVn?q|3^&H>8$7*3M2LrxmX&z@J*+3N1uP=1BVTVMRbhysY1&Uc z2JG08mIIgWXF9;MKa&S5K;^qw^=l<^T674*dA=PdHT;~hJM z8U`tB=om;dbiHEMFaj=07iH90<)~Ij;!_h|9%x96_zkUmp|Z{Bfi@d>5PIGh4>K(FVF|I3f>Orl_Ekv z3d0&XY^V*I7mlHnb`qDJ5|w4SvDlP}n6I>6*w%n-o!+K}+r~Z*DSF@%7>9B+rH?U( ztsz3VGRA|xcOEbWCIPHxF0#$zd0qI6m?kc~R-6csj|2|Z5-qM?k&P`ygc{$igMw7;2O~@%inQlq$Y_zSIc3x{EV9-FiQ5;Ios8sMlZJkpCIVaps z%Gs&Cq5{~3Ik6mVmdh)4zmE6(kG<|2vx z{EWAm-YLDK2^;~HnK+RJwF`NDV*ArKZd>Q=*Z+`yyr6c_JyK8M*r!o9zE|S2qJF`L z0E0FZm01N8b(#a)Mo5AUXZT6)JG~Xg-KX~;GylHXG?!nTyex!tLA=ZXhAQEj*e*&4 z0~Lef*vwYp?wB-&Ooo{HKu03no?#T)%OFQ51jlw|y%-^1i5j8Z(NO3`sSYYeuXBLu zD1sr;8D*f-@gT%4q5Xtml)W>u6Es6uz?@NyE?`A4AZ<#t#!y2-z#KSdr8q7t!87I$ z)MYZB)u!lU72>iW<3hMT6J;lig5iYq2^m7I1LdnAW=-g2C9D}K4arV-L3&4{ff!Vq z7brFpimF#MIJave^2E^!Nmn!)lATh@G>l6E7o-6?=tNR7u!=QDFG5(J7`EbCk*=r> zs-HM{CgJ*y`(*q%iPjAdJMlIq-&1vR%$OBc>o3U2guH?#+%CAUXt<)iVYNUFgqR5F zr28@dpZrQ#pC*E(?JyGB=d*^`k#rKmM>KwmjAQP%T(MTLaz|vKQn3EUD19a$S0$|L zyzGyiQI|RF=80{)Orxy4(Ax`RZ;bIq+!A4ZkEDe4iV|6MVI7^S2V`&;!nPq{L1IGJ zK@0;4pa_h?I6K1!8ZyHjI;0c{TSPQ5Mj+VFNO?mqoiQBj2_1&DlZJB^!H%6)8jreA zN5w-V=sR=`^BGzn=+eLxJKt~%tm|dUE9${@>#Wxs&!4_wz1(mDtq;5{$a0%jXK%O& z=#KZn*aZ(VE4-R#RoLIacHEAy1I;=O;c8$jfk9l};VI%)X#GIs#*!Dn5E;C?MY=2E zm4xD6XuZJ5K*xNdY%ByuJ6LYdtnVZ1wX*7+&D3U&j?qyGcF z>y^0ujIdqMT##)A3hKZbNz2BkZ~g**>Yx2@K7Rg(f9~IT_ls}-TK@f~|E+%9{?Xs~ zoBzg7slT7rPXoZ8)_?Zu|M>g=u9YwU_Lo2Y+yDJv|E>RnwAX(`x&Rs(<&}87u&f^m z>kHO8=MVpop_B*he5P^bbNL?jia!o|+z9dxyF5=u(Chbjd!Q`% zC6QvCW;tEa<1^zlydRT$LSp!aT4cN&^mA?$>$%fMBk5qn2mmqoF=qVSYx1j$K4ns zgAW)P;|*&Qa6ishjKFbRsdScYNA*TIDt7(`3~GO#gOu1v@2BKrJSt&ZP>IB7gzx?o ze)}(BKl~b93NDvf?ezt>X%#JJCoF@wT(IGY#(CRU-qT-_wU|&V!&3StMaHNcduOO|dHx;Z?LD;(7+=V_kk^&kAJn5G8i-rK4x=+`L9#65R>0S}W)SYDI?87Due{sACRkbnw;(qg8r&(4^4!K5gWhS+h>axkPGb zR!GW@n$kjL$$@(j>VBYY(EFf;2MfxOk7$o9vfx3m@&j6C-Ef2(r^3d@ut6JlBo5Nk zg;f%dx1Dwr7H@=Ja4$Fo(S~QGS;hJt6(yufE0x~c97@MXP(jW&7#(Y4UK}(hrT4V9 z;q{mtwWH9-PWQlw@9~kj(DC#Fbn>#IqarSJ5(6XjiV$E8)KYLFx(2jws0BQ)geJ6O z=f_eABq9ZOqxWr^*GD7eMC~`M?1T_0j}wiZEEg6QtZkfUquk$E^v0T>Cn!Hhf?Rld zx3Xo!_ym5Rzfs4Hp^o)~<+kDd!C5Q4CblggwG;FMX3w0K2-YDEhBz8-(06RWs+mPH z_YP{tg)$RDLpcw@SXttM6(@!S@g41aq4{URb0*8mvLxcTVdB9hhJLUlqP?#wkLMk?tq`ez5n+;!CPDNl=`68b?e# zg@F3WL7HZ1JBS)cB1B;DppyuiXtvXbO>xe7M?CU)80X6%Uw(mvlRg|@Cim?UHu_jF zz|Se>2-diNnIaeulkb+3AR#aY_|hqsP|XydgPg^j7KJWO(#b}Y<-(R0q*u_&mX(&C z8Fe8@A^02s_uaX!j)p+>mGWg?O!hIzmq0xmb_`e=bVabQ^knrEeL zIEW5hjg%bmh~74+0E1$ashna!sElstmJv6W?LBdMKLu}PfCE{O3DtuhAv+vCfB*G8 zF=pgEXC-wgpMNycI+NPoD_(?{1NT;OoY#WBU(NJi<5|;~k5tf{R zFZlUFm&B+Gt~)BqIPX|{LnITH59sndzmN4q(v=*qQy`K*BDP?y(at*|eS=%Td_bKD z4M{UKm(mr{XW~Cibjk&KrMDN{1i?w`6^ZZhlo?~7)8H#1f?N?IYx0?xb?D>4=m$Z+ML9t_>V>?VSc$lO#c`e^|8)B4Xz{r&xaxcx8w z=YRFDjPm`z_VTO0^Uwe4Kls1MvQ<}q|edYY}AM*C&e?lLhc*x`) zNPmM7X^)fs`JZ6x9cc%;3!3v}UMztz5}`Cwe`VAY@s8FLI|PXrG`%tOjvw!EafX~E zF=!8bf5Rl7Bk>(R2FKnAK`5m$z> zC4z2LTTnakIA*jv-syhg-RI3$4R|{tbdKYVC4Qvt8|V4J;~=JOR!?ov&m9tYej?eg zk@}c5N!@6pBkgDO^;@VrB6r%D(vp}ec6PkQ$@1!g9R(Ad%CJz*KR-{`gy zz0xhy+I?1nN5(7?79*??2?|Fe;8<^XUGR&e@gno>knENj@LW*LC8;NYtx`+Z?s{Yt{6AgWR%ApD;KgQJbYlUpBd8V z!#N+n#?DU2iMOuwAxCwbnmFPhT1Fu)A52y$2 zapFs4Suga*j`KoYIy^c^Ach-NR<`_g!@Z_Cd>WNvN-v$LSBfu0-w}nrH_D?kdMCty zEKJC;4@8vXhztu1J?CIq0-H4AvhZdvjP}Gr;SeWk;<7|U1JVSs2U+jLb;BD3>C}3o zjs+V#VGLgCPQNM6{7pxDKr-9io zFiYg6pvyB>jZ$6_U+7wJ8HBO2NT;}PjGb%FsK2AXJfM%+lvAPjeE%dgVhAKt-fHEN zuRL8o0Z+4H=9L(3)09~bqB*rrvtn=s7Lxt~i4TSibUbm6mpS0Eh!RLvXdLwJXct@s z9V=m5FkR_qL4y(VLYIVzW2R{CNO(`LvtntMCum$UQEX09+KLUsT1R{#g^y?w>Iih- zK@&Hbwalh<+6()g5sVlkNxxzvWF>NNjGZwHjKl>ld733DZ^Sr-2gL=G3zw)=e?Wkd zK7lU?F9>(qc_N##t_3U8dK|@Pa&er98!=oMWST{)b@pnE@*t*6&?^?-2vMji#IP_P zP#u~*PgA(*tf;CmTES$c_Xqo<5eO`rVHkr%Yk_eNdi@dChUP(07~=`=cXE!Lb|J=y zkdUerUOA2o#{d^XHq;f(?{V)~ ze}%4`!zX{N1B(*s4XF*sNw;;{eCsi-(TgF=Lak2R7TldRZTMv}wZ;yu4XQwCJ|#$D zAR5pdvByqVMN~K+gA@l65+gu*0+&dueGY?j#CxNd)2frxz%fV>sbFWHd(kMI3Q~>p z=tP8$GEkyBA)LyfNGvdBd`CjU9>4h_h#Ent2HO6p-JZD=a?xkTyfu!WhF%+l}1;P7;s&XD5UK& zn>v0&^E=-C?mO0e;r`>_pPcXf0ZAV~LBg0wpf<2lC(}<9sw4FPE%^3v)?lB#kMFvyB`+%!>E2 zkTj!fMwf<<$~bpwDTqIzx+3d|_x9DEe3=5XzERIkYn^@$j<=J#f2N#arYh^0HQfk7 z6V?^Tm;}z!NNYf2LPnvr$E?`vm1|6ML?E{*#1O%TqEYDePCXvemfMV0?~{WoWquBA zrHxsWmH0#onJ5(jM8Gi?R#XC|&KAcw9~_TDEe|ARV!RRvgo~2g@pj@-h#_DS+2T85 zHq1bW;&sgTS%e@RNy4%StuY0EZNWTppsaeM_X?>YW_X9=9_Kev;dZRpM>d(T4^B$AQkTt)vU4&qcY@bNCU*eL{_#+k@1aL3N z?F#W3*G$w8y!-TD_TT+;|H9w-^s_(vNAG_3o4+3a;OXD}De?Ey`e^|8)B4X({QZ;9 zPyhN~{a5}6R{r>Z-H%`W%lpd@fARaj|L=2r{ttPK2+fdC(CZU6K5)u=Ed51#{~h}H z$J7!j{efAbcaZ&{l?Q&D4C_Q5XuA>mZ!z8=8taD-cuz<(V!mME27b)Vmu%oGxtuU6 zqh2{}&^#0M8Luy#ZO77;{k&mxLcEYdLa!H6e(-vKC7j9#cg{y4`$Dyq35RJc(YZb+ zmK5;v1<8Ssza^x|Xa^795r2oK4+N|8pfMEFCq{!PpKvOBPu!M*I6TTL<|pfArPTyx zX#PUT4!STxp9VA_j)UY4I|s59+!xN>Nmk%dFnJ-Qgf8#NIbp+z3PwTfz|=UaG1@!I z8tCH-y*R--Q78C)-0!4#L(&sD{Dx>JK5p1+pY^$%W}W0TYBhSV#BxkQi+1|Cqq%eJ zi5MrJn-w_D`9nxzf4mYS*mmGr@pZCr&icSN#l>iH!(3^{7t*Liz3}$-iXVZ#{T_@# zA9q4YI49!*njKY#vr_ImPN9s-`6e9W3vcyA4o5=cJO=JB&=a0BTfR(_<1o&4QgS4F z!tzcXg?Ki4+sSd^u#SWem|uzgl`aeAe4!Vob(xz;c4S$QckejPLZY!GrI4|j$o7Vs z6XMB;mA*Twflfmk*l`k;Z5}>qA*Y3Od!n=ph+ypty>A@hLeMswEMz*%+&KFyM>m3H zLP`u>Skrqn8t1t))_^FSrE$?u*f5-*&jS)aBHnoICtZ#yk%`8;OThgkX@s7TRzcq& ze#`yw1A!9@H`4XW=qJZ`pd=Pqk#HgCiRl}!UploJ^{lMtZ<_LU1pNk`gHhlfRQ=hPYy0VSJ`l=l)P$9&bFY!g5i3 z2ssaee8lS;XK&Q;#;Bj^VtC9DmC`zWoLrX9(JIRp31i{@*pYZgLI5#_2CO$M7#0&j zpp8ly&s@R>(k-GPQ%j(=JG~Wx6jY4e!%UZk3(NHbaTOwyrPs?78afYun}>;TN?^2hjShs(L0e7c;ou~L>h_G1=qp01};P`PjocN&Vzg*1y+)VQ#p6)PvzK2iL_8ap3W;~tb2J4=T$9uVWKiCbf6!3RVt ztv2?NriD}c#9M^Oek7K6H{$IH)r_nwk|2fatcoWicws-@IK03xj?o!(dTE#lEgQWK z%mnO8(wR^)nB3u6L?kTl5I3ZDx(i+tV-Hw!oCjSe0^(>lk`{swh#4CV5hv6^|C-R; z5_l4h<1s6%0bFM_Qer~VGKEvY=H6n7lLcFi-a6ufULrE)V6(dsE?-TP=}In*W8ZN- z@Ut_EF~msg0|^3QA%t0nHtSfKd_`Xz?}0FwL#u5;)kt|>URr_P zoS*|$L3AUeP7Fpp$27|8AcRP*N?Za`E*Kq&gXkIQU&TNvd>!h(F!Q>Cc}0`aB+;u7 zRp!uZI8hBGqPn1!`S~|P#aKrLkGrJ~D?_4?=L1Zr+p8Gf%bufCQ*OhiwG=Rzz zk~bth6J!cPdc7k$&~PKBD>)T}H|prX2T}+KfnhVPXE;f~5TY1n2dz0lB0-!n0W?@^RLILrc*pRHDVRrM8hCmprYk8XBuCcmJ?r|68H7A9 zL!U1jdn>agGz8N|2oaHvS|@}?AAw^m1Uu0+5{6+tA{XKPckeN)Sg#Cg94EBe2y$gf zk+gtlVoe(+#^@_z8O@z^8^mNJO?bQ#)zSE#b9_%&B4PbGJ|?SEmy98VOCZJfgt(zJ z($h-Z-e9~UWUNFq{R~|a(l?%-e!(yQ?0@_5?eG8jKl=1%e($e7{pD}}Pyfar{hMEY znri&Cei{J&wEhdNf9-$vKmHfT{&)U2ZU60`8TId9&bNd6_utcA|Ac6rE*X9I2eAB% zA-@Z8Mf0~vPn`7yu}XcN234sC!UOjQCKaK;aR*62#oGq?88wIdXXuKDnat>KJ2V5k zLf`3Os@}c6F!ong{rYEkqo2_Ib>5n_h>8&;vZhWc1@1dJ2}K6^@-(fR<%Vj+j~CE^ zEw{;C+26Q?LGxD*Ydppq+ww%tHx{|mo3qB1!eqjn2G=zpws7okBrSMLczvM;!HASv zr@7NEj4%lO9Wc=qXmwhGbrAGGwoKIywIc=WxIjysrw|b=Dc%n@4cJJO<1=S{A+jR5BIPq; zfe;71J3SaGfm)wvkHYczOshiE#C-^H46d@U`jykJn7{J0f;1tHc{}I+4YUJ^2g~}7 z(Twvb9D5=pA)^y=9EH&uu?@~~^5a`33?s`v>pz5P8GP<6OCS!ziV=E&z9YU9ZeYPV zh66$l3Ax_r<3ziY)(aAUi45hkEs#E9@&p_N9%!#v`i@c?R$gfGjFLI~9nllv9iCR& zfT$G~a38Q0mC9>eM5#8x!=kr~NdYPbnuRQ7l z*NP$xe}{xSfkNm|9NOqu9IX1p*(;Pm*FqE_U6im?&U!E`a?@wDRl3*7LSiG!My)4h zzk>*;gVaoI4y~}hf6wLmi8x;9Y>aRxR3i}B9frISz0%G~1VoL|66-q6f@wSx+scS1 zgHKdoTo@ydYVoY1s!k3m!UKxk~15 zgUDnnmd7i@?zj)mV`q3kbh2{7xZtjwvND=d#>p*gJleq8fd*sQzQIiK>WEHksX2~1w3pon6cMI{|MtvKMF>v)Miiro_23uZmg>o7a zJ8`{&S6UA&Ht_H^H`=B&d!rBM^EpsiSS6FJaTF)X6*RF*z(U5;6V?uD+sPr&)af2D z5_)wA2jlgmHzRCcxn>kb5JE9>sF1EW8$oVZc#m2m=!KY!F&y(9u|TaSt-R6ugAkpg zE#R3;{6vZglZ1_v7#yY1#R**ygPhw0oyQxENOfU}E4mtGY(&43Gl(|QHppQko51Z` z(vna;DZ@CQ@7?p00cqM3_$%v8g>@>_GHZ*mqE_j(5fel|@qQB3aWPVK)V8mzfIz?*UZ5CtG-Mbf-bmpS zDJqPFbt8vQNR_&|MHpnG^?F+<~pn1p5Nl%h2647)H!Vv8r;8>Z_#gu4UIhzVlD zvLNRL9~qAW)fJ>+2tMY(Kc|i19q|=O>1&Fn(yK89{-5mqORRNUx1I+*t+n3!7-P=4 z)_2+a-~WH^zQwlUU<>3BB1C}_1xl1bC?CpG5V!73Vqq-I8fZZy0yRC8gtCvTYul@@m&a? zLog&UYA2T`oX*jvyhyFncca>v+}bpV3blcq#&AIdG&!|9oQj3vp2^{O4?-Y{Vy6(t z;5_F=j~YY-qbimPM8j)PK21hoJO;Y@{Pjbo)ItPQkyMeg(9Suaav508WT|r)5}70e zbD4ZX7kYCz`ZSc6L=43dvIg1|F`aD&F(fISU|kY)=trj@w0mGl$?}25pezd|uUItF z^@(l$1)6-;I^{h*YlHlpNVX#R^At85P?9rH%9;@}=XsK?qeba;nOxRlnB{2&j$^hZ z5X`Pl0!P@fGi#jzdaVp7l}FZSvZ9B2Y{#YL!$n z8KaKIx)ipj3vI9X{uRpwOPRhm>bcXq(`qBLkgtMeoqXdon+&6Nq6ZcWv7A(YBP5f{ zZ(t?R#S#5XvY_2hdaZJ;-tiVOxwlyfe}noUM2K7ouDG0Y;N^|cHX?$4?ueaO zNz{5W`arYK@o6|IJ0%NceJ13NopnCxj@APx--;qv?uf#d6)cM1T zEzj@6z5pp`GIUi^s&lC8cYIXn!MYi1*@(0fegX#~fL;+3EMFO;F!mjdjw7gLk{Wd! zL?~VbwJ9LMf>aieL>SzKrmjA&#%NLEP8N{FDU&({e0M&2p$5%v-IdtSk zPETyN>qG`Dimjlkh&_>7K^Moi+xxrl3BmC81+k5x4UHdJuUAN)ST5gi{q7q?14cz+ zAo?JDLGps;S>+e~j9fpU%Z;==vz4FovtRqO{kz}!=l<8f{%8OBzw+TP{^q}vzgd3u z(=_9!_0s_Gr}dv|MGgHMfAw!{=dZs1AAI@4fB(POj{g9Ym3l1n`iWtJ-!gIiExdfB z#+~|jWAGILM*Bnd_5;cr@-W)|f)gnB8Nmj0OT>M__8kuxtfV~f_5;xyTEF7=#`y7| zw?bN9pe9DX;_C;-r68@5`U@(?2;;05vIp*0ioBs#=m?S)Viol1Bje>Hmrl~(fC&1y zYAbd}PGQ*((xHoc(098-97PTnpvn6L8}k2ma*; z`sggu7}Al&*xgu~kV43^QYsX?FxtYS-^qI7MHC~kXOQ-bH5WugY^@VcErEp4sxD!35cC?eMVK$equE^&W?=-9vyrh1Vtw1 zJLQeNoeY0tGbPE57~iw^fqTWuoktZ!eb&W~K}!cYZ*=}R-B&K95k4zex~$xfuSggc zA2`Ps_T!|TPO?PGMt`lCuN)CT!K|{BN=k(vUmv&>+PPCb;Vztyon_g;t}qUgRh-E( zIv<@Bvvvg)KZPY_T#a2CS~Kb0IM)3G{XD7T!R4}2>BQJsHYNHql5eE+Wp0eq1zga* zu@7(?^nOCEkbb$SU4OM-f(qd3I> z-?BbEbGtN%135e1e!vRUIPg9Y=_E^NGiqcQjU|2H=$VBrO)@!@#skyAMLwYR zfiKlr>`IP=_7AjnutxxZ!IgCm=m|$^_c>wPxA_wY&6i-;XQh8uyXSqCax&6jWIJO6-Z}jFUhKmv{=tJ;! zrRc^UN-6^rB`pohPWDV^)}M0}q6ImZnHaK-C9TvJ9Qr*MX(*Y~-xF$iCy&Z$C*-GD zy_FS71swLa!YC}+SQldmh@{Dq^DlH7=hyPy#)32N=Uj)9cG>_V2x zh(wUMrUD+sIcVttabn$I{bO((9Da}qF4@s#&@>ovLytg(D zYKUEFs;FMLm=Gc)=|nX~9oQwK$q7{=1d&co0}qHE3>lO~DP7+Oc7l{C?MUYHG9Xpb zaz)*7oLnF+j*bg{1d7iDo=xs&S4RU(AYH_5~rStFrz)@a9hj3hhQ0M4G=*e?;ebHvRpPKWMViL zf%Kk8ygN~xTnt-R)COT4mB0d0UQy}u`zkNk0$~~B6KCJC%S`FkbDGYrG`tQ*AEe91 zwj7MH6U}i8MgxC4z!WcvrUF$M=O9IpmO$5M^43vVuu|~j&KO40E6Txs2$ok;x}bF8 z)v)DcDTC3Bl8hmWW!_V1f=DA`04qVoib1-g{fZXwcGCPnr80QT|EFE&#ik697o>jW zd^?f&Kx-Aq^tZPufua+2kcv;)Lp_ipjN>bEHby-;8QAj9{S(Oc0bLJF&v(OeBlFvuz*<6K`765eVcn^ptBt7Qv za|Ea$Iiu-H_{8E^dYT;I_VUi^yU>mu^o^YFNGnq;qyaip=eAwBRDs-xfN``bHW8gQ z-f<)A&hV39K`3Y}Fnn6W)4Vi^u@f|u8@e_$I?^vtt}NTi?V9N=@b*AU!^$VJ<#|R4 z!MkD6$tlt0U_^!J6OqD#*g{A`EVDjsETz-?S9%rP1xo|dOj&QU4ll-*JJolxCITZI z)E3s5Sf`q=q!4^O7?Btp^l-MkU`NC4hETx=9tD$=EJo1C1|AQ>-!OTi_e_&cjXB)4 zbU|&w{7O9=!-dW=IeSqsOLK@>jf7w+alL&a_Cei!GO#1Ft}ErTP%eszLoAd~D9-Q$ zm2>j)W%9UHHkv>1VJufjDOQX zZ~qVfZ2jT)|CcX+@PGWTy#1s9+qInsp})=kBu=J6pnclC2B{URIiE{aX#)(J3Sn!^CoF|2j$b#mW^`o+& za!f<(FmS_)q3cG=8=RT_{*{r1%d&vaq=Uslj)djJUY_Z1JICW!*b045ob?SU-x9G9 z?SF<1uK-mtWw^~A@6bAPbJiS#?R-SIp0vC-0w^iIlwmK7Zv z4()*-3+~PlZ}>=13;kSh>(COCKC+Mzt(bIVOS7}^G>4w-jjjZKLZLmb5 zwxHKW9i5~~dip?%8|M+E{J>;jWuJiOUXXrA?aG^!SrKf`B8f_7#1oJ4pt?XLYIi*E zh-|cWFr=|@MYZDINn}1Qc~&%Z!}BZ3V}iMx)2nkt#cSd`D)-|AyD^T1=sU$4o-)1d ztX(NNF=CmCJA3C`Aq;E}Z8<&Oz%+8_IqjoL!OQV1%>YK2tnqN_RX@b6+UwoVA^|qHU8^ePt zv+{R|K&=y_&}AAg8GXtXBzS9`$GD&cKyp+=om zRTaXYuxx0Xe7-hbX?+?nu|^G@hnfKF&cRHdENQ{y6(X?fgCuv7T(Op@$DKE6SPw2w z7tqA@wz0P#8FC`SQBIOIDuwQXd8M`ogHGClQD+K5lVFi}s{<{H$Y0Dg-jDE6OCFO-UpRm|T@xnR4NTddJoYXP!R;lNgX}e@vf3tQ%0@Vy-P*Ud0 zsL*x7y?f?)yOASkJ{U<^qu}wLi10E^=IA`=`hgzHtTXb2%Sx5Wf-JUzCt5v8y^~YW z&sk&BHsvKA&ZAZG5lF2J2HID=RwOE3AnD3u47QS3+<5JGTCY$CNd`?jT32dQ?sXt( z5T1y-Glmiax(>+1qA&sRqoZn!L)qK+tjmoL>(3FtkVini)5?vqBsMAZ=9F8otcjkC z13{vpRE8IN&4`R?3J*tnA|f%yfsIa1PDEx%Ce&v=Gb*-RiCQ_%7e+rxTfnM_=b2!A zhNumxF}a0liciJh`6;1w&;(S1G$6`ALr7$Fc}C8i?gR6Rtso`vyD<)%f{i5@XF!gb zBI`kY703(aX+f@c#Dn2M8_>?d@|217ihG|`VheJPDcnf|mq9T>lMp1roMj7=e1ndH zSs>cc%M~jZ9`yuHR;gH0;D(-ocZZP~y)jlnB~TO#z&6AJEKhEw8s&M`2BUX;bWCl& z8$D2-sbf(09b#p@&OPV8JAR&&%Z^5a?ie7w(RjS?R|U6B+fVAf6NlqzaNc)H4$=*h ztfa&oc$S#^SQ7|{))_+?u9!QvK4EqzCgBwK1JrOIgx=BYh-54|Sdf<|tSBCH_{KOH zBA8`VoOHQ>IBHj-1#z5^^qt2C!xh;(A#bQVq8r{n%t36)3bw_?&dvj9ycfR|R zf9ChT`7i&8zr6nX^Z)*L|K?AFzn|7m1HhlwKjS+8qyON)KI%XEw_gA7|M4&X@b~}E z*R%dU5ubT|ePdMT>+2uE`JZ6zPH%6-`2*Bfto}&JD>8O6Ld1geiP(1*>4*ld&-A#U zso?iJniQmSe*ePh3+p!@u@;QigIGV!Te4{2PKpA>7)L{rV&_4OP8-kE$B92WaSpl* zQBS;g(48?3&ix>HAbpxZ`z|~l52C-a?z`7;cC-&iBB<;3Iga$X6DA1K0bk{@McL6XWd_;texk4TjWd z!X2;db%S#t{6PKsh0zyqAsMvO80U#Bius`RKyL+;owL7jj#tVEDve@4Ln7g+B9{y8 z{wqRW(O#(g!g+Ms*opc^Z$iya)ca@J-m&e z(ihgJ!D2xY#cd&Jg)Hd#ptqffgEj({j7z0N1MY+yB8v4p8iNQUH@1u()!L8|%|YnyxIV;tG5JMCv}D z+3`x-58fV=YcGW+#`F zNOl1!R2qveldBn(epVu<$uEnOq(%y%#~a}lG;{VF``H-DW(vlg)vjDb(2LQt(EA%U zD!0gteQhG;GLO#$%NeV~> zlw!xrOQF^~BMpA>o4?KW^b2fD_!0Qn-x>J@J)R%}&jV=*!9fN|GtnEZ zI+j1u-B|&SD z#SmU->g;EynEX@DQKI60172A;CaWer=p*4h=DXC4y(-7O^WbDnK}t-ifE1)wq}x0I znqpn3eh?8z7^xV~DMP^dc4YvU5-dL9>K+4=jSi5Zl!SGmY2)oZX|k;|<$1n+kN7J> zowZKM)Q2H@p=*$2npNxQl(aJQK4EOX)yYO(_iq*Gh6zAwXgJgKoTz5Cb!c!_EYflmC~J~7bF#80hW#N z^&s3}Q=$#VF^~++SHxB%4v+zD5dFlxF(NQqi4^qFP}@Mp6fQ)ec|+0yTVoI~jEioB z4)!{epdtz9of8FuZrX2;;0M6;+T>B40=W`MNOtMBCu6aGqGzC+TL zHD$&yMmr|AE?=g|!vLMUS0PaCM8DHxuzdc6rjOu(<-p?(R=^L8LXV966Ip|1WH_!J z(Mr-xr%hg^CPEJUIFVc!z0=N0SuR-Kz!sA2bPgB_jLB4#pA&u%;h1EumtQAeHX;wu zA0Y|(@`OePEeK=QE^{HR7jg>RI+|8Q6(0%jjt-y6(&j{;&u6ww&KtMuHto{c$V)@i zNcu$1%3#M|JK@JnDQd#~N>qr)K}ZFIqTo{a@bp9*gJCD7tmJf|Nn@NpKz^d?!uTf% zY|WFGXalS<&W0`pO&267!5sESzY^L&=br=JNl_u+klgU&q}Msn)HE0)p(D-XyM4m) z1xrHT2c={p?}Q&X7f^5-Cc^q|kq?xJ9YaArGP?7WE{vG@vi(!{S^Foe+N06=xeo}OWq0vn)pt~o zKI6HOzbTaRn=JMleD_=b`Tp&1{`3FdcYoqf{@dUDvETS>>!1Ggw|+|e{j`1>0RFW8 z*($#g`EUH?zp?%G|L%Y5zqbGQcmEgXl|0^X zzjO8ny)G#Wj7_X?_Q4&6`^zQiKQz%*poVPkR!bt{7 zrN{+OJ2D{JPM0SvU$JrGELiR=OJ%f759922WOa%Q4ao8d;UKhAWSTCAKY%+blbzQ3 z%F*szmlMk~-4z`qC5Aka^Hz;fAN%+yL+`1ULsVo@l91F25qG(OTlR zBoOd;Ld?-+g2G$>o=6Agm8MXc^#ZRQZ=H1s(g^A!QI7*+aCS(^$XeL)0)FE$D&suR zv~mTE2gh;XJ`H7db2K`Ae=wx8tP3Ry=h2b$k=~%okGN*Eb{Gxug(ZJLwGig09uv=! zm${RdidiANBPHYAI7AT^hCe9TSnM*N$0YLx^%VAikQHGijSrv;n(n9>B{^mXqbqMm zV^4*~6W2V@GLZHws@SY!k2gZWd8USe%%62OrO1l;9hC=S^*yn&A_dfy-FMR1S$)Sv zSn>^%7fw+Yo*4X+?v5?6awV0O;AA+od}B>%R=%=u%MLi%g2{_l9w}q?%9;vkotsC? zpMY;T_#<4DayS|fl!VDALI>SnP*Fy&^jaDDMoG@9!Xm-YO5-c`p4b?pa@#UdJC<*t zAL){jcH%PVML;%8jH1t|6pqIWB@&VoUM`HWzHiJENq$C;S4KT>>*NHReK)ItI8BzB zM36%Dg@WS(k7(@sL9`tUWjCX!F?u5Vtg)5!4K3jE{E=^d=QHc4XC8m_`}lZ8>%uyM z7zcG2Ar*O>1BSqm5dB4P!#`Q{%Odhc1%ma||nC8j|d`!ln=)wuC zW`rpwI;-`qaNHY@{$*kpq){+>WcF~3pUs1qd{5TO85yJDJ+q%LtUB3Jtp_@MaF|9)vvM{w+F$B=aynSb4Z2dSz%Qnc}{27@YASBjn}6cD=DIH+FAi1od^^oQqOS zX`UzF&|aysl6;VMA!MLBEu<}km+qiKNFZ5(4s=pfM1|G^4;=w~y*KWnR54sO zx<4pdIa_6+a7)i*ue^%$=s}XfVhvTHOQyvWofl#xoJzLD;U}xCtQaGXnHtwY^i6jMsS zB33!~PMGp;f1>w5dM7V!3Ou4s$MX1$5j1tPD4%Q^N`ZNh2O20b{W&QToDP z$XVy*jOpZ0%AJ%!q7YO<=b%@UV9Q3F?q53pgS9@jm6V)fidE&Jb25k(C z8=OuEND53EeJEX&vP_Gz(h+Zj&I=>6jEB6}9Ork=7(sjMGkv#R-hUoYat3|Oi`8u< zsnZD}f}AdtYr(WKJaFA0HEb>9^35F344*^Kb((Q8N3){ZCm;Dp=yF5E=>9_g>QgS# z=6+&$%mGCLNYrtlT8ZIEn-%PcgNQQ4DDq5NE?D|V-kjdQ%wKC5=V>&}6unZ%8-+|R zN-8lEr}e<)gw}C=MPerQq+AK@xMaiwkN3~7Op%4;1+(@(P-=)=5QBc4$k_hrc|zS# z=~I-kDrh2=LAcXA5$8_CmuZEqhWHbbu0-wR^+80R15kmI7u*(lbumRY_r`Wmn&l!lKSK@mY9isU$Im$ed4IE)cYHG*;p;HpI>SH zM~=PH51sF<^?~LB@!p6zCdbfHhWKXg(Z>Vr8)e;C*PjE8AwrfZnL5syE|mep2PrRH z*H47lWP9rq@^0d`Qm0v0g(01gE3PZ5cWAG3NS8NU5)vm7pjE&(?D~-rZOUyFy3c)R z^^J%|v~wmfqp>YlOs`lZ$eBnB5=PO^Xs?(lLxf7E^%M09k#K@G?yMN$3y%|W`hv9` zkClOAS#fWG(qqs8vpg?*hOxKDY=V&xE#v}9L1OL+Yju*{2~$!i0_bK$Zs;bYWYl5Q zJ(0GKXqzaWr;iWOKkE>E9HnkcDZYsS)wrUhFQQ$buQ zWyRK?p_dE!xs#I2b8cKo+cTOzaJl>j-~HBKX3G($g$`at>@LVrNF$wQ-e^xS#3 z77)AR4UYSuM5ioYQSFS!1b2&cyvBPp---5>a@}w_88K+}B+g9J2jh`Zd63cz5}n9T z)Vg3Yor~dD@J{uoSuC0D2f*uF^F+gs#uH4&?oGl2QDX!j~u8A#YOh1#% zXrpuZ&d7Jh-avzO>6pwqS4q%EV3F7?IL?)~x}(b*QGNrBjU}8_AA}5sZ6@~?tzr{5s!R=_AGGjo)GsX>VjTX~vSX*VJF%4Z36u*%q6S9*W2<7lJ z4=ZQG`og-d+~4bXrUU4RUBDadfUGOS-)M26>qdA$y-+MDGBB>BG;as5Du_POV(02Y z)WO-DGi_YNxTM5^GW;ZUCE0ZjK^lCy5A3>3USq9{^9$Y^s^3s#r=JIwGJ1j4I&~i$ z^&o3zSwB)rXK4a4a0Uzc{lL(;yOEO6&Q5dYtvD6+1!3jhg!4R!HsSQa!F_*l4rh!f zO3J7-7Wu?Q3#bx{QJe5qD;kw6ostV}C^K&N4Sl@Q`x`zs2%~$YSfR(2;U^|PB3V$m zf@hk7#Yv5d)Ih~%a!SE{aJIp+J~4)I(vXqJ@dJ`NH5N34MT1Tw#Od-%awC;zOgD7+nh^t+NVqo`?&U zGxiiLY2o~O=j)F@QuN00I_Q3q_5<<3{Zv{gHg>Senr~zadd`!hHU_=zEWDu!Mm59| zsAGPROo-8m>eN0Hro#kf@*b=1Y}E+6PGdAD8VkaeF5e>k6}5qrXtB_!tf?TD30{a; zIRt7=q#+!#b2@BkqomBMD|IyX^9~KN79y^c#mH768mE8H5?4eQ9{m;Ql)SR0G3|tw zX~TKA;E6d1%UAA4BD5lONGF0#n7Kns8%V+B&T1D-0%PMrrj#IUze#H!$oX{|KP`i7 zj7Ti@pm|2iLXm{Z9eP8wVLFMOQdTseuwxy@soX1=6}sPfgrlBNyOVs!k2zTDy5LPI zc96%nytS{KG7XRtZ&d9_Kj|Li)Ui6a1T$F@N{^2;9Er*%g=nt~uN-^k+$(E#h6%Z> z1Q&cflSZYE2LgDV1F|(u3-s=e$wrJPEEG!zicSQQ3{l4-xg0N2v70{UiT9#*Oaz^ji=+Fbw z#2*~d@Ot1ezjJ$RXwJymu=a{sCrKgVf?Ye8e3^D%AMAU>v%qK+frv`Ttn%e0AwBA8saUqZE6rz;^VZ@mjv6EM0c!w;k z+lJIx6PB350K}${!v~BTmW`?>KH5KRAgn3Fw$VmIqL9i3&5cro?v3aUJ*HTL!F~)R z6e&W>eKJ%{8KI<$ke&}D?`X?(AB2GC8{6gA7~>@NMy*ViR|2n&j}9&v3rJAgK+0!I zvMHJ2-At-igwEqQK<6-~zwIOg&23gt$HC|W^dr_+1_N6P?tMb^1=?AG%IF8lGEm-= zP~dHysXupA3%w0e9!Q=0DGSF(BC%klvNxY?gloY^K~*{ZK5e-%pg%ZkLJPDySTC1Z zo$Q^uzaiG4EaWXA=2%*Yv(xFbp1!US7rZOSebD&~~_DBPiD!c@@gL^)(Zi7Fw;)E1EaxPPBwwu0(s_$AjJm zQqL)1xjdu!3UNbo1`dKLvQTMLKsBb#R%}C2RP*GCW=F3d(Xj*mj^GGX6+aI8Xb3Cw z-eQ^WD=#pq4CGkoqt2mhoM;jl1%FgV{D8%kCEe)#d;0x8FUMLS?asPR)@TdEq(L(J z`Ir?@e-K_#O%Q1guWRPu3gKuSxHz>Bv?(DCa%boT?-!`xVOY8o{VR3x4UN+YCBS(A1G`N0ntaa{R?ntZjGod-5c7+ItZAxm^hG-)CiPF$4 zzzabmDP%k6o^Ag+FFM*s)Sdu^c7a%d@6jzG>3L2BvmrV|2$p3UqeV#LKvKq;X+goT z_(<|TS(UeSTDb{`XG{v~T46N8UuXJ|nZoP!K#p_rMeP~0*|Zt<%yxZZ(HoJ1T6c!u ziO7`nk&X~#Mh%Qgkw)59vQO*rU<2t>e3S}!LKuwtOPU|#(iu@$@`_18RMF#{7pLAZ zRXT;!1qH-1L`TeVPA;|}dZFA_o`3dm2 z75MZ%WLCDPC(fhIcUSrdvLd=7Ye70_{v~Wv)+OymUM@sDBW22WmXDwK?zjIOzxJp8 z#lQ3OKlP`7@7q8A8-H#6GoSv}@BUl=+E0nUpVm(Uz@OGXd+P76{Wt&8f9aQh@PGf^ zfB3imw}0vT|Igq3^>%!{>_7g<`TE9N-FX{d*Bo=sM<-tvtUmC^fgUGrnN${{HF!MW^(3-SXzlsRdHguF^_vm(M7_@g zWZ96MK!g7Eqz@;xE4;I(5al>4aWsy0!?iH#m&vxeY&_0NYXkTtqd^~?Tsk;>y`PLY zd0rD8CR3}wy@Pf$bxbxH5@^1V(kIY6=lKO0P8t_d9h~+VTQix1kja$kBazE*;~G5V zb;k5hsHalYS<@>od!vzQvhg}9#Ro;77`;*Z4|EGIxgdQf`ztMkS`&K+y`MyXr6i>_ zr)*#}ELMgj{Jf)mpC-TZ8A*4Lpe#S5amT~h$DOz1K5IF5kQk`l$ZQ;M9~k-rwtV2x zU~~a_rlkT$KyO5u1A-4ml!3{GtO=KfN#m^#G&P1)hV5jTnK$1)TIcMQamKtowMuVBu`9ApPGW5*yYH;B&>IXotp|JSq)Wod z?59%S=CHbk(#Ovy{8%de81xEl9K0SUhD{5gyt4R%-Ww;+z{%-04|m6%Ad%M_P9Tvv z2V_pt5Ne0VE|3ycI`^|8@)3l@Z<;y_xps3OPeB=lxOvQJ#jknB3O2+SE?Do zyrsXpa4=IKC00^6O`(UtIPr_HEgKsvhkxa)ZzM^WG(zrpJ2`EzNkY=kIL4jh_0E=! zMXww@2+5?e;sR&OMC?4}!Llrrl1Z{msJ-qCIaxMk&`9N5?ytf9?MFU*RJQ9CtCh#= zgM&I@)LN(d(!L`t7pe~^#@@fsTLYVE7S|1n#Ngzz7|ApKg3tvWgW67l%H9T9pRi?R#4E)VweLuxsGNBHN|ytTkF$b!-6;73Z)4D7 zaC=8pJ=!ZZE4B{mJ`Lrx;0&Qy!bWHHImB$KQdCLN8R8^UuKI!F>}U$K1ZfSD>BJet z8?HfX&T%$+@AJKtR-TrXAsLrf$Z%;3T`RqmDWG7G*Fl#9j}?nV4Uk1hu7qFc^~QC% z@No&&TLM3Lc@vJ>5nCAqi*;gu!FuAG@{v*+U*6srhm#yy7@?J{g4mVZ^W-;Tn4VNQ ziE)x*p{LG$&y0LU7vXySh_sFU{L15T(nrCrACS^HfD}gVPFe=1f{n_f?WlDeOg3V!oih?R? zMjJtUJ@7gcn#V&>QPT3nVk`Z85H{a2RuZ(ysoiTM)+X)#)YqY8iI(ZGkCV9@KBjW{?3`tOVVj#%qq?{R#L7cNqAjwhbY$;Rs%JBX^ zRCII%y+O)KB&AD1Dfn^Xz7tI#DWz`)(QA0R*oX-PB$%hTE%WutZ>*DG+t$4ortu80}P6GW!( zuXGyYF(&`f=H6IS#fme|ipLbhbjfp=r$Rhts|FQDbku^jA3W|AO@>gWmdhLX9g)xI zlJI&UBvw=0fEcv1k#1@7uOq!zP7N&u-s`EjqAo;lczfVcr+GWBNNz| zkz&F9jZ)I&JMIbkAmlMqz_)|T=TEfupw$)Z8(enUXe`SG5{wAEAGipbx0(1n4&pGv z#*|Hz4ZUPk7jkK+zDzL{KS!;A3~W1*B)~J4KBEeqgWf*DSZ3W>25GrM6yg}~sma+e zvAm#dq03IlEB(m$NOayf&YfD*{HM!?rUl6#kT8fJpd5_-z_e2GJ6Aj2h*r^Zft0EB zM}`c-GZy!m(vyH5h$gHIN`}#cAfY88YJ|TLUFq&TJwE}4Mx}G&?Zl#>2E#76EtKsO zHV!fs^#id)#2x96X&6SRy%N1Jx}j-aE-sf3ti^Ee?Cw-HdOPs`!q|VLoj>9dWWC`0 zNbtajJ}i03h5d84{*LPJRy=0|AxFik;{e4$8Y)gYySej_Q(FEzx&;9 z{+WN{=YRH({k8Q^fBbiU_uu>}@%PjEX#n`s`p>ZZADm>b_!H%@bh@BXfHGQVb z2U`1r^U7%#9_LE$CmMBfab%&^POmRm3etFR9*IYP=H3N3DRQTbJFa=AFU`@s;O)jH ziL)k-{s9$3mqyBg59i(-v&2;!-d{LI$H$fD^#jGOz<~`Xw6NEc=3mJ%fD_xE5xs%_ z5!Zm%_QIP&s}HO@Mc=?GqDu7(AuGuPB{=p6#WEwWga;aT+zrzeH$mh!(@d$;N18kx zGD9c)c(_n&qxOA@4)ls2UkFR2e5FL<>;1vK54N)4;)I_pDRK6Ssv%>;%R*#9wUE41 z>wSu3B2S}YS*g8K_sp;>X}gjZqrHBbDGz&_#_RBz@`xz{7{^JE%5aC#*dGnkK^Yg0 z(~0G04C|OTd~eedXTp$A#CZ_=gH{JA1w#(nIT%{-p_orb*&|hOp`BNrx09#zL?dy^ zo%<1}DBHTSw;gFlk4j0fd!M$&i;?1)>XoROaHqE&<3{L;^%IxQWrNU@JqoUa!~m(2 zPiZ$UIneZg2;y)=4qEP1T7YZAP-zl>4(HfeSqkbl0;4;&SMRca?-Vf9<1~Ikcbe**;;Uo7rXs4ic z;p~Ixg6heV!CiShPIML4-0AfsI;bT|%sQvH+k|5K3)VVmt7z`T(TQP1t(+*a8aXM8 z?hIMUWW)^}3ri^OiKc}pE2{*eN`G`(t&ASi6v@Cw5bG0Njko(7DV%!?9&M&w7MV%U zgFE3n%~mc}5M5}h?Dav~Ce*%l7f?AS2eTxkD$kd1SW-uau5Q%F=ZT^H81F#Lt? zN*kZxT*&c?l^Yqud?tOO8_^uI%t0Zn;qg5dMx+MX7z}dybt2F2tz8?@jHHH((Q83` z=ahxWnUOoq`eZiBN(-gs!MfN?wdzT+!PzIuU|ACN@t6kebfMXmJe>Y$EMfF`<+L{I zjVZte4;j?HPR{FjMV3Lg`-JWTrCiWu!;i1jv6C+sF8O!3*N*DWHC5ExthT9gG^ooH z>v~~13yBBW=Fn&?nSsO7sW`RvS@Fb>2aE>kYQ*v_Ee^KsG#g+_*v5GdQZ%Fq!xI{g z4>)_nC^U}=H*ZEd8Ws<#B`kl&2V7RcLOITk$9#`3*Uwza1&JT9q?F|Y+j{VIyz;|a z=X?xgg;6pdjU~NMxTBNTz=+1Z-lud$6HRZ3{(^-I`?+&lH$>mCwL!XI{+>9KL{ew3 zf+Qss>!ut1lLl5sx~tz?^Z@m3qB zD_MlHB!q^FVFq^dvSI1xh&*$guf#ZsBt&b| zCVTr9l?6~@ywD<1*3S@zw@SKvM1~UxqM38-s2ch>=x1dZY?lnyi6La`z`LZZzQA}F zOuRpbF>cs(L5odhAkVYr-gly1i7}-&CbLS}8u(d}{*G<1SF9|UW%_89+M4jl~k@Ig3*F- zSgg%=%_Wi32S|lfIz9$yCeDQBAT1#07u+h62N7?Rg;x@i(oD@|r{oRcO6Wl2HhI%} z&_@OulZNS7x}owjY^g}@Q{YoF$xd=EAeD%ON+$XzL@q3<6D_hn&x>3VarAdHy`f3y z`xi!iBVRUB$|Nx!_XCwVsL#b%$^tSI&?&7%JLrwcYvh@dJ`v)Km@S$ul-3?ZI|(1` zN5z?~iL)<+CPJJgCvtK`q1i$8Mv4n=Q-mR&Fd0NRos4+FNvzuqJR^P};#}8{v&K)R zb|+~@b^euo2&*|d3T~P8V?lWafuSpAK`x!!Hh;zqXZ`#Ew;QxdjbmbAQbw#`$=R-j zg@n^s`>ef38|=N)n?iLYo%1YaI-QTYuzdKIhzoffgl05XgbSD3H#2n}KQKBhn<65B zOaTfY5wz1e_eRR!kjrngK7Ziy@n<}L`c`e^|8)B4Z8{?&iwul|XD^!NV#zxnt7&j04q+t(MuU@@bgf-VaqDf`wfa*(=0ZtPO2exfn3Gc)2!v^UgF z@}jg_sBx$Ij`V}ppRn|aj`4WB(e_5jg^$~3HdRhfgulV@M(;BM-&&oFzt{mI_Juks z?f4Z5rPqPyS%t_sA(~0@nX|v(K4ay_{yjwoT?Q!}mW7h$5au{KTfQ+w(0=Episg*t zN@LKZky}Eo(L7NZTw>vppUC!sNJ96F#}m|Z!gR|=JO*BZOZtwoEL7iV<32aMx zj$@^G!m@JomHoa?$oFEzF>jiy!o|Rk%)K9+BPh2kDi>H%4uWMw9Oyzy-ou699UU}7jiN}oALfZjx>ez5JozpxRPK!X+J2@3%RMJw3B2b->$I2;ke1oD zlgo4PayMS?iL@Bm7S4F)qMh1;uXp8A1hb&-4d+gHr)-~Rf^;~mInj3zf`2SP)99{9bzp>#aTwE1aeKi<%s8Rj%U&{i1zj-*aUXb+*c z&Y~X(8pBV{MJMCGw`oMJ4;V&|9WOUDU0G#dz0gx3w=~fWt)kVDB8(WQWn={RmsgxY z6e0P>NT2W&cr@DK^f1f@q~LZ@R)ZrdO_cHSAgod?C|iNFf*&Y_&c^D4MK6@wcihUx z7Q+6Rrga3)_?{k>Bp*n_Asw_jFmG&0i7LF_GcOfJuDBQKh-s=!#*!{5W2WH!!H-@s z9194P+B%zMMkG8fAO~3sH>s41v)=)icjoPYvLSxpkr}Rxs_60&iH_!z9#^D}DUcYQ zy`OjtDhbs9cOtKokC!sbk_es{>E!L}G1Ifd>5(a-I0;?9A?t$5%XOzMG1a1JBOVbh_TKA$U8GBpmkuah8i=DL|C^ z3i~0fdLdn$qyt4rIxB+i!LfJJdP7@9BvFS>1E~!#qwZ63B%;&`o>q!EXon$_52y#> z9ZNx0Bicq9ouWow3aWvRG53B_<{)jI_1mZ?I&=c~b&#Lt0Ln+3c6Iwe8+UBz#J}K> z2agVJO7VGF7(LQ<$PFnm@AH4VH~{c_Qa0lD#qRuiPIe%WY%XK9bu?^B20yJofezKLaZr z`X6GZ004jhNklF0Zjuiuf_ zuvpm2C;B+iv=Wlvg9F0zQjksPafLX^wt}@;Zyx8|Kgfpo1(HyfC&EuWgg6gUfy>&U z+^Bs;$gC-`#?E~gC^zUCwLI|wqap2;&C&(4M1;@89tOUVZy!-9TrS@bF;Ge9Xhf~_{Z1Sk>FLJh zmRVCK9uj)d+ej+@v%2&o&iMSG;>Gg#rccfL2E1I0PH*|j^KYc)Lp-l=CDNj{P|t z8UX&Z{(oNoqyPT@_~$Rb{QbZ5tAFqxuFkKpbVd7=XXxchAIACe1K$22asM9oC&u|; z{3m~a)tAYn*}oF$V4Qc_uEhOByK(rBoMW)Y2l{x!7f{_S>E|3C7B38aBH~2KiTPlh9poAD z%CgB9W4 z7VtZHA=Z`TJLo4T-Iku2g?XB;~vf_N){)@D|OrvDHPoZ`A9lvLbD>+vL#ZoXL(R;LbUe#il%ANru=Qpn5ye)=3cz8a{%slPo8= zk)zXxv0NOGcO>aa9m08^xBj|hVgypBrPO5*no#Q`AFSC~3}}t-zdY!B<>S)@Nyc&9 zIX&h;JzZH*w4HQ+u&OeAqxcKEzj5};vKT%Fy`D(fW@^O%U8#L0dL;?D36Tw1Zj4-r zJVQ47E zEAj1(^TA|Ixv=HHMrXvVsdaB0(eZvTP6tou7>GX@e&_H`j9@%6!* z7d&^4ru6eb6|#Lmt*;r>kXN^gDE%t<}87QNWWPnZfYW ztOkP%qj!cD!WRa2atf>}XN5859(L|L18IGpRnP+>1d#)~UZ(iO7ovY;jE?Az(y8E=fdv&w+#jF_C~Tt2e0vX%h(6=!=)*~s!tkib7e z7{d=lS0WtGCzmbrd;^ICf4s84HP}8=uAeEk5dFbWM~Y3uZ$BAB$VJFwr=%-UF2KP! z-;K7B=f&7~qmM?6H*CF3Ze8w32&sMH_5KR!6KYo$yO2d7JI7sN2zjZLrljo&DZu)S z`!b(RA7BYf3A)pdio{1?4#tqmSsx%y&VAPN+x#5O=7V8rr4C0eX86Dgq?h@5dQ@6> zL}eO%t$<#p3AoM+>XN7RxgUy!lXWNO3(1x#Z1IMj}wycB?dd_$|N!dtA zxs)3>2fb#VKi|l=XY%LIwEG>cZ{(*N{c(q5=j;Q!DB&we!q$a&WGqh3FK^UwrK|~m z42XmE@;K+;#j3-M@J9=IRuai58g`$_$y9g<=3O50ET^(*yE*z(Mxa2(M6 zg?%K>`jIV-|1W$0(qrqkt?5BeYyI|pV~mKHbIrB(-Y3sFnI~muVkA3dQ-C5xEKza= z2?@z1egafLNC_1R$o>ITKrUDyihuwKA#rgEY$Q@ClXe;>>62%l+ZS~@kmZoAvjPL8c_4j=q@RJa)SihqBPPb>wpK0~?q_|JH0SBX3w)fAt z3Q2{5)9pd+hKvpEoo<1)WCk~^+5GTiur4>mz|()sn2VSdqCFu+r)e!L$ZDi(L|R1c zGUMN&&I*=Z$)3T#GBPv^pvwel)5$&4RT*XS47N&?b=Hv9VD1&(v|pdP3q4giugkS=2B)7-9_hjyei`%$mX?1F;*u2dsaE+US0e zMrE8kB6q|(#sy2C5cz=bU#Sv!jB|p(_c%ZI5EzHk&V$0exf>FtO zC&-3~P#qql6QqJHn18|nJaA4B$V?%GU*k5gVe|k2Wvd5zac)m5q0Q7-$dR-x*f=;& zr}=`gk%JTRhOUXT?sGsnc3N%7a>1k0&Uel_h$YcgkZ=-JS#-sMat@{KKt9M((Y|xb z8EttosO&`3iORHSiVm&|^Weyh;1_H(QY@Gi-XA-m>$HU7s5yje~=d2d!r$8$BPWWO5Z^XvhfkAcPXRCgFCy@U`98?LknZpN*)KiIU??ESAfK zQX+lofl;ksg>5(Pr_U5k>2x*fqY+zVIFxeZffDpYe9+k$;hct9X~fns=~z~3te_pm zNaw)&g%~1Q7U+=V!LXg$2RS)bWipXsAWEhyxMvmS@4e$E7ttf?xC>B1 zCV8MXILARG6Uq;4-jUX(L?R2d3P%HX2aD5Kyb2bS#WOJ+vtF$~kaa=I6B@1rKOtY} z-{w8hAxS`ep^x{;z>G>yN(dll0ab?CtarsXLf$cMgtAioz&vwqgBlF0Co?>GGR7Q; zs3(#Jil0Pg(ySec;1wfN)+>?^Y8#kkLi~=-j`&GR7oee@sbf~c@+eRm!JXlC9u|Y( z`DA~qY{xn6oR%1EBZm|33Cc5Sl~@*noJdOav-7$QY)n)0$I$RzsV?)opcTb2QI3(Y zXk3e83@c?J!tS263 zg*e0uA_uW3&(}Xfhcf(Rqye5tnotd-90_qix-rf~$O}0s7EXdbPg#LJAu+S0`HX5U zGc+O+U>{i5S%uZkc{K9cI7g?AWkTNLgC#Vg7Mdhj919T|m^4b5DYXvlyE1$S`edpR zFb|kTyiInMlv#s29&qlCE+9)nF5jVgr9A&LxEt-<2}?lEfQyosm2)&=EWj~`4SgU< zCfFXs&PI$jaU1FKt-9@uA(T=e&a|8C0mdM#3o#hp2S*zuThMh5Bh(B%4F!%}@bJw} zTfhB(OTq;_XQx~;qR(?bV1f)q)DdO^Q{73o08#0BQhjnLWjMVxng-el zQok|z!oYN3J+g1p0IR8ELpWN%9D)q`ak6inU_tXC;P*37eWYluNZSMo32-m$DmP(`2@?fGm-P)UK>kL;%cndLcUFd?l>FHn4dK} zoP!Y?CO$DbW6&^$3DK`ps$q)v#@HHWPJQgelJSzrPd7?_V#yzf8fWq=IguT6$E$%( zDU*m}{?4{lM6bkjL822iGCVN4;kr_u0{9S~M=p8e`nj&$sDeLitUI)v|pAhwVid%d> zr-$F!cZm5J(y!3)M9dNN4W%*2n9u2~g*v6{@iI{%?If$tcWO{dzOclP9KEt+#TP+x zLJ%}M<>>=m3Z?~@3mTl~wP4;DD1*YfRLXP4EK(mQRuxT(M5Ba-5hqrmyU}f+I&1ze z5hsyTffSLr&dZ~eCVnIc<@y2!)*>=G`+2g&3%MwL1VSEkFK7%Cb5Sdc?sPp73hvPD zL6C&R!tmLEi56%YiD{6Q*NG?c55)C04Zp7sj;*s?BXN0QeSYHlGzdjl|L9kQ=g4s5 zIKN^)9|Qu;?~JK)DEbsp z6*OKZ<1eg~Pd6^#{R!Xy(SLzo{psI&{N~U8*8k%BKl_{i&6oe&pZ)9kH&6fGFLIAx z)-MCVU)FzW>-a~1@n8P(=l|~i__zPy@BXX5|Ly>H$n3u2r=x8rUN1;F z88wsT1I<38EYtWTC$fCN+a1w}?O!?fjYm5XuCRW>q|^P4vodN)Qrv0<2JhBdH2V5ikP?kgI;hj=ieay(w? zqhnPuCII{v1Peya1?2`r9$$slJ|pr3`-4*}*1uBy0PP(0PV0$o=j3qoXJiQHcF_8O z)exC%lr;|O`H`bt=Y~WwRvWEfkkIJ1lS3rgb*3lUh8-uJSA>E}ppy}vAVhkv?6t8; zquUkh9}$0I)RXS-kbx!yIqCaXPN}dY%oBx^Sf1J2!O;gtY@~1{NyWxzuz-C7zsGaM zqt9FKU{r*rih0CFVR*xJeF=j96mA1We$CsvG>Zv zvUem^Bm%x*{X|P46Od|XHsYeVtpsb(SBAc!+G(fL{G`@FYYX0{T;;VMgmNO|pjSt0 z;iz|l`s5h#0aanB(YHe6j>nAZ4HKvNykYGjaQcZ$z`9fY11_1O3-ys0y^@k*40_nn zn7)Ce1u=oPGUSSsilxYsURdP7O{O%(g=Q;(6^o9BhK3&)Jd?+LvQ0eFjtv(jgoP05 ztg46+L^(NNZ!|GH2-%Ebf$hvZRLQx~xzRWn?i{1is}Rx!;ZEzF+8>xLSiDYVCxVel zrnG8U=%mH1DLKv``RWwSjnIsAA12F_I#*GI%?UzU>fZ^?v|;-0=_@)^K~U zKL%1D55eeo7Sb3HgiQP<2N;a($Y#iLVUVcpGebK$Cz7t%Fop`oWWW&|O#`tff<|&M zOsARjx(X>6J!GEZN{9!t8ZoZ;xM4P@ig5>7GpR3xRvA%fz0miHsZ*tJ*2%Bxwy`?o z7CA;G#ln&o`uTAWC=)mX4J`=9e(Gm8~uC`M@L#lY=F)u zri2S&oW$r;BGE2rZyeRBA+Zmjl$rQ8V~k7(ZYVzBq%%Y~TO&6oqzn77IT-IoYab9` z@Bf5;zw_9qrPYJXifW9w4J4jCsUwzYAtCjkwuTR7oB`p&@En~`&Z0L>n>*MrgDkn^2IHmtuxZ$!D$F>-p4pDr+%X3D!G z#}|~7rdLM0a`!h9Q!sJ%F))=e3VbGixRLXPKCUEP$a2zoM=z6i zrfLW`vUfiGI?%?QdOzpTMg|tY8Oc=;8p9j?aI`QljAXv&V;)nKQ5|Uq!7EOKIPl;+ ztyg>o>87o=8~G`dzF}9^W#K#;TIXeHSPUuieKswdlRYYnBB`^#SK9kzS_SQdtIpq9 z7S#G28ep72zp!a5mh2fQ7fT!aw7 z&2dRk47Y=$&LpFhKrqPZine#)9nFH474MB&ABc1$MLZXXA3-|j+nuuuMd!eUp@?UU z6^}yB4ju?PFKg)Mtj9}1bZ7X98n`!dx+4C9Nd$ezF|@qQp?)iPeaHC;WZ*X6RpwVj zzsI8^-s!F3qoBnRY2fqclo$~{AsWz}kg(ty;Jo53qw$VmNLuOgOw<+FW&lA0HlWgo z@p)c&tFV-aw+#=8MNh(dqm+*fZJ-y-o%>g#jRfNgz9V|U#L+B-+h4`_fcH!;Kd`Qe zERI!0N=9iM?Pokb&q1a>z#y$Z5N}sIhsNQ5$tQ{Aqpvd<@QvN z^#$7_IUdBtkr0vU^!UoY4bVYe3fPUHPGYAIVZD9F=#6ggXvmB%g!IJIQ^F)sUKYqt zw7cRFWNmo8)B78}17T1~fE?z9pa^04KwKAm+^9c37{{!si*MMu6I>bT30<637c^wj zrOjk(HNr(%UOwP45zrYfAp`X@7I6tZ~yJT{mbC*m-YWuEB^8k{D0o^QxnL1ur(n|9NZyj+%<%%f`+xS$3)4y#9v(ek@guU~Q zB8+$?lR5i4plB+DC9&26b7zk`kWiVgN0UejgLZFFg!B~f$5+PQF}pHG!J8A;d7x|F zIIlW^>tUv2#@^ZA?r7S%EIZz}Z^NL(I10MH(Dz2X86iIb3o4ab!tf`wO>5ml zPptm|4J*mkxv@=3uz&Ba+z1AXme7r(T7Wpf+gv#Kys>m5-^T+BnZ+R-$y} z>AA3-!qJ_2CSER)92;+?KowFb)Y?EhvUE}~AQM{WW;e$8fWk zSR&`S5o4poCwA{N3$)|FeM7U8!V}&NOB>amIfi2?A@M@$jblXC>nGfP&ugosi$mMl zhS1gLaKye6iI^06-WcA#9W0gWevBI zDi#vMoy#RMhH$os8C=CUd}A98Wq>(eoiUV_H(Xu_=kI2%ykDsHARLvE2E!I==qxGm zu*nS*zmdu|jk~84d`Hu)H;V+)D16K$tR+$@APm z3o1AIz7y>$8R$#naHGEq9xg~d83r07C9Tu}wSR}kjc&@ScP^JJbyK1pSj}wan0EH+ zlpc_{5aUkDE7DF{|AO^^*aMG|bO=aiya|1Sc#HH{5ZjUQiBsB=5w*d%ay&&a4s*uu7lL)m?Tg8K-A###9w+%!o*LBwI+!!Td4D`{l zAoN!84r8n!9o?06oNVm)6bj;_&_~6(5%R|SyI?8OPNNSY=oMki-!DQaiK?0YdV(3_ zV$g)q7n1DcVRToj3b7SL55jdJ)GOzy5PnCY!(~u-B6a8M;|rcoWTa_etjhR?q3Dt( zBTt3Aeg{K%-F~ERCm*jDQn=8ilj;V!vjk=I46^aq@7Oo75&1&TtST*~X>s;WUZ18EsP|bFRKrBDUb*j| ziMbHkg||8l?#o)HW%GXG>Dw@6uOIWCIXfYM3iZ$p6u zwlQ|6pN94@FVC(gTEdhTSU_T%4S}w-(@CRH$KXt_kghW&))Wr^W(GYOG4ghH*7&V< zEjDezCR|oP>a4XT;qkkZ+lL!TI$kE<^Zt;T%(Ov&ou=`S0-EJprPX0%=qs)VIE=AT zA42GY4Hy;(YoMPE@rv96)dq3vq^P7@!TUEBYKdqc!5DkNctYdbl!A!jJm}kwGOOK^CTCL1GM_6NS%z@hiE@gMUS|LVhB%Orc@;iiRsL2ENnHd4GHG^y$j;?N{j2jr1I- zKmV3p1z$5oDp58b?Kg-ik}HZ%*@+}P-WcPJ&KH(^Wwe73IyDNn=LM@@NaLjUfd%_^ z9!Vrgh#L4z==zxT{BAM@XHp4Ta6qF{{lr}-HYF!=8bph8!f!${AuR>D-iY4?#-jmO zj{2CgDtn@y3B4H0O{uSaiWL2z#3zy|)dtN5h+^$R$tx^{qy2%ccdl+I2Q~_|cf!S3 z;`j4=+$!tMW|Lxp(~WT#=nF*y%LUHufZo1gb#9OgZI9@saOppw0rKs_Xce{jbBE;u zcQCuc`8LH%CG*%pv#}JxB;v3bv@f7BaDrhAN1>$&_3Y%Kcd==I4aiO@o>^Mg{=}(g&c_GHyrk$9|vhUxW&l( zW97I{J7!3Qr}9GY8^`PKNaif@nfn+Mb{z_DXG3X(#&DATp1j=1AB}U|84NZN zG=0R{iR6q(!n9#QW(~3jG&&*wz+3+VwKwR2Bu^;N##fpzvwAxQw{%iHqVa~v7i!yC z{Dq5*c>pX=#Bd>mujFv$ZqA{1;zL-dB!Q;S^yNa3ACV)VVPJh>tFO>^&JRk|!Ws*h zFsg7aH@q#leIcin6m}k`aI_mKRPx9~y>l8^g^)7AgxjUFUNT4DY5U3Gh3u2HQ@LVx zC&f3m7BN;%uBcXIY}hbl3_=(j^@4W(G9Ds$Nz=00PF>9**71IaVKa#{b*s;Ti>kCU}R!6MT zcW1PP6dHs??F|dR!|jPkClsZ5Vjqnm4edhq%uydurxCY~jcN-cZ>Ze~l5nduoIVal zbB2AvTckuswbD1kE(>a5-V$G)aqFb|!1s5KBqR+;7d)>`Y$R9_&-w8xGU7a`n*NB_fD&h7_5XKlLZv6)Vh-wC^=x~iqwiO zgC1X??u_1f141as*a?@&hhRKTq27&9-svt>0y!JUqs}{hag3Ga`otIq4P)1e##i>E z5e;Z?DCG3ab=iWM2oiGBDl^z!Ih`0{= zHZW#VA}$FzE63I;2vH(K9Ze1qVvjUwEaO31pXekAjZqIus#uKE+23s8$%`l`t}&hd|$m`AS;;2-lsp2|ZVsf`5Ic>5muU^RuuqG8c2aYO2%{dHW>|;d4}u1| zU3l#q+cqc`V69Ybc=wr<)l7Xe)@-EclTBFW^R|o8^_9_#-VTy}zI||S^x}p6F<0Pb4I)P9eYXeMh0y>2KkqD(wKYyk7h!zE_cu~|E zW|M;$!i^MGHn}5mWt?{y9Wf(cpXQL|9PHzqReZi9x^s+;;EG712%ra1Z?qx&)HaG< zP)&$F2K77Ge_N7V&^<776QdPLyW1f z73hu!pXo{4+0TIWPTywTa+J@L@1+~*nrM#;9tYTDMY=p8(irs}t;#ukS~Q;u2_?yj zmpd9))D8AKVVUmH``1d;K)gBQ4ERVOk8c;N8NDgi27}JBOpay=u@C_yesB#Ss?I)NJZ)3ky4z;+aOqH{oxtBVn;<3WLdGT5xgOz z(|e#jX7V?xAPz^2q!m(yy>8P8D~Yi|2w&-4Sf4;zXTP6hGf2?hWE<0{fLBtj|ZbSmhy?DEA-zJFxvT! zw=03jvO-M_ABGgg$0uYkQ8&ln*dHwAM}o|uV(&XXR?4N|ZR7BTm?DD*-V+i(fp?;2 z@)8*PPHWGo7^1T&we~yqxMK~124dVeJtJ}@g*eeb@k+GJ*?(l%AO}cZF@$hga1^nV z?nab_=5TZ)icOry5JJD>a;2e+p15fu_Ji%wIq%1;++S}j@ye+I>tC?9JINLFiFgjQ zFCZt;Ryr~d{#PMiZj*oh_B`7>U5J+#yk|~_aoOq8}!Qd%QN%V_}`t)yn|IhyLZ|a|3e;NG!vVIu={<8k*SO1GI zAIJUA|4UYX%G>E5fBbv@tN%*d{>g{)q5s*x{73)3eE#~63HSdHY@;oO5dvx*ZGodT z{JX;KDD?V0!T%gT4>UJoY_#)A`$cniy{zs1b{kE?;=OHXilDQUcwL zoma*v1i2GwMEQ;nvEX*lz2g{0nVZu5Ms1lG-^t-dmtV2;1=1fl&&KErQ4-A?QoqdF zUArP_1<%y}ikToGQ`?V(?C4S$TP6Ac?~K~85eZKqVWXQN(QvO+Y#IaeNsy16{GPu3 zjCz39+13s*(vOau8xjlWzHxa9v~;7NhG=7K&Te;}FOh3DzKog13ibni`}aA@!3ZBH zXJWY0Q=#Msnr6JjNmid#b$A&f!hg^H7N#K(o# z5y75G+c8-`>Ex);dLTqleIm3@cV#;RHFk1XsIs$UM>TNV-*Gm|_=wBS+3Pe7x>XJbuOu@^fSlZD|cMxv>aNVKhCqmnOIJV5djaiQn~&4J_0Sd8q_ zX4feJYmX*MRR#&Wlq2$0>1K9_$MUDYd7F1VOeuj(F z$Bsy6k-?hxDIRjT2IaLZR5Jo6#4F^T(NDa*Frpx9VEBfd2Pq_4+Ry}}CBhIqb=;ojnRaDL>}9Q7ARQ>KJeo!R-B^=SyxPV%#0$9#UtHM zss?g&)H?fdPCateJIBP6_cLd+<$E}ugpKRIuAhc1LCpRBPC5`=UGzb;5P>D3?% z^lHR?reoLH@x=csE|ZDp@;jff!a=X9``sahwJb zY*(Zxay42VL=$WYl#sAyw9#40&x9E9q_`~X{-BPPWSzq{L=)%xj>H436A_Yt$&Kob zk_9`3t#9bJp;*=h%`b%P^zy(JO1#lMarlFhl*NRzD>)a&e$t|mwBccXFC|@ZIXKRr zkW;6%HUvu8DCK)v&J?*2<3T$1Vs0QE z9|C=*WF-z5!nItd7-sFr-BDF)5V{Jcfkb48qjtanDJZ8kVqd@oi4ap^Ri{@aj*Kml z*3UUe|1QiFs47tcvNw8Ys4FpMdN1TPuvI7JK|mR8rHu`~y%!cyj;|4xlUmDU&T?W+ zIB}MBCB_vQ3&@WQ6`Cd@nG!4Kd*?9*YhH*^32YGK6jMBu8o&_V#$Qm*$lev#lMo^0 zXIuf9iQzt8@%KB!osf+FZk!g7Qn=I~c%067f1_n1E`fR`%#GV+AV3WrdjvucJUt~m z`sCGdVhy+#B>#Z(6M;nEH-;-T!!)u4VYIIp2WlMv3{O2dF9%Z&Sn| zCmzb=z_vf&aY4#6B2JWq_7z(;1{*F7?<@WOGqJ4TC&it^19(DBXwqjwZ~kQ}jatyTLn0-e| zJJxUD0aHW#b?)WsjT|pX$}Bt(KUmTey9APMsC1eONmjD1;BN#Go|5qT`3tr@Gjc+x z44XXQ{`2qPi&NhdEfm6{7>ZjXX{4Hv$%L>Vp&@dkiX-Z%y^!?{p@BT1aiO(W^0gp! z0dFMDG;M@FzykGkLrbGRJwZ)eKK|+aydQHvmV)AO;77zqL|0{L;G84^eHi;!ql8Gz z4!hCi8{@DooNwD4^va+#pKY%aXKJ)6dV`=9FIVU*K|A;Z^&P(%`gOtgjvarF9i5{& zO#`7kk)EDW`w2S^B7qQON+wg7BEK?+s)Wi&!gBqNagT&_<>fbjjbHt>f9@ZA`m?|G zKYIG%!@ntivivgm`(^$A)cS=1`2U9Wm;cMZ`|;<${6GI|fB1{P_uu>JKl*q6m7o6n zxBv3*{`@cg^bf!Ldp~^r%iqf5v(w%mbi2=i%eJEuD7?|?cXV~SgQS96MPD4cPdIpZ zqUV9Pg?>J$)zGsb?HO-I?_U{V9>{sGoTk*~h*kD4k@odx#{Ea|S41nWnW6(x2;~EZ z8ssl{-56cT`7?RBQO6VY(HOmgd?9+|ai7Vl-aDc~;|-HY2D}dzuZ*xzZRH%FDP%-0 zJi0NCF->$-L=XJ9F--Az$NYe?(oCjxR0fO%?-`MmnT`Ak}zxG5nHF2xw0keCVK zfmz3_(sQBv3mZ-F5j1S{enHxX^*a*FWMvW*Toko};xO6gbn4(@|ndLhQiMzm%e#A zs4IQqF9~U7@p-`a-iRKt8X3dDD?($zAs0kDwF%x5dD&^bGl&#FNy@Cnr#ve=s*~N+ z4dI#IcPwU#IIJp9v$68I~u^Co@WhF;t-o+S`;0gpFD^@XjR* zLlv)$eY;>X6CJe;7y-gUs}<3~ZS9kzRhDlIt$E#SsH1dbE24Kc$cG7Orn{N~qB zNDhq0$=l{Ils*oMu5?w-Ht-P8(Q!ZVeo{h07l_B8*E*35@nxDkRj_ozxDsSQ51a&^ zN+IZXRC%L}Mib>x2d!_UU^E2L$WW!o1@FMOYGd|+N1=`d3C1APdqC5-b@h<7`f5YL;}b$APMz&NBm^H40MH7Bi26=wGomLLPqHf8@NT12q}Os9}o&s zegSvOXv7X4* zsOI!)6cJLqGOB`fLK=+eU7Z}Vbp;7z378Me!S+tR4wh>~bdXY{dZ5)zNy^0v$Jk-i zX;3|5Kd^|l8CVo@+TJY;1lU*3{6|o&VD`$VB zxgZ$Fxz7rwUFd$JJ{}lKw>wEEpE$-r8+9Tf7-(9jU?Cj@jAW5>IBs`vLDMIOCHiA0 zW+#&{pMzI6NAe(+NX+xX#l$Ej6PC{M@(ez?Y-1SxtxpkagHeszA(li6^Fo3)1vuUY zRT_g1)}}2x*i7lEU@b!Jq#~rHQM;pYMcmmRC;ga1wQf$(fW$=YiQezTn2|h%3q76_ z^l6FgKs7WbbiJZU5ZMtTMxK_=oQQD_ml2!qG;_9nFy4iwEa>XA$2+kA!69Y>3S*|r z&4dy=VV%!_6cXn?_mgX07_J0ev3{@(=d~&+2Cf%Hg5qVMD(q(m36xj~QHch1PbfEr zJm@H0G9n9?T!;Z;8e}3Bp;yCd2k)fSKnB)3hbenCjK&z9x^0|$pM&mxQtzMX`$bpwPl{{X`CvGdoh7f}Q}lv2O>+1Es>4&xlSyW14)pupq(l;hc3NCm|`A z3X%(LY>0uRC)~nJDTZa5dJ+1Vy%BH5aeO8E10Nlu5!M?+e>J(nwjo-vdNNQn{Cd7C zM4(M3bGppZ06h>Fos7>qEz*(|Yr?Qh$hUbxX$cRR+tUpVJ8d{ZL~USWp&xhX2c8Qq zD{cjJkit4G&?6F=&$K?k_f8U{+CIfzp?pJnfVkpPvF^0mXX-W>F)XZk;q;8NBAOv8 z?rkRB`$jzuut-lZQlVTD>vEw#X6oK;;2w!7pb{z9E4L39tW_Rw23APnl`#|x8A*cb zKwNM=G3|&i4Bm13nYi3gHAWr8d?7D!mN6{OnrTpiEg+eqoh7Zr5HQ!78n=~b3*tLw zN-WP48#5j=edw9!1NXqw`W+#kU{JasvJqt?UCOuTc_b`QvVbTdIx2?QoojM}?363S zqVzDud~ItG@(&B6{|HU-_CCM&=Sm0{ z+UGljPlWP<4d?oDA*BQ3olu;R12Mi3Qy~QAKFJ5pl^Cz2{E3&}{0;uf-~7)%zWd{U z?tlHq|CxW`|Mc;X|H^;s_P2icpZx8A?H8l(FYA{C;4kZ+V%hJ0{8+#K<9`{|qaUBY z{QTR0{9pgwU;N$w>K}gh?+9-X#D4`#Ch!^K6aDd(Q5A__kwc&-h8cUjFwS>q2lZXB zrw;d@NF9d0fGwB>#v^h0@IB4m(DMu0f5TZ%Y*b>7xWQ2e)>p!tBf+WVnbC#151!I8 zAJAiwvvtdw@|v!2QN{Y^30XsEotVJ{fPSZGwAa$4@0jL6<9i zz&P)u&A2yX#4A!x!ce?s2q&kEX`USuMCbp{1xn(Qy;7;k>cFg?BO7% z8;c5$`k*<~zEe}+LPp}1(K?%dnVc8B5mG?nXCe+-8B7~)M9_9ZN(4H$r$k&o@_z0R z=K%v%#+a71rAJI7k&k>m8&SWIy_2}ny5Jp76M|-P{6MffmoD@OXd;AX9z3wtv7RtH zFk6Xz&?Qq-AgT~^z>bAWT&UM4Jp4%S2evgXx4`x3!rS{DNjJ`1ag9_PlkKFihJben zy-cc2D3^RA>&aV9^wzLG z8Gp42{qcpq-f;bhlvlbdaG|7*^+8DAQ9L64PA^99!r}tU75ev_=Q}oDiLp?)Qt}l~ z&peKI(7}ga{f72d*xNgY?esBNWx+$G`+~+5)JfX7SesTx5k_7h3;XtgSSpKFG)yRZ z8w({|iRp>H{}Ut$ctLh!^G0$A=@Zf)gmTgv;8(`^n4$-5q>^dvq(3@hiGZ?)Mo)np zl@F`2hY!@aQENwh4s&t};DfijlQM+7As$J$fKyO4Gz?le=QE<~w-nm6VMg!N_XCp) z7B7_LE1IFT0=Ci!xPB%I#60N3Nm*%rMTaB4)AAEZ8>iffa)3R-IapJtt5D;O>vFKf zg+3~5SGL-Sy76&cxwj{_`zxA0qPHiMAL;u^NP>FgI8QbkNPe21?Kx&bZ3teSAj+_T z1>u?umku1%^Q3J9S$vwjyAhJ`agDq;XjaLb9M(zKE7UPK5wMVWecy=$p4Tgl#wvv~M|wZd6iD(Tdrg=JnkO#mT*Q%5sY~Sk zfZEG62!{sDig?gLJu9LMyTR?|Boh5hwAu+>(9~&XqXr|TMD2ql^YYETpsOMG!H6r` zjg%s%9^}QzODAxlZx1y3OzxD#op^=zXw8or4&l z+lfCaqXrm8P8HgProgfg$H53YG)InvUOLK2Oan1RPsNiXL%Dpoz-YAn057Dp;97wz zF${dX<0stjjq6pBC~U`oDzo}uoftsEASOdS)3*asB(Dp{xYK>(+=WtvC4~9z^2!h= zx?oK}8%mjmU}@OVW(EBE!jPG~%d1Z@#0hD+prPS)N92Vd&aihv{DJi0!%V>TJMI2P z&W0HbIY?odY|H*ikPdQUyMqK`j`Vsb^gE(pL5co^Za|!(2(Mw*W zlt>XHtbxb)LJE~@g4S2+NTg-QhokLAQlsh9G#Td;C3A@dv&1P4;z8sCq5}3Hv=c_7 z%LS1I_le4IF|}F!nn^3(X5kXH__5?$NCeZ2SS?g6B_+s305GjO|M$|N4pR zUr)UKO8|3Q~HwoApd6JX!4Ibkp zx#3ocWyfSEwmU`ByqJ`Op^op0ULBLdsEKYn;saei5DnJr2SVI9t8jlUloA-ngLZ6W zp3vJ$S_c;bwGN_0#5STh+t=UG9`E$yq*>!79fUKp*9&odLi=w?wy}Kpo)7}jz^Y6( z;JaZ@S4iIzOCmh(m<>Wyq*o4O+S5xRmO$v0qrDK811}rr>x14RVn&J=!lsi;S_=Nd zcZ39KL^M8=@&f)Dn5Jcq;6Vv-K`f$iA^Mf;_kYHRU;Wkd`tgTVbC?_9tC@INho z^TYpMMD|~%7r(4u27te;f9iGqy}$VN@BjY4_22*LpZwqcRhQ7t*-mVOaToS?o0}*=ld#`2k*}b?B8-jn`V(i1y#1KTFHT6m#@dN*e}VP? z2g5RUxgq|UK7OJfg?^beq~-(hjjINZ2E&{b1A1BUWYawPxMS~)ttk=?Xb0nA#PouA zq^oiCjdt1u$DfU=9Vss;f50g;6I?H-E8BUH+d(P`lQ(LBJ~Cc6#5Rt4%niOdAv%eT zkuOM1XzBANagTry+@|^N4AX|m0lqjOUxxvVoO!(@AvELe!xc`}BR%Z02rwi-y+E2%zU{LEuND9;@`9n%j;UeWLe!YGW# z&qz7w;ez$Rs4FRbr0RzF1(kuRvPxyEVcyuwg~wqu5x%=Vq5aOrf`k|Pv2)bFWEAkC zWO>3p(8lBpmGB+II<108VfYn~cd&&V4sud*4zvm$4n#j-wh@-f*>{#B(7Zy+6i!l{ z0~)VN@6M46RuZa^<3aESD8Uj(Ys7HkdT>A9=Rpc(RY7Y;asvIt?r)HsI5NxngvJ** zHhMT%+dyuKYgqVt8li8bK3Q*ZB-D30ja?J#@cXct7I9% zWg+x|jn45p@VKB$qMkx%hOLFSqY_*QF7z>o403gj+UR7~4ACPpuB5PIu9zjF9pI7E z92*gB9Zc!3?~o%o6^u@ondDGO^m78pBTCl?Z#}T;6Pgd!^vr`D?-65e{-q`2_1DDs z6+4YKBDm9uc$^7iykqXvJ{Y!hEem=&o(k(t*!M=$8-xLNqX(t+AJOYZmX$D8%I$&% z;eHORAGoayoyY>sksKpqIL1IiLUSa>#>Epyho(CnVGNxKiMK{O1IbR7sMKVX{vN*bdGMVjXOwxbh&; z>q%$}`Q;-$?hJpY-(h$sD8$`}w}NZL!kylpVK-WPMbnOtfCq(qgZi0T8-a$oAZ;>U zaR`(-OcEnsCeLvkLLKsr(-m;0&CKi1%#sj)eR=e(CA80L*L#7fTZ)iT~{mOY9v#KnH7pF*~oeeaT>_9}QzQXZ9vQBBq z1!9bh{UB?iH(@j-gu%5e^t0j!8m^3UaDHyMIH?@d_$YzcrhU7~otP7u3wAje*1;3r z1KkXjLG%b?Aj#(QD`j-)+#f&F>r7$ilF1JBFc9IotdJTBXBk%xztQcajgvTsvMHet_giu-Oxpad29PmN6gGq8k*qlk0jT#>?cQGH9=#@zAG% zJzm+`!8i^)2G+}O812Cyj-Oe^5HozwR5NUOCB{G`6H_9U!sGo;KN^?I9F!fsu`UBa@OI)kp!rIu9YHXe>Eh@S zNi(H=KHf-4@z79xCSC)5gLdwOm|YScc)%&;n*Q2l1|?Sa6v&{&VOYCXIu3 zLWwIPhKm55+smJ@UO?aeBknl;Y%C>`ZxBmChtl@Ww!spGAe}7+LW9TWH`48iLBsAF zF@kucZDX>C#o1az(pL&j@5ZtSdUd3CBnT$~I~w!|0!s-*4fL~e-<+5ePnXQz9G5^B zkke@O{QCj=p;8xkV0Q&Pmc z;@klNc_Lh{z@7K~5A*?1GaLunl>Q`0s^qv}k{Plwf}%soMbQ}1<${Ke#t%RxdB!E+ zQ4k-*xXnac2slQGnX^ykU5tfbmFn*^C0LXY=W}C(Sy!hwf}Uu+Vcn2Y(R`g%T))l> zeu+S&#e!J?-%x#;kn+kP9M(5Kcq}x3qFUGOZ6Z88U>T(3TFGsCGb| zdly;mT%vHw3+D)E3IxJ8{^=D90SS?>KUXyWh;?Jp$Y~e!DYKr5wkM9h<2_N<{}?NB z;r(=c+zFncKc-yD0~`w~0>(7(F7UKG&*u?=tqtVtlsx8ToEx>iQ|x=1H*5sVC;xVg zN{DG1r!Nc8vHi}24O}VFFz>t{C&Ld?&U|+hbQpV2_;|*wqLQE`Fr$r1rlLs+l1KCS5W8E>Ca*|pN&CsbI$--2%g*4<}wP^D;^=Jb(Bzr2UqCJBgQ-@I3JP0p*#rM)Ea-odkVjSfJGf zyElB>u<(K|7o3wG3ppN$J}8$9L04!S%lZQDc)cPLF&mS^nV!klAGkgJF&}>QSI@M5 z`iD>7ef&Guk01VL>vxyGFMs@t*yES=%K-3~^`Bt5d*c0G-v7bB^@h|>Eu}v~P=Met@9oG~ZF{)FabEz`uTBSqll{IPVNG z&R}?&H;w%OEw4xtX_DyUM@BV7 zBZn(K8bN05tyv@K$!P-{H$)G58%TSa#;kHOY9K7aet*N-J6Yxs(?W*U$X6r2ydeFC zjW^Vs^M1!D_+k?{8#294-j4>On{mE%Virq6U4^6gjTFz|BctO*-N*T(3_ zH>=gW;a#6sJe66I$aj2HkQLeC(c5IVH4r~o%Rxv_bpI9AD|UWn)CXsO!Y>EbIvQ@M z&CQQ#;tYj+yE8hx+o1Oc>vDq}Y0atLxNI|_bA+F;YUolhe~?va!*C)}o{+YY;!cy! z87{>50Xg2tk{NNp*tx_7p^a3utZtVlj>kK3RgzwD`+~-gT=ETBg;bQ|^A8011Hm4|psew)bL20y{gv0F5{{pU zDH1L>JXc&3K@TM@ zyjAScY3DaOjtdeCa4J2s49isPKyD;CXpoZ(Rsr|M@qnT!Gge;gK#^i)Piu~C3obq@a5t3elkkM zA4af~mjIUs2u$ua7A;cxlVAnMaI~W{*`nH#}3>A@e+yWMvH$;3LWXc#|L<= zSaZUfur!}hf-?4IcHC>jR3WZEMT>Y#){ z)0MNH)cS^4LItxW6g3eq-4%V>Ke4#h&pyRp9uA-s|=GvT4uz+V^^ zu=AN^S+F%A)^K!Q`T+T&jN^&+wiB-r@6cK!hgn0smKz5J_Y;Xe(_|Rk12JBvph5!D zI`_Oy8%)iFLmAxSaD5RXfz{y{@4%R8uBHS%2unan z#C}q1Lz3g_NI0nG$f#&~VYH5-ESfKxF07aDxM)DvjkmWy+zO)$TR)?g1ZqyKvbsvmp;vr zW2H;R`&ZIpSX0agYEH;HtD9k3ft^BY8$mlRN^6}cjq^uEbr7DFl%T|b<`uIyibfdc ze3#qg_o-~82D3}VWhWE^<2lW&#w?Lv}n#s|K>iD|AsJJK2 zHn48=;f&)TEfI-A@PG=q!Ig-Nfy4#TNcWw({Utx%nOxcEgbSn?DA6cnx)z+Dxp^UI znn_ZeJRG|uprJj{x+1G{RwJB|OHcwQ$(^xx##4eE=kPb4SX4%EbUU$ArabJLN%;k< zpQ&X0jD);_6c%YT70%&=-UzB}yOTzuTm`&BenI*i^!L_jUa8}q%k>-UPBW+>LAhSQ zN5r72e=IanG-h)8j-w0rv%wN6VI$caRaS;% zN`@u}=7tdH^#bXgID0Z=5<%VwYP>hY?3jNy`#|Gh?@IH+O*7ppCyn*_8Q}-iH`>?< z^Y7BqLi0lKgT)7a)5#`HO868IP8g9<=H=%&z{cd} zI+5jK)PCja3+a|fK^Xh|8A{Ha=Zd`x$pVKY&`vHt5Hw)NEA{vPfDkG%cG7i6LL@zB zVtm2n9n8QZ?lvVxUPueL%>?;!D-+xC=w!*$*33H5R{4P+KVtF3?FsA|jaSx}KjHa@ zzs|=$`O~+jPrv@(UY?)-hrbN{ep&zjynbN-{-?b9fAD|!xc~OY|H12D{G^PP{=6JL!_KP%*z?ZKJn9yLUL>@zWTOjKA%Z;U>lqA&5eZgy@WB zlUos{i8hH6T<~fb#+Wt-&i$aCmHv%yM0dRZh@_pQD?@I`@rtENNS|o-#&O<}F0}KY z^#}AD+bBRL=+oRSnxXxmln;2xgz*PL+fZ8=?MkpgR|EeI>CuV$N4q5OePLiz!%(3yj6zHdRHbR+7O8hE$lXku@aM@@*QlP=W^b-7$AiA-K}_Ml6jG1EfaC%Cat~LdaL@{yGnl42;ScLI{eC zoiSeNGRT)FB>ajLKG5rD?EDJ8VzSPg!=VHlxSgmv3!UEE+}KD!az#|9aacO%<3W)D zIkDS8Vrc@WG3G;$DP$($i$ zDp+J5(4{d{>0FU=Czi5-=c1Wb`Mf#uyKh z2)#Ml8mo5N=nR_&KBQ9zSP%13KVA{(c<)Hes9xyDiKISleMuN21I}=#YeP!p`StN5SFqC=-9tR7;B^7l20D59742xt< ztfjG!_N{jGnJ5Z9aq33x9ok83fmY|iFQk<$ow&xyq4R{MLQZgQiT&*hXZ;y_zq3Co zU4CZy^gU5Jx&Oq_jIk4&(F0fr#P%Tlzu5bmSlhO3zYqGg)_U(_j5*g@d++mg?|skj zy*R|NV-Z`4h!BY=frJne6p<)JLXkj%5}%S0(i0E?3ZVdnB%(wCA(0{&gcMm35!ixK z2-q>fj_vn+-@EsobM{_q&N;^DAFWa7>mjNLhg8mxPUYwvoptt_bBxhj`~QExvC?dt z+#e}q7nU5vfDwkRgLMR2F2wdNQXjMfx}0cg$Vlk=k;~?!QNaY4KygeA%y}|Jw9|)k zj>#c1FGL8@JKpD0ECKNjFqhZ}?=!`8-N=goE3(ZLUM^o@`pR}OV)=;Z!0bk=i6s|m zcOrzEm97^=R~UuSJ64XF;@m5}WlC~P3u{lTmKdJ6J$8mS^zwmHUNCn&54!yp#){XI zYJ<>~-d^AD0U#C#&LV|c54tD3H@r1u1R;};mh%N&2dfCJt+;m7PQ>9n8{Io;>9A}_ z%6QI54tkm#9<|IereK11-eQuNi6J9H;2D>brX3#*;zDPm^&8$!8qVeALQ0+96XA}oLY7YU$;l)cqK>8l@OF;F=*$h=Vga5#arah=z?Z zg&TUIhtqf<{zSwT_hYguWBz}arC?bE|&y$nS*;bXdA=YT+%WRO~2g>+&nb78gjxdiq3o+xEwj5~fmC&#s9%DU3S&?MM0hn;DB!u^4k z3(m>o+@U+|5x9Y>V+5$v-Eb2^&iPsHj&2<*3kD?Bi6Izsc%oazfquYh&;ryPwIFAM zSa4slWy8A9#Mc&S7C|$bfn}YbsnXPi*;xB2(NGmRVB4 zXfg2foqZWIowqh5mT8P$-`@{7=Ab-1lk1JVo}}#p z9Hb3Y)YtW@Xqg=j&<8>$)X#M>JZ zf-ZuHvXqJ?L$o9E)nxXzJDLsJIRgn4!UY-E$qzKe+kwQ1S^+V}dBfyRj5Mvc;|)KY zRGf89ge7|WLXt|Pg!llx5WZ0#om>KuH-2`0aupKCU{LzVUY-XyGy`8<~=R6)5gYQ^m&^obr zzG5j3j|XdHv>5i;VcpEI~ zPRdaIh3(^tq$gB9Osta3g(ZMULza%%Z3<}gYf>3gxV0GY1!KU|SIFh(h`)dAB{KcRB^Z(=T{><I9&-M(u;JX|nA{;Oz}dmE&0E20RHagJ{9n8&NW44eGvA zk1xo;+4>X#)Gm>fcdh1MSpwa>?d|P2p8I^D2XBk_l4?}&c={$XmRH$@5Fd; zc85i#WT1gRen6~{^VeVtA3uCYkrnuYTBk|o6e0PTLoIowyJ2B7B^a=+AiXh$qH96( zCxj1(1ge6JXF`JI1u_e@?Nj1mknKVnH$6Lu8=o0tway(x1G1 zY9pu2vMdlj>(+}Qase+yJ4o9?x_pDB1wX%sn7pHU`izzXSYl|W%)7EDXR8)FPscf9O)1j3awjH1E1DVl(^lH_0v!zH7- zkmN%6XGUvi3UH7#hnCl;kMCgXKzKr9pQ4rZ86Takbj*bP)>+gT%Lm3;xh{jY>_}WW z+L!}uS!lN%WKf@N_;TSvJclwIOU4ORM4WzBbP-B=#*fcfcluC*%65@y@vRHz z<42C+(}wOHLkOu1eL?gf$*i=f9)vKHXT6aYVuAo3xzd|+-W#`llKs^a*uY|deoeLwS)4I~>WR<^@j*#q&uDr`3ZL9U&NFMaxH`0Kz~$ zzrVrgl$0nb!|*x$lR(l;ABl8CH&iN@)M#UnE*}s*XCiJaI6H`eHM)<94zQp*pdSz$ zfMM#G6x;{Hf5SKqJmx)B+Y3>l^~pP0p9C}TW5BKq4^DaK*;erG#G<5iVU30d4DU$H z!A+|IZ;GZBNehFMXo}_!bltgsZZo;CY~*~fkm%mAC9&m<%3zE_mr4pDmo_=4cA<9z zpXts;8|saLVmULgZ<;d`(T6tj{FLxCJhK4lZ;>E$DTh10*eoIpK}w6*P#kBa+bc6{3@mh#cgL z(!0=(PCXlS>>O_iZ-Pf9hQYbeJ%~O~QO?*<>x7)syc+9d7;3|E%-U<@*_39=a#W4; zJaG*q8R<;$E~!an5OGC$qWc?+bHeSzi8|;Sm?=c2NFkL49W#X&(Wh;^$E*j&9F|2l zBm|E%-$61&3tSFTUpQ-rIFYXN`;Z+?ALjd2tEeUvgI+)ybu=^y-7BdE$&8#ok+%&^ z2Z>G*h_S*skjoRAD)<}Y?6eL`g0vJQ&DKTutjEW2OamF?{k=wJS}hvkPJK9i%j9hI z(HL1N4J-*N!a&Gb=mIJEOzM6~_{hl8vDDCYMb|5L?^u~>V(CgjSTE0n9PAF`bj~rq zdzU8xsc3qh4UY04tsiI7SFZH)PH#Js16@{%3htkXypa5$_l10UN8LzAY)~$R=o?Xu z{^;lm<8fkgovgh2${0?hgqkw$cVakbMnq9FP$9e#U1utCag2_Wk@X2!LGGmT5fNqV zpQ#T=DOfVRegly!I~Z3SHguLXuq{+`wSXUSNy?@eMh?h7_PT#yLn5GXd5@|N43LP=l!WTvN*wo7@t8-dcDk+ zk~>lYMx%^_a`}ky%+Ob0WpHKG6Zb!+ESaGYhtrrs5T~-qirIxBOwmlaAe`j#G!5u{ z;bKo*J_#uT#w&vZDRViSr{Ga~(&;FVJ>dWu`?0>fY!yo_G zzyB}(^MCaFzyJIFr-{W+*G~h$pRRu(*N^|kzxwsB{+)m0U-bTJqUG9DCZ6urD2_0=(g(YSxCmwh>DlgMC+MP%r5N;FF++T_4 zbJxDC^CjPPYV1jfzANa5&Vy3AVCw>w8KcvCN0SlhLfv19`i8r3HsL&>RmYD`-kvDS zccg0pj6fiEM!!Qdyq~jrQ!;riY-N2n8S`#s9-MV&)PbLk7%Q$1)bCvLh9AL@g4UC3 zE>K=L<$^_L_$!_YYg!>~P&$!5U{dIQGGs-@poJqfXk%chV3BBkn-w})$fGg*K^+wt zide836uaO{VT_LVO7@izW7f0cM10WOL8}jeWew_>&{%F3uMe0#Kx!v>XM|(Y*i4W`(K4&Aq8nF?&78A?+X}MN$AQU8>4ED^U4;j$ zuH^274bEE-;gocR)49JLti{mnN<9_WBFdI^7R2LGn2d*S$gwv~L{kL0PZZdGh*J(JjvfNh(l}X)u&IaPctO zV-5+>uh1c^+Xt4-NMmJh_i4f$f+iy+nIn@@P~NL_5rhX@F;qICfxBTTFglrvd2lr2 z91m8TF!1Bc$>}$W2;Gg)hEb@s;*G_vlDnVWb*%FeSBL*@Cn>4PA z(%VOR-%)mo?6^6b!{|49pXOXk1Mw5tc+X(Za{IHPBvu$C*$4r&D#!|jUM3-xi3n$yPo z%$s~o?=!ujiy--lg3Kgly5QrO!wOSWm1POCDxY5m8p4_{jJ~5$XL<~$NMf*{Iin?m z+l145B{1L$3%H+1G(Zq5v{6yO#V1f)I(;-OImrs6!WfB^6WjAwARD#?x+qBt;l_~8 z9Q_1=A?LJ@mZuA*FSxzEC-@rCoO-~rD&_eJGvPRbHqM!lY6tajh8SV6*OPXFxX{N; zMVTEe%a!iy6c~(!@Qibir7?IW>w$#M<(1`m$R|K9C^tr}Gs&TfTEP)C$K)Lb(8e^_ zkHDLu-qEOxX1E5fgCP~Om6AWw#*JkWoE1FJ?^sqCLTzu19;CY?$q+s=+8b5^(I-gd z-F$nWY0@JxmcY`ymn0FwZ3@2JAsRkrz0#{9l8{u0G3$+5gs6iU4Rl2y(d4%Tr5gtq6OV5S_(#)_nso8tV9&rdCc0af^Uu@co#f`h=H1* zYBH|z<4o@&rc5GRY+UIv`%Xn|}QzlL%O$+zf2i6pq&QQo@A+0Nx72Jt9fr{?T zq&5w)S2PKc7ifuEH%y)CjnOMP3nmG_H4b;Ib$Tyz>Er_t)!Vf!Obm~4oSC$j)n2FF{`>e*xf@wlh zBY@@yw81!-_TL0nev6!*aPN$ELv2Ovc``|BC0`4g^_|B!?|Ip-#M$WML0Bf|0KLz_ z$ohh4MbszLla=rRx)c3tBCgow8?1j}j8{;ZgLAPd3F0Ut|z%CgDb38RG|} ze;_mw_L(96KD1m(;aFb@TcJFY(uQ`UOOWH3oHZtgF+^u$$Lmb5a>dh$lmT^P38vvS zf0%L(eWK_UjRS8x!hy>|_%dtjqVIfeV=D`3Td#zzY-FZ{4~wY`@vZs zgzwN6v?PXHXIBFj-Pv|u2;2adWu^%U+C7QkwW01=g zWr4I3l312TlJD8ujckP^6CL0>@f5u+l=1`7>ic;mNTE1RM5SoM{Q?G7g5{!EE{Gb> zUtO^e&xEuY9$Ct4^k{}q@J6`=ZKU~}_B_9zUg`QPBp$T$%DCkDvn>njhYdf^dEeRc zH2IE$R!__;J`U<5&2~lmOqPL@7*-evo35mB;;#?7CUS}S@AS?x9C~RSW^D}FQ}zIla{AjUcUd=H_XjCpvM!gr$aEmiGZdgS@a>C&qW|ufM_Ufvb??1(!j} z3nkt-TBVf>qr5lkwr?3->HcL7ZVs7=zl+n$Z`f~x@B_&=_Btr`fra13(jVh;hvqz4 zBXXu6cUTWJ1!q?*1+R}z4napkvQYbp%ImD`I`fboN)8xt&Vx!)2xrvbEgV~32#0gu zvFym2*e;p%^334UrC&O& zD$?HvG;L5K(=8#k&jYkWG~qc7!h{3JX}r@4gx)iII>_aMro^h57{TY?#1so`!qdkW zdW9r+N=e+t&Z>~S@$d!O3hAJ?Mt=y>6o3ATa~!}O^(!HPOHc*;aB4pov4aTRUKrz* z$JlAMl2c=}VC{|j>13ddCwjAKUrmEWbc!X~_hj#!XXD-v)V3*B@gTQnI_`;|sM>^TIOgaPaZ*;#Qsc>*G8YCBv+aI9P z$*XW4gE4mg1c;EwNfMzi8S%zwjZqd3TiLFHWaH>3vKaYjw82afr^0iowCJ=LSneQ$ zwK|e^?j5*q(8v1$I8O;`WVZByegB?zoTSyUyaI|WLjDB(XfuV=8fXR&Xq}#d9zyIf zxmlWs(IGi@O>iBI`yZ2{%zMT-;aGWoDu@LA{)Ofp%`aH=`MZBdRHy=e#bqW&-3w@d z2#rn&r;m=L4Y7p8Gh_Tn&=Ea(?2VMq`FmZyLNwrfWsKiU?1VUoW459>(f2#Xm_r)M ze5=zzkM=$&=tK%yTUghHh{ogf4YM0Xc4Fy>Jt6I!$#1_<$_0;(_h-l*xpq?NczQ)& z644sNos{lGUGbi$KAQ3pLb zQNPEt65}Ao}V>(i=X4#)6N^=$&Obv7CrVbC@}xj)Tj~x2P9d`;iomRs%aY zx^uG7M`x8WS+%O<&4^9#$4Qd8h)Y9}%a!wR{Bb8ICtD_JV=O^_E({s;+AyuyIym+z zElGN^*E@?|IroDzO*1lwPJVTE*6jsvZ{#9)8??8CJ-?uOLOme{(L3#Npyy0PE+x}M zNm6E_lQ+)poLzXjE{raSEF>Ld>3D7AZ6T_#JSkE(2qA{k>rNYhWlCP>P}>ISX~RWe zJdj~X+UEU-FZ2CPFXTGdy)#-x zE3)2*vk<4vpE);%3vn()6eK&6*C|tp8}280IHP5TUa;*7UBCt@Izt^lPb58~Wtx3^ zsVE!I>n|{I-s0~-9GJ;$Pz+;97e>5MAA_SWqynY<8Y(0Wq!hvnrDU81B-nIvp)Gjl zf3J*yl9Wh!=2ODvB4ezqO*vwp>Z!-V&`wJN{t>ap-fwu!#3%99)lo;35N-Z@4^(m@+nw$zdF8xmIz7fj(fCqAD$KmOQx zvV|VXvYecK4r-U-l+F~uNTKKhjSo19o}DK*P8Ifg;xwMGO889NN;kI4_oPkmy3e0w z&B&PaK(bMiqUofcMn54xUFbOVg2emmgRT3e)S73 zAAbHfKK}f7{*OKmGEr{BQoZzxrE$@Sneb-$jm(Q11*^^0E;r)8aSukywt5 zy&m*#bjh#+Be7{ho*bTn_If}(<2_N&8+~s``iSIC(!!|=nja(;IBv+e(Am*(BKi$l zo+#r)L%_bqxFa%XV+VvWUeR&KWu-{rF*-wp+nI2^)52Lx=Jb^jCnkg5X2ntXY95rL z;oeDUK~hG^6kcemC~)u_kVNluLr4nnH@sePUy+C4xsd&2+#TTt`wnH9+sUdE-Wow4 zbGw&vKpObC5Mj8yqBa;_kp4uG8%+mie`T{fsSLCyBz?_t*$@x*{Y1w;t7&?{*A?X; z*ZJ_*w9sm2ctP7fD?%yL&%xsnXh0TWEiw5^+H*` zLdy3@>)_A0Jm_b~^Pr8t58c6n#a?iBq8TBT>Vb-bd{4Q2oTdCE)M*c4>F=D7vNFaz5Yd9XIH8${ zjxPb@8FRzOk4Scstk6#+y$5RYMnopt1CLH^LVbIs>jjsSwC}jj0fBKac!l;%YmFQW zZV-J(no~8fJdoZfYo?ur-aGAhFbLce5o6Z)awokEO8tRmmHSX~Yb+8JE8ItCKZ9Jr z>P~$Wd~|v!c3H5?N32Z)r;m=`0=C3RU(oKL#`>Iy^AqTg*y6OhbE;7C6{OK@C5^$* zlNiFN5OU$sI>BVUDF>;+sG!+M`o{To;|$2llnhi$NS^WuZ;f`m8yC|?6JzwsNJcM% zi$hBAh*{ei^<;Qu+va^>KQr#%qvr$dI@2eI`0{fe{wuwh(sP{nyUN$CsD{Z6%ZiDbE zD*fGjdGPjdFrnCn_I+0IaslZ?+Zh!=8K)yLc$}akqopHsQ0EC@kB(|0bpCypl}C5- zb3sxAI(3{p{N$_TSTR<6BH9lAE(gNtmC5%qpE~29yB^8MvDv98`>8R>E!r;=95@X9*2-dP)5aF zF@0v#9nnfjnKOdA1Cba!$d`pN4pIo>LimNy4*DR~D{7UX>y20-t%k-zZv)sV z{=#`SltyeXwDJQQ5MEIgmQ6YPzAm6v3(%3QM9t8JoX7uLD1+}aJ>EMO zjc`Gi3mS9D6DYRyS=~FFpdog}EYHLA2((=3{b1Z)@sh~#z&LSa)^_bA=@jqioIR3C zpNDcC_z>>*H^Mg7_$?y&yPbY;6Ig7ZhvKq=HY|Psp1_pW?kr-YWn-MoRFWsklBP8j zXGoq*FYe?#tEK&1kZdevAo9SxP*~@myG?#-{WAaD(4dbyy!Lkl2eT6SywIb~;ZDi8 zHN1EFV^-KDRzw?`E=cOQ&jX^zgUu5oD?OAEf%kz9W+gVSqzL-R^r(z87>|nPgf59L zH@bg734EW)qP)J)+n{jHq@*}Q8@XI*?ZhKZbVNAEaVNzf*%L0%9(UAy*2=8lhjG*c z>4Vr0a^BEkcwVLvcL;4HE+2w$A&rJESF)U-C*w5aXlMepGT$9^F!nO*&Gcy(7M*pt zD&z%{1VTfTVN05ox~Bz>gI*83cjyglBjv*0D_b;72ZfH(Q8h{~oa4mDGz+^;Y=;89 zXPP^4R)#|oMeYrg1Z$z!gV>$CT^ZU?oUtp@B<(h9mcVJqYO!U|N$R6bDr6`>OP1Xd_(#gpNuFwO;1WymXAO2k-aGF~cpBiS}n z|I+EzaW~d)pKyX`caVaJ!cfd#<^X<6vsUbZKL-5>ba6N)U(lBC$Wmzg-+|I#D;)bq z_y+!&9uMp>W+MKbEr|!BhHg`W;K$#kot5>n5C-lyq>}RYOA>=ch1^IIDWgM6fL>5Xi zQdW9DArv#ixZ-|c)5-`Z#uE{lkXJ-DTHRS!;dlr+B}NQJb83Cywm@3g-zt&@eJpI{ z6KVa79!}?lkt$EW^K&jO)4u#MF;4uEkmr^BBn-Xq_T!zB1PhRy2@S#%V>q=AoT$B9^|r`(Lc@BO*Q%g68jwe{mSf3?W= zzgYi?kN@sZlZv0NpRS)O!2iIn|H^;vzx-eOd;iYA`Ct6wzw>|n#q0NfaQXEg{XK5C z(_X)S{k2%x%sTj15xzoIn#xtWQYW;D-r#%tXku)LDmV>$n zFdf_;4^d88%k}uD+$BvIX zx4KR?%-C`1AQw2C-tY8ib0b3~+cO@|5F4W%xFkd_6p;zM4yT`gNFQSkCex0xG5CUv z`>fWT3({n=phm{*g7-|cfv6$ABKC}}!WbLJ(TLGe-3YZQP>@8iE1JKZ)xx0>-|L6;kYM6yA5NBZC-z1K?z zYH+kfbz|&;_%ea?GO!R*x==kKy&*oU&J3eI8Y3l&(4_zXfB;EEK~$U;LS7RV3AaKY zN-BZLj*8JNO`gf+1>*xs!_zz%)%s;Jk=Tfmi4eFq+J2ia-f_WYett9(eY{coAmcJ&dM9LVTfMK0+m6{}P@xlwWcg_(SW_a2lMpVw3$6WZ*CFim!K8)rQ;vEe9n5g%Z24gg0`GCaw zUZc-MH9}tLqmgY#d!x6>s_Ugw8)SB*EpzaO%<7jnnrD#AI1d&VdIS**CP4|u%8G_l zcq39qR4{3CKoA{qn{^6H_+c}ZWR;iaOo=b-w;RWPVzGlN9U;z%;C3IxNO;UdrAT0l zVZ~_mdwK)Hh_ufX6bo=cRLSOKOC)Jzf6zh+6=*VL}XrKn-ok=u^OG-h5lnM^zi%l1MaH$w6hr+C8j zmCg>eleuE$17%f;HCn%Mdu!AX`kqK>iX*xu^3z7>{QvgR5fUa!DjT7hvVNeSl@Xns zbc%Ld&^!}C`~IGIEgAPQt?oG^R`5|d&&=a?BO3U!lD9h}obwdg0b(}!ontN-WEs#V zenHGJ1M(GICj5OU@~C827E7pJ5f6lChF8=AO^I-YvlGqHEUcDhJ-5w)PateIxRk_@ z6D{)qETSYyv{va|=Kwd9RGt{U(ff(CSp^OmxDFJ-QpQ8cJN#1GsL`q7c`g4;%5XdcA!k%)yM zH*7V^Ww0y-DIXcVG5TQmNxM}>6UgtF0L`TGr{@4oDpar-+`k<3I{B~Kf>a({zRQgI zVcNB|g1q6wsK=mVgsqf(MQzsIQZc+f=FlcBq~#gacMO6IES<#BS+db4m=X&|5TsT5 zu`|v&!1s4%SI$?YUvS+KI}si8uhp#LVCK8E)dlB#mOK>ke8qx9VO;c zrZ$>8s*o*aJ^8xv{P6|b3^@#?Bc*r6C2P7yJ>3Wh^^sTUb`+upWKy zabE}tVkprPnSjNK5=6^W5JCsdB%SS&Wx28}HSvDNwJcLqK zwzA;yF33qwT-F7P%HDp(tsb~d!IMfO#6V;&5l3b0ZzK&=pBQn)3S?qsB8VvGd64ZO#fmJ6^l2x@AoOeG@)haz3q~cabuQ>%4@P(P5%j}}G=*43 zLaiZ>&-Am=TcR{)`!4hR6{O1*Up_%B^Im999s;(K(}pSd(Pk1>pGlXG$TE-n$zcmL)8{!jJZpRS*-p9X;c-dz9OfBHZBpZf9Ff9F4Z ze*brArxKFz_Mo;K^;fU-`yWq9Lwmz-U+`|Ek!ZazYK76L=PMxCV;X5A71DC09{Wtx z=|_51yx%G1nd5}EkIB67glD08B`<|RVLyyjApFT4$6_)<&(B?(ZV6E||dZlRyY7SioqV ziz)DtWIG}b>5554;(Pir4=u?$SSO|Dx&4cif)SF4sDvx6-tgnycAPRPJ7hsDSjL^m zE8(-&Et(J!G;f^81Aje;m;;H{Dj4XfM7-dZ$-2zJENu!>;(@B*Q5c$N;{~(CS$8bm z7-qN_Sq5=FX01-1=K#_>nw0I?CVveFdqMOg5ema

NnX)EH+Nua)3Y(c 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 '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/packages/react-native/template/android/gradlew.bat b/packages/react-native/template/android/gradlew.bat deleted file mode 100644 index 7101f8e4676fca..00000000000000 --- a/packages/react-native/template/android/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/packages/react-native/template/android/settings.gradle b/packages/react-native/template/android/settings.gradle deleted file mode 100644 index 09c4abaf9093ed..00000000000000 --- a/packages/react-native/template/android/settings.gradle +++ /dev/null @@ -1,6 +0,0 @@ -pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } -plugins { id("com.facebook.react.settings") } -extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } -rootProject.name = 'HelloWorld' -include ':app' -includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/packages/react-native/template/app.json b/packages/react-native/template/app.json deleted file mode 100644 index cbbc305181ac22..00000000000000 --- a/packages/react-native/template/app.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "HelloWorld", - "displayName": "HelloWorld" -} diff --git a/packages/react-native/template/babel.config.js b/packages/react-native/template/babel.config.js deleted file mode 100644 index f7b3da3b33d156..00000000000000 --- a/packages/react-native/template/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ['module:@react-native/babel-preset'], -}; diff --git a/packages/react-native/template/index.js b/packages/react-native/template/index.js deleted file mode 100644 index a850d031de7911..00000000000000 --- a/packages/react-native/template/index.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @format - */ - -import {AppRegistry} from 'react-native'; -import App from './App'; -import {name as appName} from './app.json'; - -AppRegistry.registerComponent(appName, () => App); diff --git a/packages/react-native/template/ios/HelloWorld.xcodeproj/project.pbxproj b/packages/react-native/template/ios/HelloWorld.xcodeproj/project.pbxproj deleted file mode 100644 index 38b4a59a433d7f..00000000000000 --- a/packages/react-native/template/ios/HelloWorld.xcodeproj/project.pbxproj +++ /dev/null @@ -1,688 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 00E356F31AD99517003FC87E /* HelloWorldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HelloWorldTests.m */; }; - 0C80B921A6F3F58F76C31292 /* libPods-HelloWorld.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-HelloWorld.a */; }; - 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 7699B88040F8A987B510C191 /* libPods-HelloWorld-HelloWorldTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-HelloWorld-HelloWorldTests.a */; }; - 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 13B07F861A680F5B00A75B9A; - remoteInfo = HelloWorld; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 00E356EE1AD99517003FC87E /* HelloWorldTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HelloWorldTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* HelloWorldTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HelloWorldTests.m; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloWorld.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = HelloWorld/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = HelloWorld/AppDelegate.mm; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = HelloWorld/Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = HelloWorld/Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = HelloWorld/main.m; sourceTree = ""; }; - 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = HelloWorld/PrivacyInfo.xcprivacy; sourceTree = ""; }; - 19F6CBCC0A4E27FBF8BF4A61 /* libPods-HelloWorld-HelloWorldTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld-HelloWorldTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B4392A12AC88292D35C810B /* Pods-HelloWorld.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.debug.xcconfig"; path = "Target Support Files/Pods-HelloWorld/Pods-HelloWorld.debug.xcconfig"; sourceTree = ""; }; - 5709B34CF0A7D63546082F79 /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = ""; }; - 5B7EB9410499542E8C5724F5 /* Pods-HelloWorld-HelloWorldTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.debug.xcconfig"; sourceTree = ""; }; - 5DCACB8F33CDC322A6C60F78 /* libPods-HelloWorld.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = HelloWorld/LaunchScreen.storyboard; sourceTree = ""; }; - 89C6BE57DB24E9ADA2F236DE /* Pods-HelloWorld-HelloWorldTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld-HelloWorldTests.release.xcconfig"; path = "Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests.release.xcconfig"; sourceTree = ""; }; - ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 00E356EB1AD99517003FC87E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7699B88040F8A987B510C191 /* libPods-HelloWorld-HelloWorldTests.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0C80B921A6F3F58F76C31292 /* libPods-HelloWorld.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 00E356EF1AD99517003FC87E /* HelloWorldTests */ = { - isa = PBXGroup; - children = ( - 00E356F21AD99517003FC87E /* HelloWorldTests.m */, - 00E356F01AD99517003FC87E /* Supporting Files */, - ); - path = HelloWorldTests; - sourceTree = ""; - }; - 00E356F01AD99517003FC87E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 00E356F11AD99517003FC87E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 13B07FAE1A68108700A75B9A /* HelloWorld */ = { - isa = PBXGroup; - children = ( - 13B07FAF1A68108700A75B9A /* AppDelegate.h */, - 13B07FB01A68108700A75B9A /* AppDelegate.mm */, - 13B07FB51A68108700A75B9A /* Images.xcassets */, - 13B07FB61A68108700A75B9A /* Info.plist */, - 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, - 13B07FB71A68108700A75B9A /* main.m */, - 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */, - ); - name = HelloWorld; - sourceTree = ""; - }; - 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { - isa = PBXGroup; - children = ( - ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 5DCACB8F33CDC322A6C60F78 /* libPods-HelloWorld.a */, - 19F6CBCC0A4E27FBF8BF4A61 /* libPods-HelloWorld-HelloWorldTests.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 832341AE1AAA6A7D00B99B32 /* Libraries */ = { - isa = PBXGroup; - children = ( - ); - name = Libraries; - sourceTree = ""; - }; - 83CBB9F61A601CBA00E9B192 = { - isa = PBXGroup; - children = ( - 13B07FAE1A68108700A75B9A /* HelloWorld */, - 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* HelloWorldTests */, - 83CBBA001A601CBA00E9B192 /* Products */, - 2D16E6871FA4F8E400B85C8A /* Frameworks */, - BBD78D7AC51CEA395F1C20DB /* Pods */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - usesTabs = 0; - }; - 83CBBA001A601CBA00E9B192 /* Products */ = { - isa = PBXGroup; - children = ( - 13B07F961A680F5B00A75B9A /* HelloWorld.app */, - 00E356EE1AD99517003FC87E /* HelloWorldTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - BBD78D7AC51CEA395F1C20DB /* Pods */ = { - isa = PBXGroup; - children = ( - 3B4392A12AC88292D35C810B /* Pods-HelloWorld.debug.xcconfig */, - 5709B34CF0A7D63546082F79 /* Pods-HelloWorld.release.xcconfig */, - 5B7EB9410499542E8C5724F5 /* Pods-HelloWorld-HelloWorldTests.debug.xcconfig */, - 89C6BE57DB24E9ADA2F236DE /* Pods-HelloWorld-HelloWorldTests.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 00E356ED1AD99517003FC87E /* HelloWorldTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "HelloWorldTests" */; - buildPhases = ( - A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, - 00E356EA1AD99517003FC87E /* Sources */, - 00E356EB1AD99517003FC87E /* Frameworks */, - 00E356EC1AD99517003FC87E /* Resources */, - C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, - F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - 00E356F51AD99517003FC87E /* PBXTargetDependency */, - ); - name = HelloWorldTests; - productName = HelloWorldTests; - productReference = 00E356EE1AD99517003FC87E /* HelloWorldTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 13B07F861A680F5B00A75B9A /* HelloWorld */ = { - isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HelloWorld" */; - buildPhases = ( - C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, - 13B07F871A680F5B00A75B9A /* Sources */, - 13B07F8C1A680F5B00A75B9A /* Frameworks */, - 13B07F8E1A680F5B00A75B9A /* Resources */, - 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, - E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = HelloWorld; - productName = HelloWorld; - productReference = 13B07F961A680F5B00A75B9A /* HelloWorld.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 83CBB9F71A601CBA00E9B192 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1210; - TargetAttributes = { - 00E356ED1AD99517003FC87E = { - CreatedOnToolsVersion = 6.2; - TestTargetID = 13B07F861A680F5B00A75B9A; - }; - 13B07F861A680F5B00A75B9A = { - LastSwiftMigration = 1120; - }; - }; - }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HelloWorld" */; - compatibilityVersion = "Xcode 12.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 83CBB9F61A601CBA00E9B192; - productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 13B07F861A680F5B00A75B9A /* HelloWorld */, - 00E356ED1AD99517003FC87E /* HelloWorldTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 00E356EC1AD99517003FC87E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 13B07F8E1A680F5B00A75B9A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, - 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/.xcode.env.local", - "$(SRCROOT)/.xcode.env", - ); - name = "Bundle React Native code and images"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; - }; - 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-HelloWorld-HelloWorldTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-HelloWorld-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HelloWorld-HelloWorldTests/Pods-HelloWorld-HelloWorldTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 00E356EA1AD99517003FC87E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 00E356F31AD99517003FC87E /* HelloWorldTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 13B07F871A680F5B00A75B9A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, - 13B07FC11A68108700A75B9A /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 13B07F861A680F5B00A75B9A /* HelloWorld */; - targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 00E356F61AD99517003FC87E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-HelloWorld-HelloWorldTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = HelloWorldTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.4; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - "$(inherited)", - ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HelloWorld.app/HelloWorld"; - }; - name = Debug; - }; - 00E356F71AD99517003FC87E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-HelloWorld-HelloWorldTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COPY_PHASE_STRIP = NO; - INFOPLIST_FILE = HelloWorldTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.4; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - "$(inherited)", - ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HelloWorld.app/HelloWorld"; - }; - name = Release; - }; - 13B07F941A680F5B00A75B9A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-HelloWorld.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = HelloWorld/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "$(inherited)", - "-ObjC", - "-lc++", - ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = HelloWorld; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 13B07F951A680F5B00A75B9A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-HelloWorld.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; - INFOPLIST_FILE = HelloWorld/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - OTHER_LDFLAGS = ( - "$(inherited)", - "-ObjC", - "-lc++", - ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = HelloWorld; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; - 83CBBA201A601CBA00E9B192 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++20"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.4; - LD_RUNPATH_SEARCH_PATHS = ( - /usr/lib/swift, - "$(inherited)", - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SDKROOT)/usr/lib/swift\"", - "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", - "\"$(inherited)\"", - ); - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-DFOLLY_NO_CONFIG", - "-DFOLLY_MOBILE=1", - "-DFOLLY_USE_LIBCPP=1", - "-DFOLLY_CFG_NO_COROUTINES=1", - "-DFOLLY_HAVE_CLOCK_GETTIME=1", - ); - SDKROOT = iphoneos; - }; - name = Debug; - }; - 83CBBA211A601CBA00E9B192 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++20"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.4; - LD_RUNPATH_SEARCH_PATHS = ( - /usr/lib/swift, - "$(inherited)", - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SDKROOT)/usr/lib/swift\"", - "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", - "\"$(inherited)\"", - ); - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_CPLUSPLUSFLAGS = ( - "$(OTHER_CFLAGS)", - "-DFOLLY_NO_CONFIG", - "-DFOLLY_MOBILE=1", - "-DFOLLY_USE_LIBCPP=1", - "-DFOLLY_CFG_NO_COROUTINES=1", - "-DFOLLY_HAVE_CLOCK_GETTIME=1", - ); - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "HelloWorldTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 00E356F61AD99517003FC87E /* Debug */, - 00E356F71AD99517003FC87E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HelloWorld" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 13B07F941A680F5B00A75B9A /* Debug */, - 13B07F951A680F5B00A75B9A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HelloWorld" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 83CBBA201A601CBA00E9B192 /* Debug */, - 83CBBA211A601CBA00E9B192 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; -} diff --git a/packages/react-native/template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme b/packages/react-native/template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme deleted file mode 100644 index b57be22ab2d66f..00000000000000 --- a/packages/react-native/template/ios/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/react-native/template/ios/HelloWorld/AppDelegate.h b/packages/react-native/template/ios/HelloWorld/AppDelegate.h deleted file mode 100644 index 5d2808256ca079..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : RCTAppDelegate - -@end diff --git a/packages/react-native/template/ios/HelloWorld/AppDelegate.mm b/packages/react-native/template/ios/HelloWorld/AppDelegate.mm deleted file mode 100644 index daebde2edb3273..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/AppDelegate.mm +++ /dev/null @@ -1,31 +0,0 @@ -#import "AppDelegate.h" - -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - self.moduleName = @"HelloWorld"; - // You can add your custom initial props in the dictionary below. - // They will be passed down to the ViewController used by React Native. - self.initialProps = @{}; - - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge -{ - return [self bundleURL]; -} - -- (NSURL *)bundleURL -{ -#if DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; -#else - return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; -#endif -} - -@end diff --git a/packages/react-native/template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json b/packages/react-native/template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 81213230deb40d..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/packages/react-native/template/ios/HelloWorld/Images.xcassets/Contents.json b/packages/react-native/template/ios/HelloWorld/Images.xcassets/Contents.json deleted file mode 100644 index 2d92bd53fdb222..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/Images.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/react-native/template/ios/HelloWorld/Info.plist b/packages/react-native/template/ios/HelloWorld/Info.plist deleted file mode 100644 index 07b050898d9d30..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/Info.plist +++ /dev/null @@ -1,52 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - Hello App Display Name - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - LSRequiresIPhoneOS - - NSAppTransportSecurity - - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - NSLocationWhenInUseUsageDescription - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/packages/react-native/template/ios/HelloWorld/LaunchScreen.storyboard b/packages/react-native/template/ios/HelloWorld/LaunchScreen.storyboard deleted file mode 100644 index e13962e9bf5470..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/LaunchScreen.storyboard +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/react-native/template/ios/HelloWorld/PrivacyInfo.xcprivacy b/packages/react-native/template/ios/HelloWorld/PrivacyInfo.xcprivacy deleted file mode 100644 index ef1896e70c88da..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,38 +0,0 @@ - - - - - NSPrivacyCollectedDataTypes - - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - C617.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - - - NSPrivacyTracking - - - diff --git a/packages/react-native/template/ios/HelloWorld/main.m b/packages/react-native/template/ios/HelloWorld/main.m deleted file mode 100644 index d645c7246c42e4..00000000000000 --- a/packages/react-native/template/ios/HelloWorld/main.m +++ /dev/null @@ -1,10 +0,0 @@ -#import - -#import "AppDelegate.h" - -int main(int argc, char *argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/packages/react-native/template/ios/HelloWorldTests/HelloWorldTests.m b/packages/react-native/template/ios/HelloWorldTests/HelloWorldTests.m deleted file mode 100644 index 884d405d6579c6..00000000000000 --- a/packages/react-native/template/ios/HelloWorldTests/HelloWorldTests.m +++ /dev/null @@ -1,66 +0,0 @@ -#import -#import - -#import -#import - -#define TIMEOUT_SECONDS 600 -#define TEXT_TO_LOOK_FOR @"Welcome to React" - -@interface HelloWorldTests : XCTestCase - -@end - -@implementation HelloWorldTests - -- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test -{ - if (test(view)) { - return YES; - } - for (UIView *subview in [view subviews]) { - if ([self findSubviewInView:subview matching:test]) { - return YES; - } - } - return NO; -} - -- (void)testRendersWelcomeScreen -{ - UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; - NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; - BOOL foundElement = NO; - - __block NSString *redboxError = nil; -#ifdef DEBUG - RCTSetLogFunction( - ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { - if (level >= RCTLogLevelError) { - redboxError = message; - } - }); -#endif - - while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { - [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - - foundElement = [self findSubviewInView:vc.view - matching:^BOOL(UIView *view) { - if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { - return YES; - } - return NO; - }]; - } - -#ifdef DEBUG - RCTSetLogFunction(RCTDefaultLogFunction); -#endif - - XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); - XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); -} - -@end diff --git a/packages/react-native/template/ios/HelloWorldTests/Info.plist b/packages/react-native/template/ios/HelloWorldTests/Info.plist deleted file mode 100644 index ba72822e8728ef..00000000000000 --- a/packages/react-native/template/ios/HelloWorldTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/packages/react-native/template/ios/Podfile b/packages/react-native/template/ios/Podfile deleted file mode 100644 index 6a6cd92f24e24f..00000000000000 --- a/packages/react-native/template/ios/Podfile +++ /dev/null @@ -1,40 +0,0 @@ -# Resolve react_native_pods.rb with node to allow for hoisting -require Pod::Executable.execute_command('node', ['-p', - 'require.resolve( - "react-native/scripts/react_native_pods.rb", - {paths: [process.argv[1]]}, - )', __dir__]).strip - -platform :ios, min_ios_version_supported -prepare_react_native_project! - -linkage = ENV['USE_FRAMEWORKS'] -if linkage != nil - Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green - use_frameworks! :linkage => linkage.to_sym -end - -target 'HelloWorld' do - config = use_native_modules! - - use_react_native!( - :path => config[:reactNativePath], - # An absolute path to your application root. - :app_path => "#{Pod::Config.instance.installation_root}/.." - ) - - target 'HelloWorldTests' do - inherit! :complete - # Pods for testing - end - - post_install do |installer| - # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 - react_native_post_install( - installer, - config[:reactNativePath], - :mac_catalyst_enabled => false, - # :ccache_enabled => true - ) - end -end diff --git a/packages/react-native/template/ios/_xcode.env b/packages/react-native/template/ios/_xcode.env deleted file mode 100644 index 3d5782c71568d3..00000000000000 --- a/packages/react-native/template/ios/_xcode.env +++ /dev/null @@ -1,11 +0,0 @@ -# This `.xcode.env` file is versioned and is used to source the environment -# used when running script phases inside Xcode. -# To customize your local environment, you can create an `.xcode.env.local` -# file that is not versioned. - -# NODE_BINARY variable contains the PATH to the node executable. -# -# Customize the NODE_BINARY variable here. -# For example, to use nvm with brew, add the following line -# . "$(brew --prefix nvm)/nvm.sh" --no-use -export NODE_BINARY=$(command -v node) diff --git a/packages/react-native/template/jest.config.js b/packages/react-native/template/jest.config.js deleted file mode 100644 index 8eb675e9bc68ad..00000000000000 --- a/packages/react-native/template/jest.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - preset: 'react-native', -}; diff --git a/packages/react-native/template/metro.config.js b/packages/react-native/template/metro.config.js deleted file mode 100644 index 9d41685ef1bfc2..00000000000000 --- a/packages/react-native/template/metro.config.js +++ /dev/null @@ -1,11 +0,0 @@ -const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); - -/** - * Metro configuration - * https://reactnative.dev/docs/metro - * - * @type {import('metro-config').MetroConfig} - */ -const config = {}; - -module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/packages/react-native/template/package.json b/packages/react-native/template/package.json deleted file mode 100644 index ea2089488f965f..00000000000000 --- a/packages/react-native/template/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "HelloWorld", - "version": "0.0.1", - "private": true, - "scripts": { - "android": "react-native run-android", - "ios": "react-native run-ios", - "lint": "eslint .", - "start": "react-native start", - "test": "jest" - }, - "dependencies": { - "react": "19.0.0-rc-fb9a90fa48-20240614", - "react-native": "1000.0.0" - }, - "devDependencies": { - "@babel/core": "^7.20.0", - "@babel/preset-env": "^7.20.0", - "@babel/runtime": "^7.20.0", - "@react-native/babel-preset": "0.75.0-main", - "@react-native/eslint-config": "0.75.0-main", - "@react-native/metro-config": "0.75.0-main", - "@react-native/typescript-config": "0.75.0-main", - "@types/react": "^18.2.6", - "@types/react-test-renderer": "^18.0.0", - "babel-jest": "^29.6.3", - "eslint": "^8.19.0", - "jest": "^29.6.3", - "prettier": "2.8.8", - "react-test-renderer": "19.0.0-rc-fb9a90fa48-20240614", - "typescript": "5.0.4" - }, - "engines": { - "node": ">=18" - } -} diff --git a/packages/react-native/template/tsconfig.json b/packages/react-native/template/tsconfig.json deleted file mode 100644 index 304ab4e2d83d02..00000000000000 --- a/packages/react-native/template/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "@react-native/typescript-config/tsconfig.json" -} From 5df5ed1a88a7119f9837e19169486522e615f93a Mon Sep 17 00:00:00 2001 From: Josh Katz Date: Mon, 17 Jun 2024 16:41:33 -0700 Subject: [PATCH 011/968] Revert D58602799: Add unit tests for BorderRadiusStyle Differential Revision: D58602799 Original commit changeset: 605bc384267d Original Phabricator Diff: D58602799 fbshipit-source-id: e843aa25f0cb37344a423e886b4e4a2878d89eec --- .../uimanager/style/ComputedBorderRadius.kt | 17 -- .../react/uimanager/BorderRadiusStyleTest.kt | 186 ------------------ 2 files changed, 203 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt index 292b66c5b4dfbc..d337e80ba35143 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt @@ -7,14 +7,6 @@ package com.facebook.react.uimanager.style -/** Represents the collection of possible computed border radius style properties. */ -public enum class ComputedBorderRadiusProp { - COMPUTED_BORDER_TOP_LEFT_RADIUS, - COMPUTED_BORDER_TOP_RIGHT_RADIUS, - COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS, - COMPUTED_BORDER_BOTTOM_LEFT_RADIUS, -} - /** Phsysical edge lengths (in DIPs) for a border-radius. */ public data class ComputedBorderRadius( val topLeft: Float, @@ -26,14 +18,5 @@ public data class ComputedBorderRadius( return topLeft > 0f || topRight > 0f || bottomLeft > 0f || bottomRight > 0f } - public fun get(property: ComputedBorderRadiusProp): Float { - return when (property) { - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS -> topLeft - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS -> topRight - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS -> bottomLeft - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS -> bottomRight - } - } - public constructor() : this(0f, 0f, 0f, 0f) } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt deleted file mode 100644 index 81f48635b4b1ee..00000000000000 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.uimanager - -import android.content.Context -import com.facebook.react.uimanager.style.BorderRadiusProp -import com.facebook.react.uimanager.style.BorderRadiusStyle -import com.facebook.react.uimanager.style.ComputedBorderRadiusProp -import org.assertj.core.api.Assertions.* -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment - -/** Tests for [BorderRadiusStyle] */ -@RunWith(RobolectricTestRunner::class) -class BorderRadiusStyleTest { - - private val ctx: Context = RuntimeEnvironment.getApplication() - - @Test - fun testCorrectPriorityLTR() { - val propertyOrderMap = - mapOf( - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, - BorderRadiusProp.BORDER_TOP_START_RADIUS, - BorderRadiusProp.BORDER_START_START_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, - BorderRadiusProp.BORDER_TOP_END_RADIUS, - BorderRadiusProp.BORDER_END_START_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, - BorderRadiusProp.BORDER_START_END_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, - BorderRadiusProp.BORDER_END_END_RADIUS), - ) - - propertyOrderMap.forEach { order -> - val borderRadiusStyle = BorderRadiusStyle() - // Starting count on 3 to test 0 override - var count = 3f - for (prop in order.value) { - borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) - val resolved = borderRadiusStyle.resolve(0, context = ctx, width = 100f, height = 100f) - assertThat(resolved.get(order.key)).isEqualTo(count) - count -= 1f - } - } - } - - @Test - fun testCorrectPriorityRTL() { - setContextLeftAndRightSwap(ctx, true) - val propertyOrderMap = - mapOf( - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, - BorderRadiusProp.BORDER_TOP_END_RADIUS, - BorderRadiusProp.BORDER_END_START_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, - BorderRadiusProp.BORDER_TOP_START_RADIUS, - BorderRadiusProp.BORDER_START_START_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, - BorderRadiusProp.BORDER_END_END_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, - BorderRadiusProp.BORDER_START_END_RADIUS), - ) - - propertyOrderMap.forEach { order -> - val borderRadiusStyle = BorderRadiusStyle() - // Starting count on 3 to test 0 override - var count = 3f - for (prop in order.value) { - borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) - val resolved = borderRadiusStyle.resolve(1, context = ctx, width = 100f, height = 100f) - assertThat(resolved.get(order.key)).isEqualTo(count) - count -= 1f - } - } - } - - @Test - fun testCorrectPriorityRTLNoSwap() { - setContextLeftAndRightSwap(ctx, false) - val propertyOrderMap = - mapOf( - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, - BorderRadiusProp.BORDER_TOP_END_RADIUS, - BorderRadiusProp.BORDER_END_START_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, - BorderRadiusProp.BORDER_TOP_START_RADIUS, - BorderRadiusProp.BORDER_START_START_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, - BorderRadiusProp.BORDER_END_END_RADIUS), - ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to - arrayOf( - BorderRadiusProp.BORDER_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, - BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, - BorderRadiusProp.BORDER_START_END_RADIUS), - ) - - propertyOrderMap.forEach { order -> - val borderRadiusStyle = BorderRadiusStyle() - // Starting count on 3 to test 0 override - var count = 3f - for (prop in order.value) { - borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) - val resolved = borderRadiusStyle.resolve(1, context = ctx, width = 100f, height = 100f) - assertThat(resolved.get(order.key)).isEqualTo(count) - count -= 1f - } - } - } - - @Test - fun testBorderRadiusPercentages() { - val borderRadiusStyle = - BorderRadiusStyle( - topLeft = LengthPercentage(0f, LengthPercentageType.PERCENT), - topRight = LengthPercentage(10f, LengthPercentageType.PERCENT), - bottomLeft = LengthPercentage(20f, LengthPercentageType.PERCENT), - bottomRight = LengthPercentage(30f, LengthPercentageType.PERCENT), - ) - val resolved = borderRadiusStyle.resolve(0, context = ctx, width = 1000f, height = 1000f) - - assertThat(resolved.topLeft).isEqualTo(0f) - assertThat(resolved.topRight).isEqualTo(100f) - assertThat(resolved.bottomLeft).isEqualTo(200f) - assertThat(resolved.bottomRight).isEqualTo(300f) - } - - /* - * Make I18nUtil.instance.doLeftAndRightSwapInRTL(context) return false - * by setting context preference - */ - private fun setContextLeftAndRightSwap(context: Context, leftAndRightSwap: Boolean) { - val sharedPrefs = - context.getSharedPreferences( - "com.facebook.react.modules.i18nmanager.I18nUtil", Context.MODE_PRIVATE) - val editor = sharedPrefs.edit() - editor.putBoolean("RCTI18nUtil_makeRTLFlipLeftAndRightStyles", leftAndRightSwap) - editor.apply() - } -} From 43d69ee26cbf4d4cc9b64aafbcdc32f3df0f27f9 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 18 Jun 2024 02:53:18 -0700 Subject: [PATCH 012/968] Fix ReactNativeReloads test case (#45011) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45011 Changelog: [Internal] Fixes an inspector-proxy test case that was (silently) incorrect. This is in preparation for an upcoming rewrite of the core of inspector-proxy to more strictly isolate session state, which causes the incorrect test to fail. Reviewed By: hoxyq Differential Revision: D58193527 fbshipit-source-id: bdc27179210117ca9249b272f2e4aff19ba8a06c --- .../src/__tests__/InspectorProxyReactNativeReloads-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js index a89ddbd08ed558..08cfb6088d3549 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyReactNativeReloads-test.js @@ -236,7 +236,7 @@ describe('inspector proxy React Native reloads', () => { * We can reuse our existing debugger connection to the synthetic page. * Messages from the updated page will be routed to the debugger. */ - device1.sendWrappedEvent('originalPage-initial', { + device1.sendWrappedEvent('originalPage-updated', { error: 'Another mock error', }); From 404f323359f9af469ba60132d802ffa0b2d72675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 18 Jun 2024 05:24:57 -0700 Subject: [PATCH 013/968] Set up experiment to fix the mapping of event priorities between Fabric and React (#45013) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45013 Changelog: [internal] ## Context We recently realized that in the majority of events dispatched to React from Fabric, passive effects were being mounted synchronously, blocking paint instead of in a separate task after paint. The reason for that is that in React, passive effects for discrete events are mounted synchronously by design (see https://github.com/reactwg/react-18/discussions/128), and Fabric is currently assigning the discrete event priority to most current events (including things like layout events). ## Changes This creates a feature flag to opt into a more granular control over event priorities in React Native. Instead of assigning the discrete event priority to events by default, this would assign the "default" event priority by default, except for events dispatched during continuous events that would also be considered continuous. This would also fix the priority for continuous events, that it was currently being assigned as "default" incorrectly. Reviewed By: christophpurrer, javache, sammy-SC Differential Revision: D58677191 fbshipit-source-id: c65a8dc2118ed028e1e895adec54f9072b7e55a6 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 ++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 ++++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 ++- .../featureflags/ReactNativeFeatureFlags.h | 7 ++- .../ReactNativeFeatureFlagsAccessor.cpp | 46 +++++++++++++------ .../ReactNativeFeatureFlagsAccessor.h | 6 ++- .../ReactNativeFeatureFlagsDefaults.h | 6 ++- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 ++- .../NativeReactNativeFeatureFlags.h | 4 +- .../renderer/core/EventQueueProcessor.cpp | 45 +++++++++++++----- .../ReactNativeFeatureFlags.config.js | 5 ++ .../featureflags/ReactNativeFeatureFlags.js | 7 ++- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 20 files changed, 168 insertions(+), 43 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 1d37426856c410..ccddca4abb1338 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<177f05d7b2fadcfffa32cb5a7a21c76b>> + * @generated SignedSource<<9a33a6bc10cdb2b0f9fcb15805a06982>> */ /** @@ -94,6 +94,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableUIConsistency(): Boolean = accessor.enableUIConsistency() + /** + * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. + */ + @JvmStatic + public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = accessor.fixMappingOfEventPrioritiesBetweenFabricAndReact() + /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 25b762bd413d06..884795d8109fd9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<492902f307361b8f7b7d42973561a3b4>> + * @generated SignedSource<<5d67280406c16b01ba71b7b75e814a79>> */ /** @@ -31,6 +31,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableMicrotasksCache: Boolean? = null private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null + private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null private var forceBatchingMountItemsOnAndroidCache: Boolean? = null private var fuseboxEnabledDebugCache: Boolean? = null @@ -144,6 +145,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean { + var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.fixMappingOfEventPrioritiesBetweenFabricAndReact() + fixMappingOfEventPrioritiesBetweenFabricAndReactCache = cached + } + return cached + } + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean { var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 947512885ac58f..9abef85cb31492 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<05bf91e1b2a64cdc48615137deec627a>> + * @generated SignedSource<<154baea748cdf7b8e05a1e4448053673>> */ /** @@ -50,6 +50,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableUIConsistency(): Boolean + @DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean + @DoNotStrip @JvmStatic public external fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean @DoNotStrip @JvmStatic public external fun forceBatchingMountItemsOnAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 27cf09922f0de4..04d17b77e8cce5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7c95ebf976344317cd8904d71ea22fe5>> + * @generated SignedSource<<34bbd584a612fa88cc6adf2d2bc51b92>> */ /** @@ -45,6 +45,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableUIConsistency(): Boolean = false + override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean = false override fun forceBatchingMountItemsOnAndroid(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index f73a9f3d265155..9d3d163dc48c76 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -35,6 +35,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableMicrotasksCache: Boolean? = null private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null + private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null private var forceBatchingMountItemsOnAndroidCache: Boolean? = null private var fuseboxEnabledDebugCache: Boolean? = null @@ -159,6 +160,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean { + var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache + if (cached == null) { + cached = currentProvider.fixMappingOfEventPrioritiesBetweenFabricAndReact() + accessedFeatureFlags.add("fixMappingOfEventPrioritiesBetweenFabricAndReact") + fixMappingOfEventPrioritiesBetweenFabricAndReactCache = cached + } + return cached + } + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean { var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index d4a63baf4d20e0..eb3e21e12782a8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -45,6 +45,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableUIConsistency(): Boolean + @DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean + @DoNotStrip public fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean @DoNotStrip public fun forceBatchingMountItemsOnAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 9eeab79065a2f7..d5ad1a7f1c8bd7 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2af7a8ae4860f81b46e48afb17ee54b6>> + * @generated SignedSource<<88f5b83b8a3d7902eaab333246b59ed3>> */ /** @@ -105,6 +105,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixMappingOfEventPrioritiesBetweenFabricAndReact"); + return method(javaProvider_); + } + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); @@ -242,6 +248,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableUIConsistency( return ReactNativeFeatureFlags::enableUIConsistency(); } +bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); +} + bool JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); @@ -357,6 +368,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableUIConsistency", JReactNativeFeatureFlagsCxxInterop::enableUIConsistency), + makeNativeMethod( + "fixMappingOfEventPrioritiesBetweenFabricAndReact", + JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact), makeNativeMethod( "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak", JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 1206b2215fb8a7..f9e1381671a8d2 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1d1422d073ae40ee4bbc788dc222cc28>> + * @generated SignedSource<<66b47850d8e211f78b3e3dd40b6cc37e>> */ /** @@ -63,6 +63,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableUIConsistency( facebook::jni::alias_ref); + static bool fixMappingOfEventPrioritiesBetweenFabricAndReact( + facebook::jni::alias_ref); + static bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 0d291b1b9ecde5..ce3f391dffb348 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -65,6 +65,10 @@ bool ReactNativeFeatureFlags::enableUIConsistency() { return getAccessor().enableUIConsistency(); } +bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() { + return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact(); +} + bool ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() { return getAccessor().fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index b809f8409f73e0..014c51420923e8 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5f1ae3edfe01ee0545bd89137c5cb3e9>> + * @generated SignedSource<> */ /** @@ -92,6 +92,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableUIConsistency(); + /** + * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. + */ + RN_EXPORT static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); + /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 8bca846e683bf0..179d23099e1b3f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6d08fc8ff31f1db50cb4b14edb6b690f>> + * @generated SignedSource<<44087cc6e946a05884c8761987878183>> */ /** @@ -227,6 +227,24 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAndReact() { + auto flagValue = fixMappingOfEventPrioritiesBetweenFabricAndReact_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(11, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + + flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); + fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() { auto flagValue = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_.load(); @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCa // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); + markFlagAsAccessed(12, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(13, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "fuseboxEnabledDebug"); + markFlagAsAccessed(14, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "fuseboxEnabledRelease"); + markFlagAsAccessed(15, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "lazyAnimationCallbacks"); + markFlagAsAccessed(16, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::preventDoubleTextMeasure() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "preventDoubleTextMeasure"); + markFlagAsAccessed(17, "preventDoubleTextMeasure"); flagValue = currentProvider_->preventDoubleTextMeasure(); preventDoubleTextMeasure_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "setAndroidLayoutDirection"); + markFlagAsAccessed(18, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(19, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "useModernRuntimeScheduler"); + markFlagAsAccessed(20, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(21, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(22, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "useStateAlignmentMechanism"); + markFlagAsAccessed(24, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index ac520127127cc4..092b983a4ce39a 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3be4d7eb8694603de9fb5885562d5a78>> + * @generated SignedSource<<45258896e458cce165b403e043356eb9>> */ /** @@ -42,6 +42,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableMicrotasks(); bool enableSynchronousStateUpdates(); bool enableUIConsistency(); + bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); bool forceBatchingMountItemsOnAndroid(); bool fuseboxEnabledDebug(); @@ -65,7 +66,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 24> accessedFeatureFlags_; + std::array, 25> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowCollapsableChildren_; @@ -78,6 +79,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableMicrotasks_; std::atomic> enableSynchronousStateUpdates_; std::atomic> enableUIConsistency_; + std::atomic> fixMappingOfEventPrioritiesBetweenFabricAndReact_; std::atomic> fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_; std::atomic> forceBatchingMountItemsOnAndroid_; std::atomic> fuseboxEnabledDebug_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 916ed06c2aa4e7..8af86e0d7383ca 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<97c824bb63734389fae8eea61b92d440>> + * @generated SignedSource<<0f6ca616cc516096ec250d61be440952>> */ /** @@ -71,6 +71,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override { + return false; + } + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 3923d4b9e882a2..87d9985fa20fab 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<454a55db4c97f9c28c0a8427d4c0bd57>> + * @generated SignedSource<<3da295d89796e905588eb863a51c2054>> */ /** @@ -36,6 +36,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableMicrotasks() = 0; virtual bool enableSynchronousStateUpdates() = 0; virtual bool enableUIConsistency() = 0; + virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0; virtual bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() = 0; virtual bool forceBatchingMountItemsOnAndroid() = 0; virtual bool fuseboxEnabledDebug() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 4d6a71669d17f1..6951bd603166ce 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<81d9543c4231939f31dc5c9bb06c942c>> + * @generated SignedSource<<82399968da4f450b87c908031466a38a>> */ /** @@ -92,6 +92,11 @@ bool NativeReactNativeFeatureFlags::enableUIConsistency( return ReactNativeFeatureFlags::enableUIConsistency(); } +bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); +} + bool NativeReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 0b16a9e99a0147..2266b2292037af 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6b8504e42d72611f4d4b6606d69c42aa>> */ /** @@ -57,6 +57,8 @@ class NativeReactNativeFeatureFlags bool enableUIConsistency(jsi::Runtime& runtime); + bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime); + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(jsi::Runtime& runtime); bool forceBatchingMountItemsOnAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp index 6866422b17f328..d8f0a2748d50da 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventQueueProcessor.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "EventEmitter.h" #include "EventLogger.h" #include "EventQueue.h" @@ -38,20 +39,42 @@ void EventQueueProcessor::flushEvents( } for (const auto& event : events) { - if (event.category == RawEvent::Category::ContinuousEnd) { - hasContinuousEventStarted_ = false; - } + auto reactPriority = ReactEventPriority::Default; + + if (ReactNativeFeatureFlags:: + fixMappingOfEventPrioritiesBetweenFabricAndReact()) { + reactPriority = [&]() { + switch (event.category) { + case RawEvent::Category::Discrete: + return ReactEventPriority::Discrete; + case RawEvent::Category::ContinuousStart: + hasContinuousEventStarted_ = true; + return ReactEventPriority::Discrete; + case RawEvent::Category::ContinuousEnd: + hasContinuousEventStarted_ = false; + return ReactEventPriority::Discrete; + case RawEvent::Category::Continuous: + return ReactEventPriority::Continuous; + case RawEvent::Category::Unspecified: + return hasContinuousEventStarted_ ? ReactEventPriority::Continuous + : ReactEventPriority::Default; + } + }(); + } else { + if (event.category == RawEvent::Category::ContinuousEnd) { + hasContinuousEventStarted_ = false; + } - auto reactPriority = hasContinuousEventStarted_ - ? ReactEventPriority::Default - : ReactEventPriority::Discrete; + reactPriority = hasContinuousEventStarted_ ? ReactEventPriority::Default + : ReactEventPriority::Discrete; - if (event.category == RawEvent::Category::Continuous) { - reactPriority = ReactEventPriority::Default; - } + if (event.category == RawEvent::Category::Continuous) { + reactPriority = ReactEventPriority::Default; + } - if (event.category == RawEvent::Category::Discrete) { - reactPriority = ReactEventPriority::Discrete; + if (event.category == RawEvent::Category::Discrete) { + reactPriority = ReactEventPriority::Discrete; + } } auto eventLogger = eventLogger_.lock(); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 3cd9aeabda8937..313fffce5284ee 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -88,6 +88,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).', }, + fixMappingOfEventPrioritiesBetweenFabricAndReact: { + defaultValue: false, + description: + 'Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.', + }, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 2554ebcc349ca2..6bc4b7dd1cab57 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<870e25c844e692bb04ee49fe20cd3baf>> + * @generated SignedSource<> * @flow strict-local */ @@ -51,6 +51,7 @@ export type ReactNativeFeatureFlags = { enableMicrotasks: Getter, enableSynchronousStateUpdates: Getter, enableUIConsistency: Getter, + fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: Getter, forceBatchingMountItemsOnAndroid: Getter, fuseboxEnabledDebug: Getter, @@ -150,6 +151,10 @@ export const enableSynchronousStateUpdates: Getter = createNativeFlagGe * Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution). */ export const enableUIConsistency: Getter = createNativeFlagGetter('enableUIConsistency', false); +/** + * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. + */ +export const fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter = createNativeFlagGetter('fixMappingOfEventPrioritiesBetweenFabricAndReact', false); /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 6d879790467c89..475f8fd79cf98d 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6922b452333fc62a263bd77d42afbbbe>> + * @generated SignedSource<<6715ba4954b31464c591597c53a2a0de>> * @flow strict-local */ @@ -34,6 +34,7 @@ export interface Spec extends TurboModule { +enableMicrotasks?: () => boolean; +enableSynchronousStateUpdates?: () => boolean; +enableUIConsistency?: () => boolean; + +fixMappingOfEventPrioritiesBetweenFabricAndReact?: () => boolean; +fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak?: () => boolean; +forceBatchingMountItemsOnAndroid?: () => boolean; +fuseboxEnabledDebug?: () => boolean; From 37d7ec65227c1d6ea5144d0fec46f15c384d171f Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 18 Jun 2024 05:25:22 -0700 Subject: [PATCH 014/968] Move test_android_helloworld to 4-core-ubuntu (#45023) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45023 This mirrors the same setup we have on the 0.75 release branch Changelog: [Internal] [Changed] - Move test_android_helloworld to 4-core-ubuntu Reviewed By: cipolleschi, blakef Differential Revision: D58724157 fbshipit-source-id: 754d4f777d4239eeaa6a5232508f54cfe62d4c88 --- .github/workflows/test-all.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index d35e807cabfc9a..85472ef94b0278 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -798,7 +798,7 @@ jobs: -d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"${{ github.ref_name }}\" }}" test_android_helloworld: - runs-on: ubuntu-latest + runs-on: 4-core-ubuntu needs: prepare_hermes_workspace container: image: reactnativecommunity/react-native-android:latest From 01f7ab814f847eb3038efa7120d81e92e3ff4187 Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Tue, 18 Jun 2024 05:28:21 -0700 Subject: [PATCH 015/968] Fix text baseline being moved up on iOS (#44932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Fixes https://github.com/facebook/react-native/issues/44929 Moves calling `RCTApplyBaselineOffset` so it's called in similar way as on the old architecture: https://github.com/facebook/react-native/blob/726a4a1e5ef3bc8034a068145da2bb94ae3acfaa/packages/react-native/Libraries/Text/Text/RCTTextShadowView.mm#L229 https://github.com/facebook/react-native/blob/726a4a1e5ef3bc8034a068145da2bb94ae3acfaa/packages/react-native/Libraries/Text/Text/RCTTextShadowView.mm#L165-L167 I'm not exactly sure why (and Apple's docs aren't helping) but it looks like calling `NSTextStorage initWithAttributedString` results in an attributed string where emojis are separate fragments with Apple's emoji font set, which results in the correct baseline calculations. This is the way it happens on the old arch. The way it's currently implemented on the new architecture, `RCTApplyBaselineOffset` is called on ` newly created attributed string where emojis are in the same fragment as other parts of the text which alters the result of baseline calculations compared to what's later drawn on the screen. ## Changelog: [IOS] [FIXED] - Fixed text baseline being moved upwards in certain cases Pull Request resolved: https://github.com/facebook/react-native/pull/44932 Test Plan:
Check the following snipped ```jsx import React from 'react'; import { Text, View, } from 'react-native'; const App = () => { return ( A 😞😞😞 B ); }; export default App; ```
|Before|After| |-|-| |new-broken|new-fixed| Reviewed By: cipolleschi Differential Revision: D58589249 Pulled By: sammy-SC fbshipit-source-id: 1e0a730519a5c79ff8a35b0dfb16b68966a8dd9f --- .../react/renderer/textlayoutmanager/RCTAttributedTextUtils.h | 2 ++ .../react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm | 3 +-- .../react/renderer/textlayoutmanager/RCTTextLayoutManager.mm | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h index 49a4353c5f011c..c0158f3df61e7a 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h @@ -39,6 +39,8 @@ facebook::react::AttributedStringBox RCTAttributedStringBoxFromNSAttributedStrin NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook::react::TextTransform textTransform); +void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText); + @interface RCTWeakEventEmitterWrapper : NSObject @property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter; @end diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm index 74f5b65df1338d..5bdeac31b493c1 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm @@ -300,7 +300,7 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex return [attributes copy]; } -static void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) +void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) { __block CGFloat maximumLineHeight = 0; @@ -411,7 +411,6 @@ static void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText) [nsAttributedString appendAttributedString:nsAttributedStringFragment]; } - RCTApplyBaselineOffset(nsAttributedString); [nsAttributedString endEditing]; return nsAttributedString; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index b17124642b5332..a50065a56cf416 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -185,6 +185,8 @@ - (NSTextStorage *)_textStorageAndLayoutManagerWithAttributesString:(NSAttribute NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; + RCTApplyBaselineOffset(textStorage); + [textStorage addLayoutManager:layoutManager]; if (paragraphAttributes.adjustsFontSizeToFit) { From 64d5de73719f407a8b7f2d718348d8139a77f32f Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Tue, 18 Jun 2024 06:54:31 -0700 Subject: [PATCH 016/968] Add Android Helloworld test on PR (#45019) Summary: Use GHA on PRs: 1. run test_android_helloworld when users create a PR, to provide coverage while we figure out what's going on with our CircleCI tests / deprecate them. 2. fixes uploading the `.apks` that are generated. Changelog: [Internal] Pull Request resolved: https://github.com/facebook/react-native/pull/45019 Test Plan: Does GHA run for this PR? Reviewed By: cipolleschi Differential Revision: D58728019 Pulled By: blakef fbshipit-source-id: c6db41d60225702d50343384f103585d83e3528c --- .github/workflows/test-all.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 85472ef94b0278..3e782d74649921 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -2,6 +2,7 @@ name: Test All on: workflow_dispatch: + pull_request: push: branches: - main @@ -875,7 +876,7 @@ jobs: uses: actions/upload-artifact@v4.3.1 with: name: template-apk-${{ matrix.flavor }}-${{ matrix.architecture }}-${{ matrix.jsengine }} - path: ./app/build/outputs/apk/ + path: packages/helloworld/app/build/outputs/apk/ compression-level: 0 test_ios_helloworld_with_ruby_3_2_0: From db2c44a7eb2b4aa3f98dfa16a8ca5412880680fb Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 18 Jun 2024 08:25:32 -0700 Subject: [PATCH 017/968] Make inspector-proxy protocol types mutable by default (#45021) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45021 Changelog: [Internal] TSIA, hoisted from an upcoming refactor of `Device` in inspector-proxy. Reviewed By: hoxyq Differential Revision: D58723496 fbshipit-source-id: af272b08bc280d681bd7e1adb60d2a411a549864 --- .../src/inspector-proxy/Device.js | 4 ---- .../inspector-proxy/DeviceEventReporter.js | 3 ++- .../src/inspector-proxy/cdp-types/messages.js | 23 +++++++++--------- .../src/inspector-proxy/cdp-types/protocol.js | 24 ++++++++++--------- .../src/inspector-proxy/types.js | 7 ++++++ 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 5a5f3ff0671dfd..d43654c5a50987 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -642,7 +642,6 @@ export default class Device { if ('sourceMapURL' in params) { for (const hostToRewrite of REWRITE_HOSTS_TO_LOCALHOST) { if (params.sourceMapURL.includes(hostToRewrite)) { - // $FlowFixMe[cannot-write] payload.params.sourceMapURL = params.sourceMapURL.replace( hostToRewrite, 'localhost', @@ -660,7 +659,6 @@ export default class Device { // message to the debug client. try { const sourceMap = await this.#fetchText(sourceMapURL); - // $FlowFixMe[cannot-write] payload.params.sourceMapURL = 'data:application/json;charset=utf-8;base64,' + Buffer.from(sourceMap).toString('base64'); @@ -674,7 +672,6 @@ export default class Device { if ('url' in params) { for (const hostToRewrite of REWRITE_HOSTS_TO_LOCALHOST) { if (params.url.includes(hostToRewrite)) { - // $FlowFixMe[cannot-write] payload.params.url = params.url.replace(hostToRewrite, 'localhost'); debuggerInfo.originalSourceURLAddress = hostToRewrite; } @@ -685,7 +682,6 @@ export default class Device { // Chrome to not download source maps. In this case we want to prepend script ID // with 'file://' prefix. if (payload.params.url.match(/^[0-9a-z]+$/)) { - // $FlowFixMe[cannot-write] payload.params.url = FILE_PREFIX + payload.params.url; debuggerInfo.prependedFilePrefix = true; } diff --git a/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js b/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js index 41e8e6ddc24c36..b210abf12efaaa 100644 --- a/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js +++ b/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js @@ -10,6 +10,7 @@ import type {EventReporter} from '../types/EventReporter'; import type {CDPResponse} from './cdp-types/messages'; +import type {DeepReadOnly} from './types'; import TTLCache from '@isaacs/ttlcache'; @@ -77,7 +78,7 @@ class DeviceEventReporter { } logResponse( - res: CDPResponse<>, + res: DeepReadOnly>, origin: 'device' | 'proxy', metadata: ResponseMetadata, ): void { diff --git a/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js b/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js index 79eb1458a995a3..b019728d15dfd1 100644 --- a/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js +++ b/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js @@ -9,35 +9,36 @@ * @oncall react_native */ +import type {JSONSerializable} from '../types'; import type {Commands, Events} from './protocol'; // Note: A CDP event is a JSON-RPC notification with no `id` member. -export type CDPEvent = 'unknown'> = $ReadOnly<{ +export type CDPEvent = 'unknown'> = { method: TEvent, params: Events[TEvent], -}>; +}; -export type CDPRequest = 'unknown'> = $ReadOnly<{ +export type CDPRequest = 'unknown'> = { method: TCommand, params: Commands[TCommand]['paramsType'], id: number, -}>; +}; export type CDPResponse = 'unknown'> = - | $ReadOnly<{ + | { result: Commands[TCommand]['resultType'], id: number, - }> - | $ReadOnly<{ + } + | { error: CDPRequestError, id: number, - }>; + }; -export type CDPRequestError = $ReadOnly<{ +export type CDPRequestError = { code: number, message: string, - data?: mixed, -}>; + data?: JSONSerializable, +}; export type CDPClientMessage = | CDPRequest<'Debugger.getScriptSource'> diff --git a/packages/dev-middleware/src/inspector-proxy/cdp-types/protocol.js b/packages/dev-middleware/src/inspector-proxy/cdp-types/protocol.js index 4b7500c4070b79..2111fb7dca3abb 100644 --- a/packages/dev-middleware/src/inspector-proxy/cdp-types/protocol.js +++ b/packages/dev-middleware/src/inspector-proxy/cdp-types/protocol.js @@ -11,17 +11,19 @@ // Adapted from https://github.com/ChromeDevTools/devtools-protocol/blob/master/types/protocol.d.ts +import type {JSONSerializable} from '../types'; + type integer = number; export interface Debugger { - GetScriptSourceParams: $ReadOnly<{ + GetScriptSourceParams: { /** * Id of the script to get source for. */ scriptId: string, - }>; + }; - GetScriptSourceResult: $ReadOnly<{ + GetScriptSourceResult: { /** * Script source (empty in case of Wasm bytecode). */ @@ -31,9 +33,9 @@ export interface Debugger { * Wasm bytecode. (Encoded as a base64 string when passed over JSON) */ bytecode?: string, - }>; + }; - SetBreakpointByUrlParams: $ReadOnly<{ + SetBreakpointByUrlParams: { /** * Line number to set breakpoint at. */ @@ -65,9 +67,9 @@ export interface Debugger { * breakpoint if this expression evaluates to true. */ condition?: string, - }>; + }; - ScriptParsedEvent: $ReadOnly<{ + ScriptParsedEvent: { /** * Identifier of the script parsed. */ @@ -82,12 +84,12 @@ export interface Debugger { * URL of source map associated with script (if any). */ sourceMapURL: string, - }>; + }; } export type Events = { 'Debugger.scriptParsed': Debugger['ScriptParsedEvent'], - [method: string]: mixed, + [method: string]: JSONSerializable, }; export type Commands = { @@ -100,7 +102,7 @@ export type Commands = { resultType: void, }, [method: string]: { - paramsType: mixed, - resultType: mixed, + paramsType: JSONSerializable, + resultType: JSONSerializable, }, }; diff --git a/packages/dev-middleware/src/inspector-proxy/types.js b/packages/dev-middleware/src/inspector-proxy/types.js index 72b975b27489a5..83051ba0fdfd3b 100644 --- a/packages/dev-middleware/src/inspector-proxy/types.js +++ b/packages/dev-middleware/src/inspector-proxy/types.js @@ -146,3 +146,10 @@ export type JSONSerializable = | null | $ReadOnlyArray | {+[string]: JSONSerializable}; + +export type DeepReadOnly = + T extends $ReadOnlyArray + ? $ReadOnlyArray> + : T extends {...} + ? {+[K in keyof T]: DeepReadOnly} + : T; From cdab5370af7647d00cdf71a5e6134569ce66dc2b Mon Sep 17 00:00:00 2001 From: Hailey Date: Tue, 18 Jun 2024 08:44:09 -0700 Subject: [PATCH 018/968] fix (iOS): fix `selectTextOnFocus` in Fabric and non-Fabric by calling `selectAll` after `becomeFirstResponder` (#44307) Summary: Fixes https://github.com/facebook/react-native/issues/41988 Hopefully even if this isn't the right way to go about solving this, it at least points in the right direction for a different fix! Currently - both on Paper and Fabric - the `selectTextOnFocus` prop does not work as expected on a single line text input. It seems that if the `UITextField` has not yet become the first responder, the text will be briefly selected but then deselected immediately afterward. This can be seen in the tester when running for either Fabric or Paper (video using Fabric) https://github.com/facebook/react-native/assets/153161762/aa9c609e-6eb8-4177-a41f-32aae53c06ac Instead, we can move the `selectAll` call to `reactFocus` in `RCTBaseTextInputView` or `focus` `RCTTextInputComponentView` - both of which first call `becomeFirstResponder` - to get the expected result. ## Changelog: [IOS] [FIXED] - fix selectTextOnFocus in Fabric and non-Fabric by calling selectAll after becomeFirstResponder Pull Request resolved: https://github.com/facebook/react-native/pull/44307 Test Plan: * Test changes on RN Tester (iOS) https://pxl.cl/55kDc Reviewed By: cipolleschi Differential Revision: D56699773 Pulled By: fabriziocucci fbshipit-source-id: ed092835f3c602e2c50a4198357653a9cef942d9 --- .../Text/TextInput/RCTBaseTextInputView.mm | 16 ++++++------- .../TextInput/RCTTextInputComponentView.mm | 24 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm index 826ff3a0de2c9b..72cf885c37e824 100644 --- a/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm +++ b/packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm @@ -375,14 +375,6 @@ - (BOOL)textInputShouldBeginEditing - (void)textInputDidBeginEditing { - if (_clearTextOnFocus) { - self.backedTextInputView.attributedText = [NSAttributedString new]; - } - - if (_selectTextOnFocus) { - [self.backedTextInputView selectAll:nil]; - } - [_eventDispatcher sendTextEventWithType:RCTTextEventTypeFocus reactTag:self.reactTag text:[self.backedTextInputView.attributedText.string copy] @@ -600,6 +592,14 @@ - (UIView *)reactAccessibilityElement - (void)reactFocus { [self.backedTextInputView reactFocus]; + + if (_clearTextOnFocus) { + self.backedTextInputView.attributedText = [NSAttributedString new]; + } + + if (_selectTextOnFocus) { + [self.backedTextInputView selectAll:nil]; + } } - (void)reactBlur diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 369cdf656a3cf7..51914b7448e837 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -280,18 +280,6 @@ - (BOOL)textInputShouldBeginEditing - (void)textInputDidBeginEditing { - const auto &props = static_cast(*_props); - - if (props.traits.clearTextOnFocus) { - _backedTextInputView.attributedText = nil; - [self textInputDidChange]; - } - - if (props.traits.selectTextOnFocus) { - [_backedTextInputView selectAll:nil]; - [self textInputDidChangeSelection]; - } - if (_eventEmitter) { static_cast(*_eventEmitter).onFocus([self _textInputMetrics]); } @@ -431,6 +419,18 @@ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args - (void)focus { [_backedTextInputView becomeFirstResponder]; + + const auto &props = static_cast(*_props); + + if (props.traits.clearTextOnFocus) { + _backedTextInputView.attributedText = nil; + [self textInputDidChange]; + } + + if (props.traits.selectTextOnFocus) { + [_backedTextInputView selectAll:nil]; + [self textInputDidChangeSelection]; + } } - (void)blur From a272e8ee66600a9d30135a55b40ba4ff05f5fcc3 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 18 Jun 2024 09:06:42 -0700 Subject: [PATCH 019/968] Remove unused rn-tester e2e tests (#45032) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45032 Those tests haven't been running since ~1 year now. I know it's not ideal but I'd rather remove them instead of keeping them around not executing. We can still revert them back from the history once we decide to revive the E2E testing effort. Changelog: [Internal] [Changed] - Remove unused rn-tester e2e tests Reviewed By: cipolleschi Differential Revision: D58729123 fbshipit-source-id: f0f47e3c2e087141fdff506b7c5c9b460263721b --- .circleci/README.md | 1 - .circleci/configurations/jobs.yml | 134 ---- .../configurations/test_workflows/testE2E.yml | 9 - .github/workflows/run-e2e-tests.yml | 26 - .gitignore | 4 - jest.config.js | 1 - packages/rn-tester-e2e/README.md | 124 ---- packages/rn-tester-e2e/apps/README.md | 1 - packages/rn-tester-e2e/babel.config.js | 14 - packages/rn-tester-e2e/e2e-config.js | 61 -- packages/rn-tester-e2e/jest.config.js | 18 - packages/rn-tester-e2e/jest.setup.js | 50 -- packages/rn-tester-e2e/package.json | 25 - .../rn-tester-e2e/scripts/run-e2e-tests.js | 16 - packages/rn-tester-e2e/tests/helpers/utils.js | 95 --- .../tests/screens/apis.screen.js | 15 - .../tests/screens/bookmarks.screen.js | 15 - .../tests/screens/components.screen.js | 225 ------- .../activityIndicatorComponent.screen.js | 50 -- .../components/buttonComponent.screen.js | 95 --- .../components/flatListComponent.screen.js | 351 ----------- .../jsResponderHandlerComponent.screen.js | 57 -- .../keyboardAvoidingViewComponent.screen.js | 105 ---- .../components/modalComponent.screen.js | 91 --- .../components/newAppComponent.screen.js | 49 -- .../components/pressableComponent.screen.js | 80 --- .../refreshControlComponent.screen.js | 47 -- ...scrollViewSimpleExampleComponent.screen.js | 51 -- .../activityIndicatorComponentScreen.test.js | 26 - .../components/buttonComponentScreen.test.js | 46 -- .../flatListComponentScreen.test.js | 187 ------ .../jsResponderHandlerComponentScreen.test.js | 33 - ...eyboardAvoidingViewComponentScreen.test.js | 39 -- .../components/modalComponentScreen.test.js | 31 - .../components/newAppComponentScreen.test.js | 27 - .../pressableComponentScreen.test.js | 37 -- .../refreshControlComponentScreen.test.js | 27 - ...llViewSimpleExampleComponentScreen.test.js | 27 - scripts/android-e2e-test.js | 155 ----- .../circleci/check_appium_server_status.sh | 11 - scripts/e2e/run-ci-e2e-tests.js | 328 ---------- yarn.lock | 587 +----------------- 42 files changed, 22 insertions(+), 3349 deletions(-) delete mode 100644 .circleci/configurations/test_workflows/testE2E.yml delete mode 100644 .github/workflows/run-e2e-tests.yml delete mode 100644 packages/rn-tester-e2e/README.md delete mode 100644 packages/rn-tester-e2e/apps/README.md delete mode 100644 packages/rn-tester-e2e/babel.config.js delete mode 100644 packages/rn-tester-e2e/e2e-config.js delete mode 100644 packages/rn-tester-e2e/jest.config.js delete mode 100644 packages/rn-tester-e2e/jest.setup.js delete mode 100644 packages/rn-tester-e2e/package.json delete mode 100644 packages/rn-tester-e2e/scripts/run-e2e-tests.js delete mode 100644 packages/rn-tester-e2e/tests/helpers/utils.js delete mode 100644 packages/rn-tester-e2e/tests/screens/apis.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/bookmarks.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/activityIndicatorComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/buttonComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/flatListComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/jsResponderHandlerComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/keyboardAvoidingViewComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/modalComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/newAppComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/pressableComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/refreshControlComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/screens/components/scrollViewSimpleExampleComponent.screen.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/activityIndicatorComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/buttonComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/flatListComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/jsResponderHandlerComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/keyboardAvoidingViewComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/modalComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/newAppComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/pressableComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/refreshControlComponentScreen.test.js delete mode 100644 packages/rn-tester-e2e/tests/specs/components/scrollViewSimpleExampleComponentScreen.test.js delete mode 100644 scripts/android-e2e-test.js delete mode 100755 scripts/circleci/check_appium_server_status.sh delete mode 100644 scripts/e2e/run-ci-e2e-tests.js diff --git a/.circleci/README.md b/.circleci/README.md index 0ae32f93c4d13c..17db13a4fc51de 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -63,7 +63,6 @@ These workflows are: * `testAll.yml` => runs all the possible tests. This workflow is executed on main and on PRs which change set touches both iOS and Android * `testAndroid.yml` => runs all the build steps and Android tests. This is used on changes that happens on the Android codebase and infra (`ReactAndroid` folder) * `testIOS.yml` => runs all the build steps and iOS tests. This is used on changes that happens on the iOS codebase and infra (`React` folder) -* `testE2E.yml` => runs the E2E tests. As of today, E2E tests can be triggered if the commit message contains the `#run-e2e-tests` tag. * `testJS.yml` => For all the changes that do not touch native/platform code, we only run JS tests. Notice that if there are changes on files that do not represents code (for example `.md` files like this one or the `Changelog`) we don't run any CI. diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml index fc15c96f7b8263..3a1e0da816f2d7 100644 --- a/.circleci/configurations/jobs.yml +++ b/.circleci/configurations/jobs.yml @@ -107,140 +107,6 @@ jobs: - store_test_results: path: ./reports/junit - # ------------------------- - # JOBS: iOS E2E Tests - # ------------------------- - test_e2e_ios: - executor: reactnativeios - parameters: - ruby_version: - default: "2.7.8" - description: The version of ruby that must be used - type: string - steps: - - checkout_code_with_cache - - run_yarn - - setup_hermes_version - - run: - name: Install appium - command: npm install appium@2.0.0 -g - - run: - name: Install appium drivers - command: | - appium driver install uiautomator2 - appium driver install xcuitest - - run: - name: Start Appium server - command: appium --base-path /wd/hub - background: true - - run: - name: Start Metro - command: | - cd packages/rn-tester - yarn start - background: true - - brew_install: - package: cmake - - setup_ruby: - ruby_version: << parameters.ruby_version >> - - run: - name: Boot iOS Simulator - command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true - - with_xcodebuild_cache: - steps: - - run: - name: Install Bundler - command: | - cd packages/rn-tester - bundle check || bundle install - bundle exec pod setup - RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --verbose - - run: - name: Build app - command: | - xcodebuild build \ - -workspace packages/rn-tester/RNTesterPods.xcworkspace \ - -configuration Debug \ - -scheme RNTester \ - -sdk iphonesimulator \ - -derivedDataPath /tmp/e2e/ - - run: - name: Move app to correct directory - command: mv /tmp/e2e/Build/Products/Debug-iphonesimulator/RNTester.app packages/rn-tester-e2e/apps/rn-tester.app - - run: - name: Check Appium server status - command: scripts/circleci/check_appium_server_status.sh - - run: - name: Run E2E tests - no_output_timeout: 30m - command: | - cd packages/rn-tester-e2e - (yarn test-e2e ios 2>&1 | tee /tmp/test_log) || true - - store_artifacts: - path: /tmp/test_log - - # ------------------------- - # JOBS: Android E2E Tests - # ------------------------- - test_e2e_android: - executor: - name: android/android-machine - tag: 2023.07.1 - steps: - - checkout_code_with_cache - - run_yarn - - android/create-avd: - avd-name: e2e_emulator - system-image: system-images;android-34;google_apis;x86_64 - install: true - - android/start-emulator: - avd-name: e2e_emulator - no-window: true - restore-gradle-cache-prefix: v1a - post-emulator-launch-assemble-command: "" - - run: - name: Install appium - command: npm install appium@2.0.0 -g - - run: - name: Install appium drivers - command: | - appium driver install uiautomator2@2.29.1 - appium driver install xcuitest@4.32.10 - - run: - name: Start Appium server - command: appium --base-path /wd/hub - background: true - - run: - name: Start Metro - command: | - cd packages/rn-tester - yarn start - background: true - - with_gradle_cache: - steps: - - run: - name: Build app - command: | - ./gradlew :packages:rn-tester:android:app:assembleHermesDebug -PreactNativeArchitectures=x86_64 - - run: - name: Move app to correct directory - command: mv packages/rn-tester/android/app/build/outputs/apk/hermes/debug/app-hermes-x86_64-debug.apk packages/rn-tester-e2e/apps/rn-tester.apk - - run: - name: Check Appium server status - command: | - if ! nc -z 127.0.0.1 4723; then - echo Could not find Appium server - exit 1 - fi - - run: - name: Run E2E tests - no_output_timeout: 30m - command: | - cd packages/rn-tester-e2e - (yarn test-e2e android 2>&1 | tee /tmp/test_log) || true - - store_artifacts: - path: /tmp/test_log - # ------------------------- # JOBS: Build Android # ------------------------- diff --git a/.circleci/configurations/test_workflows/testE2E.yml b/.circleci/configurations/test_workflows/testE2E.yml deleted file mode 100644 index a926a395775c0e..00000000000000 --- a/.circleci/configurations/test_workflows/testE2E.yml +++ /dev/null @@ -1,9 +0,0 @@ - tests_e2e: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - test_e2e_ios: - ruby_version: "2.7.8" - - test_e2e_android diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml deleted file mode 100644 index cf8478572270e9..00000000000000 --- a/.github/workflows/run-e2e-tests.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Run E2E Tests -# This workflow is used to trigger E2E tests on a PR when a comment is made -# containing the text "#run-e2e-tests". -on: - issue_comment: - types: [created] -permissions: - contents: read -jobs: - rebase: - name: Trigger E2E Tests - permissions: - contents: write # for cirrus-actions/rebase to push code to rebase - pull-requests: read # for cirrus-actions/rebase to get info about PR - runs-on: ubuntu-latest - if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '#run-e2e-tests') - steps: - - name: Checkout the latest code - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - fetch-depth: 0 # otherwise, you will fail to push refs to dest repo - - name: Push empty commit - run: | - git commit -m "#run-e2e-tests" --allow-empty - git push origin $(git branch --show-current) diff --git a/.gitignore b/.gitignore index 6c6e7832fd1c1d..5851f3674d5861 100644 --- a/.gitignore +++ b/.gitignore @@ -159,9 +159,5 @@ vendor/ # Temporary files created by Metro to check the health of the file watcher .metro-health-check* -# E2E files -/packages/rn-tester-e2e/apps/*.apk -/packages/rn-tester-e2e/apps/*.app - # CircleCI .circleci/generated_config.yml diff --git a/jest.config.js b/jest.config.js index 933d17ec51500f..f81a4049d9a5d2 100644 --- a/jest.config.js +++ b/jest.config.js @@ -33,7 +33,6 @@ module.exports = { '/packages/react-native/template', '/packages/react-native/sdks', '/packages/react-native/Libraries/Renderer', - '/packages/rn-tester/e2e', '/packages/react-native-test-renderer/src', ], transformIgnorePatterns: ['node_modules/(?!@react-native/)'], diff --git a/packages/rn-tester-e2e/README.md b/packages/rn-tester-e2e/README.md deleted file mode 100644 index 4f3a1b5059cbd1..00000000000000 --- a/packages/rn-tester-e2e/README.md +++ /dev/null @@ -1,124 +0,0 @@ -# RNTester E2E folder - -In this folder we have a the setup for running E2E testing in RNTester via the usage of [Appium](https://appium.io/) and [WebDriverIO](https://webdriver.io/) and [Jest](https://jestjs.io/). - -- [Setting up locally](#setting-up-locally) - - [(one-off) Setting up Appium](#one-off-setting-up-appium) - - [Building RNTester app](#building-rntester-app) - - [Building for iOS](#building-for-ios) - - [Building for Android](#building-for-android) - - [Setting up the RNTester E2E folder](#setting-up-the-rntester-e2e-folder) -- [Testing the RNTester app E2E](#testing-the-rntester-app-e2e) -- [Adding new tests (and project structure)](#adding-new-tests-and-project-structure) - -## Setting up locally - -### (one-off) Setting up Appium - -The first step you need to do is to ensure to install the tooling: - -```bash -npm install appium@2.0.0 -g -appium driver install uiautomator2 -appium driver install xcuitest -``` - -> More details about drivers in Appium [here](https://appium.github.io/appium/docs/en/2.0/guides/managing-exts/) and [here](https://appium.github.io/appium/docs/en/2.0/quickstart/uiauto2-driver/) - -You should not need to run install commands for drivers separately more than once, even if you bump the dep in package.json. - -### Building RNTester app - -Building manually *.app* and *.apk* is required to run automation tests on local environment. - -0. *(optional)* If you previously built RNTester, you may need to clean up build files and Pods: - - ```bash - yarn test-e2e-local-clean && yarn install - ``` - -1. Step 1: install packages for the repository, then navigate in the rn-tester folder - - ```bash - cd react-native - yarn install - cd packages/rn-tester - ``` - -Now, depending on the platform, there are some specific steps - -#### Building for iOS - -0. Make sure you have Bundler `gem install bundler` - we use it ensure installing the right version of CocoaPods locally. -1. Install Bundler and CocoaPods dependencies: `bundle install` then `bundle exec pod install` or `yarn setup-ios-hermes` for RNTester with Hermes. In order to use JSC instead of Hermes engine, run: `USE_HERMES=0 bundle exec pod install` or `setup-ios-jsc` instead. -2. You can build app with React Native CLI or manually with Xcode: - 1. To build with React Native CLI: - 1. Run `npx react-native build-ios --mode Debug --scheme RNTester --buildFolder /path/to/build-folder`, replace `/path/to/build-folder` with the real path. - 2. Copy the built app using `mv` - `mv /path/to/build-folder/Build/Products/Debug-iphonesimulator/RNTester.app ~/react-native/packages/rn-tester-e2e/apps` or manually. - 2. To build with Xcode, open the generated `RNTester.xcworkspace` and build. - 1. Find the **RNTester.app** in `~/Library/Developer/Xcode/DerivedData/RNTesterPods-{id}/Build/Products/Debug-iphonesimulator` - 2. Copy the app to the following directory `~/react-native/packages/rn-tester-e2e/apps`. -3. Change its name to: `rn-tester.app` - -#### Building for Android - -0. You'll need to have all the [prerequisites](https://reactnative.dev/contributing/how-to-build-from-source#prerequisites) (SDK, NDK) for Building React Native installed. -1. Start an Android emulator. -2. Build the app via - - ```bash - # In order to not use Hermes engine, run `yarn install-android-jsc` instead. - yarn install-android-hermes - yarn start - ``` - - *Note: Building for the first time can take a while.* - -3. Find the **app-*-debug.apk** in `~/react-native/packages/rn-tester/android/app/build/outputs/apk/hermes/debug` -4. Copy the app `app-*-debug.apk` to the following directory `~/react-native/packages/rn-tester-e2e/apps` -5. Change its name to: `rn-tester.apk` - -### Setting up the RNTester E2E folder - -In `react-native/packages/rn-tester-e2e` open the following file - -```bash -/react-native/packages/rn-tester-e2e/e2e-config.js -``` - -And modify lines L24->L39 to reflect your local setup configuration (ex. `platformVersion`, `deviceName`). Make sure to **not** commit this change if you send a PR to add tests. - -## Testing the RNTester app E2E - -After you have done all the above correctly, and you have the Android/iOS apps in the `rn-tester-e2e/apps` folder, in a dedicated terminal window, run: - -```bash -appium --base-path /wd/hub -``` - -This will start the Appium server - you will need this to keep running. - -Then open a second terminal window and start the Metro terminal from the `packages/rn-tester` folder, via `yarn start --reset-cache`. This terminal window also needs to keep running. - -Now, make sure that the iOS simulator/the Android emulator is up and running. - -Finally, you can open a third terminal window and run: - -```bash -yarn test-e2e android # for android -yarn test-e2e ios # for ios -``` - -Now you should see the RNTester app being open, and the defined test being run. - -## Adding new tests (and project structure) - -This project has 2 main folders: - -- `apps`, where, as you have seen above, the iOS/Android RNTester apps need to be put so that appium will pick them and install in the emulator/simulator consistently. - -- `tests`, where the tests and referencing files all live. The substructure is as follows: - - `screens` -> in this folder, you will find `*.screen.js` files, where each file represents a navigation screen for RNTester. So there are 3 root ones (`apis`, `bookmarks`, `components`) and then for subscreens, there's a folder with the same name - currently, that's only `components` that contains `buttonComponent.screen.js`. The content of these files is what was earlier mentioned as "references": they provide an easy way to define all elements present in said screen, so that they can be used for tests. - - `specs` -> this folder follows a similar 1:1 mapping to the RNTester screens, but for the tests: for each screen (or subscreen) there's a dedicated `*.test.js` file (such as `buttonComponentScreen.test.js`). Ideally, in this file the Jest tests are standard, leveraging the `*.screen.js` counterpart for the details of defining how Appium/WDIO can reach those elements on screen. - -When adding a new test, please ensure that you follow this pattern and add the relevant test in the right screen file / screen test file. Use the files mentioned above as examples. diff --git a/packages/rn-tester-e2e/apps/README.md b/packages/rn-tester-e2e/apps/README.md deleted file mode 100644 index ac0d4f7cf98755..00000000000000 --- a/packages/rn-tester-e2e/apps/README.md +++ /dev/null @@ -1 +0,0 @@ -Put the *.app and *.apk files here. diff --git a/packages/rn-tester-e2e/babel.config.js b/packages/rn-tester-e2e/babel.config.js deleted file mode 100644 index d37dc1e95605c5..00000000000000 --- a/packages/rn-tester-e2e/babel.config.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -module.exports = { - presets: [['@babel/preset-env', {targets: {node: 'current'}}]], - plugins: ['@babel/plugin-transform-flow-strip-types'], -}; diff --git a/packages/rn-tester-e2e/e2e-config.js b/packages/rn-tester-e2e/e2e-config.js deleted file mode 100644 index 4f488bd5200879..00000000000000 --- a/packages/rn-tester-e2e/e2e-config.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - */ - -const path = require('path'); - -type Capabilities = { - platformName: 'Android' | 'iOS', - 'appium:platformVersion': string, - 'appium:deviceName': string, - 'appium:app': string, - 'appium:automationName': 'UiAutomator2' | 'XCUITest', - 'appium:newCommandTimeout'?: number, -}; - -let capabilities: Capabilities; - -const android = { - platformName: 'Android', - 'appium:platformVersion': '14.0', - 'appium:deviceName': 'Android Emulator', - 'appium:app': path.join(process.cwd(), '/apps/rn-tester.apk'), - 'appium:automationName': 'UiAutomator2', - 'appium:newCommandTimeout': 240, -}; - -const ios = { - platformName: 'iOS', - 'appium:platformVersion': '16.4', - 'appium:deviceName': 'iPhone 14', - 'appium:automationName': 'XCUITest', - 'appium:app': path.join(process.cwd(), '/apps/rn-tester.app'), -}; - -// check that E2E_DEVICE exists, is a string and its either "ios" or "android" -if (!process.env.E2E_DEVICE) { - throw new Error('E2E_DEVICE environment variable is not defined'); -} else if (typeof process.env.E2E_DEVICE !== 'string') { - throw new Error('E2E_DEVICE environment variable is not a string'); -} else if ( - process.env.E2E_DEVICE !== 'ios' && - process.env.E2E_DEVICE !== 'android' -) { - throw new Error('E2E_DEVICE environment variable is not "ios" or "android"'); -} - -if (process.env.E2E_DEVICE === 'android') { - capabilities = android; -} - -if (process.env.E2E_DEVICE === 'ios') { - capabilities = ios; -} - -export default capabilities; diff --git a/packages/rn-tester-e2e/jest.config.js b/packages/rn-tester-e2e/jest.config.js deleted file mode 100644 index 8eedcd4d52ab55..00000000000000 --- a/packages/rn-tester-e2e/jest.config.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -module.exports = { - testTimeout: 120000, - bail: 0, - setupFilesAfterEnv: ['./jest.setup.js'], - testMatch: ['**/specs/**/*.js'], - maxWorkers: 1, - verbose: true, -}; diff --git a/packages/rn-tester-e2e/jest.setup.js b/packages/rn-tester-e2e/jest.setup.js deleted file mode 100644 index 8fe6ca699212a0..00000000000000 --- a/packages/rn-tester-e2e/jest.setup.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - */ - -import capabilities from './e2e-config.js'; -import {afterEach, beforeEach, jest} from '@jest/globals'; - -const wdio = require('webdriverio'); -jest.retryTimes(3); - -let driver: any; - -const config = { - path: '/wd/hub', - host: 'localhost', - port: 4723, - waitforTimeout: 60000, - capabilities: { - ...capabilities, - }, -}; - -beforeEach(async () => { - // $FlowFixMe - let testName: any = expect.getState().currentTestName; - console.info( - '------------------------------------------------------------ Test is starting... ------------------------------------------------------------', - ); - console.info( - '------------------------------ Test name: ' + - testName + - ' ------------------------------', - ); - driver = await wdio.remote(config); -}); - -afterEach(async () => { - await driver.deleteSession(); - console.info( - '------------------------------------------------------------ Done with testing. ------------------------------------------------------------', - ); -}); - -export {driver}; diff --git a/packages/rn-tester-e2e/package.json b/packages/rn-tester-e2e/package.json deleted file mode 100644 index 6d1dfdb3af457c..00000000000000 --- a/packages/rn-tester-e2e/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@react-native/tester-e2e", - "private": true, - "version": "0.75.0-main", - "license": "MIT", - "description": "React Native E2E tester app.", - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/rn-tester-e2e", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/facebook/react-native.git", - "directory": "packages/rn-tester-e2e" - }, - "scripts": { - "test-e2e": "node scripts/e2e/run-e2e-tests.js" - }, - "devDependencies": { - "@babel/core": "^7.20.0", - "@babel/plugin-transform-flow-strip-types": "^7.20.0", - "@babel/preset-env": "^7.20.0", - "@types/jest": "^29.5.3", - "eslint": "^8.19.0", - "jest": "^29.6.3", - "webdriverio": "^7.32.0" - } -} diff --git a/packages/rn-tester-e2e/scripts/run-e2e-tests.js b/packages/rn-tester-e2e/scripts/run-e2e-tests.js deleted file mode 100644 index 6ede19d34a3e92..00000000000000 --- a/packages/rn-tester-e2e/scripts/run-e2e-tests.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -const SUPPORTED_PLATFORMS = ['ios', 'android']; - -if (process.argv.length !== 3 || !SUPPORTED_PLATFORMS.includes(process.argv[2])) { - throw new Error(`Invalid platform. Supported platforms are: ${SUPPORTED_PLATFORMS.join(', ')}`); -} - -const platform = process.argv[2]; -const { execSync } = require('child_process'); -execSync(`E2E_DEVICE=${platform} jest --runInBand`, { stdio: 'inherit' }); diff --git a/packages/rn-tester-e2e/tests/helpers/utils.js b/packages/rn-tester-e2e/tests/helpers/utils.js deleted file mode 100644 index 33f4068f960075..00000000000000 --- a/packages/rn-tester-e2e/tests/helpers/utils.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - */ - -import {driver} from '../../jest.setup'; - -type PlatformsReference = { - ios: string, - android: string, -}; - -class Utils { - async checkElementExistence(locator: string): Promise { - await driver.$(locator).waitForDisplayed(); - return driver.$(locator).isDisplayed(); - } - - async clickElement(locator: string): Promise { - await driver.$(locator).waitForDisplayed(); - await driver.$(locator).click(); - } - - async getElementText(locator: string): Promise { - await driver.$(locator).waitForDisplayed(); - return driver.$(locator).getText(); - } - - platformSelect(platforms: PlatformsReference): string { - // if something goes wrong, we fallback to ios. But it should never happent, the process will fail way earlier. - // $FlowFixMe[invalid-computed-prop] - return platforms[process?.env?.E2E_DEVICE || 'ios']; - } - - async scrollToElement(locator: string): Promise { - let {width, height} = await driver.getWindowSize(); - let elementIsFound; - try { - elementIsFound = await driver.$(locator).isDisplayed(); - while (!elementIsFound) { - driver.touchPerform([ - { - action: 'press', - options: { - x: width / 2, - y: height / 2, - }, - }, - { - action: 'wait', - options: { - ms: 1000, - }, - }, - { - action: 'moveTo', - options: { - x: width / 2, - y: height / 10, - }, - }, - { - action: 'release', - }, - ]); - elementIsFound = await driver.$(locator).isDisplayed(); - } - } catch (err) { - console.log('Element is not found'); - } - } -} - -export const iOSLabel = (label: string): string => { - return `[label="${label}"]`; -}; - -export const iOSName = (name: string): string => { - return `[name="${name}"]`; -}; - -export const androidWidget = ( - type: string, - selector: string, - id: string, -): string => { - return `//android.widget.${type}[@${selector}="${id}"]`; -}; - -export const UtilsSingleton: Utils = new Utils(); diff --git a/packages/rn-tester-e2e/tests/screens/apis.screen.js b/packages/rn-tester-e2e/tests/screens/apis.screen.js deleted file mode 100644 index 286ecf56169512..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/apis.screen.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -// root level screen in RNTester: APIs - -class ApisScreen {} - -export const ApisScreenSingleton: ApisScreen = new ApisScreen(); diff --git a/packages/rn-tester-e2e/tests/screens/bookmarks.screen.js b/packages/rn-tester-e2e/tests/screens/bookmarks.screen.js deleted file mode 100644 index 2ff88eecbed009..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/bookmarks.screen.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -// root level screen in RNTester: Bookmarks - -class BookmarksScreen {} - -export const BookmarksScreenSingleton: BookmarksScreen = new BookmarksScreen(); diff --git a/packages/rn-tester-e2e/tests/screens/components.screen.js b/packages/rn-tester-e2e/tests/screens/components.screen.js deleted file mode 100644 index 605309ce668b59..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components.screen.js +++ /dev/null @@ -1,225 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import {UtilsSingleton as Utils, iOSLabel} from '../helpers/utils'; - -// root level screen in RNTester: Components - -const buttonComponentLabel = 'Button Simple React Native button component.'; -const activityIndicatorComponentLabel = - 'ActivityIndicator Animated loading indicators.'; -const keyboardAvoidingViewComponentLabel = - 'KeyboardAvoidingView Base component for views that automatically adjust their height or position to move out of the way of the keyboard.'; -const flatListComponentLabel = 'FlatList Performant, scrollable list of data.'; -const jsResponderHandlerComponentLabel = - 'JSResponderHandler Simple example to test JSResponderHandler.'; -const modalComponentLabel = 'Modal Component for presenting modal views.'; -const newAppScreenComponentLabel = - 'New App Screen Displays the content of the new app screen'; -const pressableComponentLabel = - 'Pressable Component for making views pressable.'; -const refreshControlComponentLabel = - 'RefreshControl Adds pull-to-refresh support to a scrollview.'; -const scrollViewSimpleExampleComponentLabel = - 'ScrollViewSimpleExample Component that enables scrolling through child components.'; - -type ComponentsScreenType = { - buttonComponentLabelElement: string, - activityIndicatorComponentLabelElement: string, - keyboardAvoidingViewComponentLabelElement: string, - flatListComponentLabelElement: string, - jsResponderHandlerComponentLabelElement: string, - modalComponentLabelElement: string, - newAppScreenComponentLabelElement: string, - pressableComponentLabelElement: string, - refreshControlComponentLabelElement: string, - scrollViewSimpleExampleComponentLabelElement: string, - checkButtonComponentIsDisplayed: () => Promise, - checkActivityIndicatorComponentIsDisplayed: () => Promise, - checkKeyboardAvoidingViewComponentIsDisplayed: () => Promise, - checkFlatListComponentIsDisplayed: () => Promise, - checkJSResponderHandlerComponentIsDisplayed: () => Promise, - checkModalComponentIsDisplayed: () => Promise, - checkNewAppScreenComponentIsDisplayed: () => Promise, - checkPressableComponentIsDisplayed: () => Promise, - checkRefreshControlComponentIsDisplayed: () => Promise, - checkScrollViewSimpleExampleComponentIsDisplayed: () => Promise, - clickButtonComponent: () => Promise, - clickActivityIndicatorComponent: () => Promise, - clickKeyboardAvoidingViewComponent: () => Promise, - clickFlatListComponent: () => Promise, - clickJSResponderHandlerComponent: () => Promise, - clickModalComponent: () => Promise, - clickNewAppScreenComponent: () => Promise, - clickPressableComponent: () => Promise, - clickRefreshControlComponent: () => Promise, - clickScrollViewSimpleExampleComponent: () => Promise, -}; - -export const ComponentsScreen: ComponentsScreenType = { - // Reference in the top level Component list - buttonComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(buttonComponentLabel), - android: `~${buttonComponentLabel}`, - }), - activityIndicatorComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(activityIndicatorComponentLabel), - android: `~${activityIndicatorComponentLabel}`, - }), - keyboardAvoidingViewComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(keyboardAvoidingViewComponentLabel), - android: `~${keyboardAvoidingViewComponentLabel}`, - }), - flatListComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(flatListComponentLabel), - android: `~${flatListComponentLabel}`, - }), - jsResponderHandlerComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(jsResponderHandlerComponentLabel), - android: `~${jsResponderHandlerComponentLabel}`, - }), - modalComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(modalComponentLabel), - android: `~${modalComponentLabel}`, - }), - newAppScreenComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(newAppScreenComponentLabel), - android: `~${newAppScreenComponentLabel}`, - }), - pressableComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(pressableComponentLabel), - android: `~${pressableComponentLabel}`, - }), - refreshControlComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(refreshControlComponentLabel), - android: `~${refreshControlComponentLabel}`, - }), - scrollViewSimpleExampleComponentLabelElement: Utils.platformSelect({ - ios: iOSLabel(scrollViewSimpleExampleComponentLabel), - android: `~${scrollViewSimpleExampleComponentLabel}`, - }), - // Methods to interact with top level elements in the list - checkButtonComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence(this.buttonComponentLabelElement); - }, - checkActivityIndicatorComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.activityIndicatorComponentLabelElement, - ); - }, - checkKeyboardAvoidingViewComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.keyboardAvoidingViewComponentLabelElement, - ); - }, - checkFlatListComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.flatListComponentLabelElement, - ); - }, - checkJSResponderHandlerComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.jsResponderHandlerComponentLabelElement, - ); - }, - checkModalComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence(this.modalComponentLabelElement); - }, - checkNewAppScreenComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.newAppScreenComponentLabelElement, - ); - }, - checkPressableComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.pressableComponentLabelElement, - ); - }, - checkRefreshControlComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.refreshControlComponentLabelElement, - ); - }, - checkScrollViewSimpleExampleComponentIsDisplayed: async function ( - this: ComponentsScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.scrollViewSimpleExampleComponentLabelElement, - ); - }, - clickButtonComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.buttonComponentLabelElement); - }, - clickActivityIndicatorComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.activityIndicatorComponentLabelElement); - }, - clickKeyboardAvoidingViewComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.keyboardAvoidingViewComponentLabelElement); - }, - clickFlatListComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.flatListComponentLabelElement); - }, - clickJSResponderHandlerComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.jsResponderHandlerComponentLabelElement); - }, - clickModalComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.modalComponentLabelElement); - }, - clickNewAppScreenComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.newAppScreenComponentLabelElement); - }, - clickPressableComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.pressableComponentLabelElement); - }, - clickRefreshControlComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.refreshControlComponentLabelElement); - }, - clickScrollViewSimpleExampleComponent: async function ( - this: ComponentsScreenType, - ): Promise { - await Utils.clickElement(this.scrollViewSimpleExampleComponentLabelElement); - }, -}; diff --git a/packages/rn-tester-e2e/tests/screens/components/activityIndicatorComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/activityIndicatorComponent.screen.js deleted file mode 100644 index b498546e340222..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/activityIndicatorComponent.screen.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSLabel, - iOSName, -} from '../../helpers/utils'; - -type ActivityIndicatorComponentScreenType = { - activityIndicatorScreenElement: string, - defaultActivityIndicatorScreenElement: string, - checkDefaultActivityIndicatorIsDisplayed: () => Promise, -}; - -const defaultActivityIndicatorTextDesc = 'Wait for content to load!'; - -export const ActivityIndicatorComponentScreen: ActivityIndicatorComponentScreenType = - { - // reference in the Components list - activityIndicatorScreenElement: Utils.platformSelect({ - ios: iOSName('ActivityIndicator'), - android: androidWidget('TextView', 'text', 'ActivityIndicator'), - }), - // References to elements within the Activity Indicator Component screen - defaultActivityIndicatorScreenElement: Utils.platformSelect({ - ios: iOSLabel(defaultActivityIndicatorTextDesc), - android: androidWidget( - 'FrameLayout', - 'content-desc', - defaultActivityIndicatorTextDesc, - ), - }), - // Methods to interact with the elements - checkDefaultActivityIndicatorIsDisplayed: async function ( - this: ActivityIndicatorComponentScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.defaultActivityIndicatorScreenElement, - ); - }, - }; diff --git a/packages/rn-tester-e2e/tests/screens/components/buttonComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/buttonComponent.screen.js deleted file mode 100644 index 5ac4975879ced8..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/buttonComponent.screen.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSLabel, -} from '../../helpers/utils'; - -type ButtonComponentScreenType = { - buttonScreenElement: string, - btnSubmitElement: string, - inputSearchElement: string, - btnOKElement: string, - btnCancelElement: string, - submitAlertBoxElement: string, - cancelAlertBoxElement: string, - checkButtonsScreenIsDisplayed: () => Promise, - clickSubmitApplication: () => Promise, - clickCancelApplication: () => Promise, - getCancelAlertText: () => Promise, - getSubmitAlertText: () => Promise, - clickOkButton: () => Promise, -}; - -export const ButtonComponentScreen: ButtonComponentScreenType = { - // reference in the Components list - buttonScreenElement: Utils.platformSelect({ - ios: iOSLabel('Button'), - android: androidWidget('ViewGroup', 'text', 'Button'), - }), - // References to elements within the Button Component screen - btnSubmitElement: Utils.platformSelect({ - ios: iOSLabel('Press to submit your application!'), - android: androidWidget('Button', 'resource-id', 'button_default_styling'), - }), - inputSearchElement: Utils.platformSelect({ - ios: iOSLabel('example_search'), - android: androidWidget('EditText', 'resource-id', 'example_search'), - }), - btnOKElement: Utils.platformSelect({ - ios: iOSLabel('OK'), - android: androidWidget('Button', 'text', 'OK'), - }), - btnCancelElement: Utils.platformSelect({ - ios: iOSLabel('Press to cancel your application!'), - android: androidWidget('Button', 'resource-id', 'cancel_button'), - }), - submitAlertBoxElement: Utils.platformSelect({ - ios: iOSLabel('Your application has been submitted!'), - android: androidWidget('TextView', 'resource-id', 'android:id/alertTitle'), - }), - cancelAlertBoxElement: Utils.platformSelect({ - ios: iOSLabel('Your application has been cancelled!'), - android: androidWidget('TextView', 'resource-id', 'android:id/alertTitle'), - }), - // Methods to interact with the elements - checkButtonsScreenIsDisplayed: async function ( - this: ButtonComponentScreenType, - ): Promise { - return await Utils.getElementText(this.buttonScreenElement); - }, - clickSubmitApplication: async function ( - this: ButtonComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnSubmitElement); - }, - clickCancelApplication: async function ( - this: ButtonComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnCancelElement); - }, - getCancelAlertText: async function ( - this: ButtonComponentScreenType, - ): Promise { - return await Utils.getElementText(this.cancelAlertBoxElement); - }, - getSubmitAlertText: async function ( - this: ButtonComponentScreenType, - ): Promise { - return await Utils.getElementText(this.submitAlertBoxElement); - }, - clickOkButton: async function ( - this: ButtonComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnOKElement); - }, -}; diff --git a/packages/rn-tester-e2e/tests/screens/components/flatListComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/flatListComponent.screen.js deleted file mode 100644 index ee2f009070303a..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/flatListComponent.screen.js +++ /dev/null @@ -1,351 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSLabel, - iOSName, -} from '../../helpers/utils'; - -type FlatListComponentScreenType = { - flatListScreenElement: string, - basicScreenElement: string, - onStartReachedScreenElement: string, - onEndReachedScreenElement: string, - contentInsetScreenElement: string, - invertedScreenElement: string, - onViewableItemsChangedScreenElement: string, - flatListWithSeparatorsScreenElement: string, - multiColumnScreenElement: string, - stickyHeadersScreenElement: string, - nestedScreenElement: string, - basicSearchBarScreenElement: string, - btnCollapseElement: string, - btnToggleTrueElement: string, - btnToggleFalseElement: string, - onStartBtnTestElement: string, - stickyPizzaElement: string, - pizzaElement: string, - iceCreamElement: string, - contentInsetMenuElement: string, - separatorElement: string, - listHeaderTextElement: string, - nestedHeaderTextElement: string, - checkFlatListBasicScreenIsDisplayed: () => Promise, - checkFlatListOnStartReachedScreenIsDisplayed: () => Promise, - checkFlatListOnEndReachedScreenIsDisplayed: () => Promise, - checkFlatListContentInsetScreenIsDisplayed: () => Promise, - checkFlatListInvertedScreenIsDisplayed: () => Promise, - checkFlatListOnViewableItemsChangedScreenIsDisplayed: () => Promise, - checkFlatListWithSeparatorsScreenIsDisplayed: () => Promise, - checkFlatListMultiColumnScreenIsDisplayed: () => Promise, - checkFlatListStickyHeadersScreenIsDisplayed: () => Promise, - checkFlatListNestedScreenIsDisplayed: () => Promise, - checkSearchBarIsDisplayed: () => Promise, - checkCollapseButtonIsDisplayed: () => Promise, - checkPizzaIsDisplayed: () => Promise, - checkIceCreamIsDisplayed: () => Promise, - checkContentInsetMenuIsDisplayed: () => Promise, - checkInvertedToggleFalseButtonIsDisplayed: () => Promise, - checkSeparatorIsDisplayed: () => Promise, - checkListHeaderIsDisplayed: () => Promise, - checkStickyPizzaIsDisplayed: () => Promise, - checkNestedHeaderIsDisplayed: () => Promise, - scrollUntilOnViewableItemsChangedIsDisplayed: () => Promise, - scrollUntilNestedIsDisplayed: () => Promise, - clickFlatListBasicButton: () => Promise, - clickFlatListOnStartButton: () => Promise, - clickFlatListOnStartTestButton: () => Promise, - clickFlatListOnEndButton: () => Promise, - clickFlatListContentInsetButton: () => Promise, - clickFlatListInvertedButton: () => Promise, - clickFlatListOnViewableItemsChangedButton: () => Promise, - clickFlatListWithSeparatorsButton: () => Promise, - clickFlatListMultiColumnButton: () => Promise, - clickFlatListStickyHeadersButton: () => Promise, - clickFlatListNestedButton: () => Promise, - clickToggleTrueButton: () => Promise, -}; -const flatListWithSeparatorsText = 'FlatList with Separators'; - -export const FlatListComponentScreen: FlatListComponentScreenType = { - // reference in the Components list - flatListScreenElement: Utils.platformSelect({ - ios: iOSName('FlatList'), - android: androidWidget('TextView', 'text', 'FlatList'), - }), - // References to elements within the FlatList Component screen - basicScreenElement: Utils.platformSelect({ - ios: iOSName('Basic'), - android: androidWidget('TextView', 'text', 'Basic'), - }), - onStartReachedScreenElement: Utils.platformSelect({ - ios: iOSName('onStartReached'), - android: androidWidget('TextView', 'text', 'onStartReached'), - }), - onEndReachedScreenElement: Utils.platformSelect({ - ios: iOSName('onEndReached'), - android: androidWidget('TextView', 'text', 'onEndReached'), - }), - contentInsetScreenElement: Utils.platformSelect({ - ios: iOSName('Content Inset'), - android: androidWidget('TextView', 'text', 'Content Inset'), - }), - invertedScreenElement: Utils.platformSelect({ - ios: iOSName('Inverted'), - android: androidWidget('TextView', 'text', 'Inverted'), - }), - onViewableItemsChangedScreenElement: Utils.platformSelect({ - ios: iOSName('onViewableItemsChanged'), - android: androidWidget('TextView', 'text', 'onViewableItemsChanged'), - }), - flatListWithSeparatorsScreenElement: Utils.platformSelect({ - ios: iOSName(flatListWithSeparatorsText), - android: androidWidget('TextView', 'text', flatListWithSeparatorsText), - }), - multiColumnScreenElement: Utils.platformSelect({ - ios: iOSName('MultiColumn'), - android: androidWidget('TextView', 'text', 'MultiColumn'), - }), - stickyHeadersScreenElement: Utils.platformSelect({ - ios: iOSName('Sticky Headers'), - android: androidWidget('TextView', 'text', 'Sticky Headers'), - }), - nestedScreenElement: Utils.platformSelect({ - ios: iOSName('Nested'), - android: androidWidget('TextView', 'text', 'Nested'), - }), - btnCollapseElement: Utils.platformSelect({ - ios: iOSLabel('Collapse'), - android: androidWidget('Button', 'content-desc', 'COLLAPSE'), - }), - btnToggleTrueElement: Utils.platformSelect({ - ios: iOSLabel('Toggle true'), - android: androidWidget('Button', 'content-desc', 'TOGGLE TRUE'), - }), - btnToggleFalseElement: Utils.platformSelect({ - ios: iOSLabel('Toggle false'), - android: androidWidget('Button', 'content-desc', 'TOGGLE FALSE'), - }), - basicSearchBarScreenElement: Utils.platformSelect({ - ios: iOSName('search_bar_flat_list'), - android: androidWidget('EditText', 'resource-id', 'search_bar_flat_list'), - }), - onStartBtnTestElement: Utils.platformSelect({ - ios: iOSName('start_test'), - android: androidWidget('Button', 'resource-id', 'start_test'), - }), - pizzaElement: Utils.platformSelect({ - ios: iOSLabel('Pizza'), - android: androidWidget('TextView', 'text', 'Pizza'), - }), - iceCreamElement: Utils.platformSelect({ - ios: iOSLabel('Ice Cream'), - android: androidWidget('TextView', 'text', 'Ice Cream'), - }), - contentInsetMenuElement: Utils.platformSelect({ - ios: iOSLabel('Menu'), - android: androidWidget('TextView', 'text', 'Menu'), - }), - separatorElement: Utils.platformSelect({ - ios: iOSName('flat_list_separator'), - android: androidWidget('TextView', 'resource-id', 'flat_list_separator'), - }), - listHeaderTextElement: Utils.platformSelect({ - ios: iOSName('LIST HEADER'), - android: androidWidget('TextView', 'text', 'LIST HEADER'), - }), - stickyPizzaElement: Utils.platformSelect({ - ios: iOSName('Sticky Pizza'), - android: androidWidget('TextView', 'text', 'Sticky Pizza'), - }), - nestedHeaderTextElement: Utils.platformSelect({ - ios: iOSName('Header'), - android: androidWidget('TextView', 'text', 'Header'), - }), - // Methods to interact with the FlatList elements - checkSearchBarIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.basicSearchBarScreenElement); - }, - checkCollapseButtonIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.btnCollapseElement); - }, - checkFlatListBasicScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.basicScreenElement); - }, - checkFlatListOnStartReachedScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.onStartReachedScreenElement); - }, - checkFlatListOnEndReachedScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.onEndReachedScreenElement); - }, - checkPizzaIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.pizzaElement); - }, - checkIceCreamIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.iceCreamElement); - }, - checkFlatListContentInsetScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.contentInsetScreenElement); - }, - checkFlatListInvertedScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.invertedScreenElement); - }, - checkFlatListOnViewableItemsChangedScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.onViewableItemsChangedScreenElement, - ); - }, - checkFlatListWithSeparatorsScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.flatListWithSeparatorsScreenElement, - ); - }, - checkFlatListMultiColumnScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.multiColumnScreenElement); - }, - checkFlatListStickyHeadersScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.stickyHeadersScreenElement); - }, - checkFlatListNestedScreenIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.nestedScreenElement); - }, - checkListHeaderIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.listHeaderTextElement); - }, - checkContentInsetMenuIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.contentInsetMenuElement); - }, - checkInvertedToggleFalseButtonIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.btnToggleFalseElement); - }, - checkSeparatorIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.separatorElement); - }, - checkStickyPizzaIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.stickyPizzaElement); - }, - checkNestedHeaderIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.nestedHeaderTextElement); - }, - scrollUntilOnViewableItemsChangedIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.scrollToElement( - this.onViewableItemsChangedScreenElement, - ); - }, - scrollUntilNestedIsDisplayed: async function ( - this: FlatListComponentScreenType, - ): Promise { - return await Utils.scrollToElement(this.nestedScreenElement); - }, - clickFlatListBasicButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.basicScreenElement); - }, - clickFlatListOnStartButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.onStartReachedScreenElement); - }, - clickFlatListOnStartTestButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.onStartBtnTestElement); - }, - clickFlatListOnEndButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.onEndReachedScreenElement); - }, - clickFlatListContentInsetButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.contentInsetScreenElement); - }, - clickFlatListInvertedButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.invertedScreenElement); - }, - clickFlatListOnViewableItemsChangedButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.onViewableItemsChangedScreenElement); - }, - clickFlatListWithSeparatorsButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.flatListWithSeparatorsScreenElement); - }, - clickFlatListMultiColumnButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.multiColumnScreenElement); - }, - clickFlatListStickyHeadersButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.stickyHeadersScreenElement); - }, - clickFlatListNestedButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.nestedScreenElement); - }, - clickToggleTrueButton: async function ( - this: FlatListComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnToggleTrueElement); - }, -}; diff --git a/packages/rn-tester-e2e/tests/screens/components/jsResponderHandlerComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/jsResponderHandlerComponent.screen.js deleted file mode 100644 index c711313deb7544..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/jsResponderHandlerComponent.screen.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSName, -} from '../../helpers/utils'; - -type JSResponderHandlerComponentScreenType = { - jsResponderHandlerScreenElement: string, - rowZeroScreenElement: string, - scrollUntilJSResponderHandlerComponentIsDisplayed: () => Promise, - checkRowZeroLabelIsDisplayed: () => Promise, - getRowZeroText: () => Promise, -}; - -export const JSResponderHandlerComponentScreen: JSResponderHandlerComponentScreenType = - { - // reference in the Components list - jsResponderHandlerScreenElement: Utils.platformSelect({ - ios: iOSName('JSResponderHandler'), - android: androidWidget('TextView', 'text', 'JSResponderHandler'), - }), - // References to elements within the js responder handler Component screen - rowZeroScreenElement: Utils.platformSelect({ - ios: iOSName('row_js_responder_handler'), - android: androidWidget( - 'TextView', - 'resource-id', - 'row_js_responder_handler', - ), - }), - // Methods to interact with the elements - scrollUntilJSResponderHandlerComponentIsDisplayed: async function ( - this: JSResponderHandlerComponentScreenType, - ): Promise { - return await Utils.scrollToElement(this.jsResponderHandlerScreenElement); - }, - checkRowZeroLabelIsDisplayed: async function ( - this: JSResponderHandlerComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.rowZeroScreenElement); - }, - getRowZeroText: async function ( - this: JSResponderHandlerComponentScreenType, - ): Promise { - return await Utils.getElementText(this.rowZeroScreenElement); - }, - }; diff --git a/packages/rn-tester-e2e/tests/screens/components/keyboardAvoidingViewComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/keyboardAvoidingViewComponent.screen.js deleted file mode 100644 index 098611db51e3fd..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/keyboardAvoidingViewComponent.screen.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSLabel, - iOSName, -} from '../../helpers/utils'; - -type KeyboardAvoidingViewComponentScreenType = { - keyboardAvoidingViewScreenElement: string, - btnDifferentBehaviorsOpenExampleElement: string, - btnRegisterElement: string, - registerAlertBoxElement: string, - btnOKElement: string, - scrollUntilKeyboardAvoidingViewComponentIsDisplayed: () => Promise, - checkBtnDifferentBehaviorsOpenExampleIsDisplayed: () => Promise, - checkBtnRegisterIsDisplayed: () => Promise, - clickDifferentBehaviorsOpenExampleButton: () => Promise, - clickRegisterButton: () => Promise, - clickOkButton: () => Promise, - getRegisterAlertText: () => Promise, -}; - -export const KeyboardAvoidingViewComponentScreen: KeyboardAvoidingViewComponentScreenType = - { - // reference in the Components list - keyboardAvoidingViewScreenElement: Utils.platformSelect({ - ios: iOSName('KeyboardAvoidingView'), - android: androidWidget('TextView', 'text', 'KeyboardAvoidingView'), - }), - // References to elements within the KeyboardAvoidingVIew Component screen - btnDifferentBehaviorsOpenExampleElement: Utils.platformSelect({ - ios: iOSName('keyboard_avoiding_view_behaviors_open'), - android: androidWidget( - 'TextView', - 'resource-id', - 'keyboard_avoiding_view_behaviors_open', - ), - }), - btnRegisterElement: Utils.platformSelect({ - ios: iOSName('register_button'), - android: androidWidget('Button', 'resource-id', 'register_button'), - }), - registerAlertBoxElement: Utils.platformSelect({ - ios: iOSLabel('Successfully Registered!'), - android: androidWidget( - 'TextView', - 'resource-id', - 'android:id/alertTitle', - ), - }), - btnOKElement: Utils.platformSelect({ - ios: iOSLabel('OK'), - android: androidWidget('Button', 'text', 'OK'), - }), - // Methods to interact with the elements - scrollUntilKeyboardAvoidingViewComponentIsDisplayed: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - return await Utils.scrollToElement( - this.keyboardAvoidingViewScreenElement, - ); - }, - checkBtnDifferentBehaviorsOpenExampleIsDisplayed: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.btnDifferentBehaviorsOpenExampleElement, - ); - }, - checkBtnRegisterIsDisplayed: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.btnRegisterElement); - }, - clickDifferentBehaviorsOpenExampleButton: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnDifferentBehaviorsOpenExampleElement); - }, - clickRegisterButton: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnRegisterElement); - }, - clickOkButton: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnOKElement); - }, - getRegisterAlertText: async function ( - this: KeyboardAvoidingViewComponentScreenType, - ): Promise { - return await Utils.getElementText(this.registerAlertBoxElement); - }, - }; diff --git a/packages/rn-tester-e2e/tests/screens/components/modalComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/modalComponent.screen.js deleted file mode 100644 index 88e58361b35de8..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/modalComponent.screen.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSName, -} from '../../helpers/utils'; - -type ModalComponentScreenType = { - modalScreenElement: string, - btnShowModalElement: string, - modalAnimationTypeTextElement: string, - modalModeTextElement: string, - btnCloseElement: string, - checkShowModalIsDisplayed: () => Promise, - checkModalAnimationTypeIsDisplayed: () => Promise, - scrollUntilModalComponentIsDisplayed: () => Promise, - clickShowModalButton: () => Promise, - clickCloseButton: () => Promise, -}; - -const showModalBtnText = 'Show Modal'; - -export const ModalComponentScreen: ModalComponentScreenType = { - // reference in the Components list - modalScreenElement: Utils.platformSelect({ - ios: iOSName('Modal'), - android: androidWidget('TextView', 'text', 'Modal'), - }), - // References to elements within the Modal Component screen - btnShowModalElement: Utils.platformSelect({ - ios: iOSName(showModalBtnText), - android: androidWidget('TextView', 'text', showModalBtnText), - }), - modalAnimationTypeTextElement: Utils.platformSelect({ - ios: iOSName('modal_animationType_text'), - android: androidWidget( - 'TextView', - 'resource-id', - 'modal_animationType_text', - ), - }), - modalModeTextElement: Utils.platformSelect({ - ios: iOSName('modal_animationType_text'), - android: androidWidget( - 'TextView', - 'resource-id', - 'row_js_responder_handler', - ), - }), - btnCloseElement: Utils.platformSelect({ - ios: iOSName('Close'), - android: androidWidget('TextView', 'text', 'Close'), - }), - // Methods to interact with the elements - checkShowModalIsDisplayed: async function ( - this: ModalComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.btnShowModalElement); - }, - checkModalAnimationTypeIsDisplayed: async function ( - this: ModalComponentScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.modalAnimationTypeTextElement, - ); - }, - scrollUntilModalComponentIsDisplayed: async function ( - this: ModalComponentScreenType, - ): Promise { - return await Utils.scrollToElement(this.modalScreenElement); - }, - clickShowModalButton: async function ( - this: ModalComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnShowModalElement); - }, - clickCloseButton: async function ( - this: ModalComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnCloseElement); - }, -}; diff --git a/packages/rn-tester-e2e/tests/screens/components/newAppComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/newAppComponent.screen.js deleted file mode 100644 index 705544b970499a..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/newAppComponent.screen.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSName, -} from '../../helpers/utils'; - -type NewAppComponentScreenType = { - newAppScreenElement: string, - newAppHeaderScreenElement: string, - scrollUntilNewAppHeaderComponentIsDisplayed: () => Promise, - checkNewAppHeaderIsDisplayed: () => Promise, -}; - -const newAppScreenText = 'New App Screen'; -const newAppScreenHeaderText = 'New App Screen Header'; - -export const NewAppComponentScreen: NewAppComponentScreenType = { - // reference in the Components list - newAppScreenElement: Utils.platformSelect({ - ios: iOSName(newAppScreenText), - android: androidWidget('TextView', 'text', newAppScreenText), - }), - // References to elements within the New App Component screenS - newAppHeaderScreenElement: Utils.platformSelect({ - ios: iOSName(newAppScreenHeaderText), - android: androidWidget('TextView', 'text', newAppScreenHeaderText), - }), - // Methods to interact with the elements - scrollUntilNewAppHeaderComponentIsDisplayed: async function ( - this: NewAppComponentScreenType, - ): Promise { - return await Utils.scrollToElement(this.newAppScreenElement); - }, - checkNewAppHeaderIsDisplayed: async function ( - this: NewAppComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.newAppHeaderScreenElement); - }, -}; diff --git a/packages/rn-tester-e2e/tests/screens/components/pressableComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/pressableComponent.screen.js deleted file mode 100644 index b79b899750ef01..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/pressableComponent.screen.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSName, -} from '../../helpers/utils'; - -type PressableComponentScreenType = { - pressableScreenElement: string, - pressMeHeaderElement: string, - btnPressMeElement: string, - onPressText: string, - checkPressMeHeaderIsDisplayed: () => Promise, - checkOnPressIsDisplayed: () => Promise, - scrollUntilPressableComponentIsDisplayed: () => Promise, - clickPressMeButton: () => Promise, - getOnPressText: () => Promise, -}; - -const pressMeHeaderText = 'Change content based on Press'; - -export const PressableComponentScreen: PressableComponentScreenType = { - // reference in the Components list - pressableScreenElement: Utils.platformSelect({ - ios: iOSName('Pressable'), - android: androidWidget('TextView', 'text', 'Pressable'), - }), - // References to elements within the Pressable Component screen - pressMeHeaderElement: Utils.platformSelect({ - ios: iOSName(pressMeHeaderText), - android: androidWidget('TextView', 'text', pressMeHeaderText), - }), - btnPressMeElement: Utils.platformSelect({ - ios: iOSName('one_press_me_button'), - android: androidWidget('TextView', 'resource-id', 'one_press_me_button'), - }), - onPressText: Utils.platformSelect({ - ios: iOSName('pressable_press_console'), - android: androidWidget( - 'TextView', - 'resource-id', - 'pressable_press_console', - ), - }), - // Methods to interact with the elements - checkPressMeHeaderIsDisplayed: async function ( - this: PressableComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.pressMeHeaderElement); - }, - checkOnPressIsDisplayed: async function ( - this: PressableComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.onPressText); - }, - scrollUntilPressableComponentIsDisplayed: async function ( - this: PressableComponentScreenType, - ): Promise { - return await Utils.scrollToElement(this.pressableScreenElement); - }, - clickPressMeButton: async function ( - this: PressableComponentScreenType, - ): Promise { - await Utils.clickElement(this.btnPressMeElement); - }, - getOnPressText: async function ( - this: PressableComponentScreenType, - ): Promise { - return await Utils.getElementText(this.onPressText); - }, -}; diff --git a/packages/rn-tester-e2e/tests/screens/components/refreshControlComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/refreshControlComponent.screen.js deleted file mode 100644 index c9966f318d3578..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/refreshControlComponent.screen.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSName, -} from '../../helpers/utils'; - -type RefreshControlComponentScreenType = { - refreshControlScreenElement: string, - initialRowScreenElement: string, - checkInitialRowIsDisplayed: () => Promise, - scrollUntilRefreshControlComponentIsDisplayed: () => Promise, -}; - -export const RefreshControlComponentScreen: RefreshControlComponentScreenType = - { - // reference in the Components list - refreshControlScreenElement: Utils.platformSelect({ - ios: iOSName('RefreshControl'), - android: androidWidget('TextView', 'text', 'RefreshControl'), - }), - // References to elements within the RefreshControl Component screen - initialRowScreenElement: Utils.platformSelect({ - ios: iOSName('refresh_control_row'), - android: androidWidget('TextView', 'resource-id', 'refresh_control_row'), - }), - // Methods to interact with the elements - checkInitialRowIsDisplayed: async function ( - this: RefreshControlComponentScreenType, - ): Promise { - return await Utils.checkElementExistence(this.initialRowScreenElement); - }, - scrollUntilRefreshControlComponentIsDisplayed: async function ( - this: RefreshControlComponentScreenType, - ): Promise { - return await Utils.scrollToElement(this.refreshControlScreenElement); - }, - }; diff --git a/packages/rn-tester-e2e/tests/screens/components/scrollViewSimpleExampleComponent.screen.js b/packages/rn-tester-e2e/tests/screens/components/scrollViewSimpleExampleComponent.screen.js deleted file mode 100644 index 6a3d53c694fd38..00000000000000 --- a/packages/rn-tester-e2e/tests/screens/components/scrollViewSimpleExampleComponent.screen.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import { - UtilsSingleton as Utils, - androidWidget, - iOSName, -} from '../../helpers/utils'; - -type ScrollViewSimpleExampleComponentScreenType = { - scrollViewSimpleExampleScreenElement: string, - scrollViewItemScreenElement: string, - checkScrollViewItemsDisplayed: () => Promise, - scrollUntilScrollViewSimpleExampleComponentIsDisplayed: () => Promise, -}; - -export const ScrollViewSimpleExampleComponentScreen: ScrollViewSimpleExampleComponentScreenType = - { - // reference in the Components list - scrollViewSimpleExampleScreenElement: Utils.platformSelect({ - ios: iOSName('ScrollViewSimpleExample'), - android: androidWidget('TextView', 'text', 'ScrollViewSimpleExample'), - }), - // References to elements within the ScrollViewSimpleExample Component screen - scrollViewItemScreenElement: Utils.platformSelect({ - ios: iOSName('scroll_view_item'), - android: androidWidget('TextView', 'resource-id', 'scroll_view_item'), - }), - // Methods to interact with the elements - checkScrollViewItemsDisplayed: async function ( - this: ScrollViewSimpleExampleComponentScreenType, - ): Promise { - return await Utils.checkElementExistence( - this.scrollViewItemScreenElement, - ); - }, - scrollUntilScrollViewSimpleExampleComponentIsDisplayed: async function ( - this: ScrollViewSimpleExampleComponentScreenType, - ): Promise { - return await Utils.scrollToElement( - this.scrollViewSimpleExampleScreenElement, - ); - }, - }; diff --git a/packages/rn-tester-e2e/tests/specs/components/activityIndicatorComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/activityIndicatorComponentScreen.test.js deleted file mode 100644 index de72af96c86fa4..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/activityIndicatorComponentScreen.test.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - ActivityIndicatorComponentScreen, -} = require('../../screens/components/activityIndicatorComponent.screen.js'); - -describe('Test is checking default activity indicator component', () => { - test('Should view properly default progress bar', async () => { - expect( - await ComponentsScreen.checkActivityIndicatorComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickActivityIndicatorComponent(); - expect( - await ActivityIndicatorComponentScreen.checkDefaultActivityIndicatorIsDisplayed(), - ).toBeTruthy(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/buttonComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/buttonComponentScreen.test.js deleted file mode 100644 index f75364d06f8572..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/buttonComponentScreen.test.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - ButtonComponentScreen, -} = require('../../screens/components/buttonComponent.screen.js'); - -// fixed variables -const submitText = 'Your application has been submitted!'; -const cancelText = 'Your application has been cancelled!'; - -describe('Test is checking submit button', () => { - test('Should view properly submit alert text', async () => { - expect( - await ComponentsScreen.checkButtonComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickButtonComponent(); - await ButtonComponentScreen.clickSubmitApplication(); - expect(await ButtonComponentScreen.getSubmitAlertText()).toContain( - submitText, - ); - await ButtonComponentScreen.clickOkButton(); - }); -}); - -describe('Test is checking cancel button', () => { - test('Should view properly submit cancel text', async () => { - expect( - await ComponentsScreen.checkButtonComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickButtonComponent(); - await ButtonComponentScreen.clickCancelApplication(); - expect(await ButtonComponentScreen.getCancelAlertText()).toContain( - cancelText, - ); - await ButtonComponentScreen.clickOkButton(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/flatListComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/flatListComponentScreen.test.js deleted file mode 100644 index 3c7eb202b1eb63..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/flatListComponentScreen.test.js +++ /dev/null @@ -1,187 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - FlatListComponentScreen, -} = require('../../screens/components/flatListComponent.screen.js'); - -describe('Test is checking basic flat list', () => { - test('Should view properly search bar of basic flat list', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - expect( - await FlatListComponentScreen.checkFlatListBasicScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListBasicButton(); - expect( - await FlatListComponentScreen.checkSearchBarIsDisplayed(), - ).toBeTruthy(); - }); -}); - -describe('Test is checking onStartReached flat list', () => { - test('Should view properly first element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - expect( - await FlatListComponentScreen.checkFlatListOnStartReachedScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListOnStartButton(); - expect( - await FlatListComponentScreen.checkCollapseButtonIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListOnStartTestButton(); - expect(await FlatListComponentScreen.checkPizzaIsDisplayed()).toBeTruthy(); - }); -}); - -describe('Test is checking onEndReached flat list', () => { - test('Should view properly the last element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - expect( - await FlatListComponentScreen.checkFlatListOnEndReachedScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListOnEndButton(); - expect( - await FlatListComponentScreen.checkCollapseButtonIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListOnStartTestButton(); - expect( - await FlatListComponentScreen.checkIceCreamIsDisplayed(), - ).toBeTruthy(); - }); -}); - -describe('Test is checking content inset flat list', () => { - test('Should view properly the menu element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - expect( - await FlatListComponentScreen.checkFlatListContentInsetScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListContentInsetButton(); - expect( - await FlatListComponentScreen.checkCollapseButtonIsDisplayed(), - ).toBeTruthy(); - expect( - await FlatListComponentScreen.checkContentInsetMenuIsDisplayed(), - ).toBeTruthy(); - }); -}); - -describe('Test is checking inverted flat list', () => { - test('Should view properly the menu element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - await FlatListComponentScreen.scrollUntilOnViewableItemsChangedIsDisplayed(); - expect( - await FlatListComponentScreen.checkFlatListInvertedScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListInvertedButton(); - expect(await FlatListComponentScreen.checkPizzaIsDisplayed()).toBeTruthy(); - await FlatListComponentScreen.clickToggleTrueButton(); - expect(await FlatListComponentScreen.checkPizzaIsDisplayed()).toBeTruthy(); - }); -}); - -describe('Test is checking onViewableItemsChanges component', () => { - test('Should view properly the pizza element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - await FlatListComponentScreen.scrollUntilOnViewableItemsChangedIsDisplayed(); - expect( - await FlatListComponentScreen.checkFlatListOnViewableItemsChangedScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListOnViewableItemsChangedButton(); - expect(await FlatListComponentScreen.checkPizzaIsDisplayed()).toBeTruthy(); - }); -}); - -describe('Test is checking FlatList with Separators component', () => { - test('Should view properly the separator element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - await FlatListComponentScreen.scrollUntilNestedIsDisplayed(); - expect( - await FlatListComponentScreen.checkFlatListWithSeparatorsScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListWithSeparatorsButton(); - expect( - await FlatListComponentScreen.checkSeparatorIsDisplayed(), - ).toBeTruthy(); - }); -}); - -describe('Test is checking multicolumn component', () => { - test('Should view properly the list header element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - await FlatListComponentScreen.scrollUntilNestedIsDisplayed(); - expect( - await FlatListComponentScreen.checkFlatListMultiColumnScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListMultiColumnButton(); - expect( - await FlatListComponentScreen.checkListHeaderIsDisplayed(), - ).toBeTruthy(); - }); -}); - -describe('Test is checking sticky headers component', () => { - test('Should view properly the sticky pizza element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - await FlatListComponentScreen.scrollUntilNestedIsDisplayed(); - expect( - await FlatListComponentScreen.checkFlatListStickyHeadersScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListStickyHeadersButton(); - expect( - await FlatListComponentScreen.checkStickyPizzaIsDisplayed(), - ).toBeTruthy(); - }); -}); - -describe('Test is checking nested component', () => { - test('Should view properly the nested header element', async () => { - expect( - await ComponentsScreen.checkFlatListComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickFlatListComponent(); - await FlatListComponentScreen.scrollUntilNestedIsDisplayed(); - expect( - await FlatListComponentScreen.checkFlatListNestedScreenIsDisplayed(), - ).toBeTruthy(); - await FlatListComponentScreen.clickFlatListNestedButton(); - expect( - await FlatListComponentScreen.checkNestedHeaderIsDisplayed(), - ).toBeTruthy(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/jsResponderHandlerComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/jsResponderHandlerComponentScreen.test.js deleted file mode 100644 index fc18395a8a1660..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/jsResponderHandlerComponentScreen.test.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - JSResponderHandlerComponentScreen, -} = require('../../screens/components/jsResponderHandlerComponent.screen.js'); - -// fixed variables -const roweZeroText = 'I am row 0'; - -describe('Test is checking row zero JSResponderHandler component', () => { - test('Should view properly row zero element', async () => { - await JSResponderHandlerComponentScreen.scrollUntilJSResponderHandlerComponentIsDisplayed(); - expect( - await ComponentsScreen.checkJSResponderHandlerComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickJSResponderHandlerComponent(); - expect( - await JSResponderHandlerComponentScreen.checkRowZeroLabelIsDisplayed(), - ).toBeTruthy(); - expect(await JSResponderHandlerComponentScreen.getRowZeroText()).toContain( - roweZeroText, - ); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/keyboardAvoidingViewComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/keyboardAvoidingViewComponentScreen.test.js deleted file mode 100644 index 6e22586298dd57..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/keyboardAvoidingViewComponentScreen.test.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - KeyboardAvoidingViewComponentScreen, -} = require('../../screens/components/keyboardAvoidingViewComponent.screen.js'); - -// fixed variables -const registerText = 'Successfully Registered!'; - -describe('Test is checking keyboardAvoidingView component', () => { - test('Should view properly successfully registered text', async () => { - await KeyboardAvoidingViewComponentScreen.scrollUntilKeyboardAvoidingViewComponentIsDisplayed(); - expect( - await ComponentsScreen.checkKeyboardAvoidingViewComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickKeyboardAvoidingViewComponent(); - expect( - await KeyboardAvoidingViewComponentScreen.checkBtnDifferentBehaviorsOpenExampleIsDisplayed(), - ).toBeTruthy(); - await KeyboardAvoidingViewComponentScreen.clickDifferentBehaviorsOpenExampleButton(); - expect( - await KeyboardAvoidingViewComponentScreen.checkBtnRegisterIsDisplayed(), - ).toBeTruthy(); - await KeyboardAvoidingViewComponentScreen.clickRegisterButton(); - expect( - await KeyboardAvoidingViewComponentScreen.getRegisterAlertText(), - ).toContain(registerText); - await KeyboardAvoidingViewComponentScreen.clickOkButton(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/modalComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/modalComponentScreen.test.js deleted file mode 100644 index 96d387b9a52048..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/modalComponentScreen.test.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - ModalComponentScreen, -} = require('../../screens/components/modalComponent.screen.js'); - -describe('Test is checking modal component', () => { - test('Should view show modal element', async () => { - await ModalComponentScreen.scrollUntilModalComponentIsDisplayed(); - expect( - await ComponentsScreen.checkModalComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickModalComponent(); - expect(await ModalComponentScreen.checkShowModalIsDisplayed()).toBeTruthy(); - await ModalComponentScreen.clickShowModalButton(); - expect( - await ModalComponentScreen.checkModalAnimationTypeIsDisplayed(), - ).toBeTruthy(); - await ModalComponentScreen.clickCloseButton(); - expect(await ModalComponentScreen.checkShowModalIsDisplayed()).toBeTruthy(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/newAppComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/newAppComponentScreen.test.js deleted file mode 100644 index 6eb6976e870bf3..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/newAppComponentScreen.test.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - NewAppComponentScreen, -} = require('../../screens/components/newAppComponent.screen.js'); - -describe('Test is checking new app screen component', () => { - test('Should view new app header element', async () => { - await NewAppComponentScreen.scrollUntilNewAppHeaderComponentIsDisplayed(); - expect( - await ComponentsScreen.checkNewAppScreenComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickNewAppScreenComponent(); - expect( - await NewAppComponentScreen.checkNewAppHeaderIsDisplayed(), - ).toBeTruthy(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/pressableComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/pressableComponentScreen.test.js deleted file mode 100644 index 5b5c930c6ac40e..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/pressableComponentScreen.test.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - PressableComponentScreen, -} = require('../../screens/components/pressableComponent.screen.js'); - -// fixed variables -const onPressText = 'onPress'; - -describe('Test is checking pressable component', () => { - test('Should view onPress text', async () => { - await PressableComponentScreen.scrollUntilPressableComponentIsDisplayed(); - expect( - await ComponentsScreen.checkPressableComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickPressableComponent(); - expect( - await PressableComponentScreen.checkPressMeHeaderIsDisplayed(), - ).toBeTruthy(); - await PressableComponentScreen.clickPressMeButton(); - expect( - await PressableComponentScreen.checkOnPressIsDisplayed(), - ).toBeTruthy(); - expect(await PressableComponentScreen.getOnPressText()).toContain( - onPressText, - ); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/refreshControlComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/refreshControlComponentScreen.test.js deleted file mode 100644 index 61cd4c003f0793..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/refreshControlComponentScreen.test.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - RefreshControlComponentScreen, -} = require('../../screens/components/refreshControlComponent.screen.js'); - -describe('Test is checking RefreshControl component', () => { - test('Should view initial row element', async () => { - await RefreshControlComponentScreen.scrollUntilRefreshControlComponentIsDisplayed(); - expect( - await ComponentsScreen.checkRefreshControlComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickRefreshControlComponent(); - expect( - await RefreshControlComponentScreen.checkInitialRowIsDisplayed(), - ).toBeTruthy(); - }); -}); diff --git a/packages/rn-tester-e2e/tests/specs/components/scrollViewSimpleExampleComponentScreen.test.js b/packages/rn-tester-e2e/tests/specs/components/scrollViewSimpleExampleComponentScreen.test.js deleted file mode 100644 index 0a0114803144b1..00000000000000 --- a/packages/rn-tester-e2e/tests/specs/components/scrollViewSimpleExampleComponentScreen.test.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -const {ComponentsScreen} = require('../../screens/components.screen.js'); -const { - ScrollViewSimpleExampleComponentScreen, -} = require('../../screens/components/scrollViewSimpleExampleComponent.screen.js'); - -describe('Test is checking ScrollVIewSimpleExample component', () => { - test('Should view scroll view item element', async () => { - await ScrollViewSimpleExampleComponentScreen.scrollUntilScrollViewSimpleExampleComponentIsDisplayed(); - expect( - await ComponentsScreen.checkScrollViewSimpleExampleComponentIsDisplayed(), - ).toBeTruthy(); - await ComponentsScreen.clickScrollViewSimpleExampleComponent(); - expect( - await ScrollViewSimpleExampleComponentScreen.checkScrollViewItemsDisplayed(), - ).toBeTruthy(); - }); -}); diff --git a/scripts/android-e2e-test.js b/scripts/android-e2e-test.js deleted file mode 100644 index 6af641d56cee2d..00000000000000 --- a/scripts/android-e2e-test.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -// Used in run-ci-e2e-test.js and executed in Circle CI. -// -// E2e test that verifies that init app can be installed, compiled, started and -// Hot Module reloading and Chrome debugging work. -// -// For other examples of appium refer to: -// https://github.com/appium/sample-code/tree/master/sample-code/examples/node and -// https://www.npmjs.com/package/wd-android -// -// To set up: -// - npm install --save-dev appium@1.11.1 mocha@2.4.5 wd@1.11.1 colors@1.0.3 pretty-data2@0.40.1 -// - cp -// - keytool -genkey -v -keystore android/app/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US" -// -// To run this test: -// - npm start -// - node node_modules/.bin/appium -// - (cd android && ./gradlew :app:copyDownloadableDepsToLibs) -// - react-native run-android -// - node ../node_modules/.bin/_mocha ../android-e2e-test.js - -/* eslint-env mocha */ - -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const pd = require('pretty-data2').pd; -const wd = require('wd'); - -// value in ms to print out screen contents, set this value in CI to debug if tests are failing -const appiumDebugInterval = process.env.APPIUM_DEBUG_INTERVAL; - -describe('Android Test App', function () { - this.timeout(600000); - let driver; - let debugIntervalId; - - before(function () { - driver = wd.promiseChainRemote({ - host: 'localhost', - port: 4723, - }); - driver.on('status', function (info) { - console.log(info.cyan); - }); - driver.on('command', function (method, command, data) { - if (command === 'source()' && data) { - console.log( - ' > ' + method.yellow, - 'Screen contents'.grey, - '\n', - pd.xml(data).yellow, - ); - } else { - console.log(' > ' + method.yellow, command.grey, data || ''); - } - }); - driver.on('http', function (method, urlPath, data) { - console.log(' > ' + method.magenta, urlPath, (data || '').grey); - }); - - // every interval print what is on the screen - if (appiumDebugInterval) { - debugIntervalId = setInterval(() => { - // it driver.on('command') will log the screen contents - driver.source(); - }, appiumDebugInterval); - } - - const desired = { - platformName: 'Android', - deviceName: 'Android Emulator', - app: path.resolve('android/app/build/outputs/apk/debug/app-debug.apk'), - }; - - // React Native in dev mode often starts with Red Box "Can't fibd variable __fbBatchedBridge..." - // This is fixed by clicking Reload JS which will trigger a request to Metro - return driver - .init(desired) - .setImplicitWaitTimeout(5000) - .waitForElementByXPath('//android.widget.Button[@text="Reload JS"]') - .then( - elem => { - elem.click(); - driver.sleep(2000); - }, - // eslint-disable-next-line handle-callback-err - err => { - // ignoring if Reload JS button can't be located - }, - ); - }); - - after(function () { - if (debugIntervalId) { - clearInterval(debugIntervalId); - } - return driver.quit(); - }); - - it('should display new content after a refresh', function () { - const androidAppCode = fs.readFileSync('App.js', 'utf-8'); - let intervalToUpdate; - return ( - driver - .waitForElementByXPath( - '//android.widget.TextView[starts-with(@text, "Welcome to React")]', - ) - .then(() => { - fs.writeFileSync( - 'App.js', - androidAppCode.replace('Step One', 'Step 1'), - 'utf-8', - ); - }) - .sleep(1000) - // http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_MENU - .pressDeviceKey(46) - .pressDeviceKey(46) - .sleep(2000) - .waitForElementByXPath( - '//android.widget.TextView[starts-with(@text, "Step 1")]', - ) - .finally(() => { - clearInterval(intervalToUpdate); - fs.writeFileSync('App.js', androidAppCode, 'utf-8'); - driver.pressDeviceKey(46).pressDeviceKey(46).sleep(2000); - }) - ); - }); - - it('should have the menu available', function () { - return ( - driver - .waitForElementByXPath( - '//android.widget.TextView[starts-with(@text, "Welcome to React")]', - ) - // http://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_MENU - .pressDeviceKey(82) - .waitForElementByXPath( - '//android.widget.TextView[starts-with(@text, "Toggle Inspector")]', - ) - ); - }); -}); diff --git a/scripts/circleci/check_appium_server_status.sh b/scripts/circleci/check_appium_server_status.sh deleted file mode 100755 index b0a2b917dc4a8c..00000000000000 --- a/scripts/circleci/check_appium_server_status.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -# This script checks if Appium server is running on default port (which is 4723). -if ! nc -z 127.0.0.1 4723; then - echo Could not find Appium server. - exit 1 -fi diff --git a/scripts/e2e/run-ci-e2e-tests.js b/scripts/e2e/run-ci-e2e-tests.js deleted file mode 100644 index ad3f6d16612668..00000000000000 --- a/scripts/e2e/run-ci-e2e-tests.js +++ /dev/null @@ -1,328 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - * @oncall react_native - */ - -'use strict'; - -/** - * This script tests that React Native end to end installation/bootstrap works for different platforms - * Available arguments: - * --ios - 'react-native init' and check iOS app doesn't redbox - * --android - 'react-native init' and check Android app doesn't redbox - * --js - 'react-native init' and only check the packager returns a bundle - * --skip-cli-install - to skip react-native-cli global installation (for local debugging) - * --retries [num] - how many times to retry possible flaky commands: yarn add and running tests, default 1 - */ - -const {REACT_NATIVE_PACKAGE_DIR, REPO_ROOT, SCRIPTS_DIR} = require('../consts'); -const {getPackages} = require('../utils/monorepo'); -const tryExecNTimes = require('./utils/try-n-times'); -const {setupVerdaccio} = require('./utils/verdaccio'); -const {execFileSync, spawn} = require('child_process'); -const fs = require('fs'); -const path = require('path'); -const {cd, cp, echo, exec, exit, mv} = require('shelljs'); -const argv = require('yargs').argv; - -const REACT_NATIVE_TEMP_DIR = exec( - 'mktemp -d /tmp/react-native-XXXXXXXX', -).stdout.trim(); -const REACT_NATIVE_APP_DIR = `${REACT_NATIVE_TEMP_DIR}/template`; -// $FlowFixMe[incompatible-type] -const numberOfRetries /*: number */ = argv.retries || 1; - -let SERVER_PID; -let APPIUM_PID; -let VERDACCIO_PID; -let exitCode; - -function describe(message /*: string */) { - echo(`\n\n>>>>> ${message}\n\n\n`); -} - -async function main() { - try { - if (argv.android) { - describe('Compile Android binaries'); - if ( - exec( - './gradlew publishAllToMavenTempLocal -Pjobs=1 -Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"', - ).code - ) { - throw new Error('Failed to compile Android binaries'); - } - } - - describe('Create react-native package'); - if ( - exec( - 'node ./scripts/releases/set-rn-version.js --to-version 1000.0.0 --build-type dry-run', - ).code - ) { - throw new Error( - 'Failed to set version and update package.json ready for release', - ); - } - - if (exec('npm pack', {cwd: REACT_NATIVE_PACKAGE_DIR}).code) { - throw new Error('Failed to pack react-native'); - } - - const REACT_NATIVE_PACKAGE = path.join( - REACT_NATIVE_PACKAGE_DIR, - 'react-native-*.tgz', - ); - - describe('Set up Verdaccio'); - VERDACCIO_PID = setupVerdaccio(); - - describe('Build and publish packages'); - exec('node ./scripts/build/build.js', {cwd: REPO_ROOT}); - - const packages = await getPackages({ - includeReactNative: false, - includePrivate: false, - }); - - for (const {path: packageAbsolutePath} of Object.values(packages)) { - exec( - 'npm publish --registry http://localhost:4873 --yes --access public', - {cwd: packageAbsolutePath}, - ); - } - - describe('Scaffold a basic React Native app from template'); - execFileSync('rsync', [ - '-a', - `${REPO_ROOT}/packages/react-native/template`, - REACT_NATIVE_TEMP_DIR, - ]); - cd(REACT_NATIVE_APP_DIR); - - mv('_bundle', '.bundle'); - mv('_eslintrc.js', '.eslintrc.js'); - mv('_prettierrc.js', '.prettierrc.js'); - mv('_watchmanconfig', '.watchmanconfig'); - fs.writeFileSync('.npmrc', 'registry=http://localhost:4873'); - - describe('Install React Native package'); - exec(`npm install ${REACT_NATIVE_PACKAGE}`); - - describe('Install node_modules'); - if ( - tryExecNTimes( - () => { - return exec('npm install').code; - }, - numberOfRetries, - () => exec('sleep 10s'), - ) - ) { - throw new Error( - 'Failed to execute npm install. Most common reason is npm registry connectivity, try again', - ); - } - exec('rm -rf ./node_modules/react-native/template'); - - if (argv.android) { - describe('Install end-to-end framework'); - if ( - tryExecNTimes( - () => - exec( - 'yarn add --dev appium@1.11.1 mocha@2.4.5 wd@1.11.1 colors@1.0.3 pretty-data2@0.40.1', - {silent: true}, - ).code, - numberOfRetries, - ) - ) { - throw new Error( - 'Failed to install appium. Most common reason is npm registry connectivity, try again.', - ); - } - cp(`${SCRIPTS_DIR}/android-e2e-test.js`, 'android-e2e-test.js'); - cd('android'); - describe('Download Maven deps'); - exec('./gradlew :app:copyDownloadableDepsToLibs'); - cd('..'); - - describe('Generate key'); - exec('rm android/app/debug.keystore'); - if ( - exec( - 'keytool -genkey -v -keystore android/app/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US"', - ).code - ) { - throw new Error('Key could not be generated'); - } - - // $FlowFixMe[incompatible-type] - describe(`Start appium server, ${APPIUM_PID}`); - const appiumProcess = spawn('node', ['./node_modules/.bin/appium']); - APPIUM_PID = appiumProcess.pid; - - describe('Build the app'); - if (exec('react-native run-android').code) { - throw new Error('Could not execute react-native run-android'); - } - - // $FlowFixMe[incompatible-type] - describe(`Start Metro, ${SERVER_PID}`); - // shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn - const packagerProcess = spawn('yarn', ['start', '--max-workers 1']); - SERVER_PID = packagerProcess.pid; - // wait a bit to allow packager to startup - exec('sleep 15s'); - describe('Test: Android end-to-end test'); - if ( - tryExecNTimes( - () => { - return exec('node node_modules/.bin/_mocha android-e2e-test.js') - .code; - }, - numberOfRetries, - () => exec('sleep 10s'), - ) - ) { - throw new Error( - 'Failed to run Android end-to-end tests. Most likely the code is broken.', - ); - } - } - - if (argv.ios) { - cd('ios'); - // shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn - const packagerEnv = Object.create(process.env); - // $FlowFixMe[prop-missing] - packagerEnv.REACT_NATIVE_MAX_WORKERS = 1; - describe('Start Metro'); - const packagerProcess = spawn('yarn', ['start'], { - stdio: 'inherit', - env: packagerEnv, - }); - SERVER_PID = packagerProcess.pid; - exec('sleep 15s'); - // prepare cache to reduce chances of possible red screen "Can't find variable __fbBatchedBridge..." - exec( - 'response=$(curl --write-out %{http_code} --silent --output /dev/null localhost:8081/index.bundle?platform=ios&dev=true)', - ); - echo(`Metro is running, ${SERVER_PID}`); - - describe('Install CocoaPod dependencies'); - exec('bundle exec pod install'); - - describe('Test: iOS end-to-end test'); - if ( - // TODO: Get target OS and simulator from .tests.env - tryExecNTimes( - () => { - return exec( - [ - 'xcodebuild', - '-workspace', - '"HelloWorld.xcworkspace"', - '-destination', - '"platform=iOS Simulator,name=iPhone 8,OS=13.3"', - '-scheme', - '"HelloWorld"', - '-sdk', - 'iphonesimulator', - '-UseModernBuildSystem=NO', - 'test', - ].join(' ') + - ' | ' + - [ - 'xcbeautify', - '--report', - 'junit', - '--reportPath', - '"~/react-native/reports/junit/iOS-e2e/results.xml"', - ].join(' ') + - ' && exit ${PIPESTATUS[0]}', - ).code; - }, - numberOfRetries, - () => exec('sleep 10s'), - ) - ) { - throw new Error( - 'Failed to run iOS end-to-end tests. Most likely the code is broken.', - ); - } - cd('..'); - } - - if (argv.js) { - // Check the packager produces a bundle (doesn't throw an error) - describe('Test: Verify packager can generate an Android bundle'); - if ( - exec( - 'yarn react-native bundle --verbose --entry-file index.js --platform android --dev true --bundle-output android-bundle.js --max-workers 1', - ).code - ) { - throw new Error('Could not build Android bundle'); - } - - describe('Test: Verify packager can generate an iOS bundle'); - if ( - exec( - 'yarn react-native bundle --entry-file index.js --platform ios --dev true --bundle-output ios-bundle.js --max-workers 1', - ).code - ) { - throw new Error('Could not build iOS bundle'); - } - - describe('Test: TypeScript typechecking'); - if (exec('yarn tsc').code) { - throw new Error('Typechecking errors were found'); - } - - describe('Test: Jest tests'); - if (exec('yarn test').code) { - throw new Error('Jest tests failed'); - } - - // TODO: ESLint infinitely hangs when running in the environment created by - // this script, but not projects generated by `react-native init`. - /* - describe('Test: ESLint/Prettier linting and formatting'); - if (exec('yarn lint').code) { - echo('linting errors were found'); - exitCode = 1; - throw Error(exitCode); - }*/ - } - exitCode = 0; - } finally { - describe('Clean up'); - if (SERVER_PID) { - echo(`Killing packager ${SERVER_PID}`); - exec(`kill -9 ${SERVER_PID}`); - // this is quite drastic but packager starts a daemon that we can't kill by killing the parent process - // it will be fixed in April (quote David Aurelio), so until then we will kill the zombie by the port number - exec("lsof -i tcp:8081 | awk 'NR!=1 {print $2}' | xargs kill"); - } - if (APPIUM_PID) { - echo(`Killing appium ${APPIUM_PID}`); - exec(`kill -9 ${APPIUM_PID}`); - } - if (VERDACCIO_PID) { - echo(`Killing verdaccio ${VERDACCIO_PID}`); - exec(`kill -9 ${VERDACCIO_PID}`); - } - } - exit(exitCode); -} - -if (require.main === module) { - // eslint-disable-next-line no-void - void main(); -} diff --git a/yarn.lock b/yarn.lock index 56aa017566dab0..407a33e25371e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2874,11 +2874,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-1.0.1.tgz#ea5b375a9ead6b09ccbd70c3894ea069829ea1bb" integrity sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA== -"@types/aria-query@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.1.tgz#3286741fb8f1e1580ac28784add4c7a1d49bdfbc" - integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q== - "@types/babel__core@^7.1.14": version "7.1.19" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" @@ -2940,14 +2935,6 @@ "@types/jsonfile" "*" "@types/node" "*" -"@types/glob@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" - integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== - dependencies: - "@types/minimatch" "^5.1.2" - "@types/node" "*" - "@types/graceful-fs@^4.1.3": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -3024,11 +3011,6 @@ resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== -"@types/minimatch@^5.1.2": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - "@types/node-forge@^1.3.0": version "1.3.8" resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.8.tgz#044ad98354ff309a031a55a40ad122f3be1ac2bb" @@ -3036,7 +3018,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@^18.0.0": +"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": version "18.16.14" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.14.tgz#ab67bb907f1146afc6fedb9ce60ae8a99c989631" integrity sha512-+ImzUB3mw2c5ISJUq0punjDilUQ5GnUim0ZRvchHIWJmOC0G+p0kzhXBqj6cDjK0QdPFwzrHWgrJp3RPvCG5qg== @@ -3092,16 +3074,6 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== -"@types/ua-parser-js@^0.7.33": - version "0.7.36" - resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz#9bd0b47f26b5a3151be21ba4ce9f5fa457c5f190" - integrity sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ== - -"@types/which@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf" - integrity sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA== - "@types/yargs-parser@*": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" @@ -3128,13 +3100,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yauzl@^2.9.1": - version "2.10.0" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" - integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== - dependencies: - "@types/node" "*" - "@typescript-eslint/eslint-plugin@^5.30.0": version "5.59.5" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz#f156827610a3f8cefc56baeaa93cd4a5f32966b4" @@ -3356,57 +3321,6 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@wdio/config@7.31.1": - version "7.31.1" - resolved "https://registry.yarnpkg.com/@wdio/config/-/config-7.31.1.tgz#53550a164c970403628525ecdc5e0c3f96a0ff30" - integrity sha512-WAfswbCatwiaDVqy6kfF/5T8/WS/US/SRhBGUFrfBuGMIe+RRoHgy7jURFWSvUIE7CNHj8yvs46fLUcxhXjzcQ== - dependencies: - "@types/glob" "^8.1.0" - "@wdio/logger" "7.26.0" - "@wdio/types" "7.30.2" - "@wdio/utils" "7.30.2" - deepmerge "^4.0.0" - glob "^8.0.3" - -"@wdio/logger@7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@wdio/logger/-/logger-7.26.0.tgz#2c105a00f63a81d52de969fef5a54a9035146b2d" - integrity sha512-kQj9s5JudAG9qB+zAAcYGPHVfATl2oqKgqj47yjehOQ1zzG33xmtL1ArFbQKWhDG32y1A8sN6b0pIqBEIwgg8Q== - dependencies: - chalk "^4.0.0" - loglevel "^1.6.0" - loglevel-plugin-prefix "^0.8.4" - strip-ansi "^6.0.0" - -"@wdio/protocols@7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-7.27.0.tgz#8e2663ec877dce7a5f76b021209c18dd0132e853" - integrity sha512-hT/U22R5i3HhwPjkaKAG0yd59eaOaZB0eibRj2+esCImkb5Y6rg8FirrlYRxIGFVBl0+xZV0jKHzR5+o097nvg== - -"@wdio/repl@7.30.2": - version "7.30.2" - resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-7.30.2.tgz#a92592078cb892d5bd14c2b300ef01ae6c8baf90" - integrity sha512-aW4nuMI+gbRmxmL4jMarBjuiQ+cFscr/8jHDt5hGx/gc/f7ifrZa4t6M5H8vFIKsvjUwl9lZRiVO4NVvvp6+cg== - dependencies: - "@wdio/utils" "7.30.2" - -"@wdio/types@7.30.2": - version "7.30.2" - resolved "https://registry.yarnpkg.com/@wdio/types/-/types-7.30.2.tgz#0baa4b8249aa1d98a545144e6fb494f1b186b24f" - integrity sha512-uZ8o7FX8RyBsaXiOWa59UKTCHTtADNvOArYTcHNEIzt+rh4JdB/uwqfc8y4TCNA2kYm7PWaQpUFwpStLeg0H1Q== - dependencies: - "@types/node" "^18.0.0" - got "^11.8.1" - -"@wdio/utils@7.30.2": - version "7.30.2" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-7.30.2.tgz#d4642c3b8333f3f2ae9d46229098c0a77c3f887b" - integrity sha512-np7I+smszFUennbQKdzbMN/zUL3s3EZq9pCCUcTRjjs9TE4tnn0wfmGdoz2o7REYu6kn9NfFFJyVIM2VtBbKEA== - dependencies: - "@wdio/logger" "7.26.0" - "@wdio/types" "7.30.2" - p-iteration "^1.1.8" - abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -3556,35 +3470,6 @@ aproba@^1.0.3: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -archiver-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" - integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw== - dependencies: - glob "^7.1.4" - graceful-fs "^4.2.0" - lazystream "^1.0.0" - lodash.defaults "^4.2.0" - lodash.difference "^4.5.0" - lodash.flatten "^4.4.0" - lodash.isplainobject "^4.0.6" - lodash.union "^4.6.0" - normalize-path "^3.0.0" - readable-stream "^2.0.0" - -archiver@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6" - integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w== - dependencies: - archiver-utils "^2.1.0" - async "^3.2.3" - buffer-crc32 "^0.2.1" - readable-stream "^3.6.0" - readdir-glob "^1.0.0" - tar-stream "^2.2.0" - zip-stream "^4.1.0" - are-we-there-yet@~1.1.2: version "1.1.7" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" @@ -3613,13 +3498,6 @@ aria-query@^4.2.2: "@babel/runtime" "^7.10.2" "@babel/runtime-corejs3" "^7.10.2" -aria-query@^5.2.1: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - array-includes@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" @@ -3995,11 +3873,6 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" -buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== - buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -4010,7 +3883,7 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer@^5.2.1, buffer@^5.5.0: +buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -4168,17 +4041,12 @@ chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -chrome-launcher@^0.15.0, chrome-launcher@^0.15.2: +chrome-launcher@^0.15.2: version "0.15.2" resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== @@ -4395,16 +4263,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -compress-commons@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d" - integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ== - dependencies: - buffer-crc32 "^0.2.13" - crc32-stream "^4.0.2" - normalize-path "^3.0.0" - readable-stream "^3.6.0" - compressible@~2.0.14: version "2.0.15" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.15.tgz#857a9ab0a7e5a07d8d837ed43fe2defff64fe212" @@ -4504,26 +4362,6 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: js-yaml "^3.13.0" parse-json "^4.0.0" -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -crc32-stream@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007" - integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w== - dependencies: - crc-32 "^1.2.0" - readable-stream "^3.4.0" - -cross-fetch@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4533,16 +4371,6 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -css-shorthand-properties@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz#1c808e63553c283f289f2dd56fcee8f3337bd935" - integrity sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A== - -css-value@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/css-value/-/css-value-0.0.1.tgz#5efd6c2eea5ea1fd6b6ac57ec0427b18452424ea" - integrity sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q== - csstype@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" @@ -4620,20 +4448,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -4661,7 +4482,7 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^4.0.0, deepmerge@^4.2.2, deepmerge@^4.3.0: +deepmerge@^4.2.2, deepmerge@^4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -4711,11 +4532,6 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -4731,40 +4547,6 @@ devtools-protocol@0.0.1107588: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1107588.tgz#f8cac707840b97cc30b029359341bcbbb0ad8ffa" integrity sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg== -devtools-protocol@0.0.948846: - version "0.0.948846" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.948846.tgz#bff47e2d1dba060130fa40ed2e5f78b916ba285f" - integrity sha512-5fGyt9xmMqUl2VI7+rnUkKCiAQIpLns8sfQtTENy5L70ktbNw0Z3TFJ1JoFNYdx/jffz4YXU45VF75wKZD7sZQ== - -devtools-protocol@0.0.981744: - version "0.0.981744" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.981744.tgz#9960da0370284577d46c28979a0b32651022bacf" - integrity sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg== - -devtools-protocol@^0.0.1161029: - version "0.0.1161029" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1161029.tgz#ec118810acf81100101f5fdabde042121c362940" - integrity sha512-kEUDtYEhgfepFC1T5a4F7XD6FzALn6bQa8Lkp7tM2vWXQG0LwXQ/MPS7BwmgW4bW3QGNci+G/mW4grFltFFtZA== - -devtools@7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-7.32.0.tgz#681ec21298eb6020e367bcaac0003a4294ec8c93" - integrity sha512-rf1OYJXCCSfhuQ+nosDb9o86/R4OJWBuBNd44PPGSBV0TCmLSrmf3PlqLEJ7/EbawkuOLWSQcX7EwIB/ABHFXg== - dependencies: - "@types/node" "^18.0.0" - "@types/ua-parser-js" "^0.7.33" - "@wdio/config" "7.31.1" - "@wdio/logger" "7.26.0" - "@wdio/protocols" "7.27.0" - "@wdio/types" "7.30.2" - "@wdio/utils" "7.30.2" - chrome-launcher "^0.15.0" - edge-paths "^2.1.0" - puppeteer-core "13.1.3" - query-selector-shadow-dom "^1.0.0" - ua-parser-js "^1.0.1" - uuid "^9.0.0" - diff-sequences@^29.4.3: version "29.4.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" @@ -4816,14 +4598,6 @@ ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer "^5.0.1" -edge-paths@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/edge-paths/-/edge-paths-2.2.1.tgz#d2d91513225c06514aeac9843bfce546abbf4391" - integrity sha512-AI5fC7dfDmCdKo3m5y7PkYE8m6bMqR6pvVpgtrZkkhcJXFLelUgkjrhk3kXXx8Kbw2cRaTT4LkOR7hqf39KJdw== - dependencies: - "@types/which" "^1.3.2" - which "^2.0.2" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -5299,17 +5073,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extract-zip@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" - integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== - dependencies: - debug "^4.1.1" - get-stream "^5.1.0" - yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -5320,11 +5083,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -5407,13 +5165,6 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -5598,15 +5349,6 @@ fs-exists-sync@^0.1.0: resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" integrity sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg== -fs-extra@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" - integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-extra@^11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" @@ -5796,17 +5538,6 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - globals@^11.1.0: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" @@ -5831,7 +5562,7 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -got@^11.0.2, got@^11.1.4, got@^11.8.1: +got@^11.1.4: version "11.8.6" resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== @@ -5853,7 +5584,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -grapheme-splitter@^1.0.2, grapheme-splitter@^1.0.4: +grapheme-splitter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== @@ -6063,15 +5794,7 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" -https-proxy-agent@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - -https-proxy-agent@5.0.1, https-proxy-agent@^5.0.1: +https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== @@ -7175,11 +6898,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -ky@0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/ky/-/ky-0.30.0.tgz#a3d293e4f6c4604a9a4694eceb6ce30e73d27d64" - integrity sha512-X/u76z4JtDVq10u1JA5UQfatPxgPaVDMYTrgHyiTpGN2z4TMEJkIHsoSBBSg9SWZEIXTKsi9kHgiQ9o3Y/4yog== - language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -7192,13 +6910,6 @@ language-tags@^1.0.5: dependencies: language-subtag-registry "~0.3.2" -lazystream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" - integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== - dependencies: - readable-stream "^2.0.5" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -7276,36 +6987,16 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== - lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.defaults@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== - -lodash.difference@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" - integrity sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA== - lodash.find@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" integrity sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg== -lodash.flatten@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== - lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -7316,11 +7007,6 @@ lodash.isobject@^3.0.2: resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" integrity sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA== -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - lodash.keys@^4.0.8: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" @@ -7336,7 +7022,7 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== -lodash.merge@^4.6.1, lodash.merge@^4.6.2: +lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== @@ -7346,16 +7032,6 @@ lodash.throttle@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= -lodash.union@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" - integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw== - -lodash.zip@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" - integrity sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg== - lodash@^4.17.11, lodash@^4.17.19, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -7389,16 +7065,6 @@ logkitty@^0.7.1: dayjs "^1.8.15" yargs "^15.1.0" -loglevel-plugin-prefix@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz#2fe0e05f1a820317d98d8c123e634c1bd84ff644" - integrity sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g== - -loglevel@^1.6.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" - integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== - long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -7748,20 +7414,6 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatc dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1, minimatch@^5.1.0: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^6.0.4: - version "6.2.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-6.2.0.tgz#2b70fd13294178c69c04dfc05aebdb97a4e79e42" - integrity sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg== - dependencies: - brace-expansion "^2.0.1" - minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -7782,11 +7434,6 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - "mkdirp@>=0.5 0", mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -8109,11 +7756,6 @@ p-cancelable@^2.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== -p-iteration@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/p-iteration/-/p-iteration-1.1.8.tgz#14df726d55af368beba81bcc92a26bb1b48e714a" - integrity sha512-IMFBSDIYcPNnW7uWYGrBqmvTiq7W0uB0fJn6shQZs7dlF3OvrHOre+JT9ikSZ7gZS3vWqclVgoQSvToJrns7uQ== - p-limit@^2.0.0, p-limit@^2.1.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -8255,11 +7897,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -8290,13 +7927,6 @@ pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.5: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== -pkg-dir@4.2.0, pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -8304,6 +7934,13 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -8381,11 +8018,6 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== -progress@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - promise@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" @@ -8447,11 +8079,6 @@ protobufjs@^7.0.0: "@types/node" ">=13.7.0" long "^5.0.0" -proxy-from-env@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -8470,42 +8097,6 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer-core@13.1.3: - version "13.1.3" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-13.1.3.tgz#cecb9e2ffff77410e4aa6428a1a2185ef4c6c01c" - integrity sha512-96pzvVBzq5lUGt3L/QrIH3mxn3NfZylHeusNhq06xBAHPI0Upc0SC/9u7tXjL0oRnmcExeVRJivr1lj7Ah/yDQ== - dependencies: - debug "4.3.2" - devtools-protocol "0.0.948846" - extract-zip "2.0.1" - https-proxy-agent "5.0.0" - node-fetch "2.6.7" - pkg-dir "4.2.0" - progress "2.0.3" - proxy-from-env "1.1.0" - rimraf "3.0.2" - tar-fs "2.1.1" - unbzip2-stream "1.4.3" - ws "8.2.3" - -puppeteer-core@^13.1.3: - version "13.7.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-13.7.0.tgz#3344bee3994163f49120a55ddcd144a40575ba5b" - integrity sha512-rXja4vcnAzFAP1OVLq/5dWNfwBGuzcOARJ6qGV7oAZhnLmVRU8G5MsdeQEAOy332ZhkIOnn9jp15R89LKHyp2Q== - dependencies: - cross-fetch "3.1.5" - debug "4.3.4" - devtools-protocol "0.0.981744" - extract-zip "2.0.1" - https-proxy-agent "5.0.1" - pkg-dir "4.2.0" - progress "2.0.3" - proxy-from-env "1.1.0" - rimraf "3.0.2" - tar-fs "2.1.1" - unbzip2-stream "1.4.3" - ws "8.5.0" - pure-rand@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306" @@ -8516,11 +8107,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== -query-selector-shadow-dom@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz#1c7b0058eff4881ac44f45d8f84ede32e9a2f349" - integrity sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw== - query-string@^6.12.1: version "6.14.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.14.1.tgz#7ac2dca46da7f309449ba0f86b1fd28255b0c86a" @@ -8589,7 +8175,7 @@ react@19.0.0-rc-fb9a90fa48-20240614: resolved "https://registry.yarnpkg.com/react/-/react-19.0.0-rc-fb9a90fa48-20240614.tgz#90eb43a0b005e8cc3cbf0d801c14816d01df1b08" integrity sha512-nvE3Gy+IOIfH/DXhkyxFVQSrITarFcQz4+shzC/McxQXEUSonpw2oDy/Wi9hdDtV3hlP12VYuDL95iiBREedNQ== -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@~2.3.6: +readable-stream@^2.0.6, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -8602,7 +8188,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -8611,13 +8197,6 @@ readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdir-glob@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" - integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== - dependencies: - minimatch "^5.1.0" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -8811,13 +8390,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -resq@^1.9.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/resq/-/resq-1.11.0.tgz#edec8c58be9af800fd628118c0ca8815283de196" - integrity sha512-G10EBz+zAAy3zUd/CDoBbXRL6ia9kOo3xRHrMDsHljI0GDkhYlyjwoCx5+3eCC4swi1uCoZQhskuJkj7Gp57Bw== - dependencies: - fast-deep-equal "^2.0.1" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -8849,11 +8421,6 @@ rfdc@^1.3.1: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== -rgb2hex@0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/rgb2hex/-/rgb2hex-0.2.5.tgz#f82230cd3ab1364fa73c99be3a691ed688f8dbdc" - integrity sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw== - rimraf@2: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -8861,7 +8428,7 @@ rimraf@2: dependencies: glob "^7.1.3" -rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -8998,13 +8565,6 @@ serialize-error@^2.1.0: resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= -serialize-error@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-8.1.0.tgz#3a069970c712f78634942ddd50fbbc0eaebe2f67" - integrity sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ== - dependencies: - type-fest "^0.20.2" - serve-static@^1.13.1: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" @@ -9435,17 +8995,7 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -tar-fs@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" - integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - -tar-stream@^2.1.4, tar-stream@^2.2.0: +tar-stream@^2.1.4: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== @@ -9512,7 +9062,7 @@ through2@^2.0.1: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6, through@^2.3.8: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -9673,11 +9223,6 @@ typescript@5.3.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.2.tgz#00d1c7c1c46928c5845c1ee8d0cc2791031d4c43" integrity sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ== -ua-parser-js@^1.0.1: - version "1.0.35" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011" - integrity sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA== - unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -9688,14 +9233,6 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unbzip2-stream@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" - integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - undici@^5.27.2: version "5.27.2" resolved "https://registry.yarnpkg.com/undici/-/undici-5.27.2.tgz#a270c563aea5b46cc0df2550523638c95c5d4411" @@ -9784,11 +9321,6 @@ uuid@^3.3.2, uuid@^3.3.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== - v8-to-istanbul@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" @@ -9851,54 +9383,6 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -webdriver@7.31.1: - version "7.31.1" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-7.31.1.tgz#2dafdef92b59dc6456023ac92a9707d7331ecdb6" - integrity sha512-nCdJLxRnYvOMFqTEX7sqQtF/hV/Jgov0Y6ICeOm1DMTlZSRRDaUsBMlEAPkEwif9uBJYdM0znv8qzfX358AGqQ== - dependencies: - "@types/node" "^18.0.0" - "@wdio/config" "7.31.1" - "@wdio/logger" "7.26.0" - "@wdio/protocols" "7.27.0" - "@wdio/types" "7.30.2" - "@wdio/utils" "7.30.2" - got "^11.0.2" - ky "0.30.0" - lodash.merge "^4.6.1" - -webdriverio@^7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-7.32.0.tgz#e40e9c1596c36ad0d7e06e50c5d5a9efa7782798" - integrity sha512-bW0JLNx+WbZO/6K52AfJwE9vh+2JAfdgov9JIt2ySrXkRdvFb7TO7dvEE44GP8GP2ppVfzOcr4XzXAxlGyX6ig== - dependencies: - "@types/aria-query" "^5.0.0" - "@types/node" "^18.0.0" - "@wdio/config" "7.31.1" - "@wdio/logger" "7.26.0" - "@wdio/protocols" "7.27.0" - "@wdio/repl" "7.30.2" - "@wdio/types" "7.30.2" - "@wdio/utils" "7.30.2" - archiver "^5.0.0" - aria-query "^5.2.1" - css-shorthand-properties "^1.1.1" - css-value "^0.0.1" - devtools "7.32.0" - devtools-protocol "^0.0.1161029" - fs-extra "^11.1.1" - grapheme-splitter "^1.0.2" - lodash.clonedeep "^4.5.0" - lodash.isobject "^3.0.2" - lodash.isplainobject "^4.0.6" - lodash.zip "^4.2.0" - minimatch "^6.0.4" - puppeteer-core "^13.1.3" - query-selector-shadow-dom "^1.0.0" - resq "^1.9.1" - rgb2hex "0.2.5" - serialize-error "^8.0.0" - webdriver "7.31.1" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -9947,7 +9431,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -10010,16 +9494,6 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== - -ws@8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - ws@>=7.4.6: version "8.13.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" @@ -10143,24 +9617,7 @@ yargs@^17.3.1, yargs@^17.6.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zip-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79" - integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A== - dependencies: - archiver-utils "^2.1.0" - compress-commons "^4.1.0" - readable-stream "^3.6.0" From 4ecc16502932f2d585a713521d0a0e800c346a81 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 18 Jun 2024 09:20:30 -0700 Subject: [PATCH 020/968] remove publishing jobs from cci (#45040) Summary: We are moving to publish from gha so we need to remove these jobs ## Changelog: [Internal] - Remove old publishing jobs from CI Pull Request resolved: https://github.com/facebook/react-native/pull/45040 Test Plan: CircleCI is green Reviewed By: cortinico Differential Revision: D58734881 Pulled By: cipolleschi fbshipit-source-id: 5981bfcf2aa51d55d54d08556631b30b6102a7cd --- .circleci/configurations/workflows.yml | 61 -------------------------- 1 file changed, 61 deletions(-) diff --git a/.circleci/configurations/workflows.yml b/.circleci/configurations/workflows.yml index ff50d9ac6dc873..32cfb0681f1c0d 100644 --- a/.circleci/configurations/workflows.yml +++ b/.circleci/configurations/workflows.yml @@ -15,67 +15,6 @@ workflows: version: 2 - # Release workflow, triggered by `yarn trigger-react-native-release` - create_release: - when: << pipeline.parameters.run_release_workflow >> - jobs: - - prepare_release: - name: prepare_release - version: << pipeline.parameters.release_version >> - monorepo_packages_version: << pipeline.parameters.release_monorepo_packages_version >> - tag: << pipeline.parameters.release_tag >> - dry_run: << pipeline.parameters.release_dry_run >> - - # This job will run only when a tag is published due to all the jobs being filtered. - publish_release: - jobs: - - prepare_hermes_workspace: - filters: *only_release_tags - - build_android: - filters: *only_release_tags - name: build_android_for_release - release_type: "release" - - build_hermesc_linux: - filters: *only_release_tags - requires: - - prepare_hermes_workspace - - build_hermesc_apple: - filters: *only_release_tags - requires: - - prepare_hermes_workspace - - build_apple_slices_hermes: - filters: *only_release_tags - requires: - - build_hermesc_apple - matrix: - parameters: - flavor: ["Debug", "Release"] - slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - - build_hermesc_windows: - filters: *only_release_tags - requires: - - prepare_hermes_workspace - - build_hermes_macos: - filters: *only_release_tags - requires: - - build_apple_slices_hermes - matrix: - parameters: - flavor: ["Debug", "Release"] - # This job will trigger when a version tag is pushed (by package_release) - - build_npm_package: - name: build_and_publish_npm_package - release_type: "release" - filters: *only_release_tags - requires: - - build_android_for_release - - build_hermesc_linux - - build_hermes_macos - - build_hermesc_windows - - poll_maven: - requires: - - build_and_publish_npm_package - analysis: when: and: From 6695b6e3b87e825cd283a2cf07d7eac08038342c Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 18 Jun 2024 09:39:35 -0700 Subject: [PATCH 021/968] Reuse Device instances when handing off connections based on device ID (#45027) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45027 Changelog: [Internal] Changes the device ID collision handling logic to reuse `Device` instances instead of creating new ones. This enables further refactoring of `Device` to improve session state isolation. Reviewed By: hoxyq Differential Revision: D58724884 fbshipit-source-id: bc11ce45ce8c80c58c32dcd1b07b28f1d1753a62 --- .../src/inspector-proxy/Device.js | 125 ++++++++++++------ .../src/inspector-proxy/InspectorProxy.js | 34 +++-- 2 files changed, 105 insertions(+), 54 deletions(-) diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index d43654c5a50987..fb1367dc26c94f 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -29,6 +29,7 @@ import type { import DeviceEventReporter from './DeviceEventReporter'; import * as fs from 'fs'; +import invariant from 'invariant'; import fetch from 'node-fetch'; import * as path from 'path'; import WS from 'ws'; @@ -98,7 +99,7 @@ export default class Device { #deviceSocket: WS; // Stores the most recent listing of device's pages, keyed by the `id` field. - #pages: $ReadOnlyMap; + #pages: $ReadOnlyMap = new Map(); // Stores information about currently connected debugger (if any). #debuggerConnection: ?DebuggerConnection = null; @@ -135,11 +136,30 @@ export default class Device { projectRoot: string, eventReporter: ?EventReporter, createMessageMiddleware: ?CreateCustomMessageHandlerFn, + ) { + this.#dangerouslyConstruct( + id, + name, + app, + socket, + projectRoot, + eventReporter, + createMessageMiddleware, + ); + } + + #dangerouslyConstruct( + id: string, + name: string, + app: string, + socket: WS, + projectRoot: string, + eventReporter: ?EventReporter, + createMessageMiddleware: ?CreateCustomMessageHandlerFn, ) { this.#id = id; this.#name = name; this.#app = app; - this.#pages = new Map(); this.#deviceSocket = socket; this.#projectRoot = projectRoot; this.#deviceEventReporter = eventReporter @@ -192,16 +212,67 @@ export default class Device { PAGES_POLLING_INTERVAL, ); this.#deviceSocket.on('close', () => { - this.#deviceEventReporter?.logDisconnection('device'); - // Device disconnected - close debugger connection. - if (this.#debuggerConnection) { - this.#debuggerConnection.socket.close(); - this.#debuggerConnection = null; + if (socket === this.#deviceSocket) { + this.#deviceEventReporter?.logDisconnection('device'); + // Device disconnected - close debugger connection. + if (this.#debuggerConnection) { + this.#debuggerConnection.socket.close(); + this.#debuggerConnection = null; + } + clearInterval(this.#pagesPollingIntervalId); } - clearInterval(this.#pagesPollingIntervalId); }); } + /** + * Used to recreate the device connection if there is a device ID collision. + * 1. Checks if the same device is attempting to reconnect for the same app. + * 2. If not, close both the device and debugger socket. + * 3. If the debugger connection can be reused, close the device socket only. + * + * This hack attempts to allow users to reload the app, either as result of a + * crash, or manually reloading, without having to restart the debugger. + */ + dangerouslyRecreateDevice( + id: string, + name: string, + app: string, + socket: WS, + projectRoot: string, + eventReporter: ?EventReporter, + createMessageMiddleware: ?CreateCustomMessageHandlerFn, + ) { + invariant( + id === this.#id, + 'dangerouslyRecreateDevice() can only be used for the same device ID', + ); + if (this.#app !== app || this.#name !== name) { + this.#deviceSocket.close(); + this.#debuggerConnection?.socket.close(); + } + + const oldDebugger = this.#debuggerConnection; + this.#debuggerConnection = null; + + if (oldDebugger) { + oldDebugger.socket.removeAllListeners(); + this.#deviceSocket.close(); + this.handleDebuggerConnection(oldDebugger.socket, oldDebugger.pageId, { + userAgent: oldDebugger.userAgent, + }); + } + + this.#dangerouslyConstruct( + id, + name, + app, + socket, + projectRoot, + eventReporter, + createMessageMiddleware, + ); + } + getName(): string { return this.#name; } @@ -373,40 +444,6 @@ export default class Device { }; } - /** - * Handles cleaning up a duplicate device connection, by client-side device ID. - * 1. Checks if the same device is attempting to reconnect for the same app. - * 2. If not, close both the device and debugger socket. - * 3. If the debugger connection can be reused, close the device socket only. - * - * This allows users to reload the app, either as result of a crash, or manually - * reloading, without having to restart the debugger. - */ - handleDuplicateDeviceConnection(newDevice: Device) { - if ( - this.#app !== newDevice.getApp() || - this.#name !== newDevice.getName() - ) { - this.#deviceSocket.close(); - this.#debuggerConnection?.socket.close(); - } - - const oldDebugger = this.#debuggerConnection; - this.#debuggerConnection = null; - - if (oldDebugger) { - oldDebugger.socket.removeAllListeners(); - this.#deviceSocket.close(); - newDevice.handleDebuggerConnection( - oldDebugger.socket, - oldDebugger.pageId, - { - userAgent: oldDebugger.userAgent, - }, - ); - } - } - /** * Returns `true` if a page supports the given target capability flag. */ @@ -927,4 +964,8 @@ export default class Device { return this.#pageHasCapability(page, 'prefersFuseboxFrontend'); } + + dangerouslyGetSocket(): WS { + return this.#deviceSocket; + } } diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index 717cc8c298775b..d33750b3ecd4f6 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -209,18 +209,28 @@ export default class InspectorProxy implements InspectorProxyQueries { const appName = query.app || 'Unknown'; const oldDevice = this.#devices.get(deviceId); - const newDevice = new Device( - deviceId, - deviceName, - appName, - socket, - this.#projectRoot, - this.#eventReporter, - this.#customMessageHandler, - ); - + let newDevice; if (oldDevice) { - oldDevice.handleDuplicateDeviceConnection(newDevice); + oldDevice.dangerouslyRecreateDevice( + deviceId, + deviceName, + appName, + socket, + this.#projectRoot, + this.#eventReporter, + this.#customMessageHandler, + ); + newDevice = oldDevice; + } else { + newDevice = new Device( + deviceId, + deviceName, + appName, + socket, + this.#projectRoot, + this.#eventReporter, + this.#customMessageHandler, + ); } this.#devices.set(deviceId, newDevice); @@ -230,7 +240,7 @@ export default class InspectorProxy implements InspectorProxyQueries { ); socket.on('close', () => { - if (this.#devices.get(deviceId) === newDevice) { + if (this.#devices.get(deviceId)?.dangerouslyGetSocket() === socket) { this.#devices.delete(deviceId); } debug(`Device ${deviceName} disconnected.`); From 9cca4c1ec12c6c2e30c22882c834a6133897deec Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 18 Jun 2024 09:39:35 -0700 Subject: [PATCH 022/968] Add test for connecting multiple debuggers to a single page, reproing "zombie" state (#45034) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45034 Changelog: [Internal] TSIA Reviewed By: hoxyq Differential Revision: D58728261 fbshipit-source-id: 32d4b05d69f88e68b5327dc5c8e837291e3d7726 --- .../InspectorProxyCdpTransport-test.js | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js index 1f287971b58811..fe91a2f9394962 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js @@ -10,6 +10,8 @@ */ import type { + ConnectRequest, + DisconnectRequest, JsonPagesListResponse, PageDescription, } from '../inspector-proxy/types'; @@ -17,6 +19,7 @@ import type { import {fetchJson} from './FetchUtils'; import {createDebuggerMock} from './InspectorDebuggerUtils'; import {createDeviceMock} from './InspectorDeviceUtils'; +import {sendFromDebuggerToTarget} from './InspectorProtocolUtils'; import {withAbortSignalForEachTest} from './ResourceUtils'; import {withServerForEachTest} from './ServerUtils'; import until from 'wait-for-expect'; @@ -151,5 +154,122 @@ describe.each(['HTTP', 'HTTPS'])( device1.close(); } }); + + test('multiple debuggers to the same page on the same device', async () => { + let device, debugger1, debugger2; + try { + // Connect a device to the proxy. + device = await createDeviceMock( + `${serverRef.serverBaseWsUrl}/inspector/device?device=device1&name=foo&app=bar`, + autoCleanup.signal, + ); + // Capture a log of events so we can assert on their order later. + const events: Array< + | ConnectRequest + | DisconnectRequest + | {event: 'create-debugger-mock', name: string}, + > = []; + device.disconnect.mockImplementation(message => { + events.push(message); + }); + device.connect.mockImplementation(message => { + events.push(message); + }); + // Set up the page. + device.getPages.mockImplementation(() => [ + { + app: 'bar-app', + id: 'page1', + title: 'bar-title', + vm: 'bar-vm', + }, + ]); + let pageList: Array = []; + await until(async () => { + pageList = (await fetchJson( + `${serverRef.serverBaseUrl}/json`, + // $FlowIgnore[unclear-type] + ): any); + expect(pageList).toHaveLength(1); + }); + const [{webSocketDebuggerUrl}] = pageList; + + // Connect the first debugger and send a message. + events.push({event: 'create-debugger-mock', name: 'debugger1'}); + debugger1 = await createDebuggerMock( + webSocketDebuggerUrl, + autoCleanup.signal, + ); + await sendFromDebuggerToTarget(debugger1, device, 'page1', { + method: 'Runtime.enable', + id: 0, + }); + + // Connect the second debugger. + events.push({event: 'create-debugger-mock', name: 'debugger2'}); + debugger2 = await createDebuggerMock( + webSocketDebuggerUrl, + autoCleanup.signal, + ); + + // The first debugger gets disconnected. TODO: In the future, we should + // amend the protocol to allow for multiple debuggers to connect at the + // same time. + await until(async () => { + expect([ + // CLOSING + 3, + // CLOSED + 4, + ]).toContain(debugger1.socket.readyState); + }); + + // Send a message from the second debugger. + await sendFromDebuggerToTarget(debugger2, device, 'page1', { + method: 'Debugger.enable', + id: 1, + }); + + // Check the order of `connect` and `disconnect` events received by the + // device. `create-debugger-mock` events are included for convenience. + expect(events).toEqual([ + { + event: 'create-debugger-mock', + name: 'debugger1', + }, + { + event: 'connect', + payload: { + pageId: 'page1', + }, + }, + { + event: 'create-debugger-mock', + name: 'debugger2', + }, + // FIXME: We currently send `connect` (for debugger2) before + // `disconnect` (for debugger1), which is wrong - it leaves the + // device thinking the connection is gone while the proxy keeps the + // debugger connection open. The user of debugger2 sees the frontend + // in a "zombie" state (not disconnected, but unresponsive). + { + event: 'connect', + payload: { + pageId: 'page1', + }, + }, + { + event: 'disconnect', + payload: { + pageId: 'page1', + }, + }, + ]); + } finally { + device?.close(); + debugger1?.close(); + debugger2?.close(); + } + }); }, ); From e55ea2daf11bb527f500323e3f1bb71f10cbe1c5 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 18 Jun 2024 09:39:35 -0700 Subject: [PATCH 023/968] Fix debugger handoff logic to prevent "zombie" state (#45035) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45035 Changelog: [General][Fixed] Avoid a zombie state when opening a second debugger frontend concurrently. The problem here was that we were sending proxy-protocol messages to the device in the wrong order (`disconnect` *after* `connect`): {F1701266597} The root cause was that we were depending on the outgoing debugger socket's async `close` event to trigger sending the `disconnect` message to the device. This would happen after we'd already (synchronously) sent the `connect` message. With this diff, we send the `disconnect` message synchronously with calling `close()` on the debugger socket, which fixes the ordering problem at the source. To avoid sending duplicate `disconnect` messages (e.g. one before calling `close()` and one from the `close` event handler), we store some extra state on `Device` (`#connectedPageIds`). Reviewed By: robhogan, huntie Differential Revision: D58730634 fbshipit-source-id: 0f54af2e4f8071a8f6d97cc9e3d8a4ea89a46f43 --- .../InspectorProxyCdpTransport-test.js | 11 +-- .../src/inspector-proxy/Device.js | 88 ++++++++++--------- 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js index fe91a2f9394962..5c3536be64ae20 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCdpTransport-test.js @@ -247,19 +247,16 @@ describe.each(['HTTP', 'HTTPS'])( event: 'create-debugger-mock', name: 'debugger2', }, - // FIXME: We currently send `connect` (for debugger2) before - // `disconnect` (for debugger1), which is wrong - it leaves the - // device thinking the connection is gone while the proxy keeps the - // debugger connection open. The user of debugger2 sees the frontend - // in a "zombie" state (not disconnected, but unresponsive). { - event: 'connect', + // NOTE: For debugger1 + event: 'disconnect', payload: { pageId: 'page1', }, }, { - event: 'disconnect', + // NOTE: For debugger2 + event: 'connect', payload: { pageId: 'page1', }, diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index fb1367dc26c94f..8542adcfd0491e 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -58,7 +58,7 @@ const REWRITE_HOSTS_TO_LOCALHOST: Array = [ // more details. const FILE_PREFIX = 'file://'; -type DebuggerInfo = { +type DebuggerConnection = { // Debugger web socket connection socket: WS, // If we replaced address (like '10.0.2.2') to localhost we need to store original @@ -67,10 +67,6 @@ type DebuggerInfo = { prependedFilePrefix: boolean, pageId: string, userAgent: string | null, -}; - -type DebuggerConnection = { - ...DebuggerInfo, customHandler: ?CustomMessageHandler, }; @@ -128,6 +124,8 @@ export default class Device { // The device message middleware factory function allowing implementers to handle unsupported CDP messages. #createCustomMessageHandler: ?CreateCustomMessageHandlerFn; + #connectedPageIds: Set = new Set(); + constructor( id: string, name: string, @@ -215,15 +213,23 @@ export default class Device { if (socket === this.#deviceSocket) { this.#deviceEventReporter?.logDisconnection('device'); // Device disconnected - close debugger connection. - if (this.#debuggerConnection) { - this.#debuggerConnection.socket.close(); - this.#debuggerConnection = null; - } + this.#terminateDebuggerConnection(); clearInterval(this.#pagesPollingIntervalId); } }); } + #terminateDebuggerConnection() { + const debuggerConnection = this.#debuggerConnection; + if (debuggerConnection) { + this.#sendDisconnectEventToDevice( + this.#mapToDevicePageId(debuggerConnection.pageId), + ); + debuggerConnection.socket.close(); + this.#debuggerConnection = null; + } + } + /** * Used to recreate the device connection if there is a device ID collision. * 1. Checks if the same device is attempting to reconnect for the same app. @@ -246,12 +252,14 @@ export default class Device { id === this.#id, 'dangerouslyRecreateDevice() can only be used for the same device ID', ); + + const oldDebugger = this.#debuggerConnection; + if (this.#app !== app || this.#name !== name) { this.#deviceSocket.close(); - this.#debuggerConnection?.socket.close(); + this.#terminateDebuggerConnection(); } - const oldDebugger = this.#debuggerConnection; this.#debuggerConnection = null; if (oldDebugger) { @@ -309,10 +317,7 @@ export default class Device { }); // Disconnect current debugger if we already have debugger connected. - if (this.#debuggerConnection) { - this.#debuggerConnection.socket.close(); - this.#debuggerConnection = null; - } + this.#terminateDebuggerConnection(); const debuggerInfo = { socket, @@ -377,12 +382,7 @@ export default class Device { } } - this.#sendMessageToDevice({ - event: 'connect', - payload: { - pageId: this.#mapToDevicePageId(pageId), - }, - }); + this.#sendConnectEventToDevice(this.#mapToDevicePageId(pageId)); // $FlowFixMe[incompatible-call] socket.on('message', (message: string) => { @@ -426,13 +426,9 @@ export default class Device { socket.on('close', () => { debug(`Debugger for page ${pageId} and ${this.#name} disconnected.`); this.#deviceEventReporter?.logDisconnection('debugger'); - this.#sendMessageToDevice({ - event: 'disconnect', - payload: { - pageId: this.#mapToDevicePageId(pageId), - }, - }); - this.#debuggerConnection = null; + if (this.#debuggerConnection?.socket === socket) { + this.#terminateDebuggerConnection(); + } }); // $FlowFixMe[method-unbinding] @@ -444,6 +440,28 @@ export default class Device { }; } + #sendConnectEventToDevice(devicePageId: string) { + if (this.#connectedPageIds.has(devicePageId)) { + return; + } + this.#connectedPageIds.add(devicePageId); + this.#sendMessageToDevice({ + event: 'connect', + payload: {pageId: devicePageId}, + }); + } + + #sendDisconnectEventToDevice(devicePageId: string) { + if (!this.#connectedPageIds.has(devicePageId)) { + return; + } + this.#connectedPageIds.delete(devicePageId); + this.#sendMessageToDevice({ + event: 'disconnect', + payload: {pageId: devicePageId}, + }); + } + /** * Returns `true` if a page supports the given target capability flag. */ @@ -621,20 +639,10 @@ export default class Device { // page. if (oldPageId != null) { - this.#sendMessageToDevice({ - event: 'disconnect', - payload: { - pageId: oldPageId, - }, - }); + this.#sendDisconnectEventToDevice(oldPageId); } - this.#sendMessageToDevice({ - event: 'connect', - payload: { - pageId: page.id, - }, - }); + this.#sendConnectEventToDevice(page.id); const toSend = [ {method: 'Runtime.enable', id: 1e9}, From e0fcf2983abbc0da07a7c28a16ebe5b886ae5e47 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 18 Jun 2024 09:43:20 -0700 Subject: [PATCH 024/968] Use hermes-parser when building Node packages (#45041) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45041 Changelog: [Internal] TSIA Reviewed By: huntie Differential Revision: D58734657 fbshipit-source-id: d5b17bc0ee8f36bae7c594d99ce70ecea9bf4a40 --- package.json | 1 + scripts/build/babel/node.config.js | 1 + yarn.lock | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/package.json b/package.json index 1580df032b3e6f..56e387b640095a 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "@typescript-eslint/parser": "^7.1.1", "ansi-styles": "^4.2.1", "babel-plugin-minify-dead-code-elimination": "^0.5.2", + "babel-plugin-syntax-hermes-parser": "0.22.0", "babel-plugin-transform-define": "^2.1.2", "babel-plugin-transform-flow-enums": "^0.0.2", "babel-preset-fbjs": "^3.4.0", diff --git a/scripts/build/babel/node.config.js b/scripts/build/babel/node.config.js index 52634d00f3a8ec..a30d835a335db9 100644 --- a/scripts/build/babel/node.config.js +++ b/scripts/build/babel/node.config.js @@ -28,6 +28,7 @@ const config /*: BabelCoreOptions */ = { ], ], plugins: [ + require.resolve('babel-plugin-syntax-hermes-parser'), [ require.resolve('babel-plugin-transform-define'), { diff --git a/yarn.lock b/yarn.lock index 407a33e25371e4..80a2ceeda3d984 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3709,6 +3709,13 @@ babel-plugin-syntax-hermes-parser@0.17.0: dependencies: hermes-parser "0.17.0" +babel-plugin-syntax-hermes-parser@0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.22.0.tgz#708aa61189aa8ef882d3638e40da2d685a742298" + integrity sha512-DSZphimfuycQgouuhqUq9gCV1dNKFaA1phquNFjj3nO2Rx+zAcCMc8qrUK9koxJyEN+y+CihP3Kya6ukCl13OQ== + dependencies: + hermes-parser "0.22.0" + babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: version "7.0.0-beta.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" From 3fc6963da3dfef5e6d514132a559661587f44300 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 18 Jun 2024 10:09:29 -0700 Subject: [PATCH 025/968] Fix release regex for publish-release workflow (#45043) Summary: The existing regex is not workign. I've split it in two and tested it against a private repo. ## Changelog: [INTERNAL] - Fix release regex for publish-release workflow Pull Request resolved: https://github.com/facebook/react-native/pull/45043 Test Plan: Tested on privare repo with GHA Reviewed By: cipolleschi Differential Revision: D58736292 Pulled By: cortinico fbshipit-source-id: f07ef32dcb0059922100c555f7894bbf0c7dd8f6 --- .github/workflows/publish-release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 051aef4038eda6..af1f66a8f6a3ff 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -1,9 +1,9 @@ -name: Publish release - +name: Publish Release on: push: tags: - - "v0.[0-9]+.[0-9]+(-*)?" # This should match v0.X.Y and v0.X.Y-RC.0 + - "v0.*.*" # This should match v0.X.Y + - "v0.*.*-rc.*" # This should match v0.X.Y-RC.0 jobs: set_release_type: runs-on: ubuntu-latest From d8739e1d37ceebb9643ca56d66a54aaca330665a Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Tue, 18 Jun 2024 10:46:23 -0700 Subject: [PATCH 026/968] Add unit tests for BorderRadiusStyle (#44964) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44964 Testing property priority and correct setting percentages for business logic of `BorderRadiusStyle.kt` To prevent issues like the one fixed by D57473482 Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D58705515 fbshipit-source-id: 74e9a68fc0e3d1e88b8eebbb34a1ca8c29052c21 --- .../ReactAndroid/api/ReactAndroid.api | 11 ++ .../uimanager/style/ComputedBorderRadius.kt | 17 ++ .../react/uimanager/BorderRadiusStyleTest.kt | 186 ++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index d0336cdacb2e10..44635cb1a6ab2f 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -5956,6 +5956,7 @@ public final class com/facebook/react/uimanager/style/ComputedBorderRadius { public final fun copy (FFFF)Lcom/facebook/react/uimanager/style/ComputedBorderRadius; public static synthetic fun copy$default (Lcom/facebook/react/uimanager/style/ComputedBorderRadius;FFFFILjava/lang/Object;)Lcom/facebook/react/uimanager/style/ComputedBorderRadius; public fun equals (Ljava/lang/Object;)Z + public final fun get (Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp;)F public final fun getBottomLeft ()F public final fun getBottomRight ()F public final fun getTopLeft ()F @@ -5965,6 +5966,16 @@ public final class com/facebook/react/uimanager/style/ComputedBorderRadius { public fun toString ()Ljava/lang/String; } +public final class com/facebook/react/uimanager/style/ComputedBorderRadiusProp : java/lang/Enum { + public static final field COMPUTED_BORDER_BOTTOM_LEFT_RADIUS Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp; + public static final field COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp; + public static final field COMPUTED_BORDER_TOP_LEFT_RADIUS Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp; + public static final field COMPUTED_BORDER_TOP_RIGHT_RADIUS Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp; + public static fun values ()[Lcom/facebook/react/uimanager/style/ComputedBorderRadiusProp; +} + public class com/facebook/react/uimanager/util/ReactFindViewUtil { public fun ()V public static fun addViewListener (Lcom/facebook/react/uimanager/util/ReactFindViewUtil$OnViewFoundListener;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt index d337e80ba35143..292b66c5b4dfbc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ComputedBorderRadius.kt @@ -7,6 +7,14 @@ package com.facebook.react.uimanager.style +/** Represents the collection of possible computed border radius style properties. */ +public enum class ComputedBorderRadiusProp { + COMPUTED_BORDER_TOP_LEFT_RADIUS, + COMPUTED_BORDER_TOP_RIGHT_RADIUS, + COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS, + COMPUTED_BORDER_BOTTOM_LEFT_RADIUS, +} + /** Phsysical edge lengths (in DIPs) for a border-radius. */ public data class ComputedBorderRadius( val topLeft: Float, @@ -18,5 +26,14 @@ public data class ComputedBorderRadius( return topLeft > 0f || topRight > 0f || bottomLeft > 0f || bottomRight > 0f } + public fun get(property: ComputedBorderRadiusProp): Float { + return when (property) { + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS -> topLeft + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS -> topRight + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS -> bottomLeft + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS -> bottomRight + } + } + public constructor() : this(0f, 0f, 0f, 0f) } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt new file mode 100644 index 00000000000000..81f48635b4b1ee --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/BorderRadiusStyleTest.kt @@ -0,0 +1,186 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager + +import android.content.Context +import com.facebook.react.uimanager.style.BorderRadiusProp +import com.facebook.react.uimanager.style.BorderRadiusStyle +import com.facebook.react.uimanager.style.ComputedBorderRadiusProp +import org.assertj.core.api.Assertions.* +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +/** Tests for [BorderRadiusStyle] */ +@RunWith(RobolectricTestRunner::class) +class BorderRadiusStyleTest { + + private val ctx: Context = RuntimeEnvironment.getApplication() + + @Test + fun testCorrectPriorityLTR() { + val propertyOrderMap = + mapOf( + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, + BorderRadiusProp.BORDER_TOP_START_RADIUS, + BorderRadiusProp.BORDER_START_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, + BorderRadiusProp.BORDER_TOP_END_RADIUS, + BorderRadiusProp.BORDER_END_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, + BorderRadiusProp.BORDER_START_END_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, + BorderRadiusProp.BORDER_END_END_RADIUS), + ) + + propertyOrderMap.forEach { order -> + val borderRadiusStyle = BorderRadiusStyle() + // Starting count on 3 to test 0 override + var count = 3f + for (prop in order.value) { + borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) + val resolved = borderRadiusStyle.resolve(0, context = ctx, width = 100f, height = 100f) + assertThat(resolved.get(order.key)).isEqualTo(count) + count -= 1f + } + } + } + + @Test + fun testCorrectPriorityRTL() { + setContextLeftAndRightSwap(ctx, true) + val propertyOrderMap = + mapOf( + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, + BorderRadiusProp.BORDER_TOP_END_RADIUS, + BorderRadiusProp.BORDER_END_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, + BorderRadiusProp.BORDER_TOP_START_RADIUS, + BorderRadiusProp.BORDER_START_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, + BorderRadiusProp.BORDER_END_END_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, + BorderRadiusProp.BORDER_START_END_RADIUS), + ) + + propertyOrderMap.forEach { order -> + val borderRadiusStyle = BorderRadiusStyle() + // Starting count on 3 to test 0 override + var count = 3f + for (prop in order.value) { + borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) + val resolved = borderRadiusStyle.resolve(1, context = ctx, width = 100f, height = 100f) + assertThat(resolved.get(order.key)).isEqualTo(count) + count -= 1f + } + } + } + + @Test + fun testCorrectPriorityRTLNoSwap() { + setContextLeftAndRightSwap(ctx, false) + val propertyOrderMap = + mapOf( + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_LEFT_RADIUS, + BorderRadiusProp.BORDER_TOP_END_RADIUS, + BorderRadiusProp.BORDER_END_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_TOP_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_TOP_RIGHT_RADIUS, + BorderRadiusProp.BORDER_TOP_START_RADIUS, + BorderRadiusProp.BORDER_START_START_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_LEFT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_LEFT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_START_RADIUS, + BorderRadiusProp.BORDER_END_END_RADIUS), + ComputedBorderRadiusProp.COMPUTED_BORDER_BOTTOM_RIGHT_RADIUS to + arrayOf( + BorderRadiusProp.BORDER_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_RIGHT_RADIUS, + BorderRadiusProp.BORDER_BOTTOM_END_RADIUS, + BorderRadiusProp.BORDER_START_END_RADIUS), + ) + + propertyOrderMap.forEach { order -> + val borderRadiusStyle = BorderRadiusStyle() + // Starting count on 3 to test 0 override + var count = 3f + for (prop in order.value) { + borderRadiusStyle.set(prop, LengthPercentage(count, LengthPercentageType.POINT)) + val resolved = borderRadiusStyle.resolve(1, context = ctx, width = 100f, height = 100f) + assertThat(resolved.get(order.key)).isEqualTo(count) + count -= 1f + } + } + } + + @Test + fun testBorderRadiusPercentages() { + val borderRadiusStyle = + BorderRadiusStyle( + topLeft = LengthPercentage(0f, LengthPercentageType.PERCENT), + topRight = LengthPercentage(10f, LengthPercentageType.PERCENT), + bottomLeft = LengthPercentage(20f, LengthPercentageType.PERCENT), + bottomRight = LengthPercentage(30f, LengthPercentageType.PERCENT), + ) + val resolved = borderRadiusStyle.resolve(0, context = ctx, width = 1000f, height = 1000f) + + assertThat(resolved.topLeft).isEqualTo(0f) + assertThat(resolved.topRight).isEqualTo(100f) + assertThat(resolved.bottomLeft).isEqualTo(200f) + assertThat(resolved.bottomRight).isEqualTo(300f) + } + + /* + * Make I18nUtil.instance.doLeftAndRightSwapInRTL(context) return false + * by setting context preference + */ + private fun setContextLeftAndRightSwap(context: Context, leftAndRightSwap: Boolean) { + val sharedPrefs = + context.getSharedPreferences( + "com.facebook.react.modules.i18nmanager.I18nUtil", Context.MODE_PRIVATE) + val editor = sharedPrefs.edit() + editor.putBoolean("RCTI18nUtil_makeRTLFlipLeftAndRightStyles", leftAndRightSwap) + editor.apply() + } +} From 2f0c06de1040589622a1ff27d36a7f8913a2d2b8 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 18 Jun 2024 16:23:45 -0700 Subject: [PATCH 027/968] setup gating for (#45031) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45031 changelog: [internal] Reviewed By: rubennorte Differential Revision: D58672844 fbshipit-source-id: 2c99d3b66665c8dc0b796713b21d91211b469d81 --- packages/react-native/Libraries/Text/Text.js | 7 ++++++- .../__tests__/__snapshots__/public-api-test.js.snap | 2 +- .../featureflags/ReactNativeFeatureFlags.config.js | 4 ++++ .../src/private/featureflags/ReactNativeFeatureFlags.js | 8 +++++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js index b9c10b3e736116..623fa98114fd7b 100644 --- a/packages/react-native/Libraries/Text/Text.js +++ b/packages/react-native/Libraries/Text/Text.js @@ -11,6 +11,7 @@ import type {PressEvent} from '../Types/CoreEventTypes'; import type {TextProps} from './TextProps'; +import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags'; import * as PressabilityDebug from '../Pressability/PressabilityDebug'; import usePressability from '../Pressability/usePressability'; import flattenStyle from '../StyleSheet/flattenStyle'; @@ -337,4 +338,8 @@ const verticalAlignToTextAlignVerticalMap = { middle: 'center', }; -module.exports = Text; +module.exports = ( + ReactNativeFeatureFlags.shouldUseOptimizedText() + ? require('./TextOptimized') + : Text +) as typeof Text; diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 6269e4e9bc2e32..839995a83c7af7 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -8048,7 +8048,7 @@ exports[`public API should not change unintentionally Libraries/Text/Text.js 1`] TextProps, React.ElementRef, >; -declare module.exports: Text; +declare module.exports: typeof Text; " `; diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 313fffce5284ee..79884fb2b25019 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -187,6 +187,10 @@ const definitions: FeatureFlagDefinitions = { description: 'Enables use of AnimatedObject for animating transform values.', }, + shouldUseOptimizedText: { + defaultValue: false, + description: 'Use optimized version of component.', + }, shouldUseRemoveClippedSubviewsAsDefaultOnIOS: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 6bc4b7dd1cab57..56cb85ac155578 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<522f11a571457cb932f451cf81bd384a>> * @flow strict-local */ @@ -32,6 +32,7 @@ export type ReactNativeFeatureFlagsJsOnly = { enableAccessToHostTreeInFabric: Getter, isLayoutAnimationEnabled: Getter, shouldUseAnimatedObjectForTransform: Getter, + shouldUseOptimizedText: Getter, shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter, shouldUseSetNativePropsInFabric: Getter, }; @@ -97,6 +98,11 @@ export const isLayoutAnimationEnabled: Getter = createJavaScriptFlagGet */ export const shouldUseAnimatedObjectForTransform: Getter = createJavaScriptFlagGetter('shouldUseAnimatedObjectForTransform', false); +/** + * Use optimized version of component. + */ +export const shouldUseOptimizedText: Getter = createJavaScriptFlagGetter('shouldUseOptimizedText', false); + /** * removeClippedSubviews prop will be used as the default in FlatList on iOS to match Android */ From 58ff2fc6361964b074a30a919621c080f9737b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 19 Jun 2024 04:13:38 -0700 Subject: [PATCH 028/968] Make the instructions to regenerate feature flags easier to see in the docs (#45059) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45059 Changelog: [internal] By moving the command to a code block it's going to be easier to see it when quickly reading the README. Reviewed By: cortinico Differential Revision: D58779883 fbshipit-source-id: e912a58641245c6d7dc158f7af0a722e438a0cc3 --- packages/react-native/scripts/featureflags/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/react-native/scripts/featureflags/README.md b/packages/react-native/scripts/featureflags/README.md index 7cb68fec0811e1..b39adfbda6ab4a 100644 --- a/packages/react-native/scripts/featureflags/README.md +++ b/packages/react-native/scripts/featureflags/README.md @@ -32,9 +32,13 @@ module.exports = { }; ``` -After any changes to this definitions, the code that provides access to them -must be regenerated running `yarn featureflags-update` from the `react-native` -repository. +**After any change to these definitions**, the code that provides access to them +must be regenerated running this from the `react-native` +repository: + +```shell +yarn featureflags-update +``` ## Access From 0c2fea5c23f3b420c72edb50740e1c54dd6ca931 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 19 Jun 2024 04:59:02 -0700 Subject: [PATCH 029/968] fix syntax error (#45058) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45058 changelog: [internal] Fix github action failure: ``` TransformError [SyntaxError]: /__w/react-native/react-native/packages/react-native/Libraries/Text/Text.js: Missing semicolon. (345:1) 343 | ? require('./TextOptimized') 344 | : Text > 345 | ) as typeof Text; ``` Reviewed By: fabriziocucci Differential Revision: D58779125 fbshipit-source-id: 76917aebf8ae8cfb9f2aa7a75a76383c5a832732 --- packages/react-native/Libraries/Text/Text.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js index 623fa98114fd7b..bc68479ae4b3f6 100644 --- a/packages/react-native/Libraries/Text/Text.js +++ b/packages/react-native/Libraries/Text/Text.js @@ -338,8 +338,6 @@ const verticalAlignToTextAlignVerticalMap = { middle: 'center', }; -module.exports = ( - ReactNativeFeatureFlags.shouldUseOptimizedText() - ? require('./TextOptimized') - : Text -) as typeof Text; +module.exports = ((ReactNativeFeatureFlags.shouldUseOptimizedText() + ? require('./TextOptimized') + : Text): typeof Text); From 927815b9f6f086ab77e422efa2eb39754e0de56b Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Wed, 19 Jun 2024 05:00:41 -0700 Subject: [PATCH 030/968] use correct has to label hermes cache key (#45061) Summary: This incorrectly used the SHA from facebook/react-native instead of facebook/hermes to label the hermes cache key. This would bloat our cache by ~ 1.2GB for each PR. Changelog: [Internal] Pull Request resolved: https://github.com/facebook/react-native/pull/45061 Test Plan: We should remove the existing entries for v4-hermes and track the growth over time. Reviewed By: cipolleschi Differential Revision: D58780475 Pulled By: blakef fbshipit-source-id: 0f192faa287f53154f1c8319be6783820d614018 --- .github/workflows/nightly.yml | 2 +- .github/workflows/publish-release.yml | 2 +- .github/workflows/test-all.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 76de850c9a4bb8..05524352f12174 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -48,7 +48,7 @@ jobs: else echo "Hermes Version file not found!!!" echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/$GITHUB_REPOSITORY main | cut -f 1 | tr -d '[:space:]') + HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" fi echo "Hermes commit is $HERMES_TAG_SHA" diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index af1f66a8f6a3ff..257c019a975327 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -45,7 +45,7 @@ jobs: else echo "Hermes Version file not found!!!" echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/$GITHUB_REPOSITORY main | cut -f 1 | tr -d '[:space:]') + HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" fi echo "Hermes commit is $HERMES_TAG_SHA" diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 3e782d74649921..246b0e04f22f68 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -55,7 +55,7 @@ jobs: else echo "Hermes Version file not found!!!" echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/$GITHUB_REPOSITORY main | cut -f 1 | tr -d '[:space:]') + HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" fi echo "Hermes commit is $HERMES_TAG_SHA" From 9b67547bec36cae2b4d9f99f66938fbe6b1466bf Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 19 Jun 2024 05:05:00 -0700 Subject: [PATCH 031/968] Remove enableArchitectureIndicator from AppRegistry API (#45025) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45025 This API just passed through the `enableArchitectureIndicator` prop to a custom WrapperComponent, as there is no default consumer of it. Instead, each provider of a custom WrapperComponent can capture the required value of itself. Changelog: [General][Removed] Removed enableArchitectureIndicator API which is only used internally. Reviewed By: cortinico Differential Revision: D58723922 fbshipit-source-id: 0c52a904424382f33caab92ac50b316ae161f877 --- .../react-native/Libraries/ReactNative/AppContainer-dev.js | 6 +----- .../react-native/Libraries/ReactNative/AppContainer-prod.js | 6 +----- packages/react-native/Libraries/ReactNative/AppContainer.js | 1 - packages/react-native/Libraries/ReactNative/AppRegistry.js | 6 ------ .../react-native/Libraries/ReactNative/renderApplication.js | 2 -- .../__tests__/__snapshots__/public-api-test.js.snap | 3 --- 6 files changed, 2 insertions(+), 22 deletions(-) diff --git a/packages/react-native/Libraries/ReactNative/AppContainer-dev.js b/packages/react-native/Libraries/ReactNative/AppContainer-dev.js index fe71b3c04d3dca..b5a1a0756eef0e 100644 --- a/packages/react-native/Libraries/ReactNative/AppContainer-dev.js +++ b/packages/react-native/Libraries/ReactNative/AppContainer-dev.js @@ -90,7 +90,6 @@ const AppContainer = ({ internal_excludeInspector = false, internal_excludeLogBox = false, rootTag, - showArchitectureIndicator, WrapperComponent, rootViewStyle, }: Props): React.Node => { @@ -150,10 +149,7 @@ const AppContainer = ({ if (WrapperComponent != null) { innerView = ( - + {innerView} ); diff --git a/packages/react-native/Libraries/ReactNative/AppContainer-prod.js b/packages/react-native/Libraries/ReactNative/AppContainer-prod.js index 0f091d5669c922..4be53572da2323 100644 --- a/packages/react-native/Libraries/ReactNative/AppContainer-prod.js +++ b/packages/react-native/Libraries/ReactNative/AppContainer-prod.js @@ -21,7 +21,6 @@ const AppContainer = ({ fabric, initialProps, rootTag, - showArchitectureIndicator, WrapperComponent, rootViewStyle, }: Props): React.Node => { @@ -29,10 +28,7 @@ const AppContainer = ({ if (WrapperComponent != null) { innerView = ( - + {innerView} ); diff --git a/packages/react-native/Libraries/ReactNative/AppContainer.js b/packages/react-native/Libraries/ReactNative/AppContainer.js index 3463d14dcf2f6d..91a51cd8f48a31 100644 --- a/packages/react-native/Libraries/ReactNative/AppContainer.js +++ b/packages/react-native/Libraries/ReactNative/AppContainer.js @@ -18,7 +18,6 @@ export type Props = $ReadOnly<{| fabric?: boolean, rootTag: number | RootTag, initialProps?: {...}, - showArchitectureIndicator?: boolean, WrapperComponent?: ?React.ComponentType, rootViewStyle?: ?ViewStyleProp, internal_excludeLogBox?: boolean, diff --git a/packages/react-native/Libraries/ReactNative/AppRegistry.js b/packages/react-native/Libraries/ReactNative/AppRegistry.js index 68bd3895571778..d073995be8c859 100644 --- a/packages/react-native/Libraries/ReactNative/AppRegistry.js +++ b/packages/react-native/Libraries/ReactNative/AppRegistry.js @@ -73,7 +73,6 @@ let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = let wrapperComponentProvider: ?WrapperComponentProvider; let rootViewStyleProvider: ?RootViewStyleProvider; -let showArchitectureIndicator = false; /** * `AppRegistry` is the JavaScript entry point to running all React Native apps. @@ -89,10 +88,6 @@ const AppRegistry = { rootViewStyleProvider = provider; }, - enableArchitectureIndicator(enabled: boolean): void { - showArchitectureIndicator = enabled; - }, - registerConfig(config: Array): void { config.forEach(appConfig => { if (appConfig.run) { @@ -139,7 +134,6 @@ const AppRegistry = { wrapperComponentProvider && wrapperComponentProvider(appParameters), rootViewStyleProvider && rootViewStyleProvider(appParameters), appParameters.fabric, - showArchitectureIndicator, scopedPerformanceLogger, appKey === 'LogBox', // is logbox appKey, diff --git a/packages/react-native/Libraries/ReactNative/renderApplication.js b/packages/react-native/Libraries/ReactNative/renderApplication.js index 701db565ffe80c..c483082f919d4c 100644 --- a/packages/react-native/Libraries/ReactNative/renderApplication.js +++ b/packages/react-native/Libraries/ReactNative/renderApplication.js @@ -35,7 +35,6 @@ export default function renderApplication( WrapperComponent?: ?React.ComponentType, rootViewStyle?: ?ViewStyleProp, fabric?: boolean, - showArchitectureIndicator?: boolean, scopedPerformanceLogger?: IPerformanceLogger, isLogBox?: boolean, debugName?: string, @@ -52,7 +51,6 @@ export default function renderApplication( , rootViewStyle?: ?ViewStyleProp, internal_excludeLogBox?: boolean, @@ -6633,7 +6632,6 @@ export type RootViewStyleProvider = (appParameters: Object) => ViewStyleProp; declare const AppRegistry: { setWrapperComponentProvider(provider: WrapperComponentProvider): void, setRootViewStyleProvider(provider: RootViewStyleProvider): void, - enableArchitectureIndicator(enabled: boolean): void, registerConfig(config: Array): void, registerComponent( appKey: string, @@ -6973,7 +6971,6 @@ exports[`public API should not change unintentionally Libraries/ReactNative/rend WrapperComponent?: ?React.ComponentType, rootViewStyle?: ?ViewStyleProp, fabric?: boolean, - showArchitectureIndicator?: boolean, scopedPerformanceLogger?: IPerformanceLogger, isLogBox?: boolean, debugName?: string, From 51e464f50fb04fee622edb1f35255607a018337c Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 19 Jun 2024 05:05:00 -0700 Subject: [PATCH 032/968] Remove unnecessary synchronized collections from ReactHostImpl (#45026) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45026 All callsites for these containers already explicitly synchronize using these objects, so there's no need to use a synchronized collection wrapper here. Changelog: [Internal] Reviewed By: rshest Differential Revision: D58724044 fbshipit-source-id: 5151ebb0ceda8656b6039d9984cc32a843051abd --- .../facebook/react/runtime/ReactHostImpl.java | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 28c266a64c4e96..890458f1888a5e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -44,7 +44,6 @@ import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.UiThreadUtil; -import com.facebook.react.bridge.queue.QueueThreadExceptionHandler; import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; import com.facebook.react.common.build.ReactBuildConfig; @@ -72,8 +71,8 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -104,14 +103,10 @@ public class ReactHostImpl implements ReactHost { private final DevSupportManager mDevSupportManager; private final Executor mBGExecutor; private final Executor mUIExecutor; - private final QueueThreadExceptionHandler mQueueThreadExceptionHandler; - private final Set mAttachedSurfaces = - Collections.synchronizedSet(new HashSet<>()); + private final Set mAttachedSurfaces = new HashSet<>(); private final MemoryPressureRouter mMemoryPressureRouter; private final boolean mAllowPackagerServerAccess; private final boolean mUseDevSupport; - private final Collection mReactInstanceEventListeners = - Collections.synchronizedList(new ArrayList<>()); // todo: T192399917 This no longer needs to store the react instance private final BridgelessAtomicRef> mCreateReactInstanceTaskRef = @@ -133,8 +128,8 @@ public class ReactHostImpl implements ReactHost { private @Nullable MemoryPressureListener mMemoryPressureListener; private @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler; - private final Set> mBeforeDestroyListeners = - Collections.synchronizedSet(new HashSet<>()); + private final List mReactInstanceEventListeners = new ArrayList<>(); + private final List> mBeforeDestroyListeners = new ArrayList<>(); private @Nullable ReactHostInspectorTarget mReactHostInspectorTarget; @@ -167,7 +162,6 @@ public ReactHostImpl( mComponentFactory = componentFactory; mBGExecutor = bgExecutor; mUIExecutor = uiExecutor; - mQueueThreadExceptionHandler = ReactHostImpl.this::handleHostException; mMemoryPressureRouter = new MemoryPressureRouter(context); mAllowPackagerServerAccess = allowPackagerServerAccess; mUseDevSupport = useDevSupport; @@ -416,12 +410,16 @@ public boolean onBackPressed() { /** Add a listener to be notified of ReactInstance events. */ public void addReactInstanceEventListener(ReactInstanceEventListener listener) { - mReactInstanceEventListeners.add(listener); + synchronized (mReactInstanceEventListeners) { + mReactInstanceEventListeners.add(listener); + } } /** Remove a listener previously added with {@link #addReactInstanceEventListener}. */ public void removeReactInstanceEventListener(ReactInstanceEventListener listener) { - mReactInstanceEventListeners.remove(listener); + synchronized (mReactInstanceEventListeners) { + mReactInstanceEventListeners.remove(listener); + } } /** @@ -1067,7 +1065,7 @@ private Task getOrCreateReactInstanceTask() { mReactHostDelegate, mComponentFactory, devSupportManager, - mQueueThreadExceptionHandler, + this::handleHostException, mUseDevSupport, getOrCreateReactHostInspectorTarget()); mReactInstance = instance; @@ -1147,13 +1145,13 @@ class Result { reactContext, getCurrentActivity()); } - ReactInstanceEventListener[] listeners = - new ReactInstanceEventListener[mReactInstanceEventListeners.size()]; - final ReactInstanceEventListener[] finalListeners = - mReactInstanceEventListeners.toArray(listeners); - log(method, "Executing ReactInstanceEventListeners"); - for (ReactInstanceEventListener listener : finalListeners) { + ReactInstanceEventListener[] instanceEventListeners; + synchronized (mReactInstanceEventListeners) { + instanceEventListeners = + mReactInstanceEventListeners.toArray(new ReactInstanceEventListener[0]); + } + for (ReactInstanceEventListener listener : instanceEventListeners) { if (listener != null) { listener.onReactContextInitialized(reactContext); } @@ -1397,11 +1395,10 @@ private Task getOrCreateReloadTask(String reason) { reactInstanceTaskUnwrapper.unwrap( task, "3: Executing Before Destroy Listeners"); - Set> beforeDestroyListeners; + Function0[] beforeDestroyListeners; synchronized (mBeforeDestroyListeners) { - beforeDestroyListeners = new HashSet<>(mBeforeDestroyListeners); + beforeDestroyListeners = mBeforeDestroyListeners.toArray(new Function0[0]); } - for (Function0 destroyListener : beforeDestroyListeners) { destroyListener.invoke(); } From 82325b42602d72dc57bbcdb808620501c122c3af Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 19 Jun 2024 10:06:15 -0700 Subject: [PATCH 033/968] use feature flag in render function for optimized text (#45068) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45068 changelog: [internal] In D58672844 I added gating to module.exports. This gating is sensitive to when feature flags are initialised and causes test failures and regressions for developers. Let's move the feature flag check to component's render function. It introduces extra spread operator but it is good enough to compare new and old component. Reviewed By: GijsWeterings Differential Revision: D58783941 fbshipit-source-id: f89f4f48e6aeb774ed4a84483a9f4ad59d5bc045 --- packages/react-native/Libraries/Text/Text.js | 22 ++++++++++++++----- .../__snapshots__/public-api-test.js.snap | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js index bc68479ae4b3f6..807b1c73d165e7 100644 --- a/packages/react-native/Libraries/Text/Text.js +++ b/packages/react-native/Libraries/Text/Text.js @@ -19,6 +19,7 @@ import processColor from '../StyleSheet/processColor'; import Platform from '../Utilities/Platform'; import TextAncestor from './TextAncestor'; import {NativeText, NativeVirtualText} from './TextNativeComponent'; +import TextOptimized from './TextOptimized'; import * as React from 'react'; import {useContext, useMemo, useState} from 'react'; @@ -27,7 +28,7 @@ import {useContext, useMemo, useState} from 'react'; * * @see https://reactnative.dev/docs/text */ -const Text: React.AbstractComponent< +const TextLegacy: React.AbstractComponent< TextProps, React.ElementRef, > = React.forwardRef((props: TextProps, forwardedRef) => { @@ -308,7 +309,7 @@ const Text: React.AbstractComponent< ); }); -Text.displayName = 'Text'; +TextLegacy.displayName = 'TextLegacy'; /** * Returns false until the first time `newValue` is true, after which this will @@ -338,6 +339,17 @@ const verticalAlignToTextAlignVerticalMap = { middle: 'center', }; -module.exports = ((ReactNativeFeatureFlags.shouldUseOptimizedText() - ? require('./TextOptimized') - : Text): typeof Text); +const Text: React.AbstractComponent< + TextProps, + React.ElementRef, +> = React.forwardRef((props: TextProps, forwardedRef) => { + if (ReactNativeFeatureFlags.shouldUseOptimizedText()) { + return ; + } else { + return ; + } +}); + +Text.displayName = 'Text'; + +module.exports = Text; diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index ccd24bce524d68..cd9e2b44087649 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -8045,7 +8045,7 @@ exports[`public API should not change unintentionally Libraries/Text/Text.js 1`] TextProps, React.ElementRef, >; -declare module.exports: typeof Text; +declare module.exports: Text; " `; From 30087a6e00a6ee9456ccf20bf284f2593b3ba443 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Wed, 19 Jun 2024 10:11:14 -0700 Subject: [PATCH 034/968] Introduce FuseboxTracer for DevTools tracing (#44840) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44840 Changelog: [Internal] Introduce a simplified and minimal tracing backend for Fusebox. This backend is sufficient to implement a pretty usable performance panel. Although the more I see how easy this is and how annoying working with Perfetto is, the more I think we should just maintain this going forward. Anyways we can figure that out incrementally. For now the plan is still for this to be temporary. Reviewed By: motiz88 Differential Revision: D57981944 fbshipit-source-id: b3d8c6e8c5a18311bbe98254f8ddf3810fa1334b --- .../jsinspector-modern/CMakeLists.txt | 1 + .../jsinspector-modern/HostAgent.cpp | 46 +++++--- .../React-jsinspector.podspec | 1 + .../webperformance/NativePerformance.cpp | 14 ++- .../reactperflogger/CMakeLists.txt | 7 +- .../reactperflogger/React-perflogger.podspec | 18 +++- .../reactperflogger/fusebox/FuseboxTracer.cpp | 102 ++++++++++++++++++ .../reactperflogger/fusebox/FuseboxTracer.h | 52 +++++++++ .../fusebox/tests/FuseboxTracerTest.cpp | 90 ++++++++++++++++ 9 files changed, 313 insertions(+), 18 deletions(-) create mode 100644 packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.cpp create mode 100644 packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.h create mode 100644 packages/react-native/ReactCommon/reactperflogger/fusebox/tests/FuseboxTracerTest.cpp diff --git a/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt b/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt index cbbc44f6dd0162..73994bd2ecacfd 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt +++ b/packages/react-native/ReactCommon/jsinspector-modern/CMakeLists.txt @@ -23,4 +23,5 @@ target_link_libraries(jsinspector glog react_featureflags runtimeexecutor + reactperflogger ) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp index 46c1a94df312e1..260c5aadd6f584 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp @@ -15,6 +15,8 @@ #include +#include + using namespace std::chrono; using namespace std::literals::string_view_literals; @@ -146,25 +148,41 @@ void HostAgent::handleRequest(const cdp::PreparsedRequest& req) { shouldSendOKResponse = true; isFinishedHandlingRequest = true; } else if (req.method == "Tracing.start") { - // @cdp Tracing.start is implemented as a stub only. - frontendChannel_(cdp::jsonNotification( - // @cdp Tracing.bufferUsage is implemented as a stub only. - "Tracing.bufferUsage", - folly::dynamic::object("percentFull", 0)("eventCount", 0)("value", 0))); - shouldSendOKResponse = true; + // @cdp Tracing.start support is experimental. + if (FuseboxTracer::getFuseboxTracer().startTracing()) { + shouldSendOKResponse = true; + } else { + frontendChannel_(cdp::jsonError( + req.id, + cdp::ErrorCode::InternalError, + "Tracing session already started")); + return; + } isFinishedHandlingRequest = true; } else if (req.method == "Tracing.end") { - // @cdp Tracing.end is implemented as a stub only. - frontendChannel_(cdp::jsonNotification( - // @cdp Tracing.dataCollected is implemented as a stub only. - "Tracing.dataCollected", - folly::dynamic::object("value", folly::dynamic::array()))); + // @cdp Tracing.end support is experimental. + bool firstChunk = true; + auto id = req.id; + bool wasStopped = FuseboxTracer::getFuseboxTracer().stopTracing( + [this, firstChunk, id](const folly::dynamic& eventsChunk) { + if (firstChunk) { + frontendChannel_(cdp::jsonResult(id)); + } + frontendChannel_(cdp::jsonNotification( + "Tracing.dataCollected", + folly::dynamic::object("value", eventsChunk))); + }); + if (!wasStopped) { + frontendChannel_(cdp::jsonError( + req.id, + cdp::ErrorCode::InternalError, + "Tracing session not started")); + return; + } frontendChannel_(cdp::jsonNotification( - // @cdp Tracing.tracingComplete is implemented as a stub only. "Tracing.tracingComplete", folly::dynamic::object("dataLossOccurred", false))); - shouldSendOKResponse = true; - isFinishedHandlingRequest = true; + return; } if (!isFinishedHandlingRequest && instanceAgent_ && diff --git a/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec b/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec index 86783dcfd9b633..261c73b03595c2 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec +++ b/packages/react-native/ReactCommon/jsinspector-modern/React-jsinspector.podspec @@ -54,6 +54,7 @@ Pod::Spec.new do |s| s.dependency "DoubleConversion" s.dependency "React-runtimeexecutor", version s.dependency "React-jsi" + s.dependency "React-perflogger", version if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1" s.dependency "hermes-engine" end diff --git a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp index 1d8af0bcdb495a..91b2cac1a09744 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp @@ -15,7 +15,8 @@ #include #include #include - +#include +#include "NativePerformance.h" #include "Plugins.h" #ifdef WITH_PERFETTO @@ -112,6 +113,17 @@ void NativePerformance::measure( } } #endif + std::string trackName = "Web Performance"; + const int TRACK_PREFIX = 6; + if (name.starts_with("Track:")) { + const auto trackNameDelimiter = name.find(':', TRACK_PREFIX); + if (trackNameDelimiter != std::string::npos) { + trackName = name.substr(TRACK_PREFIX, trackNameDelimiter - TRACK_PREFIX); + name = name.substr(trackNameDelimiter + 1); + } + } + FuseboxTracer::getFuseboxTracer().addEvent( + name, (uint64_t)startTime, (uint64_t)endTime, trackName); PerformanceEntryReporter::getInstance()->measure( name, startTime, endTime, duration, startMark, endMark); } diff --git a/packages/react-native/ReactCommon/reactperflogger/CMakeLists.txt b/packages/react-native/ReactCommon/reactperflogger/CMakeLists.txt index 1f19cda575dfda..8f3226861b52ce 100644 --- a/packages/react-native/ReactCommon/reactperflogger/CMakeLists.txt +++ b/packages/react-native/ReactCommon/reactperflogger/CMakeLists.txt @@ -13,7 +13,12 @@ add_compile_options( -Wall -Wpedantic) -file(GLOB reactperflogger_SRC CONFIGURE_DEPENDS reactperflogger/*.cpp) + +file(GLOB reactperflogger_SRC CONFIGURE_DEPENDS + reactperflogger/*.cpp + fusebox/*.cpp) add_library(reactperflogger STATIC ${reactperflogger_SRC}) target_include_directories(reactperflogger PUBLIC .) + +target_link_libraries(reactperflogger folly_runtime) diff --git a/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec b/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec index e672bf66c8a35f..f94326abcdd898 100644 --- a/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec +++ b/packages/react-native/ReactCommon/reactperflogger/React-perflogger.podspec @@ -19,7 +19,13 @@ end folly_config = get_folly_config() folly_compiler_flags = folly_config[:compiler_flags] folly_version = folly_config[:version] -boost_compiler_flags = '-Wno-documentation' + +header_search_paths = [ + "\"$(PODS_TARGET_SRCROOT)/..\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/fmt/include\"" +] Pod::Spec.new do |s| s.name = "React-perflogger" @@ -30,7 +36,15 @@ Pod::Spec.new do |s| s.author = "Meta Platforms, Inc. and its affiliates" s.platforms = min_supported_versions s.source = source - s.source_files = "**/*.{cpp,h}" + s.source_files = "reactperflogger/*.{cpp,h}", "fusebox/*.{cpp,h}" s.header_dir = "reactperflogger" s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++20" } + s.compiler_flags = folly_compiler_flags + s.pod_target_xcconfig = { + "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", + "HEADER_SEARCH_PATHS" => header_search_paths.join(' '), + } + + s.dependency "RCT-Folly", folly_version + s.dependency "DoubleConversion" end diff --git a/packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.cpp b/packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.cpp new file mode 100644 index 00000000000000..263830c37fea66 --- /dev/null +++ b/packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +#include "FuseboxTracer.h" + +namespace facebook::react { + +bool FuseboxTracer::isTracing() { + std::lock_guard lock(mutex_); + return tracing_; +} + +bool FuseboxTracer::startTracing() { + std::lock_guard lock(mutex_); + if (tracing_) { + return false; + } + tracing_ = true; + return true; +} + +bool FuseboxTracer::stopTracing( + const std::function& + resultCallback) { + std::lock_guard lock(mutex_); + + if (!tracing_) { + return false; + } + + tracing_ = false; + if (buffer_.empty()) { + return true; + } + + auto traceEvents = folly::dynamic::array(); + auto savedBuffer = std::move(buffer_); + buffer_.clear(); + + std::unordered_map trackIdMap; + uint64_t nextTrack = 1000; + + // Name the main process. Only one process is supported currently. + traceEvents.push_back(folly::dynamic::object( + "args", folly::dynamic::object("name", "Main App"))("cat", "__metadata")( + "name", "process_name")("ph", "M")("pid", 1000)("tid", 0)("ts", 0)); + + for (auto& event : savedBuffer) { + if (!trackIdMap.contains(event.track)) { + auto trackId = nextTrack++; + trackIdMap[event.track] = trackId; + // New track + traceEvents.push_back(folly::dynamic::object( + "args", folly::dynamic::object("name", event.track))( + "cat", "__metadata")("name", "thread_name")("ph", "M")("pid", 1000)( + "tid", trackId)("ts", 0)); + } + auto trackId = trackIdMap[event.track]; + + // New event + traceEvents.push_back(folly::dynamic::object( + "args", folly::dynamic::object())("cat", "react.native")( + "dur", (event.end - event.start) * 1000)("name", event.name)("ph", "X")( + "ts", event.start * 1000)("pid", 1000)("tid", trackId)); + + if (traceEvents.size() >= 1000) { + resultCallback(traceEvents); + traceEvents = folly::dynamic::array(); + } + } + + if (traceEvents.size() >= 1) { + resultCallback(traceEvents); + } + return true; +} + +void FuseboxTracer::addEvent( + const std::string& name, + uint64_t start, + uint64_t end, + const std::string& track) { + std::lock_guard lock(mutex_); + if (!tracing_) { + return; + } + buffer_.push_back(BufferEvent{start, end, name, track}); +} + +/* static */ FuseboxTracer& FuseboxTracer::getFuseboxTracer() { + static FuseboxTracer tracer; + return tracer; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.h b/packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.h new file mode 100644 index 00000000000000..81c86a71799b59 --- /dev/null +++ b/packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include "folly/dynamic.h" + +namespace facebook::react { + +struct BufferEvent { + uint64_t start; + uint64_t end; + std::string name; + std::string track; +}; + +class FuseboxTracer { + public: + FuseboxTracer(const FuseboxTracer&) = delete; + + bool isTracing(); + // Verifies that tracing isn't started and starts tracing all in one step. + // Returns true if we were able to successful start tracing. + bool startTracing(); + // Verifies that we're tracing and dumps the trace all in one step to avoid + // TOCTOU bugs. Returns false if we're not tracing. No result callbacks + // are expected in that scenario. + bool stopTracing(const std::function& + resultCallback); + void addEvent( + const std::string& name, + uint64_t start, + uint64_t end, + const std::string& track); + + static FuseboxTracer& getFuseboxTracer(); + + private: + FuseboxTracer() {} + + bool tracing_{false}; + std::vector buffer_; + std::mutex mutex_; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/reactperflogger/fusebox/tests/FuseboxTracerTest.cpp b/packages/react-native/ReactCommon/reactperflogger/fusebox/tests/FuseboxTracerTest.cpp new file mode 100644 index 00000000000000..08facb1438a8ed --- /dev/null +++ b/packages/react-native/ReactCommon/reactperflogger/fusebox/tests/FuseboxTracerTest.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include + +using namespace ::testing; + +namespace facebook::react { + +namespace { + +class FuseboxTracerTest : public ::testing::Test { + protected: + FuseboxTracerTest() = default; + + ~FuseboxTracerTest() override = default; + + void SetUp() override { + stopTracingAndCollect(); + } + + void TearDown() override { + stopTracingAndCollect(); + } + + folly::dynamic stopTracingAndCollect() { + folly::dynamic trace = folly::dynamic::array; + FuseboxTracer::getFuseboxTracer().stopTracing( + [&trace](const folly::dynamic& eventsChunk) { + for (const auto& event : eventsChunk) { + trace.push_back(event); + } + }); + return trace; + } +}; + +} // namespace + +TEST_F(FuseboxTracerTest, TracingOffByDefault) { + EXPECT_FALSE(FuseboxTracer::getFuseboxTracer().isTracing()); +} + +TEST_F(FuseboxTracerTest, TracingOn) { + FuseboxTracer::getFuseboxTracer().startTracing(); + EXPECT_TRUE(FuseboxTracer::getFuseboxTracer().isTracing()); + stopTracingAndCollect(); +} + +TEST_F(FuseboxTracerTest, DiscardEventWhenNotOn) { + EXPECT_FALSE(FuseboxTracer::getFuseboxTracer().isTracing()); + EXPECT_EQ(stopTracingAndCollect().size(), 0); + FuseboxTracer::getFuseboxTracer().addEvent("test", 0, 0, "default track"); + FuseboxTracer::getFuseboxTracer().addEvent("test", 0, 0, "default track"); + EXPECT_EQ(stopTracingAndCollect().size(), 0); +} + +TEST_F(FuseboxTracerTest, NoDefaultEvents) { + FuseboxTracer::getFuseboxTracer().startTracing(); + EXPECT_EQ(stopTracingAndCollect().size(), 0); +} + +TEST_F(FuseboxTracerTest, SimpleEvent) { + FuseboxTracer::getFuseboxTracer().startTracing(); + FuseboxTracer::getFuseboxTracer().addEvent("test", 0, 0, "default track"); + EXPECT_GE(stopTracingAndCollect().size(), 1); +} + +TEST_F(FuseboxTracerTest, MultiEvents) { + FuseboxTracer::getFuseboxTracer().startTracing(); + for (int i = 0; i < 10; i++) { + FuseboxTracer::getFuseboxTracer().addEvent("test", 0, 0, "default track"); + } + EXPECT_GE(stopTracingAndCollect().size(), 10); + EXPECT_EQ(stopTracingAndCollect().size(), 0); +} + +TEST_F(FuseboxTracerTest, ShouldEndTracingEvenIfThereIsNoEvents) { + FuseboxTracer::getFuseboxTracer().startTracing(); + EXPECT_EQ(stopTracingAndCollect().size(), 0); + EXPECT_FALSE(FuseboxTracer::getFuseboxTracer().isTracing()); +} + +} // namespace facebook::react From 53951d7fec2997487d1ee948304ab904c21338aa Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Wed, 19 Jun 2024 11:28:36 -0700 Subject: [PATCH 035/968] Debugger: Make /json/list ordered (#45069) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45069 Currently, `/json/list` returns pages within each device in the iteration order of a C++ `unordered_map`, which doesn't tell us anything useful. Page IDs happen to be sequential, but only as an implementation detail. Change this contract so that we guarantee ordering reflects addition order, allowing clients to consistently select e.g. most recently added page for a given device. The implementation of this is as simple as switching from an `unordered_map` to a key-ordered`map`, because we already assign keys (page IDs) with an incrementing integer. Within the inspector proxy, devices already use an insertion (connection)-ordered JS `Map`, so we just document this guarantee. Changelog: [General][Changed] Debugger: Make `/json/list` return connection-addition-ordered targets. Reviewed By: huntie Differential Revision: D58735947 fbshipit-source-id: 7a132cc5e750475792a2b845afc9a42424690bf1 --- .../src/inspector-proxy/Device.js | 1 + .../src/inspector-proxy/InspectorProxy.js | 4 ++ .../InspectorInterfaces.cpp | 6 ++- .../jsinspector-modern/InspectorInterfaces.h | 6 ++- .../tests/InspectorPackagerConnectionTest.cpp | 41 +++++++++++++------ 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 8542adcfd0491e..7be749d07cd93c 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -491,6 +491,7 @@ export default class Device { // locations). async #handleMessageFromDevice(message: MessageFromDevice) { if (message.event === 'getPages') { + // Preserve ordering - getPages guarantees addition order. this.#pages = new Map( message.payload.map(({capabilities, ...page}) => [ page.id, diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index d33750b3ecd4f6..8c692f06e51bed 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -43,6 +43,10 @@ const DEBUGGER_HEARTBEAT_INTERVAL_MS = 10000; const INTERNAL_ERROR_CODE = 1011; export interface InspectorProxyQueries { + /** + * Returns list of page descriptions ordered by device connection order, then + * page addition order. + */ getPageDescriptions(): Array; } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp index 2958055938990d..9efdfcd85cf21e 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp @@ -73,7 +73,7 @@ class InspectorImpl : public IInspector { }; mutable std::mutex mutex_; int nextPageId_{1}; - std::unordered_map pages_; + std::map pages_; std::list> listeners_; }; @@ -109,6 +109,8 @@ int InspectorImpl::addPage( InspectorTargetCapabilities capabilities) { std::scoped_lock lock(mutex_); + // Note: getPages guarantees insertion/addition order. As an implementation + // detail, incrementing page IDs takes advantage of std::map's key ordering. int pageId = nextPageId_++; assert(pages_.count(pageId) == 0 && "Unexpected duplicate page ID"); pages_.emplace( @@ -133,6 +135,8 @@ std::vector InspectorImpl::getPages() const { std::scoped_lock lock(mutex_); std::vector inspectorPages; + // pages_ is a std::map keyed on an incremental id, so this is insertion + // ordered. for (auto& it : pages_) { inspectorPages.push_back(InspectorPageDescription(it.second)); } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h b/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h index 86c9a4b03b9d03..68ef76de1f3df1 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h @@ -109,7 +109,11 @@ class JSINSPECTOR_EXPORT IInspector : public IDestructible { /// debuggable pages. virtual void removePage(int pageId) = 0; - /// getPages is called by the client to list all debuggable pages. + /** + * Called by the client to retrieve all debuggable pages. + * \returns A vector of page descriptions in the order in which they were + * added with \c addPage. + */ virtual std::vector getPages() const = 0; /** diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorPackagerConnectionTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorPackagerConnectionTest.cpp index db23471a638259..bc7a14814931c2 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorPackagerConnectionTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorPackagerConnectionTest.cpp @@ -199,34 +199,51 @@ TEST_F(InspectorPackagerConnectionTest, TestGetPages) { "event": "getPages" })"); - auto pageId = getInspectorInstance().addPage( - "mock-title", + auto pageId1 = getInspectorInstance().addPage( + "mock-title-1", + "mock-vm", + localConnections_ + .lazily_make_unique>(), + {.nativePageReloads = true}); + + auto pageId2 = getInspectorInstance().addPage( + "mock-title-2", "mock-vm", localConnections_ .lazily_make_unique>(), {.nativePageReloads = true}); - // getPages now reports the page we registered. + // getPages now reports the page we registered, in the order added EXPECT_CALL( *webSockets_[0], send(JsonParsed(AllOf( AtJsonPtr("/event", Eq("getPages")), AtJsonPtr( "/payload", - ElementsAreArray({AllOf( - AtJsonPtr("/app", Eq("my-app")), - AtJsonPtr("/title", Eq("mock-title [C++ connection]")), - AtJsonPtr("/id", Eq(std::to_string(pageId))), - AtJsonPtr("/capabilities/nativePageReloads", Eq(true)), - AtJsonPtr( - "/capabilities/nativeSourceCodeFetching", - Eq(false)))})))))) + ElementsAreArray( + {AllOf( + AtJsonPtr("/app", Eq("my-app")), + AtJsonPtr("/title", Eq("mock-title-1 [C++ connection]")), + AtJsonPtr("/id", Eq(std::to_string(pageId1))), + AtJsonPtr("/capabilities/nativePageReloads", Eq(true)), + AtJsonPtr( + "/capabilities/nativeSourceCodeFetching", + Eq(false))), + AllOf( + AtJsonPtr("/app", Eq("my-app")), + AtJsonPtr("/title", Eq("mock-title-2 [C++ connection]")), + AtJsonPtr("/id", Eq(std::to_string(pageId2))), + AtJsonPtr("/capabilities/nativePageReloads", Eq(true)), + AtJsonPtr( + "/capabilities/nativeSourceCodeFetching", + Eq(false)))})))))) .RetiresOnSaturation(); webSockets_[0]->getDelegate().didReceiveMessage(R"({ "event": "getPages" })"); - getInspectorInstance().removePage(pageId); + getInspectorInstance().removePage(pageId1); + getInspectorInstance().removePage(pageId2); // getPages is back to reporting no pages. EXPECT_CALL( From 2a6a895b17fdd4112349853e08a50c4c90886cb8 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Wed, 19 Jun 2024 11:28:36 -0700 Subject: [PATCH 036/968] Debugger: `j` opens debugger on most recently connected target (#45060) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45060 Currently, `j`, (i.e., `/open-debugger` with no parameters), connects the "first available" target, which in practice is the first page of the first connected device still connected. In the absence of a target selection UI, a better guess at user intent is to use the *latest* target (most recently added page of most recently connected device). Also slightly reduces CLI noise by not claiming that we're launching a debugger when there's no target, and not qualifying which target when there's only one. Changelog: [General][Changed] Debugger: `j` opens most recent (not first) target. Reviewed By: huntie Differential Revision: D58736151 fbshipit-source-id: 3d106a1fa958f9e5c91b16e04075609e1abf6e97 --- .../dev-middleware/src/middleware/openDebuggerMiddleware.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js b/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js index 22105f07d5ba4a..7aa102ab7baa3c 100644 --- a/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js +++ b/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js @@ -86,12 +86,12 @@ export default function openDebuggerMiddleware({ if (!target && typeof appId === 'string') { target = targets.find(_target => _target.description === appId); } - } else { + } else if (targets.length > 0) { logger?.info( (launchType === 'launch' ? 'Launching' : 'Redirecting to') + - ' JS debugger for first available target...', + ` JS debugger${targets.length === 1 ? '' : ' for most recently connected target'}...`, ); - target = targets[0]; + target = targets[targets.length - 1]; } if (!target) { From e5c7eb57e2f61243b4f63e734e3675a1fbf5cde6 Mon Sep 17 00:00:00 2001 From: Edmond Chui Date: Thu, 20 Jun 2024 02:46:03 -0700 Subject: [PATCH 037/968] Update debugger-frontend from f7e972c...750ed14 (#45074) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45074 Changelog: [Internal] - Update `react-native/debugger-frontend` from f7e972c...750ed14 Resyncs `react-native/debugger-frontend` from GitHub - see `rn-chrome-devtools-frontend` [changelog](https://github.com/facebookexperimental/rn-chrome-devtools-frontend/compare/f7e972ce2917749a125fc0871781d9307ca336e8...750ed147da1c0edd118f359f906d5c7553c338a8). Reviewed By: vzaidman Differential Revision: D58790390 fbshipit-source-id: b6b15ecbd521cdb231aa9d21135aacc39f31a425 --- packages/debugger-frontend/BUILD_INFO | 4 ++-- .../dist/third-party/front_end/core/host/host.js | 2 +- .../front_end/entrypoints/rn_fusebox/rn_fusebox.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/debugger-frontend/BUILD_INFO b/packages/debugger-frontend/BUILD_INFO index 789c9b30ed417e..63df8286037b62 100644 --- a/packages/debugger-frontend/BUILD_INFO +++ b/packages/debugger-frontend/BUILD_INFO @@ -1,5 +1,5 @@ -@generated SignedSource<> -Git revision: f7e972ce2917749a125fc0871781d9307ca336e8 +@generated SignedSource<<8a7e1344ddeadab69e7df05782ae8b45>> +Git revision: 750ed147da1c0edd118f359f906d5c7553c338a8 Built with --nohooks: false Is local checkout: false Remote URL: https://github.com/facebookexperimental/rn-chrome-devtools-frontend diff --git a/packages/debugger-frontend/dist/third-party/front_end/core/host/host.js b/packages/debugger-frontend/dist/third-party/front_end/core/host/host.js index a608b7541fe6ab..14d2b17a6a00bc 100644 --- a/packages/debugger-frontend/dist/third-party/front_end/core/host/host.js +++ b/packages/debugger-frontend/dist/third-party/front_end/core/host/host.js @@ -1 +1 @@ -import*as e from"../platform/platform.js";import*as r from"../root/root.js";import*as o from"../common/common.js";import*as t from"../i18n/i18n.js";var n;!function(e){e.AppendedToURL="appendedToURL",e.CanceledSaveURL="canceledSaveURL",e.ColorThemeChanged="colorThemeChanged",e.ContextMenuCleared="contextMenuCleared",e.ContextMenuItemSelected="contextMenuItemSelected",e.DeviceCountUpdated="deviceCountUpdated",e.DevicesDiscoveryConfigChanged="devicesDiscoveryConfigChanged",e.DevicesPortForwardingStatusChanged="devicesPortForwardingStatusChanged",e.DevicesUpdated="devicesUpdated",e.DispatchMessage="dispatchMessage",e.DispatchMessageChunk="dispatchMessageChunk",e.EnterInspectElementMode="enterInspectElementMode",e.EyeDropperPickedColor="eyeDropperPickedColor",e.FileSystemsLoaded="fileSystemsLoaded",e.FileSystemRemoved="fileSystemRemoved",e.FileSystemAdded="fileSystemAdded",e.FileSystemFilesChangedAddedRemoved="FileSystemFilesChangedAddedRemoved",e.IndexingTotalWorkCalculated="indexingTotalWorkCalculated",e.IndexingWorked="indexingWorked",e.IndexingDone="indexingDone",e.KeyEventUnhandled="keyEventUnhandled",e.ReattachRootTarget="reattachMainTarget",e.ReloadInspectedPage="reloadInspectedPage",e.RevealSourceLine="revealSourceLine",e.SavedURL="savedURL",e.SearchCompleted="searchCompleted",e.SetInspectedTabId="setInspectedTabId",e.SetUseSoftMenu="setUseSoftMenu",e.ShowPanel="showPanel"}(n||(n={}));const s=[[n.AppendedToURL,"appendedToURL",["url"]],[n.CanceledSaveURL,"canceledSaveURL",["url"]],[n.ColorThemeChanged,"colorThemeChanged",[]],[n.ContextMenuCleared,"contextMenuCleared",[]],[n.ContextMenuItemSelected,"contextMenuItemSelected",["id"]],[n.DeviceCountUpdated,"deviceCountUpdated",["count"]],[n.DevicesDiscoveryConfigChanged,"devicesDiscoveryConfigChanged",["config"]],[n.DevicesPortForwardingStatusChanged,"devicesPortForwardingStatusChanged",["status"]],[n.DevicesUpdated,"devicesUpdated",["devices"]],[n.DispatchMessage,"dispatchMessage",["messageObject"]],[n.DispatchMessageChunk,"dispatchMessageChunk",["messageChunk","messageSize"]],[n.EnterInspectElementMode,"enterInspectElementMode",[]],[n.EyeDropperPickedColor,"eyeDropperPickedColor",["color"]],[n.FileSystemsLoaded,"fileSystemsLoaded",["fileSystems"]],[n.FileSystemRemoved,"fileSystemRemoved",["fileSystemPath"]],[n.FileSystemAdded,"fileSystemAdded",["errorMessage","fileSystem"]],[n.FileSystemFilesChangedAddedRemoved,"fileSystemFilesChangedAddedRemoved",["changed","added","removed"]],[n.IndexingTotalWorkCalculated,"indexingTotalWorkCalculated",["requestId","fileSystemPath","totalWork"]],[n.IndexingWorked,"indexingWorked",["requestId","fileSystemPath","worked"]],[n.IndexingDone,"indexingDone",["requestId","fileSystemPath"]],[n.KeyEventUnhandled,"keyEventUnhandled",["event"]],[n.ReattachRootTarget,"reattachMainTarget",[]],[n.ReloadInspectedPage,"reloadInspectedPage",["hard"]],[n.RevealSourceLine,"revealSourceLine",["url","lineNumber","columnNumber"]],[n.SavedURL,"savedURL",["url","fileSystemPath"]],[n.SearchCompleted,"searchCompleted",["requestId","fileSystemPath","files"]],[n.SetInspectedTabId,"setInspectedTabId",["tabId"]],[n.SetUseSoftMenu,"setUseSoftMenu",["useSoftMenu"]],[n.ShowPanel,"showPanel",["panelName"]]];var i=Object.freeze({__proto__:null,get Events(){return n},EventDescriptors:s});const a={systemError:"System error",connectionError:"Connection error",certificateError:"Certificate error",httpError:"HTTP error",cacheError:"Cache error",signedExchangeError:"Signed Exchange error",ftpError:"FTP error",certificateManagerError:"Certificate manager error",dnsResolverError:"DNS resolver error",unknownError:"Unknown error",httpErrorStatusCodeSS:"HTTP error: status code {PH1}, {PH2}",invalidUrl:"Invalid URL",decodingDataUrlFailed:"Decoding Data URL failed"},d=t.i18n.registerUIStrings("core/host/ResourceLoader.ts",a),c=t.i18n.getLocalizedString.bind(void 0,d);let l=0;const u={},m=function(e){return u[++l]=e,l},g=function(e){u[e].close(),delete u[e]},p=function(e,r){u[e].write(r)};let h=function(e,r,t,n){const s=new o.StringOutputStream.StringOutputStream;w(e,r,s,(function(e,r,o){t(e,r,s.data(),o)}),n)};function v(e,r,o){if(void 0===e||void 0===o)return null;if(0!==e){if(function(e){return e<=-300&&e>-400}(e))return c(a.httpErrorStatusCodeSS,{PH1:String(r),PH2:o});const t=function(e){return c(e>-100?a.systemError:e>-200?a.connectionError:e>-300?a.certificateError:e>-400?a.httpError:e>-500?a.cacheError:e>-600?a.signedExchangeError:e>-700?a.ftpError:e>-800?a.certificateManagerError:e>-900?a.dnsResolverError:a.unknownError)}(e);return`${t}: ${o}`}return null}const w=function(e,r,t,n,s){const i=m(t);if(new o.ParsedURL.ParsedURL(e).isDataURL())return void(e=>new Promise(((r,o)=>{const t=new XMLHttpRequest;t.withCredentials=!1,t.open("GET",e,!0),t.onreadystatechange=function(){if(t.readyState===XMLHttpRequest.DONE){if(200!==t.status)return t.onreadystatechange=null,void o(new Error(String(t.status)));t.onreadystatechange=null,r(t.responseText)}},t.send(null)})))(e).then((function(e){p(i,e),l({statusCode:200})})).catch((function(e){l({statusCode:404,messageOverride:c(a.decodingDataUrlFailed)})}));if(!s&&function(e){try{const r=new URL(e);return"file:"===r.protocol&&""!==r.host}catch(e){return!1}}(e))return void(n&&n(!1,{},{statusCode:400,netError:-20,netErrorName:"net::BLOCKED_BY_CLIENT",message:"Loading from a remote file path is prohibited for security reasons."}));const d=[];if(r)for(const e in r)d.push(e+": "+r[e]);function l(e){if(n){const{success:r,description:o}=function(e){const{statusCode:r,netError:o,netErrorName:t,urlValid:n,messageOverride:s}=e;let i="";const d=r>=200&&r<300;if("string"==typeof s)i=s;else if(!d)if(void 0===o)i=c(!1===n?a.invalidUrl:a.unknownError);else{const e=v(o,r,t);e&&(i=e)}return console.assert(d===(0===i.length)),{success:d,description:{statusCode:r,netError:o,netErrorName:t,urlValid:n,message:i}}}(e);n(r,e.headers||{},o)}g(i)}I.loadNetworkResource(e,d.join("\r\n"),i,l)};var C=Object.freeze({__proto__:null,ResourceLoader:{},bindOutputStream:m,discardOutputStream:g,streamWrite:p,get load(){return h},setLoadForTest:function(e){h=e},netErrorToMessage:v,loadAsStream:w});const k={devtoolsS:"DevTools - {PH1}"},S=t.i18n.registerUIStrings("core/host/InspectorFrontendHost.ts",k),f=t.i18n.getLocalizedString.bind(void 0,S),y="/overrides";class b{#e;events;#r=null;recordedCountHistograms=[];recordedEnumeratedHistograms=[];recordedPerformanceHistograms=[];constructor(){function e(e){!("mac"===this.platform()?e.metaKey:e.ctrlKey)||"+"!==e.key&&"-"!==e.key||e.stopPropagation()}this.#e=new Map,"undefined"!=typeof document&&document.addEventListener("keydown",(r=>{e.call(this,r)}),!0)}platform(){const e=navigator.userAgent;return e.includes("Windows NT")?"windows":e.includes("Mac OS X")?"mac":"linux"}loadCompleted(){}bringToFront(){}closeWindow(){}setIsDocked(e,r){window.setTimeout(r,0)}showSurvey(e,r){window.setTimeout((()=>r({surveyShown:!1})),0)}canShowSurvey(e,r){window.setTimeout((()=>r({canShowSurvey:!1})),0)}setInspectedPageBounds(e){}inspectElementCompleted(){}setInjectedScriptForOrigin(e,r){}inspectedURLChanged(e){document.title=f(k.devtoolsS,{PH1:e.replace(/^https?:\/\//,"")})}copyText(e){null!=e&&navigator.clipboard.writeText(e)}openInNewTab(e){window.open(e,"_blank")}openSearchResultsInNewTab(e){o.Console.Console.instance().error("Search is not enabled in hosted mode. Please inspect using chrome://inspect")}showItemInFolder(e){o.Console.Console.instance().error("Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect")}save(e,r,o){let t=this.#e.get(e);t||(t=[],this.#e.set(e,t)),t.push(r),this.events.dispatchEventToListeners(n.SavedURL,{url:e,fileSystemPath:e})}append(e,r){const o=this.#e.get(e);o&&(o.push(r),this.events.dispatchEventToListeners(n.AppendedToURL,e))}close(r){const o=this.#e.get(r)||[];this.#e.delete(r);let t="";if(r)try{const o=e.StringUtilities.trimURL(r);t=e.StringUtilities.removeURLFragment(o)}catch(e){t=r}const n=document.createElement("a");n.download=t;const s=new Blob([o.join("")],{type:"text/plain"}),i=URL.createObjectURL(s);n.href=i,n.click(),URL.revokeObjectURL(i)}sendMessageToBackend(e){}recordCountHistogram(e,r,o,t,n){this.recordedCountHistograms.length>=100&&this.recordedCountHistograms.shift(),this.recordedCountHistograms.push({histogramName:e,sample:r,min:o,exclusiveMax:t,bucketSize:n})}recordEnumeratedHistogram(e,r,o){this.recordedEnumeratedHistograms.length>=100&&this.recordedEnumeratedHistograms.shift(),this.recordedEnumeratedHistograms.push({actionName:e,actionCode:r})}recordPerformanceHistogram(e,r){this.recordedPerformanceHistograms.length>=100&&this.recordedPerformanceHistograms.shift(),this.recordedPerformanceHistograms.push({histogramName:e,duration:r})}recordUserMetricsAction(e){}requestFileSystems(){this.events.dispatchEventToListeners(n.FileSystemsLoaded,[])}addFileSystem(e){window.webkitRequestFileSystem(window.TEMPORARY,1048576,(e=>{this.#r=e;const r={fileSystemName:"sandboxedRequestedFileSystem",fileSystemPath:y,rootURL:"filesystem:devtools://devtools/isolated/",type:"overrides"};this.events.dispatchEventToListeners(n.FileSystemAdded,{fileSystem:r})}))}removeFileSystem(e){const r=e=>{e.forEach((e=>{e.isDirectory?e.removeRecursively((()=>{})):e.isFile&&e.remove((()=>{}))}))};this.#r&&this.#r.root.createReader().readEntries(r),this.#r=null,this.events.dispatchEventToListeners(n.FileSystemRemoved,y)}isolatedFileSystem(e,r){return this.#r}loadNetworkResource(e,r,o,t){fetch(e).then((async e=>{const r=await e.arrayBuffer();let o=r;if(function(e){const r=new Uint8Array(e);return!(!r||r.length<3)&&31===r[0]&&139===r[1]&&8===r[2]}(r)){const e=new DecompressionStream("gzip"),t=e.writable.getWriter();t.write(r),t.close(),o=e.readable}return await new Response(o).text()})).then((function(e){p(o,e),t({statusCode:200,headers:void 0,messageOverride:void 0,netError:void 0,netErrorName:void 0,urlValid:void 0})})).catch((function(){t({statusCode:404,headers:void 0,messageOverride:void 0,netError:void 0,netErrorName:void 0,urlValid:void 0})}))}registerPreference(e,r){}getPreferences(e){const r={};for(const e in window.localStorage)r[e]=window.localStorage[e];e(r)}getPreference(e,r){r(window.localStorage[e])}setPreference(e,r){window.localStorage[e]=r}removePreference(e){delete window.localStorage[e]}clearPreferences(){window.localStorage.clear()}getSyncInformation(e){e({isSyncActive:!1,arePreferencesSynced:!1})}upgradeDraggedFileSystemPermissions(e){}indexPath(e,r,o){}stopIndexing(e){}searchInPath(e,r,o){}zoomFactor(){return 1}zoomIn(){}zoomOut(){}resetZoom(){}setWhitelistedShortcuts(e){}setEyeDropperActive(e){}showCertificateViewer(e){}reattach(e){e()}readyForTest(){}connectionReady(){}setOpenNewWindowForPopups(e){}setDevicesDiscoveryConfig(e){}setDevicesUpdatesEnabled(e){}performActionOnRemotePage(e,r){}openRemotePage(e,r){}openNodeFrontend(){}showContextMenuAtPoint(e,r,o,t){throw"Soft context menu should be used"}isHostedMode(){return!0}setAddExtensionCallback(e){}async initialTargetId(){return null}doAidaConversation(e,r,o){o({error:"Not implemened"})}registerAidaClientEvent(e){}recordImpression(e){}recordResize(e){}recordClick(e){}recordHover(e){}recordDrag(e){}recordChange(e){}recordKeyDown(e){}}let I=globalThis.InspectorFrontendHost;class x{constructor(){for(const e of s)this[e[1]]=this.dispatch.bind(this,e[0],e[2],e[3])}dispatch(e,r,o,...t){if(r.length<2){try{I.events.dispatchEventToListeners(e,t[0])}catch(e){console.error(e+" "+e.stack)}return}const n={};for(let e=0;e{let{promise:r,resolve:o,reject:t}=e.PromiseUtilities.promiseWithResolvers();return{write:async n=>{o(n),({promise:r,resolve:o,reject:t}=e.PromiseUtilities.promiseWithResolvers())},close:async()=>{o(null)},read:()=>r,fail:e=>t(e)}})(),t=m(o);let n;I.doAidaConversation(JSON.stringify(P.buildApiRequest(r)),t,(e=>{403===e.statusCode?o.fail(new Error("Server responded: permission denied")):e.error?o.fail(new Error(`Cannot send request: ${e.error} ${e.detail||""}`)):200!==e.statusCode?o.fail(new Error(`Request failed: ${JSON.stringify(e)}`)):o.close()}));const s=[];let i=!1;for(;n=await o.read();){if(!n.length)continue;let e;n.startsWith(",")&&(n=n.slice(1)),n.startsWith("[")||(n="["+n),n.endsWith("]")||(n+="]");try{e=JSON.parse(n)}catch(e){throw new Error("Cannot parse chunk: "+n,{cause:e})}const r="\n`````\n";for(const o of e)if("textChunk"in o)i&&(s.push(r),i=!1),s.push(o.textChunk.text);else{if(!("codeChunk"in o))throw"error"in o?new Error(`Server responded: ${JSON.stringify(o)}`):new Error("Unknown chunk result");i||(s.push(r),i=!0),s.push(o.codeChunk.code)}yield{explanation:s.join("")+(i?r:""),metadata:{rpcGlobalId:e[0]?.metadata?.rpcGlobalId}}}}}var T=Object.freeze({__proto__:null,AidaClient:P});let R,M,F,D,O;function _(){return R||(R=I.platform()),R}var H=Object.freeze({__proto__:null,platform:_,isMac:function(){return void 0===M&&(M="mac"===_()),M},isWin:function(){return void 0===F&&(F="windows"===_()),F},setPlatformForTests:function(e){R=e,M=void 0,F=void 0},isCustomDevtoolsFrontend:function(){return void 0===D&&(D=window.location.toString().startsWith("devtools://devtools/custom/")),D},fontFamily:function(){if(O)return O;switch(_()){case"linux":O="Roboto, Ubuntu, Arial, sans-serif";break;case"mac":O="'Lucida Grande', sans-serif";break;case"windows":O="'Segoe UI', Tahoma, sans-serif"}return O}});let A=null;function L(){return null===A&&(A=new N),A}class N{#o="error";#t=new Set;#n=null;addEventListener(e){this.#t.add(e);return()=>{this.#t.delete(e)}}removeAllEventListeners(){this.#t.clear()}sendEvent(e){if(!0!==globalThis.enableReactNativePerfMetrics)return;const r=this.#s(e),o=[];for(const e of this.#t)try{e(r)}catch(e){o.push(e)}if(o.length>0){const e=new AggregateError(o);console.error("Error occurred when calling event listeners",e)}}registerPerfMetricsGlobalPostMessageHandler(){!0===globalThis.enableReactNativePerfMetrics&&!0===globalThis.enableReactNativePerfMetricsGlobalPostMessage&&this.addEventListener((e=>{window.postMessage({event:e,tag:"react-native-chrome-devtools-perf-metrics"},window.location.origin)}))}registerGlobalErrorReporting(){window.addEventListener("error",(e=>{const[r,o]=W(`[RNPerfMetrics] uncaught error: ${e.message}`,e.error);this.sendEvent({eventName:"Browser.Error",params:{type:"error",message:r,error:o}})}),{passive:!0}),window.addEventListener("unhandledrejection",(e=>{const[r,o]=W("[RNPerfMetrics] unhandled promise rejection",e.reason);this.sendEvent({eventName:"Browser.Error",params:{type:"rejectedPromise",message:r,error:o}})}),{passive:!0});const e=globalThis.console,r=e[this.#o];e[this.#o]=(...o)=>{try{const e=o[0],[r,t]=W("[RNPerfMetrics] console.error",e);this.sendEvent({eventName:"Browser.Error",params:{message:r,error:t,type:"consoleError"}})}catch(e){const[r,o]=W("[RNPerfMetrics] Error handling console.error",e);this.sendEvent({eventName:"Browser.Error",params:{message:r,error:o,type:"consoleError"}})}finally{r.apply(e,o)}}}setLaunchId(e){this.#n=e}entryPointLoadingStarted(e){this.sendEvent({eventName:"Entrypoint.LoadingStarted",entryPoint:e})}entryPointLoadingFinished(e){this.sendEvent({eventName:"Entrypoint.LoadingFinished",entryPoint:e})}browserVisibilityChanged(e){this.sendEvent({eventName:"Browser.VisibilityChange",params:{visibilityState:e}})}remoteDebuggingTerminated(e){this.sendEvent({eventName:"Connection.DebuggingTerminated",params:{reason:e}})}developerResourceLoadingStarted(e,r){const o=U(e);this.sendEvent({eventName:"DeveloperResource.LoadingStarted",params:{url:o,loadingMethod:r}})}developerResourceLoadingFinished(e,r,o){const t=U(e);this.sendEvent({eventName:"DeveloperResource.LoadingFinished",params:{url:t,loadingMethod:r,success:o.success,errorMessage:o.errorDescription?.message}})}#s(e){return{...e,...{timestamp:performance.timeOrigin+performance.now(),launchId:this.#n}}}}function U(e){const{url:r}=e;return e.isHttpOrHttps()?r:`${r.slice(0,100)} …(omitted ${r.length-100} characters)`}function W(e,r){if(r instanceof Error){return[`${e}: ${r.message}`,r]}const o=`${e}: ${String(r)}`;return[o,new Error(o,{cause:r})]}var V,B,j,q,G,z,$,X,K,Q,J,Y,Z,ee,re,oe,te=Object.freeze({__proto__:null,getInstance:L});class ne{#i;#a;#d;constructor(){this.#i=!1,this.#a=!1,this.#d=""}breakpointWithConditionAdded(e){e>=2||I.recordEnumeratedHistogram("DevTools.BreakpointWithConditionAdded",e,2)}breakpointEditDialogRevealedFrom(e){e>=7||I.recordEnumeratedHistogram("DevTools.BreakpointEditDialogRevealedFrom",e,7)}panelShown(e,r){const o=B[e]||0;I.recordEnumeratedHistogram("DevTools.PanelShown",o,B.MaxValue),I.recordUserMetricsAction("DevTools_PanelShown_"+e),r||(this.#i=!0)}panelClosed(e){const r=B[e]||0;I.recordEnumeratedHistogram("DevTools.PanelClosed",r,B.MaxValue),this.#i=!0}panelShownInLocation(e,r){const o=j[`${e}-${r}`]||0;I.recordEnumeratedHistogram("DevTools.PanelShownInLocation",o,j.MaxValue)}elementsSidebarTabShown(e){const r=q[e]||0;I.recordEnumeratedHistogram("DevTools.Elements.SidebarTabShown",r,q.MaxValue)}sourcesSidebarTabShown(e){const r=G[e]||0;I.recordEnumeratedHistogram("DevTools.Sources.SidebarTabShown",r,G.MaxValue)}settingsPanelShown(e){this.panelShown("settings-"+e)}sourcesPanelFileDebugged(e){const r=e&&z[e]||z.Unknown;I.recordEnumeratedHistogram("DevTools.SourcesPanelFileDebugged",r,z.MaxValue)}sourcesPanelFileOpened(e){const r=e&&z[e]||z.Unknown;I.recordEnumeratedHistogram("DevTools.SourcesPanelFileOpened",r,z.MaxValue)}networkPanelResponsePreviewOpened(e){const r=e&&z[e]||z.Unknown;I.recordEnumeratedHistogram("DevTools.NetworkPanelResponsePreviewOpened",r,z.MaxValue)}actionTaken(e){I.recordEnumeratedHistogram("DevTools.ActionTaken",e,V.MaxValue)}panelLoaded(e,r){this.#a||e!==this.#d||(this.#a=!0,requestAnimationFrame((()=>{window.setTimeout((()=>{performance.mark(r),this.#i||I.recordPerformanceHistogram(r,performance.now())}),0)})))}setLaunchPanel(e){this.#d=e}performanceTraceLoad(e){I.recordPerformanceHistogram("DevTools.TraceLoad",e.duration)}keybindSetSettingChanged(e){const r=$[e]||0;I.recordEnumeratedHistogram("DevTools.KeybindSetSettingChanged",r,$.MaxValue)}keyboardShortcutFired(e){const r=X[e]||X.OtherShortcut;I.recordEnumeratedHistogram("DevTools.KeyboardShortcutFired",r,X.MaxValue)}issuesPanelOpenedFrom(e){I.recordEnumeratedHistogram("DevTools.IssuesPanelOpenedFrom",e,6)}issuesPanelIssueExpanded(e){if(void 0===e)return;const r=Q[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.IssuesPanelIssueExpanded",r,Q.MaxValue)}issuesPanelResourceOpened(e,r){const o=J[e+r];void 0!==o&&I.recordEnumeratedHistogram("DevTools.IssuesPanelResourceOpened",o,J.MaxValue)}issueCreated(e){const r=Y[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.IssueCreated",r,Y.MaxValue)}experimentEnabledAtLaunch(e){const r=K[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.ExperimentEnabledAtLaunch",r,K.MaxValue)}experimentDisabledAtLaunch(e){const r=K[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.ExperimentDisabledAtLaunch",r,K.MaxValue)}experimentChanged(e,r){const o=K[e];if(void 0===o)return;const t=r?"DevTools.ExperimentEnabled":"DevTools.ExperimentDisabled";I.recordEnumeratedHistogram(t,o,K.MaxValue)}developerResourceLoaded(e){e>=8||I.recordEnumeratedHistogram("DevTools.DeveloperResourceLoaded",e,8)}developerResourceScheme(e){e>=9||I.recordEnumeratedHistogram("DevTools.DeveloperResourceScheme",e,9)}inlineScriptParsed(e){e>=2||I.recordEnumeratedHistogram("DevTools.InlineScriptParsed",e,2)}vmInlineScriptContentShown(e){e>=2||I.recordEnumeratedHistogram("DevTools.VMInlineScriptShown",e,2)}language(e){const r=re[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.Language",r,re.MaxValue)}syncSetting(e){I.getSyncInformation((r=>{let o=1;r.isSyncActive&&!r.arePreferencesSynced?o=2:r.isSyncActive&&r.arePreferencesSynced&&(o=e?4:3),I.recordEnumeratedHistogram("DevTools.SyncSetting",o,5)}))}recordingAssertion(e){I.recordEnumeratedHistogram("DevTools.RecordingAssertion",e,4)}recordingToggled(e){I.recordEnumeratedHistogram("DevTools.RecordingToggled",e,3)}recordingReplayFinished(e){I.recordEnumeratedHistogram("DevTools.RecordingReplayFinished",e,5)}recordingReplaySpeed(e){I.recordEnumeratedHistogram("DevTools.RecordingReplaySpeed",e,5)}recordingReplayStarted(e){I.recordEnumeratedHistogram("DevTools.RecordingReplayStarted",e,4)}recordingEdited(e){I.recordEnumeratedHistogram("DevTools.RecordingEdited",e,11)}recordingExported(e){I.recordEnumeratedHistogram("DevTools.RecordingExported",e,6)}recordingCodeToggled(e){I.recordEnumeratedHistogram("DevTools.RecordingCodeToggled",e,3)}recordingCopiedToClipboard(e){I.recordEnumeratedHistogram("DevTools.RecordingCopiedToClipboard",e,9)}styleTextCopied(e){I.recordEnumeratedHistogram("DevTools.StyleTextCopied",e,11)}manifestSectionSelected(e){const r=oe[e]||oe.OtherSection;I.recordEnumeratedHistogram("DevTools.ManifestSectionSelected",r,oe.MaxValue)}cssHintShown(e){I.recordEnumeratedHistogram("DevTools.CSSHintShown",e,14)}lighthouseModeRun(e){I.recordEnumeratedHistogram("DevTools.LighthouseModeRun",e,4)}lighthouseCategoryUsed(e){I.recordEnumeratedHistogram("DevTools.LighthouseCategoryUsed",e,6)}colorConvertedFrom(e){I.recordEnumeratedHistogram("DevTools.ColorConvertedFrom",e,2)}colorPickerOpenedFrom(e){I.recordEnumeratedHistogram("DevTools.ColorPickerOpenedFrom",e,2)}cssPropertyDocumentation(e){I.recordEnumeratedHistogram("DevTools.CSSPropertyDocumentation",e,3)}swatchActivated(e){I.recordEnumeratedHistogram("DevTools.SwatchActivated",e,10)}badgeActivated(e){I.recordEnumeratedHistogram("DevTools.BadgeActivated",e,9)}breakpointsRestoredFromStorage(e){const r=this.#c(e);I.recordEnumeratedHistogram("DevTools.BreakpointsRestoredFromStorageCount",r,10)}animationPlaybackRateChanged(e){I.recordEnumeratedHistogram("DevTools.AnimationPlaybackRateChanged",e,4)}animationPointDragged(e){I.recordEnumeratedHistogram("DevTools.AnimationPointDragged",e,5)}#c(e){return e<100?0:e<300?1:e<1e3?2:e<3e3?3:e<1e4?4:e<3e4?5:e<1e5?6:e<3e5?7:e<1e6?8:9}workspacesPopulated(e){I.recordPerformanceHistogram("DevTools.Workspaces.PopulateWallClocktime",e)}visualLoggingProcessingDone(e){I.recordPerformanceHistogram("DevTools.VisualLogging.ProcessingTime",e)}legacyResourceTypeFilterNumberOfSelectedChanged(e){const r=Math.max(Math.min(e,Z.MaxValue-1),1);I.recordEnumeratedHistogram("DevTools.LegacyResourceTypeFilterNumberOfSelectedChanged",r,Z.MaxValue)}legacyResourceTypeFilterItemSelected(e){const r=Z[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.LegacyResourceTypeFilterItemSelected",r,Z.MaxValue)}resourceTypeFilterNumberOfSelectedChanged(e){const r=Math.max(Math.min(e,Z.MaxValue-1),1);I.recordEnumeratedHistogram("DevTools.ResourceTypeFilterNumberOfSelectedChanged",r,Z.MaxValue)}resourceTypeFilterItemSelected(e){const r=Z[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.ResourceTypeFilterItemSelected",r,Z.MaxValue)}networkPanelMoreFiltersNumberOfSelectedChanged(e){const r=Math.max(Math.min(e,ee.MaxValue),0);I.recordEnumeratedHistogram("DevTools.NetworkPanelMoreFiltersNumberOfSelectedChanged",r,ee.MaxValue)}networkPanelMoreFiltersItemSelected(e){const r=ee[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.NetworkPanelMoreFiltersItemSelected",r,ee.MaxValue)}}!function(e){e[e.WindowDocked=1]="WindowDocked",e[e.WindowUndocked=2]="WindowUndocked",e[e.ScriptsBreakpointSet=3]="ScriptsBreakpointSet",e[e.TimelineStarted=4]="TimelineStarted",e[e.ProfilesCPUProfileTaken=5]="ProfilesCPUProfileTaken",e[e.ProfilesHeapProfileTaken=6]="ProfilesHeapProfileTaken",e[e.ConsoleEvaluated=8]="ConsoleEvaluated",e[e.FileSavedInWorkspace=9]="FileSavedInWorkspace",e[e.DeviceModeEnabled=10]="DeviceModeEnabled",e[e.AnimationsPlaybackRateChanged=11]="AnimationsPlaybackRateChanged",e[e.RevisionApplied=12]="RevisionApplied",e[e.FileSystemDirectoryContentReceived=13]="FileSystemDirectoryContentReceived",e[e.StyleRuleEdited=14]="StyleRuleEdited",e[e.CommandEvaluatedInConsolePanel=15]="CommandEvaluatedInConsolePanel",e[e.DOMPropertiesExpanded=16]="DOMPropertiesExpanded",e[e.ResizedViewInResponsiveMode=17]="ResizedViewInResponsiveMode",e[e.TimelinePageReloadStarted=18]="TimelinePageReloadStarted",e[e.ConnectToNodeJSFromFrontend=19]="ConnectToNodeJSFromFrontend",e[e.ConnectToNodeJSDirectly=20]="ConnectToNodeJSDirectly",e[e.CpuThrottlingEnabled=21]="CpuThrottlingEnabled",e[e.CpuProfileNodeFocused=22]="CpuProfileNodeFocused",e[e.CpuProfileNodeExcluded=23]="CpuProfileNodeExcluded",e[e.SelectFileFromFilePicker=24]="SelectFileFromFilePicker",e[e.SelectCommandFromCommandMenu=25]="SelectCommandFromCommandMenu",e[e.ChangeInspectedNodeInElementsPanel=26]="ChangeInspectedNodeInElementsPanel",e[e.StyleRuleCopied=27]="StyleRuleCopied",e[e.CoverageStarted=28]="CoverageStarted",e[e.LighthouseStarted=29]="LighthouseStarted",e[e.LighthouseFinished=30]="LighthouseFinished",e[e.ShowedThirdPartyBadges=31]="ShowedThirdPartyBadges",e[e.LighthouseViewTrace=32]="LighthouseViewTrace",e[e.FilmStripStartedRecording=33]="FilmStripStartedRecording",e[e.CoverageReportFiltered=34]="CoverageReportFiltered",e[e.CoverageStartedPerBlock=35]="CoverageStartedPerBlock",e[e["SettingsOpenedFromGear-deprecated"]=36]="SettingsOpenedFromGear-deprecated",e[e["SettingsOpenedFromMenu-deprecated"]=37]="SettingsOpenedFromMenu-deprecated",e[e["SettingsOpenedFromCommandMenu-deprecated"]=38]="SettingsOpenedFromCommandMenu-deprecated",e[e.TabMovedToDrawer=39]="TabMovedToDrawer",e[e.TabMovedToMainPanel=40]="TabMovedToMainPanel",e[e.CaptureCssOverviewClicked=41]="CaptureCssOverviewClicked",e[e.VirtualAuthenticatorEnvironmentEnabled=42]="VirtualAuthenticatorEnvironmentEnabled",e[e.SourceOrderViewActivated=43]="SourceOrderViewActivated",e[e.UserShortcutAdded=44]="UserShortcutAdded",e[e.ShortcutRemoved=45]="ShortcutRemoved",e[e.ShortcutModified=46]="ShortcutModified",e[e.CustomPropertyLinkClicked=47]="CustomPropertyLinkClicked",e[e.CustomPropertyEdited=48]="CustomPropertyEdited",e[e.ServiceWorkerNetworkRequestClicked=49]="ServiceWorkerNetworkRequestClicked",e[e.ServiceWorkerNetworkRequestClosedQuickly=50]="ServiceWorkerNetworkRequestClosedQuickly",e[e.NetworkPanelServiceWorkerRespondWith=51]="NetworkPanelServiceWorkerRespondWith",e[e.NetworkPanelCopyValue=52]="NetworkPanelCopyValue",e[e.ConsoleSidebarOpened=53]="ConsoleSidebarOpened",e[e.PerfPanelTraceImported=54]="PerfPanelTraceImported",e[e.PerfPanelTraceExported=55]="PerfPanelTraceExported",e[e.StackFrameRestarted=56]="StackFrameRestarted",e[e.CaptureTestProtocolClicked=57]="CaptureTestProtocolClicked",e[e.BreakpointRemovedFromRemoveButton=58]="BreakpointRemovedFromRemoveButton",e[e.BreakpointGroupExpandedStateChanged=59]="BreakpointGroupExpandedStateChanged",e[e.HeaderOverrideFileCreated=60]="HeaderOverrideFileCreated",e[e.HeaderOverrideEnableEditingClicked=61]="HeaderOverrideEnableEditingClicked",e[e.HeaderOverrideHeaderAdded=62]="HeaderOverrideHeaderAdded",e[e.HeaderOverrideHeaderEdited=63]="HeaderOverrideHeaderEdited",e[e.HeaderOverrideHeaderRemoved=64]="HeaderOverrideHeaderRemoved",e[e.HeaderOverrideHeadersFileEdited=65]="HeaderOverrideHeadersFileEdited",e[e.PersistenceNetworkOverridesEnabled=66]="PersistenceNetworkOverridesEnabled",e[e.PersistenceNetworkOverridesDisabled=67]="PersistenceNetworkOverridesDisabled",e[e.BreakpointRemovedFromContextMenu=68]="BreakpointRemovedFromContextMenu",e[e.BreakpointsInFileRemovedFromRemoveButton=69]="BreakpointsInFileRemovedFromRemoveButton",e[e.BreakpointsInFileRemovedFromContextMenu=70]="BreakpointsInFileRemovedFromContextMenu",e[e.BreakpointsInFileCheckboxToggled=71]="BreakpointsInFileCheckboxToggled",e[e.BreakpointsInFileEnabledDisabledFromContextMenu=72]="BreakpointsInFileEnabledDisabledFromContextMenu",e[e.BreakpointConditionEditedFromSidebar=73]="BreakpointConditionEditedFromSidebar",e[e.WorkspaceTabAddFolder=74]="WorkspaceTabAddFolder",e[e.WorkspaceTabRemoveFolder=75]="WorkspaceTabRemoveFolder",e[e.OverrideTabAddFolder=76]="OverrideTabAddFolder",e[e.OverrideTabRemoveFolder=77]="OverrideTabRemoveFolder",e[e.WorkspaceSourceSelected=78]="WorkspaceSourceSelected",e[e.OverridesSourceSelected=79]="OverridesSourceSelected",e[e.StyleSheetInitiatorLinkClicked=80]="StyleSheetInitiatorLinkClicked",e[e.BreakpointRemovedFromGutterContextMenu=81]="BreakpointRemovedFromGutterContextMenu",e[e.BreakpointRemovedFromGutterToggle=82]="BreakpointRemovedFromGutterToggle",e[e.StylePropertyInsideKeyframeEdited=83]="StylePropertyInsideKeyframeEdited",e[e.OverrideContentFromSourcesContextMenu=84]="OverrideContentFromSourcesContextMenu",e[e.OverrideContentFromNetworkContextMenu=85]="OverrideContentFromNetworkContextMenu",e[e.OverrideScript=86]="OverrideScript",e[e.OverrideStyleSheet=87]="OverrideStyleSheet",e[e.OverrideDocument=88]="OverrideDocument",e[e.OverrideFetchXHR=89]="OverrideFetchXHR",e[e.OverrideImage=90]="OverrideImage",e[e.OverrideFont=91]="OverrideFont",e[e.OverrideContentContextMenuSetup=92]="OverrideContentContextMenuSetup",e[e.OverrideContentContextMenuAbandonSetup=93]="OverrideContentContextMenuAbandonSetup",e[e.OverrideContentContextMenuActivateDisabled=94]="OverrideContentContextMenuActivateDisabled",e[e.OverrideContentContextMenuOpenExistingFile=95]="OverrideContentContextMenuOpenExistingFile",e[e.OverrideContentContextMenuSaveNewFile=96]="OverrideContentContextMenuSaveNewFile",e[e.ShowAllOverridesFromSourcesContextMenu=97]="ShowAllOverridesFromSourcesContextMenu",e[e.ShowAllOverridesFromNetworkContextMenu=98]="ShowAllOverridesFromNetworkContextMenu",e[e.AnimationGroupsCleared=99]="AnimationGroupsCleared",e[e.AnimationsPaused=100]="AnimationsPaused",e[e.AnimationsResumed=101]="AnimationsResumed",e[e.AnimatedNodeDescriptionClicked=102]="AnimatedNodeDescriptionClicked",e[e.AnimationGroupScrubbed=103]="AnimationGroupScrubbed",e[e.AnimationGroupReplayed=104]="AnimationGroupReplayed",e[e.OverrideTabDeleteFolderContextMenu=105]="OverrideTabDeleteFolderContextMenu",e[e.WorkspaceDropFolder=107]="WorkspaceDropFolder",e[e.WorkspaceSelectFolder=108]="WorkspaceSelectFolder",e[e.OverrideContentContextMenuSourceMappedWarning=109]="OverrideContentContextMenuSourceMappedWarning",e[e.OverrideContentContextMenuRedirectToDeployed=110]="OverrideContentContextMenuRedirectToDeployed",e[e.NewStyleRuleAdded=111]="NewStyleRuleAdded",e[e.TraceExpanded=112]="TraceExpanded",e[e.InsightConsoleMessageShown=113]="InsightConsoleMessageShown",e[e.InsightRequestedViaContextMenu=114]="InsightRequestedViaContextMenu",e[e.InsightRequestedViaHoverButton=115]="InsightRequestedViaHoverButton",e[e.InsightRatedPositive=117]="InsightRatedPositive",e[e.InsightRatedNegative=118]="InsightRatedNegative",e[e.InsightClosed=119]="InsightClosed",e[e.InsightErrored=120]="InsightErrored",e[e.InsightHoverButtonShown=121]="InsightHoverButtonShown",e[e.SelfXssWarningConsoleMessageShown=122]="SelfXssWarningConsoleMessageShown",e[e.SelfXssWarningDialogShown=123]="SelfXssWarningDialogShown",e[e.SelfXssAllowPastingInConsole=124]="SelfXssAllowPastingInConsole",e[e.SelfXssAllowPastingInDialog=125]="SelfXssAllowPastingInDialog",e[e.ToggleEmulateFocusedPageFromStylesPaneOn=126]="ToggleEmulateFocusedPageFromStylesPaneOn",e[e.ToggleEmulateFocusedPageFromStylesPaneOff=127]="ToggleEmulateFocusedPageFromStylesPaneOff",e[e.ToggleEmulateFocusedPageFromRenderingTab=128]="ToggleEmulateFocusedPageFromRenderingTab",e[e.ToggleEmulateFocusedPageFromCommandMenu=129]="ToggleEmulateFocusedPageFromCommandMenu",e[e.InsightGenerated=130]="InsightGenerated",e[e.InsightErroredApi=131]="InsightErroredApi",e[e.InsightErroredMarkdown=132]="InsightErroredMarkdown",e[e.ToggleShowWebVitals=133]="ToggleShowWebVitals",e[e.InsightErroredPermissionDenied=134]="InsightErroredPermissionDenied",e[e.InsightErroredCannotSend=135]="InsightErroredCannotSend",e[e.InsightErroredRequestFailed=136]="InsightErroredRequestFailed",e[e.InsightErroredCannotParseChunk=137]="InsightErroredCannotParseChunk",e[e.InsightErroredUnknownChunk=138]="InsightErroredUnknownChunk",e[e.InsightErroredOther=139]="InsightErroredOther",e[e.MaxValue=140]="MaxValue"}(V||(V={})),function(e){e[e.elements=1]="elements",e[e.resources=2]="resources",e[e.network=3]="network",e[e.sources=4]="sources",e[e.timeline=5]="timeline",e[e["heap-profiler"]=6]="heap-profiler",e[e.console=8]="console",e[e.layers=9]="layers",e[e["console-view"]=10]="console-view",e[e.animations=11]="animations",e[e["network.config"]=12]="network.config",e[e.rendering=13]="rendering",e[e.sensors=14]="sensors",e[e["sources.search"]=15]="sources.search",e[e.security=16]="security",e[e["js-profiler"]=17]="js-profiler",e[e.lighthouse=18]="lighthouse",e[e.coverage=19]="coverage",e[e["protocol-monitor"]=20]="protocol-monitor",e[e["remote-devices"]=21]="remote-devices",e[e["web-audio"]=22]="web-audio",e[e["changes.changes"]=23]="changes.changes",e[e["performance.monitor"]=24]="performance.monitor",e[e["release-note"]=25]="release-note",e[e["live-heap-profile"]=26]="live-heap-profile",e[e["sources.quick"]=27]="sources.quick",e[e["network.blocked-urls"]=28]="network.blocked-urls",e[e["settings-preferences"]=29]="settings-preferences",e[e["settings-workspace"]=30]="settings-workspace",e[e["settings-experiments"]=31]="settings-experiments",e[e["settings-blackbox"]=32]="settings-blackbox",e[e["settings-devices"]=33]="settings-devices",e[e["settings-throttling-conditions"]=34]="settings-throttling-conditions",e[e["settings-emulation-locations"]=35]="settings-emulation-locations",e[e["settings-shortcuts"]=36]="settings-shortcuts",e[e["issues-pane"]=37]="issues-pane",e[e["settings-keybinds"]=38]="settings-keybinds",e[e.cssoverview=39]="cssoverview",e[e["chrome-recorder"]=40]="chrome-recorder",e[e["trust-tokens"]=41]="trust-tokens",e[e["reporting-api"]=42]="reporting-api",e[e["interest-groups"]=43]="interest-groups",e[e["back-forward-cache"]=44]="back-forward-cache",e[e["service-worker-cache"]=45]="service-worker-cache",e[e["background-service-background-fetch"]=46]="background-service-background-fetch",e[e["background-service-background-sync"]=47]="background-service-background-sync",e[e["background-service-push-messaging"]=48]="background-service-push-messaging",e[e["background-service-notifications"]=49]="background-service-notifications",e[e["background-service-payment-handler"]=50]="background-service-payment-handler",e[e["background-service-periodic-background-sync"]=51]="background-service-periodic-background-sync",e[e["service-workers"]=52]="service-workers",e[e["app-manifest"]=53]="app-manifest",e[e.storage=54]="storage",e[e.cookies=55]="cookies",e[e["frame-details"]=56]="frame-details",e[e["frame-resource"]=57]="frame-resource",e[e["frame-window"]=58]="frame-window",e[e["frame-worker"]=59]="frame-worker",e[e["dom-storage"]=60]="dom-storage",e[e["indexed-db"]=61]="indexed-db",e[e["web-sql"]=62]="web-sql",e[e["performance-insights"]=63]="performance-insights",e[e.preloading=64]="preloading",e[e["bounce-tracking-mitigations"]=65]="bounce-tracking-mitigations",e[e["developer-resources"]=66]="developer-resources",e[e["autofill-view"]=67]="autofill-view",e[e.MaxValue=68]="MaxValue"}(B||(B={})),function(e){e[e["elements-main"]=1]="elements-main",e[e["elements-drawer"]=2]="elements-drawer",e[e["resources-main"]=3]="resources-main",e[e["resources-drawer"]=4]="resources-drawer",e[e["network-main"]=5]="network-main",e[e["network-drawer"]=6]="network-drawer",e[e["sources-main"]=7]="sources-main",e[e["sources-drawer"]=8]="sources-drawer",e[e["timeline-main"]=9]="timeline-main",e[e["timeline-drawer"]=10]="timeline-drawer",e[e["heap_profiler-main"]=11]="heap_profiler-main",e[e["heap_profiler-drawer"]=12]="heap_profiler-drawer",e[e["console-main"]=13]="console-main",e[e["console-drawer"]=14]="console-drawer",e[e["layers-main"]=15]="layers-main",e[e["layers-drawer"]=16]="layers-drawer",e[e["console-view-main"]=17]="console-view-main",e[e["console-view-drawer"]=18]="console-view-drawer",e[e["animations-main"]=19]="animations-main",e[e["animations-drawer"]=20]="animations-drawer",e[e["network.config-main"]=21]="network.config-main",e[e["network.config-drawer"]=22]="network.config-drawer",e[e["rendering-main"]=23]="rendering-main",e[e["rendering-drawer"]=24]="rendering-drawer",e[e["sensors-main"]=25]="sensors-main",e[e["sensors-drawer"]=26]="sensors-drawer",e[e["sources.search-main"]=27]="sources.search-main",e[e["sources.search-drawer"]=28]="sources.search-drawer",e[e["security-main"]=29]="security-main",e[e["security-drawer"]=30]="security-drawer",e[e["js_profiler-main"]=31]="js_profiler-main",e[e["js_profiler-drawer"]=32]="js_profiler-drawer",e[e["lighthouse-main"]=33]="lighthouse-main",e[e["lighthouse-drawer"]=34]="lighthouse-drawer",e[e["coverage-main"]=35]="coverage-main",e[e["coverage-drawer"]=36]="coverage-drawer",e[e["protocol-monitor-main"]=37]="protocol-monitor-main",e[e["protocol-monitor-drawer"]=38]="protocol-monitor-drawer",e[e["remote-devices-main"]=39]="remote-devices-main",e[e["remote-devices-drawer"]=40]="remote-devices-drawer",e[e["web-audio-main"]=41]="web-audio-main",e[e["web-audio-drawer"]=42]="web-audio-drawer",e[e["changes.changes-main"]=43]="changes.changes-main",e[e["changes.changes-drawer"]=44]="changes.changes-drawer",e[e["performance.monitor-main"]=45]="performance.monitor-main",e[e["performance.monitor-drawer"]=46]="performance.monitor-drawer",e[e["release-note-main"]=47]="release-note-main",e[e["release-note-drawer"]=48]="release-note-drawer",e[e["live_heap_profile-main"]=49]="live_heap_profile-main",e[e["live_heap_profile-drawer"]=50]="live_heap_profile-drawer",e[e["sources.quick-main"]=51]="sources.quick-main",e[e["sources.quick-drawer"]=52]="sources.quick-drawer",e[e["network.blocked-urls-main"]=53]="network.blocked-urls-main",e[e["network.blocked-urls-drawer"]=54]="network.blocked-urls-drawer",e[e["settings-preferences-main"]=55]="settings-preferences-main",e[e["settings-preferences-drawer"]=56]="settings-preferences-drawer",e[e["settings-workspace-main"]=57]="settings-workspace-main",e[e["settings-workspace-drawer"]=58]="settings-workspace-drawer",e[e["settings-experiments-main"]=59]="settings-experiments-main",e[e["settings-experiments-drawer"]=60]="settings-experiments-drawer",e[e["settings-blackbox-main"]=61]="settings-blackbox-main",e[e["settings-blackbox-drawer"]=62]="settings-blackbox-drawer",e[e["settings-devices-main"]=63]="settings-devices-main",e[e["settings-devices-drawer"]=64]="settings-devices-drawer",e[e["settings-throttling-conditions-main"]=65]="settings-throttling-conditions-main",e[e["settings-throttling-conditions-drawer"]=66]="settings-throttling-conditions-drawer",e[e["settings-emulation-locations-main"]=67]="settings-emulation-locations-main",e[e["settings-emulation-locations-drawer"]=68]="settings-emulation-locations-drawer",e[e["settings-shortcuts-main"]=69]="settings-shortcuts-main",e[e["settings-shortcuts-drawer"]=70]="settings-shortcuts-drawer",e[e["issues-pane-main"]=71]="issues-pane-main",e[e["issues-pane-drawer"]=72]="issues-pane-drawer",e[e["settings-keybinds-main"]=73]="settings-keybinds-main",e[e["settings-keybinds-drawer"]=74]="settings-keybinds-drawer",e[e["cssoverview-main"]=75]="cssoverview-main",e[e["cssoverview-drawer"]=76]="cssoverview-drawer",e[e["chrome_recorder-main"]=77]="chrome_recorder-main",e[e["chrome_recorder-drawer"]=78]="chrome_recorder-drawer",e[e["trust_tokens-main"]=79]="trust_tokens-main",e[e["trust_tokens-drawer"]=80]="trust_tokens-drawer",e[e["reporting_api-main"]=81]="reporting_api-main",e[e["reporting_api-drawer"]=82]="reporting_api-drawer",e[e["interest_groups-main"]=83]="interest_groups-main",e[e["interest_groups-drawer"]=84]="interest_groups-drawer",e[e["back_forward_cache-main"]=85]="back_forward_cache-main",e[e["back_forward_cache-drawer"]=86]="back_forward_cache-drawer",e[e["service_worker_cache-main"]=87]="service_worker_cache-main",e[e["service_worker_cache-drawer"]=88]="service_worker_cache-drawer",e[e["background_service_backgroundFetch-main"]=89]="background_service_backgroundFetch-main",e[e["background_service_backgroundFetch-drawer"]=90]="background_service_backgroundFetch-drawer",e[e["background_service_backgroundSync-main"]=91]="background_service_backgroundSync-main",e[e["background_service_backgroundSync-drawer"]=92]="background_service_backgroundSync-drawer",e[e["background_service_pushMessaging-main"]=93]="background_service_pushMessaging-main",e[e["background_service_pushMessaging-drawer"]=94]="background_service_pushMessaging-drawer",e[e["background_service_notifications-main"]=95]="background_service_notifications-main",e[e["background_service_notifications-drawer"]=96]="background_service_notifications-drawer",e[e["background_service_paymentHandler-main"]=97]="background_service_paymentHandler-main",e[e["background_service_paymentHandler-drawer"]=98]="background_service_paymentHandler-drawer",e[e["background_service_periodicBackgroundSync-main"]=99]="background_service_periodicBackgroundSync-main",e[e["background_service_periodicBackgroundSync-drawer"]=100]="background_service_periodicBackgroundSync-drawer",e[e["service_workers-main"]=101]="service_workers-main",e[e["service_workers-drawer"]=102]="service_workers-drawer",e[e["app_manifest-main"]=103]="app_manifest-main",e[e["app_manifest-drawer"]=104]="app_manifest-drawer",e[e["storage-main"]=105]="storage-main",e[e["storage-drawer"]=106]="storage-drawer",e[e["cookies-main"]=107]="cookies-main",e[e["cookies-drawer"]=108]="cookies-drawer",e[e["frame_details-main"]=109]="frame_details-main",e[e["frame_details-drawer"]=110]="frame_details-drawer",e[e["frame_resource-main"]=111]="frame_resource-main",e[e["frame_resource-drawer"]=112]="frame_resource-drawer",e[e["frame_window-main"]=113]="frame_window-main",e[e["frame_window-drawer"]=114]="frame_window-drawer",e[e["frame_worker-main"]=115]="frame_worker-main",e[e["frame_worker-drawer"]=116]="frame_worker-drawer",e[e["dom_storage-main"]=117]="dom_storage-main",e[e["dom_storage-drawer"]=118]="dom_storage-drawer",e[e["indexed_db-main"]=119]="indexed_db-main",e[e["indexed_db-drawer"]=120]="indexed_db-drawer",e[e["web_sql-main"]=121]="web_sql-main",e[e["web_sql-drawer"]=122]="web_sql-drawer",e[e["performance_insights-main"]=123]="performance_insights-main",e[e["performance_insights-drawer"]=124]="performance_insights-drawer",e[e["preloading-main"]=125]="preloading-main",e[e["preloading-drawer"]=126]="preloading-drawer",e[e["bounce_tracking_mitigations-main"]=127]="bounce_tracking_mitigations-main",e[e["bounce_tracking_mitigations-drawer"]=128]="bounce_tracking_mitigations-drawer",e[e["developer-resources-main"]=129]="developer-resources-main",e[e["developer-resources-drawer"]=130]="developer-resources-drawer",e[e["autofill-view-main"]=131]="autofill-view-main",e[e["autofill-view-drawer"]=132]="autofill-view-drawer",e[e.MaxValue=133]="MaxValue"}(j||(j={})),function(e){e[e.OtherSidebarPane=0]="OtherSidebarPane",e[e.styles=1]="styles",e[e.computed=2]="computed",e[e["elements.layout"]=3]="elements.layout",e[e["elements.event-listeners"]=4]="elements.event-listeners",e[e["elements.dom-breakpoints"]=5]="elements.dom-breakpoints",e[e["elements.dom-properties"]=6]="elements.dom-properties",e[e["accessibility.view"]=7]="accessibility.view",e[e.MaxValue=8]="MaxValue"}(q||(q={})),function(e){e[e.OtherSidebarPane=0]="OtherSidebarPane",e[e["navigator-network"]=1]="navigator-network",e[e["navigator-files"]=2]="navigator-files",e[e["navigator-overrides"]=3]="navigator-overrides",e[e["navigator-content-scripts"]=4]="navigator-content-scripts",e[e["navigator-snippets"]=5]="navigator-snippets",e[e.MaxValue=6]="MaxValue"}(G||(G={})),function(e){e[e.Unknown=0]="Unknown",e[e["text/css"]=2]="text/css",e[e["text/html"]=3]="text/html",e[e["application/xml"]=4]="application/xml",e[e["application/wasm"]=5]="application/wasm",e[e["application/manifest+json"]=6]="application/manifest+json",e[e["application/x-aspx"]=7]="application/x-aspx",e[e["application/jsp"]=8]="application/jsp",e[e["text/x-c++src"]=9]="text/x-c++src",e[e["text/x-coffeescript"]=10]="text/x-coffeescript",e[e["application/vnd.dart"]=11]="application/vnd.dart",e[e["text/typescript"]=12]="text/typescript",e[e["text/typescript-jsx"]=13]="text/typescript-jsx",e[e["application/json"]=14]="application/json",e[e["text/x-csharp"]=15]="text/x-csharp",e[e["text/x-java"]=16]="text/x-java",e[e["text/x-less"]=17]="text/x-less",e[e["application/x-httpd-php"]=18]="application/x-httpd-php",e[e["text/x-python"]=19]="text/x-python",e[e["text/x-sh"]=20]="text/x-sh",e[e["text/x-gss"]=21]="text/x-gss",e[e["text/x-sass"]=22]="text/x-sass",e[e["text/x-scss"]=23]="text/x-scss",e[e["text/markdown"]=24]="text/markdown",e[e["text/x-clojure"]=25]="text/x-clojure",e[e["text/jsx"]=26]="text/jsx",e[e["text/x-go"]=27]="text/x-go",e[e["text/x-kotlin"]=28]="text/x-kotlin",e[e["text/x-scala"]=29]="text/x-scala",e[e["text/x.svelte"]=30]="text/x.svelte",e[e["text/javascript+plain"]=31]="text/javascript+plain",e[e["text/javascript+minified"]=32]="text/javascript+minified",e[e["text/javascript+sourcemapped"]=33]="text/javascript+sourcemapped",e[e["text/x.angular"]=34]="text/x.angular",e[e["text/x.vue"]=35]="text/x.vue",e[e.MaxValue=36]="MaxValue"}(z||(z={})),function(e){e[e.devToolsDefault=0]="devToolsDefault",e[e.vsCode=1]="vsCode",e[e.MaxValue=2]="MaxValue"}($||($={})),function(e){e[e.OtherShortcut=0]="OtherShortcut",e[e["quick-open.show-command-menu"]=1]="quick-open.show-command-menu",e[e["console.clear"]=2]="console.clear",e[e["console.toggle"]=3]="console.toggle",e[e["debugger.step"]=4]="debugger.step",e[e["debugger.step-into"]=5]="debugger.step-into",e[e["debugger.step-out"]=6]="debugger.step-out",e[e["debugger.step-over"]=7]="debugger.step-over",e[e["debugger.toggle-breakpoint"]=8]="debugger.toggle-breakpoint",e[e["debugger.toggle-breakpoint-enabled"]=9]="debugger.toggle-breakpoint-enabled",e[e["debugger.toggle-pause"]=10]="debugger.toggle-pause",e[e["elements.edit-as-html"]=11]="elements.edit-as-html",e[e["elements.hide-element"]=12]="elements.hide-element",e[e["elements.redo"]=13]="elements.redo",e[e["elements.toggle-element-search"]=14]="elements.toggle-element-search",e[e["elements.undo"]=15]="elements.undo",e[e["main.search-in-panel.find"]=16]="main.search-in-panel.find",e[e["main.toggle-drawer"]=17]="main.toggle-drawer",e[e["network.hide-request-details"]=18]="network.hide-request-details",e[e["network.search"]=19]="network.search",e[e["network.toggle-recording"]=20]="network.toggle-recording",e[e["quick-open.show"]=21]="quick-open.show",e[e["settings.show"]=22]="settings.show",e[e["sources.search"]=23]="sources.search",e[e["background-service.toggle-recording"]=24]="background-service.toggle-recording",e[e["components.collect-garbage"]=25]="components.collect-garbage",e[e["console.clear.history"]=26]="console.clear.history",e[e["console.create-pin"]=27]="console.create-pin",e[e["coverage.start-with-reload"]=28]="coverage.start-with-reload",e[e["coverage.toggle-recording"]=29]="coverage.toggle-recording",e[e["debugger.breakpoint-input-window"]=30]="debugger.breakpoint-input-window",e[e["debugger.evaluate-selection"]=31]="debugger.evaluate-selection",e[e["debugger.next-call-frame"]=32]="debugger.next-call-frame",e[e["debugger.previous-call-frame"]=33]="debugger.previous-call-frame",e[e["debugger.run-snippet"]=34]="debugger.run-snippet",e[e["debugger.toggle-breakpoints-active"]=35]="debugger.toggle-breakpoints-active",e[e["elements.capture-area-screenshot"]=36]="elements.capture-area-screenshot",e[e["emulation.capture-full-height-screenshot"]=37]="emulation.capture-full-height-screenshot",e[e["emulation.capture-node-screenshot"]=38]="emulation.capture-node-screenshot",e[e["emulation.capture-screenshot"]=39]="emulation.capture-screenshot",e[e["emulation.show-sensors"]=40]="emulation.show-sensors",e[e["emulation.toggle-device-mode"]=41]="emulation.toggle-device-mode",e[e["help.release-notes"]=42]="help.release-notes",e[e["help.report-issue"]=43]="help.report-issue",e[e["input.start-replaying"]=44]="input.start-replaying",e[e["input.toggle-pause"]=45]="input.toggle-pause",e[e["input.toggle-recording"]=46]="input.toggle-recording",e[e["inspector-main.focus-debuggee"]=47]="inspector-main.focus-debuggee",e[e["inspector-main.hard-reload"]=48]="inspector-main.hard-reload",e[e["inspector-main.reload"]=49]="inspector-main.reload",e[e["live-heap-profile.start-with-reload"]=50]="live-heap-profile.start-with-reload",e[e["live-heap-profile.toggle-recording"]=51]="live-heap-profile.toggle-recording",e[e["main.debug-reload"]=52]="main.debug-reload",e[e["main.next-tab"]=53]="main.next-tab",e[e["main.previous-tab"]=54]="main.previous-tab",e[e["main.search-in-panel.cancel"]=55]="main.search-in-panel.cancel",e[e["main.search-in-panel.find-next"]=56]="main.search-in-panel.find-next",e[e["main.search-in-panel.find-previous"]=57]="main.search-in-panel.find-previous",e[e["main.toggle-dock"]=58]="main.toggle-dock",e[e["main.zoom-in"]=59]="main.zoom-in",e[e["main.zoom-out"]=60]="main.zoom-out",e[e["main.zoom-reset"]=61]="main.zoom-reset",e[e["network-conditions.network-low-end-mobile"]=62]="network-conditions.network-low-end-mobile",e[e["network-conditions.network-mid-tier-mobile"]=63]="network-conditions.network-mid-tier-mobile",e[e["network-conditions.network-offline"]=64]="network-conditions.network-offline",e[e["network-conditions.network-online"]=65]="network-conditions.network-online",e[e["profiler.heap-toggle-recording"]=66]="profiler.heap-toggle-recording",e[e["profiler.js-toggle-recording"]=67]="profiler.js-toggle-recording",e[e["resources.clear"]=68]="resources.clear",e[e["settings.documentation"]=69]="settings.documentation",e[e["settings.shortcuts"]=70]="settings.shortcuts",e[e["sources.add-folder-to-workspace"]=71]="sources.add-folder-to-workspace",e[e["sources.add-to-watch"]=72]="sources.add-to-watch",e[e["sources.close-all"]=73]="sources.close-all",e[e["sources.close-editor-tab"]=74]="sources.close-editor-tab",e[e["sources.create-snippet"]=75]="sources.create-snippet",e[e["sources.go-to-line"]=76]="sources.go-to-line",e[e["sources.go-to-member"]=77]="sources.go-to-member",e[e["sources.jump-to-next-location"]=78]="sources.jump-to-next-location",e[e["sources.jump-to-previous-location"]=79]="sources.jump-to-previous-location",e[e["sources.rename"]=80]="sources.rename",e[e["sources.save"]=81]="sources.save",e[e["sources.save-all"]=82]="sources.save-all",e[e["sources.switch-file"]=83]="sources.switch-file",e[e["timeline.jump-to-next-frame"]=84]="timeline.jump-to-next-frame",e[e["timeline.jump-to-previous-frame"]=85]="timeline.jump-to-previous-frame",e[e["timeline.load-from-file"]=86]="timeline.load-from-file",e[e["timeline.next-recording"]=87]="timeline.next-recording",e[e["timeline.previous-recording"]=88]="timeline.previous-recording",e[e["timeline.record-reload"]=89]="timeline.record-reload",e[e["timeline.save-to-file"]=90]="timeline.save-to-file",e[e["timeline.show-history"]=91]="timeline.show-history",e[e["timeline.toggle-recording"]=92]="timeline.toggle-recording",e[e["sources.increment-css"]=93]="sources.increment-css",e[e["sources.increment-css-by-ten"]=94]="sources.increment-css-by-ten",e[e["sources.decrement-css"]=95]="sources.decrement-css",e[e["sources.decrement-css-by-ten"]=96]="sources.decrement-css-by-ten",e[e["layers.reset-view"]=97]="layers.reset-view",e[e["layers.pan-mode"]=98]="layers.pan-mode",e[e["layers.rotate-mode"]=99]="layers.rotate-mode",e[e["layers.zoom-in"]=100]="layers.zoom-in",e[e["layers.zoom-out"]=101]="layers.zoom-out",e[e["layers.up"]=102]="layers.up",e[e["layers.down"]=103]="layers.down",e[e["layers.left"]=104]="layers.left",e[e["layers.right"]=105]="layers.right",e[e["help.report-translation-issue"]=106]="help.report-translation-issue",e[e["rendering.toggle-prefers-color-scheme"]=107]="rendering.toggle-prefers-color-scheme",e[e["chrome-recorder.start-recording"]=108]="chrome-recorder.start-recording",e[e["chrome-recorder.replay-recording"]=109]="chrome-recorder.replay-recording",e[e["chrome-recorder.toggle-code-view"]=110]="chrome-recorder.toggle-code-view",e[e["chrome-recorder.copy-recording-or-step"]=111]="chrome-recorder.copy-recording-or-step",e[e["changes.revert"]=112]="changes.revert",e[e["changes.copy"]=113]="changes.copy",e[e["elements.new-style-rule"]=114]="elements.new-style-rule",e[e["elements.refresh-event-listeners"]=115]="elements.refresh-event-listeners",e[e["coverage.clear"]=116]="coverage.clear",e[e["coverage.export"]=117]="coverage.export",e[e.MaxValue=118]="MaxValue"}(X||(X={})),function(e){e[e["apply-custom-stylesheet"]=0]="apply-custom-stylesheet",e[e["capture-node-creation-stacks"]=1]="capture-node-creation-stacks",e[e["live-heap-profile"]=11]="live-heap-profile",e[e["protocol-monitor"]=13]="protocol-monitor",e[e["sampling-heap-profiler-timeline"]=17]="sampling-heap-profiler-timeline",e[e["show-option-tp-expose-internals-in-heap-snapshot"]=18]="show-option-tp-expose-internals-in-heap-snapshot",e[e["timeline-invalidation-tracking"]=26]="timeline-invalidation-tracking",e[e["timeline-show-all-events"]=27]="timeline-show-all-events",e[e["timeline-v8-runtime-call-stats"]=28]="timeline-v8-runtime-call-stats",e[e.apca=39]="apca",e[e["font-editor"]=41]="font-editor",e[e["full-accessibility-tree"]=42]="full-accessibility-tree",e[e["ignore-list-js-frames-on-timeline"]=43]="ignore-list-js-frames-on-timeline",e[e["contrast-issues"]=44]="contrast-issues",e[e["experimental-cookie-features"]=45]="experimental-cookie-features",e[e["styles-pane-css-changes"]=55]="styles-pane-css-changes",e[e["evaluate-expressions-with-source-maps"]=58]="evaluate-expressions-with-source-maps",e[e["instrumentation-breakpoints"]=61]="instrumentation-breakpoints",e[e["authored-deployed-grouping"]=63]="authored-deployed-grouping",e[e["important-dom-properties"]=64]="important-dom-properties",e[e["just-my-code"]=65]="just-my-code",e[e["timeline-as-console-profile-result-panel"]=67]="timeline-as-console-profile-result-panel",e[e["preloading-status-panel"]=68]="preloading-status-panel",e[e["outermost-target-selector"]=71]="outermost-target-selector",e[e["js-profiler-temporarily-enable"]=72]="js-profiler-temporarily-enable",e[e["highlight-errors-elements-panel"]=73]="highlight-errors-elements-panel",e[e["set-all-breakpoints-eagerly"]=74]="set-all-breakpoints-eagerly",e[e["self-xss-warning"]=75]="self-xss-warning",e[e["use-source-map-scopes"]=76]="use-source-map-scopes",e[e["storage-buckets-tree"]=77]="storage-buckets-tree",e[e["network-panel-filter-bar-redesign"]=79]="network-panel-filter-bar-redesign",e[e["track-context-menu"]=81]="track-context-menu",e[e["autofill-view"]=82]="autofill-view",e[e["sources-frame-indentation-markers-temporarily-disable"]=83]="sources-frame-indentation-markers-temporarily-disable",e[e["heap-snapshot-treat-backing-store-as-containing-object"]=84]="heap-snapshot-treat-backing-store-as-containing-object",e[e["css-type-component-length-deprecate"]=85]="css-type-component-length-deprecate",e[e.MaxValue=86]="MaxValue"}(K||(K={})),function(e){e[e.CrossOriginEmbedderPolicy=0]="CrossOriginEmbedderPolicy",e[e.MixedContent=1]="MixedContent",e[e.SameSiteCookie=2]="SameSiteCookie",e[e.HeavyAd=3]="HeavyAd",e[e.ContentSecurityPolicy=4]="ContentSecurityPolicy",e[e.Other=5]="Other",e[e.Generic=6]="Generic",e[e.ThirdPartyPhaseoutCookie=7]="ThirdPartyPhaseoutCookie",e[e.GenericCookie=8]="GenericCookie",e[e.MaxValue=9]="MaxValue"}(Q||(Q={})),function(e){e[e.CrossOriginEmbedderPolicyRequest=0]="CrossOriginEmbedderPolicyRequest",e[e.CrossOriginEmbedderPolicyElement=1]="CrossOriginEmbedderPolicyElement",e[e.MixedContentRequest=2]="MixedContentRequest",e[e.SameSiteCookieCookie=3]="SameSiteCookieCookie",e[e.SameSiteCookieRequest=4]="SameSiteCookieRequest",e[e.HeavyAdElement=5]="HeavyAdElement",e[e.ContentSecurityPolicyDirective=6]="ContentSecurityPolicyDirective",e[e.ContentSecurityPolicyElement=7]="ContentSecurityPolicyElement",e[e.MaxValue=13]="MaxValue"}(J||(J={})),function(e){e[e.MixedContentIssue=0]="MixedContentIssue",e[e["ContentSecurityPolicyIssue::kInlineViolation"]=1]="ContentSecurityPolicyIssue::kInlineViolation",e[e["ContentSecurityPolicyIssue::kEvalViolation"]=2]="ContentSecurityPolicyIssue::kEvalViolation",e[e["ContentSecurityPolicyIssue::kURLViolation"]=3]="ContentSecurityPolicyIssue::kURLViolation",e[e["ContentSecurityPolicyIssue::kTrustedTypesSinkViolation"]=4]="ContentSecurityPolicyIssue::kTrustedTypesSinkViolation",e[e["ContentSecurityPolicyIssue::kTrustedTypesPolicyViolation"]=5]="ContentSecurityPolicyIssue::kTrustedTypesPolicyViolation",e[e["HeavyAdIssue::NetworkTotalLimit"]=6]="HeavyAdIssue::NetworkTotalLimit",e[e["HeavyAdIssue::CpuTotalLimit"]=7]="HeavyAdIssue::CpuTotalLimit",e[e["HeavyAdIssue::CpuPeakLimit"]=8]="HeavyAdIssue::CpuPeakLimit",e[e["CrossOriginEmbedderPolicyIssue::CoepFrameResourceNeedsCoepHeader"]=9]="CrossOriginEmbedderPolicyIssue::CoepFrameResourceNeedsCoepHeader",e[e["CrossOriginEmbedderPolicyIssue::CoopSandboxedIFrameCannotNavigateToCoopPage"]=10]="CrossOriginEmbedderPolicyIssue::CoopSandboxedIFrameCannotNavigateToCoopPage",e[e["CrossOriginEmbedderPolicyIssue::CorpNotSameOrigin"]=11]="CrossOriginEmbedderPolicyIssue::CorpNotSameOrigin",e[e["CrossOriginEmbedderPolicyIssue::CorpNotSameOriginAfterDefaultedToSameOriginByCoep"]=12]="CrossOriginEmbedderPolicyIssue::CorpNotSameOriginAfterDefaultedToSameOriginByCoep",e[e["CrossOriginEmbedderPolicyIssue::CorpNotSameSite"]=13]="CrossOriginEmbedderPolicyIssue::CorpNotSameSite",e[e["CookieIssue::ExcludeSameSiteNoneInsecure::ReadCookie"]=14]="CookieIssue::ExcludeSameSiteNoneInsecure::ReadCookie",e[e["CookieIssue::ExcludeSameSiteNoneInsecure::SetCookie"]=15]="CookieIssue::ExcludeSameSiteNoneInsecure::SetCookie",e[e["CookieIssue::WarnSameSiteNoneInsecure::ReadCookie"]=16]="CookieIssue::WarnSameSiteNoneInsecure::ReadCookie",e[e["CookieIssue::WarnSameSiteNoneInsecure::SetCookie"]=17]="CookieIssue::WarnSameSiteNoneInsecure::SetCookie",e[e["CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Secure"]=18]="CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Secure",e[e["CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Insecure"]=19]="CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Insecure",e[e["CookieIssue::WarnCrossDowngrade::ReadCookie::Secure"]=20]="CookieIssue::WarnCrossDowngrade::ReadCookie::Secure",e[e["CookieIssue::WarnCrossDowngrade::ReadCookie::Insecure"]=21]="CookieIssue::WarnCrossDowngrade::ReadCookie::Insecure",e[e["CookieIssue::WarnCrossDowngrade::SetCookie::Secure"]=22]="CookieIssue::WarnCrossDowngrade::SetCookie::Secure",e[e["CookieIssue::WarnCrossDowngrade::SetCookie::Insecure"]=23]="CookieIssue::WarnCrossDowngrade::SetCookie::Insecure",e[e["CookieIssue::ExcludeNavigationContextDowngrade::Secure"]=24]="CookieIssue::ExcludeNavigationContextDowngrade::Secure",e[e["CookieIssue::ExcludeNavigationContextDowngrade::Insecure"]=25]="CookieIssue::ExcludeNavigationContextDowngrade::Insecure",e[e["CookieIssue::ExcludeContextDowngrade::ReadCookie::Secure"]=26]="CookieIssue::ExcludeContextDowngrade::ReadCookie::Secure",e[e["CookieIssue::ExcludeContextDowngrade::ReadCookie::Insecure"]=27]="CookieIssue::ExcludeContextDowngrade::ReadCookie::Insecure",e[e["CookieIssue::ExcludeContextDowngrade::SetCookie::Secure"]=28]="CookieIssue::ExcludeContextDowngrade::SetCookie::Secure",e[e["CookieIssue::ExcludeContextDowngrade::SetCookie::Insecure"]=29]="CookieIssue::ExcludeContextDowngrade::SetCookie::Insecure",e[e["CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::ReadCookie"]=30]="CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::ReadCookie",e[e["CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::SetCookie"]=31]="CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::SetCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::ReadCookie"]=32]="CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::ReadCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::SetCookie"]=33]="CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::SetCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::ReadCookie"]=34]="CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::ReadCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::SetCookie"]=35]="CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::SetCookie",e[e["SharedArrayBufferIssue::TransferIssue"]=36]="SharedArrayBufferIssue::TransferIssue",e[e["SharedArrayBufferIssue::CreationIssue"]=37]="SharedArrayBufferIssue::CreationIssue",e[e.LowTextContrastIssue=41]="LowTextContrastIssue",e[e["CorsIssue::InsecurePrivateNetwork"]=42]="CorsIssue::InsecurePrivateNetwork",e[e["CorsIssue::InvalidHeaders"]=44]="CorsIssue::InvalidHeaders",e[e["CorsIssue::WildcardOriginWithCredentials"]=45]="CorsIssue::WildcardOriginWithCredentials",e[e["CorsIssue::PreflightResponseInvalid"]=46]="CorsIssue::PreflightResponseInvalid",e[e["CorsIssue::OriginMismatch"]=47]="CorsIssue::OriginMismatch",e[e["CorsIssue::AllowCredentialsRequired"]=48]="CorsIssue::AllowCredentialsRequired",e[e["CorsIssue::MethodDisallowedByPreflightResponse"]=49]="CorsIssue::MethodDisallowedByPreflightResponse",e[e["CorsIssue::HeaderDisallowedByPreflightResponse"]=50]="CorsIssue::HeaderDisallowedByPreflightResponse",e[e["CorsIssue::RedirectContainsCredentials"]=51]="CorsIssue::RedirectContainsCredentials",e[e["CorsIssue::DisallowedByMode"]=52]="CorsIssue::DisallowedByMode",e[e["CorsIssue::CorsDisabledScheme"]=53]="CorsIssue::CorsDisabledScheme",e[e["CorsIssue::PreflightMissingAllowExternal"]=54]="CorsIssue::PreflightMissingAllowExternal",e[e["CorsIssue::PreflightInvalidAllowExternal"]=55]="CorsIssue::PreflightInvalidAllowExternal",e[e["CorsIssue::NoCorsRedirectModeNotFollow"]=57]="CorsIssue::NoCorsRedirectModeNotFollow",e[e["QuirksModeIssue::QuirksMode"]=58]="QuirksModeIssue::QuirksMode",e[e["QuirksModeIssue::LimitedQuirksMode"]=59]="QuirksModeIssue::LimitedQuirksMode",e[e.DeprecationIssue=60]="DeprecationIssue",e[e["ClientHintIssue::MetaTagAllowListInvalidOrigin"]=61]="ClientHintIssue::MetaTagAllowListInvalidOrigin",e[e["ClientHintIssue::MetaTagModifiedHTML"]=62]="ClientHintIssue::MetaTagModifiedHTML",e[e["CorsIssue::PreflightAllowPrivateNetworkError"]=63]="CorsIssue::PreflightAllowPrivateNetworkError",e[e["GenericIssue::CrossOriginPortalPostMessageError"]=64]="GenericIssue::CrossOriginPortalPostMessageError",e[e["GenericIssue::FormLabelForNameError"]=65]="GenericIssue::FormLabelForNameError",e[e["GenericIssue::FormDuplicateIdForInputError"]=66]="GenericIssue::FormDuplicateIdForInputError",e[e["GenericIssue::FormInputWithNoLabelError"]=67]="GenericIssue::FormInputWithNoLabelError",e[e["GenericIssue::FormAutocompleteAttributeEmptyError"]=68]="GenericIssue::FormAutocompleteAttributeEmptyError",e[e["GenericIssue::FormEmptyIdAndNameAttributesForInputError"]=69]="GenericIssue::FormEmptyIdAndNameAttributesForInputError",e[e["GenericIssue::FormAriaLabelledByToNonExistingId"]=70]="GenericIssue::FormAriaLabelledByToNonExistingId",e[e["GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError"]=71]="GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError",e[e["GenericIssue::FormLabelHasNeitherForNorNestedInput"]=72]="GenericIssue::FormLabelHasNeitherForNorNestedInput",e[e["GenericIssue::FormLabelForMatchesNonExistingIdError"]=73]="GenericIssue::FormLabelForMatchesNonExistingIdError",e[e["GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError"]=74]="GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError",e[e["GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError"]=75]="GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError",e[e["StylesheetLoadingIssue::LateImportRule"]=76]="StylesheetLoadingIssue::LateImportRule",e[e["StylesheetLoadingIssue::RequestFailed"]=77]="StylesheetLoadingIssue::RequestFailed",e[e["CorsIssue::PreflightMissingPrivateNetworkAccessId"]=78]="CorsIssue::PreflightMissingPrivateNetworkAccessId",e[e["CorsIssue::PreflightMissingPrivateNetworkAccessName"]=79]="CorsIssue::PreflightMissingPrivateNetworkAccessName",e[e["CorsIssue::PrivateNetworkAccessPermissionUnavailable"]=80]="CorsIssue::PrivateNetworkAccessPermissionUnavailable",e[e["CorsIssue::PrivateNetworkAccessPermissionDenied"]=81]="CorsIssue::PrivateNetworkAccessPermissionDenied",e[e["CookieIssue::WarnThirdPartyPhaseout::ReadCookie"]=82]="CookieIssue::WarnThirdPartyPhaseout::ReadCookie",e[e["CookieIssue::WarnThirdPartyPhaseout::SetCookie"]=83]="CookieIssue::WarnThirdPartyPhaseout::SetCookie",e[e["CookieIssue::ExcludeThirdPartyPhaseout::ReadCookie"]=84]="CookieIssue::ExcludeThirdPartyPhaseout::ReadCookie",e[e["CookieIssue::ExcludeThirdPartyPhaseout::SetCookie"]=85]="CookieIssue::ExcludeThirdPartyPhaseout::SetCookie",e[e.MaxValue=86]="MaxValue"}(Y||(Y={})),function(e){e[e.all=0]="all",e[e.Documents=1]="Documents",e[e.Scripts=2]="Scripts",e[e["Fetch and XHR"]=3]="Fetch and XHR",e[e.Stylesheets=4]="Stylesheets",e[e.Fonts=5]="Fonts",e[e.Images=6]="Images",e[e.Media=7]="Media",e[e.Manifest=8]="Manifest",e[e.WebSockets=9]="WebSockets",e[e.WebAssembly=10]="WebAssembly",e[e.Other=11]="Other",e[e.MaxValue=12]="MaxValue"}(Z||(Z={})),function(e){e[e["Hide data URLs"]=0]="Hide data URLs",e[e["Hide extension URLs"]=1]="Hide extension URLs",e[e["Blocked response cookies"]=2]="Blocked response cookies",e[e["Blocked requests"]=3]="Blocked requests",e[e["3rd-party requests"]=4]="3rd-party requests",e[e.MaxValue=5]="MaxValue"}(ee||(ee={})),function(e){e[e.af=1]="af",e[e.am=2]="am",e[e.ar=3]="ar",e[e.as=4]="as",e[e.az=5]="az",e[e.be=6]="be",e[e.bg=7]="bg",e[e.bn=8]="bn",e[e.bs=9]="bs",e[e.ca=10]="ca",e[e.cs=11]="cs",e[e.cy=12]="cy",e[e.da=13]="da",e[e.de=14]="de",e[e.el=15]="el",e[e["en-GB"]=16]="en-GB",e[e["en-US"]=17]="en-US",e[e["es-419"]=18]="es-419",e[e.es=19]="es",e[e.et=20]="et",e[e.eu=21]="eu",e[e.fa=22]="fa",e[e.fi=23]="fi",e[e.fil=24]="fil",e[e["fr-CA"]=25]="fr-CA",e[e.fr=26]="fr",e[e.gl=27]="gl",e[e.gu=28]="gu",e[e.he=29]="he",e[e.hi=30]="hi",e[e.hr=31]="hr",e[e.hu=32]="hu",e[e.hy=33]="hy",e[e.id=34]="id",e[e.is=35]="is",e[e.it=36]="it",e[e.ja=37]="ja",e[e.ka=38]="ka",e[e.kk=39]="kk",e[e.km=40]="km",e[e.kn=41]="kn",e[e.ko=42]="ko",e[e.ky=43]="ky",e[e.lo=44]="lo",e[e.lt=45]="lt",e[e.lv=46]="lv",e[e.mk=47]="mk",e[e.ml=48]="ml",e[e.mn=49]="mn",e[e.mr=50]="mr",e[e.ms=51]="ms",e[e.my=52]="my",e[e.ne=53]="ne",e[e.nl=54]="nl",e[e.no=55]="no",e[e.or=56]="or",e[e.pa=57]="pa",e[e.pl=58]="pl",e[e["pt-PT"]=59]="pt-PT",e[e.pt=60]="pt",e[e.ro=61]="ro",e[e.ru=62]="ru",e[e.si=63]="si",e[e.sk=64]="sk",e[e.sl=65]="sl",e[e.sq=66]="sq",e[e["sr-Latn"]=67]="sr-Latn",e[e.sr=68]="sr",e[e.sv=69]="sv",e[e.sw=70]="sw",e[e.ta=71]="ta",e[e.te=72]="te",e[e.th=73]="th",e[e.tr=74]="tr",e[e.uk=75]="uk",e[e.ur=76]="ur",e[e.uz=77]="uz",e[e.vi=78]="vi",e[e.zh=79]="zh",e[e["zh-HK"]=80]="zh-HK",e[e["zh-TW"]=81]="zh-TW",e[e.zu=82]="zu",e[e.MaxValue=83]="MaxValue"}(re||(re={})),function(e){e[e.OtherSection=0]="OtherSection",e[e.Identity=1]="Identity",e[e.Presentation=2]="Presentation",e[e["Protocol Handlers"]=3]="Protocol Handlers",e[e.Icons=4]="Icons",e[e["Window Controls Overlay"]=5]="Window Controls Overlay",e[e.MaxValue=6]="MaxValue"}(oe||(oe={}));var se=Object.freeze({__proto__:null,UserMetrics:ne,get Action(){return V},get PanelCodes(){return B},get PanelWithLocation(){return j},get ElementsSidebarTabCodes(){return q},get SourcesSidebarTabCodes(){return G},get MediaTypes(){return z},get KeybindSetSettings(){return $},get KeyboardShortcutAction(){return X},get DevtoolsExperiments(){return K},get IssueExpanded(){return Q},get IssueResourceOpened(){return J},get IssueCreated(){return Y},get ResourceType(){return Z},get NetworkPanelMoreFilters(){return ee},get Language(){return re},get ManifestSectionCodes(){return oe}});const ie=new ne,ae=L();export{T as AidaClient,E as InspectorFrontendHost,i as InspectorFrontendHostAPI,H as Platform,te as RNPerfMetrics,C as ResourceLoader,se as UserMetrics,ae as rnPerfMetrics,ie as userMetrics}; +import*as e from"../platform/platform.js";import*as r from"../root/root.js";import*as o from"../common/common.js";import*as t from"../i18n/i18n.js";var n;!function(e){e.AppendedToURL="appendedToURL",e.CanceledSaveURL="canceledSaveURL",e.ColorThemeChanged="colorThemeChanged",e.ContextMenuCleared="contextMenuCleared",e.ContextMenuItemSelected="contextMenuItemSelected",e.DeviceCountUpdated="deviceCountUpdated",e.DevicesDiscoveryConfigChanged="devicesDiscoveryConfigChanged",e.DevicesPortForwardingStatusChanged="devicesPortForwardingStatusChanged",e.DevicesUpdated="devicesUpdated",e.DispatchMessage="dispatchMessage",e.DispatchMessageChunk="dispatchMessageChunk",e.EnterInspectElementMode="enterInspectElementMode",e.EyeDropperPickedColor="eyeDropperPickedColor",e.FileSystemsLoaded="fileSystemsLoaded",e.FileSystemRemoved="fileSystemRemoved",e.FileSystemAdded="fileSystemAdded",e.FileSystemFilesChangedAddedRemoved="FileSystemFilesChangedAddedRemoved",e.IndexingTotalWorkCalculated="indexingTotalWorkCalculated",e.IndexingWorked="indexingWorked",e.IndexingDone="indexingDone",e.KeyEventUnhandled="keyEventUnhandled",e.ReattachRootTarget="reattachMainTarget",e.ReloadInspectedPage="reloadInspectedPage",e.RevealSourceLine="revealSourceLine",e.SavedURL="savedURL",e.SearchCompleted="searchCompleted",e.SetInspectedTabId="setInspectedTabId",e.SetUseSoftMenu="setUseSoftMenu",e.ShowPanel="showPanel"}(n||(n={}));const s=[[n.AppendedToURL,"appendedToURL",["url"]],[n.CanceledSaveURL,"canceledSaveURL",["url"]],[n.ColorThemeChanged,"colorThemeChanged",[]],[n.ContextMenuCleared,"contextMenuCleared",[]],[n.ContextMenuItemSelected,"contextMenuItemSelected",["id"]],[n.DeviceCountUpdated,"deviceCountUpdated",["count"]],[n.DevicesDiscoveryConfigChanged,"devicesDiscoveryConfigChanged",["config"]],[n.DevicesPortForwardingStatusChanged,"devicesPortForwardingStatusChanged",["status"]],[n.DevicesUpdated,"devicesUpdated",["devices"]],[n.DispatchMessage,"dispatchMessage",["messageObject"]],[n.DispatchMessageChunk,"dispatchMessageChunk",["messageChunk","messageSize"]],[n.EnterInspectElementMode,"enterInspectElementMode",[]],[n.EyeDropperPickedColor,"eyeDropperPickedColor",["color"]],[n.FileSystemsLoaded,"fileSystemsLoaded",["fileSystems"]],[n.FileSystemRemoved,"fileSystemRemoved",["fileSystemPath"]],[n.FileSystemAdded,"fileSystemAdded",["errorMessage","fileSystem"]],[n.FileSystemFilesChangedAddedRemoved,"fileSystemFilesChangedAddedRemoved",["changed","added","removed"]],[n.IndexingTotalWorkCalculated,"indexingTotalWorkCalculated",["requestId","fileSystemPath","totalWork"]],[n.IndexingWorked,"indexingWorked",["requestId","fileSystemPath","worked"]],[n.IndexingDone,"indexingDone",["requestId","fileSystemPath"]],[n.KeyEventUnhandled,"keyEventUnhandled",["event"]],[n.ReattachRootTarget,"reattachMainTarget",[]],[n.ReloadInspectedPage,"reloadInspectedPage",["hard"]],[n.RevealSourceLine,"revealSourceLine",["url","lineNumber","columnNumber"]],[n.SavedURL,"savedURL",["url","fileSystemPath"]],[n.SearchCompleted,"searchCompleted",["requestId","fileSystemPath","files"]],[n.SetInspectedTabId,"setInspectedTabId",["tabId"]],[n.SetUseSoftMenu,"setUseSoftMenu",["useSoftMenu"]],[n.ShowPanel,"showPanel",["panelName"]]];var i=Object.freeze({__proto__:null,get Events(){return n},EventDescriptors:s});const a={systemError:"System error",connectionError:"Connection error",certificateError:"Certificate error",httpError:"HTTP error",cacheError:"Cache error",signedExchangeError:"Signed Exchange error",ftpError:"FTP error",certificateManagerError:"Certificate manager error",dnsResolverError:"DNS resolver error",unknownError:"Unknown error",httpErrorStatusCodeSS:"HTTP error: status code {PH1}, {PH2}",invalidUrl:"Invalid URL",decodingDataUrlFailed:"Decoding Data URL failed"},d=t.i18n.registerUIStrings("core/host/ResourceLoader.ts",a),c=t.i18n.getLocalizedString.bind(void 0,d);let l=0;const u={},m=function(e){return u[++l]=e,l},g=function(e){u[e].close(),delete u[e]},p=function(e,r){u[e].write(r)};let h=function(e,r,t,n){const s=new o.StringOutputStream.StringOutputStream;w(e,r,s,(function(e,r,o){t(e,r,s.data(),o)}),n)};function v(e,r,o){if(void 0===e||void 0===o)return null;if(0!==e){if(function(e){return e<=-300&&e>-400}(e))return c(a.httpErrorStatusCodeSS,{PH1:String(r),PH2:o});const t=function(e){return c(e>-100?a.systemError:e>-200?a.connectionError:e>-300?a.certificateError:e>-400?a.httpError:e>-500?a.cacheError:e>-600?a.signedExchangeError:e>-700?a.ftpError:e>-800?a.certificateManagerError:e>-900?a.dnsResolverError:a.unknownError)}(e);return`${t}: ${o}`}return null}const w=function(e,r,t,n,s){const i=m(t);if(new o.ParsedURL.ParsedURL(e).isDataURL())return void(e=>new Promise(((r,o)=>{const t=new XMLHttpRequest;t.withCredentials=!1,t.open("GET",e,!0),t.onreadystatechange=function(){if(t.readyState===XMLHttpRequest.DONE){if(200!==t.status)return t.onreadystatechange=null,void o(new Error(String(t.status)));t.onreadystatechange=null,r(t.responseText)}},t.send(null)})))(e).then((function(e){p(i,e),l({statusCode:200})})).catch((function(e){l({statusCode:404,messageOverride:c(a.decodingDataUrlFailed)})}));if(!s&&function(e){try{const r=new URL(e);return"file:"===r.protocol&&""!==r.host}catch(e){return!1}}(e))return void(n&&n(!1,{},{statusCode:400,netError:-20,netErrorName:"net::BLOCKED_BY_CLIENT",message:"Loading from a remote file path is prohibited for security reasons."}));const d=[];if(r)for(const e in r)d.push(e+": "+r[e]);function l(e){if(n){const{success:r,description:o}=function(e){const{statusCode:r,netError:o,netErrorName:t,urlValid:n,messageOverride:s}=e;let i="";const d=r>=200&&r<300;if("string"==typeof s)i=s;else if(!d)if(void 0===o)i=c(!1===n?a.invalidUrl:a.unknownError);else{const e=v(o,r,t);e&&(i=e)}return console.assert(d===(0===i.length)),{success:d,description:{statusCode:r,netError:o,netErrorName:t,urlValid:n,message:i}}}(e);n(r,e.headers||{},o)}g(i)}I.loadNetworkResource(e,d.join("\r\n"),i,l)};var C=Object.freeze({__proto__:null,ResourceLoader:{},bindOutputStream:m,discardOutputStream:g,streamWrite:p,get load(){return h},setLoadForTest:function(e){h=e},netErrorToMessage:v,loadAsStream:w});const k={devtoolsS:"DevTools - {PH1}"},S=t.i18n.registerUIStrings("core/host/InspectorFrontendHost.ts",k),f=t.i18n.getLocalizedString.bind(void 0,S),y="/overrides";class b{#e;events;#r=null;recordedCountHistograms=[];recordedEnumeratedHistograms=[];recordedPerformanceHistograms=[];constructor(){function e(e){!("mac"===this.platform()?e.metaKey:e.ctrlKey)||"+"!==e.key&&"-"!==e.key||e.stopPropagation()}this.#e=new Map,"undefined"!=typeof document&&document.addEventListener("keydown",(r=>{e.call(this,r)}),!0)}platform(){const e=navigator.userAgent;return e.includes("Windows NT")?"windows":e.includes("Mac OS X")?"mac":"linux"}loadCompleted(){}bringToFront(){}closeWindow(){}setIsDocked(e,r){window.setTimeout(r,0)}showSurvey(e,r){window.setTimeout((()=>r({surveyShown:!1})),0)}canShowSurvey(e,r){window.setTimeout((()=>r({canShowSurvey:!1})),0)}setInspectedPageBounds(e){}inspectElementCompleted(){}setInjectedScriptForOrigin(e,r){}inspectedURLChanged(e){document.title=f(k.devtoolsS,{PH1:e.replace(/^https?:\/\//,"")})}copyText(e){null!=e&&navigator.clipboard.writeText(e)}openInNewTab(e){window.open(e,"_blank")}openSearchResultsInNewTab(e){o.Console.Console.instance().error("Search is not enabled in hosted mode. Please inspect using chrome://inspect")}showItemInFolder(e){o.Console.Console.instance().error("Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect")}save(e,r,o){let t=this.#e.get(e);t||(t=[],this.#e.set(e,t)),t.push(r),this.events.dispatchEventToListeners(n.SavedURL,{url:e,fileSystemPath:e})}append(e,r){const o=this.#e.get(e);o&&(o.push(r),this.events.dispatchEventToListeners(n.AppendedToURL,e))}close(r){const o=this.#e.get(r)||[];this.#e.delete(r);let t="";if(r)try{const o=e.StringUtilities.trimURL(r);t=e.StringUtilities.removeURLFragment(o)}catch(e){t=r}const n=document.createElement("a");n.download=t;const s=new Blob([o.join("")],{type:"text/plain"}),i=URL.createObjectURL(s);n.href=i,n.click(),URL.revokeObjectURL(i)}sendMessageToBackend(e){}recordCountHistogram(e,r,o,t,n){this.recordedCountHistograms.length>=100&&this.recordedCountHistograms.shift(),this.recordedCountHistograms.push({histogramName:e,sample:r,min:o,exclusiveMax:t,bucketSize:n})}recordEnumeratedHistogram(e,r,o){this.recordedEnumeratedHistograms.length>=100&&this.recordedEnumeratedHistograms.shift(),this.recordedEnumeratedHistograms.push({actionName:e,actionCode:r})}recordPerformanceHistogram(e,r){this.recordedPerformanceHistograms.length>=100&&this.recordedPerformanceHistograms.shift(),this.recordedPerformanceHistograms.push({histogramName:e,duration:r})}recordUserMetricsAction(e){}requestFileSystems(){this.events.dispatchEventToListeners(n.FileSystemsLoaded,[])}addFileSystem(e){window.webkitRequestFileSystem(window.TEMPORARY,1048576,(e=>{this.#r=e;const r={fileSystemName:"sandboxedRequestedFileSystem",fileSystemPath:y,rootURL:"filesystem:devtools://devtools/isolated/",type:"overrides"};this.events.dispatchEventToListeners(n.FileSystemAdded,{fileSystem:r})}))}removeFileSystem(e){const r=e=>{e.forEach((e=>{e.isDirectory?e.removeRecursively((()=>{})):e.isFile&&e.remove((()=>{}))}))};this.#r&&this.#r.root.createReader().readEntries(r),this.#r=null,this.events.dispatchEventToListeners(n.FileSystemRemoved,y)}isolatedFileSystem(e,r){return this.#r}loadNetworkResource(e,r,o,t){fetch(e).then((async e=>{const r=await e.arrayBuffer();let o=r;if(function(e){const r=new Uint8Array(e);return!(!r||r.length<3)&&31===r[0]&&139===r[1]&&8===r[2]}(r)){const e=new DecompressionStream("gzip"),t=e.writable.getWriter();t.write(r),t.close(),o=e.readable}return await new Response(o).text()})).then((function(e){p(o,e),t({statusCode:200,headers:void 0,messageOverride:void 0,netError:void 0,netErrorName:void 0,urlValid:void 0})})).catch((function(){t({statusCode:404,headers:void 0,messageOverride:void 0,netError:void 0,netErrorName:void 0,urlValid:void 0})}))}registerPreference(e,r){}getPreferences(e){const r={};for(const e in window.localStorage)r[e]=window.localStorage[e];e(r)}getPreference(e,r){r(window.localStorage[e])}setPreference(e,r){window.localStorage[e]=r}removePreference(e){delete window.localStorage[e]}clearPreferences(){window.localStorage.clear()}getSyncInformation(e){e({isSyncActive:!1,arePreferencesSynced:!1})}upgradeDraggedFileSystemPermissions(e){}indexPath(e,r,o){}stopIndexing(e){}searchInPath(e,r,o){}zoomFactor(){return 1}zoomIn(){}zoomOut(){}resetZoom(){}setWhitelistedShortcuts(e){}setEyeDropperActive(e){}showCertificateViewer(e){}reattach(e){e()}readyForTest(){}connectionReady(){}setOpenNewWindowForPopups(e){}setDevicesDiscoveryConfig(e){}setDevicesUpdatesEnabled(e){}performActionOnRemotePage(e,r){}openRemotePage(e,r){}openNodeFrontend(){}showContextMenuAtPoint(e,r,o,t){throw"Soft context menu should be used"}isHostedMode(){return!0}setAddExtensionCallback(e){}async initialTargetId(){return null}doAidaConversation(e,r,o){o({error:"Not implemened"})}registerAidaClientEvent(e){}recordImpression(e){}recordResize(e){}recordClick(e){}recordHover(e){}recordDrag(e){}recordChange(e){}recordKeyDown(e){}}let I=globalThis.InspectorFrontendHost;class x{constructor(){for(const e of s)this[e[1]]=this.dispatch.bind(this,e[0],e[2],e[3])}dispatch(e,r,o,...t){if(r.length<2){try{I.events.dispatchEventToListeners(e,t[0])}catch(e){console.error(e+" "+e.stack)}return}const n={};for(let e=0;e{let{promise:r,resolve:o,reject:t}=e.PromiseUtilities.promiseWithResolvers();return{write:async n=>{o(n),({promise:r,resolve:o,reject:t}=e.PromiseUtilities.promiseWithResolvers())},close:async()=>{o(null)},read:()=>r,fail:e=>t(e)}})(),t=m(o);let n;I.doAidaConversation(JSON.stringify(P.buildApiRequest(r)),t,(e=>{403===e.statusCode?o.fail(new Error("Server responded: permission denied")):e.error?o.fail(new Error(`Cannot send request: ${e.error} ${e.detail||""}`)):200!==e.statusCode?o.fail(new Error(`Request failed: ${JSON.stringify(e)}`)):o.close()}));const s=[];let i=!1;for(;n=await o.read();){if(!n.length)continue;let e;n.startsWith(",")&&(n=n.slice(1)),n.startsWith("[")||(n="["+n),n.endsWith("]")||(n+="]");try{e=JSON.parse(n)}catch(e){throw new Error("Cannot parse chunk: "+n,{cause:e})}const r="\n`````\n";for(const o of e)if("textChunk"in o)i&&(s.push(r),i=!1),s.push(o.textChunk.text);else{if(!("codeChunk"in o))throw"error"in o?new Error(`Server responded: ${JSON.stringify(o)}`):new Error("Unknown chunk result");i||(s.push(r),i=!0),s.push(o.codeChunk.code)}yield{explanation:s.join("")+(i?r:""),metadata:{rpcGlobalId:e[0]?.metadata?.rpcGlobalId}}}}}var T=Object.freeze({__proto__:null,AidaClient:P});let M,R,F,D,O;function _(){return M||(M=I.platform()),M}var H=Object.freeze({__proto__:null,platform:_,isMac:function(){return void 0===R&&(R="mac"===_()),R},isWin:function(){return void 0===F&&(F="windows"===_()),F},setPlatformForTests:function(e){M=e,R=void 0,F=void 0},isCustomDevtoolsFrontend:function(){return void 0===D&&(D=window.location.toString().startsWith("devtools://devtools/custom/")),D},fontFamily:function(){if(O)return O;switch(_()){case"linux":O="Roboto, Ubuntu, Arial, sans-serif";break;case"mac":O="'Lucida Grande', sans-serif";break;case"windows":O="'Segoe UI', Tahoma, sans-serif"}return O}});let A=null;function L(){return null===A&&(A=new N),A}class N{#o="error";#t=new Set;#n=null;addEventListener(e){this.#t.add(e);return()=>{this.#t.delete(e)}}removeAllEventListeners(){this.#t.clear()}sendEvent(e){if(!0!==globalThis.enableReactNativePerfMetrics)return;const r=this.#s(e),o=[];for(const e of this.#t)try{e(r)}catch(e){o.push(e)}if(o.length>0){const e=new AggregateError(o);console.error("Error occurred when calling event listeners",e)}}registerPerfMetricsGlobalPostMessageHandler(){!0===globalThis.enableReactNativePerfMetrics&&!0===globalThis.enableReactNativePerfMetricsGlobalPostMessage&&this.addEventListener((e=>{window.postMessage({event:e,tag:"react-native-chrome-devtools-perf-metrics"},window.location.origin)}))}registerGlobalErrorReporting(){window.addEventListener("error",(e=>{const[r,o]=W(`[RNPerfMetrics] uncaught error: ${e.message}`,e.error);this.sendEvent({eventName:"Browser.Error",params:{type:"error",message:r,error:o}})}),{passive:!0}),window.addEventListener("unhandledrejection",(e=>{const[r,o]=W("[RNPerfMetrics] unhandled promise rejection",e.reason);this.sendEvent({eventName:"Browser.Error",params:{type:"rejectedPromise",message:r,error:o}})}),{passive:!0});const e=globalThis.console,r=e[this.#o];e[this.#o]=(...o)=>{try{const e=o[0],[r,t]=W("[RNPerfMetrics] console.error",e);this.sendEvent({eventName:"Browser.Error",params:{message:r,error:t,type:"consoleError"}})}catch(e){const[r,o]=W("[RNPerfMetrics] Error handling console.error",e);this.sendEvent({eventName:"Browser.Error",params:{message:r,error:o,type:"consoleError"}})}finally{r.apply(e,o)}}}setLaunchId(e){this.#n=e}entryPointLoadingStarted(e){this.sendEvent({eventName:"Entrypoint.LoadingStarted",entryPoint:e})}entryPointLoadingFinished(e){this.sendEvent({eventName:"Entrypoint.LoadingFinished",entryPoint:e})}browserVisibilityChanged(e){this.sendEvent({eventName:"Browser.VisibilityChange",params:{visibilityState:e}})}remoteDebuggingTerminated(e){this.sendEvent({eventName:"Connection.DebuggingTerminated",params:{reason:e}})}developerResourceLoadingStarted(e,r){const o=U(e);this.sendEvent({eventName:"DeveloperResource.LoadingStarted",params:{url:o,loadingMethod:r}})}developerResourceLoadingFinished(e,r,o){const t=U(e);this.sendEvent({eventName:"DeveloperResource.LoadingFinished",params:{url:t,loadingMethod:r,success:o.success,errorMessage:o.errorDescription?.message}})}fuseboxSetClientMetadataStarted(){this.sendEvent({eventName:"FuseboxSetClientMetadataStarted"})}fuseboxSetClientMetadataFinished(e,r){if(e)this.sendEvent({eventName:"FuseboxSetClientMetadataFinished",params:{success:!0}});else{const[e,o]=W("[RNPerfMetrics] Fusebox setClientMetadata failed",r);this.sendEvent({eventName:"FuseboxSetClientMetadataFinished",params:{success:!1,error:o,errorMessage:e}})}}#s(e){return{...e,...{timestamp:performance.timeOrigin+performance.now(),launchId:this.#n}}}}function U(e){const{url:r}=e;return e.isHttpOrHttps()?r:`${r.slice(0,100)} …(omitted ${r.length-100} characters)`}function W(e,r){if(r instanceof Error){return[`${e}: ${r.message}`,r]}const o=`${e}: ${String(r)}`;return[o,new Error(o,{cause:r})]}var V,B,j,q,G,z,$,X,K,Q,J,Y,Z,ee,re,oe,te=Object.freeze({__proto__:null,getInstance:L});class ne{#i;#a;#d;constructor(){this.#i=!1,this.#a=!1,this.#d=""}breakpointWithConditionAdded(e){e>=2||I.recordEnumeratedHistogram("DevTools.BreakpointWithConditionAdded",e,2)}breakpointEditDialogRevealedFrom(e){e>=7||I.recordEnumeratedHistogram("DevTools.BreakpointEditDialogRevealedFrom",e,7)}panelShown(e,r){const o=B[e]||0;I.recordEnumeratedHistogram("DevTools.PanelShown",o,B.MaxValue),I.recordUserMetricsAction("DevTools_PanelShown_"+e),r||(this.#i=!0)}panelClosed(e){const r=B[e]||0;I.recordEnumeratedHistogram("DevTools.PanelClosed",r,B.MaxValue),this.#i=!0}panelShownInLocation(e,r){const o=j[`${e}-${r}`]||0;I.recordEnumeratedHistogram("DevTools.PanelShownInLocation",o,j.MaxValue)}elementsSidebarTabShown(e){const r=q[e]||0;I.recordEnumeratedHistogram("DevTools.Elements.SidebarTabShown",r,q.MaxValue)}sourcesSidebarTabShown(e){const r=G[e]||0;I.recordEnumeratedHistogram("DevTools.Sources.SidebarTabShown",r,G.MaxValue)}settingsPanelShown(e){this.panelShown("settings-"+e)}sourcesPanelFileDebugged(e){const r=e&&z[e]||z.Unknown;I.recordEnumeratedHistogram("DevTools.SourcesPanelFileDebugged",r,z.MaxValue)}sourcesPanelFileOpened(e){const r=e&&z[e]||z.Unknown;I.recordEnumeratedHistogram("DevTools.SourcesPanelFileOpened",r,z.MaxValue)}networkPanelResponsePreviewOpened(e){const r=e&&z[e]||z.Unknown;I.recordEnumeratedHistogram("DevTools.NetworkPanelResponsePreviewOpened",r,z.MaxValue)}actionTaken(e){I.recordEnumeratedHistogram("DevTools.ActionTaken",e,V.MaxValue)}panelLoaded(e,r){this.#a||e!==this.#d||(this.#a=!0,requestAnimationFrame((()=>{window.setTimeout((()=>{performance.mark(r),this.#i||I.recordPerformanceHistogram(r,performance.now())}),0)})))}setLaunchPanel(e){this.#d=e}performanceTraceLoad(e){I.recordPerformanceHistogram("DevTools.TraceLoad",e.duration)}keybindSetSettingChanged(e){const r=$[e]||0;I.recordEnumeratedHistogram("DevTools.KeybindSetSettingChanged",r,$.MaxValue)}keyboardShortcutFired(e){const r=X[e]||X.OtherShortcut;I.recordEnumeratedHistogram("DevTools.KeyboardShortcutFired",r,X.MaxValue)}issuesPanelOpenedFrom(e){I.recordEnumeratedHistogram("DevTools.IssuesPanelOpenedFrom",e,6)}issuesPanelIssueExpanded(e){if(void 0===e)return;const r=Q[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.IssuesPanelIssueExpanded",r,Q.MaxValue)}issuesPanelResourceOpened(e,r){const o=J[e+r];void 0!==o&&I.recordEnumeratedHistogram("DevTools.IssuesPanelResourceOpened",o,J.MaxValue)}issueCreated(e){const r=Y[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.IssueCreated",r,Y.MaxValue)}experimentEnabledAtLaunch(e){const r=K[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.ExperimentEnabledAtLaunch",r,K.MaxValue)}experimentDisabledAtLaunch(e){const r=K[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.ExperimentDisabledAtLaunch",r,K.MaxValue)}experimentChanged(e,r){const o=K[e];if(void 0===o)return;const t=r?"DevTools.ExperimentEnabled":"DevTools.ExperimentDisabled";I.recordEnumeratedHistogram(t,o,K.MaxValue)}developerResourceLoaded(e){e>=8||I.recordEnumeratedHistogram("DevTools.DeveloperResourceLoaded",e,8)}developerResourceScheme(e){e>=9||I.recordEnumeratedHistogram("DevTools.DeveloperResourceScheme",e,9)}inlineScriptParsed(e){e>=2||I.recordEnumeratedHistogram("DevTools.InlineScriptParsed",e,2)}vmInlineScriptContentShown(e){e>=2||I.recordEnumeratedHistogram("DevTools.VMInlineScriptShown",e,2)}language(e){const r=re[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.Language",r,re.MaxValue)}syncSetting(e){I.getSyncInformation((r=>{let o=1;r.isSyncActive&&!r.arePreferencesSynced?o=2:r.isSyncActive&&r.arePreferencesSynced&&(o=e?4:3),I.recordEnumeratedHistogram("DevTools.SyncSetting",o,5)}))}recordingAssertion(e){I.recordEnumeratedHistogram("DevTools.RecordingAssertion",e,4)}recordingToggled(e){I.recordEnumeratedHistogram("DevTools.RecordingToggled",e,3)}recordingReplayFinished(e){I.recordEnumeratedHistogram("DevTools.RecordingReplayFinished",e,5)}recordingReplaySpeed(e){I.recordEnumeratedHistogram("DevTools.RecordingReplaySpeed",e,5)}recordingReplayStarted(e){I.recordEnumeratedHistogram("DevTools.RecordingReplayStarted",e,4)}recordingEdited(e){I.recordEnumeratedHistogram("DevTools.RecordingEdited",e,11)}recordingExported(e){I.recordEnumeratedHistogram("DevTools.RecordingExported",e,6)}recordingCodeToggled(e){I.recordEnumeratedHistogram("DevTools.RecordingCodeToggled",e,3)}recordingCopiedToClipboard(e){I.recordEnumeratedHistogram("DevTools.RecordingCopiedToClipboard",e,9)}styleTextCopied(e){I.recordEnumeratedHistogram("DevTools.StyleTextCopied",e,11)}manifestSectionSelected(e){const r=oe[e]||oe.OtherSection;I.recordEnumeratedHistogram("DevTools.ManifestSectionSelected",r,oe.MaxValue)}cssHintShown(e){I.recordEnumeratedHistogram("DevTools.CSSHintShown",e,14)}lighthouseModeRun(e){I.recordEnumeratedHistogram("DevTools.LighthouseModeRun",e,4)}lighthouseCategoryUsed(e){I.recordEnumeratedHistogram("DevTools.LighthouseCategoryUsed",e,6)}colorConvertedFrom(e){I.recordEnumeratedHistogram("DevTools.ColorConvertedFrom",e,2)}colorPickerOpenedFrom(e){I.recordEnumeratedHistogram("DevTools.ColorPickerOpenedFrom",e,2)}cssPropertyDocumentation(e){I.recordEnumeratedHistogram("DevTools.CSSPropertyDocumentation",e,3)}swatchActivated(e){I.recordEnumeratedHistogram("DevTools.SwatchActivated",e,10)}badgeActivated(e){I.recordEnumeratedHistogram("DevTools.BadgeActivated",e,9)}breakpointsRestoredFromStorage(e){const r=this.#c(e);I.recordEnumeratedHistogram("DevTools.BreakpointsRestoredFromStorageCount",r,10)}animationPlaybackRateChanged(e){I.recordEnumeratedHistogram("DevTools.AnimationPlaybackRateChanged",e,4)}animationPointDragged(e){I.recordEnumeratedHistogram("DevTools.AnimationPointDragged",e,5)}#c(e){return e<100?0:e<300?1:e<1e3?2:e<3e3?3:e<1e4?4:e<3e4?5:e<1e5?6:e<3e5?7:e<1e6?8:9}workspacesPopulated(e){I.recordPerformanceHistogram("DevTools.Workspaces.PopulateWallClocktime",e)}visualLoggingProcessingDone(e){I.recordPerformanceHistogram("DevTools.VisualLogging.ProcessingTime",e)}legacyResourceTypeFilterNumberOfSelectedChanged(e){const r=Math.max(Math.min(e,Z.MaxValue-1),1);I.recordEnumeratedHistogram("DevTools.LegacyResourceTypeFilterNumberOfSelectedChanged",r,Z.MaxValue)}legacyResourceTypeFilterItemSelected(e){const r=Z[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.LegacyResourceTypeFilterItemSelected",r,Z.MaxValue)}resourceTypeFilterNumberOfSelectedChanged(e){const r=Math.max(Math.min(e,Z.MaxValue-1),1);I.recordEnumeratedHistogram("DevTools.ResourceTypeFilterNumberOfSelectedChanged",r,Z.MaxValue)}resourceTypeFilterItemSelected(e){const r=Z[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.ResourceTypeFilterItemSelected",r,Z.MaxValue)}networkPanelMoreFiltersNumberOfSelectedChanged(e){const r=Math.max(Math.min(e,ee.MaxValue),0);I.recordEnumeratedHistogram("DevTools.NetworkPanelMoreFiltersNumberOfSelectedChanged",r,ee.MaxValue)}networkPanelMoreFiltersItemSelected(e){const r=ee[e];void 0!==r&&I.recordEnumeratedHistogram("DevTools.NetworkPanelMoreFiltersItemSelected",r,ee.MaxValue)}}!function(e){e[e.WindowDocked=1]="WindowDocked",e[e.WindowUndocked=2]="WindowUndocked",e[e.ScriptsBreakpointSet=3]="ScriptsBreakpointSet",e[e.TimelineStarted=4]="TimelineStarted",e[e.ProfilesCPUProfileTaken=5]="ProfilesCPUProfileTaken",e[e.ProfilesHeapProfileTaken=6]="ProfilesHeapProfileTaken",e[e.ConsoleEvaluated=8]="ConsoleEvaluated",e[e.FileSavedInWorkspace=9]="FileSavedInWorkspace",e[e.DeviceModeEnabled=10]="DeviceModeEnabled",e[e.AnimationsPlaybackRateChanged=11]="AnimationsPlaybackRateChanged",e[e.RevisionApplied=12]="RevisionApplied",e[e.FileSystemDirectoryContentReceived=13]="FileSystemDirectoryContentReceived",e[e.StyleRuleEdited=14]="StyleRuleEdited",e[e.CommandEvaluatedInConsolePanel=15]="CommandEvaluatedInConsolePanel",e[e.DOMPropertiesExpanded=16]="DOMPropertiesExpanded",e[e.ResizedViewInResponsiveMode=17]="ResizedViewInResponsiveMode",e[e.TimelinePageReloadStarted=18]="TimelinePageReloadStarted",e[e.ConnectToNodeJSFromFrontend=19]="ConnectToNodeJSFromFrontend",e[e.ConnectToNodeJSDirectly=20]="ConnectToNodeJSDirectly",e[e.CpuThrottlingEnabled=21]="CpuThrottlingEnabled",e[e.CpuProfileNodeFocused=22]="CpuProfileNodeFocused",e[e.CpuProfileNodeExcluded=23]="CpuProfileNodeExcluded",e[e.SelectFileFromFilePicker=24]="SelectFileFromFilePicker",e[e.SelectCommandFromCommandMenu=25]="SelectCommandFromCommandMenu",e[e.ChangeInspectedNodeInElementsPanel=26]="ChangeInspectedNodeInElementsPanel",e[e.StyleRuleCopied=27]="StyleRuleCopied",e[e.CoverageStarted=28]="CoverageStarted",e[e.LighthouseStarted=29]="LighthouseStarted",e[e.LighthouseFinished=30]="LighthouseFinished",e[e.ShowedThirdPartyBadges=31]="ShowedThirdPartyBadges",e[e.LighthouseViewTrace=32]="LighthouseViewTrace",e[e.FilmStripStartedRecording=33]="FilmStripStartedRecording",e[e.CoverageReportFiltered=34]="CoverageReportFiltered",e[e.CoverageStartedPerBlock=35]="CoverageStartedPerBlock",e[e["SettingsOpenedFromGear-deprecated"]=36]="SettingsOpenedFromGear-deprecated",e[e["SettingsOpenedFromMenu-deprecated"]=37]="SettingsOpenedFromMenu-deprecated",e[e["SettingsOpenedFromCommandMenu-deprecated"]=38]="SettingsOpenedFromCommandMenu-deprecated",e[e.TabMovedToDrawer=39]="TabMovedToDrawer",e[e.TabMovedToMainPanel=40]="TabMovedToMainPanel",e[e.CaptureCssOverviewClicked=41]="CaptureCssOverviewClicked",e[e.VirtualAuthenticatorEnvironmentEnabled=42]="VirtualAuthenticatorEnvironmentEnabled",e[e.SourceOrderViewActivated=43]="SourceOrderViewActivated",e[e.UserShortcutAdded=44]="UserShortcutAdded",e[e.ShortcutRemoved=45]="ShortcutRemoved",e[e.ShortcutModified=46]="ShortcutModified",e[e.CustomPropertyLinkClicked=47]="CustomPropertyLinkClicked",e[e.CustomPropertyEdited=48]="CustomPropertyEdited",e[e.ServiceWorkerNetworkRequestClicked=49]="ServiceWorkerNetworkRequestClicked",e[e.ServiceWorkerNetworkRequestClosedQuickly=50]="ServiceWorkerNetworkRequestClosedQuickly",e[e.NetworkPanelServiceWorkerRespondWith=51]="NetworkPanelServiceWorkerRespondWith",e[e.NetworkPanelCopyValue=52]="NetworkPanelCopyValue",e[e.ConsoleSidebarOpened=53]="ConsoleSidebarOpened",e[e.PerfPanelTraceImported=54]="PerfPanelTraceImported",e[e.PerfPanelTraceExported=55]="PerfPanelTraceExported",e[e.StackFrameRestarted=56]="StackFrameRestarted",e[e.CaptureTestProtocolClicked=57]="CaptureTestProtocolClicked",e[e.BreakpointRemovedFromRemoveButton=58]="BreakpointRemovedFromRemoveButton",e[e.BreakpointGroupExpandedStateChanged=59]="BreakpointGroupExpandedStateChanged",e[e.HeaderOverrideFileCreated=60]="HeaderOverrideFileCreated",e[e.HeaderOverrideEnableEditingClicked=61]="HeaderOverrideEnableEditingClicked",e[e.HeaderOverrideHeaderAdded=62]="HeaderOverrideHeaderAdded",e[e.HeaderOverrideHeaderEdited=63]="HeaderOverrideHeaderEdited",e[e.HeaderOverrideHeaderRemoved=64]="HeaderOverrideHeaderRemoved",e[e.HeaderOverrideHeadersFileEdited=65]="HeaderOverrideHeadersFileEdited",e[e.PersistenceNetworkOverridesEnabled=66]="PersistenceNetworkOverridesEnabled",e[e.PersistenceNetworkOverridesDisabled=67]="PersistenceNetworkOverridesDisabled",e[e.BreakpointRemovedFromContextMenu=68]="BreakpointRemovedFromContextMenu",e[e.BreakpointsInFileRemovedFromRemoveButton=69]="BreakpointsInFileRemovedFromRemoveButton",e[e.BreakpointsInFileRemovedFromContextMenu=70]="BreakpointsInFileRemovedFromContextMenu",e[e.BreakpointsInFileCheckboxToggled=71]="BreakpointsInFileCheckboxToggled",e[e.BreakpointsInFileEnabledDisabledFromContextMenu=72]="BreakpointsInFileEnabledDisabledFromContextMenu",e[e.BreakpointConditionEditedFromSidebar=73]="BreakpointConditionEditedFromSidebar",e[e.WorkspaceTabAddFolder=74]="WorkspaceTabAddFolder",e[e.WorkspaceTabRemoveFolder=75]="WorkspaceTabRemoveFolder",e[e.OverrideTabAddFolder=76]="OverrideTabAddFolder",e[e.OverrideTabRemoveFolder=77]="OverrideTabRemoveFolder",e[e.WorkspaceSourceSelected=78]="WorkspaceSourceSelected",e[e.OverridesSourceSelected=79]="OverridesSourceSelected",e[e.StyleSheetInitiatorLinkClicked=80]="StyleSheetInitiatorLinkClicked",e[e.BreakpointRemovedFromGutterContextMenu=81]="BreakpointRemovedFromGutterContextMenu",e[e.BreakpointRemovedFromGutterToggle=82]="BreakpointRemovedFromGutterToggle",e[e.StylePropertyInsideKeyframeEdited=83]="StylePropertyInsideKeyframeEdited",e[e.OverrideContentFromSourcesContextMenu=84]="OverrideContentFromSourcesContextMenu",e[e.OverrideContentFromNetworkContextMenu=85]="OverrideContentFromNetworkContextMenu",e[e.OverrideScript=86]="OverrideScript",e[e.OverrideStyleSheet=87]="OverrideStyleSheet",e[e.OverrideDocument=88]="OverrideDocument",e[e.OverrideFetchXHR=89]="OverrideFetchXHR",e[e.OverrideImage=90]="OverrideImage",e[e.OverrideFont=91]="OverrideFont",e[e.OverrideContentContextMenuSetup=92]="OverrideContentContextMenuSetup",e[e.OverrideContentContextMenuAbandonSetup=93]="OverrideContentContextMenuAbandonSetup",e[e.OverrideContentContextMenuActivateDisabled=94]="OverrideContentContextMenuActivateDisabled",e[e.OverrideContentContextMenuOpenExistingFile=95]="OverrideContentContextMenuOpenExistingFile",e[e.OverrideContentContextMenuSaveNewFile=96]="OverrideContentContextMenuSaveNewFile",e[e.ShowAllOverridesFromSourcesContextMenu=97]="ShowAllOverridesFromSourcesContextMenu",e[e.ShowAllOverridesFromNetworkContextMenu=98]="ShowAllOverridesFromNetworkContextMenu",e[e.AnimationGroupsCleared=99]="AnimationGroupsCleared",e[e.AnimationsPaused=100]="AnimationsPaused",e[e.AnimationsResumed=101]="AnimationsResumed",e[e.AnimatedNodeDescriptionClicked=102]="AnimatedNodeDescriptionClicked",e[e.AnimationGroupScrubbed=103]="AnimationGroupScrubbed",e[e.AnimationGroupReplayed=104]="AnimationGroupReplayed",e[e.OverrideTabDeleteFolderContextMenu=105]="OverrideTabDeleteFolderContextMenu",e[e.WorkspaceDropFolder=107]="WorkspaceDropFolder",e[e.WorkspaceSelectFolder=108]="WorkspaceSelectFolder",e[e.OverrideContentContextMenuSourceMappedWarning=109]="OverrideContentContextMenuSourceMappedWarning",e[e.OverrideContentContextMenuRedirectToDeployed=110]="OverrideContentContextMenuRedirectToDeployed",e[e.NewStyleRuleAdded=111]="NewStyleRuleAdded",e[e.TraceExpanded=112]="TraceExpanded",e[e.InsightConsoleMessageShown=113]="InsightConsoleMessageShown",e[e.InsightRequestedViaContextMenu=114]="InsightRequestedViaContextMenu",e[e.InsightRequestedViaHoverButton=115]="InsightRequestedViaHoverButton",e[e.InsightRatedPositive=117]="InsightRatedPositive",e[e.InsightRatedNegative=118]="InsightRatedNegative",e[e.InsightClosed=119]="InsightClosed",e[e.InsightErrored=120]="InsightErrored",e[e.InsightHoverButtonShown=121]="InsightHoverButtonShown",e[e.SelfXssWarningConsoleMessageShown=122]="SelfXssWarningConsoleMessageShown",e[e.SelfXssWarningDialogShown=123]="SelfXssWarningDialogShown",e[e.SelfXssAllowPastingInConsole=124]="SelfXssAllowPastingInConsole",e[e.SelfXssAllowPastingInDialog=125]="SelfXssAllowPastingInDialog",e[e.ToggleEmulateFocusedPageFromStylesPaneOn=126]="ToggleEmulateFocusedPageFromStylesPaneOn",e[e.ToggleEmulateFocusedPageFromStylesPaneOff=127]="ToggleEmulateFocusedPageFromStylesPaneOff",e[e.ToggleEmulateFocusedPageFromRenderingTab=128]="ToggleEmulateFocusedPageFromRenderingTab",e[e.ToggleEmulateFocusedPageFromCommandMenu=129]="ToggleEmulateFocusedPageFromCommandMenu",e[e.InsightGenerated=130]="InsightGenerated",e[e.InsightErroredApi=131]="InsightErroredApi",e[e.InsightErroredMarkdown=132]="InsightErroredMarkdown",e[e.ToggleShowWebVitals=133]="ToggleShowWebVitals",e[e.InsightErroredPermissionDenied=134]="InsightErroredPermissionDenied",e[e.InsightErroredCannotSend=135]="InsightErroredCannotSend",e[e.InsightErroredRequestFailed=136]="InsightErroredRequestFailed",e[e.InsightErroredCannotParseChunk=137]="InsightErroredCannotParseChunk",e[e.InsightErroredUnknownChunk=138]="InsightErroredUnknownChunk",e[e.InsightErroredOther=139]="InsightErroredOther",e[e.MaxValue=140]="MaxValue"}(V||(V={})),function(e){e[e.elements=1]="elements",e[e.resources=2]="resources",e[e.network=3]="network",e[e.sources=4]="sources",e[e.timeline=5]="timeline",e[e["heap-profiler"]=6]="heap-profiler",e[e.console=8]="console",e[e.layers=9]="layers",e[e["console-view"]=10]="console-view",e[e.animations=11]="animations",e[e["network.config"]=12]="network.config",e[e.rendering=13]="rendering",e[e.sensors=14]="sensors",e[e["sources.search"]=15]="sources.search",e[e.security=16]="security",e[e["js-profiler"]=17]="js-profiler",e[e.lighthouse=18]="lighthouse",e[e.coverage=19]="coverage",e[e["protocol-monitor"]=20]="protocol-monitor",e[e["remote-devices"]=21]="remote-devices",e[e["web-audio"]=22]="web-audio",e[e["changes.changes"]=23]="changes.changes",e[e["performance.monitor"]=24]="performance.monitor",e[e["release-note"]=25]="release-note",e[e["live-heap-profile"]=26]="live-heap-profile",e[e["sources.quick"]=27]="sources.quick",e[e["network.blocked-urls"]=28]="network.blocked-urls",e[e["settings-preferences"]=29]="settings-preferences",e[e["settings-workspace"]=30]="settings-workspace",e[e["settings-experiments"]=31]="settings-experiments",e[e["settings-blackbox"]=32]="settings-blackbox",e[e["settings-devices"]=33]="settings-devices",e[e["settings-throttling-conditions"]=34]="settings-throttling-conditions",e[e["settings-emulation-locations"]=35]="settings-emulation-locations",e[e["settings-shortcuts"]=36]="settings-shortcuts",e[e["issues-pane"]=37]="issues-pane",e[e["settings-keybinds"]=38]="settings-keybinds",e[e.cssoverview=39]="cssoverview",e[e["chrome-recorder"]=40]="chrome-recorder",e[e["trust-tokens"]=41]="trust-tokens",e[e["reporting-api"]=42]="reporting-api",e[e["interest-groups"]=43]="interest-groups",e[e["back-forward-cache"]=44]="back-forward-cache",e[e["service-worker-cache"]=45]="service-worker-cache",e[e["background-service-background-fetch"]=46]="background-service-background-fetch",e[e["background-service-background-sync"]=47]="background-service-background-sync",e[e["background-service-push-messaging"]=48]="background-service-push-messaging",e[e["background-service-notifications"]=49]="background-service-notifications",e[e["background-service-payment-handler"]=50]="background-service-payment-handler",e[e["background-service-periodic-background-sync"]=51]="background-service-periodic-background-sync",e[e["service-workers"]=52]="service-workers",e[e["app-manifest"]=53]="app-manifest",e[e.storage=54]="storage",e[e.cookies=55]="cookies",e[e["frame-details"]=56]="frame-details",e[e["frame-resource"]=57]="frame-resource",e[e["frame-window"]=58]="frame-window",e[e["frame-worker"]=59]="frame-worker",e[e["dom-storage"]=60]="dom-storage",e[e["indexed-db"]=61]="indexed-db",e[e["web-sql"]=62]="web-sql",e[e["performance-insights"]=63]="performance-insights",e[e.preloading=64]="preloading",e[e["bounce-tracking-mitigations"]=65]="bounce-tracking-mitigations",e[e["developer-resources"]=66]="developer-resources",e[e["autofill-view"]=67]="autofill-view",e[e.MaxValue=68]="MaxValue"}(B||(B={})),function(e){e[e["elements-main"]=1]="elements-main",e[e["elements-drawer"]=2]="elements-drawer",e[e["resources-main"]=3]="resources-main",e[e["resources-drawer"]=4]="resources-drawer",e[e["network-main"]=5]="network-main",e[e["network-drawer"]=6]="network-drawer",e[e["sources-main"]=7]="sources-main",e[e["sources-drawer"]=8]="sources-drawer",e[e["timeline-main"]=9]="timeline-main",e[e["timeline-drawer"]=10]="timeline-drawer",e[e["heap_profiler-main"]=11]="heap_profiler-main",e[e["heap_profiler-drawer"]=12]="heap_profiler-drawer",e[e["console-main"]=13]="console-main",e[e["console-drawer"]=14]="console-drawer",e[e["layers-main"]=15]="layers-main",e[e["layers-drawer"]=16]="layers-drawer",e[e["console-view-main"]=17]="console-view-main",e[e["console-view-drawer"]=18]="console-view-drawer",e[e["animations-main"]=19]="animations-main",e[e["animations-drawer"]=20]="animations-drawer",e[e["network.config-main"]=21]="network.config-main",e[e["network.config-drawer"]=22]="network.config-drawer",e[e["rendering-main"]=23]="rendering-main",e[e["rendering-drawer"]=24]="rendering-drawer",e[e["sensors-main"]=25]="sensors-main",e[e["sensors-drawer"]=26]="sensors-drawer",e[e["sources.search-main"]=27]="sources.search-main",e[e["sources.search-drawer"]=28]="sources.search-drawer",e[e["security-main"]=29]="security-main",e[e["security-drawer"]=30]="security-drawer",e[e["js_profiler-main"]=31]="js_profiler-main",e[e["js_profiler-drawer"]=32]="js_profiler-drawer",e[e["lighthouse-main"]=33]="lighthouse-main",e[e["lighthouse-drawer"]=34]="lighthouse-drawer",e[e["coverage-main"]=35]="coverage-main",e[e["coverage-drawer"]=36]="coverage-drawer",e[e["protocol-monitor-main"]=37]="protocol-monitor-main",e[e["protocol-monitor-drawer"]=38]="protocol-monitor-drawer",e[e["remote-devices-main"]=39]="remote-devices-main",e[e["remote-devices-drawer"]=40]="remote-devices-drawer",e[e["web-audio-main"]=41]="web-audio-main",e[e["web-audio-drawer"]=42]="web-audio-drawer",e[e["changes.changes-main"]=43]="changes.changes-main",e[e["changes.changes-drawer"]=44]="changes.changes-drawer",e[e["performance.monitor-main"]=45]="performance.monitor-main",e[e["performance.monitor-drawer"]=46]="performance.monitor-drawer",e[e["release-note-main"]=47]="release-note-main",e[e["release-note-drawer"]=48]="release-note-drawer",e[e["live_heap_profile-main"]=49]="live_heap_profile-main",e[e["live_heap_profile-drawer"]=50]="live_heap_profile-drawer",e[e["sources.quick-main"]=51]="sources.quick-main",e[e["sources.quick-drawer"]=52]="sources.quick-drawer",e[e["network.blocked-urls-main"]=53]="network.blocked-urls-main",e[e["network.blocked-urls-drawer"]=54]="network.blocked-urls-drawer",e[e["settings-preferences-main"]=55]="settings-preferences-main",e[e["settings-preferences-drawer"]=56]="settings-preferences-drawer",e[e["settings-workspace-main"]=57]="settings-workspace-main",e[e["settings-workspace-drawer"]=58]="settings-workspace-drawer",e[e["settings-experiments-main"]=59]="settings-experiments-main",e[e["settings-experiments-drawer"]=60]="settings-experiments-drawer",e[e["settings-blackbox-main"]=61]="settings-blackbox-main",e[e["settings-blackbox-drawer"]=62]="settings-blackbox-drawer",e[e["settings-devices-main"]=63]="settings-devices-main",e[e["settings-devices-drawer"]=64]="settings-devices-drawer",e[e["settings-throttling-conditions-main"]=65]="settings-throttling-conditions-main",e[e["settings-throttling-conditions-drawer"]=66]="settings-throttling-conditions-drawer",e[e["settings-emulation-locations-main"]=67]="settings-emulation-locations-main",e[e["settings-emulation-locations-drawer"]=68]="settings-emulation-locations-drawer",e[e["settings-shortcuts-main"]=69]="settings-shortcuts-main",e[e["settings-shortcuts-drawer"]=70]="settings-shortcuts-drawer",e[e["issues-pane-main"]=71]="issues-pane-main",e[e["issues-pane-drawer"]=72]="issues-pane-drawer",e[e["settings-keybinds-main"]=73]="settings-keybinds-main",e[e["settings-keybinds-drawer"]=74]="settings-keybinds-drawer",e[e["cssoverview-main"]=75]="cssoverview-main",e[e["cssoverview-drawer"]=76]="cssoverview-drawer",e[e["chrome_recorder-main"]=77]="chrome_recorder-main",e[e["chrome_recorder-drawer"]=78]="chrome_recorder-drawer",e[e["trust_tokens-main"]=79]="trust_tokens-main",e[e["trust_tokens-drawer"]=80]="trust_tokens-drawer",e[e["reporting_api-main"]=81]="reporting_api-main",e[e["reporting_api-drawer"]=82]="reporting_api-drawer",e[e["interest_groups-main"]=83]="interest_groups-main",e[e["interest_groups-drawer"]=84]="interest_groups-drawer",e[e["back_forward_cache-main"]=85]="back_forward_cache-main",e[e["back_forward_cache-drawer"]=86]="back_forward_cache-drawer",e[e["service_worker_cache-main"]=87]="service_worker_cache-main",e[e["service_worker_cache-drawer"]=88]="service_worker_cache-drawer",e[e["background_service_backgroundFetch-main"]=89]="background_service_backgroundFetch-main",e[e["background_service_backgroundFetch-drawer"]=90]="background_service_backgroundFetch-drawer",e[e["background_service_backgroundSync-main"]=91]="background_service_backgroundSync-main",e[e["background_service_backgroundSync-drawer"]=92]="background_service_backgroundSync-drawer",e[e["background_service_pushMessaging-main"]=93]="background_service_pushMessaging-main",e[e["background_service_pushMessaging-drawer"]=94]="background_service_pushMessaging-drawer",e[e["background_service_notifications-main"]=95]="background_service_notifications-main",e[e["background_service_notifications-drawer"]=96]="background_service_notifications-drawer",e[e["background_service_paymentHandler-main"]=97]="background_service_paymentHandler-main",e[e["background_service_paymentHandler-drawer"]=98]="background_service_paymentHandler-drawer",e[e["background_service_periodicBackgroundSync-main"]=99]="background_service_periodicBackgroundSync-main",e[e["background_service_periodicBackgroundSync-drawer"]=100]="background_service_periodicBackgroundSync-drawer",e[e["service_workers-main"]=101]="service_workers-main",e[e["service_workers-drawer"]=102]="service_workers-drawer",e[e["app_manifest-main"]=103]="app_manifest-main",e[e["app_manifest-drawer"]=104]="app_manifest-drawer",e[e["storage-main"]=105]="storage-main",e[e["storage-drawer"]=106]="storage-drawer",e[e["cookies-main"]=107]="cookies-main",e[e["cookies-drawer"]=108]="cookies-drawer",e[e["frame_details-main"]=109]="frame_details-main",e[e["frame_details-drawer"]=110]="frame_details-drawer",e[e["frame_resource-main"]=111]="frame_resource-main",e[e["frame_resource-drawer"]=112]="frame_resource-drawer",e[e["frame_window-main"]=113]="frame_window-main",e[e["frame_window-drawer"]=114]="frame_window-drawer",e[e["frame_worker-main"]=115]="frame_worker-main",e[e["frame_worker-drawer"]=116]="frame_worker-drawer",e[e["dom_storage-main"]=117]="dom_storage-main",e[e["dom_storage-drawer"]=118]="dom_storage-drawer",e[e["indexed_db-main"]=119]="indexed_db-main",e[e["indexed_db-drawer"]=120]="indexed_db-drawer",e[e["web_sql-main"]=121]="web_sql-main",e[e["web_sql-drawer"]=122]="web_sql-drawer",e[e["performance_insights-main"]=123]="performance_insights-main",e[e["performance_insights-drawer"]=124]="performance_insights-drawer",e[e["preloading-main"]=125]="preloading-main",e[e["preloading-drawer"]=126]="preloading-drawer",e[e["bounce_tracking_mitigations-main"]=127]="bounce_tracking_mitigations-main",e[e["bounce_tracking_mitigations-drawer"]=128]="bounce_tracking_mitigations-drawer",e[e["developer-resources-main"]=129]="developer-resources-main",e[e["developer-resources-drawer"]=130]="developer-resources-drawer",e[e["autofill-view-main"]=131]="autofill-view-main",e[e["autofill-view-drawer"]=132]="autofill-view-drawer",e[e.MaxValue=133]="MaxValue"}(j||(j={})),function(e){e[e.OtherSidebarPane=0]="OtherSidebarPane",e[e.styles=1]="styles",e[e.computed=2]="computed",e[e["elements.layout"]=3]="elements.layout",e[e["elements.event-listeners"]=4]="elements.event-listeners",e[e["elements.dom-breakpoints"]=5]="elements.dom-breakpoints",e[e["elements.dom-properties"]=6]="elements.dom-properties",e[e["accessibility.view"]=7]="accessibility.view",e[e.MaxValue=8]="MaxValue"}(q||(q={})),function(e){e[e.OtherSidebarPane=0]="OtherSidebarPane",e[e["navigator-network"]=1]="navigator-network",e[e["navigator-files"]=2]="navigator-files",e[e["navigator-overrides"]=3]="navigator-overrides",e[e["navigator-content-scripts"]=4]="navigator-content-scripts",e[e["navigator-snippets"]=5]="navigator-snippets",e[e.MaxValue=6]="MaxValue"}(G||(G={})),function(e){e[e.Unknown=0]="Unknown",e[e["text/css"]=2]="text/css",e[e["text/html"]=3]="text/html",e[e["application/xml"]=4]="application/xml",e[e["application/wasm"]=5]="application/wasm",e[e["application/manifest+json"]=6]="application/manifest+json",e[e["application/x-aspx"]=7]="application/x-aspx",e[e["application/jsp"]=8]="application/jsp",e[e["text/x-c++src"]=9]="text/x-c++src",e[e["text/x-coffeescript"]=10]="text/x-coffeescript",e[e["application/vnd.dart"]=11]="application/vnd.dart",e[e["text/typescript"]=12]="text/typescript",e[e["text/typescript-jsx"]=13]="text/typescript-jsx",e[e["application/json"]=14]="application/json",e[e["text/x-csharp"]=15]="text/x-csharp",e[e["text/x-java"]=16]="text/x-java",e[e["text/x-less"]=17]="text/x-less",e[e["application/x-httpd-php"]=18]="application/x-httpd-php",e[e["text/x-python"]=19]="text/x-python",e[e["text/x-sh"]=20]="text/x-sh",e[e["text/x-gss"]=21]="text/x-gss",e[e["text/x-sass"]=22]="text/x-sass",e[e["text/x-scss"]=23]="text/x-scss",e[e["text/markdown"]=24]="text/markdown",e[e["text/x-clojure"]=25]="text/x-clojure",e[e["text/jsx"]=26]="text/jsx",e[e["text/x-go"]=27]="text/x-go",e[e["text/x-kotlin"]=28]="text/x-kotlin",e[e["text/x-scala"]=29]="text/x-scala",e[e["text/x.svelte"]=30]="text/x.svelte",e[e["text/javascript+plain"]=31]="text/javascript+plain",e[e["text/javascript+minified"]=32]="text/javascript+minified",e[e["text/javascript+sourcemapped"]=33]="text/javascript+sourcemapped",e[e["text/x.angular"]=34]="text/x.angular",e[e["text/x.vue"]=35]="text/x.vue",e[e.MaxValue=36]="MaxValue"}(z||(z={})),function(e){e[e.devToolsDefault=0]="devToolsDefault",e[e.vsCode=1]="vsCode",e[e.MaxValue=2]="MaxValue"}($||($={})),function(e){e[e.OtherShortcut=0]="OtherShortcut",e[e["quick-open.show-command-menu"]=1]="quick-open.show-command-menu",e[e["console.clear"]=2]="console.clear",e[e["console.toggle"]=3]="console.toggle",e[e["debugger.step"]=4]="debugger.step",e[e["debugger.step-into"]=5]="debugger.step-into",e[e["debugger.step-out"]=6]="debugger.step-out",e[e["debugger.step-over"]=7]="debugger.step-over",e[e["debugger.toggle-breakpoint"]=8]="debugger.toggle-breakpoint",e[e["debugger.toggle-breakpoint-enabled"]=9]="debugger.toggle-breakpoint-enabled",e[e["debugger.toggle-pause"]=10]="debugger.toggle-pause",e[e["elements.edit-as-html"]=11]="elements.edit-as-html",e[e["elements.hide-element"]=12]="elements.hide-element",e[e["elements.redo"]=13]="elements.redo",e[e["elements.toggle-element-search"]=14]="elements.toggle-element-search",e[e["elements.undo"]=15]="elements.undo",e[e["main.search-in-panel.find"]=16]="main.search-in-panel.find",e[e["main.toggle-drawer"]=17]="main.toggle-drawer",e[e["network.hide-request-details"]=18]="network.hide-request-details",e[e["network.search"]=19]="network.search",e[e["network.toggle-recording"]=20]="network.toggle-recording",e[e["quick-open.show"]=21]="quick-open.show",e[e["settings.show"]=22]="settings.show",e[e["sources.search"]=23]="sources.search",e[e["background-service.toggle-recording"]=24]="background-service.toggle-recording",e[e["components.collect-garbage"]=25]="components.collect-garbage",e[e["console.clear.history"]=26]="console.clear.history",e[e["console.create-pin"]=27]="console.create-pin",e[e["coverage.start-with-reload"]=28]="coverage.start-with-reload",e[e["coverage.toggle-recording"]=29]="coverage.toggle-recording",e[e["debugger.breakpoint-input-window"]=30]="debugger.breakpoint-input-window",e[e["debugger.evaluate-selection"]=31]="debugger.evaluate-selection",e[e["debugger.next-call-frame"]=32]="debugger.next-call-frame",e[e["debugger.previous-call-frame"]=33]="debugger.previous-call-frame",e[e["debugger.run-snippet"]=34]="debugger.run-snippet",e[e["debugger.toggle-breakpoints-active"]=35]="debugger.toggle-breakpoints-active",e[e["elements.capture-area-screenshot"]=36]="elements.capture-area-screenshot",e[e["emulation.capture-full-height-screenshot"]=37]="emulation.capture-full-height-screenshot",e[e["emulation.capture-node-screenshot"]=38]="emulation.capture-node-screenshot",e[e["emulation.capture-screenshot"]=39]="emulation.capture-screenshot",e[e["emulation.show-sensors"]=40]="emulation.show-sensors",e[e["emulation.toggle-device-mode"]=41]="emulation.toggle-device-mode",e[e["help.release-notes"]=42]="help.release-notes",e[e["help.report-issue"]=43]="help.report-issue",e[e["input.start-replaying"]=44]="input.start-replaying",e[e["input.toggle-pause"]=45]="input.toggle-pause",e[e["input.toggle-recording"]=46]="input.toggle-recording",e[e["inspector-main.focus-debuggee"]=47]="inspector-main.focus-debuggee",e[e["inspector-main.hard-reload"]=48]="inspector-main.hard-reload",e[e["inspector-main.reload"]=49]="inspector-main.reload",e[e["live-heap-profile.start-with-reload"]=50]="live-heap-profile.start-with-reload",e[e["live-heap-profile.toggle-recording"]=51]="live-heap-profile.toggle-recording",e[e["main.debug-reload"]=52]="main.debug-reload",e[e["main.next-tab"]=53]="main.next-tab",e[e["main.previous-tab"]=54]="main.previous-tab",e[e["main.search-in-panel.cancel"]=55]="main.search-in-panel.cancel",e[e["main.search-in-panel.find-next"]=56]="main.search-in-panel.find-next",e[e["main.search-in-panel.find-previous"]=57]="main.search-in-panel.find-previous",e[e["main.toggle-dock"]=58]="main.toggle-dock",e[e["main.zoom-in"]=59]="main.zoom-in",e[e["main.zoom-out"]=60]="main.zoom-out",e[e["main.zoom-reset"]=61]="main.zoom-reset",e[e["network-conditions.network-low-end-mobile"]=62]="network-conditions.network-low-end-mobile",e[e["network-conditions.network-mid-tier-mobile"]=63]="network-conditions.network-mid-tier-mobile",e[e["network-conditions.network-offline"]=64]="network-conditions.network-offline",e[e["network-conditions.network-online"]=65]="network-conditions.network-online",e[e["profiler.heap-toggle-recording"]=66]="profiler.heap-toggle-recording",e[e["profiler.js-toggle-recording"]=67]="profiler.js-toggle-recording",e[e["resources.clear"]=68]="resources.clear",e[e["settings.documentation"]=69]="settings.documentation",e[e["settings.shortcuts"]=70]="settings.shortcuts",e[e["sources.add-folder-to-workspace"]=71]="sources.add-folder-to-workspace",e[e["sources.add-to-watch"]=72]="sources.add-to-watch",e[e["sources.close-all"]=73]="sources.close-all",e[e["sources.close-editor-tab"]=74]="sources.close-editor-tab",e[e["sources.create-snippet"]=75]="sources.create-snippet",e[e["sources.go-to-line"]=76]="sources.go-to-line",e[e["sources.go-to-member"]=77]="sources.go-to-member",e[e["sources.jump-to-next-location"]=78]="sources.jump-to-next-location",e[e["sources.jump-to-previous-location"]=79]="sources.jump-to-previous-location",e[e["sources.rename"]=80]="sources.rename",e[e["sources.save"]=81]="sources.save",e[e["sources.save-all"]=82]="sources.save-all",e[e["sources.switch-file"]=83]="sources.switch-file",e[e["timeline.jump-to-next-frame"]=84]="timeline.jump-to-next-frame",e[e["timeline.jump-to-previous-frame"]=85]="timeline.jump-to-previous-frame",e[e["timeline.load-from-file"]=86]="timeline.load-from-file",e[e["timeline.next-recording"]=87]="timeline.next-recording",e[e["timeline.previous-recording"]=88]="timeline.previous-recording",e[e["timeline.record-reload"]=89]="timeline.record-reload",e[e["timeline.save-to-file"]=90]="timeline.save-to-file",e[e["timeline.show-history"]=91]="timeline.show-history",e[e["timeline.toggle-recording"]=92]="timeline.toggle-recording",e[e["sources.increment-css"]=93]="sources.increment-css",e[e["sources.increment-css-by-ten"]=94]="sources.increment-css-by-ten",e[e["sources.decrement-css"]=95]="sources.decrement-css",e[e["sources.decrement-css-by-ten"]=96]="sources.decrement-css-by-ten",e[e["layers.reset-view"]=97]="layers.reset-view",e[e["layers.pan-mode"]=98]="layers.pan-mode",e[e["layers.rotate-mode"]=99]="layers.rotate-mode",e[e["layers.zoom-in"]=100]="layers.zoom-in",e[e["layers.zoom-out"]=101]="layers.zoom-out",e[e["layers.up"]=102]="layers.up",e[e["layers.down"]=103]="layers.down",e[e["layers.left"]=104]="layers.left",e[e["layers.right"]=105]="layers.right",e[e["help.report-translation-issue"]=106]="help.report-translation-issue",e[e["rendering.toggle-prefers-color-scheme"]=107]="rendering.toggle-prefers-color-scheme",e[e["chrome-recorder.start-recording"]=108]="chrome-recorder.start-recording",e[e["chrome-recorder.replay-recording"]=109]="chrome-recorder.replay-recording",e[e["chrome-recorder.toggle-code-view"]=110]="chrome-recorder.toggle-code-view",e[e["chrome-recorder.copy-recording-or-step"]=111]="chrome-recorder.copy-recording-or-step",e[e["changes.revert"]=112]="changes.revert",e[e["changes.copy"]=113]="changes.copy",e[e["elements.new-style-rule"]=114]="elements.new-style-rule",e[e["elements.refresh-event-listeners"]=115]="elements.refresh-event-listeners",e[e["coverage.clear"]=116]="coverage.clear",e[e["coverage.export"]=117]="coverage.export",e[e.MaxValue=118]="MaxValue"}(X||(X={})),function(e){e[e["apply-custom-stylesheet"]=0]="apply-custom-stylesheet",e[e["capture-node-creation-stacks"]=1]="capture-node-creation-stacks",e[e["live-heap-profile"]=11]="live-heap-profile",e[e["protocol-monitor"]=13]="protocol-monitor",e[e["sampling-heap-profiler-timeline"]=17]="sampling-heap-profiler-timeline",e[e["show-option-tp-expose-internals-in-heap-snapshot"]=18]="show-option-tp-expose-internals-in-heap-snapshot",e[e["timeline-invalidation-tracking"]=26]="timeline-invalidation-tracking",e[e["timeline-show-all-events"]=27]="timeline-show-all-events",e[e["timeline-v8-runtime-call-stats"]=28]="timeline-v8-runtime-call-stats",e[e.apca=39]="apca",e[e["font-editor"]=41]="font-editor",e[e["full-accessibility-tree"]=42]="full-accessibility-tree",e[e["ignore-list-js-frames-on-timeline"]=43]="ignore-list-js-frames-on-timeline",e[e["contrast-issues"]=44]="contrast-issues",e[e["experimental-cookie-features"]=45]="experimental-cookie-features",e[e["styles-pane-css-changes"]=55]="styles-pane-css-changes",e[e["evaluate-expressions-with-source-maps"]=58]="evaluate-expressions-with-source-maps",e[e["instrumentation-breakpoints"]=61]="instrumentation-breakpoints",e[e["authored-deployed-grouping"]=63]="authored-deployed-grouping",e[e["important-dom-properties"]=64]="important-dom-properties",e[e["just-my-code"]=65]="just-my-code",e[e["timeline-as-console-profile-result-panel"]=67]="timeline-as-console-profile-result-panel",e[e["preloading-status-panel"]=68]="preloading-status-panel",e[e["outermost-target-selector"]=71]="outermost-target-selector",e[e["js-profiler-temporarily-enable"]=72]="js-profiler-temporarily-enable",e[e["highlight-errors-elements-panel"]=73]="highlight-errors-elements-panel",e[e["set-all-breakpoints-eagerly"]=74]="set-all-breakpoints-eagerly",e[e["self-xss-warning"]=75]="self-xss-warning",e[e["use-source-map-scopes"]=76]="use-source-map-scopes",e[e["storage-buckets-tree"]=77]="storage-buckets-tree",e[e["network-panel-filter-bar-redesign"]=79]="network-panel-filter-bar-redesign",e[e["track-context-menu"]=81]="track-context-menu",e[e["autofill-view"]=82]="autofill-view",e[e["sources-frame-indentation-markers-temporarily-disable"]=83]="sources-frame-indentation-markers-temporarily-disable",e[e["heap-snapshot-treat-backing-store-as-containing-object"]=84]="heap-snapshot-treat-backing-store-as-containing-object",e[e["css-type-component-length-deprecate"]=85]="css-type-component-length-deprecate",e[e.MaxValue=86]="MaxValue"}(K||(K={})),function(e){e[e.CrossOriginEmbedderPolicy=0]="CrossOriginEmbedderPolicy",e[e.MixedContent=1]="MixedContent",e[e.SameSiteCookie=2]="SameSiteCookie",e[e.HeavyAd=3]="HeavyAd",e[e.ContentSecurityPolicy=4]="ContentSecurityPolicy",e[e.Other=5]="Other",e[e.Generic=6]="Generic",e[e.ThirdPartyPhaseoutCookie=7]="ThirdPartyPhaseoutCookie",e[e.GenericCookie=8]="GenericCookie",e[e.MaxValue=9]="MaxValue"}(Q||(Q={})),function(e){e[e.CrossOriginEmbedderPolicyRequest=0]="CrossOriginEmbedderPolicyRequest",e[e.CrossOriginEmbedderPolicyElement=1]="CrossOriginEmbedderPolicyElement",e[e.MixedContentRequest=2]="MixedContentRequest",e[e.SameSiteCookieCookie=3]="SameSiteCookieCookie",e[e.SameSiteCookieRequest=4]="SameSiteCookieRequest",e[e.HeavyAdElement=5]="HeavyAdElement",e[e.ContentSecurityPolicyDirective=6]="ContentSecurityPolicyDirective",e[e.ContentSecurityPolicyElement=7]="ContentSecurityPolicyElement",e[e.MaxValue=13]="MaxValue"}(J||(J={})),function(e){e[e.MixedContentIssue=0]="MixedContentIssue",e[e["ContentSecurityPolicyIssue::kInlineViolation"]=1]="ContentSecurityPolicyIssue::kInlineViolation",e[e["ContentSecurityPolicyIssue::kEvalViolation"]=2]="ContentSecurityPolicyIssue::kEvalViolation",e[e["ContentSecurityPolicyIssue::kURLViolation"]=3]="ContentSecurityPolicyIssue::kURLViolation",e[e["ContentSecurityPolicyIssue::kTrustedTypesSinkViolation"]=4]="ContentSecurityPolicyIssue::kTrustedTypesSinkViolation",e[e["ContentSecurityPolicyIssue::kTrustedTypesPolicyViolation"]=5]="ContentSecurityPolicyIssue::kTrustedTypesPolicyViolation",e[e["HeavyAdIssue::NetworkTotalLimit"]=6]="HeavyAdIssue::NetworkTotalLimit",e[e["HeavyAdIssue::CpuTotalLimit"]=7]="HeavyAdIssue::CpuTotalLimit",e[e["HeavyAdIssue::CpuPeakLimit"]=8]="HeavyAdIssue::CpuPeakLimit",e[e["CrossOriginEmbedderPolicyIssue::CoepFrameResourceNeedsCoepHeader"]=9]="CrossOriginEmbedderPolicyIssue::CoepFrameResourceNeedsCoepHeader",e[e["CrossOriginEmbedderPolicyIssue::CoopSandboxedIFrameCannotNavigateToCoopPage"]=10]="CrossOriginEmbedderPolicyIssue::CoopSandboxedIFrameCannotNavigateToCoopPage",e[e["CrossOriginEmbedderPolicyIssue::CorpNotSameOrigin"]=11]="CrossOriginEmbedderPolicyIssue::CorpNotSameOrigin",e[e["CrossOriginEmbedderPolicyIssue::CorpNotSameOriginAfterDefaultedToSameOriginByCoep"]=12]="CrossOriginEmbedderPolicyIssue::CorpNotSameOriginAfterDefaultedToSameOriginByCoep",e[e["CrossOriginEmbedderPolicyIssue::CorpNotSameSite"]=13]="CrossOriginEmbedderPolicyIssue::CorpNotSameSite",e[e["CookieIssue::ExcludeSameSiteNoneInsecure::ReadCookie"]=14]="CookieIssue::ExcludeSameSiteNoneInsecure::ReadCookie",e[e["CookieIssue::ExcludeSameSiteNoneInsecure::SetCookie"]=15]="CookieIssue::ExcludeSameSiteNoneInsecure::SetCookie",e[e["CookieIssue::WarnSameSiteNoneInsecure::ReadCookie"]=16]="CookieIssue::WarnSameSiteNoneInsecure::ReadCookie",e[e["CookieIssue::WarnSameSiteNoneInsecure::SetCookie"]=17]="CookieIssue::WarnSameSiteNoneInsecure::SetCookie",e[e["CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Secure"]=18]="CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Secure",e[e["CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Insecure"]=19]="CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Insecure",e[e["CookieIssue::WarnCrossDowngrade::ReadCookie::Secure"]=20]="CookieIssue::WarnCrossDowngrade::ReadCookie::Secure",e[e["CookieIssue::WarnCrossDowngrade::ReadCookie::Insecure"]=21]="CookieIssue::WarnCrossDowngrade::ReadCookie::Insecure",e[e["CookieIssue::WarnCrossDowngrade::SetCookie::Secure"]=22]="CookieIssue::WarnCrossDowngrade::SetCookie::Secure",e[e["CookieIssue::WarnCrossDowngrade::SetCookie::Insecure"]=23]="CookieIssue::WarnCrossDowngrade::SetCookie::Insecure",e[e["CookieIssue::ExcludeNavigationContextDowngrade::Secure"]=24]="CookieIssue::ExcludeNavigationContextDowngrade::Secure",e[e["CookieIssue::ExcludeNavigationContextDowngrade::Insecure"]=25]="CookieIssue::ExcludeNavigationContextDowngrade::Insecure",e[e["CookieIssue::ExcludeContextDowngrade::ReadCookie::Secure"]=26]="CookieIssue::ExcludeContextDowngrade::ReadCookie::Secure",e[e["CookieIssue::ExcludeContextDowngrade::ReadCookie::Insecure"]=27]="CookieIssue::ExcludeContextDowngrade::ReadCookie::Insecure",e[e["CookieIssue::ExcludeContextDowngrade::SetCookie::Secure"]=28]="CookieIssue::ExcludeContextDowngrade::SetCookie::Secure",e[e["CookieIssue::ExcludeContextDowngrade::SetCookie::Insecure"]=29]="CookieIssue::ExcludeContextDowngrade::SetCookie::Insecure",e[e["CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::ReadCookie"]=30]="CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::ReadCookie",e[e["CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::SetCookie"]=31]="CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::SetCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::ReadCookie"]=32]="CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::ReadCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::SetCookie"]=33]="CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::SetCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::ReadCookie"]=34]="CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::ReadCookie",e[e["CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::SetCookie"]=35]="CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::SetCookie",e[e["SharedArrayBufferIssue::TransferIssue"]=36]="SharedArrayBufferIssue::TransferIssue",e[e["SharedArrayBufferIssue::CreationIssue"]=37]="SharedArrayBufferIssue::CreationIssue",e[e.LowTextContrastIssue=41]="LowTextContrastIssue",e[e["CorsIssue::InsecurePrivateNetwork"]=42]="CorsIssue::InsecurePrivateNetwork",e[e["CorsIssue::InvalidHeaders"]=44]="CorsIssue::InvalidHeaders",e[e["CorsIssue::WildcardOriginWithCredentials"]=45]="CorsIssue::WildcardOriginWithCredentials",e[e["CorsIssue::PreflightResponseInvalid"]=46]="CorsIssue::PreflightResponseInvalid",e[e["CorsIssue::OriginMismatch"]=47]="CorsIssue::OriginMismatch",e[e["CorsIssue::AllowCredentialsRequired"]=48]="CorsIssue::AllowCredentialsRequired",e[e["CorsIssue::MethodDisallowedByPreflightResponse"]=49]="CorsIssue::MethodDisallowedByPreflightResponse",e[e["CorsIssue::HeaderDisallowedByPreflightResponse"]=50]="CorsIssue::HeaderDisallowedByPreflightResponse",e[e["CorsIssue::RedirectContainsCredentials"]=51]="CorsIssue::RedirectContainsCredentials",e[e["CorsIssue::DisallowedByMode"]=52]="CorsIssue::DisallowedByMode",e[e["CorsIssue::CorsDisabledScheme"]=53]="CorsIssue::CorsDisabledScheme",e[e["CorsIssue::PreflightMissingAllowExternal"]=54]="CorsIssue::PreflightMissingAllowExternal",e[e["CorsIssue::PreflightInvalidAllowExternal"]=55]="CorsIssue::PreflightInvalidAllowExternal",e[e["CorsIssue::NoCorsRedirectModeNotFollow"]=57]="CorsIssue::NoCorsRedirectModeNotFollow",e[e["QuirksModeIssue::QuirksMode"]=58]="QuirksModeIssue::QuirksMode",e[e["QuirksModeIssue::LimitedQuirksMode"]=59]="QuirksModeIssue::LimitedQuirksMode",e[e.DeprecationIssue=60]="DeprecationIssue",e[e["ClientHintIssue::MetaTagAllowListInvalidOrigin"]=61]="ClientHintIssue::MetaTagAllowListInvalidOrigin",e[e["ClientHintIssue::MetaTagModifiedHTML"]=62]="ClientHintIssue::MetaTagModifiedHTML",e[e["CorsIssue::PreflightAllowPrivateNetworkError"]=63]="CorsIssue::PreflightAllowPrivateNetworkError",e[e["GenericIssue::CrossOriginPortalPostMessageError"]=64]="GenericIssue::CrossOriginPortalPostMessageError",e[e["GenericIssue::FormLabelForNameError"]=65]="GenericIssue::FormLabelForNameError",e[e["GenericIssue::FormDuplicateIdForInputError"]=66]="GenericIssue::FormDuplicateIdForInputError",e[e["GenericIssue::FormInputWithNoLabelError"]=67]="GenericIssue::FormInputWithNoLabelError",e[e["GenericIssue::FormAutocompleteAttributeEmptyError"]=68]="GenericIssue::FormAutocompleteAttributeEmptyError",e[e["GenericIssue::FormEmptyIdAndNameAttributesForInputError"]=69]="GenericIssue::FormEmptyIdAndNameAttributesForInputError",e[e["GenericIssue::FormAriaLabelledByToNonExistingId"]=70]="GenericIssue::FormAriaLabelledByToNonExistingId",e[e["GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError"]=71]="GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError",e[e["GenericIssue::FormLabelHasNeitherForNorNestedInput"]=72]="GenericIssue::FormLabelHasNeitherForNorNestedInput",e[e["GenericIssue::FormLabelForMatchesNonExistingIdError"]=73]="GenericIssue::FormLabelForMatchesNonExistingIdError",e[e["GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError"]=74]="GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError",e[e["GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError"]=75]="GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError",e[e["StylesheetLoadingIssue::LateImportRule"]=76]="StylesheetLoadingIssue::LateImportRule",e[e["StylesheetLoadingIssue::RequestFailed"]=77]="StylesheetLoadingIssue::RequestFailed",e[e["CorsIssue::PreflightMissingPrivateNetworkAccessId"]=78]="CorsIssue::PreflightMissingPrivateNetworkAccessId",e[e["CorsIssue::PreflightMissingPrivateNetworkAccessName"]=79]="CorsIssue::PreflightMissingPrivateNetworkAccessName",e[e["CorsIssue::PrivateNetworkAccessPermissionUnavailable"]=80]="CorsIssue::PrivateNetworkAccessPermissionUnavailable",e[e["CorsIssue::PrivateNetworkAccessPermissionDenied"]=81]="CorsIssue::PrivateNetworkAccessPermissionDenied",e[e["CookieIssue::WarnThirdPartyPhaseout::ReadCookie"]=82]="CookieIssue::WarnThirdPartyPhaseout::ReadCookie",e[e["CookieIssue::WarnThirdPartyPhaseout::SetCookie"]=83]="CookieIssue::WarnThirdPartyPhaseout::SetCookie",e[e["CookieIssue::ExcludeThirdPartyPhaseout::ReadCookie"]=84]="CookieIssue::ExcludeThirdPartyPhaseout::ReadCookie",e[e["CookieIssue::ExcludeThirdPartyPhaseout::SetCookie"]=85]="CookieIssue::ExcludeThirdPartyPhaseout::SetCookie",e[e.MaxValue=86]="MaxValue"}(Y||(Y={})),function(e){e[e.all=0]="all",e[e.Documents=1]="Documents",e[e.Scripts=2]="Scripts",e[e["Fetch and XHR"]=3]="Fetch and XHR",e[e.Stylesheets=4]="Stylesheets",e[e.Fonts=5]="Fonts",e[e.Images=6]="Images",e[e.Media=7]="Media",e[e.Manifest=8]="Manifest",e[e.WebSockets=9]="WebSockets",e[e.WebAssembly=10]="WebAssembly",e[e.Other=11]="Other",e[e.MaxValue=12]="MaxValue"}(Z||(Z={})),function(e){e[e["Hide data URLs"]=0]="Hide data URLs",e[e["Hide extension URLs"]=1]="Hide extension URLs",e[e["Blocked response cookies"]=2]="Blocked response cookies",e[e["Blocked requests"]=3]="Blocked requests",e[e["3rd-party requests"]=4]="3rd-party requests",e[e.MaxValue=5]="MaxValue"}(ee||(ee={})),function(e){e[e.af=1]="af",e[e.am=2]="am",e[e.ar=3]="ar",e[e.as=4]="as",e[e.az=5]="az",e[e.be=6]="be",e[e.bg=7]="bg",e[e.bn=8]="bn",e[e.bs=9]="bs",e[e.ca=10]="ca",e[e.cs=11]="cs",e[e.cy=12]="cy",e[e.da=13]="da",e[e.de=14]="de",e[e.el=15]="el",e[e["en-GB"]=16]="en-GB",e[e["en-US"]=17]="en-US",e[e["es-419"]=18]="es-419",e[e.es=19]="es",e[e.et=20]="et",e[e.eu=21]="eu",e[e.fa=22]="fa",e[e.fi=23]="fi",e[e.fil=24]="fil",e[e["fr-CA"]=25]="fr-CA",e[e.fr=26]="fr",e[e.gl=27]="gl",e[e.gu=28]="gu",e[e.he=29]="he",e[e.hi=30]="hi",e[e.hr=31]="hr",e[e.hu=32]="hu",e[e.hy=33]="hy",e[e.id=34]="id",e[e.is=35]="is",e[e.it=36]="it",e[e.ja=37]="ja",e[e.ka=38]="ka",e[e.kk=39]="kk",e[e.km=40]="km",e[e.kn=41]="kn",e[e.ko=42]="ko",e[e.ky=43]="ky",e[e.lo=44]="lo",e[e.lt=45]="lt",e[e.lv=46]="lv",e[e.mk=47]="mk",e[e.ml=48]="ml",e[e.mn=49]="mn",e[e.mr=50]="mr",e[e.ms=51]="ms",e[e.my=52]="my",e[e.ne=53]="ne",e[e.nl=54]="nl",e[e.no=55]="no",e[e.or=56]="or",e[e.pa=57]="pa",e[e.pl=58]="pl",e[e["pt-PT"]=59]="pt-PT",e[e.pt=60]="pt",e[e.ro=61]="ro",e[e.ru=62]="ru",e[e.si=63]="si",e[e.sk=64]="sk",e[e.sl=65]="sl",e[e.sq=66]="sq",e[e["sr-Latn"]=67]="sr-Latn",e[e.sr=68]="sr",e[e.sv=69]="sv",e[e.sw=70]="sw",e[e.ta=71]="ta",e[e.te=72]="te",e[e.th=73]="th",e[e.tr=74]="tr",e[e.uk=75]="uk",e[e.ur=76]="ur",e[e.uz=77]="uz",e[e.vi=78]="vi",e[e.zh=79]="zh",e[e["zh-HK"]=80]="zh-HK",e[e["zh-TW"]=81]="zh-TW",e[e.zu=82]="zu",e[e.MaxValue=83]="MaxValue"}(re||(re={})),function(e){e[e.OtherSection=0]="OtherSection",e[e.Identity=1]="Identity",e[e.Presentation=2]="Presentation",e[e["Protocol Handlers"]=3]="Protocol Handlers",e[e.Icons=4]="Icons",e[e["Window Controls Overlay"]=5]="Window Controls Overlay",e[e.MaxValue=6]="MaxValue"}(oe||(oe={}));var se=Object.freeze({__proto__:null,UserMetrics:ne,get Action(){return V},get PanelCodes(){return B},get PanelWithLocation(){return j},get ElementsSidebarTabCodes(){return q},get SourcesSidebarTabCodes(){return G},get MediaTypes(){return z},get KeybindSetSettings(){return $},get KeyboardShortcutAction(){return X},get DevtoolsExperiments(){return K},get IssueExpanded(){return Q},get IssueResourceOpened(){return J},get IssueCreated(){return Y},get ResourceType(){return Z},get NetworkPanelMoreFilters(){return ee},get Language(){return re},get ManifestSectionCodes(){return oe}});const ie=new ne,ae=L();export{T as AidaClient,E as InspectorFrontendHost,i as InspectorFrontendHostAPI,H as Platform,te as RNPerfMetrics,C as ResourceLoader,se as UserMetrics,ae as rnPerfMetrics,ie as userMetrics}; diff --git a/packages/debugger-frontend/dist/third-party/front_end/entrypoints/rn_fusebox/rn_fusebox.js b/packages/debugger-frontend/dist/third-party/front_end/entrypoints/rn_fusebox/rn_fusebox.js index 9caf382828b496..8cb4801cbfa70c 100644 --- a/packages/debugger-frontend/dist/third-party/front_end/entrypoints/rn_fusebox/rn_fusebox.js +++ b/packages/debugger-frontend/dist/third-party/front_end/entrypoints/rn_fusebox/rn_fusebox.js @@ -1 +1 @@ -import"../shell/shell.js";import*as e from"../../core/common/common.js";import*as t from"../../core/i18n/i18n.js";import*as o from"../../core/root/root.js";import*as i from"../../ui/legacy/legacy.js";import*as n from"../../models/issues_manager/issues_manager.js";import*as a from"../../core/sdk/sdk.js";import*as r from"../../models/workspace/workspace.js";import*as s from"../../panels/network/forward/forward.js";import*as l from"../../core/host/host.js";import*as c from"../main/main.js";import*as d from"../../core/rn_experiments/rn_experiments.js";const g={toggleDeviceToolbar:"Toggle device toolbar",captureScreenshot:"Capture screenshot",captureFullSizeScreenshot:"Capture full size screenshot",captureNodeScreenshot:"Capture node screenshot",showMediaQueries:"Show media queries",device:"device",hideMediaQueries:"Hide media queries",showRulers:"Show rulers in the Device Mode toolbar",hideRulers:"Hide rulers in the Device Mode toolbar",showDeviceFrame:"Show device frame",hideDeviceFrame:"Hide device frame"},m=t.i18n.registerUIStrings("panels/emulation/emulation-meta.ts",g),w=t.i18n.getLazilyComputedLocalizedString.bind(void 0,m);let u;async function p(){return u||(u=await import("../../panels/emulation/emulation.js")),u}i.ActionRegistration.registerActionExtension({category:"MOBILE",actionId:"emulation.toggle-device-mode",toggleable:!0,loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.toggleDeviceToolbar),iconClass:"devices",bindings:[{platform:"windows,linux",shortcut:"Shift+Ctrl+M"},{platform:"mac",shortcut:"Shift+Meta+M"}]}),i.ActionRegistration.registerActionExtension({actionId:"emulation.capture-screenshot",category:"SCREENSHOT",loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.captureScreenshot)}),i.ActionRegistration.registerActionExtension({actionId:"emulation.capture-full-height-screenshot",category:"SCREENSHOT",loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.captureFullSizeScreenshot)}),i.ActionRegistration.registerActionExtension({actionId:"emulation.capture-node-screenshot",category:"SCREENSHOT",loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.captureNodeScreenshot)}),e.Settings.registerSettingExtension({category:"MOBILE",settingName:"show-media-query-inspector",settingType:"boolean",defaultValue:!1,options:[{value:!0,title:w(g.showMediaQueries)},{value:!1,title:w(g.hideMediaQueries)}],tags:[w(g.device)]}),e.Settings.registerSettingExtension({category:"MOBILE",settingName:"emulation.show-rulers",settingType:"boolean",defaultValue:!1,options:[{value:!0,title:w(g.showRulers)},{value:!1,title:w(g.hideRulers)}],tags:[w(g.device)]}),e.Settings.registerSettingExtension({category:"MOBILE",settingName:"emulation.show-device-outline",settingType:"boolean",defaultValue:!1,options:[{value:!0,title:w(g.showDeviceFrame)},{value:!1,title:w(g.hideDeviceFrame)}],tags:[w(g.device)]}),i.Toolbar.registerToolbarItem({actionId:"emulation.toggle-device-mode",condition:o.Runtime.conditions.canDock,location:"main-toolbar-left",order:1,showLabel:void 0,loadItem:void 0,separator:void 0}),e.AppProvider.registerAppProvider({loadAppProvider:async()=>(await p()).AdvancedApp.AdvancedAppProvider.instance(),condition:o.Runtime.conditions.canDock,order:0}),i.ContextMenu.registerItem({location:"deviceModeMenu/save",order:12,actionId:"emulation.capture-screenshot"}),i.ContextMenu.registerItem({location:"deviceModeMenu/save",order:13,actionId:"emulation.capture-full-height-screenshot"});const v={sensors:"Sensors",geolocation:"geolocation",timezones:"timezones",locale:"locale",locales:"locales",accelerometer:"accelerometer",deviceOrientation:"device orientation",locations:"Locations",touch:"Touch",devicebased:"Device-based",forceEnabled:"Force enabled",emulateIdleDetectorState:"Emulate Idle Detector state",noIdleEmulation:"No idle emulation",userActiveScreenUnlocked:"User active, screen unlocked",userActiveScreenLocked:"User active, screen locked",userIdleScreenUnlocked:"User idle, screen unlocked",userIdleScreenLocked:"User idle, screen locked",showSensors:"Show Sensors",showLocations:"Show Locations"},y=t.i18n.registerUIStrings("panels/sensors/sensors-meta.ts",v),R=t.i18n.getLazilyComputedLocalizedString.bind(void 0,y);let h;async function f(){return h||(h=await import("../../panels/sensors/sensors.js")),h}i.ViewManager.registerViewExtension({location:"drawer-view",commandPrompt:R(v.showSensors),title:R(v.sensors),id:"sensors",persistence:"closeable",order:100,loadView:async()=>new((await f()).SensorsView.SensorsView),tags:[R(v.geolocation),R(v.timezones),R(v.locale),R(v.locales),R(v.accelerometer),R(v.deviceOrientation)]}),i.ViewManager.registerViewExtension({location:"settings-view",id:"emulation-locations",commandPrompt:R(v.showLocations),title:R(v.locations),order:40,loadView:async()=>new((await f()).LocationsSettingsTab.LocationsSettingsTab),settings:["emulation.locations"]}),e.Settings.registerSettingExtension({storageType:"Synced",settingName:"emulation.locations",settingType:"array",defaultValue:[{title:"Berlin",lat:52.520007,long:13.404954,timezoneId:"Europe/Berlin",locale:"de-DE"},{title:"London",lat:51.507351,long:-.127758,timezoneId:"Europe/London",locale:"en-GB"},{title:"Moscow",lat:55.755826,long:37.6173,timezoneId:"Europe/Moscow",locale:"ru-RU"},{title:"Mountain View",lat:37.386052,long:-122.083851,timezoneId:"America/Los_Angeles",locale:"en-US"},{title:"Mumbai",lat:19.075984,long:72.877656,timezoneId:"Asia/Kolkata",locale:"mr-IN"},{title:"San Francisco",lat:37.774929,long:-122.419416,timezoneId:"America/Los_Angeles",locale:"en-US"},{title:"Shanghai",lat:31.230416,long:121.473701,timezoneId:"Asia/Shanghai",locale:"zh-Hans-CN"},{title:"São Paulo",lat:-23.55052,long:-46.633309,timezoneId:"America/Sao_Paulo",locale:"pt-BR"},{title:"Tokyo",lat:35.689487,long:139.691706,timezoneId:"Asia/Tokyo",locale:"ja-JP"}]}),e.Settings.registerSettingExtension({title:R(v.touch),reloadRequired:!0,settingName:"emulation.touch",settingType:"enum",defaultValue:"none",options:[{value:"none",title:R(v.devicebased),text:R(v.devicebased)},{value:"force",title:R(v.forceEnabled),text:R(v.forceEnabled)}]}),e.Settings.registerSettingExtension({title:R(v.emulateIdleDetectorState),settingName:"emulation.idle-detection",settingType:"enum",defaultValue:"none",options:[{value:"none",title:R(v.noIdleEmulation),text:R(v.noIdleEmulation)},{value:'{"isUserActive":true,"isScreenUnlocked":true}',title:R(v.userActiveScreenUnlocked),text:R(v.userActiveScreenUnlocked)},{value:'{"isUserActive":true,"isScreenUnlocked":false}',title:R(v.userActiveScreenLocked),text:R(v.userActiveScreenLocked)},{value:'{"isUserActive":false,"isScreenUnlocked":true}',title:R(v.userIdleScreenUnlocked),text:R(v.userIdleScreenUnlocked)},{value:'{"isUserActive":false,"isScreenUnlocked":false}',title:R(v.userIdleScreenLocked),text:R(v.userIdleScreenLocked)}]});const k={developerResources:"Developer resources",showDeveloperResources:"Show Developer resources"},S=t.i18n.registerUIStrings("panels/developer_resources/developer_resources-meta.ts",k),A=t.i18n.getLazilyComputedLocalizedString.bind(void 0,S);let T;i.ViewManager.registerViewExtension({location:"drawer-view",id:"developer-resources",title:A(k.developerResources),commandPrompt:A(k.showDeveloperResources),order:100,persistence:"closeable",loadView:async()=>new((await async function(){return T||(T=await import("../../panels/developer_resources/developer_resources.js")),T}()).DeveloperResourcesView.DeveloperResourcesView)});const b={rendering:"Rendering",showRendering:"Show Rendering",paint:"paint",layout:"layout",fps:"fps",cssMediaType:"CSS media type",cssMediaFeature:"CSS media feature",visionDeficiency:"vision deficiency",colorVisionDeficiency:"color vision deficiency",reloadPage:"Reload page",hardReloadPage:"Hard reload page",forceAdBlocking:"Force ad blocking on this site",blockAds:"Block ads on this site",showAds:"Show ads on this site, if allowed",autoOpenDevTools:"Auto-open DevTools for popups",doNotAutoOpen:"Do not auto-open DevTools for popups",disablePaused:"Disable paused state overlay",toggleCssPrefersColorSchemeMedia:"Toggle CSS media feature prefers-color-scheme"},P=t.i18n.registerUIStrings("entrypoints/inspector_main/inspector_main-meta.ts",b),N=t.i18n.getLazilyComputedLocalizedString.bind(void 0,P);let E;async function I(){return E||(E=await import("../inspector_main/inspector_main.js")),E}i.ViewManager.registerViewExtension({location:"drawer-view",id:"rendering",title:N(b.rendering),commandPrompt:N(b.showRendering),persistence:"closeable",order:50,loadView:async()=>new((await I()).RenderingOptions.RenderingOptionsView),tags:[N(b.paint),N(b.layout),N(b.fps),N(b.cssMediaType),N(b.cssMediaFeature),N(b.visionDeficiency),N(b.colorVisionDeficiency)]}),i.ActionRegistration.registerActionExtension({category:"NAVIGATION",actionId:"inspector-main.reload",loadActionDelegate:async()=>new((await I()).InspectorMain.ReloadActionDelegate),iconClass:"refresh",title:N(b.reloadPage),bindings:[{platform:"windows,linux",shortcut:"Ctrl+R"},{platform:"windows,linux",shortcut:"F5"},{platform:"mac",shortcut:"Meta+R"}]}),i.ActionRegistration.registerActionExtension({category:"NAVIGATION",actionId:"inspector-main.hard-reload",loadActionDelegate:async()=>new((await I()).InspectorMain.ReloadActionDelegate),title:N(b.hardReloadPage),bindings:[{platform:"windows,linux",shortcut:"Shift+Ctrl+R"},{platform:"windows,linux",shortcut:"Shift+F5"},{platform:"windows,linux",shortcut:"Ctrl+F5"},{platform:"windows,linux",shortcut:"Ctrl+Shift+F5"},{platform:"mac",shortcut:"Shift+Meta+R"}]}),i.ActionRegistration.registerActionExtension({actionId:"rendering.toggle-prefers-color-scheme",category:"RENDERING",title:N(b.toggleCssPrefersColorSchemeMedia),loadActionDelegate:async()=>new((await I()).RenderingOptions.ReloadActionDelegate)}),e.Settings.registerSettingExtension({category:"NETWORK",title:N(b.forceAdBlocking),settingName:"network.ad-blocking-enabled",settingType:"boolean",storageType:"Session",defaultValue:!1,options:[{value:!0,title:N(b.blockAds)},{value:!1,title:N(b.showAds)}]}),e.Settings.registerSettingExtension({category:"GLOBAL",storageType:"Synced",title:N(b.autoOpenDevTools),settingName:"auto-attach-to-created-pages",settingType:"boolean",order:2,defaultValue:!1,options:[{value:!0,title:N(b.autoOpenDevTools)},{value:!1,title:N(b.doNotAutoOpen)}]}),e.Settings.registerSettingExtension({category:"APPEARANCE",storageType:"Synced",title:N(b.disablePaused),settingName:"disable-paused-state-overlay",settingType:"boolean",defaultValue:!1}),i.Toolbar.registerToolbarItem({loadItem:async()=>(await I()).InspectorMain.NodeIndicator.instance(),order:2,location:"main-toolbar-left"}),i.Toolbar.registerToolbarItem({loadItem:async()=>(await I()).OutermostTargetSelector.OutermostTargetSelector.instance(),order:98,location:"main-toolbar-right",experiment:"outermost-target-selector"}),i.Toolbar.registerToolbarItem({loadItem:async()=>(await I()).OutermostTargetSelector.OutermostTargetSelector.instance(),order:98,location:"main-toolbar-right",showLabel:void 0,condition:void 0,separator:void 0,actionId:void 0,experiment:"outermost-target-selector"});const x={issues:"Issues",showIssues:"Show Issues"},D=t.i18n.registerUIStrings("panels/issues/issues-meta.ts",x),M=t.i18n.getLazilyComputedLocalizedString.bind(void 0,D);let L;async function C(){return L||(L=await import("../../panels/issues/issues.js")),L}i.ViewManager.registerViewExtension({location:"drawer-view",id:"issues-pane",title:M(x.issues),commandPrompt:M(x.showIssues),order:100,persistence:"closeable",loadView:async()=>new((await C()).IssuesPane.IssuesPane)}),e.Revealer.registerRevealer({contextTypes:()=>[n.Issue.Issue],destination:e.Revealer.RevealerDestination.ISSUES_VIEW,loadRevealer:async()=>new((await C()).IssueRevealer.IssueRevealer)});const V={throttling:"Throttling",showThrottling:"Show Throttling",goOffline:"Go offline",device:"device",throttlingTag:"throttling",enableSlowGThrottling:"Enable slow `3G` throttling",enableFastGThrottling:"Enable fast `3G` throttling",goOnline:"Go online"},O=t.i18n.registerUIStrings("panels/mobile_throttling/mobile_throttling-meta.ts",V),F=t.i18n.getLazilyComputedLocalizedString.bind(void 0,O);let U;async function B(){return U||(U=await import("../../panels/mobile_throttling/mobile_throttling.js")),U}i.ViewManager.registerViewExtension({location:"settings-view",id:"throttling-conditions",title:F(V.throttling),commandPrompt:F(V.showThrottling),order:35,loadView:async()=>new((await B()).ThrottlingSettingsTab.ThrottlingSettingsTab),settings:["custom-network-conditions"]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-offline",category:"NETWORK",title:F(V.goOffline),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-low-end-mobile",category:"NETWORK",title:F(V.enableSlowGThrottling),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-mid-tier-mobile",category:"NETWORK",title:F(V.enableFastGThrottling),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-online",category:"NETWORK",title:F(V.goOnline),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),e.Settings.registerSettingExtension({storageType:"Synced",settingName:"custom-network-conditions",settingType:"array",defaultValue:[]});const _={showNetwork:"Show Network",network:"Network",showNetworkRequestBlocking:"Show Network request blocking",networkRequestBlocking:"Network request blocking",showNetworkConditions:"Show Network conditions",networkConditions:"Network conditions",diskCache:"disk cache",networkThrottling:"network throttling",showSearch:"Show Search",search:"Search",recordNetworkLog:"Record network log",stopRecordingNetworkLog:"Stop recording network log",hideRequestDetails:"Hide request details",colorcodeResourceTypes:"Color-code resource types",colorCode:"color code",resourceType:"resource type",colorCodeByResourceType:"Color code by resource type",useDefaultColors:"Use default colors",groupNetworkLogByFrame:"Group network log by frame",netWork:"network",frame:"frame",group:"group",groupNetworkLogItemsByFrame:"Group network log items by frame",dontGroupNetworkLogItemsByFrame:"Don't group network log items by frame",clear:"Clear network log",addNetworkRequestBlockingPattern:"Add network request blocking pattern",removeAllNetworkRequestBlockingPatterns:"Remove all network request blocking patterns"},z=t.i18n.registerUIStrings("panels/network/network-meta.ts",_),q=t.i18n.getLazilyComputedLocalizedString.bind(void 0,z);let W;async function j(){return W||(W=await import("../../panels/network/network.js")),W}function K(e){return void 0===W?[]:e(W)}i.ViewManager.registerViewExtension({location:"panel",id:"network",commandPrompt:q(_.showNetwork),title:q(_.network),order:40,condition:o.Runtime.conditions.reactNativeUnstableNetworkPanel,loadView:async()=>(await j()).NetworkPanel.NetworkPanel.instance()}),i.ViewManager.registerViewExtension({location:"drawer-view",id:"network.blocked-urls",commandPrompt:q(_.showNetworkRequestBlocking),title:q(_.networkRequestBlocking),persistence:"closeable",order:60,loadView:async()=>new((await j()).BlockedURLsPane.BlockedURLsPane)}),i.ViewManager.registerViewExtension({location:"drawer-view",id:"network.config",commandPrompt:q(_.showNetworkConditions),title:q(_.networkConditions),persistence:"closeable",order:40,tags:[q(_.diskCache),q(_.networkThrottling),t.i18n.lockedLazyString("useragent"),t.i18n.lockedLazyString("user agent"),t.i18n.lockedLazyString("user-agent")],loadView:async()=>(await j()).NetworkConfigView.NetworkConfigView.instance()}),i.ViewManager.registerViewExtension({location:"network-sidebar",id:"network.search-network-tab",commandPrompt:q(_.showSearch),title:q(_.search),persistence:"permanent",loadView:async()=>(await j()).NetworkPanel.SearchNetworkView.instance()}),i.ActionRegistration.registerActionExtension({actionId:"network.toggle-recording",category:"NETWORK",iconClass:"record-start",toggleable:!0,toggledIconClass:"record-stop",toggleWithRedColor:!0,contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),options:[{value:!0,title:q(_.recordNetworkLog)},{value:!1,title:q(_.stopRecordingNetworkLog)}],bindings:[{shortcut:"Ctrl+E",platform:"windows,linux"},{shortcut:"Meta+E",platform:"mac"}]}),i.ActionRegistration.registerActionExtension({actionId:"network.clear",category:"NETWORK",title:q(_.clear),iconClass:"clear",loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),bindings:[{shortcut:"Ctrl+L"},{shortcut:"Meta+K",platform:"mac"}]}),i.ActionRegistration.registerActionExtension({actionId:"network.hide-request-details",category:"NETWORK",title:q(_.hideRequestDetails),contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),bindings:[{shortcut:"Esc"}]}),i.ActionRegistration.registerActionExtension({actionId:"network.search",category:"NETWORK",title:q(_.search),contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),bindings:[{platform:"mac",shortcut:"Meta+F",keybindSets:["devToolsDefault","vsCode"]},{platform:"windows,linux",shortcut:"Ctrl+F",keybindSets:["devToolsDefault","vsCode"]}]}),i.ActionRegistration.registerActionExtension({actionId:"network.add-network-request-blocking-pattern",category:"NETWORK",title:q(_.addNetworkRequestBlockingPattern),iconClass:"plus",contextTypes:()=>K((e=>[e.BlockedURLsPane.BlockedURLsPane])),loadActionDelegate:async()=>new((await j()).BlockedURLsPane.ActionDelegate)}),i.ActionRegistration.registerActionExtension({actionId:"network.remove-all-network-request-blocking-patterns",category:"NETWORK",title:q(_.removeAllNetworkRequestBlockingPatterns),iconClass:"clear",contextTypes:()=>K((e=>[e.BlockedURLsPane.BlockedURLsPane])),loadActionDelegate:async()=>new((await j()).BlockedURLsPane.ActionDelegate)}),e.Settings.registerSettingExtension({category:"NETWORK",storageType:"Synced",title:q(_.colorcodeResourceTypes),settingName:"network-color-code-resource-types",settingType:"boolean",defaultValue:!1,tags:[q(_.colorCode),q(_.resourceType)],options:[{value:!0,title:q(_.colorCodeByResourceType)},{value:!1,title:q(_.useDefaultColors)}]}),e.Settings.registerSettingExtension({category:"NETWORK",storageType:"Synced",title:q(_.groupNetworkLogByFrame),settingName:"network.group-by-frame",settingType:"boolean",defaultValue:!1,tags:[q(_.netWork),q(_.frame),q(_.group)],options:[{value:!0,title:q(_.groupNetworkLogItemsByFrame)},{value:!1,title:q(_.dontGroupNetworkLogItemsByFrame)}]}),i.ViewManager.registerLocationResolver({name:"network-sidebar",category:"NETWORK",loadResolver:async()=>(await j()).NetworkPanel.NetworkPanel.instance()}),i.ContextMenu.registerProvider({contextTypes:()=>[a.NetworkRequest.NetworkRequest,a.Resource.Resource,r.UISourceCode.UISourceCode],loadProvider:async()=>(await j()).NetworkPanel.NetworkPanel.instance(),experiment:void 0}),e.Revealer.registerRevealer({contextTypes:()=>[a.NetworkRequest.NetworkRequest],destination:e.Revealer.RevealerDestination.NETWORK_PANEL,loadRevealer:async()=>new((await j()).NetworkPanel.RequestRevealer)}),e.Revealer.registerRevealer({contextTypes:()=>[s.UIRequestLocation.UIRequestLocation],destination:void 0,loadRevealer:async()=>new((await j()).NetworkPanel.RequestLocationRevealer)}),e.Revealer.registerRevealer({contextTypes:()=>[s.NetworkRequestId.NetworkRequestId],destination:e.Revealer.RevealerDestination.NETWORK_PANEL,loadRevealer:async()=>new((await j()).NetworkPanel.RequestIdRevealer)}),e.Revealer.registerRevealer({contextTypes:()=>[s.UIFilter.UIRequestFilter],destination:e.Revealer.RevealerDestination.NETWORK_PANEL,loadRevealer:async()=>new((await j()).NetworkPanel.NetworkLogWithFilterRevealer)});const G={title:"⚛️ React DevTools",command:"Show React DevTools panel"},H=t.i18n.registerUIStrings("panels/react_devtools/react_devtools-meta.ts",G),J=t.i18n.getLazilyComputedLocalizedString.bind(void 0,H);let Q;i.ViewManager.registerViewExtension({location:"panel",id:"react-devtools",title:J(G.title),commandPrompt:J(G.command),persistence:"permanent",order:1e3,loadView:async()=>new((await async function(){return Q||(Q=await import("../../panels/react_devtools/react_devtools.js")),Q}()).ReactDevToolsView.ReactDevToolsViewImpl)});const Y={rnWelcome:"Welcome",showRnWelcome:"Show React Native Welcome panel",debuggerBrandName:"React Native DevTools",debuggerBrandNameInternal:"React Native DevTools (Fusebox ⚡)"},X=t.i18n.registerUIStrings("panels/rn_welcome/rn_welcome-meta.ts",Y),Z=t.i18n.getLazilyComputedLocalizedString.bind(void 0,X);let $;i.ViewManager.registerViewExtension({location:"panel",id:"rn-welcome",title:Z(Y.rnWelcome),commandPrompt:Z(Y.showRnWelcome),order:-10,persistence:"permanent",loadView:async()=>(await async function(){return $||($=await import("../../panels/rn_welcome/rn_welcome.js")),$}()).RNWelcome.RNWelcomeImpl.instance({debuggerBrandName:Z(Boolean(o.Runtime.Runtime.queryParam(o.Runtime.ConditionName.REACT_NATIVE_USE_INTERNAL_BRANDING))?Y.debuggerBrandNameInternal:Y.debuggerBrandName),showBetaLabel:!0,showDocs:!0}),experiment:"react-native-specific-ui"});const ee={performance:"Performance",showPerformance:"Show Performance",javascriptProfiler:"JavaScript Profiler",showJavascriptProfiler:"Show JavaScript Profiler",record:"Record",stop:"Stop",startProfilingAndReloadPage:"Start profiling and reload page",saveProfile:"Save profile…",loadProfile:"Load profile…",previousFrame:"Previous frame",nextFrame:"Next frame",showRecentTimelineSessions:"Show recent timeline sessions",previousRecording:"Previous recording",nextRecording:"Next recording",hideChromeFrameInLayersView:"Hide `chrome` frame in Layers view",startStopRecording:"Start/stop recording"},te=t.i18n.registerUIStrings("panels/timeline/timeline-meta.ts",ee),oe=t.i18n.getLazilyComputedLocalizedString.bind(void 0,te);let ie,ne;async function ae(){return ie||(ie=await import("../../panels/timeline/timeline.js")),ie}async function re(){return ne||(ne=await import("../../panels/profiler/profiler.js")),ne}function se(e){return void 0===ie?[]:e(ie)}i.ViewManager.registerViewExtension({location:"panel",id:"timeline",title:oe(ee.performance),commandPrompt:oe(ee.showPerformance),order:50,experiment:"enable-performance-panel",loadView:async()=>(await ae()).TimelinePanel.TimelinePanel.instance()}),i.ViewManager.registerViewExtension({location:"panel",id:"js-profiler",title:oe(ee.javascriptProfiler),commandPrompt:oe(ee.showJavascriptProfiler),persistence:"permanent",order:65,experiment:"js-profiler-temporarily-enable",loadView:async()=>(await re()).ProfilesPanel.JSProfilerPanel.instance()}),i.ActionRegistration.registerActionExtension({actionId:"timeline.toggle-recording",category:"PERFORMANCE",iconClass:"record-start",toggleable:!0,toggledIconClass:"record-stop",toggleWithRedColor:!0,contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),options:[{value:!0,title:oe(ee.record)},{value:!1,title:oe(ee.stop)}],bindings:[{platform:"windows,linux",shortcut:"Ctrl+E"},{platform:"mac",shortcut:"Meta+E"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.record-reload",iconClass:"refresh",contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),category:"PERFORMANCE",title:oe(ee.startProfilingAndReloadPage),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),bindings:[{platform:"windows,linux",shortcut:"Ctrl+Shift+E"},{platform:"mac",shortcut:"Meta+Shift+E"}]}),i.ActionRegistration.registerActionExtension({category:"PERFORMANCE",actionId:"timeline.save-to-file",contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.saveProfile),bindings:[{platform:"windows,linux",shortcut:"Ctrl+S"},{platform:"mac",shortcut:"Meta+S"}]}),i.ActionRegistration.registerActionExtension({category:"PERFORMANCE",actionId:"timeline.load-from-file",contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.loadProfile),bindings:[{platform:"windows,linux",shortcut:"Ctrl+O"},{platform:"mac",shortcut:"Meta+O"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.jump-to-previous-frame",category:"PERFORMANCE",title:oe(ee.previousFrame),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),bindings:[{shortcut:"["}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.jump-to-next-frame",category:"PERFORMANCE",title:oe(ee.nextFrame),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),bindings:[{shortcut:"]"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.show-history",loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),category:"PERFORMANCE",title:oe(ee.showRecentTimelineSessions),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),bindings:[{platform:"windows,linux",shortcut:"Ctrl+H"},{platform:"mac",shortcut:"Meta+Y"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.previous-recording",category:"PERFORMANCE",loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.previousRecording),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),bindings:[{platform:"windows,linux",shortcut:"Alt+Left"},{platform:"mac",shortcut:"Meta+Left"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.next-recording",category:"PERFORMANCE",loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.nextRecording),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),bindings:[{platform:"windows,linux",shortcut:"Alt+Right"},{platform:"mac",shortcut:"Meta+Right"}]}),i.ActionRegistration.registerActionExtension({actionId:"profiler.js-toggle-recording",category:"JAVASCRIPT_PROFILER",title:oe(ee.startStopRecording),iconClass:"record-start",toggleable:!0,toggledIconClass:"record-stop",toggleWithRedColor:!0,contextTypes:()=>void 0===ne?[]:(e=>[e.ProfilesPanel.JSProfilerPanel])(ne),loadActionDelegate:async()=>(await re()).ProfilesPanel.JSProfilerPanel.instance(),bindings:[{platform:"windows,linux",shortcut:"Ctrl+E"},{platform:"mac",shortcut:"Meta+E"}]}),e.Settings.registerSettingExtension({category:"PERFORMANCE",storageType:"Synced",title:oe(ee.hideChromeFrameInLayersView),settingName:"frame-viewer-hide-chrome-window",settingType:"boolean",defaultValue:!1}),e.Linkifier.registerLinkifier({contextTypes:()=>se((e=>[e.CLSLinkifier.CLSRect])),loadLinkifier:async()=>(await ae()).CLSLinkifier.Linkifier.instance()}),i.ContextMenu.registerItem({location:"timelineMenu/open",actionId:"timeline.load-from-file",order:10}),i.ContextMenu.registerItem({location:"timelineMenu/open",actionId:"timeline.save-to-file",order:15}),l.rnPerfMetrics.registerPerfMetricsGlobalPostMessageHandler(),l.rnPerfMetrics.registerGlobalErrorReporting(),l.rnPerfMetrics.setLaunchId(o.Runtime.Runtime.queryParam("launchId")),l.rnPerfMetrics.entryPointLoadingStarted("rn_fusebox");const le={networkTitle:"React Native",showReactNative:"Show React Native",sendFeedback:"[FB-only] Send feedback"},ce=t.i18n.registerUIStrings("entrypoints/rn_fusebox/rn_fusebox.ts",le),de=t.i18n.getLazilyComputedLocalizedString.bind(void 0,ce);i.ViewManager.maybeRemoveViewExtension("network.blocked-urls"),i.ViewManager.maybeRemoveViewExtension("network.config"),i.ViewManager.maybeRemoveViewExtension("coverage"),i.ViewManager.maybeRemoveViewExtension("linear-memory-inspector"),i.ViewManager.maybeRemoveViewExtension("rendering"),i.ViewManager.maybeRemoveViewExtension("issues-pane"),i.ViewManager.maybeRemoveViewExtension("sensors"),i.ViewManager.maybeRemoveViewExtension("devices"),i.ViewManager.maybeRemoveViewExtension("emulation-locations"),i.ViewManager.maybeRemoveViewExtension("throttling-conditions"),d.RNExperimentsImpl.setIsReactNativeEntryPoint(!0),d.RNExperimentsImpl.Instance.enableExperimentsByDefault(["react-native-specific-ui"]),document.addEventListener("visibilitychange",(()=>{l.rnPerfMetrics.browserVisibilityChanged(document.visibilityState)}));class ge extends a.SDKModel.SDKModel{constructor(e){super(e),e.fuseboxClientAgent().invoke_setClientMetadata()}}let me;if(a.SDKModel.SDKModel.register(ge,{capabilities:0,autostart:!0,early:!0}),i.ViewManager.registerViewExtension({location:"navigator-view",id:"navigator-network",title:de(le.networkTitle),commandPrompt:de(le.showReactNative),order:2,persistence:"permanent",loadView:async()=>(await async function(){return me||(me=await import("../../panels/sources/sources.js")),me}()).SourcesNavigator.NetworkNavigatorView.instance()}),self.runtime=o.Runtime.Runtime.instance({forceNew:!0}),new c.MainImpl.MainImpl,globalThis.FB_ONLY__reactNativeFeedbackLink){const e=globalThis.FB_ONLY__reactNativeFeedbackLink,t="react-native-send-feedback",o={handleAction:(o,i)=>i===t&&(l.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(e),!0)};i.ActionRegistration.registerActionExtension({category:"GLOBAL",actionId:t,title:de(le.sendFeedback),loadActionDelegate:async()=>o,iconClass:"bug"}),i.Toolbar.registerToolbarItem({location:"main-toolbar-right",actionId:t,showLabel:!0})}l.rnPerfMetrics.entryPointLoadingFinished("rn_fusebox"); +import"../shell/shell.js";import*as e from"../../core/common/common.js";import*as t from"../../core/i18n/i18n.js";import*as o from"../../core/root/root.js";import*as i from"../../ui/legacy/legacy.js";import*as n from"../../models/issues_manager/issues_manager.js";import*as a from"../../core/sdk/sdk.js";import*as r from"../../models/workspace/workspace.js";import*as s from"../../panels/network/forward/forward.js";import*as l from"../../core/host/host.js";import*as c from"../main/main.js";import*as d from"../../core/rn_experiments/rn_experiments.js";const g={toggleDeviceToolbar:"Toggle device toolbar",captureScreenshot:"Capture screenshot",captureFullSizeScreenshot:"Capture full size screenshot",captureNodeScreenshot:"Capture node screenshot",showMediaQueries:"Show media queries",device:"device",hideMediaQueries:"Hide media queries",showRulers:"Show rulers in the Device Mode toolbar",hideRulers:"Hide rulers in the Device Mode toolbar",showDeviceFrame:"Show device frame",hideDeviceFrame:"Hide device frame"},m=t.i18n.registerUIStrings("panels/emulation/emulation-meta.ts",g),w=t.i18n.getLazilyComputedLocalizedString.bind(void 0,m);let u;async function p(){return u||(u=await import("../../panels/emulation/emulation.js")),u}i.ActionRegistration.registerActionExtension({category:"MOBILE",actionId:"emulation.toggle-device-mode",toggleable:!0,loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.toggleDeviceToolbar),iconClass:"devices",bindings:[{platform:"windows,linux",shortcut:"Shift+Ctrl+M"},{platform:"mac",shortcut:"Shift+Meta+M"}]}),i.ActionRegistration.registerActionExtension({actionId:"emulation.capture-screenshot",category:"SCREENSHOT",loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.captureScreenshot)}),i.ActionRegistration.registerActionExtension({actionId:"emulation.capture-full-height-screenshot",category:"SCREENSHOT",loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.captureFullSizeScreenshot)}),i.ActionRegistration.registerActionExtension({actionId:"emulation.capture-node-screenshot",category:"SCREENSHOT",loadActionDelegate:async()=>new((await p()).DeviceModeWrapper.ActionDelegate),condition:o.Runtime.conditions.canDock,title:w(g.captureNodeScreenshot)}),e.Settings.registerSettingExtension({category:"MOBILE",settingName:"show-media-query-inspector",settingType:"boolean",defaultValue:!1,options:[{value:!0,title:w(g.showMediaQueries)},{value:!1,title:w(g.hideMediaQueries)}],tags:[w(g.device)]}),e.Settings.registerSettingExtension({category:"MOBILE",settingName:"emulation.show-rulers",settingType:"boolean",defaultValue:!1,options:[{value:!0,title:w(g.showRulers)},{value:!1,title:w(g.hideRulers)}],tags:[w(g.device)]}),e.Settings.registerSettingExtension({category:"MOBILE",settingName:"emulation.show-device-outline",settingType:"boolean",defaultValue:!1,options:[{value:!0,title:w(g.showDeviceFrame)},{value:!1,title:w(g.hideDeviceFrame)}],tags:[w(g.device)]}),i.Toolbar.registerToolbarItem({actionId:"emulation.toggle-device-mode",condition:o.Runtime.conditions.canDock,location:"main-toolbar-left",order:1,showLabel:void 0,loadItem:void 0,separator:void 0}),e.AppProvider.registerAppProvider({loadAppProvider:async()=>(await p()).AdvancedApp.AdvancedAppProvider.instance(),condition:o.Runtime.conditions.canDock,order:0}),i.ContextMenu.registerItem({location:"deviceModeMenu/save",order:12,actionId:"emulation.capture-screenshot"}),i.ContextMenu.registerItem({location:"deviceModeMenu/save",order:13,actionId:"emulation.capture-full-height-screenshot"});const v={sensors:"Sensors",geolocation:"geolocation",timezones:"timezones",locale:"locale",locales:"locales",accelerometer:"accelerometer",deviceOrientation:"device orientation",locations:"Locations",touch:"Touch",devicebased:"Device-based",forceEnabled:"Force enabled",emulateIdleDetectorState:"Emulate Idle Detector state",noIdleEmulation:"No idle emulation",userActiveScreenUnlocked:"User active, screen unlocked",userActiveScreenLocked:"User active, screen locked",userIdleScreenUnlocked:"User idle, screen unlocked",userIdleScreenLocked:"User idle, screen locked",showSensors:"Show Sensors",showLocations:"Show Locations"},y=t.i18n.registerUIStrings("panels/sensors/sensors-meta.ts",v),h=t.i18n.getLazilyComputedLocalizedString.bind(void 0,y);let R;async function f(){return R||(R=await import("../../panels/sensors/sensors.js")),R}i.ViewManager.registerViewExtension({location:"drawer-view",commandPrompt:h(v.showSensors),title:h(v.sensors),id:"sensors",persistence:"closeable",order:100,loadView:async()=>new((await f()).SensorsView.SensorsView),tags:[h(v.geolocation),h(v.timezones),h(v.locale),h(v.locales),h(v.accelerometer),h(v.deviceOrientation)]}),i.ViewManager.registerViewExtension({location:"settings-view",id:"emulation-locations",commandPrompt:h(v.showLocations),title:h(v.locations),order:40,loadView:async()=>new((await f()).LocationsSettingsTab.LocationsSettingsTab),settings:["emulation.locations"]}),e.Settings.registerSettingExtension({storageType:"Synced",settingName:"emulation.locations",settingType:"array",defaultValue:[{title:"Berlin",lat:52.520007,long:13.404954,timezoneId:"Europe/Berlin",locale:"de-DE"},{title:"London",lat:51.507351,long:-.127758,timezoneId:"Europe/London",locale:"en-GB"},{title:"Moscow",lat:55.755826,long:37.6173,timezoneId:"Europe/Moscow",locale:"ru-RU"},{title:"Mountain View",lat:37.386052,long:-122.083851,timezoneId:"America/Los_Angeles",locale:"en-US"},{title:"Mumbai",lat:19.075984,long:72.877656,timezoneId:"Asia/Kolkata",locale:"mr-IN"},{title:"San Francisco",lat:37.774929,long:-122.419416,timezoneId:"America/Los_Angeles",locale:"en-US"},{title:"Shanghai",lat:31.230416,long:121.473701,timezoneId:"Asia/Shanghai",locale:"zh-Hans-CN"},{title:"São Paulo",lat:-23.55052,long:-46.633309,timezoneId:"America/Sao_Paulo",locale:"pt-BR"},{title:"Tokyo",lat:35.689487,long:139.691706,timezoneId:"Asia/Tokyo",locale:"ja-JP"}]}),e.Settings.registerSettingExtension({title:h(v.touch),reloadRequired:!0,settingName:"emulation.touch",settingType:"enum",defaultValue:"none",options:[{value:"none",title:h(v.devicebased),text:h(v.devicebased)},{value:"force",title:h(v.forceEnabled),text:h(v.forceEnabled)}]}),e.Settings.registerSettingExtension({title:h(v.emulateIdleDetectorState),settingName:"emulation.idle-detection",settingType:"enum",defaultValue:"none",options:[{value:"none",title:h(v.noIdleEmulation),text:h(v.noIdleEmulation)},{value:'{"isUserActive":true,"isScreenUnlocked":true}',title:h(v.userActiveScreenUnlocked),text:h(v.userActiveScreenUnlocked)},{value:'{"isUserActive":true,"isScreenUnlocked":false}',title:h(v.userActiveScreenLocked),text:h(v.userActiveScreenLocked)},{value:'{"isUserActive":false,"isScreenUnlocked":true}',title:h(v.userIdleScreenUnlocked),text:h(v.userIdleScreenUnlocked)},{value:'{"isUserActive":false,"isScreenUnlocked":false}',title:h(v.userIdleScreenLocked),text:h(v.userIdleScreenLocked)}]});const k={developerResources:"Developer resources",showDeveloperResources:"Show Developer resources"},S=t.i18n.registerUIStrings("panels/developer_resources/developer_resources-meta.ts",k),A=t.i18n.getLazilyComputedLocalizedString.bind(void 0,S);let T;i.ViewManager.registerViewExtension({location:"drawer-view",id:"developer-resources",title:A(k.developerResources),commandPrompt:A(k.showDeveloperResources),order:100,persistence:"closeable",loadView:async()=>new((await async function(){return T||(T=await import("../../panels/developer_resources/developer_resources.js")),T}()).DeveloperResourcesView.DeveloperResourcesView)});const b={rendering:"Rendering",showRendering:"Show Rendering",paint:"paint",layout:"layout",fps:"fps",cssMediaType:"CSS media type",cssMediaFeature:"CSS media feature",visionDeficiency:"vision deficiency",colorVisionDeficiency:"color vision deficiency",reloadPage:"Reload page",hardReloadPage:"Hard reload page",forceAdBlocking:"Force ad blocking on this site",blockAds:"Block ads on this site",showAds:"Show ads on this site, if allowed",autoOpenDevTools:"Auto-open DevTools for popups",doNotAutoOpen:"Do not auto-open DevTools for popups",disablePaused:"Disable paused state overlay",toggleCssPrefersColorSchemeMedia:"Toggle CSS media feature prefers-color-scheme"},P=t.i18n.registerUIStrings("entrypoints/inspector_main/inspector_main-meta.ts",b),E=t.i18n.getLazilyComputedLocalizedString.bind(void 0,P);let N;async function x(){return N||(N=await import("../inspector_main/inspector_main.js")),N}i.ViewManager.registerViewExtension({location:"drawer-view",id:"rendering",title:E(b.rendering),commandPrompt:E(b.showRendering),persistence:"closeable",order:50,loadView:async()=>new((await x()).RenderingOptions.RenderingOptionsView),tags:[E(b.paint),E(b.layout),E(b.fps),E(b.cssMediaType),E(b.cssMediaFeature),E(b.visionDeficiency),E(b.colorVisionDeficiency)]}),i.ActionRegistration.registerActionExtension({category:"NAVIGATION",actionId:"inspector-main.reload",loadActionDelegate:async()=>new((await x()).InspectorMain.ReloadActionDelegate),iconClass:"refresh",title:E(b.reloadPage),bindings:[{platform:"windows,linux",shortcut:"Ctrl+R"},{platform:"windows,linux",shortcut:"F5"},{platform:"mac",shortcut:"Meta+R"}]}),i.ActionRegistration.registerActionExtension({category:"NAVIGATION",actionId:"inspector-main.hard-reload",loadActionDelegate:async()=>new((await x()).InspectorMain.ReloadActionDelegate),title:E(b.hardReloadPage),bindings:[{platform:"windows,linux",shortcut:"Shift+Ctrl+R"},{platform:"windows,linux",shortcut:"Shift+F5"},{platform:"windows,linux",shortcut:"Ctrl+F5"},{platform:"windows,linux",shortcut:"Ctrl+Shift+F5"},{platform:"mac",shortcut:"Shift+Meta+R"}]}),i.ActionRegistration.registerActionExtension({actionId:"rendering.toggle-prefers-color-scheme",category:"RENDERING",title:E(b.toggleCssPrefersColorSchemeMedia),loadActionDelegate:async()=>new((await x()).RenderingOptions.ReloadActionDelegate)}),e.Settings.registerSettingExtension({category:"NETWORK",title:E(b.forceAdBlocking),settingName:"network.ad-blocking-enabled",settingType:"boolean",storageType:"Session",defaultValue:!1,options:[{value:!0,title:E(b.blockAds)},{value:!1,title:E(b.showAds)}]}),e.Settings.registerSettingExtension({category:"GLOBAL",storageType:"Synced",title:E(b.autoOpenDevTools),settingName:"auto-attach-to-created-pages",settingType:"boolean",order:2,defaultValue:!1,options:[{value:!0,title:E(b.autoOpenDevTools)},{value:!1,title:E(b.doNotAutoOpen)}]}),e.Settings.registerSettingExtension({category:"APPEARANCE",storageType:"Synced",title:E(b.disablePaused),settingName:"disable-paused-state-overlay",settingType:"boolean",defaultValue:!1}),i.Toolbar.registerToolbarItem({loadItem:async()=>(await x()).InspectorMain.NodeIndicator.instance(),order:2,location:"main-toolbar-left"}),i.Toolbar.registerToolbarItem({loadItem:async()=>(await x()).OutermostTargetSelector.OutermostTargetSelector.instance(),order:98,location:"main-toolbar-right",experiment:"outermost-target-selector"}),i.Toolbar.registerToolbarItem({loadItem:async()=>(await x()).OutermostTargetSelector.OutermostTargetSelector.instance(),order:98,location:"main-toolbar-right",showLabel:void 0,condition:void 0,separator:void 0,actionId:void 0,experiment:"outermost-target-selector"});const I={issues:"Issues",showIssues:"Show Issues"},D=t.i18n.registerUIStrings("panels/issues/issues-meta.ts",I),M=t.i18n.getLazilyComputedLocalizedString.bind(void 0,D);let C;async function L(){return C||(C=await import("../../panels/issues/issues.js")),C}i.ViewManager.registerViewExtension({location:"drawer-view",id:"issues-pane",title:M(I.issues),commandPrompt:M(I.showIssues),order:100,persistence:"closeable",loadView:async()=>new((await L()).IssuesPane.IssuesPane)}),e.Revealer.registerRevealer({contextTypes:()=>[n.Issue.Issue],destination:e.Revealer.RevealerDestination.ISSUES_VIEW,loadRevealer:async()=>new((await L()).IssueRevealer.IssueRevealer)});const V={throttling:"Throttling",showThrottling:"Show Throttling",goOffline:"Go offline",device:"device",throttlingTag:"throttling",enableSlowGThrottling:"Enable slow `3G` throttling",enableFastGThrottling:"Enable fast `3G` throttling",goOnline:"Go online"},O=t.i18n.registerUIStrings("panels/mobile_throttling/mobile_throttling-meta.ts",V),F=t.i18n.getLazilyComputedLocalizedString.bind(void 0,O);let U;async function B(){return U||(U=await import("../../panels/mobile_throttling/mobile_throttling.js")),U}i.ViewManager.registerViewExtension({location:"settings-view",id:"throttling-conditions",title:F(V.throttling),commandPrompt:F(V.showThrottling),order:35,loadView:async()=>new((await B()).ThrottlingSettingsTab.ThrottlingSettingsTab),settings:["custom-network-conditions"]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-offline",category:"NETWORK",title:F(V.goOffline),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-low-end-mobile",category:"NETWORK",title:F(V.enableSlowGThrottling),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-mid-tier-mobile",category:"NETWORK",title:F(V.enableFastGThrottling),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),i.ActionRegistration.registerActionExtension({actionId:"network-conditions.network-online",category:"NETWORK",title:F(V.goOnline),loadActionDelegate:async()=>new((await B()).ThrottlingManager.ActionDelegate),tags:[F(V.device),F(V.throttlingTag)]}),e.Settings.registerSettingExtension({storageType:"Synced",settingName:"custom-network-conditions",settingType:"array",defaultValue:[]});const _={showNetwork:"Show Network",network:"Network",showNetworkRequestBlocking:"Show Network request blocking",networkRequestBlocking:"Network request blocking",showNetworkConditions:"Show Network conditions",networkConditions:"Network conditions",diskCache:"disk cache",networkThrottling:"network throttling",showSearch:"Show Search",search:"Search",recordNetworkLog:"Record network log",stopRecordingNetworkLog:"Stop recording network log",hideRequestDetails:"Hide request details",colorcodeResourceTypes:"Color-code resource types",colorCode:"color code",resourceType:"resource type",colorCodeByResourceType:"Color code by resource type",useDefaultColors:"Use default colors",groupNetworkLogByFrame:"Group network log by frame",netWork:"network",frame:"frame",group:"group",groupNetworkLogItemsByFrame:"Group network log items by frame",dontGroupNetworkLogItemsByFrame:"Don't group network log items by frame",clear:"Clear network log",addNetworkRequestBlockingPattern:"Add network request blocking pattern",removeAllNetworkRequestBlockingPatterns:"Remove all network request blocking patterns"},z=t.i18n.registerUIStrings("panels/network/network-meta.ts",_),q=t.i18n.getLazilyComputedLocalizedString.bind(void 0,z);let W;async function j(){return W||(W=await import("../../panels/network/network.js")),W}function K(e){return void 0===W?[]:e(W)}i.ViewManager.registerViewExtension({location:"panel",id:"network",commandPrompt:q(_.showNetwork),title:q(_.network),order:40,condition:o.Runtime.conditions.reactNativeUnstableNetworkPanel,loadView:async()=>(await j()).NetworkPanel.NetworkPanel.instance()}),i.ViewManager.registerViewExtension({location:"drawer-view",id:"network.blocked-urls",commandPrompt:q(_.showNetworkRequestBlocking),title:q(_.networkRequestBlocking),persistence:"closeable",order:60,loadView:async()=>new((await j()).BlockedURLsPane.BlockedURLsPane)}),i.ViewManager.registerViewExtension({location:"drawer-view",id:"network.config",commandPrompt:q(_.showNetworkConditions),title:q(_.networkConditions),persistence:"closeable",order:40,tags:[q(_.diskCache),q(_.networkThrottling),t.i18n.lockedLazyString("useragent"),t.i18n.lockedLazyString("user agent"),t.i18n.lockedLazyString("user-agent")],loadView:async()=>(await j()).NetworkConfigView.NetworkConfigView.instance()}),i.ViewManager.registerViewExtension({location:"network-sidebar",id:"network.search-network-tab",commandPrompt:q(_.showSearch),title:q(_.search),persistence:"permanent",loadView:async()=>(await j()).NetworkPanel.SearchNetworkView.instance()}),i.ActionRegistration.registerActionExtension({actionId:"network.toggle-recording",category:"NETWORK",iconClass:"record-start",toggleable:!0,toggledIconClass:"record-stop",toggleWithRedColor:!0,contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),options:[{value:!0,title:q(_.recordNetworkLog)},{value:!1,title:q(_.stopRecordingNetworkLog)}],bindings:[{shortcut:"Ctrl+E",platform:"windows,linux"},{shortcut:"Meta+E",platform:"mac"}]}),i.ActionRegistration.registerActionExtension({actionId:"network.clear",category:"NETWORK",title:q(_.clear),iconClass:"clear",loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),bindings:[{shortcut:"Ctrl+L"},{shortcut:"Meta+K",platform:"mac"}]}),i.ActionRegistration.registerActionExtension({actionId:"network.hide-request-details",category:"NETWORK",title:q(_.hideRequestDetails),contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),bindings:[{shortcut:"Esc"}]}),i.ActionRegistration.registerActionExtension({actionId:"network.search",category:"NETWORK",title:q(_.search),contextTypes:()=>K((e=>[e.NetworkPanel.NetworkPanel])),loadActionDelegate:async()=>new((await j()).NetworkPanel.ActionDelegate),bindings:[{platform:"mac",shortcut:"Meta+F",keybindSets:["devToolsDefault","vsCode"]},{platform:"windows,linux",shortcut:"Ctrl+F",keybindSets:["devToolsDefault","vsCode"]}]}),i.ActionRegistration.registerActionExtension({actionId:"network.add-network-request-blocking-pattern",category:"NETWORK",title:q(_.addNetworkRequestBlockingPattern),iconClass:"plus",contextTypes:()=>K((e=>[e.BlockedURLsPane.BlockedURLsPane])),loadActionDelegate:async()=>new((await j()).BlockedURLsPane.ActionDelegate)}),i.ActionRegistration.registerActionExtension({actionId:"network.remove-all-network-request-blocking-patterns",category:"NETWORK",title:q(_.removeAllNetworkRequestBlockingPatterns),iconClass:"clear",contextTypes:()=>K((e=>[e.BlockedURLsPane.BlockedURLsPane])),loadActionDelegate:async()=>new((await j()).BlockedURLsPane.ActionDelegate)}),e.Settings.registerSettingExtension({category:"NETWORK",storageType:"Synced",title:q(_.colorcodeResourceTypes),settingName:"network-color-code-resource-types",settingType:"boolean",defaultValue:!1,tags:[q(_.colorCode),q(_.resourceType)],options:[{value:!0,title:q(_.colorCodeByResourceType)},{value:!1,title:q(_.useDefaultColors)}]}),e.Settings.registerSettingExtension({category:"NETWORK",storageType:"Synced",title:q(_.groupNetworkLogByFrame),settingName:"network.group-by-frame",settingType:"boolean",defaultValue:!1,tags:[q(_.netWork),q(_.frame),q(_.group)],options:[{value:!0,title:q(_.groupNetworkLogItemsByFrame)},{value:!1,title:q(_.dontGroupNetworkLogItemsByFrame)}]}),i.ViewManager.registerLocationResolver({name:"network-sidebar",category:"NETWORK",loadResolver:async()=>(await j()).NetworkPanel.NetworkPanel.instance()}),i.ContextMenu.registerProvider({contextTypes:()=>[a.NetworkRequest.NetworkRequest,a.Resource.Resource,r.UISourceCode.UISourceCode],loadProvider:async()=>(await j()).NetworkPanel.NetworkPanel.instance(),experiment:void 0}),e.Revealer.registerRevealer({contextTypes:()=>[a.NetworkRequest.NetworkRequest],destination:e.Revealer.RevealerDestination.NETWORK_PANEL,loadRevealer:async()=>new((await j()).NetworkPanel.RequestRevealer)}),e.Revealer.registerRevealer({contextTypes:()=>[s.UIRequestLocation.UIRequestLocation],destination:void 0,loadRevealer:async()=>new((await j()).NetworkPanel.RequestLocationRevealer)}),e.Revealer.registerRevealer({contextTypes:()=>[s.NetworkRequestId.NetworkRequestId],destination:e.Revealer.RevealerDestination.NETWORK_PANEL,loadRevealer:async()=>new((await j()).NetworkPanel.RequestIdRevealer)}),e.Revealer.registerRevealer({contextTypes:()=>[s.UIFilter.UIRequestFilter],destination:e.Revealer.RevealerDestination.NETWORK_PANEL,loadRevealer:async()=>new((await j()).NetworkPanel.NetworkLogWithFilterRevealer)});const G={title:"⚛️ React DevTools",command:"Show React DevTools panel"},H=t.i18n.registerUIStrings("panels/react_devtools/react_devtools-meta.ts",G),J=t.i18n.getLazilyComputedLocalizedString.bind(void 0,H);let Q;i.ViewManager.registerViewExtension({location:"panel",id:"react-devtools",title:J(G.title),commandPrompt:J(G.command),persistence:"permanent",order:1e3,loadView:async()=>new((await async function(){return Q||(Q=await import("../../panels/react_devtools/react_devtools.js")),Q}()).ReactDevToolsView.ReactDevToolsViewImpl)});const Y={rnWelcome:"Welcome",showRnWelcome:"Show React Native Welcome panel",debuggerBrandName:"React Native DevTools",debuggerBrandNameInternal:"React Native DevTools (Fusebox ⚡)"},X=t.i18n.registerUIStrings("panels/rn_welcome/rn_welcome-meta.ts",Y),Z=t.i18n.getLazilyComputedLocalizedString.bind(void 0,X);let $;i.ViewManager.registerViewExtension({location:"panel",id:"rn-welcome",title:Z(Y.rnWelcome),commandPrompt:Z(Y.showRnWelcome),order:-10,persistence:"permanent",loadView:async()=>(await async function(){return $||($=await import("../../panels/rn_welcome/rn_welcome.js")),$}()).RNWelcome.RNWelcomeImpl.instance({debuggerBrandName:Z(Boolean(o.Runtime.Runtime.queryParam(o.Runtime.ConditionName.REACT_NATIVE_USE_INTERNAL_BRANDING))?Y.debuggerBrandNameInternal:Y.debuggerBrandName),showBetaLabel:!0,showDocs:!0}),experiment:"react-native-specific-ui"});const ee={performance:"Performance",showPerformance:"Show Performance",javascriptProfiler:"JavaScript Profiler",showJavascriptProfiler:"Show JavaScript Profiler",record:"Record",stop:"Stop",startProfilingAndReloadPage:"Start profiling and reload page",saveProfile:"Save profile…",loadProfile:"Load profile…",previousFrame:"Previous frame",nextFrame:"Next frame",showRecentTimelineSessions:"Show recent timeline sessions",previousRecording:"Previous recording",nextRecording:"Next recording",hideChromeFrameInLayersView:"Hide `chrome` frame in Layers view",startStopRecording:"Start/stop recording"},te=t.i18n.registerUIStrings("panels/timeline/timeline-meta.ts",ee),oe=t.i18n.getLazilyComputedLocalizedString.bind(void 0,te);let ie,ne;async function ae(){return ie||(ie=await import("../../panels/timeline/timeline.js")),ie}async function re(){return ne||(ne=await import("../../panels/profiler/profiler.js")),ne}function se(e){return void 0===ie?[]:e(ie)}i.ViewManager.registerViewExtension({location:"panel",id:"timeline",title:oe(ee.performance),commandPrompt:oe(ee.showPerformance),order:50,experiment:"enable-performance-panel",loadView:async()=>(await ae()).TimelinePanel.TimelinePanel.instance()}),i.ViewManager.registerViewExtension({location:"panel",id:"js-profiler",title:oe(ee.javascriptProfiler),commandPrompt:oe(ee.showJavascriptProfiler),persistence:"permanent",order:65,experiment:"js-profiler-temporarily-enable",loadView:async()=>(await re()).ProfilesPanel.JSProfilerPanel.instance()}),i.ActionRegistration.registerActionExtension({actionId:"timeline.toggle-recording",category:"PERFORMANCE",iconClass:"record-start",toggleable:!0,toggledIconClass:"record-stop",toggleWithRedColor:!0,contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),options:[{value:!0,title:oe(ee.record)},{value:!1,title:oe(ee.stop)}],bindings:[{platform:"windows,linux",shortcut:"Ctrl+E"},{platform:"mac",shortcut:"Meta+E"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.record-reload",iconClass:"refresh",contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),category:"PERFORMANCE",title:oe(ee.startProfilingAndReloadPage),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),bindings:[{platform:"windows,linux",shortcut:"Ctrl+Shift+E"},{platform:"mac",shortcut:"Meta+Shift+E"}]}),i.ActionRegistration.registerActionExtension({category:"PERFORMANCE",actionId:"timeline.save-to-file",contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.saveProfile),bindings:[{platform:"windows,linux",shortcut:"Ctrl+S"},{platform:"mac",shortcut:"Meta+S"}]}),i.ActionRegistration.registerActionExtension({category:"PERFORMANCE",actionId:"timeline.load-from-file",contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.loadProfile),bindings:[{platform:"windows,linux",shortcut:"Ctrl+O"},{platform:"mac",shortcut:"Meta+O"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.jump-to-previous-frame",category:"PERFORMANCE",title:oe(ee.previousFrame),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),bindings:[{shortcut:"["}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.jump-to-next-frame",category:"PERFORMANCE",title:oe(ee.nextFrame),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),bindings:[{shortcut:"]"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.show-history",loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),category:"PERFORMANCE",title:oe(ee.showRecentTimelineSessions),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),bindings:[{platform:"windows,linux",shortcut:"Ctrl+H"},{platform:"mac",shortcut:"Meta+Y"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.previous-recording",category:"PERFORMANCE",loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.previousRecording),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),bindings:[{platform:"windows,linux",shortcut:"Alt+Left"},{platform:"mac",shortcut:"Meta+Left"}]}),i.ActionRegistration.registerActionExtension({actionId:"timeline.next-recording",category:"PERFORMANCE",loadActionDelegate:async()=>new((await ae()).TimelinePanel.ActionDelegate),title:oe(ee.nextRecording),contextTypes:()=>se((e=>[e.TimelinePanel.TimelinePanel])),bindings:[{platform:"windows,linux",shortcut:"Alt+Right"},{platform:"mac",shortcut:"Meta+Right"}]}),i.ActionRegistration.registerActionExtension({actionId:"profiler.js-toggle-recording",category:"JAVASCRIPT_PROFILER",title:oe(ee.startStopRecording),iconClass:"record-start",toggleable:!0,toggledIconClass:"record-stop",toggleWithRedColor:!0,contextTypes:()=>void 0===ne?[]:(e=>[e.ProfilesPanel.JSProfilerPanel])(ne),loadActionDelegate:async()=>(await re()).ProfilesPanel.JSProfilerPanel.instance(),bindings:[{platform:"windows,linux",shortcut:"Ctrl+E"},{platform:"mac",shortcut:"Meta+E"}]}),e.Settings.registerSettingExtension({category:"PERFORMANCE",storageType:"Synced",title:oe(ee.hideChromeFrameInLayersView),settingName:"frame-viewer-hide-chrome-window",settingType:"boolean",defaultValue:!1}),e.Linkifier.registerLinkifier({contextTypes:()=>se((e=>[e.CLSLinkifier.CLSRect])),loadLinkifier:async()=>(await ae()).CLSLinkifier.Linkifier.instance()}),i.ContextMenu.registerItem({location:"timelineMenu/open",actionId:"timeline.load-from-file",order:10}),i.ContextMenu.registerItem({location:"timelineMenu/open",actionId:"timeline.save-to-file",order:15}),l.rnPerfMetrics.registerPerfMetricsGlobalPostMessageHandler(),l.rnPerfMetrics.registerGlobalErrorReporting(),l.rnPerfMetrics.setLaunchId(o.Runtime.Runtime.queryParam("launchId")),l.rnPerfMetrics.entryPointLoadingStarted("rn_fusebox");const le={networkTitle:"React Native",showReactNative:"Show React Native",sendFeedback:"[FB-only] Send feedback"},ce=t.i18n.registerUIStrings("entrypoints/rn_fusebox/rn_fusebox.ts",le),de=t.i18n.getLazilyComputedLocalizedString.bind(void 0,ce);i.ViewManager.maybeRemoveViewExtension("network.blocked-urls"),i.ViewManager.maybeRemoveViewExtension("network.config"),i.ViewManager.maybeRemoveViewExtension("coverage"),i.ViewManager.maybeRemoveViewExtension("linear-memory-inspector"),i.ViewManager.maybeRemoveViewExtension("rendering"),i.ViewManager.maybeRemoveViewExtension("issues-pane"),i.ViewManager.maybeRemoveViewExtension("sensors"),i.ViewManager.maybeRemoveViewExtension("devices"),i.ViewManager.maybeRemoveViewExtension("emulation-locations"),i.ViewManager.maybeRemoveViewExtension("throttling-conditions"),d.RNExperimentsImpl.setIsReactNativeEntryPoint(!0),d.RNExperimentsImpl.Instance.enableExperimentsByDefault(["react-native-specific-ui"]),document.addEventListener("visibilitychange",(()=>{l.rnPerfMetrics.browserVisibilityChanged(document.visibilityState)}));class ge extends a.SDKModel.SDKModel{constructor(e){super(e),l.rnPerfMetrics.fuseboxSetClientMetadataStarted(),e.fuseboxClientAgent().invoke_setClientMetadata().then((e=>{const t=e.getError(),o=!t;l.rnPerfMetrics.fuseboxSetClientMetadataFinished(o,t)})).catch((e=>{l.rnPerfMetrics.fuseboxSetClientMetadataFinished(!1,e)}))}}let me;if(a.SDKModel.SDKModel.register(ge,{capabilities:0,autostart:!0,early:!0}),i.ViewManager.registerViewExtension({location:"navigator-view",id:"navigator-network",title:de(le.networkTitle),commandPrompt:de(le.showReactNative),order:2,persistence:"permanent",loadView:async()=>(await async function(){return me||(me=await import("../../panels/sources/sources.js")),me}()).SourcesNavigator.NetworkNavigatorView.instance()}),self.runtime=o.Runtime.Runtime.instance({forceNew:!0}),new c.MainImpl.MainImpl,globalThis.FB_ONLY__reactNativeFeedbackLink){const e=globalThis.FB_ONLY__reactNativeFeedbackLink,t="react-native-send-feedback",o={handleAction:(o,i)=>i===t&&(l.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(e),!0)};i.ActionRegistration.registerActionExtension({category:"GLOBAL",actionId:t,title:de(le.sendFeedback),loadActionDelegate:async()=>o,iconClass:"bug"}),i.Toolbar.registerToolbarItem({location:"main-toolbar-right",actionId:t,showLabel:!0})}l.rnPerfMetrics.entryPointLoadingFinished("rn_fusebox"); From bb886d751f125944d3e9202ebe7d8849866c54b9 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 03:13:13 -0700 Subject: [PATCH 038/968] Improve test stability in CI (#45070) Summary: This change splits the build step and the test step for running the test on iOS, so we can introduce a retry for the test only. We are doing that because we have seen some flakyness in CI jobs as sometimes the simulator fails to install the app. ## Changelog: [Internal] - Add retry to iOS tests Pull Request resolved: https://github.com/facebook/react-native/pull/45070 Test Plan: Testing in CircleCI Reviewed By: cortinico Differential Revision: D58786706 Pulled By: cipolleschi fbshipit-source-id: 61363cb86dd1a496d3595b43b6331cbee7f032ea --- scripts/objc-test.sh | 50 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/scripts/objc-test.sh b/scripts/objc-test.sh index 8a72413fb59b26..b8b34d0a7f07e3 100755 --- a/scripts/objc-test.sh +++ b/scripts/objc-test.sh @@ -83,6 +83,24 @@ runTests() { "${SKIPPED_TESTS[@]}" } +buildForTesting() { + # shellcheck disable=SC1091 + source "$ROOT/scripts/.tests.env" + xcodebuild build-for-testing \ + -workspace RNTesterPods.xcworkspace \ + -scheme RNTester \ + -sdk iphonesimulator +} + +runTestsOnly() { + xcodebuild test \ + -workspace RNTesterPods.xcworkspace \ + -scheme RNTester \ + -sdk iphonesimulator \ + -destination "platform=iOS Simulator,name=$IOS_DEVICE,OS=$IOS_TARGET_OS" \ + "${SKIPPED_TESTS[@]}" +} + buildProject() { xcodebuild build \ -workspace RNTesterPods.xcworkspace \ @@ -133,13 +151,33 @@ main() { preloadBundlesRNTester preloadBundlesRNIntegrationTests + buildForTesting + # Build and run tests. - if [ -x "$(command -v xcbeautify)" ]; then - runTests | xcbeautifyFormat && exit "${PIPESTATUS[0]}" - else - echo 'Warning: xcbeautify is not installed. Install xcbeautify to generate JUnit reports.' - runTests - fi + RESULT=-1 + MAX_RETRY=3 + for ((i=1; i<=MAX_RETRY; i++)) + do + echo "Attempt #$i of running tests..." + if [ -x "$(command -v xcbeautify)" ]; then + runTests | xcbeautifyFormat && exit "${PIPESTATUS[0]}" + RESULT="$?" + else + echo 'Warning: xcbeautify is not installed. Install xcbeautify to generate JUnit reports.' + runTests + RESULT="$?" + fi + + if [[ "$RESULT" == 0 ]]; then + # Successful tests! + echo "Test completed successfully!" + exit 0 + fi + done + + echo "Test Failed with code $RESULT!" + exit $RESULT + else # Build without running tests. if [ -x "$(command -v xcbeautify)" ]; then From b04d0d0c8cc8912b9f75fc40fb45c0cdc2b1163e Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 03:24:29 -0700 Subject: [PATCH 039/968] Port Update the testing script to run with the community template (#45064) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45064 This changes port back in main the changes we made in the Stable branch with https://github.com/facebook/react-native/commit/b236f9bd82374e5cf92e1ad622bba3b14f948a04 ## Changelog: [Internal] - Update release testing to work with the new template Reviewed By: cortinico Differential Revision: D58782241 fbshipit-source-id: be9f6d4310d3a83e6cc0df4bb690c746229c7ae3 --- scripts/release-testing/test-e2e-local.js | 28 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/scripts/release-testing/test-e2e-local.js b/scripts/release-testing/test-e2e-local.js index 0242df6dfa3a69..a4710c41458317 100644 --- a/scripts/release-testing/test-e2e-local.js +++ b/scripts/release-testing/test-e2e-local.js @@ -19,7 +19,6 @@ const {REPO_ROOT} = require('../consts'); const {initNewProjectFromSource} = require('../e2e/init-template-e2e'); -const updateTemplatePackage = require('../releases/update-template-package'); const { checkPackagerRunning, launchPackagerInSeparateWindow, @@ -245,6 +244,11 @@ async function testRNTestProject( const buildType = 'dry-run'; const reactNativePackagePath = `${REPO_ROOT}/packages/react-native`; + const templateRepoFolder = '/tmp/template'; + const pathToTemplate = path.join(templateRepoFolder, 'template'); + + // Cleanup template clone folder + exec(`rm -rf ${templateRepoFolder}`); const localNodeTGZPath = `${reactNativePackagePath}/react-native-${releaseVersion}.tgz`; const mavenLocalPath = @@ -282,18 +286,32 @@ async function testRNTestProject( } } - updateTemplatePackage({ - 'react-native': `file://${newLocalNodeTGZ}`, - }); + // Cloning the template repo + // TODO: handle versioning of the template to make sure that we are downloading the right version of + // the template, given a specific React Native version + exec( + `git clone https://github.com/react-native-community/template ${templateRepoFolder} --depth=1`, + ); + + // Update template version. + const appPackageJsonPath = path.join(pathToTemplate, 'package.json'); + const appPackageJson = JSON.parse( + fs.readFileSync(appPackageJsonPath, 'utf8'), + ); + appPackageJson.dependencies['react-native'] = `file:${newLocalNodeTGZ}`; + fs.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2)); pushd('/tmp/'); debug('Creating RNTestProject from template'); + // Cleanup RNTestProject folder. This makes it easier to rerun the script when it fails + exec('rm -rf /tmp/RNTestProject'); + await initNewProjectFromSource({ projectName: 'RNTestProject', directory: '/tmp/RNTestProject', - templatePath: reactNativePackagePath, + templatePath: templateRepoFolder, }); cd('RNTestProject'); From 90d4d551220b7bbd2cf10722ae09fb978bf119fe Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 03:24:29 -0700 Subject: [PATCH 040/968] Port Create Release fixes from Stable to main (#45063) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45063 While doing the release of 0.75, we have to fix the Create Release action a few times to get it right. This change contains the fixes from * https://github.com/facebook/react-native/commit/e36b46f0c970dc3f1f5b5058a8d10834acdb2667 * https://github.com/facebook/react-native/commit/1b891357b2f1995f2344cc991be423ca66fa6770 * https://github.com/facebook/react-native/commit/56e1c8bfdd57600e79c0b17de1d2fd933d20b8f9 * https://github.com/facebook/react-native/commit/03591318fbabdc0c06808316f471cc361b53c57f * https://github.com/facebook/react-native/commit/528097709aeef434b0d85565bfd89a4a9ff5644e * https://github.com/facebook/react-native/commit/f4b1dd1fa11374cae8a696833ad9ded0767cba8f ## Changelog [Internal] - Backport changes to Create Release github action Reviewed By: cortinico Differential Revision: D58782391 fbshipit-source-id: b68088fb8c4290efcb4599d1b090b18e401e4b66 --- .github/actions/create-release/action.yml | 18 +++++++++++++++++- .github/workflows/create-release.yml | 8 +++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/actions/create-release/action.yml b/.github/actions/create-release/action.yml index cce43d9348ba82..fb52223504f087 100644 --- a/.github/actions/create-release/action.yml +++ b/.github/actions/create-release/action.yml @@ -1,11 +1,27 @@ name: create_release description: Creates a new React Native release +inputs: + version: + description: 'The version of React Native we want to release. For example 0.75.0-rc.0' + required: true + is_latest_on_npm: + description: 'Whether we want to tag this release as latest on NPM' + required: true + default: "false" + dry_run: + description: 'Whether the job should be executed in dry-run mode or not' + default: "true" runs: using: composite steps: - name: Yarn install shell: bash run: yarn install --non-interactive + - name: Configure Git + shell: bash + run: | + git config --local user.email "bot@reactnative.dev" + git config --local user.name "React Native Bot" - name: Creating release commit shell: bash run: | @@ -23,7 +39,7 @@ runs: git tag -a "latest" -m "latest" - name: Pushing release commit shell: bash - if: ${{ inputs.dry_run == false }} + if: ${{ inputs.dry_run == 'false' }} run: | CURR_BRANCH="$(git branch --show-current)" git push origin "$CURR_BRANCH" --follow-tags diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 85e14987843cae..07e46d8a7a167a 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -18,11 +18,13 @@ on: default: false jobs: - prepare_release: + create_release: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4.1.1 + with: + token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }} - name: Check if on stable branch id: check_stable_branch run: | @@ -46,3 +48,7 @@ jobs: - name: Execute Prepare Release if: ${{ steps.check_stable_branch.outputs.ON_STABLE_BRANCH && !steps.check_if_tag_exists.outputs.TAG_EXISTS }} uses: ./.github/actions/create-release + with: + version: ${{ inputs.version }} + is_latest_on_npm: ${{ inputs.is_latest_on_npm }} + dry_run: ${{ inputs.dry_run }} From 710b0e64ab7539fb4d98e8bec4b51bea798a4f3f Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 03:24:29 -0700 Subject: [PATCH 041/968] Port fixes to release scripts to use GITHUB_REF and GITHUB_REF_NAME variables (#45066) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45066 This changes ports in main the fixes we had to make to the release scripts to run properly in release mode. This includes the commits: * https://github.com/facebook/react-native/commit/375c88478c985976e1b59dfa7353042a18b4d132 * https://github.com/facebook/react-native/commit/609c7c05b13214f2a834b251de095243f8dcbf68 * https://github.com/facebook/react-native/pull/45062 ## Changelog: [Internal] - Fix release scripts to run properly in release mode Reviewed By: cortinico Differential Revision: D58782925 fbshipit-source-id: b096909d5f8281809ee3c2a01eefda1d19f32936 --- scripts/__tests__/npm-utils-test.js | 30 ++++++++++++++++++++++++++++- scripts/npm-utils.js | 20 ++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/scripts/__tests__/npm-utils-test.js b/scripts/__tests__/npm-utils-test.js index 7b4345256d5b05..8bf753470fe906 100644 --- a/scripts/__tests__/npm-utils-test.js +++ b/scripts/__tests__/npm-utils-test.js @@ -115,6 +115,12 @@ describe('npm-utils', () => { }); describe('getNpmInfo', () => { + beforeEach(() => { + process.env.CIRCLE_TAG = ''; + process.env.GITHUB_REF = ''; + process.env.GITHUB_REF_NAME = ''; + }); + it('return the expected format for prealpha', () => { const isoStringSpy = jest.spyOn(Date.prototype, 'toISOString'); isoStringSpy.mockReturnValue('2023-10-04T15:43:55.123Z'); @@ -147,7 +153,29 @@ describe('npm-utils', () => { version: `0.74.1-rc.0`, tag: '--no-tag', }); - process.env.CIRCLE_TAG = null; + }); + + it('return the expected format for patch-prereleases on GHA', () => { + const isoStringSpy = jest.spyOn(Date.prototype, 'toISOString'); + isoStringSpy.mockReturnValue('2023-10-04T15:43:55.123Z'); + getCurrentCommitMock.mockImplementation(() => 'abcd1234'); + // exitIfNotOnGit takes a function as a param and it: + // 1. checks if we are on git => if not it exits + // 2. run the function passed as a param and return the output to the caller + // For the mock, we are assuming we are on github and we are returning `false` + // as the `getNpmInfo` function will pass a function that checks if the + // current commit is a tagged with 'latest'. + // In the Mock, we are assuming that we are on git (it does not exits) and the + // checkIfLatest function returns `false` + exitIfNotOnGitMock.mockImplementation(() => false); + + process.env.GITHUB_REF = 'refs/tags/v0.74.1-rc.0'; + process.env.GITHUB_REF_NAME = 'v0.74.1-rc.0'; + const returnedValue = getNpmInfo('release'); + expect(returnedValue).toMatchObject({ + version: `0.74.1-rc.0`, + tag: '--no-tag', + }); }); }); diff --git a/scripts/npm-utils.js b/scripts/npm-utils.js index 3a973a87f664d5..7594283d69f15f 100644 --- a/scripts/npm-utils.js +++ b/scripts/npm-utils.js @@ -89,14 +89,28 @@ function getNpmInfo(buildType /*: BuildType */) /*: NpmInfo */ { } if (buildType === 'release') { - if (process.env.CIRCLE_TAG == null) { + let versionTag /*: string*/ = ''; + if (process.env.CIRCLE_TAG != null && process.env.CIRCLE_TAG !== '') { + versionTag = process.env.CIRCLE_TAG; + } else if ( + process.env.GITHUB_REF != null && + process.env.GITHUB_REF.includes('/tags/') && + process.env.GITHUB_REF_NAME != null && + process.env.GITHUB_REF_NAME !== '' + ) { + // GITHUB_REF contains the fully qualified ref, for example refs/tags/v0.75.0-rc.0 + // GITHUB_REF_NAME contains the short name, for example v0.75.0-rc.0 + versionTag = process.env.GITHUB_REF_NAME; + } + + if (versionTag === '') { throw new Error( - 'CIRCLE_TAG is not set for release. This should only be run in CircleCI. See https://circleci.com/docs/variables/ for how CIRCLE_TAG is set.', + 'No version tag found in CI. It looks like this script is running in release mode, but the CIRCLE_TAG or the GITHUB_REF_NAME are missing.', ); } const {version, major, minor, patch, prerelease} = parseVersion( - process.env.CIRCLE_TAG, + versionTag, buildType, ); From ea31a79fe929214cacf592ee3c2ad79eb6835388 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 03:24:29 -0700 Subject: [PATCH 042/968] Fix build_android by setting git safe folders (#45065) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45065 This fix makes sure that Android runner can run git commands. This is porting in main the commit https://github.com/facebook/react-native/commit/fee215664287ddca31c8400c87a825c8e9822290 ## Changelog [Internal] - Make the build_android run git commands Reviewed By: cortinico Differential Revision: D58782969 fbshipit-source-id: ab35f7e3d1733ab770f2a397552daa1ec7c13cf7 --- .github/workflows/publish-release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 257c019a975327..dbbf132723ab1b 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -515,7 +515,9 @@ jobs: - name: Install dependencies run: yarn install --non-interactive - name: Set React Native Version - run: node ./scripts/releases/set-rn-version.js --build-type ${{ needs.set_release_type.outputs.RELEASE_TYPE }} + run: | + git config --global --add safe.directory /__w/react-native/react-native + node ./scripts/releases/set-rn-version.js --build-type ${{ needs.set_release_type.outputs.RELEASE_TYPE }} - name: Setup gradle uses: ./.github/actions/setup-gradle - name: Build and publish all the Android Artifacts to /tmp/maven-local From a297b30377d67a6e343d1692bc5e5961e1a9584e Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 20 Jun 2024 06:04:45 -0700 Subject: [PATCH 043/968] Bump reactnativecommunity/react-native-android to 13.1 (#45073) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45073 We can also remove the workaround needed for git `safe.directory` as this is now configured inside the container as `*` Changelog: [Internal] [Changed] - Bump reactnativecommunity/react-native-android to 13.1 Reviewed By: blakef Differential Revision: D58789791 fbshipit-source-id: f44163a0aa822b19e0dd1106d3f039fd0dc83186 --- .circleci/configurations/top_level.yml | 2 +- .github/workflows/nightly.yml | 1 - .github/workflows/publish-release.yml | 1 - .github/workflows/test-all.yml | 5 ----- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.circleci/configurations/top_level.yml b/.circleci/configurations/top_level.yml index 3ede1cc3d9dc59..fd25dab7892f0b 100644 --- a/.circleci/configurations/top_level.yml +++ b/.circleci/configurations/top_level.yml @@ -25,7 +25,7 @@ references: android-defaults: &android-defaults working_directory: ~/react-native docker: - - image: reactnativecommunity/react-native-android:v13.0 + - image: reactnativecommunity/react-native-android:v13.1 environment: - TERM: "dumb" - GRADLE_OPTS: '-Dorg.gradle.daemon=false' diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 05524352f12174..155eddf0a3f108 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -668,7 +668,6 @@ jobs: run: echo "//registry.npmjs.org/:_authToken=${{ secrets.GHA_NPM_TOKEN }}" > ~/.npmrc - name: Publish NPM run: | - git config --global --add safe.directory /__w/react-native/react-native echo "GRADLE_OPTS = $GRADLE_OPTS" export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64" node ./scripts/releases-ci/publish-npm.js -t nightly diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index dbbf132723ab1b..30da62e810fa2e 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -668,7 +668,6 @@ jobs: run: echo "//registry.npmjs.org/:_authToken=${{ secrets.GHA_NPM_TOKEN }}" > ~/.npmrc - name: Publish NPM run: | - git config --global --add safe.directory /__w/react-native/react-native echo "GRADLE_OPTS = $GRADLE_OPTS" export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64" node ./scripts/releases-ci/publish-npm.js -t release diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 246b0e04f22f68..f2dc2829019399 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -748,11 +748,6 @@ jobs: - name: Publish NPM shell: bash run: | - # The checkout command puts react-native in a folder that is not "safe" for git - # Every git command run in an unsafe folder fails. We need to pick the current commit to use it as part of the version - # The following line marks the folder where react-native lives as "safe" - git config --global --add safe.directory /__w/react-native/react-native - echo "GRADLE_OPTS = $GRADLE_OPTS" # We can't have a separate step because each command is executed in a separate shell # so variables exported in a command are not visible in another. From a2cb34371e6e52305ee58f23d3b2fefc1e8c7157 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 20 Jun 2024 06:15:11 -0700 Subject: [PATCH 044/968] Handle textAlignment: start and make logs consistent (#45076) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45076 > **start**: The same as left if direction is left-to-right and right if direction is right-to-left. This is equivalent to `auto`, which is not actually a valid CSS value. Changelog: [General][Added] Add support for `texAlignment: 'start'` Reviewed By: sammy-SC Differential Revision: D58791937 fbshipit-source-id: 09622d814212a7055f94b1f091c71edae5db117c --- .../renderer/attributedstring/conversions.h | 3 +-- .../renderer/components/view/conversions.h | 20 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h index a975fe080d9b33..d2a40f49765304 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h @@ -413,7 +413,7 @@ inline void fromRawValue( react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; - if (string == "auto") { + if (string == "auto" || string == "start") { result = TextAlignment::Natural; } else if (string == "left") { result = TextAlignment::Left; @@ -425,7 +425,6 @@ inline void fromRawValue( result = TextAlignment::Justified; } else { LOG(ERROR) << "Unsupported TextAlignment value: " << string; - react_native_expect(false); // sane default for prod result = TextAlignment::Natural; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index e11e075b52a789..d1cd9b9ac0fc85 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -188,8 +188,7 @@ inline void fromRawValue( result = yoga::Direction::RTL; return; } - LOG(ERROR) << "Could not parse Direction:" << stringValue; - react_native_expect(false); + LOG(ERROR) << "Could not parse yoga::Direction: " << stringValue; } inline void fromRawValue( @@ -218,8 +217,7 @@ inline void fromRawValue( result = yoga::FlexDirection::RowReverse; return; } - LOG(ERROR) << "Could not parse yoga::FlexDirection:" << stringValue; - react_native_expect(false); + LOG(ERROR) << "Could not parse yoga::FlexDirection: " << stringValue; } inline void fromRawValue( @@ -256,8 +254,7 @@ inline void fromRawValue( result = yoga::Justify::SpaceEvenly; return; } - LOG(ERROR) << "Could not parse yoga::Justify:" << stringValue; - react_native_expect(false); + LOG(ERROR) << "Could not parse yoga::Justify: " << stringValue; } inline void fromRawValue( @@ -306,7 +303,7 @@ inline void fromRawValue( result = yoga::Align::SpaceEvenly; return; } - LOG(ERROR) << "Could not parse yoga::Align:" << stringValue; + LOG(ERROR) << "Could not parse yoga::Align: " << stringValue; react_native_expect(false); } @@ -332,8 +329,7 @@ inline void fromRawValue( result = yoga::PositionType::Absolute; return; } - LOG(ERROR) << "Could not parse yoga::PositionType:" << stringValue; - react_native_expect(false); + LOG(ERROR) << "Could not parse yoga::PositionType: " << stringValue; } inline void fromRawValue( @@ -358,8 +354,7 @@ inline void fromRawValue( result = yoga::Wrap::WrapReverse; return; } - LOG(ERROR) << "Could not parse yoga::Wrap:" << stringValue; - react_native_expect(false); + LOG(ERROR) << "Could not parse yoga::Wrap: " << stringValue; } inline void fromRawValue( @@ -406,8 +401,7 @@ inline void fromRawValue( result = yoga::Display::None; return; } - LOG(ERROR) << "Could not parse yoga::Display:" << stringValue; - react_native_expect(false); + LOG(ERROR) << "Could not parse yoga::Display: " << stringValue; } inline void fromRawValue( From 2e6f105ef3af60e8a6c83a88df106b51bc253f4b Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 20 Jun 2024 06:15:11 -0700 Subject: [PATCH 045/968] Pass EventDispatcher listeners by value (#45077) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45077 Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D58791938 fbshipit-source-id: 079fbfad4dd309a41c360e1bdb93e56f8793e6b3 --- .../ReactCommon/react/renderer/core/EventDispatcher.cpp | 5 +++-- .../ReactCommon/react/renderer/core/EventDispatcher.h | 2 +- .../ReactCommon/react/renderer/core/EventListener.cpp | 9 ++++++--- .../ReactCommon/react/renderer/core/EventListener.h | 2 +- .../ReactCommon/react/renderer/scheduler/Scheduler.cpp | 4 ++-- .../ReactCommon/react/renderer/scheduler/Scheduler.h | 2 +- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp index 5b95b5d62b30f8..f55e5023297e59 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp @@ -59,12 +59,13 @@ void EventDispatcher::dispatchUniqueEvent(RawEvent&& rawEvent) const { if (eventListeners_.willDispatchEvent(rawEvent)) { return; } + eventQueue_.enqueueUniqueEvent(std::move(rawEvent)); } void EventDispatcher::addListener( - const std::shared_ptr& listener) const { - eventListeners_.addListener(listener); + std::shared_ptr listener) const { + eventListeners_.addListener(std::move(listener)); } /* diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h index f339ba6d8313d5..36e4d03c6d9e6a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h @@ -64,7 +64,7 @@ class EventDispatcher { /* * Adds provided event listener to the event dispatcher. */ - void addListener(const std::shared_ptr& listener) const; + void addListener(std::shared_ptr listener) const; /* * Removes provided event listener to the event dispatcher. diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventListener.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventListener.cpp index cbe8d3287ba846..a64e24fdff706a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventListener.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventListener.cpp @@ -16,16 +16,19 @@ bool EventListenerContainer::willDispatchEvent(const RawEvent& event) { bool handled = false; for (const auto& listener : eventListeners_) { - handled = handled || listener->operator()(event); + handled = (*listener)(event); + if (handled) { + break; + } } return handled; } void EventListenerContainer::addListener( - const std::shared_ptr& listener) { + std::shared_ptr listener) { std::unique_lock lock(mutex_); - eventListeners_.push_back(listener); + eventListeners_.push_back(std::move(listener)); } void EventListenerContainer::removeListener( diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventListener.h b/packages/react-native/ReactCommon/react/renderer/core/EventListener.h index ca36430a453237..1d5e72168dd923 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventListener.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventListener.h @@ -30,7 +30,7 @@ class EventListenerContainer { */ bool willDispatchEvent(const RawEvent& event); - void addListener(const std::shared_ptr& listener); + void addListener(std::shared_ptr listener); void removeListener(const std::shared_ptr& listener); private: diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp index 8469db758205b4..a178f2b3a76500 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -364,9 +364,9 @@ std::shared_ptr Scheduler::getUIManager() const { } void Scheduler::addEventListener( - const std::shared_ptr& listener) { + std::shared_ptr listener) { if (eventDispatcher_->has_value()) { - eventDispatcher_->value().addListener(listener); + eventDispatcher_->value().addListener(std::move(listener)); } } diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h index 265aebc9a65461..893030895d7932 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.h @@ -109,7 +109,7 @@ class Scheduler final : public UIManagerDelegate { void reportMount(SurfaceId surfaceId) const; #pragma mark - Event listeners - void addEventListener(const std::shared_ptr& listener); + void addEventListener(std::shared_ptr listener); void removeEventListener( const std::shared_ptr& listener); From 9c6c63781669bd1d6451c880671a151060220020 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 06:50:23 -0700 Subject: [PATCH 046/968] Refactor Hermes workspace (#45071) Summary: This change is the first step in refactoring GHA so that they can be reused more easily across jobs. Its goal is also to be more reliable w.r.t. caches. That this change do: * moves `prepare_hermes_workspace` to a composite action * saves the `prepare_hermes_workspace` caches only on main * uploads the destination folder as an artifact so that we can use it later in the run * makes the `test-all`, `nightly` and `publish-release` workflow use the new composite action * updates the `setup-hermes-workspace` to download and use the artifact uploaded by `prepare_hermes_workspace` ## Changelog: [Internal] - Factor out the prepare_hermes_workspace action Pull Request resolved: https://github.com/facebook/react-native/pull/45071 Test Plan: GHA in CI Reviewed By: cortinico Differential Revision: D58808087 Pulled By: cipolleschi fbshipit-source-id: 42c46bcf75fc73b2edfda9be62b5d0fe8a919a5d --- .github/actions/cache_setup/action.yml | 2 +- .../prepare-hermes-workspace/action.yml | 104 ++++++++++++++++++ .../action.yml | 9 +- .../actions/test_ios_helloworld/action.yml | 4 +- .github/workflows/nightly.yml | 69 ++---------- .github/workflows/publish-release.yml | 69 ++---------- .github/workflows/test-all.yml | 70 +++--------- 7 files changed, 153 insertions(+), 174 deletions(-) create mode 100644 .github/actions/prepare-hermes-workspace/action.yml rename .github/actions/{setup_hermes_workspace => restore-hermes-workspace}/action.yml (56%) diff --git a/.github/actions/cache_setup/action.yml b/.github/actions/cache_setup/action.yml index 7258313b8ca2b9..e88137432836bd 100644 --- a/.github/actions/cache_setup/action.yml +++ b/.github/actions/cache_setup/action.yml @@ -84,5 +84,5 @@ runs: path: | /tmp/hermes/download/ /tmp/hermes/hermes/ - key: v1-hermes-${{ inputs.hermes-version }}-${{ github.run_number }} + key: v1-hermes-${{ inputs.hermes-version }} enableCrossOsArchive: true diff --git a/.github/actions/prepare-hermes-workspace/action.yml b/.github/actions/prepare-hermes-workspace/action.yml new file mode 100644 index 00000000000000..8daa02ca4874da --- /dev/null +++ b/.github/actions/prepare-hermes-workspace/action.yml @@ -0,0 +1,104 @@ +name: prepare-hermes-workspace +description: This action prepares the hermes workspace with the right hermes and react-native versions. +inputs: + HERMES_WS_DIR: + required: true + description: The hermes dir we need to use to setup the workspace + HERMES_VERSION_FILE: + required: true + description: the path to the file that will contain the hermes version + BUILD_FROM_SOURCE: + description: Whether we need to build from source or not + default: true +outputs: + hermes-version: + description: the version of Hermes tied to this run + value: ${{ steps.hermes-version.outputs.VERSION }} + react-native-version: + description: the version of React Native tied to this run + value: ${{ steps.react-native-version.outputs.VERSION }} +runs: + using: composite + steps: + - name: Setup node.js + uses: ./.github/actions/setup-node + + - name: Setup hermes version + shell: bash + id: hermes-version + run: | + mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" + + if [ -f "$HERMES_VERSION_FILE" ]; then + echo "Hermes Version file found! Using this version for the build:" + echo "VERSION=$(cat $HERMES_VERSION_FILE)" >> "$GITHUB_OUTPUT" + else + echo "Hermes Version file not found!!!" + echo "Using the last commit from main for the build:" + HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') + echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" + fi + echo "Hermes commit is $HERMES_TAG_SHA" + + - name: Get react-native version + shell: bash + id: react-native-version + run: | + VERSION=$(cat packages/react-native/package.json | jq -r '.version') + # Save the react native version we are building in an output variable so we can use that file as part of the cache key. + echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" + echo "React Native Version is $VERSION" + + - name: Cache hermes workspace + id: restore-hermes + uses: actions/cache/restore@v4.0.0 + with: + path: | + /tmp/hermes/download/ + /tmp/hermes/hermes/ + key: v1-hermes-${{ steps.hermes-version.outputs.version }} + enableCrossOsArchive: true + + # It happened while testing that a cache was created from the right folders + # but those folders where empty. Thus, the next check ensures that we can work with those caches. + - name: Check if cache was meaningful + id: meaningful-cache + shell: bash + run: | + if [[ -d /tmp/hermes/hermes ]] && [[ -n "$(ls -A /tmp/hermes/hermes)" ]]; then + echo "Found a good hermes cache" + echo "HERMES_CACHED=true" >> "$GITHUB_OUTPUT" + fi + + - name: Yarn- Install Dependencies + if: ${{ steps.meaningful-cache.outputs.HERMES_CACHED != 'true' }} + shell: bash + run: yarn install --non-interactive + + - name: Download Hermes tarball + if: ${{ steps.meaningful-cache.outputs.HERMES_CACHED != 'true' }} + shell: bash + run: | + node packages/react-native/scripts/hermes/prepare-hermes-for-build ${{ github.event.pull_request.html_url }} + cp packages/react-native/sdks/download/* $HERMES_WS_DIR/download/. + cp -r packages/react-native/sdks/hermes/* $HERMES_WS_DIR/hermes/. + + echo ${{ steps.hermes-version.outputs.version }} + + - name: Upload Hermes artifact + uses: actions/upload-artifact@v4 + with: + name: hermes-workspace + path: | + /tmp/hermes/download/ + /tmp/hermes/hermes/ + + - name: Cache hermes workspace + uses: actions/cache/save@v4.0.0 + if: ${{ github.ref == 'refs/heads/main' }} # To avoid that the cache explode. + with: + path: | + /tmp/hermes/download/ + /tmp/hermes/hermes/ + key: v1-hermes-${{ steps.hermes-version.outputs.version }} + enableCrossOsArchive: true diff --git a/.github/actions/setup_hermes_workspace/action.yml b/.github/actions/restore-hermes-workspace/action.yml similarity index 56% rename from .github/actions/setup_hermes_workspace/action.yml rename to .github/actions/restore-hermes-workspace/action.yml index a6fc425be672c9..0b1cb259435785 100644 --- a/.github/actions/setup_hermes_workspace/action.yml +++ b/.github/actions/restore-hermes-workspace/action.yml @@ -1,8 +1,13 @@ -name: setup_hermes_workspace -description: "Setup hermes workspace" +name: restore-hermes-workspace +description: "Restore hermes workspace that has been created in Prepare Hermes Workspace" runs: using: composite steps: + - name: Download Previous Artifacts + uses: actions/download-artifact@v4 + with: + name: hermes-workspace + path: /tmp/hermes - name: Set up workspace shell: bash run: | diff --git a/.github/actions/test_ios_helloworld/action.yml b/.github/actions/test_ios_helloworld/action.yml index b0e225cf39d80d..c4d4efb46d3ff6 100644 --- a/.github/actions/test_ios_helloworld/action.yml +++ b/.github/actions/test_ios_helloworld/action.yml @@ -54,8 +54,8 @@ runs: - name: Run yarn shell: bash run: yarn install --non-interactive - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Setup ruby uses: ruby/setup-ruby@v1.170.0 with: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 155eddf0a3f108..8ea77bb12431de 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -30,52 +30,14 @@ jobs: BUILD_FROM_SOURCE: true GRADLE_OPTS: '-Dorg.gradle.daemon=false' outputs: - react-native-version: ${{ steps.react-native-version.outputs.version }} - hermes-version: ${{ steps.hermes-version.outputs.version }} + react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }} + hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }} steps: - name: Checkout uses: actions/checkout@v4.1.1 - - name: Setup node.js - uses: ./.github/actions/setup-node - - name: Setup hermes version - id: hermes-version - run: | - mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" - - if [ -f "$HERMES_VERSION_FILE" ]; then - echo "Hermes Version file found! Using this version for the build:" - echo "VERSION=$(cat $HERMES_VERSION_FILE)" >> "$GITHUB_OUTPUT" - else - echo "Hermes Version file not found!!!" - echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') - echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" - fi - echo "Hermes commit is $HERMES_TAG_SHA" - - name: Get react-native version - id: react-native-version - run: | - VERSION=$(cat packages/react-native/package.json | jq -r '.version') - # Save the react native version we are building in an output variable so we can use that file as part of the cache key. - echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" - echo "React Native Version is $VERSION" - - name: Cache hermes workspace - uses: actions/cache@v4.0.0 - with: - path: | - /tmp/hermes/download/ - /tmp/hermes/hermes/ - key: v1-hermes-${{ steps.hermes-version.outputs.version }}-${{ github.run_number }} - enableCrossOsArchive: true - - name: Yarn- Install Dependencies - run: yarn install --non-interactive - - name: Download Hermes tarball - run: | - node packages/react-native/scripts/hermes/prepare-hermes-for-build ${{ github.event.pull_request.html_url }} - cp packages/react-native/sdks/download/* $HERMES_WS_DIR/download/. - cp -r packages/react-native/sdks/hermes/* $HERMES_WS_DIR/hermes/. - - echo ${{ steps.hermes-version.outputs.version }} + - name: Prepare Hermes Workspace + id: prepare-hermes-workspace + uses: ./.github/actions/prepare-hermes-workspace build_hermesc_apple: runs-on: macos-13 @@ -86,16 +48,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 - - name: Cache hermes workspace - uses: actions/cache@v4.0.0 - with: - path: | - /tmp/hermes/download/ - /tmp/hermes/hermes/ - key: v1-hermes-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ github.run_number }} - enableCrossOsArchive: true - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Hermes apple cache uses: actions/cache@v4.0.0 with: @@ -131,8 +85,8 @@ jobs: with: hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Check if the required artifacts already exist id: check_if_apple_artifacts_are_there run: | @@ -226,8 +180,8 @@ jobs: with: hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Check if the required artifacts already exist id: check_if_apple_artifacts_are_there run: | @@ -306,6 +260,7 @@ jobs: run: | cd ./packages/react-native/sdks/hermes || exit 1 echo "[HERMES] Creating the universal framework" + chmod +x ./utils/build-ios-framework.sh ./utils/build-ios-framework.sh build_framework - name: Package the Hermes Apple frameworks if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 30da62e810fa2e..fc3c5c8b8ddeb1 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -27,52 +27,14 @@ jobs: BUILD_FROM_SOURCE: true GRADLE_OPTS: '-Dorg.gradle.daemon=false' outputs: - react-native-version: ${{ steps.react-native-version.outputs.version }} - hermes-version: ${{ steps.hermes-version.outputs.version }} + react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }} + hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }} steps: - name: Checkout uses: actions/checkout@v4.1.1 - - name: Setup node.js - uses: ./.github/actions/setup-node - - name: Setup hermes version - id: hermes-version - run: | - mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" - - if [ -f "$HERMES_VERSION_FILE" ]; then - echo "Hermes Version file found! Using this version for the build:" - echo "VERSION=$(cat $HERMES_VERSION_FILE)" >> "$GITHUB_OUTPUT" - else - echo "Hermes Version file not found!!!" - echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') - echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" - fi - echo "Hermes commit is $HERMES_TAG_SHA" - - name: Get react-native version - id: react-native-version - run: | - VERSION=$(cat packages/react-native/package.json | jq -r '.version') - # Save the react native version we are building in an output variable so we can use that file as part of the cache key. - echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" - echo "React Native Version is $VERSION" - - name: Cache hermes workspace - uses: actions/cache@v4.0.0 - with: - path: | - /tmp/hermes/download/ - /tmp/hermes/hermes/ - key: v1-hermes-${{ steps.hermes-version.outputs.version }}-${{ github.run_number }} - enableCrossOsArchive: true - - name: Yarn- Install Dependencies - run: yarn install --non-interactive - - name: Download Hermes tarball - run: | - node packages/react-native/scripts/hermes/prepare-hermes-for-build ${{ github.event.pull_request.html_url }} - cp packages/react-native/sdks/download/* $HERMES_WS_DIR/download/. - cp -r packages/react-native/sdks/hermes/* $HERMES_WS_DIR/hermes/. - - echo ${{ steps.hermes-version.outputs.version }} + - name: Prepare Hermes Workspace + id: prepare-hermes-workspace + uses: ./.github/actions/prepare-hermes-workspace build_hermesc_apple: runs-on: macos-13 @@ -83,16 +45,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 - - name: Cache hermes workspace - uses: actions/cache@v4.0.0 - with: - path: | - /tmp/hermes/download/ - /tmp/hermes/hermes/ - key: v1-hermes-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ github.run_number }} - enableCrossOsArchive: true - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Hermes apple cache uses: actions/cache@v4.0.0 with: @@ -128,8 +82,8 @@ jobs: with: hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Check if the required artifacts already exist id: check_if_apple_artifacts_are_there run: | @@ -223,8 +177,8 @@ jobs: with: hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Check if the required artifacts already exist id: check_if_apple_artifacts_are_there run: | @@ -303,6 +257,7 @@ jobs: run: | cd ./packages/react-native/sdks/hermes || exit 1 echo "[HERMES] Creating the universal framework" + chmod +x ./utils/build-ios-framework.sh ./utils/build-ios-framework.sh build_framework - name: Package the Hermes Apple frameworks if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index f2dc2829019399..3b316a07aedd4f 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -37,52 +37,18 @@ jobs: HERMES_VERSION_FILE: packages/react-native/sdks/.hermesversion BUILD_FROM_SOURCE: true outputs: - react-native-version: ${{ steps.react-native-version.outputs.version }} - hermes-version: ${{ steps.hermes-version.outputs.version }} + react-native-version: ${{ steps.prepare-hermes-workspace.outputs.react-native-version }} + hermes-version: ${{ steps.prepare-hermes-workspace.outputs.hermes-version }} steps: - name: Checkout uses: actions/checkout@v4.1.1 - - name: Setup node.js - uses: ./.github/actions/setup-node - - name: Setup hermes version - id: hermes-version - run: | - mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" - - if [ -f "$HERMES_VERSION_FILE" ]; then - echo "Hermes Version file found! Using this version for the build:" - echo "VERSION=$(cat $HERMES_VERSION_FILE)" >> "$GITHUB_OUTPUT" - else - echo "Hermes Version file not found!!!" - echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') - echo "VERSION=$HERMES_TAG_SHA" >> "$GITHUB_OUTPUT" - fi - echo "Hermes commit is $HERMES_TAG_SHA" - - name: Get react-native version - id: react-native-version - run: | - VERSION=$(cat packages/react-native/package.json | jq -r '.version') - # Save the react native version we are building in an output variable so we can use that file as part of the cache key. - echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" - echo "React Native Version is $VERSION" - - name: Cache hermes workspace - uses: actions/cache@v4.0.0 + - name: Prepare Hermes Workspace + id: prepare-hermes-workspace + uses: ./.github/actions/prepare-hermes-workspace with: - path: | - /tmp/hermes/download/ - /tmp/hermes/hermes/ - key: v1-hermes-${{ steps.hermes-version.outputs.version }}-${{ github.run_number }} - enableCrossOsArchive: true - - name: Yarn- Install Dependencies - run: yarn install --non-interactive - - name: Download Hermes tarball - run: | - node packages/react-native/scripts/hermes/prepare-hermes-for-build ${{ github.event.pull_request.html_url }} - cp packages/react-native/sdks/download/* $HERMES_WS_DIR/download/. - cp -r packages/react-native/sdks/hermes/* $HERMES_WS_DIR/hermes/. - - echo ${{ steps.hermes-version.outputs.version }} + HERMES_WS_DIR: ${{ env.HERMES_WS_DIR }} + HERMES_VERSION_FILE: ${{ env.HERMES_VERSION_FILE }} + BUILD_FROM_SOURCE: ${{ env.BUILD_FROM_SOURCE }} build_hermesc_apple: runs-on: macos-13 @@ -93,16 +59,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 - - name: Cache hermes workspace - uses: actions/cache@v4.0.0 - with: - path: | - /tmp/hermes/download/ - /tmp/hermes/hermes/ - key: v1-hermes-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ github.run_number }} enableCrossOsArchive: true - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Hermes apple cache uses: actions/cache@v4.0.0 with: @@ -138,8 +97,8 @@ jobs: with: hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Check if the required artifacts already exist id: check_if_apple_artifacts_are_there run: | @@ -230,8 +189,8 @@ jobs: with: hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} - - name: Setup Hermes workspace - uses: ./.github/actions/setup_hermes_workspace + - name: Restore Hermes workspace + uses: ./.github/actions/restore-hermes-workspace - name: Check if the required artifacts already exist id: check_if_apple_artifacts_are_there run: | @@ -309,6 +268,7 @@ jobs: run: | cd ./packages/react-native/sdks/hermes || exit 1 echo "[HERMES] Creating the universal framework" + chmod +x ./utils/build-ios-framework.sh ./utils/build-ios-framework.sh build_framework - name: Package the Hermes Apple frameworks if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} From 75451d5b89d7f6c33688df23b57bea521374c2dc Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Jun 2024 07:49:52 -0700 Subject: [PATCH 047/968] Fix yml syntax on main (#45084) Summary: While landing a change on GH, I forget to remove one line that does not belong to an action ## Changelog: [Internal] - CI fix Pull Request resolved: https://github.com/facebook/react-native/pull/45084 Test Plan: GHA are green Reviewed By: blakef Differential Revision: D58817768 Pulled By: cipolleschi fbshipit-source-id: 5fc02d2d2a19dd3fe2202c93d0d1873e5dda4b82 --- .github/workflows/test-all.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 3b316a07aedd4f..46d0d8b7858bef 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -59,7 +59,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 - enableCrossOsArchive: true - name: Restore Hermes workspace uses: ./.github/actions/restore-hermes-workspace - name: Hermes apple cache From 8a3ffb6d23f169752891eddc7dad9e34cb2d861c Mon Sep 17 00:00:00 2001 From: Alan Lee Date: Thu, 20 Jun 2024 10:38:58 -0700 Subject: [PATCH 048/968] fix TextInput 'contextMenuHidden' prop (#45014) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45014 `TextInput`'s `contextMenuHidden` prop isn't working working as expected. It should hide the context menu (copy/paste/...) that pops up from input text. Reference: [Android doc](https://developer.android.com/reference/android/widget/TextView#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback)) > Returning false from `ActionMode.Callback.onCreateActionMode(ActionMode, android.view.Menu)` will prevent the action mode from being started. **Changelog:** [Android][Fixed] - TextInput's `contextMenuHidden` prop bug fix Reviewed By: javache Differential Revision: D58684366 fbshipit-source-id: 328c267ed0e896a78e114578e3a00adf41f2e095 --- packages/react-native/ReactAndroid/api/ReactAndroid.api | 1 + .../facebook/react/views/textinput/ReactEditText.java | 8 ++++++++ .../react/views/textinput/ReactTextInputManager.java | 9 +-------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 44635cb1a6ab2f..5140979d64d2e5 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -7739,6 +7739,7 @@ public class com/facebook/react/views/textinput/ReactEditText : androidx/appcomp public fun setBorderStyle (Ljava/lang/String;)V public fun setBorderWidth (IF)V public fun setContentSizeWatcher (Lcom/facebook/react/views/textinput/ContentSizeWatcher;)V + public fun setContextMenuHidden (Z)V public fun setDisableFullscreenUI (Z)V public fun setFontFamily (Ljava/lang/String;)V public fun setFontFeatureSettings (Ljava/lang/String;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 014e0b489dd340..92cd700113c86e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -118,6 +118,7 @@ public class ReactEditText extends AppCompatEditText { private int mFontWeight = ReactConstants.UNSET; private int mFontStyle = ReactConstants.UNSET; private boolean mAutoFocus = false; + private boolean mContextMenuHidden = false; private boolean mDidAttachToWindow = false; private @Nullable String mPlaceholder = null; @@ -191,6 +192,9 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) { */ @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { + if (mContextMenuHidden) { + return false; + } menu.removeItem(android.R.id.pasteAsPlainText); return true; } @@ -1121,6 +1125,10 @@ public void setAutoFocus(boolean autoFocus) { mAutoFocus = autoFocus; } + public void setContextMenuHidden(boolean contextMenuHidden) { + mContextMenuHidden = contextMenuHidden; + } + protected void applyTextAttributes() { // In general, the `getEffective*` functions return `Float.NaN` if the // property hasn't been set. diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 2c225da1554890..a0e92290e417c6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -651,14 +651,7 @@ && shouldHideCursorForEmailTextInput()) { @ReactProp(name = "contextMenuHidden", defaultBoolean = false) public void setContextMenuHidden(ReactEditText view, boolean contextMenuHidden) { - final boolean _contextMenuHidden = contextMenuHidden; - view.setOnLongClickListener( - new View.OnLongClickListener() { - public boolean onLongClick(View v) { - return _contextMenuHidden; - } - ; - }); + view.setContextMenuHidden(contextMenuHidden); } @ReactProp(name = "selectTextOnFocus", defaultBoolean = false) From 8a6b88eeafef4eb63ee537c4ce71f9928f81a766 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 20 Jun 2024 11:06:46 -0700 Subject: [PATCH 049/968] Back out "Add Float and Int type support for Android modules" (#45087) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45087 Original commit changeset: 32b3bbdf5fd2 Fixes https://github.com/facebook/react-native/issues/44963 Closes https://github.com/facebook/react-native/pull/45024 Original Phabricator Diff: D52420921 Changelog: [Internal] [Changed] - Back out "[RN][Codegen]Add Float and Int type support for Android modules" Reviewed By: dmytrorykun Differential Revision: D58820544 fbshipit-source-id: 59cd0e7cc17a681785c57b5ce1a9d50d28a348af --- .../src/generators/modules/GenerateModuleJavaSpec.js | 4 ++-- .../src/generators/modules/GenerateModuleJniCpp.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js index efbf63c97335bf..ee3237d5d8c0cf 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js @@ -136,11 +136,11 @@ function translateFunctionParamToJavaType( case 'NumberTypeAnnotation': return wrapOptional('double', isRequired); case 'FloatTypeAnnotation': - return wrapOptional('float', isRequired); + return wrapOptional('double', isRequired); case 'DoubleTypeAnnotation': return wrapOptional('double', isRequired); case 'Int32TypeAnnotation': - return wrapOptional('int', isRequired); + return wrapOptional('double', isRequired); case 'BooleanTypeAnnotation': return wrapOptional('boolean', isRequired); case 'EnumDeclaration': diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js index eb2cf1ca133517..2930ab1be9a0be 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js @@ -334,9 +334,9 @@ function translateReturnTypeToJniType( case 'DoubleTypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': - return nullable ? 'Ljava/lang/Float;' : 'F'; + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': - return nullable ? 'Ljava/lang/Integer;' : 'I'; + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'PromiseTypeAnnotation': return 'Lcom/facebook/react/bridge/Promise;'; case 'GenericObjectTypeAnnotation': From 2eaf0b0848d660eb19fde2921570f9e8bd2bd1de Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Thu, 20 Jun 2024 11:09:15 -0700 Subject: [PATCH 050/968] Add an overload for `createLayout` to reduce code duplication (#45083) Summary: Adds an overload for `createLayout` method that also handles extracting paragraph attributes and scaling font size if necessary. ## Changelog: [ANDROID] [CHANGED] - Extracted common parts related to calculating text layout to a helper Pull Request resolved: https://github.com/facebook/react-native/pull/45083 Test Plan: Tried out on RNTester Reviewed By: robhogan Differential Revision: D58818560 Pulled By: cortinico fbshipit-source-id: a42b5de04c4a70edb88cdd734387d7e4cee94032 --- .../ReactAndroid/api/ReactAndroid.api | 1 + .../react/views/text/TextLayoutManager.java | 178 ++++++++---------- 2 files changed, 75 insertions(+), 104 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 5140979d64d2e5..1b209ef24d3e93 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -7628,6 +7628,7 @@ public class com/facebook/react/views/text/TextLayoutManager { public static final field PA_KEY_TEXT_BREAK_STRATEGY S public fun ()V public static fun adjustSpannableFontToFit (Landroid/text/Spannable;FLcom/facebook/yoga/YogaMeasureMode;FLcom/facebook/yoga/YogaMeasureMode;DIZIILandroid/text/Layout$Alignment;)V + public static fun createLayout (Landroid/content/Context;Lcom/facebook/react/common/mapbuffer/MapBuffer;Lcom/facebook/react/common/mapbuffer/MapBuffer;FFLcom/facebook/react/views/text/ReactTextViewManagerCallback;)Landroid/text/Layout; public static fun deleteCachedSpannableForTag (I)V public static fun getOrCreateSpannableForText (Landroid/content/Context;Lcom/facebook/react/common/mapbuffer/MapBuffer;Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)Landroid/text/Spannable; public static fun getTextAlignment (Lcom/facebook/react/common/mapbuffer/MapBuffer;Landroid/text/Spannable;)Landroid/text/Layout$Alignment; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java index 2921f84140d1d4..4857780a3a212f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java @@ -422,6 +422,69 @@ private static Layout createLayout( return layout; } + public static Layout createLayout( + @NonNull Context context, + MapBuffer attributedString, + MapBuffer paragraphAttributes, + float width, + float height, + ReactTextViewManagerCallback reactTextViewManagerCallback) { + Spannable text = + getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback); + BoringLayout.Metrics boring = BoringLayout.isBoring(text, sTextPaintInstance); + + int textBreakStrategy = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(PA_KEY_TEXT_BREAK_STRATEGY)); + boolean includeFontPadding = + paragraphAttributes.contains(PA_KEY_INCLUDE_FONT_PADDING) + ? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING) + : DEFAULT_INCLUDE_FONT_PADDING; + int hyphenationFrequency = + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY)); + boolean adjustFontSizeToFit = + paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) + ? paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) + : DEFAULT_ADJUST_FONT_SIZE_TO_FIT; + int maximumNumberOfLines = + paragraphAttributes.contains(PA_KEY_MAX_NUMBER_OF_LINES) + ? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES) + : ReactConstants.UNSET; + + Layout.Alignment alignment = getTextAlignment(attributedString, text); + + if (adjustFontSizeToFit) { + double minimumFontSize = + paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE) + ? paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE) + : Double.NaN; + + adjustSpannableFontToFit( + text, + width, + YogaMeasureMode.EXACTLY, + height, + YogaMeasureMode.UNDEFINED, + minimumFontSize, + maximumNumberOfLines, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency, + alignment); + } + + return createLayout( + text, + boring, + width, + YogaMeasureMode.EXACTLY, + includeFontPadding, + textBreakStrategy, + hyphenationFrequency, + alignment); + } + public static void adjustSpannableFontToFit( Spannable text, float width, @@ -505,66 +568,25 @@ public static long measureText( @Nullable float[] attachmentsPositions) { // TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic) - Spannable text = - getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback); + Layout layout = + createLayout( + context, + attributedString, + paragraphAttributes, + width, + height, + reactTextViewManagerCallback); + Spannable text = (Spannable) layout.getText(); if (text == null) { return 0; } - int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy( - paragraphAttributes.getString(PA_KEY_TEXT_BREAK_STRATEGY)); - boolean includeFontPadding = - paragraphAttributes.contains(PA_KEY_INCLUDE_FONT_PADDING) - ? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING) - : DEFAULT_INCLUDE_FONT_PADDING; - int hyphenationFrequency = - TextAttributeProps.getHyphenationFrequency( - paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY)); - boolean adjustFontSizeToFit = - paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) - ? paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) - : DEFAULT_ADJUST_FONT_SIZE_TO_FIT; int maximumNumberOfLines = paragraphAttributes.contains(PA_KEY_MAX_NUMBER_OF_LINES) ? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES) : ReactConstants.UNSET; - Layout.Alignment alignment = getTextAlignment(attributedString, text); - - if (adjustFontSizeToFit) { - double minimumFontSize = - paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE) - ? paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE) - : Double.NaN; - - adjustSpannableFontToFit( - text, - width, - widthYogaMeasureMode, - height, - heightYogaMeasureMode, - minimumFontSize, - maximumNumberOfLines, - includeFontPadding, - textBreakStrategy, - hyphenationFrequency, - alignment); - } - - BoringLayout.Metrics boring = BoringLayout.isBoring(text, sTextPaintInstance); - Layout layout = - createLayout( - text, - boring, - width, - widthYogaMeasureMode, - includeFontPadding, - textBreakStrategy, - hyphenationFrequency, - alignment); - int calculatedLineCount = maximumNumberOfLines == ReactConstants.UNSET || maximumNumberOfLines == 0 ? layout.getLineCount() @@ -718,60 +740,8 @@ public static WritableArray measureLines( float width, float height) { - Spannable text = getOrCreateSpannableForText(context, attributedString, null); - BoringLayout.Metrics boring = BoringLayout.isBoring(text, sTextPaintInstance); - - int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy( - paragraphAttributes.getString(PA_KEY_TEXT_BREAK_STRATEGY)); - boolean includeFontPadding = - paragraphAttributes.contains(PA_KEY_INCLUDE_FONT_PADDING) - ? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING) - : DEFAULT_INCLUDE_FONT_PADDING; - int hyphenationFrequency = - TextAttributeProps.getTextBreakStrategy( - paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY)); - boolean adjustFontSizeToFit = - paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) - ? paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT) - : DEFAULT_ADJUST_FONT_SIZE_TO_FIT; - int maximumNumberOfLines = - paragraphAttributes.contains(PA_KEY_MAX_NUMBER_OF_LINES) - ? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES) - : ReactConstants.UNSET; - - Layout.Alignment alignment = getTextAlignment(attributedString, text); - - if (adjustFontSizeToFit) { - double minimumFontSize = - paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE) - ? paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE) - : Double.NaN; - - adjustSpannableFontToFit( - text, - width, - YogaMeasureMode.EXACTLY, - height, - YogaMeasureMode.UNDEFINED, - minimumFontSize, - maximumNumberOfLines, - includeFontPadding, - textBreakStrategy, - hyphenationFrequency, - alignment); - } - Layout layout = - createLayout( - text, - boring, - width, - YogaMeasureMode.EXACTLY, - includeFontPadding, - textBreakStrategy, - hyphenationFrequency, - alignment); - return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context); + createLayout(context, attributedString, paragraphAttributes, width, height, null); + return FontMetricsUtil.getFontMetrics(layout.getText(), layout, sTextPaintInstance, context); } } From 3dcf86b8022090e766c93aed062e4d1d849299a1 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Thu, 20 Jun 2024 11:48:18 -0700 Subject: [PATCH 051/968] Update @react-native-community/cli to 14.0.0-alpha.7 (#45086) Summary: RN CLI to 14.0.0-alpha.7 ## Changelog: [General][Changed] RN CLI to 14.0.0-alpha.7 Pull Request resolved: https://github.com/facebook/react-native/pull/45086 Test Plan: ``` yarn ``` Reviewed By: cortinico Differential Revision: D58819145 Pulled By: blakef fbshipit-source-id: 025f190908c52afd3f1055a665986fea4785e192 --- packages/react-native/package.json | 6 +- yarn.lock | 165 ++++++++++++++++++++--------- 2 files changed, 116 insertions(+), 55 deletions(-) diff --git a/packages/react-native/package.json b/packages/react-native/package.json index e9824d707a8396..e6dacc724d320f 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -109,9 +109,9 @@ }, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "14.0.0-alpha.2", - "@react-native-community/cli-platform-android": "14.0.0-alpha.2", - "@react-native-community/cli-platform-ios": "14.0.0-alpha.2", + "@react-native-community/cli": "14.0.0-alpha.7", + "@react-native-community/cli-platform-android": "14.0.0-alpha.7", + "@react-native-community/cli-platform-ios": "14.0.0-alpha.7", "@react-native/assets-registry": "0.75.0-main", "@react-native/codegen": "0.75.0-main", "@react-native/community-cli-plugin": "0.75.0-main", diff --git a/yarn.lock b/yarn.lock index 80a2ceeda3d984..3711f40e3c7ac2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2615,24 +2615,24 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" -"@react-native-community/cli-clean@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.2.tgz#f87f1e313652360ad78b3008f91476af9d95e365" - integrity sha512-QZ8BcrPL+/tWPCk8QH6Z8HMX3gGCLibmJeDdJrCvq/Td/1QSftxxLGLbXowUw4ElukJA9Jkxpc6FyB79E3fDUw== +"@react-native-community/cli-clean@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.7.tgz#94b35e06d20a81b804f7510bb58ff2afee6abb4e" + integrity sha512-p7JHg6UbDfpoFdxYIHqjds9pwPSnBeNDNOanT6/IPdz8lCXhFkAnQOcqcoltxA9LOmb6G2d5GYg2aiKa1uZGPQ== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.2" + "@react-native-community/cli-tools" "14.0.0-alpha.7" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" -"@react-native-community/cli-config@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.2.tgz#392b0e7d768842b57ec594cb3995f3d4f6fbabe8" - integrity sha512-UTSkQ9rEQ3WK114Q9zy4XipxPpiAT+Ehgc1bx1HRw8ib4yWD/r53JV40o4OCC2GjWKgj600Lk0PMolCsaGamXA== +"@react-native-community/cli-config@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.7.tgz#3db66b6f6ccd2500b0c5ca28e9378a28e452a2b7" + integrity sha512-rfwU7fnnWN0RcJPny3/n0jlqf1xIWW2wc33MjyCmztZtJs5ow3ivEudi81PucQmWleIdk77H35Xp06um1nJjOg== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.2" + "@react-native-community/cli-tools" "14.0.0-alpha.7" chalk "^4.1.2" - cosmiconfig "^5.1.0" + cosmiconfig "^9.0.0" deepmerge "^4.3.0" fast-glob "^3.3.2" joi "^17.2.1" @@ -2656,16 +2656,23 @@ dependencies: serve-static "^1.13.1" -"@react-native-community/cli-doctor@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.2.tgz#0a3e5b7512b930a079e9dacae2cc77073b111f95" - integrity sha512-qxHiOQX0mKYq5zTJgkBluyYXUH932zauyB4oYEx4pbYMMdITfDskjNIqvXFZDIba3mfv1dsknL+7x05wwZOPtA== +"@react-native-community/cli-debugger-ui@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.0.0-alpha.7.tgz#79ce17779c14b8454e081d165e900ebf992a9cce" + integrity sha512-PegGpU9XVpBOSJ21aFtSdpAfxgl3tlCuwWBoNSV9UgeyWtbvVyVNDHI4YdAL7hymH1zWRcUsP1uIVQ3/kmooeg== dependencies: - "@react-native-community/cli-config" "14.0.0-alpha.2" - "@react-native-community/cli-platform-android" "14.0.0-alpha.2" - "@react-native-community/cli-platform-apple" "14.0.0-alpha.2" - "@react-native-community/cli-platform-ios" "14.0.0-alpha.2" - "@react-native-community/cli-tools" "14.0.0-alpha.2" + serve-static "^1.13.1" + +"@react-native-community/cli-doctor@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.7.tgz#186eb62d0ea779539c10fcb002f8444b4ebf2f2e" + integrity sha512-tS7it/541M0ArDJOmrfyMfqpn9Ei7rJGge9ctc0JdwTVpZJZAL96ZMROzFsIj7TaEyFMmFmeV2v1bTAyWLjIwA== + dependencies: + "@react-native-community/cli-config" "14.0.0-alpha.7" + "@react-native-community/cli-platform-android" "14.0.0-alpha.7" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.7" + "@react-native-community/cli-platform-ios" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.7" chalk "^4.1.2" command-exists "^1.2.8" deepmerge "^4.3.0" @@ -2678,28 +2685,28 @@ wcwidth "^1.0.1" yaml "^2.2.1" -"@react-native-community/cli-platform-android@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.2.tgz#a2ce4de0f3003db3cf34fcdbf384f701ae1dc16d" - integrity sha512-gQoP3WdjzpwGv81kypx2dcu3Cdz4vRuYubEUdfiTe/KV416cFsRAYnhx6L1LFrO36SoRKODwHaYTfo14ZpFp5Q== +"@react-native-community/cli-platform-android@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.7.tgz#47049f804c9ac5f347a99088ac9ca7be3fade63e" + integrity sha512-db1lHAjlzbm5V3okfKCiuHTNgsVsBVdWG7wvAvHmCGY8esNQrjIpGHsVuvOFmCGvuKk3NkwJ6qTxbV1RWWnBYw== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.2" + "@react-native-community/cli-tools" "14.0.0-alpha.7" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" fast-xml-parser "^4.2.4" logkitty "^0.7.1" -"@react-native-community/cli-platform-apple@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.2.tgz#feaa2770005dd08b6bff380c623ec177a65d2a65" - integrity sha512-IYdkvodYOKRmK2AuN7tHhisrwVGabI5UW0NABbk4X/ANh/ds27kbhLR/Jc4wC4QeuYtdIiHmv8gxIXbB2p5eWw== +"@react-native-community/cli-platform-apple@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.7.tgz#13dd14ecaa39fd90872c8f7c5af9c583dd6c3af0" + integrity sha512-eOmgrJoPpz2RN1L2fOo9C1reiZ+aPNS5+oUepT/SeFRT/ybmVgXTKnPKjcJ0MXErgay485esLqZrWR609m8VMA== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.2" + "@react-native-community/cli-tools" "14.0.0-alpha.7" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" - fast-xml-parser "^4.0.12" + fast-xml-parser "^4.2.4" ora "^5.4.1" "@react-native-community/cli-platform-apple@^13.6.4": @@ -2714,12 +2721,12 @@ fast-xml-parser "^4.0.12" ora "^5.4.1" -"@react-native-community/cli-platform-ios@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.2.tgz#6651691421d57d4230ee8d0dcd309af94a8303a7" - integrity sha512-QugzljDvIQ1UZ8EvaJJ6PyGEMKcRsIGa2afwwKAwexQyGOWxPaN5vAwl1OwNpl+AmnbR4RiAqctUBXm8HhxghA== +"@react-native-community/cli-platform-ios@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.7.tgz#d666c19b37f5c79b71bb00ecd63c4740a25badae" + integrity sha512-mgHGqJcHegwNE4dSyoP2g5Oc8jxeeSUKql6WTsUNfhQKKdF1Cmtms5xaupbWqEjewf9oMfYqL7shSjAgMsDq6Q== dependencies: - "@react-native-community/cli-platform-apple" "14.0.0-alpha.2" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.7" "@react-native-community/cli-server-api@14.0.0-alpha.2": version "14.0.0-alpha.2" @@ -2736,6 +2743,21 @@ serve-static "^1.13.1" ws "^7.5.1" +"@react-native-community/cli-server-api@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.7.tgz#0d61005dde4c81a0d1f16ab850b76a130f688a95" + integrity sha512-4N5lAebocJmGH3b2yQBHeKiD0Th4XEa3h0vIMWN0TTu+af/z5k4jB2szzzulHnER5lyvChCkYm+ZO1amAKmc9g== + dependencies: + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.7" + compression "^1.7.1" + connect "^3.6.5" + errorhandler "^1.5.1" + nocache "^3.0.1" + pretty-format "^26.6.2" + serve-static "^1.13.1" + ws "^6.2.2" + "@react-native-community/cli-tools@13.6.4", "@react-native-community/cli-tools@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-13.6.4.tgz#ab396604b6dcf215790807fe89656e779b11f0ec" @@ -2770,10 +2792,26 @@ shell-quote "^1.7.3" sudo-prompt "^9.0.0" -"@react-native-community/cli-types@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.2.tgz#6ebb5d088350901ed6d9870ab9b1e75dd7609ca9" - integrity sha512-aG6HvmhnmMU5kNnSxLtajX8b75hE2Y0bzJLhVX6eqR+nUhqCcwKvGxiHSIU93K3aPRnp1sXMo8owaBVBDESGYQ== +"@react-native-community/cli-tools@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-14.0.0-alpha.7.tgz#680c63d3cdac4f2cd2a834a34eaeac48d64c08d8" + integrity sha512-fiLcyZEtY9bB3DQ7Y3FBbJaKQkHmT3yhaagtg1kOaaWyW9NcELMrXhVSHTO+kC8L7XvHEfC0EAfA6N5JWDNfwQ== + dependencies: + appdirsjs "^1.2.4" + chalk "^4.1.2" + execa "^5.0.0" + find-up "^5.0.0" + mime "^2.4.1" + open "^6.2.0" + ora "^5.4.1" + semver "^7.5.2" + shell-quote "^1.7.3" + sudo-prompt "^9.0.0" + +"@react-native-community/cli-types@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.7.tgz#7e9ee2c478d7572f06e7aabc3f0688c869c61c1e" + integrity sha512-B/lyk7x2RRjWISbGbORCj+9Fub4Is1rk2b8dHm6ccML0kH6rj+H6afMXNwV9371+slSB+MeRpqCR5CBcag2Etw== dependencies: joi "^17.2.1" @@ -2784,18 +2822,18 @@ dependencies: joi "^17.2.1" -"@react-native-community/cli@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.2.tgz#39ca31ebe0ff615398012bacdd3de710229707a1" - integrity sha512-7y+G2wGHue8leoKSE1MvhGH4CqfSgTc3JWl9MMBeEVBNW7kwS+CGQEUziGZBVea/EVU4t0OEHIJOMK516rYl3A== - dependencies: - "@react-native-community/cli-clean" "14.0.0-alpha.2" - "@react-native-community/cli-config" "14.0.0-alpha.2" - "@react-native-community/cli-debugger-ui" "14.0.0-alpha.2" - "@react-native-community/cli-doctor" "14.0.0-alpha.2" - "@react-native-community/cli-server-api" "14.0.0-alpha.2" - "@react-native-community/cli-tools" "14.0.0-alpha.2" - "@react-native-community/cli-types" "14.0.0-alpha.2" +"@react-native-community/cli@14.0.0-alpha.7": + version "14.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.7.tgz#5495ca20c9ef0c94639eef21322bbc846f81f1a3" + integrity sha512-DrdyBhdM6lCYqljDs18mWLuyta2CdeaJkdJAVomkfAme+TldTCiLp34XwsXhYAVWNQXrv+W17bQ+PmurXu0s9w== + dependencies: + "@react-native-community/cli-clean" "14.0.0-alpha.7" + "@react-native-community/cli-config" "14.0.0-alpha.7" + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.7" + "@react-native-community/cli-doctor" "14.0.0-alpha.7" + "@react-native-community/cli-server-api" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-types" "14.0.0-alpha.7" chalk "^4.1.2" commander "^9.4.1" deepmerge "^4.3.0" @@ -4369,6 +4407,16 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: js-yaml "^3.13.0" parse-json "^4.0.0" +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4652,6 +4700,11 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + envinfo@^7.10.0: version "7.11.0" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f" @@ -5874,6 +5927,14 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" From 3429dc1ccf32b6b23f4f0ad3cfdf0d5697af665f Mon Sep 17 00:00:00 2001 From: psionic12 Date: Thu, 20 Jun 2024 13:16:32 -0700 Subject: [PATCH 052/968] Log a SoftException on SurfaceMountingManager.addRootView (#34785) Summary: Follow the same solution (do not throw a crash when view ID is set already) used in `ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java` for `ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java` ## Changelog [Android] [Changed] - Log a SoftException on SurfaceMountingManager.addRootView Pull Request resolved: https://github.com/facebook/react-native/pull/34785 Test Plan: None Reviewed By: cipolleschi Differential Revision: D40022263 Pulled By: cortinico fbshipit-source-id: d565d2831e2833ccea55f28ea16083b7bae0ed32 --- .../mounting/SurfaceMountingManager.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java index 63b79a4d2228aa..754bc894574712 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java @@ -211,11 +211,22 @@ private void addRootView(@NonNull final View rootView) { + " tag: [%d]", rootView.getId(), mSurfaceId); - throw new IllegalViewOperationException( - "Trying to add a root view with an explicit id already set. React Native uses the" - + " id field to track react tags and will overwrite this field. If that is" - + " fine, explicitly overwrite the id field to View.NO_ID before calling" - + " addRootView."); + // This behavior can not be guaranteed in hybrid apps that have a native android layer + // over + // which reactRootViews are added and the native views need to have ids on them in order + // to + // work. + // Hence this can cause unnecessary crashes at runtime for hybrid apps. + // So converting this to a soft exception such that pure react-native devs can still see + // the + // warning while hybrid apps continue to run without crashes + ReactSoftExceptionLogger.logSoftException( + TAG, + new IllegalViewOperationException( + "Trying to add a root view with an explicit id already set. React Native uses" + + " the id field to track react tags and will overwrite this field. If that" + + " is fine, explicitly overwrite the id field to View.NO_ID before calling" + + " addRootView.")); } rootView.setId(mSurfaceId); From 15909fab9532f7dc32c320ebc98fa3b67679b79e Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 21 Jun 2024 01:08:00 -0700 Subject: [PATCH 053/968] packages/react-native-gradle-plugin/ -> packages/gradle-plugin/ (#44832) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44832 I'm renaming this folder as now we have 2 gradle plugins + we currently have `package/react-native-gradle-plugin/react-native-gradle-plugin/` which is confusing so we can just call this folder `packages/gradle-plugin/` to be consistent with the NPM package name Changelog: [Internal] [Changed] - packages/react-native-gradle-plugin/ -> packages/gradle-plugin/ Reviewed By: blakef Differential Revision: D58284883 fbshipit-source-id: 5a7bb40a5d80f6fbab4ffb29e44107453f1013ec --- .circleci/configurations/jobs.yml | 11 +++++++---- .github/workflows/nightly.yml | 5 +++-- .github/workflows/publish-release.yml | 4 ++-- .github/workflows/test-all.yml | 4 ++-- build.gradle.kts | 4 ++-- .../.gitignore | 2 +- .../README.md | 2 +- .../build.gradle.kts | 0 .../gradle.properties | 0 .../gradle/libs.versions.toml | 0 .../gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 .../gradlew | 0 .../gradlew.bat | 5 +++++ .../package.json | 4 ++-- .../react-native-gradle-plugin/README.md | 0 .../react-native-gradle-plugin/build.gradle.kts | 0 .../kotlin/com/facebook/react/ReactExtension.kt | 0 .../main/kotlin/com/facebook/react/ReactPlugin.kt | 0 .../com/facebook/react/ReactRootProjectPlugin.kt | 0 .../kotlin/com/facebook/react/TaskConfiguration.kt | 0 .../react/internal/PrivateReactExtension.kt | 0 .../com/facebook/react/tasks/BundleHermesCTask.kt | 0 .../GenerateAutolinkingNewArchitecturesFileTask.kt | 0 .../react/tasks/GenerateCodegenArtifactsTask.kt | 0 .../react/tasks/GenerateCodegenSchemaTask.kt | 0 .../facebook/react/tasks/GeneratePackageListTask.kt | 0 .../react/tasks/internal/BuildCodegenCLITask.kt | 0 .../react/tasks/internal/PrepareBoostTask.kt | 0 .../react/tasks/internal/PrepareGlogTask.kt | 0 .../facebook/react/tasks/internal/PrepareJSCTask.kt | 0 .../tasks/internal/PreparePrefabHeadersTask.kt | 0 .../internal/utils/PrefabPreprocessingEntry.kt | 0 .../facebook/react/utils/AgpConfiguratorUtils.kt | 0 .../com/facebook/react/utils/BackwardCompatUtils.kt | 0 .../com/facebook/react/utils/DependencyUtils.kt | 0 .../kotlin/com/facebook/react/utils/FileUtils.kt | 0 .../facebook/react/utils/JdkConfiguratorUtils.kt | 0 .../facebook/react/utils/KotlinStdlibCompatUtils.kt | 0 .../facebook/react/utils/NdkConfiguratorUtils.kt | 0 .../src/main/kotlin/com/facebook/react/utils/Os.kt | 0 .../kotlin/com/facebook/react/utils/PathUtils.kt | 0 .../kotlin/com/facebook/react/utils/ProjectUtils.kt | 0 .../com/facebook/react/utils/PropertyUtils.kt | 0 .../kotlin/com/facebook/react/utils/TaskUtils.kt | 0 .../kotlin/com/facebook/react/ReactExtensionTest.kt | 0 .../kotlin/com/facebook/react/TestReactExtension.kt | 0 .../model/ModelAutolinkingDependenciesJsonTest.kt | 0 .../facebook/react/tasks/BundleHermesCTaskTest.kt | 0 ...nerateAutolinkingNewArchitecturesFileTaskTest.kt | 0 .../react/tasks/GenerateCodegenArtifactsTaskTest.kt | 0 .../react/tasks/GenerateCodegenSchemaTaskTest.kt | 0 .../react/tasks/GeneratePackageListTaskTest.kt | 0 .../react/tasks/internal/BuildCodegenCLITaskTest.kt | 0 .../react/tasks/internal/PrepareBoostTaskTest.kt | 0 .../react/tasks/internal/PrepareGlogTaskTest.kt | 0 .../react/tasks/internal/PrepareJSCTaskTest.kt | 0 .../tasks/internal/PreparePrefabHeadersTaskTest.kt | 0 .../internal/utils/PrefabPreprocessingEntryTest.kt | 0 .../test/kotlin/com/facebook/react/tests/OsRule.kt | 0 .../com/facebook/react/tests/TaskTestUtils.kt | 0 .../test/kotlin/com/facebook/react/tests/WithOs.kt | 0 .../react/utils/AgpConfiguratorUtilsTest.kt | 0 .../facebook/react/utils/BackwardCompatUtilsTest.kt | 0 .../com/facebook/react/utils/DependencyUtilsTest.kt | 0 .../com/facebook/react/utils/FileUtilsTest.kt | 0 .../react/utils/KotlinStdlibCompatUtilsTest.kt | 0 .../react/utils/NdkConfiguratorUtilsTest.kt | 0 .../test/kotlin/com/facebook/react/utils/OsTest.kt | 0 .../com/facebook/react/utils/PathUtilsTest.kt | 0 .../com/facebook/react/utils/ProjectUtilsTest.kt | 0 .../com/facebook/react/utils/TaskUtilsTest.kt | 0 .../settings-plugin/build.gradle.kts | 0 .../com/facebook/react/ReactSettingsExtension.kt | 0 .../com/facebook/react/ReactSettingsPlugin.kt | 0 .../facebook/react/ReactSettingsExtensionTest.kt | 0 .../settings.gradle.kts | 2 +- .../shared/build.gradle.kts | 0 .../model/ModelAutolinkingAndroidProjectJson.kt | 0 .../react/model/ModelAutolinkingConfigJson.kt | 0 .../react/model/ModelAutolinkingDependenciesJson.kt | 0 ...delAutolinkingDependenciesPlatformAndroidJson.kt | 0 .../ModelAutolinkingDependenciesPlatformJson.kt | 0 .../react/model/ModelAutolinkingProjectJson.kt | 0 .../com/facebook/react/model/ModelCodegenConfig.kt | 0 .../react/model/ModelCodegenConfigAndroid.kt | 0 .../com/facebook/react/model/ModelPackageJson.kt | 0 .../kotlin/com/facebook/react/utils/JsonUtils.kt | 0 .../com/facebook/react/utils/JsonUtilsTest.kt | 0 packages/helloworld/android/settings.gradle | 4 ++-- settings.gradle.kts | 4 ++-- 91 files changed, 30 insertions(+), 21 deletions(-) rename packages/{react-native-gradle-plugin => gradle-plugin}/.gitignore (56%) rename packages/{react-native-gradle-plugin => gradle-plugin}/README.md (92%) rename packages/{react-native-gradle-plugin => gradle-plugin}/build.gradle.kts (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/gradle.properties (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/gradle/libs.versions.toml (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/gradle/wrapper/gradle-wrapper.jar (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/gradle/wrapper/gradle-wrapper.properties (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/gradlew (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/gradlew.bat (90%) rename packages/{react-native-gradle-plugin => gradle-plugin}/package.json (88%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/README.md (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/build.gradle.kts (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GeneratePackageListTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/FileUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/ReactExtensionTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/TestReactExtension.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJsonTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GeneratePackageListTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareBoostTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareGlogTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareJSCTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTaskTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntryTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/OsRule.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/TaskTestUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/WithOs.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/AgpConfiguratorUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/FileUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/settings-plugin/build.gradle.kts (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsPlugin.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/settings.gradle.kts (91%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/build.gradle.kts (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingAndroidProjectJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingConfigJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformAndroidJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingProjectJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt (100%) rename packages/{react-native-gradle-plugin => gradle-plugin}/shared/src/test/kotlin/com/facebook/react/utils/JsonUtilsTest.kt (100%) diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml index 3a1e0da816f2d7..328e5e8bb89f11 100644 --- a/.circleci/configurations/jobs.yml +++ b/.circleci/configurations/jobs.yml @@ -151,8 +151,10 @@ jobs: - packages/react-native/ReactAndroid/hermes-engine/.cxx/ - packages/react-native/ReactAndroid/hermes-engine/build/ - packages/react-native/ReactAndroid/src/main/jni/prebuilt/ - - packages/react-native-gradle-plugin/.gradle/ - - packages/react-native-gradle-plugin/build/ + - packages/gradle-plugin/.gradle/ + - packages/gradle-plugin/react-native-gradle-plugin/build/ + - packages/gradle-plugin/settings-plugin/build/ + - packages/gradle-plugin/shared/build/ - packages/react-native-codegen/lib/ # ------------------------- @@ -181,8 +183,9 @@ jobs: platform: android - store_test_results: - path: ~/react-native/packages/react-native-gradle-plugin/build/test-results - + path: ~/react-native/packages/gradle-plugin/react-native-gradle-plugin/build/test-results + - store_test_results: + path: ~/react-native/packages/gradle-plugin/settings-plugin/build/test-results - store_test_results: path: ~/react-native/packages/react-native/ReactAndroid/build/test-results diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8ea77bb12431de..110257858d87c0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -493,8 +493,8 @@ jobs: name: build-android-results compression-level: 1 path: | - packages/react-native-gradle-plugin/react-native-gradle-plugin/build/reports - packages/react-native-gradle-plugin/settings-plugin/build/reports + packages/gradle-plugin/settings-plugin/build/reports + packages/gradle-plugin/react-native-gradle-plugin/build/reports packages/react-native/ReactAndroid/build/reports - name: Upload RNTester APK if: ${{ always() }} @@ -503,6 +503,7 @@ jobs: name: rntester-apk path: packages/rn-tester/android/app/build/outputs/apk/ compression-level: 0 + build_npm_package: runs-on: 8-core-ubuntu needs: [set_release_type, prepare_hermes_workspace, build_hermes_macos, build_hermesc_linux, build_hermesc_windows,build_android] diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index fc3c5c8b8ddeb1..874ee9ae54c4e7 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -492,8 +492,8 @@ jobs: name: build-android-results compression-level: 1 path: | - packages/react-native-gradle-plugin/react-native-gradle-plugin/build/reports - packages/react-native-gradle-plugin/settings-plugin/build/reports + packages/gradle-plugin/react-native-gradle-plugin/build/reports + packages/gradle-plugin/settings-plugin/build/reports packages/react-native/ReactAndroid/build/reports - name: Upload RNTester APK if: ${{ always() }} diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 46d0d8b7858bef..ee458b5c8d4bfd 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -565,8 +565,8 @@ jobs: name: build-android-results compression-level: 1 path: | - packages/react-native-gradle-plugin/react-native-gradle-plugin/build/reports - packages/react-native-gradle-plugin/settings-plugin/build/reports + packages/gradle-plugin/react-native-gradle-plugin/build/reports + packages/gradle-plugin/settings-plugin/build/reports packages/react-native/ReactAndroid/build/reports - name: Upload RNTester APK if: ${{ always() }} diff --git a/build.gradle.kts b/build.gradle.kts index e24bf6467328f4..b967428d10206c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -60,7 +60,7 @@ nexusPublishing { tasks.register("clean", Delete::class.java) { description = "Remove all the build files and intermediate build outputs" - dependsOn(gradle.includedBuild("react-native-gradle-plugin").task(":clean")) + dependsOn(gradle.includedBuild("gradle-plugin").task(":clean")) subprojects.forEach { if (it.project.plugins.hasPlugin("com.android.library") || it.project.plugins.hasPlugin("com.android.application")) { @@ -86,7 +86,7 @@ tasks.register("clean", Delete::class.java) { tasks.register("build") { description = "Build and test all the React Native relevant projects." - dependsOn(gradle.includedBuild("react-native-gradle-plugin").task(":build")) + dependsOn(gradle.includedBuild("gradle-plugin").task(":build")) } tasks.register("publishAllToMavenTempLocal") { diff --git a/packages/react-native-gradle-plugin/.gitignore b/packages/gradle-plugin/.gitignore similarity index 56% rename from packages/react-native-gradle-plugin/.gitignore rename to packages/gradle-plugin/.gitignore index 7b987dbf0c939a..ffd4ff5e1256e8 100644 --- a/packages/react-native-gradle-plugin/.gitignore +++ b/packages/gradle-plugin/.gitignore @@ -1,4 +1,4 @@ build/ -app-plugin/build/ +react-native-gradle-plugin/build/ settings-plugin/build/ shared/build/ diff --git a/packages/react-native-gradle-plugin/README.md b/packages/gradle-plugin/README.md similarity index 92% rename from packages/react-native-gradle-plugin/README.md rename to packages/gradle-plugin/README.md index 7233d33cbd3f6a..bb9f0a3a87b807 100644 --- a/packages/react-native-gradle-plugin/README.md +++ b/packages/gradle-plugin/README.md @@ -20,4 +20,4 @@ yarn add @react-native/gradle-plugin To run the tests in this package, run the following commands from the React Native root folder: 1. `yarn` to install the dependencies. You just need to run this once -2. `yarn jest packages/react-native-gradle-plugin`. +2. `./gradlew -p packages/gradle-plugin test`. diff --git a/packages/react-native-gradle-plugin/build.gradle.kts b/packages/gradle-plugin/build.gradle.kts similarity index 100% rename from packages/react-native-gradle-plugin/build.gradle.kts rename to packages/gradle-plugin/build.gradle.kts diff --git a/packages/react-native-gradle-plugin/gradle.properties b/packages/gradle-plugin/gradle.properties similarity index 100% rename from packages/react-native-gradle-plugin/gradle.properties rename to packages/gradle-plugin/gradle.properties diff --git a/packages/react-native-gradle-plugin/gradle/libs.versions.toml b/packages/gradle-plugin/gradle/libs.versions.toml similarity index 100% rename from packages/react-native-gradle-plugin/gradle/libs.versions.toml rename to packages/gradle-plugin/gradle/libs.versions.toml diff --git a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar b/packages/gradle-plugin/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.jar rename to packages/gradle-plugin/gradle/wrapper/gradle-wrapper.jar diff --git a/packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/packages/gradle-plugin/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from packages/react-native-gradle-plugin/gradle/wrapper/gradle-wrapper.properties rename to packages/gradle-plugin/gradle/wrapper/gradle-wrapper.properties diff --git a/packages/react-native-gradle-plugin/gradlew b/packages/gradle-plugin/gradlew similarity index 100% rename from packages/react-native-gradle-plugin/gradlew rename to packages/gradle-plugin/gradlew diff --git a/packages/react-native-gradle-plugin/gradlew.bat b/packages/gradle-plugin/gradlew.bat similarity index 90% rename from packages/react-native-gradle-plugin/gradlew.bat rename to packages/gradle-plugin/gradlew.bat index 7101f8e4676fca..f84fe1edba4cf4 100644 --- a/packages/react-native-gradle-plugin/gradlew.bat +++ b/packages/gradle-plugin/gradlew.bat @@ -1,3 +1,8 @@ +@REM Copyright (c) Meta Platforms, Inc. and affiliates. +@REM +@REM This source code is licensed under the MIT license found in the +@REM LICENSE file in the root directory of this source tree. + @rem @rem Copyright 2015 the original author or authors. @rem diff --git a/packages/react-native-gradle-plugin/package.json b/packages/gradle-plugin/package.json similarity index 88% rename from packages/react-native-gradle-plugin/package.json rename to packages/gradle-plugin/package.json index 81c6915f3f5376..99f3487c1d777a 100644 --- a/packages/react-native-gradle-plugin/package.json +++ b/packages/gradle-plugin/package.json @@ -6,9 +6,9 @@ "repository": { "type": "git", "url": "git+https://github.com/facebook/react-native.git", - "directory": "packages/react-native-gradle-plugin" + "directory": "packages/gradle-plugin" }, - "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin#readme", + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/gradle-plugin#readme", "keywords": [ "gradle", "plugin", diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/README.md b/packages/gradle-plugin/react-native-gradle-plugin/README.md similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/README.md rename to packages/gradle-plugin/react-native-gradle-plugin/README.md diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/build.gradle.kts b/packages/gradle-plugin/react-native-gradle-plugin/build.gradle.kts similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/build.gradle.kts rename to packages/gradle-plugin/react-native-gradle-plugin/build.gradle.kts diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactExtension.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactRootProjectPlugin.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/BundleHermesCTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GeneratePackageListTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GeneratePackageListTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GeneratePackageListTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/GeneratePackageListTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareBoostTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareGlogTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PrepareJSCTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTask.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntry.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/BackwardCompatUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/FileUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/FileUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/FileUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/FileUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/JdkConfiguratorUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/NdkConfiguratorUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/Os.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/TaskUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/ReactExtensionTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/ReactExtensionTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/ReactExtensionTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/ReactExtensionTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/TestReactExtension.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/TestReactExtension.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/TestReactExtension.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/TestReactExtension.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJsonTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJsonTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJsonTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJsonTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/BundleHermesCTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateAutolinkingNewArchitecturesFileTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenArtifactsTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GenerateCodegenSchemaTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GeneratePackageListTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GeneratePackageListTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GeneratePackageListTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/GeneratePackageListTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/BuildCodegenCLITaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareBoostTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareBoostTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareBoostTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareBoostTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareGlogTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareGlogTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareGlogTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareGlogTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareJSCTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareJSCTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareJSCTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PrepareJSCTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTaskTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTaskTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTaskTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/PreparePrefabHeadersTaskTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntryTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntryTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntryTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tasks/internal/utils/PrefabPreprocessingEntryTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/OsRule.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/OsRule.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/OsRule.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/OsRule.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/TaskTestUtils.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/TaskTestUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/TaskTestUtils.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/TaskTestUtils.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/WithOs.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/WithOs.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/WithOs.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/tests/WithOs.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/AgpConfiguratorUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/AgpConfiguratorUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/AgpConfiguratorUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/AgpConfiguratorUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/BackwardCompatUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/FileUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/FileUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/FileUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/FileUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/KotlinStdlibCompatUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/NdkConfiguratorUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/OsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt b/packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt rename to packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/TaskUtilsTest.kt diff --git a/packages/react-native-gradle-plugin/settings-plugin/build.gradle.kts b/packages/gradle-plugin/settings-plugin/build.gradle.kts similarity index 100% rename from packages/react-native-gradle-plugin/settings-plugin/build.gradle.kts rename to packages/gradle-plugin/settings-plugin/build.gradle.kts diff --git a/packages/react-native-gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt similarity index 100% rename from packages/react-native-gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt rename to packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt diff --git a/packages/react-native-gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsPlugin.kt b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsPlugin.kt similarity index 100% rename from packages/react-native-gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsPlugin.kt rename to packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsPlugin.kt diff --git a/packages/react-native-gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt b/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt rename to packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt diff --git a/packages/react-native-gradle-plugin/settings.gradle.kts b/packages/gradle-plugin/settings.gradle.kts similarity index 91% rename from packages/react-native-gradle-plugin/settings.gradle.kts rename to packages/gradle-plugin/settings.gradle.kts index f342618821e50c..bce34ba3a8b82a 100644 --- a/packages/react-native-gradle-plugin/settings.gradle.kts +++ b/packages/gradle-plugin/settings.gradle.kts @@ -21,4 +21,4 @@ include( ":shared", ) -rootProject.name = "gradle-plugins-root" +rootProject.name = "gradle-plugin-root" diff --git a/packages/react-native-gradle-plugin/shared/build.gradle.kts b/packages/gradle-plugin/shared/build.gradle.kts similarity index 100% rename from packages/react-native-gradle-plugin/shared/build.gradle.kts rename to packages/gradle-plugin/shared/build.gradle.kts diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingAndroidProjectJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingAndroidProjectJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingAndroidProjectJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingAndroidProjectJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingConfigJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingConfigJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingConfigJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingConfigJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformAndroidJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformAndroidJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformAndroidJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformAndroidJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingDependenciesPlatformJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingProjectJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingProjectJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingProjectJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelAutolinkingProjectJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfig.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelCodegenConfigAndroid.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/model/ModelPackageJson.kt diff --git a/packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt b/packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt rename to packages/gradle-plugin/shared/src/main/kotlin/com/facebook/react/utils/JsonUtils.kt diff --git a/packages/react-native-gradle-plugin/shared/src/test/kotlin/com/facebook/react/utils/JsonUtilsTest.kt b/packages/gradle-plugin/shared/src/test/kotlin/com/facebook/react/utils/JsonUtilsTest.kt similarity index 100% rename from packages/react-native-gradle-plugin/shared/src/test/kotlin/com/facebook/react/utils/JsonUtilsTest.kt rename to packages/gradle-plugin/shared/src/test/kotlin/com/facebook/react/utils/JsonUtilsTest.kt diff --git a/packages/helloworld/android/settings.gradle b/packages/helloworld/android/settings.gradle index 6da9a43763d13e..248883a85f2bc9 100644 --- a/packages/helloworld/android/settings.gradle +++ b/packages/helloworld/android/settings.gradle @@ -6,13 +6,13 @@ */ // Autolinking has now moved into the React Native Gradle Plugin -pluginManagement { includeBuild("../../react-native-gradle-plugin") } +pluginManagement { includeBuild("../../gradle-plugin") } plugins { id("com.facebook.react.settings") } extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } rootProject.name = 'HelloWorld' include ':app' -includeBuild('../../react-native-gradle-plugin') +includeBuild('../../gradle-plugin') includeBuild('../../react-native') { dependencySubstitution { substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid")) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0b877b180f675c..4a6e16a5aeaa13 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,7 +11,7 @@ pluginManagement { google() gradlePluginPortal() } - includeBuild("packages/react-native-gradle-plugin/") + includeBuild("packages/gradle-plugin/") } include( @@ -20,7 +20,7 @@ include( ":packages:react-native:ReactAndroid:external-artifacts", ":packages:rn-tester:android:app") -includeBuild("packages/react-native-gradle-plugin/") +includeBuild("packages/gradle-plugin/") dependencyResolutionManagement { versionCatalogs { From e7d1708701636dd524798541ad6ebe555d213350 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 21 Jun 2024 03:41:40 -0700 Subject: [PATCH 054/968] Fix broken unableToAddHandledRootView (#45101) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45101 This test broke after I merged https://github.com/facebook/react-native/pull/34785 yesterday. Just fixing it in a similar way as the test above. Changelog: [Internal] [Changed] - Fix broken unableToAddHandledRootView Reviewed By: rubennorte, blakef Differential Revision: D58864166 fbshipit-source-id: 4f48dbfd5238a2811564ce02199af7fc284d39b4 --- .../java/com/facebook/react/fabric/MountingManagerTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/MountingManagerTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/MountingManagerTest.kt index 3eaa174f84e691..4f009cb1adf21f 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/MountingManagerTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/fabric/MountingManagerTest.kt @@ -13,7 +13,6 @@ import com.facebook.react.bridge.ReactTestHelper.createMockCatalystInstance import com.facebook.react.fabric.mounting.MountingManager import com.facebook.react.fabric.mounting.MountingManager.MountItemExecutor import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsForTests -import com.facebook.react.uimanager.IllegalViewOperationException import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ViewManager import com.facebook.react.uimanager.ViewManagerRegistry @@ -68,11 +67,13 @@ class MountingManagerTest { mountingManager.startSurface(rootReactTag, themedReactContext, reactRootView) } - @Test(expected = IllegalViewOperationException::class) fun unableToAddHandledRootView() { val reactRootView = ReactRootView(themedReactContext) reactRootView.id = 1234567 val rootReactTag = nextRootTag++ + + // As above this is also a SoftException. + // See https://github.com/facebook/react-native/pull/34785 for more context. mountingManager.startSurface(rootReactTag, themedReactContext, reactRootView) } } From a7b25556449db64d7211c163bdd2e5437c1ad5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Fri, 21 Jun 2024 04:12:26 -0700 Subject: [PATCH 055/968] feat: remove upper limit for Cocoapods version (allow for 1.15.2) (#45099) Summary: This PR uses a suggested solution from here: https://github.com/facebook/react-native/issues/42698 to allow users to use Cocoapods 1.15.2 which fixed issues regarding RN builds. ## Changelog: [IOS] [FIXED] - Bump cocoapods version to 1.15.2 excluding 1.15.0, 1.15.1 Pull Request resolved: https://github.com/facebook/react-native/pull/45099 Test Plan: CI Green Reviewed By: blakef Differential Revision: D58863685 Pulled By: cipolleschi fbshipit-source-id: 0128eb0cbf83e4a3d35addbae4c31e349775688c --- Gemfile | 2 +- packages/helloworld/Gemfile | 2 +- packages/rn-tester/Gemfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 8e468b2c4e6681..88f17b435ec0c3 100644 --- a/Gemfile +++ b/Gemfile @@ -3,5 +3,5 @@ source 'https://rubygems.org' # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version ruby ">= 2.6.10" -gem 'cocoapods', '~> 1.13' +gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1' gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' diff --git a/packages/helloworld/Gemfile b/packages/helloworld/Gemfile index 6180ec4fafab31..50320de98530d5 100644 --- a/packages/helloworld/Gemfile +++ b/packages/helloworld/Gemfile @@ -2,5 +2,5 @@ source 'https://rubygems.org' ruby ">= 2.6.10" -gem 'cocoapods', '>= 1.13', '< 1.15' +gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1' gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' diff --git a/packages/rn-tester/Gemfile b/packages/rn-tester/Gemfile index 687d5db0dc63c4..0ea65792a4e02c 100644 --- a/packages/rn-tester/Gemfile +++ b/packages/rn-tester/Gemfile @@ -5,6 +5,6 @@ ruby ">= 2.6.10" # Cocoapods 1.15 introduced a bug which break the build. We will remove the upper # bound in the template on Cocoapods with next React Native release. -gem 'cocoapods', '>= 1.13', '< 1.15' +gem 'cocoapods', '~> 1.13', '!= 1.15.0', '!= 1.15.1' gem 'rexml' gem 'activesupport', '>= 6.1.7.5', '< 7.1.0' From 1bec961c9556572d16aa117e3c09468868406dcb Mon Sep 17 00:00:00 2001 From: Irfanwani Date: Fri, 21 Jun 2024 04:36:01 -0700 Subject: [PATCH 056/968] fix: post install error in iOS after running pod install, `undefined method 'path' for nil:NilClass` (#45095) Summary: After upgrading my project to the latest version of react native i.e, 0.74.2, i was getting an error when running `pod install` an the error was coming from the post install hook. Going deeper into the file tree, i found that some of the things are Nil and react native is trying to use some methods on them, so fixed those issues by using chaining operators to conditionally apply the path method on them. ## Changelog: [Internal] - fixes the post install issue when running pod install with react native version, 0.74.2 Pull Request resolved: https://github.com/facebook/react-native/pull/45095 Test Plan: Manually tested the fix. Works perfectly fine in both debug and production mode. Reviewed By: cortinico Differential Revision: D58863666 Pulled By: cipolleschi fbshipit-source-id: 64459711dcf926b7544b99b542e9861c1c0f05ca --- .../cocoapods/privacy_manifest_utils.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/privacy_manifest_utils.rb b/packages/react-native/scripts/cocoapods/privacy_manifest_utils.rb index 220d5d55eece46..098dc41206d75c 100644 --- a/packages/react-native/scripts/cocoapods/privacy_manifest_utils.rb +++ b/packages/react-native/scripts/cocoapods/privacy_manifest_utils.rb @@ -67,26 +67,34 @@ def self.read_privacyinfo_file(file_path) end def self.ensure_reference(file_path, user_project, target) - reference_exists = target.resources_build_phase.files_references.any? { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" } + reference_exists = target.resources_build_phase.files_references.any? { |file_ref| file_ref&.path&.end_with? "PrivacyInfo.xcprivacy" } unless reference_exists # We try to find the main group, but if it doesn't exist, we default to adding the file to the project root – both work - file_root = user_project.root_object.main_group.children.find { |group| group.class == Xcodeproj::Project::Object::PBXGroup && (group.name == target.name || group.path == target.name) } || user_project + file_root = user_project.root_object.main_group.children.find { |group| + group.class == Xcodeproj::Project::Object::PBXGroup && (group.name == target.name || group.path == target.name) + } || user_project file_ref = file_root.new_file(file_path) build_file = target.resources_build_phase.add_file_reference(file_ref, true) end end def self.get_privacyinfo_file_path(user_project, targets) + file_refs = targets.flat_map { |target| target.resources_build_phase.files_references } - existing_file = file_refs.find { |file_ref| file_ref.path&.end_with? "PrivacyInfo.xcprivacy" } + existing_file = file_refs.find { |file_ref| file_ref&.path&.end_with?("PrivacyInfo.xcprivacy") } + + if existing_file return existing_file.real_path end + # We try to find a file we know exists in the project to get the path to the main group directory info_plist_path = user_project.files.find { |file_ref| file_ref.name == "Info.plist" } if info_plist_path.nil? # return path that is sibling to .xcodeproj + path = user_project.path + return File.join(File.dirname(path), "PrivacyInfo.xcprivacy") end return File.join(File.dirname(info_plist_path.real_path),"PrivacyInfo.xcprivacy") @@ -117,6 +125,7 @@ def self.get_used_required_reason_apis(installer) end end end + return used_apis end @@ -124,7 +133,7 @@ def self.get_privacy_manifest_paths_from(user_project) privacy_manifests = user_project .files .select { |p| - p.path&.end_with?('PrivacyInfo.xcprivacy') + p&.path&.end_with?('PrivacyInfo.xcprivacy') } return privacy_manifests end @@ -162,7 +171,7 @@ def self.add_privacy_manifest_if_needed(installer) "NSPrivacyTracking" => false, "NSPrivacyAccessedAPITypes" => get_core_accessed_apis } - path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy") + path = File.join(user_project&.path.parent, "PrivacyInfo.xcprivacy") Xcodeproj::Plist.write_to_path(privacy_manifest, path) Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red end From fdf0183831f619d027d74924a2d386575a68f262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Fri, 21 Jun 2024 05:13:20 -0700 Subject: [PATCH 057/968] Stop defining setImmediate and clearImmediate from TimerManager when using microtasks (#45090) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45090 Changelog: [internal] The definition of these methods is redundant when using microtasks, so it's better to avoid defining them in the first place (to also detect issues if the setup is not what we expect). Reviewed By: sammy-SC Differential Revision: D58816582 fbshipit-source-id: dd1b07f8b11069605e3184b1272a9bbc3b44ca75 --- .../react/runtime/TimerManager.cpp | 111 +++++++++--------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp b/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp index 3ebf425447eeaf..057b6a1c58410b 100644 --- a/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp +++ b/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp @@ -8,6 +8,7 @@ #include "TimerManager.h" #include +#include #include namespace facebook::react { @@ -148,60 +149,64 @@ void TimerManager::callTimer(TimerHandle timerHandle) { void TimerManager::attachGlobals(jsi::Runtime& runtime) { // Install host functions for timers. // TODO (T45786383): Add missing timer functions from JSTimers - // TODO (T96212789): Remove when JSVM microtask queue is used everywhere in - // bridgeless mode. This is being overwritten in JS in that case. - runtime.global().setProperty( - runtime, - "setImmediate", - jsi::Function::createFromHostFunction( - runtime, - jsi::PropNameID::forAscii(runtime, "setImmediate"), - 2, // Function, ...args - [this]( - jsi::Runtime& rt, - const jsi::Value& thisVal, - const jsi::Value* args, - size_t count) { - if (count == 0) { - throw jsi::JSError( - rt, - "setImmediate must be called with at least one argument (a function to call)"); - } - - if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) { - throw jsi::JSError( - rt, "The first argument to setImmediate must be a function."); - } - auto callback = args[0].getObject(rt).getFunction(rt); - - // Package up the remaining argument values into one place. - std::vector moreArgs; - for (size_t extraArgNum = 1; extraArgNum < count; extraArgNum++) { - moreArgs.emplace_back(rt, args[extraArgNum]); - } - - return createReactNativeMicrotask( - std::move(callback), std::move(moreArgs)); - })); - runtime.global().setProperty( - runtime, - "clearImmediate", - jsi::Function::createFromHostFunction( - runtime, - jsi::PropNameID::forAscii(runtime, "clearImmediate"), - 1, // handle - [this]( - jsi::Runtime& rt, - const jsi::Value& thisVal, - const jsi::Value* args, - size_t count) { - if (count > 0 && args[0].isNumber()) { - auto handle = (TimerHandle)args[0].asNumber(); - deleteReactNativeMicrotask(rt, handle); - } - return jsi::Value::undefined(); - })); + // Ensure that we don't define `setImmediate` and `clearImmediate` if + // microtasks are enabled (as we polyfill them using `queueMicrotask` then). + if (!ReactNativeFeatureFlags::enableMicrotasks()) { + runtime.global().setProperty( + runtime, + "setImmediate", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "setImmediate"), + 2, // Function, ...args + [this]( + jsi::Runtime& rt, + const jsi::Value& thisVal, + const jsi::Value* args, + size_t count) { + if (count == 0) { + throw jsi::JSError( + rt, + "setImmediate must be called with at least one argument (a function to call)"); + } + + if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) { + throw jsi::JSError( + rt, + "The first argument to setImmediate must be a function."); + } + auto callback = args[0].getObject(rt).getFunction(rt); + + // Package up the remaining argument values into one place. + std::vector moreArgs; + for (size_t extraArgNum = 1; extraArgNum < count; extraArgNum++) { + moreArgs.emplace_back(rt, args[extraArgNum]); + } + + return createReactNativeMicrotask( + std::move(callback), std::move(moreArgs)); + })); + + runtime.global().setProperty( + runtime, + "clearImmediate", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "clearImmediate"), + 1, // handle + [this]( + jsi::Runtime& rt, + const jsi::Value& thisVal, + const jsi::Value* args, + size_t count) { + if (count > 0 && args[0].isNumber()) { + auto handle = (TimerHandle)args[0].asNumber(); + deleteReactNativeMicrotask(rt, handle); + } + return jsi::Value::undefined(); + })); + } runtime.global().setProperty( runtime, From a8a76f9bfab4aaefedf58b7fbcbea8efa7850e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Fri, 21 Jun 2024 05:13:20 -0700 Subject: [PATCH 058/968] Improve profiling information for timers (#45091) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45091 Changelog: [internal] We're currently logging when we execute timers in Systrace/Perfetto, but we have no information about them whatsoever. This adds some additional information: * What kind of timer it is * It's ID * And most importantly, when it was created (including the ID as well). This allows us to know where was a specific timer scheduled and with what API. Reviewed By: bgirard Differential Revision: D58832112 fbshipit-source-id: 1bc11759b6c8296acf63ff3533ca1dc3428360a7 --- .../react/runtime/TimerManager.cpp | 77 ++++++++++++++++--- .../ReactCommon/react/runtime/TimerManager.h | 20 ++++- 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp b/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp index 057b6a1c58410b..1f4cade5f85653 100644 --- a/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp +++ b/packages/react-native/ReactCommon/react/runtime/TimerManager.cpp @@ -13,6 +13,21 @@ namespace facebook::react { +namespace { +inline const char* getTimerSourceName(TimerSource source) { + switch (source) { + case TimerSource::Unknown: + return "unknown"; + case TimerSource::SetTimeout: + return "setTimeout"; + case TimerSource::SetInterval: + return "setInterval"; + case TimerSource::RequestAnimationFrame: + return "requestAnimationFrame"; + } +} +} // namespace + TimerManager::TimerManager( std::unique_ptr platformTimerRegistry) noexcept : platformTimerRegistry_(std::move(platformTimerRegistry)) {} @@ -60,14 +75,28 @@ void TimerManager::callReactNativeMicrotasks(jsi::Runtime& runtime) { TimerHandle TimerManager::createTimer( jsi::Function&& callback, std::vector&& args, - double delay) { + double delay, + TimerSource source) { // Get the id for the callback. TimerHandle timerID = timerIndex_++; + + SystraceSection s( + "TimerManager::createTimer", + "id", + timerID, + "type", + getTimerSourceName(source), + "delay", + delay); + timers_.emplace( std::piecewise_construct, std::forward_as_tuple(timerID), std::forward_as_tuple( - std::move(callback), std::move(args), /* repeat */ false)); + std::move(callback), + std::move(args), + /* repeat */ false, + source)); platformTimerRegistry_->createTimer(timerID, delay); @@ -77,14 +106,25 @@ TimerHandle TimerManager::createTimer( TimerHandle TimerManager::createRecurringTimer( jsi::Function&& callback, std::vector&& args, - double delay) { + double delay, + TimerSource source) { // Get the id for the callback. TimerHandle timerID = timerIndex_++; + + SystraceSection s( + "TimerManager::createRecurringTimer", + "id", + timerID, + "type", + getTimerSourceName(source), + "delay", + delay); + timers_.emplace( std::piecewise_construct, std::forward_as_tuple(timerID), std::forward_as_tuple( - std::move(callback), std::move(args), /* repeat */ true)); + std::move(callback), std::move(args), /* repeat */ true, source)); platformTimerRegistry_->createRecurringTimer(timerID, delay); @@ -131,11 +171,20 @@ void TimerManager::deleteRecurringTimer( void TimerManager::callTimer(TimerHandle timerHandle) { runtimeExecutor_([this, timerHandle](jsi::Runtime& runtime) { - SystraceSection s("TimerManager::callTimer"); auto it = timers_.find(timerHandle); if (it != timers_.end()) { - bool repeats = it->second.repeat; - it->second.invoke(runtime); + auto& timerCallback = it->second; + bool repeats = timerCallback.repeat; + + { + SystraceSection s( + "TimerManager::callTimer", + "id", + timerHandle, + "type", + getTimerSourceName(timerCallback.source)); + timerCallback.invoke(runtime); + } if (!repeats) { // Invoking a timer has the potential to delete it. Do not re-use the @@ -246,7 +295,11 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) { moreArgs.emplace_back(rt, args[extraArgNum]); } - return createTimer(std::move(callback), std::move(moreArgs), delay); + return createTimer( + std::move(callback), + std::move(moreArgs), + delay, + TimerSource::SetTimeout); })); runtime.global().setProperty( @@ -301,7 +354,10 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) { } return createRecurringTimer( - std::move(callback), std::move(moreArgs), delay); + std::move(callback), + std::move(moreArgs), + delay, + TimerSource::SetInterval); })); runtime.global().setProperty( @@ -370,7 +426,8 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) { return createTimer( std::move(callback), std::vector(), - /* delay */ 0); + /* delay */ 0, + TimerSource::RequestAnimationFrame); })); runtime.global().setProperty( diff --git a/packages/react-native/ReactCommon/react/runtime/TimerManager.h b/packages/react-native/ReactCommon/react/runtime/TimerManager.h index 9743087e80c897..879ba30430a18f 100644 --- a/packages/react-native/ReactCommon/react/runtime/TimerManager.h +++ b/packages/react-native/ReactCommon/react/runtime/TimerManager.h @@ -18,6 +18,13 @@ namespace facebook::react { using TimerHandle = int; +enum class TimerSource { + Unknown, + SetTimeout, + SetInterval, + RequestAnimationFrame +}; + /* * Wraps a jsi::Function to make it copyable so we can pass it into a lambda. */ @@ -25,10 +32,12 @@ struct TimerCallback { TimerCallback( jsi::Function callback, std::vector args, - bool repeat) + bool repeat, + TimerSource source = TimerSource::Unknown) : callback_(std::move(callback)), args_(std::move(args)), - repeat(repeat) {} + repeat(repeat), + source(source) {} void invoke(jsi::Runtime& runtime) { callback_.call(runtime, args_.data(), args_.size()); @@ -37,6 +46,7 @@ struct TimerCallback { jsi::Function callback_; const std::vector args_; bool repeat; + TimerSource source; }; class TimerManager { @@ -62,14 +72,16 @@ class TimerManager { TimerHandle createTimer( jsi::Function&& callback, std::vector&& args, - double delay); + double delay, + TimerSource source = TimerSource::Unknown); void deleteTimer(jsi::Runtime& runtime, TimerHandle handle); TimerHandle createRecurringTimer( jsi::Function&& callback, std::vector&& args, - double delay); + double delay, + TimerSource source = TimerSource::Unknown); void deleteRecurringTimer(jsi::Runtime& runtime, TimerHandle handle); From 34cd195d9fbd075a161afbfac842f896355991e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Fri, 21 Jun 2024 08:27:50 -0700 Subject: [PATCH 059/968] fix: retrieve statusbar size using RCTUIStatusBarManager (#45103) Summary: This PR changes the call from `RCTSharedApplication()` to retrieve the status bar size using the `RCTUIStatusBarManager()` method, a way which supports multi-window apps. ## Changelog: [IOS] [FIXED] - Retrieve status bar size using RCTUIStatusBarManager Pull Request resolved: https://github.com/facebook/react-native/pull/45103 Test Plan: Check if the perf menu pops up in the correct spot. Reviewed By: javache Differential Revision: D58868503 Pulled By: cipolleschi fbshipit-source-id: db5fc80a712a8a18a2863cdfbbe44f48bafe9fc3 --- packages/react-native/React/CoreModules/RCTPerfMonitor.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm index 023a5311db2e53..13872eac5567c4 100644 --- a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm +++ b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm @@ -171,7 +171,7 @@ - (UIPanGestureRecognizer *)gestureRecognizer - (UIView *)container { if (!_container) { - CGSize statusBarSize = RCTSharedApplication().statusBarFrame.size; + CGSize statusBarSize = RCTUIStatusBarManager().statusBarFrame.size; CGFloat statusBarHeight = statusBarSize.height; _container = [[UIView alloc] initWithFrame:CGRectMake(10, statusBarHeight, 180, RCTPerfMonitorBarHeight)]; _container.layer.borderWidth = 2; From 8a6508c62314a73fd08913cd1d03a98baaa4f1d8 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Fri, 21 Jun 2024 13:31:55 -0700 Subject: [PATCH 060/968] Increase the buffer size and try kStall to avoid dropping samples (#45111) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45111 Spent time debugging this issue today: https://fb.workplace.com/groups/1700234700326965/posts/2197109080639522 The problem is described here: https://perfetto.dev/docs/concepts/buffers But basically we're writing too much data, too fast and the traced process can't read it fast enough. Perfetto is doing data drop. This diff tries to use the `kStall` mode. It doesn't seem to do much but I'll leave it in for now because it shouldn't hurt too much. It's designed for our use case. The main fix comes from increasing the buffer size to 20MB. Since it's not on by default I think it's fine to have a really large buffer for now to unblock tracing. Reviewed By: javache Differential Revision: D58832598 fbshipit-source-id: 101b364e2e9e28aa6a041ded1df82d5fec1f42e1 --- .../reactperflogger/HermesPerfettoDataSource.h | 3 +++ .../reactperflogger/reactperflogger/ReactPerfetto.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.h b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.h index 4f7c2b4bcc6628..cf1818c0fce8ac 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.h +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/HermesPerfettoDataSource.h @@ -27,6 +27,9 @@ class HermesPerfettoDataSource dsd.set_name("com.facebook.hermes.profiler"); HermesPerfettoDataSource::Register(dsd); } + + constexpr static perfetto::BufferExhaustedPolicy kBufferExhaustedPolicy = + perfetto::BufferExhaustedPolicy::kStall; }; PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(HermesPerfettoDataSource); diff --git a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp index cf7bd386d2f6cd..1dea5e1fc45557 100644 --- a/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp +++ b/packages/react-native/ReactCommon/reactperflogger/reactperflogger/ReactPerfetto.cpp @@ -17,6 +17,10 @@ std::once_flag perfettoInit; void initializePerfetto() { std::call_once(perfettoInit, []() { perfetto::TracingInitArgs args; + // Raise the size of the shared memory buffer. Since this + // is only used in tracing build, large buffers are okay + // for now. + args.shmem_size_hint_kb = 20 * 1024; args.backends |= perfetto::kSystemBackend; args.use_monotonic_clock = true; perfetto::Tracing::Initialize(args); From f7fe68861a52a0428698a9352d39a6e39afefe42 Mon Sep 17 00:00:00 2001 From: Panos Vekris Date: Fri, 21 Jun 2024 16:15:34 -0700 Subject: [PATCH 061/968] set one_sided_type_guards=true in fbsource (#45107) Summary: This diff enables: 1. [one-sided type guards](https://flow.org/en/docs/types/type-guards/#one-sided-type-guards) (`implies x is T`), and 2. stricter checking of type guard consistency (see [relevant docs page](https://flow.org/en/docs/types/type-guards/#toc-consistency-checks-of-type-guard-functions)). To prevent many new errors from being introduced this diff also converts some two-sided type guards to [one-sided](https://flow.org/en/docs/types/type-guards/#one-sided-type-guards) ones. Pull Request resolved: https://github.com/facebook/react-native/pull/45107 Updated the flowconfigs and synced flow_runner/codemods since the change has already been applied there: ``` js1 upgrade www-shared -p flow_runner/codemods ``` Changelog: [Internal] Reviewed By: gkz Differential Revision: D58874409 fbshipit-source-id: 959a6773701518a1d6aa35e2ec28fd4ce12d2e75 --- .flowconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.flowconfig b/.flowconfig index 55643d39e942e9..7e2c3948db21c9 100644 --- a/.flowconfig +++ b/.flowconfig @@ -64,6 +64,8 @@ module.name_mapper='^react-native/\(.*\)$' -> '/packages/react-nat module.name_mapper='^@react-native/dev-middleware$' -> '/packages/dev-middleware' module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/packages/react-native/Libraries/Image/RelativeImageStub' +one_sided_type_guards=true + suppress_type=$FlowIssue suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps From 6bb75c7b133c9be5f613c3310aa918e5a28cec7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Mon, 24 Jun 2024 03:14:55 -0700 Subject: [PATCH 062/968] fix: set proper framework dependencies for built-in pods (#45104) Summary: Platforms like visionOS require explicit framework dependencies to be set in pods to build properly. For some reason linking on visionOS is more strict than on iOS but this might change in some future OS versions so it's good to have pods having exact dependencies. I've discussed that earlier with Saadnajmi and cipolleschi. Let me know if you are okay with this change. ## Changelog: [IOS] [FIXED] - set proper framework dependencies for built-in pods Pull Request resolved: https://github.com/facebook/react-native/pull/45104 Test Plan: CI Green Reviewed By: dmytrorykun Differential Revision: D58943593 Pulled By: cipolleschi fbshipit-source-id: 3d2df4f3bbdf36704e09f5e39bfb838b2e0f3c99 --- packages/react-native/Libraries/Image/React-RCTImage.podspec | 2 +- .../react-native/Libraries/LinkingIOS/React-RCTLinking.podspec | 1 + .../Libraries/NativeAnimation/React-RCTAnimation.podspec | 1 + .../PushNotificationIOS/React-RCTPushNotification.podspec | 2 +- .../react/nativemodule/samples/ReactCommon-Samples.podspec | 2 ++ .../ReactCommon/react/renderer/graphics/React-graphics.podspec | 1 + .../rn-tester/NativeModuleExample/ScreenshotManager.podspec | 1 + 7 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/Image/React-RCTImage.podspec b/packages/react-native/Libraries/Image/React-RCTImage.podspec index 5aacf0d7999c32..8f77a54b2372b5 100644 --- a/packages/react-native/Libraries/Image/React-RCTImage.podspec +++ b/packages/react-native/Libraries/Image/React-RCTImage.podspec @@ -45,7 +45,7 @@ Pod::Spec.new do |s| "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } - s.framework = ["Accelerate", "UIKit"] + s.framework = ["Accelerate", "UIKit", "QuartzCore", "ImageIO", "CoreGraphics"] s.dependency "RCT-Folly", folly_version s.dependency "RCTTypeSafety" diff --git a/packages/react-native/Libraries/LinkingIOS/React-RCTLinking.podspec b/packages/react-native/Libraries/LinkingIOS/React-RCTLinking.podspec index eff125c9615056..a0c4e1a5b74cda 100644 --- a/packages/react-native/Libraries/LinkingIOS/React-RCTLinking.podspec +++ b/packages/react-native/Libraries/LinkingIOS/React-RCTLinking.podspec @@ -44,6 +44,7 @@ Pod::Spec.new do |s| "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } + s.framework = "UIKit" s.dependency "React-Core/RCTLinkingHeaders", version s.dependency "ReactCommon/turbomodule/core", version diff --git a/packages/react-native/Libraries/NativeAnimation/React-RCTAnimation.podspec b/packages/react-native/Libraries/NativeAnimation/React-RCTAnimation.podspec index c9f32c9eea7e36..259790ed4e2d73 100644 --- a/packages/react-native/Libraries/NativeAnimation/React-RCTAnimation.podspec +++ b/packages/react-native/Libraries/NativeAnimation/React-RCTAnimation.podspec @@ -43,6 +43,7 @@ Pod::Spec.new do |s| "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "HEADER_SEARCH_PATHS" => header_search_paths.join(" ") } + s.framework = ["UIKit", "QuartzCore"] s.dependency "RCT-Folly", folly_version s.dependency "RCTTypeSafety" diff --git a/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec b/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec index 7a82e20d911a68..6f274ca83d4dea 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec +++ b/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec @@ -44,7 +44,7 @@ Pod::Spec.new do |s| "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } - s.framework = "UserNotifications" + s.framework = ["UIKit", "UserNotifications"] s.dependency "RCTTypeSafety" s.dependency "React-Core/RCTPushNotificationHeaders" diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec b/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec index 5c6fc31aa5333d..e88b986d6e6204 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/ReactCommon-Samples.podspec @@ -49,6 +49,8 @@ Pod::Spec.new do |s| "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "GCC_WARN_PEDANTIC" => "YES" } + s.framework = "UIKit" + if ENV['USE_FRAMEWORKS'] s.header_mappings_dir = './' end diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec index 94743610da2fe2..9125fddb886750 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec +++ b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec @@ -47,6 +47,7 @@ Pod::Spec.new do |s| "platform/cxx", "platform/windows", s.header_dir = "react/renderer/graphics" + s.framework = "UIKit" if ENV['USE_FRAMEWORKS'] s.module_name = "React_graphics" diff --git a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec index 17daaf5934d9fd..3177cf590fe73a 100644 --- a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec +++ b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec @@ -21,6 +21,7 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,mm,swift}" s.requires_arc = true + s.framework = ["UIKit", "CoreGraphics"] install_modules_dependencies(s) end From 72ce6ff03a3b192f529ba82b00925708f572fed6 Mon Sep 17 00:00:00 2001 From: Nick Lefever Date: Mon, 24 Jun 2024 05:20:42 -0700 Subject: [PATCH 063/968] Fix runtime shadow node reference corruption on measure (#45116) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45116 Changelog: [Internal] The UIManagerBinding `findShadowNodeByTag_DEPRECATED` method returns a shadow node and was updating the runtime reference on the shadow node with the created wrapper for the return value. The JSObject holding the wrapper would get deallocated, which would deallocate the wrapper stored on the shadow node. This would cause crashes on the next reference update for the shadow node, due to the shared_ptr being reassigned with the new value while it was already deallocated. The `sendAccessibilityEvent` function calls `findShadowNodeByTag_DEPRECATED` to get the shadow node referenced by the provided react tag, which could lead to runtime shadow node reference corruption. Reviewed By: sammy-SC Differential Revision: D58920296 fbshipit-source-id: ddb9ed0ee64bc01934aabde7070731dc53a2db70 --- .../react/renderer/uimanager/UIManagerBinding.cpp | 15 ++++++++++----- .../react/renderer/uimanager/primitives.h | 11 ++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 96d3dfb221b857..d7f6a424467431 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -256,7 +256,8 @@ jsi::Value UIManagerBinding::get( stringFromValue(runtime, arguments[1]), surfaceIdFromValue(runtime, arguments[2]), RawProps(runtime, arguments[3]), - std::move(instanceHandle))); + std::move(instanceHandle)), + true); } catch (const std::logic_error& ex) { LOG(FATAL) << "logic_error in createNode: " << ex.what(); } @@ -282,7 +283,8 @@ jsi::Value UIManagerBinding::get( uiManager->cloneNode( *shadowNodeFromValue(runtime, arguments[0]), nullptr, - RawProps())); + RawProps()), + true); }); } @@ -369,7 +371,8 @@ jsi::Value UIManagerBinding::get( *shadowNodeFromValue(runtime, arguments[0]), count > 1 ? shadowNodeListFromValue(runtime, arguments[1]) : ShadowNode::emptySharedShadowNodeSharedList(), - RawProps())); + RawProps()), + true); }); } @@ -392,7 +395,8 @@ jsi::Value UIManagerBinding::get( uiManager->cloneNode( *shadowNodeFromValue(runtime, arguments[0]), nullptr, - RawProps(runtime, arguments[1]))); + RawProps(runtime, arguments[1])), + true); }); } @@ -420,7 +424,8 @@ jsi::Value UIManagerBinding::get( hasChildrenArg ? shadowNodeListFromValue(runtime, arguments[1]) : ShadowNode::emptySharedShadowNodeSharedList(), - RawProps(runtime, arguments[hasChildrenArg ? 2 : 1]))); + RawProps(runtime, arguments[hasChildrenArg ? 2 : 1])), + true); }); } diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/primitives.h b/packages/react-native/ReactCommon/react/renderer/uimanager/primitives.h index 6c7e8b3dbafee8..0a6b29dab58291 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/primitives.h @@ -44,12 +44,17 @@ inline static ShadowNode::Shared shadowNodeFromValue( inline static jsi::Value valueFromShadowNode( jsi::Runtime& runtime, - ShadowNode::Shared shadowNode) { + ShadowNode::Shared shadowNode, + bool assignRuntimeShadowNodeReference = false) { // Wrap the shadow node so that we can update JS references from native auto wrappedShadowNode = std::make_shared(std::move(shadowNode)); - wrappedShadowNode->shadowNode->setRuntimeShadowNodeReference( - &*wrappedShadowNode); + + if (assignRuntimeShadowNodeReference) { + wrappedShadowNode->shadowNode->setRuntimeShadowNodeReference( + &*wrappedShadowNode); + } + jsi::Object obj(runtime); obj.setNativeState(runtime, std::move(wrappedShadowNode)); return obj; From 42735717b5e7c29d44215bed7d66bbfb44931288 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 24 Jun 2024 05:54:30 -0700 Subject: [PATCH 064/968] Fix Cache checks in build_hermes_macos (#45127) Summary: The cache checks in GHA were performed against bool values, while the actual values are strings. So the checks were always failing and all the steps were executed, even when not necessary. The reason why it was failing is because, with this setup, when a cache is hit, some steps were skipped in previous jobs, making following jobs trying to execute code on not-existing files. ## Changelog: [Internal] - Fix cache for build_hermes_macos Pull Request resolved: https://github.com/facebook/react-native/pull/45127 Test Plan: GHA are green again Reviewed By: blakef Differential Revision: D58947838 Pulled By: cipolleschi fbshipit-source-id: 8dba216e72a3034fd4c1484418d37bfb78cf314d --- .github/workflows/nightly.yml | 28 +++++++++++++-------------- .github/workflows/publish-release.yml | 28 +++++++++++++-------------- .github/workflows/test-all.yml | 23 +++++++++++----------- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 110257858d87c0..bf621b8cd6bc30 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -105,7 +105,7 @@ jobs: echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT fi - name: Build the Hermes ${{ matrix.slice }} frameworks - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 SLICE=${{ matrix.slice }} @@ -150,7 +150,7 @@ jobs: exit 1 fi - name: Save slice cache - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_${{ matrix.slice }}_${{ matrix.flavor }} @@ -200,46 +200,46 @@ jobs: echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT fi - name: Yarn- Install Dependencies - if: ${{ ! contains(github.event.head_commit.message, 'Bump metro@') && steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: yarn install --non-interactive - name: Slice cache macosx - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_macosx_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-macosx-${{ matrix.flavor }} - name: Slice cache iphoneos - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_iphoneos_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-iphoneos-${{ matrix.flavor }} - name: Slice cache iphonesimulator - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_iphonesimulator_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-iphonesimulator-${{ matrix.flavor }} - name: Slice cache catalyst - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_catalyst_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-catalyst-${{ matrix.flavor }} - name: Slice cache xros - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_xros_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-xros-${{ matrix.flavor }} - name: Slice cache xrsimulator - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_xrsimulator_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-xrsimulator-${{ matrix.flavor }} - name: Move back build folders - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | ls -l ./packages/react-native/sdks/hermes cd ./packages/react-native/sdks/hermes || exit 1 @@ -250,20 +250,20 @@ jobs: mv build_xros_${{ matrix.flavor }} build_xros mv build_xrsimulator_${{ matrix.flavor }} build_xrsimulator - name: Prepare destroot folder - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 . ./utils/build-apple-framework.sh prepare_dest_root_for_ci - name: Create fat framework for iOS - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 echo "[HERMES] Creating the universal framework" chmod +x ./utils/build-ios-framework.sh ./utils/build-ios-framework.sh build_framework - name: Package the Hermes Apple frameworks - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | BUILD_TYPE="${{ matrix.flavor }}" echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" @@ -298,7 +298,7 @@ jobs: name: hermes-osx-bin-${{ matrix.flavor }} path: /tmp/hermes/osx-bin - name: Create dSYM archive - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | FLAVOR=${{ matrix.flavor }} WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR" diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 874ee9ae54c4e7..2331ae41793dba 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -102,7 +102,7 @@ jobs: echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT fi - name: Build the Hermes ${{ matrix.slice }} frameworks - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 SLICE=${{ matrix.slice }} @@ -147,7 +147,7 @@ jobs: exit 1 fi - name: Save slice cache - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_${{ matrix.slice }}_${{ matrix.flavor }} @@ -197,46 +197,46 @@ jobs: echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT fi - name: Yarn- Install Dependencies - if: ${{ ! contains(github.event.head_commit.message, 'Bump metro@') && steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: yarn install --non-interactive - name: Slice cache macosx - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_macosx_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-macosx-${{ matrix.flavor }} - name: Slice cache iphoneos - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_iphoneos_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-iphoneos-${{ matrix.flavor }} - name: Slice cache iphonesimulator - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_iphonesimulator_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-iphonesimulator-${{ matrix.flavor }} - name: Slice cache catalyst - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_catalyst_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-catalyst-${{ matrix.flavor }} - name: Slice cache xros - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_xros_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-xros-${{ matrix.flavor }} - name: Slice cache xrsimulator - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_xrsimulator_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-xrsimulator-${{ matrix.flavor }} - name: Move back build folders - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | ls -l ./packages/react-native/sdks/hermes cd ./packages/react-native/sdks/hermes || exit 1 @@ -247,20 +247,20 @@ jobs: mv build_xros_${{ matrix.flavor }} build_xros mv build_xrsimulator_${{ matrix.flavor }} build_xrsimulator - name: Prepare destroot folder - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 . ./utils/build-apple-framework.sh prepare_dest_root_for_ci - name: Create fat framework for iOS - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 echo "[HERMES] Creating the universal framework" chmod +x ./utils/build-ios-framework.sh ./utils/build-ios-framework.sh build_framework - name: Package the Hermes Apple frameworks - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | BUILD_TYPE="${{ matrix.flavor }}" echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" @@ -295,7 +295,7 @@ jobs: name: hermes-osx-bin-${{ matrix.flavor }} path: /tmp/hermes/osx-bin - name: Create dSYM archive - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | FLAVOR=${{ matrix.flavor }} WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR" diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index ee458b5c8d4bfd..2e2e70e06d3670 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -208,45 +208,46 @@ jobs: echo "ARTIFACTS_EXIST=true" >> $GITHUB_OUTPUT fi - name: Yarn- Install Dependencies + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: yarn install --non-interactive - name: Slice cache macosx - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_macosx_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-macosx-${{ matrix.flavor }} - name: Slice cache iphoneos - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_iphoneos_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-iphoneos-${{ matrix.flavor }} - name: Slice cache iphonesimulator - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_iphonesimulator_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-iphonesimulator-${{ matrix.flavor }} - name: Slice cache catalyst - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_catalyst_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-catalyst-${{ matrix.flavor }} - name: Slice cache xros - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_xros_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-xros-${{ matrix.flavor }} - name: Slice cache xrsimulator - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} uses: actions/cache@v4.0.0 with: path: ./packages/react-native/sdks/hermes/build_xrsimulator_${{ matrix.flavor }} key: v4-hermes-apple-${{ needs.prepare_hermes_workspace.outputs.hermes-version }}-${{ needs.prepare_hermes_workspace.outputs.react-native-version }}-${{ hashfiles('packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh') }}-xrsimulator-${{ matrix.flavor }} - name: Move back build folders - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | ls -l ./packages/react-native/sdks/hermes cd ./packages/react-native/sdks/hermes || exit 1 @@ -257,20 +258,20 @@ jobs: mv build_xros_${{ matrix.flavor }} build_xros mv build_xrsimulator_${{ matrix.flavor }} build_xrsimulator - name: Prepare destroot folder - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 . ./utils/build-apple-framework.sh prepare_dest_root_for_ci - name: Create fat framework for iOS - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | cd ./packages/react-native/sdks/hermes || exit 1 echo "[HERMES] Creating the universal framework" chmod +x ./utils/build-ios-framework.sh ./utils/build-ios-framework.sh build_framework - name: Package the Hermes Apple frameworks - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | BUILD_TYPE="${{ matrix.flavor }}" echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" @@ -305,7 +306,7 @@ jobs: name: hermes-osx-bin-${{ matrix.flavor }} path: /tmp/hermes/osx-bin - name: Create dSYM archive - if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != true }} + if: ${{ steps.check_if_apple_artifacts_are_there.outputs.ARTIFACTS_EXIST != 'true' }} run: | FLAVOR=${{ matrix.flavor }} WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR" From 61b3c95b45b42a5b86d0a3b013b4f37d0e138613 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 24 Jun 2024 06:51:29 -0700 Subject: [PATCH 065/968] Bump CLI to 14 alpha9 (#45121) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45121 As the title says Changelog: [Internal] [Changed] - Bump CLI to 14 alpha9 Reviewed By: cipolleschi, blakef Differential Revision: D58945983 fbshipit-source-id: 227b56bb0441a60ce247524ac8361e5eb8674c3c --- packages/community-cli-plugin/package.json | 4 +- packages/react-native/package.json | 6 +- yarn.lock | 167 ++++++++------------- 3 files changed, 69 insertions(+), 108 deletions(-) diff --git a/packages/community-cli-plugin/package.json b/packages/community-cli-plugin/package.json index ef1622e1c16f3c..281a5d26ced3cf 100644 --- a/packages/community-cli-plugin/package.json +++ b/packages/community-cli-plugin/package.json @@ -22,8 +22,8 @@ "dist" ], "dependencies": { - "@react-native-community/cli-server-api": "14.0.0-alpha.2", - "@react-native-community/cli-tools": "14.0.0-alpha.2", + "@react-native-community/cli-server-api": "14.0.0-alpha.9", + "@react-native-community/cli-tools": "14.0.0-alpha.9", "@react-native/dev-middleware": "0.75.0-main", "@react-native/metro-babel-transformer": "0.75.0-main", "chalk": "^4.0.0", diff --git a/packages/react-native/package.json b/packages/react-native/package.json index e6dacc724d320f..af5d2fb324b5c5 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -109,9 +109,9 @@ }, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "14.0.0-alpha.7", - "@react-native-community/cli-platform-android": "14.0.0-alpha.7", - "@react-native-community/cli-platform-ios": "14.0.0-alpha.7", + "@react-native-community/cli": "14.0.0-alpha.9", + "@react-native-community/cli-platform-android": "14.0.0-alpha.9", + "@react-native-community/cli-platform-ios": "14.0.0-alpha.9", "@react-native/assets-registry": "0.75.0-main", "@react-native/codegen": "0.75.0-main", "@react-native/community-cli-plugin": "0.75.0-main", diff --git a/yarn.lock b/yarn.lock index 3711f40e3c7ac2..8217f7dce08123 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2615,22 +2615,22 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" -"@react-native-community/cli-clean@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.7.tgz#94b35e06d20a81b804f7510bb58ff2afee6abb4e" - integrity sha512-p7JHg6UbDfpoFdxYIHqjds9pwPSnBeNDNOanT6/IPdz8lCXhFkAnQOcqcoltxA9LOmb6G2d5GYg2aiKa1uZGPQ== +"@react-native-community/cli-clean@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.9.tgz#cf4cd3e55a583b40ecaadb343f23b36c70cf7baf" + integrity sha512-Cz8nNivB9I06nqiPQiDDb8ZE7yDNCQBtRoSe1hle2rbxBYsvtMoAEC/jdyJIuxm9e0tA72WbrrdUSQqM1eLw3A== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.9" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" -"@react-native-community/cli-config@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.7.tgz#3db66b6f6ccd2500b0c5ca28e9378a28e452a2b7" - integrity sha512-rfwU7fnnWN0RcJPny3/n0jlqf1xIWW2wc33MjyCmztZtJs5ow3ivEudi81PucQmWleIdk77H35Xp06um1nJjOg== +"@react-native-community/cli-config@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.9.tgz#20878d1984738ef0b14d8e3a5ab03753c9dc3710" + integrity sha512-vxhWya2S3yhrlfjXXpSxj/jEB6zKZjoDpDbZaN+aDzdub8Er+z0LEgCNJUA7QgcLtV4MEH9sNA43gZLhNkRW1A== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.9" chalk "^4.1.2" cosmiconfig "^9.0.0" deepmerge "^4.3.0" @@ -2649,30 +2649,23 @@ fast-glob "^3.3.2" joi "^17.2.1" -"@react-native-community/cli-debugger-ui@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.0.0-alpha.2.tgz#484847fb01eef67ea2c26cd35a88342112c15ff9" - integrity sha512-HdKmbFF0/7QST00JfC2jexdYPbUelmVaK7VjN9ZnZbZnirseHQU4MsG1lcF5dIuwrQkFH03mt/mF6WSg5ghPeA== +"@react-native-community/cli-debugger-ui@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.0.0-alpha.9.tgz#233f5fa5ffde9d2b44597bf71890777e4c918de0" + integrity sha512-lIKYXKpDJuTvmDqP03aR9G9CLc3WLn9btJ+CldCxoffIs3CpOEZUYC1NRcxRWbGDTZwNSLgra/oTKWXCgVK1gg== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-debugger-ui@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.0.0-alpha.7.tgz#79ce17779c14b8454e081d165e900ebf992a9cce" - integrity sha512-PegGpU9XVpBOSJ21aFtSdpAfxgl3tlCuwWBoNSV9UgeyWtbvVyVNDHI4YdAL7hymH1zWRcUsP1uIVQ3/kmooeg== +"@react-native-community/cli-doctor@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.9.tgz#f1ee17c67a674ac83d56bed65c45fe02c841f3b6" + integrity sha512-pN7t6xna1+GqJDuXb1zTtAgbqc9jyw3T0ySvJ86eA9BLCAW11TSI9rjU6IIPcnKB+JxsxOyD4blmQjrFN2VIzA== dependencies: - serve-static "^1.13.1" - -"@react-native-community/cli-doctor@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.7.tgz#186eb62d0ea779539c10fcb002f8444b4ebf2f2e" - integrity sha512-tS7it/541M0ArDJOmrfyMfqpn9Ei7rJGge9ctc0JdwTVpZJZAL96ZMROzFsIj7TaEyFMmFmeV2v1bTAyWLjIwA== - dependencies: - "@react-native-community/cli-config" "14.0.0-alpha.7" - "@react-native-community/cli-platform-android" "14.0.0-alpha.7" - "@react-native-community/cli-platform-apple" "14.0.0-alpha.7" - "@react-native-community/cli-platform-ios" "14.0.0-alpha.7" - "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-config" "14.0.0-alpha.9" + "@react-native-community/cli-platform-android" "14.0.0-alpha.9" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.9" + "@react-native-community/cli-platform-ios" "14.0.0-alpha.9" + "@react-native-community/cli-tools" "14.0.0-alpha.9" chalk "^4.1.2" command-exists "^1.2.8" deepmerge "^4.3.0" @@ -2685,24 +2678,24 @@ wcwidth "^1.0.1" yaml "^2.2.1" -"@react-native-community/cli-platform-android@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.7.tgz#47049f804c9ac5f347a99088ac9ca7be3fade63e" - integrity sha512-db1lHAjlzbm5V3okfKCiuHTNgsVsBVdWG7wvAvHmCGY8esNQrjIpGHsVuvOFmCGvuKk3NkwJ6qTxbV1RWWnBYw== +"@react-native-community/cli-platform-android@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.9.tgz#8fdadf53e3fa0586b5093adb77a52701995768b7" + integrity sha512-DjPtKnPnKr8JmyIbSnVeEbRk825NWa0kL0ZL6F461NKawhvKunHQ6oIH1xs+oJbQ4apmWvijjFCUCp2/Ye/1xg== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.9" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" fast-xml-parser "^4.2.4" logkitty "^0.7.1" -"@react-native-community/cli-platform-apple@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.7.tgz#13dd14ecaa39fd90872c8f7c5af9c583dd6c3af0" - integrity sha512-eOmgrJoPpz2RN1L2fOo9C1reiZ+aPNS5+oUepT/SeFRT/ybmVgXTKnPKjcJ0MXErgay485esLqZrWR609m8VMA== +"@react-native-community/cli-platform-apple@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.9.tgz#d8c2683e9609f52c27939e4c6b604be43145e8c0" + integrity sha512-Gs4USDaMhtrnPb46DpjXkC7eq9Bkpc3ENIV2YFBgBdMo2aIFmIsBycvm5+asMSJlKwsyDYnxBJBLo6FOUkwE2w== dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-tools" "14.0.0-alpha.9" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" @@ -2721,35 +2714,20 @@ fast-xml-parser "^4.0.12" ora "^5.4.1" -"@react-native-community/cli-platform-ios@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.7.tgz#d666c19b37f5c79b71bb00ecd63c4740a25badae" - integrity sha512-mgHGqJcHegwNE4dSyoP2g5Oc8jxeeSUKql6WTsUNfhQKKdF1Cmtms5xaupbWqEjewf9oMfYqL7shSjAgMsDq6Q== +"@react-native-community/cli-platform-ios@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.9.tgz#4f2686ca03efa186aac3bf354cbf15936627d4f8" + integrity sha512-7Rb399ErNpVpQvcF7RQolFk9HF6xRsZkdSlAZQGM2lCNQ3Wj4CRX6Bixa59bnGAY+uK3bjE/LeFcUbFXPgzr0Q== dependencies: - "@react-native-community/cli-platform-apple" "14.0.0-alpha.7" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.9" -"@react-native-community/cli-server-api@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.2.tgz#28ddb885f2fee76b325799f512ff0fbdd02570cd" - integrity sha512-msL6fzZkUe9GTtG8E/LN1/Uh7x2mE3xr7rjtpk5ADTx+TlJpnPtkHucyODu57e2i19jcLqXzO0u0ImfgOG55WA== +"@react-native-community/cli-server-api@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.9.tgz#f5ac1de8a955dd496617322d659e120e44cdc0a5" + integrity sha512-8iEZoFNv0EzqVuTXm2tamUOKzPfq8E3Yjc7kdpqT68gwRD/MBpXM+t7ItEU8EbfhArccUHVADKWjWGdnQ43adw== dependencies: - "@react-native-community/cli-debugger-ui" "14.0.0-alpha.2" - "@react-native-community/cli-tools" "14.0.0-alpha.2" - compression "^1.7.1" - connect "^3.6.5" - errorhandler "^1.5.1" - nocache "^3.0.1" - pretty-format "^26.6.2" - serve-static "^1.13.1" - ws "^7.5.1" - -"@react-native-community/cli-server-api@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.7.tgz#0d61005dde4c81a0d1f16ab850b76a130f688a95" - integrity sha512-4N5lAebocJmGH3b2yQBHeKiD0Th4XEa3h0vIMWN0TTu+af/z5k4jB2szzzulHnER5lyvChCkYm+ZO1amAKmc9g== - dependencies: - "@react-native-community/cli-debugger-ui" "14.0.0-alpha.7" - "@react-native-community/cli-tools" "14.0.0-alpha.7" + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.9" + "@react-native-community/cli-tools" "14.0.0-alpha.9" compression "^1.7.1" connect "^3.6.5" errorhandler "^1.5.1" @@ -2775,27 +2753,10 @@ shell-quote "^1.7.3" sudo-prompt "^9.0.0" -"@react-native-community/cli-tools@14.0.0-alpha.2": - version "14.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-14.0.0-alpha.2.tgz#fa898083fa48449d9a2a08624fa2d71057a37d2e" - integrity sha512-GDFwGSPjcTYhdn8bmT+oleL2rFrVHgLAZbKu8LjIq0n4bO7cacSTbRtqe31h3QixolNYMWsVobtDpD/zBtKVxg== - dependencies: - appdirsjs "^1.2.4" - chalk "^4.1.2" - execa "^5.0.0" - find-up "^5.0.0" - mime "^2.4.1" - node-fetch "^2.6.0" - open "^6.2.0" - ora "^5.4.1" - semver "^7.5.2" - shell-quote "^1.7.3" - sudo-prompt "^9.0.0" - -"@react-native-community/cli-tools@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-14.0.0-alpha.7.tgz#680c63d3cdac4f2cd2a834a34eaeac48d64c08d8" - integrity sha512-fiLcyZEtY9bB3DQ7Y3FBbJaKQkHmT3yhaagtg1kOaaWyW9NcELMrXhVSHTO+kC8L7XvHEfC0EAfA6N5JWDNfwQ== +"@react-native-community/cli-tools@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-14.0.0-alpha.9.tgz#1356a21c69bb1982586ea705351d1c1ffd4489f5" + integrity sha512-DGDHyJA/acfOwzjqyPK5cm0ZMHzu1IctL4HwK01y48o+bi5gIxUcKhmGUZWA2LwLTNjIto64EE3i3dUT9jRHAA== dependencies: appdirsjs "^1.2.4" chalk "^4.1.2" @@ -2808,10 +2769,10 @@ shell-quote "^1.7.3" sudo-prompt "^9.0.0" -"@react-native-community/cli-types@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.7.tgz#7e9ee2c478d7572f06e7aabc3f0688c869c61c1e" - integrity sha512-B/lyk7x2RRjWISbGbORCj+9Fub4Is1rk2b8dHm6ccML0kH6rj+H6afMXNwV9371+slSB+MeRpqCR5CBcag2Etw== +"@react-native-community/cli-types@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.9.tgz#9a95bf0e3184e8eb44fd6082016ddb1c93b06c24" + integrity sha512-XEDwsrgje9JG5hVuUCBWaH8XVV1H3ZcTwXxd/XhmDNemPyOLnDfgeAlitbEMyi+X/SWB04EGQu1SeRwe5vLePA== dependencies: joi "^17.2.1" @@ -2822,18 +2783,18 @@ dependencies: joi "^17.2.1" -"@react-native-community/cli@14.0.0-alpha.7": - version "14.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.7.tgz#5495ca20c9ef0c94639eef21322bbc846f81f1a3" - integrity sha512-DrdyBhdM6lCYqljDs18mWLuyta2CdeaJkdJAVomkfAme+TldTCiLp34XwsXhYAVWNQXrv+W17bQ+PmurXu0s9w== - dependencies: - "@react-native-community/cli-clean" "14.0.0-alpha.7" - "@react-native-community/cli-config" "14.0.0-alpha.7" - "@react-native-community/cli-debugger-ui" "14.0.0-alpha.7" - "@react-native-community/cli-doctor" "14.0.0-alpha.7" - "@react-native-community/cli-server-api" "14.0.0-alpha.7" - "@react-native-community/cli-tools" "14.0.0-alpha.7" - "@react-native-community/cli-types" "14.0.0-alpha.7" +"@react-native-community/cli@14.0.0-alpha.9": + version "14.0.0-alpha.9" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.9.tgz#0a00a3f8bcee9edb482ad59018bd4d3a8e7210f7" + integrity sha512-1EAs79u+dPxDIBq1TkT2TV3Pa7fw1CakmoFTTSVYA4EHnRVqSnonAQj/kSf8cVuL4ORHDavlnzHcCaSXCB0MRQ== + dependencies: + "@react-native-community/cli-clean" "14.0.0-alpha.9" + "@react-native-community/cli-config" "14.0.0-alpha.9" + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.9" + "@react-native-community/cli-doctor" "14.0.0-alpha.9" + "@react-native-community/cli-server-api" "14.0.0-alpha.9" + "@react-native-community/cli-tools" "14.0.0-alpha.9" + "@react-native-community/cli-types" "14.0.0-alpha.9" chalk "^4.1.2" commander "^9.4.1" deepmerge "^4.3.0" From 9ba600c066fe9667dbc5b412ed202ed30bed408a Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 24 Jun 2024 08:08:11 -0700 Subject: [PATCH 066/968] chore: remove lockfile from Helloworld (#45135) Summary: Accidentally shipped, removing. ## Changelog: [Internal] [INTERNAL] [ADDED] - Conditionals for iOS only code in RCTDeviceInfo.mm Pull Request resolved: https://github.com/facebook/react-native/pull/45176 Test Plan: CI Green Reviewed By: christophpurrer Differential Revision: D59106103 Pulled By: cipolleschi fbshipit-source-id: 594a9d2451024baddfbc9cd3bc1ccfb8829fc31c --- Gemfile.lock | 2 +- .../React/CoreModules/RCTDeviceInfo.mm | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9ec5569aaf6e63..7801444199f7db 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,7 +90,7 @@ PLATFORMS DEPENDENCIES activesupport (>= 6.1.7.5, < 7.1.0) - cocoapods (~> 1.13) + cocoapods (~> 1.13, != 1.15.1, != 1.15.0) RUBY VERSION ruby 3.2.0p0 diff --git a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm index 245a392e854630..b72352f5453f3b 100644 --- a/packages/react-native/React/CoreModules/RCTDeviceInfo.mm +++ b/packages/react-native/React/CoreModules/RCTDeviceInfo.mm @@ -52,8 +52,6 @@ - (void)initialize name:RCTAccessibilityManagerDidUpdateMultiplierNotification object:[_moduleRegistry moduleForName:"AccessibilityManager"]]; - _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; - _currentInterfaceDimensions = [self _exportedDimensions]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -70,10 +68,16 @@ - (void)initialize selector:@selector(interfaceFrameDidChange) name:RCTWindowFrameDidChangeNotification object:nil]; + +#if TARGET_OS_IOS + + _currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interfaceFrameDidChange) name:UIDeviceOrientationDidChangeNotification object:nil]; +#endif // TODO T175901725 - Registering the RCTDeviceInfo module to the notification is a short-term fix to unblock 0.73 // The actual behavior should be that the module is properly registered in the TurboModule/Bridge infrastructure @@ -109,7 +113,9 @@ - (void)_cleanupObservers [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil]; +#if TARGET_OS_IOS [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; +#endif } static BOOL RCTIsIPhoneNotched() @@ -117,12 +123,14 @@ static BOOL RCTIsIPhoneNotched() static BOOL isIPhoneNotched = NO; static dispatch_once_t onceToken; +#if TARGET_OS_IOS dispatch_once(&onceToken, ^{ RCTAssertMainQueue(); // 20pt is the top safeArea value in non-notched devices isIPhoneNotched = RCTSharedApplication().keyWindow.safeAreaInsets.top > 20; }); +#endif return isIPhoneNotched; } @@ -206,6 +214,7 @@ - (void)interfaceOrientationDidChange - (void)_interfaceOrientationDidChange { +#if TARGET_OS_IOS UIApplication *application = RCTSharedApplication(); UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation; @@ -235,6 +244,7 @@ - (void)_interfaceOrientationDidChange _isFullscreen = isRunningInFullScreen; #pragma clang diagnostic pop } +#endif } - (void)interfaceFrameDidChange From 5532e511afdbb60884c7a296cf2b51902dfd6f32 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Fri, 28 Jun 2024 06:35:32 -0700 Subject: [PATCH 137/968] Systrace instrumentation for prop parsing (#45153) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45153 This diff adds more Systrace logging to the component create/update flow. Changelog: [Internal] Reviewed By: javache Differential Revision: D56706472 fbshipit-source-id: c94445693694dfee43f1d46881fc1e18a507eb5e --- .../core/ConcreteComponentDescriptor.h | 18 +++++++++++++----- .../react/renderer/core/RawProps.cpp | 3 +++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index b7a4e0bdd0c8dc..d7fa46d5e72e75 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -8,7 +8,9 @@ #pragma once #include +#include +#include #include #include #include @@ -65,6 +67,7 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { std::shared_ptr createShadowNode( const ShadowNodeFragment& fragment, const ShadowNodeFamily::Shared& family) const override { + SystraceSection s("ConcreteComponentDescriptor::createShadowNode"); auto shadowNode = std::make_shared(fragment, family, getTraits()); @@ -96,6 +99,7 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { const PropsParserContext& context, const Props::Shared& props, RawProps rawProps) const override { + SystraceSection s1("ConcreteComponentDescriptor::cloneProps"); // Optimization: // Quite often nodes are constructed with default/empty props: the base // `props` object is `null` (there no base because it's not cloning) and the @@ -111,18 +115,18 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { rawProps.parse(rawPropsParser_); - // Call old-style constructor - auto shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); - // Use the new-style iterator // Note that we just check if `Props` has this flag set, no matter // the type of ShadowNode; it acts as the single global flag. if (CoreFeatures::enablePropIteratorSetter) { + auto shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); #ifdef ANDROID const auto& dynamic = shadowNodeProps->rawProps; #else const auto& dynamic = static_cast(rawProps); #endif + SystraceSection s2( + "ConcreteComponentDescriptor::cloneProps - iterateOverValues"); for (const auto& pair : dynamic.items()) { const auto& name = pair.first.getString(); shadowNodeProps->setProp( @@ -131,9 +135,13 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { name.c_str(), RawValue(pair.second)); } + return shadowNodeProps; + } else { + SystraceSection s3( + "ConcreteComponentDescriptor::cloneProps - old-style constructor"); + // Call old-style constructor + return ShadowNodeT::Props(context, rawProps, props); } - - return shadowNodeProps; }; virtual State::Shared createInitialState( diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp index 49f288e358d878..3eeffa3f9f4f0a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.cpp @@ -7,6 +7,7 @@ #include "RawProps.h" +#include #include #include #include @@ -161,6 +162,7 @@ RawProps& RawProps::operator=(const RawProps& other) noexcept { } void RawProps::parse(const RawPropsParser& parser) noexcept { + SystraceSection s("RawProps::parse"); react_native_assert(parser_ == nullptr && "A parser was already assigned."); parser_ = &parser; parser.preparse(*this); @@ -172,6 +174,7 @@ void RawProps::parse(const RawPropsParser& parser) noexcept { * will be removed as soon Android implementation does not need it. */ RawProps::operator folly::dynamic() const noexcept { + SystraceSection s("RawProps::operator folly::dynamic()"); switch (mode_) { case Mode::Empty: return folly::dynamic::object(); From 9833338b5d242db1e01995f94419cc04550de235 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 28 Jun 2024 06:44:52 -0700 Subject: [PATCH 138/968] Support @//xplat/mode/no-react-fusebox (#45216) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45216 Buck modifications supporting the internal React Native DevTools (Fusebox) rollout. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D59154105 fbshipit-source-id: ba22a7f2f64d199b3e4e5a83ffa5036ae36b1a3b --- .../ReactCommon/jsinspector-modern/InspectorFlags.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp index b134f799e7eace..d71944064e5964 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp @@ -25,12 +25,20 @@ void InspectorFlags::dangerouslyResetFlags() { *this = InspectorFlags{}; } +#if defined(REACT_NATIVE_FORCE_ENABLE_FUSEBOX) && \ + defined(REACT_NATIVE_FORCE_DISABLE_FUSEBOX) +#error \ + "Cannot define both REACT_NATIVE_FORCE_ENABLE_FUSEBOX and REACT_NATIVE_FORCE_DISABLE_FUSEBOX" +#endif + const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged() const { InspectorFlags::Values newValues = { .fuseboxEnabled = #if defined(REACT_NATIVE_FORCE_ENABLE_FUSEBOX) true, +#elif defined(REACT_NATIVE_FORCE_DISABLE_FUSEBOX) + false, #elif defined(HERMES_ENABLE_DEBUGGER) && \ defined(REACT_NATIVE_ENABLE_FUSEBOX_DEBUG) true, From ffc16fc18bcc44d1e98d66dbbe56fb726962fb72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Knutzen?= <2263015+hakonk@users.noreply.github.com> Date: Fri, 28 Jun 2024 07:37:45 -0700 Subject: [PATCH 139/968] Fix data races in `RCTImageLoader` and `RCTNetworkTask` with shared atomic counters (#45114) Summary: In order to fix the data races described in https://github.com/facebook/react-native/issues/44715, I propose a simple solution by leveraging shared counter functions wherein `std::atomic` is the backing for the integer values. ## Changelog: [iOS] [Fixed] - Implement shared atomic counters and replace static integers in `RCTImageLoader` and `RCTNetworkTask` that were accessed concurrently, which in some cases lead to data races. Pull Request resolved: https://github.com/facebook/react-native/pull/45114 Test Plan: Added unit tests for the counters in `RCTSharedCounterTests`. Reviewed By: cipolleschi Differential Revision: D59155076 Pulled By: javache fbshipit-source-id: f73afce6a816ad3226ed8c123cb2ccf4183549a0 --- packages/react-native/Libraries/Image/RCTImageLoader.mm | 8 ++------ packages/react-native/Libraries/Network/RCTNetworkTask.mm | 7 ++++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/react-native/Libraries/Image/RCTImageLoader.mm b/packages/react-native/Libraries/Image/RCTImageLoader.mm index 46b267ccccaa42..dac4ecc5fe40ac 100644 --- a/packages/react-native/Libraries/Image/RCTImageLoader.mm +++ b/packages/react-native/Libraries/Image/RCTImageLoader.mm @@ -32,11 +32,7 @@ static NSInteger RCTImageBytesForImage(UIImage *image) return image.images ? image.images.count * singleImageBytes : singleImageBytes; } -static uint64_t getNextImageRequestCount(void) -{ - static uint64_t requestCounter = 0; - return requestCounter++; -} +static auto currentRequestCount = std::atomic(0); static NSError *addResponseHeadersToError(NSError *originalError, NSHTTPURLResponse *response) { @@ -510,7 +506,7 @@ - (RCTImageURLLoaderRequest *)_loadImageOrDataWithURLRequest:(NSURLRequest *)req auto cancelled = std::make_shared>(0); __block dispatch_block_t cancelLoad = nil; __block NSLock *cancelLoadLock = [NSLock new]; - NSString *requestId = [NSString stringWithFormat:@"%@-%llu", [[NSUUID UUID] UUIDString], getNextImageRequestCount()]; + NSString *requestId = [NSString stringWithFormat:@"%@-%llu", [[NSUUID UUID] UUIDString], currentRequestCount++]; void (^completionHandler)(NSError *, id, id, NSURLResponse *) = ^(NSError *error, id imageOrData, id imageMetadata, NSURLResponse *response) { diff --git a/packages/react-native/Libraries/Network/RCTNetworkTask.mm b/packages/react-native/Libraries/Network/RCTNetworkTask.mm index 96a7ded6c9c8f4..c89e2b7b350aec 100644 --- a/packages/react-native/Libraries/Network/RCTNetworkTask.mm +++ b/packages/react-native/Libraries/Network/RCTNetworkTask.mm @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +#import #import #import @@ -20,6 +21,8 @@ @implementation RCTNetworkTask { RCTNetworkTask *_selfReference; } +static auto currentRequestId = std::atomic(0); + - (instancetype)initWithRequest:(NSURLRequest *)request handler:(id)handler callbackQueue:(dispatch_queue_t)callbackQueue @@ -28,10 +31,8 @@ - (instancetype)initWithRequest:(NSURLRequest *)request RCTAssertParam(handler); RCTAssertParam(callbackQueue); - static NSUInteger requestID = 0; - if ((self = [super init])) { - _requestID = @(requestID++); + _requestID = @(currentRequestId++); _request = request; _handler = handler; _callbackQueue = callbackQueue; From 9269429bb955d47088793a2e32454fddb712152b Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Fri, 28 Jun 2024 07:48:10 -0700 Subject: [PATCH 140/968] remove @react-native-community dependencies (#44928) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44928 The react-native-community/ dependencies aren't being explicitly included as part of the Framworks (RFC-0759) work. Changelog: [General][Breaking] react-native isn't dependend on react-native-community/* WARNING: Do not commit until we've cut 0.75, this goes in the 0.76 release only otherwise it'll break `npx react-native@latest init`. Reviewed By: cortinico Differential Revision: D58528447 fbshipit-source-id: f238e621c47df9e28b2e18f4137eb08e525052f6 --- packages/react-native/package.json | 3 - yarn.lock | 207 +---------------------------- 2 files changed, 3 insertions(+), 207 deletions(-) diff --git a/packages/react-native/package.json b/packages/react-native/package.json index d02ef0383cd13a..cb2f7119fb51b8 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -109,9 +109,6 @@ }, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "14.0.0-alpha.11", - "@react-native-community/cli-platform-android": "14.0.0-alpha.11", - "@react-native-community/cli-platform-ios": "14.0.0-alpha.11", "@react-native/assets-registry": "0.76.0-main", "@react-native/codegen": "0.76.0-main", "@react-native/community-cli-plugin": "0.76.0-main", diff --git a/yarn.lock b/yarn.lock index 642a83ec092782..7f64e72ee69e36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2619,28 +2619,6 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" -"@react-native-community/cli-clean@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.11.tgz#6b7b95533ec9483562e33d2aae4c0501d4fa41c1" - integrity sha512-pGhrL7xncBv6ciE6vybJHCRAz5c+ejchEdtIcuMBk3GDSP+cWh9A8jwwezMo/6zKDh1FMWSN7KxXFL0fr11Eyw== - dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.11" - chalk "^4.1.2" - execa "^5.0.0" - fast-glob "^3.3.2" - -"@react-native-community/cli-config@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.11.tgz#44605edc66f4fb7f65e7c9aeb71ed4c4a54e3abd" - integrity sha512-6De3iEH71LnEPUTQZXORnl8J5t1p3Lsp1iweFf5oaHdYlBPqPLt2pGZxtSc09oNIOdtmYW9RHm14OM6/mJm/xA== - dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.11" - chalk "^4.1.2" - cosmiconfig "^9.0.0" - deepmerge "^4.3.0" - fast-glob "^3.3.2" - joi "^17.2.1" - "@react-native-community/cli-config@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-13.6.4.tgz#3004c7bca55cb384b3a99c38c1a48dad24533237" @@ -2660,52 +2638,6 @@ dependencies: serve-static "^1.13.1" -"@react-native-community/cli-doctor@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.11.tgz#1ee0910be05113c920027bd042c3a658908ec203" - integrity sha512-i+awVrt964+MxneGuw/6GXdzm+MJtFyS9Jpuc87HApLxOY9AC4pVjFSi6tUUjC5SlORN3zuMo87DmzgQuqBR+w== - dependencies: - "@react-native-community/cli-config" "14.0.0-alpha.11" - "@react-native-community/cli-platform-android" "14.0.0-alpha.11" - "@react-native-community/cli-platform-apple" "14.0.0-alpha.11" - "@react-native-community/cli-platform-ios" "14.0.0-alpha.11" - "@react-native-community/cli-tools" "14.0.0-alpha.11" - chalk "^4.1.2" - command-exists "^1.2.8" - deepmerge "^4.3.0" - envinfo "^7.10.0" - execa "^5.0.0" - node-stream-zip "^1.9.1" - ora "^5.4.1" - semver "^7.5.2" - strip-ansi "^5.2.0" - wcwidth "^1.0.1" - yaml "^2.2.1" - -"@react-native-community/cli-platform-android@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.11.tgz#29bb5ee9e55eea0199d824335f54f7adc0cf50f5" - integrity sha512-DIKku0qcJ2pB75YTqBCHdJiQaMtFBkp8Hhloq57OpNMspDqLTuWjDDbcCtqD7LQb9MGpaf+b6FWUQFw9BNtVkQ== - dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.11" - chalk "^4.1.2" - execa "^5.0.0" - fast-glob "^3.3.2" - fast-xml-parser "^4.2.4" - logkitty "^0.7.1" - -"@react-native-community/cli-platform-apple@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.11.tgz#7085a08b2f71f78291722196834e1e47a5d74ae5" - integrity sha512-tNKKte5K/tNNHy0Pxy/vJaSUw0jS7Cuo+F7tTT2ZgDmarp7IlfWnfVMKCtlSC3rR8ZCktmgPgteTf9SicSldxg== - dependencies: - "@react-native-community/cli-tools" "14.0.0-alpha.11" - chalk "^4.1.2" - execa "^5.0.0" - fast-glob "^3.3.2" - fast-xml-parser "^4.2.4" - ora "^5.4.1" - "@react-native-community/cli-platform-apple@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.4.tgz#4912eaf519800a957745192718822b94655c8119" @@ -2718,13 +2650,6 @@ fast-xml-parser "^4.0.12" ora "^5.4.1" -"@react-native-community/cli-platform-ios@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.11.tgz#d446583ebf1eeaf0066ddb649e28b345aa32149e" - integrity sha512-coHbTcymVsrOBYvch0M7JtKIRlfCc2GwXs7JEyG54CUKTfhLGDgWWTGOdAwWxiF4cDbj46Qr/4Es2AGJbmTBGA== - dependencies: - "@react-native-community/cli-platform-apple" "14.0.0-alpha.11" - "@react-native-community/cli-server-api@14.0.0-alpha.11": version "14.0.0-alpha.11" resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.11.tgz#505163e11d3a30ebc874950956f72f5b3b6c5fc1" @@ -2773,13 +2698,6 @@ shell-quote "^1.7.3" sudo-prompt "^9.0.0" -"@react-native-community/cli-types@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.11.tgz#d8ca6352659bc44d569bae3fb321ed52502168f0" - integrity sha512-jujAIipCmgc0mHXh9G+6cVT8wPaw1m8L3OSpajNKuARtjva+jGNYmx4itRP05c+SgFqN4eASEV563nNfI4Ja/g== - dependencies: - joi "^17.2.1" - "@react-native-community/cli-types@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-13.6.4.tgz#e499a3691ee597aa4b93196ff182a4782fae7afb" @@ -2787,28 +2705,6 @@ dependencies: joi "^17.2.1" -"@react-native-community/cli@14.0.0-alpha.11": - version "14.0.0-alpha.11" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.11.tgz#e2fe662a68f0597b3ab738240c997301ce11b404" - integrity sha512-V32VYYa1dZJWt7ohxCYQIRa7DVGAXpw3RnP36BSfm4rqv1DD8ymDLM71PVZHoeHG6UWyNABXbTHTY+FOUYjKlQ== - dependencies: - "@react-native-community/cli-clean" "14.0.0-alpha.11" - "@react-native-community/cli-config" "14.0.0-alpha.11" - "@react-native-community/cli-debugger-ui" "14.0.0-alpha.11" - "@react-native-community/cli-doctor" "14.0.0-alpha.11" - "@react-native-community/cli-server-api" "14.0.0-alpha.11" - "@react-native-community/cli-tools" "14.0.0-alpha.11" - "@react-native-community/cli-types" "14.0.0-alpha.11" - chalk "^4.1.2" - commander "^9.4.1" - deepmerge "^4.3.0" - execa "^5.0.0" - find-up "^5.0.0" - fs-extra "^8.1.0" - graceful-fs "^4.1.3" - prompts "^2.4.2" - semver "^7.5.2" - "@rnx-kit/rn-changelog-generator@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@rnx-kit/rn-changelog-generator/-/rn-changelog-generator-0.4.0.tgz#637d87bcf8de6e87599930ed88d9375010277660" @@ -3388,15 +3284,6 @@ ansi-escapes@^6.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f" integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig== -ansi-fragments@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" - integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== - dependencies: - colorette "^1.0.7" - slice-ansi "^2.0.0" - strip-ansi "^5.0.0" - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -3556,11 +3443,6 @@ ast-types@0.15.2: dependencies: tslib "^2.0.1" -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" @@ -4221,11 +4103,6 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.0.7: - version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" - integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== - colorette@^2.0.20: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" @@ -4263,11 +4140,6 @@ commander@^4.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^9.4.1: - version "9.4.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" - integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -4372,16 +4244,6 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: js-yaml "^3.13.0" parse-json "^4.0.0" -cosmiconfig@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" - integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== - dependencies: - env-paths "^2.2.1" - import-fresh "^3.3.0" - js-yaml "^4.1.0" - parse-json "^5.2.0" - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4456,11 +4318,6 @@ data-uri-to-buffer@^6.0.1: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz#540bd4c8753a25ee129035aebdedf63b078703c7" integrity sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg== -dayjs@^1.8.15: - version "1.8.15" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.15.tgz#7121bc04e6a7f2621ed6db566be4a8aaf8c3913e" - integrity sha512-HYHCI1nohG52B45vCQg8Re3hNDZbMroWPkhz50yaX7Lu0ATyjGsTdoYZBpjED9ar6chqTx2dmSmM8A51mojnAg== - debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4665,16 +4522,6 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -env-paths@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -envinfo@^7.10.0: - version "7.11.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f" - integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg== - error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -5162,13 +5009,6 @@ fast-xml-parser@^4.0.12: dependencies: strnum "^1.0.5" -fast-xml-parser@^4.2.4: - version "4.2.7" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz#871f2ca299dc4334b29f8da3658c164e68395167" - integrity sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig== - dependencies: - strnum "^1.0.5" - fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -5604,7 +5444,7 @@ got@^11.1.4: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -5892,14 +5732,6 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-fresh@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -6042,11 +5874,6 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -7089,15 +6916,6 @@ log-update@^6.0.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" -logkitty@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" - integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== - dependencies: - ansi-fragments "^0.2.1" - dayjs "^1.8.15" - yargs "^15.1.0" - long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -7568,11 +7386,6 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== -node-stream-zip@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.9.1.tgz#66d210204da7c60e2d6d685eb21a11d016981fd0" - integrity sha512-7/Xs9gkuYF0WBimz5OrSc6UVKLDTxvBG2yLGtEK8PSx94d86o/6iQLvIe/140ATz35JDqHKWIxh3GcA3u5hB0w== - "normalize-package-data@~1.0.1 || ^2.0.0 || ^3.0.0": version "3.0.3" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" @@ -8058,7 +7871,7 @@ promise@^8.3.0: dependencies: asap "~2.0.6" -prompts@^2.0.1, prompts@^2.4.2: +prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -8690,15 +8503,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" @@ -8938,7 +8742,7 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.2.0: +strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== @@ -9579,11 +9383,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" - integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== - yaml@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.1.tgz#2e57e0b5e995292c25c75d2658f0664765210eed" From dba25fa96643bdadc9bad85b20d35e106885f8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Knutzen?= <2263015+hakonk@users.noreply.github.com> Date: Fri, 28 Jun 2024 08:11:34 -0700 Subject: [PATCH 141/968] Data race related to reading/writing to `AllocationTestModule.valid` (#45191) Summary: The fix entails making `AllocationTestModule.valid` an Objective-C atomic property and funneling access to the ivar via the synthesized property getter and setter. While the data race was present in test code, it would make it more difficult to spot more severe data races with the TSan. Also, getting rid of a data race is always good. ## Changelog: [iOS][Fixed] - Data race related to access of `AllocationTestModule.valid` Pull Request resolved: https://github.com/facebook/react-native/pull/45191 Test Plan: `RCTAllocationTests` will test the implementation of `AllocationTestModule`. Reviewed By: christophpurrer Differential Revision: D59155083 Pulled By: javache fbshipit-source-id: e3217cffd0801377a25f04bf8ed0b4e2d1d88498 --- packages/rn-tester/RNTesterUnitTests/RCTAllocationTests.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rn-tester/RNTesterUnitTests/RCTAllocationTests.m b/packages/rn-tester/RNTesterUnitTests/RCTAllocationTests.m index ea66d188978f9a..ed1f3a7e5da1ea 100644 --- a/packages/rn-tester/RNTesterUnitTests/RCTAllocationTests.m +++ b/packages/rn-tester/RNTesterUnitTests/RCTAllocationTests.m @@ -16,7 +16,7 @@ @interface AllocationTestModule : NSObject -@property (nonatomic, assign, getter=isValid) BOOL valid; +@property (atomic, assign, getter=isValid) BOOL valid; @end @@ -27,14 +27,14 @@ @implementation AllocationTestModule - (instancetype)init { if ((self = [super init])) { - _valid = YES; + self.valid = YES; } return self; } - (void)invalidate { - _valid = NO; + self.valid = NO; } RCT_EXPORT_METHOD(test From 84a9f5e6c8e3af97e7d084ccb8ffdef44dcc87fb Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Fri, 28 Jun 2024 09:41:02 -0700 Subject: [PATCH 142/968] Add Java Turbo Module Event Emitter example (#44906) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44906 Shows a proof of concept how '*strongly typed Turbo Module scoped*' `EventEmitters` can be used in a Java Turbo Module. ## Changelog: [Android] [Added] - Add Java Turbo Module Event Emitter example Reviewed By: javache Differential Revision: D57530807 fbshipit-source-id: 04261d8885760f0e3b3c8c1931e0d56a5d33a0df --- .../src/parsers/error-utils.js | 4 +-- .../src/parsers/errors.js | 3 -- .../modules/__test_fixtures__/fixtures.js | 2 +- .../module-parser-snapshot-test.js.snap | 6 +--- .../src/parsers/parsers-commons.js | 1 - .../modules/__test_fixtures__/fixtures.js | 2 +- ...script-module-parser-snapshot-test.js.snap | 6 +--- .../ReactAndroid/api/ReactAndroid.api | 1 + .../facebook/react/bridge/BaseJavaModule.java | 8 +++++ .../android/ReactCommon/JavaTurboModule.cpp | 30 +++++++++++++++++++ .../android/ReactCommon/JavaTurboModule.h | 2 ++ .../android/NativeSampleTurboModuleSpec.java | 16 ++++++++++ .../ReactCommon/SampleTurboModuleSpec.cpp | 9 ++++++ .../platform/android/SampleTurboModule.java | 21 ++++++++++++- .../specs/modules/NativeSampleTurboModule.js | 15 +++++++++- .../TurboModule/SampleTurboModuleExample.js | 26 ++++++++++++++++ 16 files changed, 131 insertions(+), 21 deletions(-) diff --git a/packages/react-native-codegen/src/parsers/error-utils.js b/packages/react-native-codegen/src/parsers/error-utils.js index 049920939922bc..29f54d61dcc5ca 100644 --- a/packages/react-native-codegen/src/parsers/error-utils.js +++ b/packages/react-native-codegen/src/parsers/error-utils.js @@ -164,9 +164,8 @@ function throwIfEventEmitterTypeIsUnsupported( parser: Parser, nullable: boolean, untyped: boolean, - cxxOnly: boolean, ) { - if (nullable || untyped || !cxxOnly) { + if (nullable || untyped) { throw new UnsupportedModuleEventEmitterPropertyParserError( nativeModuleName, propertyName, @@ -174,7 +173,6 @@ function throwIfEventEmitterTypeIsUnsupported( parser.language(), nullable, untyped, - cxxOnly, ); } } diff --git a/packages/react-native-codegen/src/parsers/errors.js b/packages/react-native-codegen/src/parsers/errors.js index 101138a7e10f8d..91b9c827b24575 100644 --- a/packages/react-native-codegen/src/parsers/errors.js +++ b/packages/react-native-codegen/src/parsers/errors.js @@ -100,15 +100,12 @@ class UnsupportedModuleEventEmitterPropertyParserError extends ParserError { language: ParserType, nullable: boolean, untyped: boolean, - cxxOnly: boolean, ) { let message = `${language} interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's or non nullable 'EventEmitter's. Further the EventEmitter property `; if (nullable) { message += `'${propertyValue}' must non nullable.`; } else if (untyped) { message += `'${propertyValue}' must have a concrete or void eventType.`; - } else if (!cxxOnly) { - message += `'${propertyValue}' is only supported in C++ Turbo Modules.`; } super(nativeModuleName, propertyValue, message); } diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js index 4b1efc38eedf84..25c692ccd5b7dd 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js @@ -652,7 +652,7 @@ export interface Spec extends TurboModule { +onEvent6: EventEmitter; } -export default TurboModuleRegistry.getEnforcing('SampleTurboModuleCxx'); +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap index 17684eeea4603f..48dbda72558485 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -1531,11 +1531,7 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_EVENT_EM ], 'methods': [] }, - 'moduleName': 'SampleTurboModuleCxx', - 'excludedPlatforms': [ - 'iOS', - 'android' - ] + 'moduleName': 'SampleTurboModule' } } }" diff --git a/packages/react-native-codegen/src/parsers/parsers-commons.js b/packages/react-native-codegen/src/parsers/parsers-commons.js index f012943eade12b..8dd3f24346e5f6 100644 --- a/packages/react-native-codegen/src/parsers/parsers-commons.js +++ b/packages/react-native-codegen/src/parsers/parsers-commons.js @@ -513,7 +513,6 @@ function buildEventEmitterSchema( parser, typeAnnotationNullable, typeAnnotationUntyped, - cxxOnly, ); const eventTypeResolutionStatus = resolveTypeAnnotationFN( typeAnnotation.typeParameters.params[0], diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js index 56a3a87a074113..7faff4f0a695f3 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js @@ -751,7 +751,7 @@ export interface Spec extends TurboModule { readonly onEvent6: EventEmitter; } -export default TurboModuleRegistry.getEnforcing('SampleTurboModuleCxx'); +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index 6eeda94587ba8e..bc7eb2ba00b4e9 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -1731,11 +1731,7 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_EV ], 'methods': [] }, - 'moduleName': 'SampleTurboModuleCxx', - 'excludedPlatforms': [ - 'iOS', - 'android' - ] + 'moduleName': 'SampleTurboModule' } } }" diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 2827d31f901108..3004783bfb31ce 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -543,6 +543,7 @@ public abstract class com/facebook/react/bridge/BaseJavaModule : com/facebook/re public static final field METHOD_TYPE_ASYNC Ljava/lang/String; public static final field METHOD_TYPE_PROMISE Ljava/lang/String; public static final field METHOD_TYPE_SYNC Ljava/lang/String; + protected field mEventEmitterCallback Lcom/facebook/react/bridge/CxxCallbackImpl; public fun ()V public fun (Lcom/facebook/react/bridge/ReactApplicationContext;)V public fun canOverrideExistingModule ()Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java index 0d2f21e209be92..c9b635eb36f321 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/BaseJavaModule.java @@ -13,6 +13,7 @@ import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.ThreadConfined; +import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; import com.facebook.react.common.annotations.StableReactNativeAPI; @@ -54,6 +55,8 @@ public abstract class BaseJavaModule implements NativeModule { public static final String METHOD_TYPE_PROMISE = "promise"; public static final String METHOD_TYPE_SYNC = "sync"; + protected @Nullable CxxCallbackImpl mEventEmitterCallback; + private final @Nullable ReactApplicationContext mReactApplicationContext; public BaseJavaModule() { @@ -129,4 +132,9 @@ protected final ReactApplicationContext getReactApplicationContext() { } return null; } + + @DoNotStrip + private final void setEventEmitterCallback(CxxCallbackImpl eventEmitterCallback) { + mEventEmitterCallback = eventEmitterCallback; + } } diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp index 1b4d747e98f7a6..1fcf29ac86f5c6 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp @@ -992,4 +992,34 @@ jsi::Value JavaTurboModule::invokeJavaMethod( } } +void JavaTurboModule::setEventEmitterCallback( + jni::alias_ref jinstance) { + JNIEnv* env = jni::Environment::current(); + auto instance = jinstance.get(); + static jmethodID cachedMethodId = nullptr; + if (cachedMethodId == nullptr) { + jclass cls = env->GetObjectClass(instance); + cachedMethodId = env->GetMethodID( + cls, + "setEventEmitterCallback", + "(Lcom/facebook/react/bridge/CxxCallbackImpl;)V"); + } + + auto eventEmitterLookup = + [&](const std::string& eventName) -> AsyncEventEmitter& { + return static_cast&>( + *eventEmitterMap_[eventName].get()); + }; + + jvalue arg; + arg.l = JCxxCallbackImpl::newObjectCxxArgs([eventEmitterLookup = std::move( + eventEmitterLookup)]( + folly::dynamic args) { + auto eventName = args.at(0).asString(); + auto eventArgs = args.size() > 1 ? args.at(1) : nullptr; + eventEmitterLookup(eventName).emit(std::move(eventArgs)); + }).release(); + env->CallVoidMethod(instance, cachedMethodId, arg); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h index 15a8265645df5c..3a9d542e898b74 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h @@ -51,6 +51,8 @@ class JSI_EXPORT JavaTurboModule : public TurboModule { size_t argCount, jmethodID& cachedMethodID); + void setEventEmitterCallback(jni::alias_ref instance); + private: // instance_ can be of type JTurboModule, or JNativeModule jni::global_ref instance_; diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java index 81a230fccdcc6c..f2104c737ec8bc 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java @@ -40,6 +40,22 @@ public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) { return NAME; } + protected final void emitOnPress() { + mEventEmitterCallback.invoke("onPress"); + } + + protected final void emitOnClick(String value) { + mEventEmitterCallback.invoke("onClick", value); + } + + protected final void emitOnChange(ReadableMap value) { + mEventEmitterCallback.invoke("onChange", value); + } + + protected void emitOnSubmit(ReadableArray value) { + mEventEmitterCallback.invoke("onSubmit", value); + } + protected abstract Map getTypedExportedConstants(); @Override diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp index 72f9d1320b3f74..f5ff8843423308 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp @@ -351,6 +351,15 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI( 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObjectAssert}; methodMap_["promiseAssert"] = MethodMetadata{ 0, __hostFunction_NativeSampleTurboModuleSpecJSI_promiseAssert}; + eventEmitterMap_["onPress"] = + std::make_shared>(); + eventEmitterMap_["onClick"] = + std::make_shared>(); + eventEmitterMap_["onChange"] = + std::make_shared>(); + eventEmitterMap_["onSubmit"] = + std::make_shared>(); + setEventEmitterCallback(params.instance); } std::shared_ptr SampleTurboModuleSpec_ModuleProvider( diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java index a0f3b16e42d10c..f74faf4b4dd1e9 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java @@ -104,7 +104,26 @@ public double getRootTag(double arg) { @Override public void voidFunc() { log("voidFunc", "", ""); - return; + emitOnPress(); + emitOnClick("click"); + { + WritableNativeMap map = new WritableNativeMap(); + map.putInt("a", 1); + map.putString("b", "two"); + emitOnChange(map); + } + { + WritableNativeArray array = new WritableNativeArray(); + WritableNativeMap map = new WritableNativeMap(); + map.putInt("a", 1); + map.putString("b", "two"); + array.pushMap(map); + WritableNativeMap map1 = new WritableNativeMap(); + map1.putInt("a", 3); + map1.putString("b", "four"); + array.pushMap(map1); + emitOnSubmit(array); + } } // This function returns {@link WritableMap} instead of {@link Map} for backward compat with diff --git a/packages/react-native/src/private/specs/modules/NativeSampleTurboModule.js b/packages/react-native/src/private/specs/modules/NativeSampleTurboModule.js index 4c1fab3c4946c1..0cecad05b3dbe1 100644 --- a/packages/react-native/src/private/specs/modules/NativeSampleTurboModule.js +++ b/packages/react-native/src/private/specs/modules/NativeSampleTurboModule.js @@ -12,7 +12,10 @@ import type { RootTag, TurboModule, } from '../../../../Libraries/TurboModule/RCTExport'; -import type {UnsafeObject} from '../../../../Libraries/Types/CodegenTypes'; +import type { + EventEmitter, + UnsafeObject, +} from '../../../../Libraries/Types/CodegenTypes'; import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; @@ -21,7 +24,17 @@ export enum EnumInt { B = 42, } +export type ObjectStruct = { + a: number, + b: string, + c?: ?string, +}; + export interface Spec extends TurboModule { + +onPress: EventEmitter; + +onClick: EventEmitter; + +onChange: EventEmitter; + +onSubmit: EventEmitter; // Exported methods. +getConstants: () => {| const1: boolean, diff --git a/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js b/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js index bcfc81b582cecc..2d590df3907a3d 100644 --- a/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/SampleTurboModuleExample.js @@ -9,6 +9,7 @@ */ import type {RootTag} from 'react-native/Libraries/ReactNative/RootTag'; +import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter'; import styles from './TurboModuleExampleCommon'; import * as React from 'react'; @@ -68,6 +69,7 @@ type ErrorExamples = class SampleTurboModuleExample extends React.Component<{||}, State> { static contextType: React$Context = RootTagContext; + eventSubscriptions: EventSubscription[] = []; state: State = { testResults: {}, @@ -218,6 +220,30 @@ class SampleTurboModuleExample extends React.Component<{||}, State> { 'The JSI bindings for SampleTurboModule are not installed.', ); } + this.eventSubscriptions.push( + NativeSampleTurboModule.onPress(value => console.log('onPress: ()')), + ); + this.eventSubscriptions.push( + NativeSampleTurboModule.onClick(value => + console.log(`onClick: (${value})`), + ), + ); + this.eventSubscriptions.push( + NativeSampleTurboModule.onChange(value => + console.log(`onChange: (${JSON.stringify(value)})`), + ), + ); + this.eventSubscriptions.push( + NativeSampleTurboModule.onSubmit(value => + console.log(`onSubmit: (${JSON.stringify(value)})`), + ), + ); + } + + componentWillUnmount() { + for (const subscription of this.eventSubscriptions) { + subscription.remove(); + } } render(): React.Node { From d6e8c061cd00be0cb6c6a2dc693b4096a4d05ef0 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Fri, 28 Jun 2024 12:05:14 -0700 Subject: [PATCH 143/968] fix: ios Helloworld assumes community cli is present (#45221) Summary: Use the hard-coded config for Helloworld instead of assuming the community cli is there to generate a config, which we can no longer assume. Changelog: [Internal] Pull Request resolved: https://github.com/facebook/react-native/pull/45221 Test Plan: This works in my local environment: ``` bundle exec pod install ``` and ``` ./gradlew generateAutolinkingPackageList ``` Changelog: [Internal] Reviewed By: javache Differential Revision: D59162715 Pulled By: blakef fbshipit-source-id: 95ff2c3929f12ee0ecf468cb80d2df1281eb746e --- .../com/facebook/react/ReactSettingsExtension.kt | 2 +- packages/helloworld/.react-native.config | 1 + packages/helloworld/android/settings.gradle | 3 ++- packages/helloworld/ios/Podfile | 2 +- packages/helloworld/scripts/config.sh | 14 ++++++++++++++ 5 files changed, 19 insertions(+), 3 deletions(-) create mode 100755 packages/helloworld/scripts/config.sh diff --git a/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt index b72f6701f9ea03..11deff4b8c3b65 100644 --- a/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt +++ b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt @@ -46,7 +46,7 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings ) { outputFile.parentFile.mkdirs() val lockFilesChanged = checkAndUpdateLockfiles(lockFiles, outputFolder) - if (lockFilesChanged || outputFile.exists().not()) { + if (lockFilesChanged || outputFile.exists().not() || outputFile.length() != 0L) { ProcessBuilder(command) .directory(workingDirectory) .redirectOutput(ProcessBuilder.Redirect.to(outputFile)) diff --git a/packages/helloworld/.react-native.config b/packages/helloworld/.react-native.config index 767ff13459bb5d..67e1e4e23e30bb 100644 --- a/packages/helloworld/.react-native.config +++ b/packages/helloworld/.react-native.config @@ -2,6 +2,7 @@ "reactNativePath": "REACT_NATIVE_PATH", "reactNativeVersion": "1000.0.0", "root": "HELLOWORLD_PATH", + "dependencies": {}, "platforms": { "ios": {}, "android": {} diff --git a/packages/helloworld/android/settings.gradle b/packages/helloworld/android/settings.gradle index 248883a85f2bc9..68914505a41d88 100644 --- a/packages/helloworld/android/settings.gradle +++ b/packages/helloworld/android/settings.gradle @@ -5,10 +5,11 @@ * LICENSE file in the root directory of this source tree. */ + // Autolinking has now moved into the React Native Gradle Plugin pluginManagement { includeBuild("../../gradle-plugin") } plugins { id("com.facebook.react.settings") } -extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand(["/bin/sh", "./scripts/config.sh"]) } rootProject.name = 'HelloWorld' include ':app' diff --git a/packages/helloworld/ios/Podfile b/packages/helloworld/ios/Podfile index 9cde0ddcf38dd2..cefe3e0d5fc62a 100644 --- a/packages/helloworld/ios/Podfile +++ b/packages/helloworld/ios/Podfile @@ -10,7 +10,7 @@ if linkage != nil end target 'HelloWorld' do - config = use_native_modules! + config = use_native_modules!(['sh', '../scripts/config.sh']) use_react_native!( :path => "../../react-native", diff --git a/packages/helloworld/scripts/config.sh b/packages/helloworld/scripts/config.sh new file mode 100755 index 00000000000000..3886652620d15d --- /dev/null +++ b/packages/helloworld/scripts/config.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set -e + +script_dir=$(dirname "$(readlink -f "$0")") + +HELLOWORLD_PATH=$(realpath ../) +REACT_NATIVE_PATH=$(realpath ../../react-native) + +sed -e "s|HELLOWORLD_PATH|$HELLOWORLD_PATH|g" -e "s|REACT_NATIVE_PATH|$REACT_NATIVE_PATH|g" "$script_dir/../.react-native.config" From ed5f558a6cb5ff597870e7013150113b9460c0dc Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Fri, 28 Jun 2024 13:29:15 -0700 Subject: [PATCH 144/968] Code-generate an optional base class to use for every NativeModule (#45113) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45113 ## Changelog: [iOS][Added] - Code-generate an optional base class to use for every NativeModule Extend RN Code-gen to generate a NativeModule base class for each ObjC Turbo Modules. Its usage is not mandatory now, but would become for future features to add A practial first step would be to migrate https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h#L157-L160 from the `protocol` to the default `interface` and then provide a default implementation for it Reviewed By: RSNara Differential Revision: D58907395 fbshipit-source-id: a6b0ef97a5c7f5bb0c53a4cb6fd83d2e55306953 --- .../GenerateModuleObjCpp-test.js.snap | 192 ++++++++++++++++++ .../modules/GenerateModuleObjCpp/index.js | 5 + .../source/serializeModule.js | 10 +- .../GenerateModuleHObjCpp-test.js.snap | 36 ++++ .../GenerateModuleMm-test.js.snap | 36 ++++ .../RCTNativeSampleTurboModuleSpec.h | 3 + .../RCTNativeSampleTurboModuleSpec.mm | 3 + .../ios/ReactCommon/RCTSampleTurboModule.h | 2 +- 8 files changed, 285 insertions(+), 2 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap index 6aa2ad226091ba..0f545d88d4a096 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap @@ -42,6 +42,10 @@ exports[`GenerateModuleObjCpp can generate a header file NativeModule specs 1`] b:(NSArray *)b; @end + +@interface NativeArrayTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeArrayTurboModule' @@ -58,6 +62,10 @@ namespace facebook::react { - (NSNumber *)getBooleanWithAlias:(BOOL)arg; @end + +@interface NativeBooleanTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeBooleanTurboModule' @@ -74,6 +82,10 @@ namespace facebook::react { - (void)getValueWithCallbackWithAlias:(RCTResponseSenderBlock)c; @end + +@interface NativeCallbackTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeCallbackTurboModule' @@ -130,6 +142,10 @@ namespace JS { - (NSDictionary *)getStateTypeWithEnums:(JS::NativeEnumTurboModule::StateTypeWithEnums &)paramOfTypeWithEnums; @end + +@interface NativeEnumTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeEnumTurboModule' @@ -151,6 +167,10 @@ namespace facebook::react { reject:(RCTPromiseRejectBlock)reject; @end + +@interface NativeNullableTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeNullableTurboModule' @@ -167,6 +187,10 @@ namespace facebook::react { - (NSNumber *)getNumberWithAlias:(double)arg; @end + +@interface NativeNumberTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeNumberTurboModule' @@ -336,6 +360,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeObjectTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeObjectTurboModule' @@ -468,6 +496,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeOptionalObjectTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeOptionalObjectTurboModule' @@ -534,6 +566,10 @@ namespace JS { value2:(JS::NativePartialAnnotationTurboModule::SpecGetPartialPartialValue2 &)value2; @end + +@interface NativePartialAnnotationTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativePartialAnnotationTurboModule' @@ -554,6 +590,10 @@ namespace facebook::react { reject:(RCTPromiseRejectBlock)reject; @end + +@interface NativePromiseTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativePromiseTurboModule' @@ -644,6 +684,10 @@ getValuegetValuegetValuegetValuegetValuey:(NSString *)getValuegetValuegetValuege - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -732,6 +776,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleArraysSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleArrays' @@ -822,6 +870,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleNullableSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleNullable' @@ -912,6 +964,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleNullableAndOptionalSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleNullableAndOptional' @@ -1002,6 +1058,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleOptionalSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleOptional' @@ -1018,6 +1078,10 @@ namespace facebook::react { - (NSString *)getStringWithAlias:(NSString *)arg; @end + +@interface NativeStringTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeStringTurboModule' @@ -1394,6 +1458,10 @@ NS_ASSUME_NONNULL_BEGIN b:(NSArray *)b; @end + +@interface NativeArrayTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeArrayTurboModule' @@ -1410,6 +1478,10 @@ namespace facebook::react { - (NSNumber *)getBooleanWithAlias:(BOOL)arg; @end + +@interface NativeBooleanTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeBooleanTurboModule' @@ -1426,6 +1498,10 @@ namespace facebook::react { - (void)getValueWithCallbackWithAlias:(RCTResponseSenderBlock)c; @end + +@interface NativeCallbackTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeCallbackTurboModule' @@ -1482,6 +1558,10 @@ namespace JS { - (NSDictionary *)getStateTypeWithEnums:(JS::NativeEnumTurboModule::StateTypeWithEnums &)paramOfTypeWithEnums; @end + +@interface NativeEnumTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeEnumTurboModule' @@ -1503,6 +1583,10 @@ namespace facebook::react { reject:(RCTPromiseRejectBlock)reject; @end + +@interface NativeNullableTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeNullableTurboModule' @@ -1519,6 +1603,10 @@ namespace facebook::react { - (NSNumber *)getNumberWithAlias:(double)arg; @end + +@interface NativeNumberTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeNumberTurboModule' @@ -1688,6 +1776,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeObjectTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeObjectTurboModule' @@ -1820,6 +1912,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeOptionalObjectTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeOptionalObjectTurboModule' @@ -1886,6 +1982,10 @@ namespace JS { value2:(JS::NativePartialAnnotationTurboModule::SpecGetPartialPartialValue2 &)value2; @end + +@interface NativePartialAnnotationTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativePartialAnnotationTurboModule' @@ -1906,6 +2006,10 @@ namespace facebook::react { reject:(RCTPromiseRejectBlock)reject; @end + +@interface NativePromiseTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativePromiseTurboModule' @@ -1996,6 +2100,10 @@ getValuegetValuegetValuegetValuegetValuey:(NSString *)getValuegetValuegetValuege - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -2084,6 +2192,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleArraysSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleArrays' @@ -2174,6 +2286,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleNullableSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleNullable' @@ -2264,6 +2380,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleNullableAndOptionalSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleNullableAndOptional' @@ -2354,6 +2474,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleOptionalSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModuleOptional' @@ -2370,6 +2494,10 @@ namespace facebook::react { - (NSString *)getStringWithAlias:(NSString *)arg; @end + +@interface NativeStringTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeStringTurboModule' @@ -2720,6 +2848,10 @@ exports[`GenerateModuleObjCpp can generate an implementation file NativeModule s #import \\"RNCodegenModuleFixtures.h\\" +@implementation NativeArrayTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -2748,6 +2880,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeBooleanTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeBooleanTurboModuleSpecJSI_getBoolean(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -2769,6 +2905,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeCallbackTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -2789,6 +2929,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeEnumTurboModuleSpecBase +@end + @implementation RCTCxxConvert (NativeEnumTurboModule_StateType) + (RCTManagedPointer *)JS_NativeEnumTurboModule_StateType:(id)json { @@ -2850,6 +2994,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeNullableTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -2899,6 +3047,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeNumberTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeNumberTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -2919,6 +3071,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeObjectTurboModuleSpecBase +@end + @implementation RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectAE) + (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectAE:(id)json { @@ -2973,6 +3129,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeOptionalObjectTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeOptionalObjectTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -2986,6 +3146,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativePartialAnnotationTurboModuleSpecBase +@end + @implementation RCTCxxConvert (NativePartialAnnotationTurboModule_SpecGetSomeObjFromPartialSomeObjValue) + (RCTManagedPointer *)JS_NativePartialAnnotationTurboModule_SpecGetSomeObjFromPartialSomeObjValue:(id)json { @@ -3040,6 +3204,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativePromiseTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -3060,6 +3228,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeSampleTurboModuleSpecBase +@end + @implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetObjectShapeArg) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetObjectShapeArg:(id)json { @@ -3170,6 +3342,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeSampleTurboModuleArraysSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -3267,6 +3443,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeSampleTurboModuleNullableSpecBase +@end + @implementation RCTCxxConvert (NativeSampleTurboModuleNullable_SpecGetObjectShapeArg) + (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:(id)json { @@ -3376,6 +3556,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeSampleTurboModuleNullableAndOptionalSpecBase +@end + @implementation RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg) + (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:(id)json { @@ -3485,6 +3669,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeSampleTurboModuleOptionalSpecBase +@end + @implementation RCTCxxConvert (NativeSampleTurboModuleOptional_SpecGetObjectShapeArg) + (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:(id)json { @@ -3595,6 +3783,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeStringTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeStringTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js index 297cc738ded838..e1a8d02cf36f17 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js @@ -35,6 +35,10 @@ const ModuleDeclarationTemplate = ({ ${protocolMethods} @end + +@interface ${hasteModuleName}SpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module '${hasteModuleName}' @@ -199,6 +203,7 @@ module.exports = { serializeModuleSource( hasteModuleName, generatedStructs, + hasteModuleName, methodSerializations.filter( ({selector}) => selector !== '@selector(constantsToExport)', ), diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js index 62cc5e204ff088..f4760f2f7f3cb6 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js @@ -19,12 +19,18 @@ import type {Struct} from '../StructCollector'; const ModuleTemplate = ({ hasteModuleName, structs, + moduleName, methodSerializationOutputs, }: $ReadOnly<{ hasteModuleName: string, structs: $ReadOnlyArray, + moduleName: string, methodSerializationOutputs: $ReadOnlyArray, -}>) => `${structs +}>) => ` +@implementation ${hasteModuleName}SpecBase +@end + +${structs .map(struct => RCTCxxConvertCategoryTemplate({hasteModuleName, structName: struct.name}), ) @@ -105,11 +111,13 @@ const MethodMapEntryTemplate = ({ function serializeModuleSource( hasteModuleName: string, structs: $ReadOnlyArray, + moduleName: string, methodSerializationOutputs: $ReadOnlyArray, ): string { return ModuleTemplate({ hasteModuleName, structs: structs.filter(({context}) => context !== 'CONSTANTS'), + moduleName, methodSerializationOutputs, }); } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap index d65ff73ffffe6a..994c04389b79fb 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap @@ -40,6 +40,10 @@ Map { @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -206,6 +210,10 @@ namespace JS { - (NSArray> * _Nullable)getNullableArray; @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -401,6 +409,10 @@ Map { @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -522,6 +534,10 @@ namespace JS { - (void)cropImage:(JS::AliasTurboModule::Options &)cropData; @end + +@interface AliasTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'AliasTurboModule' @@ -660,6 +676,10 @@ namespace JS { reject:(RCTPromiseRejectBlock)reject; @end + +@interface NativeCameraRollManagerSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeCameraRollManager' @@ -725,6 +745,10 @@ namespace JS { - (void)dismissRedbox; @end + +@interface NativeExceptionsManagerSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeExceptionsManager' @@ -929,6 +953,10 @@ namespace JS { - (facebook::react::ModuleConstants)getConstants; @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -996,6 +1024,10 @@ Map { - (void)voidFunc; @end + +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule' @@ -1011,6 +1043,10 @@ namespace facebook::react { - (void)voidFunc; @end + +@interface NativeSampleTurboModule2SpecBase : NSObject +@end + namespace facebook::react { /** * ObjC++ class for module 'NativeSampleTurboModule2' diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap index 630f41fbbb2b5a..cce63ca537aaf3 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap @@ -18,6 +18,10 @@ Map { #import \\"SampleWithUppercaseName.h\\" +@implementation NativeSampleTurboModuleSpecBase +@end + + namespace facebook::react { @@ -47,6 +51,10 @@ Map { #import \\"complex_objects.h\\" + +@implementation NativeSampleTurboModuleSpecBase +@end + @implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) + (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json { @@ -182,6 +190,10 @@ Map { #import \\"empty_native_modules.h\\" +@implementation NativeSampleTurboModuleSpecBase +@end + + namespace facebook::react { @@ -211,6 +223,10 @@ Map { #import \\"native_modules_with_type_aliases.h\\" + +@implementation AliasTurboModuleSpecBase +@end + @implementation RCTCxxConvert (AliasTurboModule_OptionsOffset) + (RCTManagedPointer *)JS_AliasTurboModule_OptionsOffset:(id)json { @@ -269,6 +285,10 @@ Map { #import \\"real_module_example.h\\" + +@implementation NativeCameraRollManagerSpecBase +@end + @implementation RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) + (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json { @@ -302,6 +322,10 @@ namespace facebook::react { } } // namespace facebook::react + +@implementation NativeExceptionsManagerSpecBase +@end + @implementation RCTCxxConvert (NativeExceptionsManager_StackFrame) + (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json { @@ -377,6 +401,10 @@ Map { #import \\"simple_native_modules.h\\" +@implementation NativeSampleTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -503,6 +531,10 @@ Map { #import \\"two_modules_different_files.h\\" +@implementation NativeSampleTurboModuleSpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { @@ -517,6 +549,10 @@ namespace facebook::react { } } // namespace facebook::react +@implementation NativeSampleTurboModule2SpecBase +@end + + namespace facebook::react { static facebook::jsi::Value __hostFunction_NativeSampleTurboModule2SpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h index a6f6e3b50fcd22..16bb3080528ec5 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h @@ -43,6 +43,9 @@ @end +@interface NativeSampleTurboModuleSpecBase : NSObject +@end + namespace facebook::react { /** diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm index abbe501887236e..dfb393190e7bea 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm @@ -227,3 +227,6 @@ } } // namespace facebook::react + +@implementation NativeSampleTurboModuleSpecBase +@end diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h index 76e080b0197e28..137047d2cd9a02 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h @@ -13,6 +13,6 @@ * Sample iOS-specific impl of a TurboModule, conforming to the spec protocol. * This class is also 100% compatible with the NativeModule system. */ -@interface RCTSampleTurboModule : NSObject +@interface RCTSampleTurboModule : NativeSampleTurboModuleSpecBase @end From c7988c9c82793b6b41d4c9190a28ce1202410fa0 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Fri, 28 Jun 2024 17:01:45 -0700 Subject: [PATCH 145/968] Back out "remove @react-native-community dependencies" (#45225) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45225 Original commit changeset: f238e621c47d Original Phabricator Diff: D58528447 Changelog: [Internal] Reviewed By: arushikesarwani94 Differential Revision: D59174823 fbshipit-source-id: 3c6d74aea2fd6de7cfee8f1e4389db3d63da3c4d --- packages/react-native/package.json | 3 + yarn.lock | 207 ++++++++++++++++++++++++++++- 2 files changed, 207 insertions(+), 3 deletions(-) diff --git a/packages/react-native/package.json b/packages/react-native/package.json index cb2f7119fb51b8..d02ef0383cd13a 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -109,6 +109,9 @@ }, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "14.0.0-alpha.11", + "@react-native-community/cli-platform-android": "14.0.0-alpha.11", + "@react-native-community/cli-platform-ios": "14.0.0-alpha.11", "@react-native/assets-registry": "0.76.0-main", "@react-native/codegen": "0.76.0-main", "@react-native/community-cli-plugin": "0.76.0-main", diff --git a/yarn.lock b/yarn.lock index 7f64e72ee69e36..642a83ec092782 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2619,6 +2619,28 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" +"@react-native-community/cli-clean@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.11.tgz#6b7b95533ec9483562e33d2aae4c0501d4fa41c1" + integrity sha512-pGhrL7xncBv6ciE6vybJHCRAz5c+ejchEdtIcuMBk3GDSP+cWh9A8jwwezMo/6zKDh1FMWSN7KxXFL0fr11Eyw== + dependencies: + "@react-native-community/cli-tools" "14.0.0-alpha.11" + chalk "^4.1.2" + execa "^5.0.0" + fast-glob "^3.3.2" + +"@react-native-community/cli-config@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.11.tgz#44605edc66f4fb7f65e7c9aeb71ed4c4a54e3abd" + integrity sha512-6De3iEH71LnEPUTQZXORnl8J5t1p3Lsp1iweFf5oaHdYlBPqPLt2pGZxtSc09oNIOdtmYW9RHm14OM6/mJm/xA== + dependencies: + "@react-native-community/cli-tools" "14.0.0-alpha.11" + chalk "^4.1.2" + cosmiconfig "^9.0.0" + deepmerge "^4.3.0" + fast-glob "^3.3.2" + joi "^17.2.1" + "@react-native-community/cli-config@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-13.6.4.tgz#3004c7bca55cb384b3a99c38c1a48dad24533237" @@ -2638,6 +2660,52 @@ dependencies: serve-static "^1.13.1" +"@react-native-community/cli-doctor@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.11.tgz#1ee0910be05113c920027bd042c3a658908ec203" + integrity sha512-i+awVrt964+MxneGuw/6GXdzm+MJtFyS9Jpuc87HApLxOY9AC4pVjFSi6tUUjC5SlORN3zuMo87DmzgQuqBR+w== + dependencies: + "@react-native-community/cli-config" "14.0.0-alpha.11" + "@react-native-community/cli-platform-android" "14.0.0-alpha.11" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.11" + "@react-native-community/cli-platform-ios" "14.0.0-alpha.11" + "@react-native-community/cli-tools" "14.0.0-alpha.11" + chalk "^4.1.2" + command-exists "^1.2.8" + deepmerge "^4.3.0" + envinfo "^7.10.0" + execa "^5.0.0" + node-stream-zip "^1.9.1" + ora "^5.4.1" + semver "^7.5.2" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + yaml "^2.2.1" + +"@react-native-community/cli-platform-android@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.11.tgz#29bb5ee9e55eea0199d824335f54f7adc0cf50f5" + integrity sha512-DIKku0qcJ2pB75YTqBCHdJiQaMtFBkp8Hhloq57OpNMspDqLTuWjDDbcCtqD7LQb9MGpaf+b6FWUQFw9BNtVkQ== + dependencies: + "@react-native-community/cli-tools" "14.0.0-alpha.11" + chalk "^4.1.2" + execa "^5.0.0" + fast-glob "^3.3.2" + fast-xml-parser "^4.2.4" + logkitty "^0.7.1" + +"@react-native-community/cli-platform-apple@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.11.tgz#7085a08b2f71f78291722196834e1e47a5d74ae5" + integrity sha512-tNKKte5K/tNNHy0Pxy/vJaSUw0jS7Cuo+F7tTT2ZgDmarp7IlfWnfVMKCtlSC3rR8ZCktmgPgteTf9SicSldxg== + dependencies: + "@react-native-community/cli-tools" "14.0.0-alpha.11" + chalk "^4.1.2" + execa "^5.0.0" + fast-glob "^3.3.2" + fast-xml-parser "^4.2.4" + ora "^5.4.1" + "@react-native-community/cli-platform-apple@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.4.tgz#4912eaf519800a957745192718822b94655c8119" @@ -2650,6 +2718,13 @@ fast-xml-parser "^4.0.12" ora "^5.4.1" +"@react-native-community/cli-platform-ios@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.11.tgz#d446583ebf1eeaf0066ddb649e28b345aa32149e" + integrity sha512-coHbTcymVsrOBYvch0M7JtKIRlfCc2GwXs7JEyG54CUKTfhLGDgWWTGOdAwWxiF4cDbj46Qr/4Es2AGJbmTBGA== + dependencies: + "@react-native-community/cli-platform-apple" "14.0.0-alpha.11" + "@react-native-community/cli-server-api@14.0.0-alpha.11": version "14.0.0-alpha.11" resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.11.tgz#505163e11d3a30ebc874950956f72f5b3b6c5fc1" @@ -2698,6 +2773,13 @@ shell-quote "^1.7.3" sudo-prompt "^9.0.0" +"@react-native-community/cli-types@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.11.tgz#d8ca6352659bc44d569bae3fb321ed52502168f0" + integrity sha512-jujAIipCmgc0mHXh9G+6cVT8wPaw1m8L3OSpajNKuARtjva+jGNYmx4itRP05c+SgFqN4eASEV563nNfI4Ja/g== + dependencies: + joi "^17.2.1" + "@react-native-community/cli-types@^13.6.4": version "13.6.4" resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-13.6.4.tgz#e499a3691ee597aa4b93196ff182a4782fae7afb" @@ -2705,6 +2787,28 @@ dependencies: joi "^17.2.1" +"@react-native-community/cli@14.0.0-alpha.11": + version "14.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.11.tgz#e2fe662a68f0597b3ab738240c997301ce11b404" + integrity sha512-V32VYYa1dZJWt7ohxCYQIRa7DVGAXpw3RnP36BSfm4rqv1DD8ymDLM71PVZHoeHG6UWyNABXbTHTY+FOUYjKlQ== + dependencies: + "@react-native-community/cli-clean" "14.0.0-alpha.11" + "@react-native-community/cli-config" "14.0.0-alpha.11" + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.11" + "@react-native-community/cli-doctor" "14.0.0-alpha.11" + "@react-native-community/cli-server-api" "14.0.0-alpha.11" + "@react-native-community/cli-tools" "14.0.0-alpha.11" + "@react-native-community/cli-types" "14.0.0-alpha.11" + chalk "^4.1.2" + commander "^9.4.1" + deepmerge "^4.3.0" + execa "^5.0.0" + find-up "^5.0.0" + fs-extra "^8.1.0" + graceful-fs "^4.1.3" + prompts "^2.4.2" + semver "^7.5.2" + "@rnx-kit/rn-changelog-generator@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@rnx-kit/rn-changelog-generator/-/rn-changelog-generator-0.4.0.tgz#637d87bcf8de6e87599930ed88d9375010277660" @@ -3284,6 +3388,15 @@ ansi-escapes@^6.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f" integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig== +ansi-fragments@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" + integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== + dependencies: + colorette "^1.0.7" + slice-ansi "^2.0.0" + strip-ansi "^5.0.0" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -3443,6 +3556,11 @@ ast-types@0.15.2: dependencies: tslib "^2.0.1" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" @@ -4103,6 +4221,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^1.0.7: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + colorette@^2.0.20: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" @@ -4140,6 +4263,11 @@ commander@^4.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commander@^9.4.1: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -4244,6 +4372,16 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: js-yaml "^3.13.0" parse-json "^4.0.0" +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4318,6 +4456,11 @@ data-uri-to-buffer@^6.0.1: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz#540bd4c8753a25ee129035aebdedf63b078703c7" integrity sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg== +dayjs@^1.8.15: + version "1.8.15" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.15.tgz#7121bc04e6a7f2621ed6db566be4a8aaf8c3913e" + integrity sha512-HYHCI1nohG52B45vCQg8Re3hNDZbMroWPkhz50yaX7Lu0ATyjGsTdoYZBpjED9ar6chqTx2dmSmM8A51mojnAg== + debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4522,6 +4665,16 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +envinfo@^7.10.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f" + integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -5009,6 +5162,13 @@ fast-xml-parser@^4.0.12: dependencies: strnum "^1.0.5" +fast-xml-parser@^4.2.4: + version "4.2.7" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz#871f2ca299dc4334b29f8da3658c164e68395167" + integrity sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig== + dependencies: + strnum "^1.0.5" + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -5444,7 +5604,7 @@ got@^11.1.4: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -5732,6 +5892,14 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -5874,6 +6042,11 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -6916,6 +7089,15 @@ log-update@^6.0.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" +logkitty@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" + integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== + dependencies: + ansi-fragments "^0.2.1" + dayjs "^1.8.15" + yargs "^15.1.0" + long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -7386,6 +7568,11 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +node-stream-zip@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.9.1.tgz#66d210204da7c60e2d6d685eb21a11d016981fd0" + integrity sha512-7/Xs9gkuYF0WBimz5OrSc6UVKLDTxvBG2yLGtEK8PSx94d86o/6iQLvIe/140ATz35JDqHKWIxh3GcA3u5hB0w== + "normalize-package-data@~1.0.1 || ^2.0.0 || ^3.0.0": version "3.0.3" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" @@ -7871,7 +8058,7 @@ promise@^8.3.0: dependencies: asap "~2.0.6" -prompts@^2.0.1: +prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -8503,6 +8690,15 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + slice-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" @@ -8742,7 +8938,7 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^5.2.0: +strip-ansi@^5.0.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== @@ -9383,6 +9579,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== + yaml@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.1.tgz#2e57e0b5e995292c25c75d2658f0664765210eed" From cef17ba14f435b966d2ffd9b3660ccf28fe03b6c Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 1 Jul 2024 03:32:14 -0700 Subject: [PATCH 146/968] Fix crash due to missing @JvmStatic to `convertToCase` Summary: Users are reporting that RN 0.75 is crashing due to us attempting to accessing a static method on `AndroidUnicodeUtils.convertToCase` which is not static anymore due to Kotlin conversion. Static access is inside Hermes codebase here: https://github.com/facebook/hermes/blob/f5c867514c71b25212eb3039230e0c095518b532/lib/Platform/Unicode/PlatformUnicodeJava.cpp#L107-L109 Changelog: [Android] [Fixed] - Fix crash due to missing JvmStatic to `convertToCase` Reviewed By: javache Differential Revision: D59218291 fbshipit-source-id: ac121a8bcd5fd917ee134d257f967c8e3e338ca5 --- .../main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt index 09d844461e4cd6..e784606489e8c7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt @@ -39,6 +39,7 @@ public object AndroidUnicodeUtils { } @DoNotStrip + @JvmStatic public fun convertToCase(input: String, targetCase: Int, useCurrentLocale: Boolean): String { // Note Java's case conversions use the user's locale. For example "I".toLowerCase() // will produce a dotless i. From Java's docs: "To obtain correct results for locale From 20521cc908a347e3a2b3ac0fd6710946f18b1510 Mon Sep 17 00:00:00 2001 From: Gabriel Donadel Date: Mon, 1 Jul 2024 05:05:23 -0700 Subject: [PATCH 147/968] Fix Android autolink plugin for libraries that are platform specific (#45223) Summary: Fixes https://github.com/facebook/react-native/issues/45222 ## Changelog: [ANDROID] [FIXED] - Fix autolink plugin for libraries that are platform-specific Pull Request resolved: https://github.com/facebook/react-native/pull/45223 Test Plan: And a library that does not have Android native code such as react-native-segmented-control/segmented-control and sync gradle Reviewed By: rshest Differential Revision: D59221562 Pulled By: cortinico fbshipit-source-id: 55739d63ded63e46897d0d770281f937668c1f50 --- .../facebook/react/ReactSettingsExtension.kt | 12 ++++++-- .../react/ReactSettingsExtensionTest.kt | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt index 11deff4b8c3b65..60049c0b656927 100644 --- a/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt +++ b/packages/gradle-plugin/settings-plugin/src/main/kotlin/com/facebook/react/ReactSettingsExtension.kt @@ -112,9 +112,15 @@ abstract class ReactSettingsExtension @Inject constructor(val settings: Settings internal fun getLibrariesToAutolink(buildFile: File): Map { val model = JsonUtils.fromAutolinkingConfigJson(buildFile) - return model?.dependencies?.values?.associate { deps -> - ":${deps.nameCleansed}" to File(deps.platforms?.android?.sourceDir) - } ?: emptyMap() + return model + ?.dependencies + ?.values + // We handle scenarios where there are deps that are + // iOS-only or missing the Android configs. + ?.filter { it.platforms?.android?.sourceDir != null } + ?.associate { deps -> + ":${deps.nameCleansed}" to File(deps.platforms?.android?.sourceDir) + } ?: emptyMap() } internal fun computeSha256(lockFile: File) = diff --git a/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt b/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt index 21454324253b55..72d687b2ef5c29 100644 --- a/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt +++ b/packages/gradle-plugin/settings-plugin/src/test/kotlin/com/facebook/react/ReactSettingsExtensionTest.kt @@ -103,6 +103,35 @@ class ReactSettingsExtensionTest { map[":react-native_oss-library-example"]) } + @Test + fun getLibrariesToAutolink_withiOSOnlyLibrary_returnsEmptyMap() { + val validJsonFile = + createJsonFile( + """ + { + "reactNativeVersion": "1000.0.0", + "dependencies": { + "@react-native/oss-library-example": { + "root": "./node_modules/@react-native/oss-library-example", + "name": "@react-native/oss-library-example", + "platforms": { + "ios": { + "podspecPath": "./node_modules/@react-native/oss-library-example/OSSLibraryExample.podspec", + "version": "0.0.1", + "configurations": [], + "scriptPhases": [] + } + } + } + } + } + """ + .trimIndent()) + + val map = getLibrariesToAutolink(validJsonFile) + assertEquals(0, map.keys.size) + } + @Test fun checkAndUpdateLockfiles_withNothingToCheck_returnsFalse() { val project = ProjectBuilder.builder().build() From de7976c69d9f837729e8822f2b89e6d08ea6883a Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 1 Jul 2024 05:20:31 -0700 Subject: [PATCH 148/968] Remove unused hybrid class from DefaultComponentsRegistry (#45205) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45205 We only need a static register method, which includes the core components and the provider function. CoreComponentsRegistry isn't referenced at all in Kotlin/Java, and can be replaced with DefaultComponentsRegistry with no change in behaviour in all scenarios. Changelog: [Android][Removed] CoreComponentsRegistry is now fully replaced by DefaultComponentRegistry. Reviewed By: cortinico Differential Revision: D59107106 fbshipit-source-id: e679be490f43dab52eb5e11a08aa9d0ae2a89a92 --- .../ReactAndroid/api/ReactAndroid.api | 19 +------ .../defaults/DefaultComponentsRegistry.kt | 25 ++-------- .../react/fabric/CoreComponentsRegistry.kt | 30 ------------ .../react/fabric/CoreComponentsRegistry.cpp | 46 ++--------------- .../jni/react/fabric/CoreComponentsRegistry.h | 31 ++---------- .../src/main/jni/react/fabric/OnLoad.cpp | 2 - .../DefaultComponentsRegistry.cpp | 49 ++++++------------- .../DefaultComponentsRegistry.h | 13 +---- 8 files changed, 32 insertions(+), 183 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/CoreComponentsRegistry.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 3004783bfb31ce..99b24343aab50c 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1979,13 +1979,8 @@ public class com/facebook/react/config/ReactFeatureFlags { } public final class com/facebook/react/defaults/DefaultComponentsRegistry { - public static final field Companion Lcom/facebook/react/defaults/DefaultComponentsRegistry$Companion; - public synthetic fun (Lcom/facebook/react/fabric/ComponentFactory;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public static final fun register (Lcom/facebook/react/fabric/ComponentFactory;)Lcom/facebook/react/defaults/DefaultComponentsRegistry; -} - -public final class com/facebook/react/defaults/DefaultComponentsRegistry$Companion { - public final fun register (Lcom/facebook/react/fabric/ComponentFactory;)Lcom/facebook/react/defaults/DefaultComponentsRegistry; + public static final field INSTANCE Lcom/facebook/react/defaults/DefaultComponentsRegistry; + public static final fun register (Lcom/facebook/react/fabric/ComponentFactory;)V } public final class com/facebook/react/defaults/DefaultNewArchitectureEntryPoint { @@ -2532,16 +2527,6 @@ public final class com/facebook/react/fabric/ComponentFactory { public fun ()V } -public final class com/facebook/react/fabric/CoreComponentsRegistry { - public static final field Companion Lcom/facebook/react/fabric/CoreComponentsRegistry$Companion; - public synthetic fun (Lcom/facebook/react/fabric/ComponentFactory;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public static final fun register (Lcom/facebook/react/fabric/ComponentFactory;)Lcom/facebook/react/fabric/CoreComponentsRegistry; -} - -public final class com/facebook/react/fabric/CoreComponentsRegistry$Companion { - public final fun register (Lcom/facebook/react/fabric/ComponentFactory;)Lcom/facebook/react/fabric/CoreComponentsRegistry; -} - public class com/facebook/react/fabric/DevToolsReactPerfLogger : com/facebook/react/bridge/ReactMarker$FabricMarkerListener { public static final field mStreamingBatchExecutionStats Lcom/facebook/react/fabric/LongStreamingStats; public static final field mStreamingCommitStats Lcom/facebook/react/fabric/LongStreamingStats; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt index 14d33e576056f4..c289de9a66cfa9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt @@ -7,7 +7,6 @@ package com.facebook.react.defaults -import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.fabric.ComponentFactory @@ -21,24 +20,10 @@ import com.facebook.react.fabric.ComponentFactory * TODO(T186951312): Should this be @UnstableReactNativeAPI? */ @DoNotStrip -public class DefaultComponentsRegistry -@DoNotStrip -private constructor(componentFactory: ComponentFactory) { - - @DoNotStrip - @Suppress("NoHungarianNotation") - private val mHybridData: HybridData = initHybrid(componentFactory) - - @DoNotStrip private external fun initHybrid(componentFactory: ComponentFactory): HybridData - - public companion object { - init { - DefaultSoLoader.maybeLoadSoLibrary() - } - - @JvmStatic - @DoNotStrip - public fun register(componentFactory: ComponentFactory): DefaultComponentsRegistry = - DefaultComponentsRegistry(componentFactory) +public object DefaultComponentsRegistry { + init { + DefaultSoLoader.maybeLoadSoLibrary() } + + @JvmStatic @DoNotStrip public external fun register(componentFactory: ComponentFactory): Unit } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/CoreComponentsRegistry.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/CoreComponentsRegistry.kt deleted file mode 100644 index 7072418ddcb5bd..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/CoreComponentsRegistry.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.fabric - -import com.facebook.jni.HybridData -import com.facebook.proguard.annotations.DoNotStripAny - -@DoNotStripAny -public class CoreComponentsRegistry private constructor(componentFactory: ComponentFactory) { - - @Suppress("NoHungarianNotation") - private val mHybridData: HybridData = initHybrid(componentFactory) - - private external fun initHybrid(componentFactory: ComponentFactory): HybridData - - public companion object { - init { - FabricSoLoader.staticInit() - } - - @JvmStatic - public fun register(componentFactory: ComponentFactory): CoreComponentsRegistry = - CoreComponentsRegistry(componentFactory) - } -} diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp index fd8e579865f73b..b4a1117673d3a1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include @@ -24,13 +22,10 @@ #include #include -namespace facebook::react { - -CoreComponentsRegistry::CoreComponentsRegistry(ComponentFactory* delegate) - : delegate_(delegate) {} +namespace facebook::react::CoreComponentsRegistry { std::shared_ptr -CoreComponentsRegistry::sharedProviderRegistry() { +sharedProviderRegistry() { static auto providerRegistry = []() -> std::shared_ptr { auto providerRegistry = @@ -74,39 +69,4 @@ CoreComponentsRegistry::sharedProviderRegistry() { return providerRegistry; } -jni::local_ref -CoreComponentsRegistry::initHybrid( - jni::alias_ref, - ComponentFactory* delegate) { - auto instance = makeCxxInstance(delegate); - - // TODO T69453179: Codegen this file - auto buildRegistryFunction = - [](const EventDispatcher::Weak& eventDispatcher, - const ContextContainer::Shared& contextContainer) - -> ComponentDescriptorRegistry::Shared { - ComponentDescriptorParameters params{ - .eventDispatcher = eventDispatcher, - .contextContainer = contextContainer, - .flavor = nullptr}; - - auto registry = CoreComponentsRegistry::sharedProviderRegistry() - ->createComponentDescriptorRegistry(params); - auto& mutableRegistry = const_cast(*registry); - mutableRegistry.setFallbackComponentDescriptor( - std::make_shared(params)); - - return registry; - }; - - delegate->buildRegistryFunction = buildRegistryFunction; - return instance; -} - -void CoreComponentsRegistry::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", CoreComponentsRegistry::initHybrid), - }); -} - -} // namespace facebook::react +} // namespace facebook::react::CoreComponentsRegistry diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.h index 1f6b1475df0a2b..c515238c71a2e1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.h @@ -7,34 +7,11 @@ #pragma once -#include #include -#include -#include "ComponentFactory.h" -namespace facebook::react { +namespace facebook::react::CoreComponentsRegistry { -class CoreComponentsRegistry - : public facebook::jni::HybridClass { - public: - constexpr static auto kJavaDescriptor = - "Lcom/facebook/react/fabric/CoreComponentsRegistry;"; +std::shared_ptr +sharedProviderRegistry(); - static void registerNatives(); - - explicit CoreComponentsRegistry(ComponentFactory* delegate); - - static std::shared_ptr - sharedProviderRegistry(); - - private: - friend HybridBase; - - const ComponentFactory* delegate_; - - static jni::local_ref initHybrid( - jni::alias_ref, - ComponentFactory* delegate); -}; - -} // namespace facebook::react +} // namespace facebook::react::CoreComponentsRegistry diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp index 1e4ab75b826511..bcdf164ffab430 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp @@ -9,7 +9,6 @@ #include "Binding.h" #include "ComponentFactory.h" -#include "CoreComponentsRegistry.h" #include "EventBeatManager.h" #include "EventEmitterWrapper.h" #include "JEmptyReactNativeConfig.h" @@ -23,7 +22,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { facebook::react::EventEmitterWrapper::registerNatives(); facebook::react::StateWrapperImpl::registerNatives(); facebook::react::ComponentFactory::registerNatives(); - facebook::react::CoreComponentsRegistry::registerNatives(); facebook::react::SurfaceHandlerBinding::registerNatives(); facebook::react::JEmptyReactNativeConfig::registerNatives(); }); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp index 386d2ff1d83a44..543b387b21787d 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp @@ -18,56 +18,39 @@ namespace facebook::react { std::function)> DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint{}; -DefaultComponentsRegistry::DefaultComponentsRegistry(ComponentFactory* delegate) - : delegate_(delegate) {} - -std::shared_ptr -DefaultComponentsRegistry::sharedProviderRegistry() { - auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); - - if (DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint) { - (DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint)( - providerRegistry); - } else { - LOG(WARNING) - << "Custom component descriptors were not configured from JNI_OnLoad"; - } - - return providerRegistry; -} - -jni::local_ref -DefaultComponentsRegistry::initHybrid( +void DefaultComponentsRegistry::setRegistryRunction( jni::alias_ref, ComponentFactory* delegate) { - auto instance = makeCxxInstance(delegate); - - auto buildRegistryFunction = - [](const EventDispatcher::Weak& eventDispatcher, - const ContextContainer::Shared& contextContainer) - -> ComponentDescriptorRegistry::Shared { + delegate + ->buildRegistryFunction = [](const EventDispatcher::Weak& eventDispatcher, + const ContextContainer::Shared& + contextContainer) { ComponentDescriptorParameters params{ .eventDispatcher = eventDispatcher, .contextContainer = contextContainer, .flavor = nullptr}; - auto registry = DefaultComponentsRegistry::sharedProviderRegistry() - ->createComponentDescriptorRegistry(params); + auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); + if (registerComponentDescriptorsFromEntryPoint) { + registerComponentDescriptorsFromEntryPoint(providerRegistry); + } else { + LOG(WARNING) + << "Custom component descriptors were not configured from JNI_OnLoad"; + } + auto registry = providerRegistry->createComponentDescriptorRegistry(params); auto& mutableRegistry = const_cast(*registry); mutableRegistry.setFallbackComponentDescriptor( std::make_shared(params)); return registry; }; - - delegate->buildRegistryFunction = buildRegistryFunction; - return instance; } void DefaultComponentsRegistry::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", DefaultComponentsRegistry::initHybrid), + javaClassLocal()->registerNatives({ + makeNativeMethod( + "register", DefaultComponentsRegistry::setRegistryRunction), }); } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h index d1950e8c746ae9..cf95b8709cf332 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h @@ -16,7 +16,7 @@ namespace facebook::react { class DefaultComponentsRegistry - : public facebook::jni::HybridClass { + : public facebook::jni::JavaClass { public: constexpr static auto kJavaDescriptor = "Lcom/facebook/react/defaults/DefaultComponentsRegistry;"; @@ -27,17 +27,8 @@ class DefaultComponentsRegistry std::shared_ptr)> registerComponentDescriptorsFromEntryPoint; - DefaultComponentsRegistry(ComponentFactory* delegate); - private: - friend HybridBase; - - static std::shared_ptr - sharedProviderRegistry(); - - const ComponentFactory* delegate_; - - static jni::local_ref initHybrid( + static void setRegistryRunction( jni::alias_ref, ComponentFactory* delegate); }; From c911c897285aa838594a405b26462e00baeac8fb Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 1 Jul 2024 06:28:51 -0700 Subject: [PATCH 149/968] Setup `git config --global --add safe.directory '*'` when running jobs inside Docker (#45231) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45231 Following up to cipolleschi's work, it turns out that me setting this command inside the docker file for React Android is unneffective: https://github.com/react-native-community/docker-android/pull/228 The reason is that the user executing is different (1001 for the Dockerfile, while GHA executes as root 1000). So we need to set this, otherwise the nightlies will be invoked with the `-TEMP` prefix: Changelog: [Internal] [Changed] - Setup `git config --global --add safe.directory '*'` when running jobs inside Docker Reviewed By: blakef Differential Revision: D59223862 fbshipit-source-id: 26674fc8cdaebf6687407072cc4e4f5c38246845 --- .github/workflows/nightly.yml | 4 ++++ .github/workflows/publish-release.yml | 4 ++++ .github/workflows/test-all.yml | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 897c17bb9e8527..2bec7b84e7b87d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -509,6 +509,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Setup node.js uses: ./.github/actions/setup-node - name: Install dependencies @@ -576,6 +578,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Create /tmp/hermes/osx-bin directory run: mkdir -p /tmp/hermes/osx-bin - name: Download osx-bin release artifacts diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 43d82ba74b41a2..6b9a0869c551d1 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -506,6 +506,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Setup node.js uses: ./.github/actions/setup-node - name: Install dependencies @@ -573,6 +575,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Create /tmp/hermes/osx-bin directory run: mkdir -p /tmp/hermes/osx-bin - name: Download osx-bin release artifacts diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index a48a4112322c11..748315fbf4c45b 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -582,6 +582,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Setup node.js uses: ./.github/actions/setup-node - name: Install dependencies @@ -654,6 +656,8 @@ jobs: echo '|1|If6MU203eXTaaWL678YEfWkVMrw=|kqLeIAyTy8pzpj8x8Ae4Fr8Mtlc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Create /tmp/hermes/osx-bin directory run: mkdir -p /tmp/hermes/osx-bin - name: Download osx-bin release artifacts @@ -820,6 +824,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4.1.1 + - name: Setup git safe folders + run: git config --global --add safe.directory '*' - name: Cache setup id: cache_setup uses: ./.github/actions/cache_setup From c68f35d4441c8a03541da17e3adc03f355e8c45e Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 1 Jul 2024 07:28:42 -0700 Subject: [PATCH 150/968] Merge newarchdefaults jni target into fabric and turbomodule targets (#45207) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45207 These are their own shared library, and their own soloader-call, but they can easily be pulled into existing targets without causing excessive bloat. Changelog: [Android][Removed] react_newarchdefaults is no longer a prefab, instead use fabricjni Reviewed By: christophpurrer Differential Revision: D59107105 fbshipit-source-id: fb3b25f3ce4511aa18126477f2beefe1292c6d09 --- .../generators/modules/GenerateModuleJniH.js | 1 - .../GenerateModuleJniH-test.js.snap | 8 ----- .../ReactAndroid/build.gradle.kts | 12 ++++---- .../cmake-utils/ReactNative-application.cmake | 2 -- ...faultSoLoader.kt => AppModulesSoLoader.kt} | 3 +- .../defaults/DefaultComponentsRegistry.kt | 4 ++- .../DefaultNewArchitectureEntryPoint.kt | 2 +- .../DefaultTurboModuleManagerDelegate.kt | 4 ++- .../ReactAndroid/src/main/jni/CMakeLists.txt | 1 - .../DefaultComponentsRegistry.cpp | 0 .../DefaultComponentsRegistry.h | 0 .../src/main/jni/react/fabric/OnLoad.cpp | 4 ++- .../jni/react/newarchdefaults/CMakeLists.txt | 29 ------------------- .../main/jni/react/newarchdefaults/OnLoad.cpp | 18 ------------ .../main/jni/react/turbomodule/CMakeLists.txt | 3 ++ .../DefaultTurboModuleManagerDelegate.cpp | 0 .../DefaultTurboModuleManagerDelegate.h | 0 .../react/turbomodule/ReactCommon/OnLoad.cpp | 2 ++ .../ReactCommon/react/runtime/CMakeLists.txt | 2 -- 19 files changed, 21 insertions(+), 74 deletions(-) rename packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/{DefaultSoLoader.kt => AppModulesSoLoader.kt} (87%) rename packages/react-native/ReactAndroid/src/main/jni/react/{newarchdefaults => fabric}/DefaultComponentsRegistry.cpp (100%) rename packages/react-native/ReactAndroid/src/main/jni/react/{newarchdefaults => fabric}/DefaultComponentsRegistry.h (100%) delete mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt delete mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp rename packages/react-native/ReactAndroid/src/main/jni/react/{newarchdefaults => turbomodule}/DefaultTurboModuleManagerDelegate.cpp (100%) rename packages/react-native/ReactAndroid/src/main/jni/react/{newarchdefaults => turbomodule}/DefaultTurboModuleManagerDelegate.h (100%) diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js index 0bb2b35d15cbf1..5a5e2b84e1979f 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js @@ -100,7 +100,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index 72877187166bd8..9751cb1fe793ed 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -70,7 +70,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -157,7 +156,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -237,7 +235,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -324,7 +321,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -411,7 +407,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -506,7 +501,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -593,7 +587,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) @@ -688,7 +681,6 @@ target_link_libraries( react_utils rrc_image rrc_view - turbomodulejsijni yoga ) diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 76d41a679a6fdb..263c4d246a9cc3 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -96,8 +96,6 @@ val preparePrefab by Pair( "../ReactCommon/react/renderer/componentregistry/", "react/renderer/componentregistry/")), - PrefabPreprocessingEntry( - "react_newarchdefaults", Pair("src/main/jni/react/newarchdefaults", "")), PrefabPreprocessingEntry( "react_render_animations", Pair("../ReactCommon/react/renderer/animations/", "react/renderer/animations/")), @@ -152,7 +150,11 @@ val preparePrefab by PrefabPreprocessingEntry( "glog", Pair(File(buildDir, "third-party-ndk/glog/exported/").absolutePath, "")), PrefabPreprocessingEntry( - "fabricjni", Pair("src/main/jni/react/fabric", "react/fabric/")), + "fabricjni", + listOf( + Pair("src/main/jni/react/fabric/DefaultComponentsRegistry.h", ""), + Pair("src/main/jni/react/fabric", "react/fabric/"), + )), PrefabPreprocessingEntry( "mapbufferjni", Pair("src/main/jni/react/mapbuffer", "react/mapbuffer/")), PrefabPreprocessingEntry( @@ -561,7 +563,6 @@ android { "react_performance_timeline", "react_utils", "react_render_componentregistry", - "react_newarchdefaults", "react_render_animations", "react_render_core", "react_render_consistency", @@ -682,9 +683,6 @@ android { create("react_render_componentregistry") { headers = File(prefabHeadersDir, "react_render_componentregistry").absolutePath } - create("react_newarchdefaults") { - headers = File(prefabHeadersDir, "react_newarchdefaults").absolutePath - } create("react_render_animations") { headers = File(prefabHeadersDir, "react_render_animations").absolutePath } diff --git a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake index 468b5c1c975c49..071705af0d503f 100644 --- a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +++ b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake @@ -69,7 +69,6 @@ add_library(react_codegen_rncore ALIAS ReactAndroid::react_codegen_rncore) add_library(react_debug ALIAS ReactAndroid::react_debug) add_library(react_utils ALIAS ReactAndroid::react_utils) add_library(react_render_componentregistry ALIAS ReactAndroid::react_render_componentregistry) -add_library(react_newarchdefaults ALIAS ReactAndroid::react_newarchdefaults) add_library(react_render_core ALIAS ReactAndroid::react_render_core) add_library(react_render_graphics ALIAS ReactAndroid::react_render_graphics) add_library(rrc_view ALIAS ReactAndroid::rrc_view) @@ -102,7 +101,6 @@ target_link_libraries(${CMAKE_PROJECT_NAME} react_debug # prefab ready react_utils # prefab ready react_nativemodule_core # prefab ready - react_newarchdefaults # prefab ready react_render_componentregistry # prefab ready react_render_core # prefab ready react_render_debug # prefab ready diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/AppModulesSoLoader.kt similarity index 87% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/AppModulesSoLoader.kt index cebdc7c93234fa..eae33477d5211e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/AppModulesSoLoader.kt @@ -9,12 +9,11 @@ package com.facebook.react.defaults import com.facebook.soloader.SoLoader -internal class DefaultSoLoader { +internal class AppModulesSoLoader { companion object { @Synchronized @JvmStatic fun maybeLoadSoLibrary() { - SoLoader.loadLibrary("react_newarchdefaults") try { SoLoader.loadLibrary("appmodules") } catch (e: UnsatisfiedLinkError) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt index c289de9a66cfa9..883d0068291682 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt @@ -9,6 +9,7 @@ package com.facebook.react.defaults import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.fabric.ComponentFactory +import com.facebook.react.fabric.FabricSoLoader /** * A utility class that provides users a ComponentRegistry they can customize with a C++ @@ -22,7 +23,8 @@ import com.facebook.react.fabric.ComponentFactory @DoNotStrip public object DefaultComponentsRegistry { init { - DefaultSoLoader.maybeLoadSoLibrary() + FabricSoLoader.staticInit() + AppModulesSoLoader.maybeLoadSoLibrary() } @JvmStatic @DoNotStrip public external fun register(componentFactory: ComponentFactory): Unit diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt index 0f8dfad5146109..9419eb8d671e0b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt @@ -69,7 +69,7 @@ public object DefaultNewArchitectureEntryPoint { privateConcurrentReactEnabled = fabricEnabled privateBridgelessEnabled = bridgelessEnabled - DefaultSoLoader.maybeLoadSoLibrary() + AppModulesSoLoader.maybeLoadSoLibrary() loaded = true } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index 3da64bac3f0c3a..3413162cdd98ce 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -13,6 +13,7 @@ import com.facebook.react.ReactPackage import com.facebook.react.ReactPackageTurboModuleManagerDelegate import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.common.annotations.UnstableReactNativeAPI +import com.facebook.react.internal.turbomodule.core.NativeModuleSoLoader import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage /** @@ -69,7 +70,8 @@ private constructor( private companion object { init { - DefaultSoLoader.maybeLoadSoLibrary() + NativeModuleSoLoader.maybeLoadSoLibrary() + AppModulesSoLoader.maybeLoadSoLibrary() } @DoNotStrip diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index 488cd4aa29ee08..9978dac7f7112c 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -130,7 +130,6 @@ add_react_android_subdir(src/main/jni/react/mapbuffer) add_react_android_subdir(src/main/jni/react/reactnativeblob) add_react_android_subdir(src/main/jni/react/fabric) add_react_android_subdir(src/main/jni/react/featureflags) -add_react_android_subdir(src/main/jni/react/newarchdefaults) add_react_android_subdir(src/main/jni/react/hermes/reactexecutor) add_react_android_subdir(src/main/jni/react/hermes/instrumentation/) add_react_android_subdir(src/main/jni/react/runtime/cxxreactpackage) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.cpp similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp rename to packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.cpp diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.h similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h rename to packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.h diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp index bcdf164ffab430..6d3b78b604565f 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp @@ -9,6 +9,7 @@ #include "Binding.h" #include "ComponentFactory.h" +#include "DefaultComponentsRegistry.h" #include "EventBeatManager.h" #include "EventEmitterWrapper.h" #include "JEmptyReactNativeConfig.h" @@ -18,10 +19,11 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { return facebook::jni::initialize(vm, [] { facebook::react::Binding::registerNatives(); + facebook::react::ComponentFactory::registerNatives(); + facebook::react::DefaultComponentsRegistry::registerNatives(); facebook::react::EventBeatManager::registerNatives(); facebook::react::EventEmitterWrapper::registerNatives(); facebook::react::StateWrapperImpl::registerNatives(); - facebook::react::ComponentFactory::registerNatives(); facebook::react::SurfaceHandlerBinding::registerNatives(); facebook::react::JEmptyReactNativeConfig::registerNatives(); }); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt deleted file mode 100644 index 932157aee86e37..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -cmake_minimum_required(VERSION 3.13) -set(CMAKE_VERBOSE_MAKEFILE on) - -add_compile_options(-fexceptions -frtti -std=c++20 -Wall -DLOG_TAG=\"ReactNative\") - -file(GLOB react_newarchdefaults_SRC CONFIGURE_DEPENDS *.cpp) - -add_library(react_newarchdefaults SHARED ${react_newarchdefaults_SRC}) - -target_include_directories(react_newarchdefaults PUBLIC .) - -target_link_libraries(react_newarchdefaults - fbjni - fabricjni - react_featureflagsjni - react_nativemodule_core - react_codegen_rncore - react_cxxreactpackage - react_nativemodule_defaults - react_nativemodule_dom - react_nativemodule_featureflags - react_nativemodule_microtasks - react_nativemodule_idlecallbacks - jsi) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp deleted file mode 100644 index a66675651cd015..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include - -#include "DefaultComponentsRegistry.h" -#include "DefaultTurboModuleManagerDelegate.h" - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { - return facebook::jni::initialize(vm, [] { - facebook::react::DefaultTurboModuleManagerDelegate::registerNatives(); - facebook::react::DefaultComponentsRegistry::registerNatives(); - }); -} diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt index 4c7aeb1f896427..57eb1cef70b468 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt @@ -44,6 +44,7 @@ target_link_libraries(callinvokerholder add_library( turbomodulejsijni SHARED + DefaultTurboModuleManagerDelegate.cpp ReactCommon/BindingsInstallerHolder.cpp ReactCommon/CompositeTurboModuleManagerDelegate.cpp ReactCommon/OnLoad.cpp @@ -60,6 +61,8 @@ target_link_libraries(turbomodulejsijni fb fbjni jsi + react_cxxreactpackage react_nativemodule_core + react_nativemodule_defaults callinvokerholder reactperfloggerjni) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.cpp similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp rename to packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.cpp diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.h similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h rename to packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.h diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp index 013e2ca94f0764..b0cbd198d9572e 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp @@ -10,6 +10,7 @@ #include #include "CompositeTurboModuleManagerDelegate.h" +#include "DefaultTurboModuleManagerDelegate.h" #include "TurboModuleManager.h" void jniEnableCppLogging( @@ -26,6 +27,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { // "ComponentDescriptorFactory" is defined in Fabric facebook::react::TurboModuleManager::registerNatives(); + facebook::react::DefaultTurboModuleManagerDelegate::registerNatives(); facebook::react::CompositeTurboModuleManagerDelegate::registerNatives(); facebook::jni::registerNatives( diff --git a/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt b/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt index 3a440e009b0c7a..338a224ef877b9 100644 --- a/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt @@ -30,8 +30,6 @@ target_link_libraries( bridgeless jserrorhandler fabricjni - react_featureflagsjni - turbomodulejsijni fb jsi jsireact From 8b121c507170bc7a6cb76f0db68b1f77e7498a12 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 1 Jul 2024 09:16:25 -0700 Subject: [PATCH 151/968] Use RAII for cleaning up global_refs in JavaTurboModule (#45218) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45218 Noticed that when an exception occurred we would not cleanup global_refs, leaking them in the global table. Restructure this to use RAII and rely on JNIArgs to do the cleanup as necessary. Changelog: [Android][Internal] Reviewed By: RSNara Differential Revision: D59156494 fbshipit-source-id: c89552d72387bad2a120373e78a2c545415a7c82 --- .../android/ReactCommon/JavaTurboModule.cpp | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp index 1fcf29ac86f5c6..52039dd6cdb30f 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -81,9 +82,22 @@ bool rejectTurboModulePromiseOnNativeError() { } struct JNIArgs { - JNIArgs(size_t count) : args_(count) {} - std::vector args_; - std::vector globalRefs_; + JNIArgs(size_t count) : args(count) {} + JNIArgs(const JNIArgs&) = delete; + JNIArgs(JNIArgs&& jniArgs) noexcept = default; + + JNIArgs& operator=(const JNIArgs& other) = delete; + JNIArgs& operator=(JNIArgs&& other) noexcept = default; + + std::vector args; + std::vector globalRefs; + + ~JNIArgs() { + JNIEnv* env = jni::Environment::current(); + for (auto globalRef : globalRefs) { + env->DeleteGlobalRef(globalRef); + } + } }; jsi::Value createJSRuntimeError(jsi::Runtime& runtime, jsi::Value&& message) { @@ -316,11 +330,10 @@ JNIArgs convertJSIArgsToJNIArgs( } JNIArgs jniArgs(valueKind == PromiseKind ? count + 1 : count); - auto& jargs = jniArgs.args_; - auto& globalRefs = jniArgs.globalRefs_; + auto& jargs = jniArgs.args; + auto& globalRefs = jniArgs.globalRefs; - auto makeGlobalIfNecessary = - [&globalRefs, env, valueKind](jobject obj) -> jobject { + auto makeGlobalIfNecessary = [&](jobject obj) { if (valueKind == VoidKind || valueKind == PromiseKind) { jobject globalObj = env->NewGlobalRef(obj); globalRefs.push_back(globalObj); @@ -634,8 +647,8 @@ jsi::Value JavaTurboModule::invokeJavaMethod( TMPL::syncMethodCallExecutionStart(moduleName, methodName); } - auto& jargs = jniArgs.args_; - auto& globalRefs = jniArgs.globalRefs_; + auto& jargs = jniArgs.args; + auto& globalRefs = jniArgs.globalRefs; switch (valueKind) { case BooleanKind: { @@ -820,8 +833,7 @@ jsi::Value JavaTurboModule::invokeJavaMethod( nativeMethodCallInvoker_->invokeAsync( methodName, - [jargs, - globalRefs, + [jniArgs = makeMoveWrapper(std::move(jniArgs)), methodID, instance_ = jni::make_weak(instance_), moduleNameStr = name_, @@ -848,17 +860,14 @@ jsi::Value JavaTurboModule::invokeJavaMethod( const char* methodName = methodNameStr.c_str(); TMPL::asyncMethodCallExecutionStart(moduleName, methodName, id); - env->CallVoidMethodA(instance.get(), methodID, jargs.data()); + env->CallVoidMethodA( + instance.get(), methodID, jniArgs->args.data()); try { FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); } catch (...) { TMPL::asyncMethodCallExecutionFail(moduleName, methodName, id); throw; } - - for (auto globalRef : globalRefs) { - env->DeleteGlobalRef(globalRef); - } TMPL::asyncMethodCallExecutionEnd(moduleName, methodName, id); }); @@ -933,10 +942,9 @@ jsi::Value JavaTurboModule::invokeJavaMethod( TMPL::asyncMethodCallDispatch(moduleName, methodName); nativeMethodCallInvoker_->invokeAsync( methodName, - [jargs, + [jniArgs = makeMoveWrapper(std::move(jniArgs)), rejectCallback = std::move(nativeRejectCallback), jsInvocationStack = std::move(jsInvocationStack), - globalRefs, methodID, instance_ = jni::make_weak(instance_), moduleNameStr = name_, @@ -962,24 +970,21 @@ jsi::Value JavaTurboModule::invokeJavaMethod( const char* moduleName = moduleNameStr.c_str(); const char* methodName = methodNameStr.c_str(); TMPL::asyncMethodCallExecutionStart(moduleName, methodName, id); - env->CallVoidMethodA(instance.get(), methodID, jargs.data()); + env->CallVoidMethodA( + instance.get(), methodID, jniArgs->args.data()); try { FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); } catch (...) { - TMPL::asyncMethodCallExecutionFail(moduleName, methodName, id); if (rejectTurboModulePromiseOnNativeError() && rejectCallback) { auto exception = std::current_exception(); rejectWithException( *rejectCallback, exception, jsInvocationStack); rejectCallback = std::nullopt; } else { + TMPL::asyncMethodCallExecutionFail(moduleName, methodName, id); throw; } } - - for (auto globalRef : globalRefs) { - env->DeleteGlobalRef(globalRef); - } TMPL::asyncMethodCallExecutionEnd(moduleName, methodName, id); }); TMPL::asyncMethodCallEnd(moduleName, methodName); From f473a2f8f48ed8ce94a1f8a3181a5dabb4c6ad8d Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Mon, 1 Jul 2024 09:36:51 -0700 Subject: [PATCH 152/968] Add ObjC Turbo Module Event Emitter example (#44914) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44914 Shows a proof of concept how '*strongly typed Turbo Module scoped*' `EventEmitters` can be used in a ObjC Turbo Module. ## Changelog: [iOS] [Added] - Add ObjC Turbo Module Event Emitter example Reviewed By: rshest Differential Revision: D57650830 fbshipit-source-id: c5c2dee4766484e9e58415e33c084999a9ae3bc6 --- .../platform/ios/ReactCommon/RCTTurboModule.h | 24 ++++++++++++-- .../ios/ReactCommon/RCTTurboModule.mm | 13 ++++++++ .../RCTNativeSampleTurboModuleSpec.h | 10 +++++- .../RCTNativeSampleTurboModuleSpec.mm | 31 +++++++++++++++++++ .../ios/ReactCommon/RCTSampleTurboModule.mm | 4 +++ 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h index 97348d0641624b..f092e3377ad25d 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h @@ -7,8 +7,6 @@ #pragma once -#import - #import #import @@ -16,6 +14,9 @@ #import #import #import +#import +#import +#import #import #import @@ -27,12 +28,21 @@ namespace facebook::react { class CallbackWrapper; class Instance; +using EventEmitterCallback = std::function; namespace TurboModuleConvertUtils { jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value); id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker); } // namespace TurboModuleConvertUtils +template <> +struct Bridging { + static jsi::Value toJs(jsi::Runtime &rt, const id &value) + { + return TurboModuleConvertUtils::convertObjCObjectToJSIValue(rt, value); + } +}; + /** * ObjC++ specific TurboModule base class. */ @@ -64,6 +74,8 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { protected: void setMethodArgConversionSelector(NSString *methodName, size_t argIndex, NSString *fnName); + void setEventEmitterCallback(EventEmitterCallback eventEmitterCallback); + /** * Why is this virtual? * @@ -154,9 +166,17 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { } // namespace facebook::react +@interface EventEmitterCallbackWrapper : NSObject { + @public + facebook::react::EventEmitterCallback _eventEmitterCallback; +} +@end + @protocol RCTTurboModule - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params; +@optional +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; @end /** diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm index 4abb7fca9bec5f..2678b19063e6d7 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm @@ -813,5 +813,18 @@ SystraceSection s( methodArgConversionSelectors_[methodName][argIndex] = selectorValue; } +void ObjCTurboModule::setEventEmitterCallback(EventEmitterCallback eventEmitterCallback) +{ + if ([instance_ conformsToProtocol:@protocol(RCTTurboModule)] && + [instance_ respondsToSelector:@selector(setEventEmitterCallback:)]) { + EventEmitterCallbackWrapper *wrapper = [EventEmitterCallbackWrapper new]; + wrapper->_eventEmitterCallback = std::move(eventEmitterCallback); + [(id)instance_ setEventEmitterCallback:wrapper]; + } +} + } // namespace react } // namespace facebook + +@implementation EventEmitterCallbackWrapper +@end diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h index 16bb3080528ec5..e37e275e1eba37 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h @@ -43,7 +43,15 @@ @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { + @protected + facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *_Nonnull)eventEmitterCallbackWrapper; +- (void)emitOnPress; +- (void)emitOnClick:(NSString *)value; +- (void)emitOnChange:(NSDictionary *)value; +- (void)emitOnSubmit:(NSArray *)value; @end namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm index dfb393190e7bea..5ad04fa341f4b1 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm @@ -224,9 +224,40 @@ methodMap_["getObjectAssert"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObjectAssert}; methodMap_["promiseAssert"] = MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_promiseAssert}; methodMap_["getConstants"] = MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; + eventEmitterMap_["onPress"] = std::make_shared>(); + eventEmitterMap_["onClick"] = std::make_shared>(); + eventEmitterMap_["onChange"] = std::make_shared>(); + eventEmitterMap_["onSubmit"] = std::make_shared>(); + setEventEmitterCallback([&](const std::string &name, id value) { + static_cast &>(*eventEmitterMap_[name]).emit(value); + }); } } // namespace facebook::react @implementation NativeSampleTurboModuleSpecBase +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *_Nonnull)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} + +- (void)emitOnPress +{ + _eventEmitterCallback("onPress", nil); +} + +- (void)emitOnClick:(NSString *)value +{ + _eventEmitterCallback("onClick", value); +} + +- (void)emitOnChange:(NSDictionary *)value +{ + _eventEmitterCallback("onChange", value); +} + +- (void)emitOnSubmit:(NSArray *)value +{ + _eventEmitterCallback("onSubmit", value); +} @end diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm index c7d9666a390cc4..2013c70a344fa6 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm @@ -82,6 +82,10 @@ - (void)installJSIBindingsWithRuntime:(facebook::jsi::Runtime &)runtime RCT_EXPORT_METHOD(voidFunc) { // Nothing to do + [self emitOnPress]; + [self emitOnClick:@"click"]; + [self emitOnChange:@{@"a" : @1, @"b" : @"two"}]; + [self emitOnSubmit:@[ @{@"a" : @1, @"b" : @"two"}, @{@"a" : @3, @"b" : @"four"} ]]; } RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, getBool : (BOOL)arg) From 9d3052378a51bcad90615dbf5961a2f266039e6c Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 1 Jul 2024 12:47:24 -0700 Subject: [PATCH 153/968] Revert D59107105: Merge newarchdefaults jni target into fabric and turbomodule targets Differential Revision: D59107105 Original commit changeset: fb3b25f3ce45 Original Phabricator Diff: D59107105 fbshipit-source-id: 2197d1deb79e7fc9b3ac7b0772225e13c23e0001 --- .../generators/modules/GenerateModuleJniH.js | 1 + .../GenerateModuleJniH-test.js.snap | 8 +++++ .../ReactAndroid/build.gradle.kts | 12 ++++---- .../cmake-utils/ReactNative-application.cmake | 2 ++ .../defaults/DefaultComponentsRegistry.kt | 4 +-- .../DefaultNewArchitectureEntryPoint.kt | 2 +- ...pModulesSoLoader.kt => DefaultSoLoader.kt} | 3 +- .../DefaultTurboModuleManagerDelegate.kt | 4 +-- .../ReactAndroid/src/main/jni/CMakeLists.txt | 1 + .../src/main/jni/react/fabric/OnLoad.cpp | 4 +-- .../jni/react/newarchdefaults/CMakeLists.txt | 29 +++++++++++++++++++ .../DefaultComponentsRegistry.cpp | 0 .../DefaultComponentsRegistry.h | 0 .../DefaultTurboModuleManagerDelegate.cpp | 0 .../DefaultTurboModuleManagerDelegate.h | 0 .../main/jni/react/newarchdefaults/OnLoad.cpp | 18 ++++++++++++ .../main/jni/react/turbomodule/CMakeLists.txt | 3 -- .../react/turbomodule/ReactCommon/OnLoad.cpp | 2 -- .../ReactCommon/react/runtime/CMakeLists.txt | 2 ++ 19 files changed, 74 insertions(+), 21 deletions(-) rename packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/{AppModulesSoLoader.kt => DefaultSoLoader.kt} (87%) create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt rename packages/react-native/ReactAndroid/src/main/jni/react/{fabric => newarchdefaults}/DefaultComponentsRegistry.cpp (100%) rename packages/react-native/ReactAndroid/src/main/jni/react/{fabric => newarchdefaults}/DefaultComponentsRegistry.h (100%) rename packages/react-native/ReactAndroid/src/main/jni/react/{turbomodule => newarchdefaults}/DefaultTurboModuleManagerDelegate.cpp (100%) rename packages/react-native/ReactAndroid/src/main/jni/react/{turbomodule => newarchdefaults}/DefaultTurboModuleManagerDelegate.h (100%) create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js index 5a5e2b84e1979f..0bb2b35d15cbf1 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js @@ -100,6 +100,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index 9751cb1fe793ed..72877187166bd8 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -70,6 +70,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -156,6 +157,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -235,6 +237,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -321,6 +324,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -407,6 +411,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -501,6 +506,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -587,6 +593,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) @@ -681,6 +688,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 263c4d246a9cc3..76d41a679a6fdb 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -96,6 +96,8 @@ val preparePrefab by Pair( "../ReactCommon/react/renderer/componentregistry/", "react/renderer/componentregistry/")), + PrefabPreprocessingEntry( + "react_newarchdefaults", Pair("src/main/jni/react/newarchdefaults", "")), PrefabPreprocessingEntry( "react_render_animations", Pair("../ReactCommon/react/renderer/animations/", "react/renderer/animations/")), @@ -150,11 +152,7 @@ val preparePrefab by PrefabPreprocessingEntry( "glog", Pair(File(buildDir, "third-party-ndk/glog/exported/").absolutePath, "")), PrefabPreprocessingEntry( - "fabricjni", - listOf( - Pair("src/main/jni/react/fabric/DefaultComponentsRegistry.h", ""), - Pair("src/main/jni/react/fabric", "react/fabric/"), - )), + "fabricjni", Pair("src/main/jni/react/fabric", "react/fabric/")), PrefabPreprocessingEntry( "mapbufferjni", Pair("src/main/jni/react/mapbuffer", "react/mapbuffer/")), PrefabPreprocessingEntry( @@ -563,6 +561,7 @@ android { "react_performance_timeline", "react_utils", "react_render_componentregistry", + "react_newarchdefaults", "react_render_animations", "react_render_core", "react_render_consistency", @@ -683,6 +682,9 @@ android { create("react_render_componentregistry") { headers = File(prefabHeadersDir, "react_render_componentregistry").absolutePath } + create("react_newarchdefaults") { + headers = File(prefabHeadersDir, "react_newarchdefaults").absolutePath + } create("react_render_animations") { headers = File(prefabHeadersDir, "react_render_animations").absolutePath } diff --git a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake index 071705af0d503f..468b5c1c975c49 100644 --- a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +++ b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake @@ -69,6 +69,7 @@ add_library(react_codegen_rncore ALIAS ReactAndroid::react_codegen_rncore) add_library(react_debug ALIAS ReactAndroid::react_debug) add_library(react_utils ALIAS ReactAndroid::react_utils) add_library(react_render_componentregistry ALIAS ReactAndroid::react_render_componentregistry) +add_library(react_newarchdefaults ALIAS ReactAndroid::react_newarchdefaults) add_library(react_render_core ALIAS ReactAndroid::react_render_core) add_library(react_render_graphics ALIAS ReactAndroid::react_render_graphics) add_library(rrc_view ALIAS ReactAndroid::rrc_view) @@ -101,6 +102,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} react_debug # prefab ready react_utils # prefab ready react_nativemodule_core # prefab ready + react_newarchdefaults # prefab ready react_render_componentregistry # prefab ready react_render_core # prefab ready react_render_debug # prefab ready diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt index 883d0068291682..c289de9a66cfa9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultComponentsRegistry.kt @@ -9,7 +9,6 @@ package com.facebook.react.defaults import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.fabric.ComponentFactory -import com.facebook.react.fabric.FabricSoLoader /** * A utility class that provides users a ComponentRegistry they can customize with a C++ @@ -23,8 +22,7 @@ import com.facebook.react.fabric.FabricSoLoader @DoNotStrip public object DefaultComponentsRegistry { init { - FabricSoLoader.staticInit() - AppModulesSoLoader.maybeLoadSoLibrary() + DefaultSoLoader.maybeLoadSoLibrary() } @JvmStatic @DoNotStrip public external fun register(componentFactory: ComponentFactory): Unit diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt index 9419eb8d671e0b..0f8dfad5146109 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt @@ -69,7 +69,7 @@ public object DefaultNewArchitectureEntryPoint { privateConcurrentReactEnabled = fabricEnabled privateBridgelessEnabled = bridgelessEnabled - AppModulesSoLoader.maybeLoadSoLibrary() + DefaultSoLoader.maybeLoadSoLibrary() loaded = true } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/AppModulesSoLoader.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt similarity index 87% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/AppModulesSoLoader.kt rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt index eae33477d5211e..cebdc7c93234fa 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/AppModulesSoLoader.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultSoLoader.kt @@ -9,11 +9,12 @@ package com.facebook.react.defaults import com.facebook.soloader.SoLoader -internal class AppModulesSoLoader { +internal class DefaultSoLoader { companion object { @Synchronized @JvmStatic fun maybeLoadSoLibrary() { + SoLoader.loadLibrary("react_newarchdefaults") try { SoLoader.loadLibrary("appmodules") } catch (e: UnsatisfiedLinkError) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt index 3413162cdd98ce..3da64bac3f0c3a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultTurboModuleManagerDelegate.kt @@ -13,7 +13,6 @@ import com.facebook.react.ReactPackage import com.facebook.react.ReactPackageTurboModuleManagerDelegate import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.common.annotations.UnstableReactNativeAPI -import com.facebook.react.internal.turbomodule.core.NativeModuleSoLoader import com.facebook.react.runtime.cxxreactpackage.CxxReactPackage /** @@ -70,8 +69,7 @@ private constructor( private companion object { init { - NativeModuleSoLoader.maybeLoadSoLibrary() - AppModulesSoLoader.maybeLoadSoLibrary() + DefaultSoLoader.maybeLoadSoLibrary() } @DoNotStrip diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index 9978dac7f7112c..488cd4aa29ee08 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -130,6 +130,7 @@ add_react_android_subdir(src/main/jni/react/mapbuffer) add_react_android_subdir(src/main/jni/react/reactnativeblob) add_react_android_subdir(src/main/jni/react/fabric) add_react_android_subdir(src/main/jni/react/featureflags) +add_react_android_subdir(src/main/jni/react/newarchdefaults) add_react_android_subdir(src/main/jni/react/hermes/reactexecutor) add_react_android_subdir(src/main/jni/react/hermes/instrumentation/) add_react_android_subdir(src/main/jni/react/runtime/cxxreactpackage) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp index 6d3b78b604565f..bcdf164ffab430 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/OnLoad.cpp @@ -9,7 +9,6 @@ #include "Binding.h" #include "ComponentFactory.h" -#include "DefaultComponentsRegistry.h" #include "EventBeatManager.h" #include "EventEmitterWrapper.h" #include "JEmptyReactNativeConfig.h" @@ -19,11 +18,10 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { return facebook::jni::initialize(vm, [] { facebook::react::Binding::registerNatives(); - facebook::react::ComponentFactory::registerNatives(); - facebook::react::DefaultComponentsRegistry::registerNatives(); facebook::react::EventBeatManager::registerNatives(); facebook::react::EventEmitterWrapper::registerNatives(); facebook::react::StateWrapperImpl::registerNatives(); + facebook::react::ComponentFactory::registerNatives(); facebook::react::SurfaceHandlerBinding::registerNatives(); facebook::react::JEmptyReactNativeConfig::registerNatives(); }); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt new file mode 100644 index 00000000000000..932157aee86e37 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_compile_options(-fexceptions -frtti -std=c++20 -Wall -DLOG_TAG=\"ReactNative\") + +file(GLOB react_newarchdefaults_SRC CONFIGURE_DEPENDS *.cpp) + +add_library(react_newarchdefaults SHARED ${react_newarchdefaults_SRC}) + +target_include_directories(react_newarchdefaults PUBLIC .) + +target_link_libraries(react_newarchdefaults + fbjni + fabricjni + react_featureflagsjni + react_nativemodule_core + react_codegen_rncore + react_cxxreactpackage + react_nativemodule_defaults + react_nativemodule_dom + react_nativemodule_featureflags + react_nativemodule_microtasks + react_nativemodule_idlecallbacks + jsi) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.cpp rename to packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.cpp diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.h b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/fabric/DefaultComponentsRegistry.h rename to packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultComponentsRegistry.h diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.cpp rename to packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.h b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h similarity index 100% rename from packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/DefaultTurboModuleManagerDelegate.h rename to packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.h diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp new file mode 100644 index 00000000000000..a66675651cd015 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/OnLoad.cpp @@ -0,0 +1,18 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include "DefaultComponentsRegistry.h" +#include "DefaultTurboModuleManagerDelegate.h" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { + return facebook::jni::initialize(vm, [] { + facebook::react::DefaultTurboModuleManagerDelegate::registerNatives(); + facebook::react::DefaultComponentsRegistry::registerNatives(); + }); +} diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt index 57eb1cef70b468..4c7aeb1f896427 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/CMakeLists.txt @@ -44,7 +44,6 @@ target_link_libraries(callinvokerholder add_library( turbomodulejsijni SHARED - DefaultTurboModuleManagerDelegate.cpp ReactCommon/BindingsInstallerHolder.cpp ReactCommon/CompositeTurboModuleManagerDelegate.cpp ReactCommon/OnLoad.cpp @@ -61,8 +60,6 @@ target_link_libraries(turbomodulejsijni fb fbjni jsi - react_cxxreactpackage react_nativemodule_core - react_nativemodule_defaults callinvokerholder reactperfloggerjni) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp index b0cbd198d9572e..013e2ca94f0764 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/turbomodule/ReactCommon/OnLoad.cpp @@ -10,7 +10,6 @@ #include #include "CompositeTurboModuleManagerDelegate.h" -#include "DefaultTurboModuleManagerDelegate.h" #include "TurboModuleManager.h" void jniEnableCppLogging( @@ -27,7 +26,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { // "ComponentDescriptorFactory" is defined in Fabric facebook::react::TurboModuleManager::registerNatives(); - facebook::react::DefaultTurboModuleManagerDelegate::registerNatives(); facebook::react::CompositeTurboModuleManagerDelegate::registerNatives(); facebook::jni::registerNatives( diff --git a/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt b/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt index 338a224ef877b9..3a440e009b0c7a 100644 --- a/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/runtime/CMakeLists.txt @@ -30,6 +30,8 @@ target_link_libraries( bridgeless jserrorhandler fabricjni + react_featureflagsjni + turbomodulejsijni fb jsi jsireact From ad3df84668f1624e830396364c331783c6f99948 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Mon, 1 Jul 2024 14:42:46 -0700 Subject: [PATCH 154/968] Add EventEmitter Code-gen support for Java and ObjC Turbo Modules (#45119) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45119 ## Changelog: [iOS][Added] - Add EventEmitter Code-gen support for Java and ObjC Turbo Modules Reviewed By: RSNara Differential Revision: D58929417 fbshipit-source-id: 5208ba5ecb5882d47c3827c2aa8e3a54a3d7f2b6 --- .../GenerateModuleObjCpp-test.js.snap | 352 ++++++++++++++++-- .../modules/GenerateModuleJavaSpec.js | 56 ++- .../modules/GenerateModuleJniCpp.js | 22 +- .../modules/GenerateModuleObjCpp/index.js | 15 +- .../serializeEventEmitter.js | 70 ++++ .../source/serializeModule.js | 35 +- .../modules/__test_fixtures__/fixtures.js | 124 ++++++ .../GenerateModuleCpp-test.js.snap | 33 ++ .../GenerateModuleH-test.js.snap | 172 +++++++++ .../GenerateModuleHObjCpp-test.js.snap | 142 ++++++- .../GenerateModuleJavaSpec-test.js.snap | 69 ++++ .../GenerateModuleJniCpp-test.js.snap | 45 +++ .../GenerateModuleJniH-test.js.snap | 86 +++++ .../GenerateModuleMm-test.js.snap | 131 +++++++ 14 files changed, 1305 insertions(+), 47 deletions(-) create mode 100644 packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeEventEmitter.js diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap index 0f545d88d4a096..e71b84d55960de 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap @@ -43,7 +43,13 @@ exports[`GenerateModuleObjCpp can generate a header file NativeModule specs 1`] @end -@interface NativeArrayTurboModuleSpecBase : NSObject +@interface NativeArrayTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -63,7 +69,13 @@ namespace facebook::react { @end -@interface NativeBooleanTurboModuleSpecBase : NSObject +@interface NativeBooleanTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -83,7 +95,13 @@ namespace facebook::react { @end -@interface NativeCallbackTurboModuleSpecBase : NSObject +@interface NativeCallbackTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -143,7 +161,13 @@ namespace JS { @end -@interface NativeEnumTurboModuleSpecBase : NSObject +@interface NativeEnumTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -168,7 +192,13 @@ namespace facebook::react { @end -@interface NativeNullableTurboModuleSpecBase : NSObject +@interface NativeNullableTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -188,7 +218,13 @@ namespace facebook::react { @end -@interface NativeNumberTurboModuleSpecBase : NSObject +@interface NativeNumberTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -361,7 +397,13 @@ namespace JS { @end -@interface NativeObjectTurboModuleSpecBase : NSObject +@interface NativeObjectTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -497,7 +539,13 @@ namespace JS { @end -@interface NativeOptionalObjectTurboModuleSpecBase : NSObject +@interface NativeOptionalObjectTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -567,7 +615,13 @@ namespace JS { @end -@interface NativePartialAnnotationTurboModuleSpecBase : NSObject +@interface NativePartialAnnotationTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -591,7 +645,13 @@ namespace facebook::react { @end -@interface NativePromiseTurboModuleSpecBase : NSObject +@interface NativePromiseTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -685,7 +745,13 @@ getValuegetValuegetValuegetValuegetValuey:(NSString *)getValuegetValuegetValuege @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -777,7 +843,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleArraysSpecBase : NSObject +@interface NativeSampleTurboModuleArraysSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -871,7 +943,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleNullableSpecBase : NSObject +@interface NativeSampleTurboModuleNullableSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -965,7 +1043,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleNullableAndOptionalSpecBase : NSObject +@interface NativeSampleTurboModuleNullableAndOptionalSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1059,7 +1143,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleOptionalSpecBase : NSObject +@interface NativeSampleTurboModuleOptionalSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1079,7 +1169,13 @@ namespace facebook::react { @end -@interface NativeStringTurboModuleSpecBase : NSObject +@interface NativeStringTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1459,7 +1555,13 @@ NS_ASSUME_NONNULL_BEGIN @end -@interface NativeArrayTurboModuleSpecBase : NSObject +@interface NativeArrayTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1479,7 +1581,13 @@ namespace facebook::react { @end -@interface NativeBooleanTurboModuleSpecBase : NSObject +@interface NativeBooleanTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1499,7 +1607,13 @@ namespace facebook::react { @end -@interface NativeCallbackTurboModuleSpecBase : NSObject +@interface NativeCallbackTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1559,7 +1673,13 @@ namespace JS { @end -@interface NativeEnumTurboModuleSpecBase : NSObject +@interface NativeEnumTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1584,7 +1704,13 @@ namespace facebook::react { @end -@interface NativeNullableTurboModuleSpecBase : NSObject +@interface NativeNullableTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1604,7 +1730,13 @@ namespace facebook::react { @end -@interface NativeNumberTurboModuleSpecBase : NSObject +@interface NativeNumberTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1777,7 +1909,13 @@ namespace JS { @end -@interface NativeObjectTurboModuleSpecBase : NSObject +@interface NativeObjectTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1913,7 +2051,13 @@ namespace JS { @end -@interface NativeOptionalObjectTurboModuleSpecBase : NSObject +@interface NativeOptionalObjectTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1983,7 +2127,13 @@ namespace JS { @end -@interface NativePartialAnnotationTurboModuleSpecBase : NSObject +@interface NativePartialAnnotationTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2007,7 +2157,13 @@ namespace facebook::react { @end -@interface NativePromiseTurboModuleSpecBase : NSObject +@interface NativePromiseTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2101,7 +2257,13 @@ getValuegetValuegetValuegetValuegetValuey:(NSString *)getValuegetValuegetValuege @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2193,7 +2355,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleArraysSpecBase : NSObject +@interface NativeSampleTurboModuleArraysSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2287,7 +2455,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleNullableSpecBase : NSObject +@interface NativeSampleTurboModuleNullableSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2381,7 +2555,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleNullableAndOptionalSpecBase : NSObject +@interface NativeSampleTurboModuleNullableAndOptionalSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2475,7 +2655,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleOptionalSpecBase : NSObject +@interface NativeSampleTurboModuleOptionalSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2495,7 +2681,13 @@ namespace facebook::react { @end -@interface NativeStringTurboModuleSpecBase : NSObject +@interface NativeStringTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -2849,6 +3041,12 @@ exports[`GenerateModuleObjCpp can generate an implementation file NativeModule s @implementation NativeArrayTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -2881,6 +3079,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeBooleanTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -2906,6 +3110,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeCallbackTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -2931,6 +3141,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeEnumTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeEnumTurboModule_StateType) @@ -2995,6 +3211,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeNullableTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -3048,6 +3270,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeNumberTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -3073,6 +3301,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeObjectTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectAE) @@ -3130,6 +3364,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeOptionalObjectTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -3148,6 +3388,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativePartialAnnotationTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativePartialAnnotationTurboModule_SpecGetSomeObjFromPartialSomeObjValue) @@ -3205,6 +3451,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativePromiseTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -3230,6 +3482,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetObjectShapeArg) @@ -3343,6 +3601,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeSampleTurboModuleArraysSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -3445,6 +3709,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeSampleTurboModuleNullableSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeSampleTurboModuleNullable_SpecGetObjectShapeArg) @@ -3558,6 +3828,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeSampleTurboModuleNullableAndOptionalSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg) @@ -3671,6 +3947,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeSampleTurboModuleOptionalSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeSampleTurboModuleOptional_SpecGetObjectShapeArg) @@ -3784,6 +4066,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeStringTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js index ee3237d5d8c0cf..86f94fbcee40cc 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js @@ -12,6 +12,7 @@ import type { NamedShape, + NativeModuleEventEmitterShape, NativeModuleFunctionTypeAnnotation, NativeModuleParamTypeAnnotation, NativeModulePropertyShape, @@ -23,6 +24,7 @@ import type {AliasResolver} from './Utils'; const {unwrapNullable} = require('../../parsers/parsers-commons'); const {wrapOptional} = require('../TypeUtils/Java'); +const {toPascalCase} = require('../Utils'); const {createAliasResolver, getModules} = require('./Utils'); type FilesOutput = Map; @@ -32,11 +34,13 @@ function FileTemplate( packageName: string, className: string, jsName: string, + eventEmitters: string, methods: string, imports: string, }>, ): string { - const {packageName, className, jsName, methods, imports} = config; + const {packageName, className, jsName, eventEmitters, methods, imports} = + config; return ` /** * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). @@ -65,11 +69,28 @@ public abstract class ${className} extends ReactContextBaseJavaModule implements return NAME; } -${methods} +${eventEmitters}${eventEmitters.length > 0 ? '\n\n' : ''}${methods} } `; } +function EventEmitterTemplate( + eventEmitter: NativeModuleEventEmitterShape, + imports: Set, +): string { + return ` protected final void emit${toPascalCase(eventEmitter.name)}(${ + eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation' + ? `${translateEventEmitterTypeToJavaType(eventEmitter, imports)} value` + : '' + }) { + mEventEmitterCallback.invoke("${eventEmitter.name}"${ + eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation' + ? ', value' + : '' + }); + }`; +} + function MethodTemplate( config: $ReadOnly<{ abstract: boolean, @@ -102,6 +123,34 @@ function MethodTemplate( type Param = NamedShape>; +function translateEventEmitterTypeToJavaType( + eventEmitter: NativeModuleEventEmitterShape, + imports: Set, +): string { + switch (eventEmitter.typeAnnotation.typeAnnotation.type) { + case 'StringTypeAnnotation': + return 'String'; + case 'NumberTypeAnnotation': + case 'FloatTypeAnnotation': + case 'DoubleTypeAnnotation': + case 'Int32TypeAnnotation': + return 'double'; + case 'BooleanTypeAnnotation': + return 'boolean'; + case 'ObjectTypeAnnotation': + case 'TypeAliasTypeAnnotation': + imports.add('com.facebook.react.bridge.ReadableMap'); + return 'ReadableMap'; + case 'ArrayTypeAnnotation': + imports.add('com.facebook.react.bridge.ReadableArray'); + return 'ReadableArray'; + default: + throw new Error( + `Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`, + ); + } +} + function translateFunctionParamToJavaType( param: Param, createErrorMessage: (typeName: string) => string, @@ -533,6 +582,9 @@ module.exports = { packageName: normalizedPackageName, className, jsName: moduleName, + eventEmitters: spec.eventEmitters + .map(eventEmitter => EventEmitterTemplate(eventEmitter, imports)) + .join('\n\n'), methods: methods.filter(Boolean).join('\n\n'), imports: Array.from(imports) .sort() diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js index 2930ab1be9a0be..92e642118d1b01 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js @@ -12,6 +12,7 @@ import type { NamedShape, + NativeModuleEventEmitterShape, NativeModuleFunctionTypeAnnotation, NativeModuleParamTypeAnnotation, NativeModulePropertyShape, @@ -54,9 +55,11 @@ const HostFunctionTemplate = ({ const ModuleClassConstructorTemplate = ({ hasteModuleName, + eventEmitters, methods, }: $ReadOnly<{ hasteModuleName: string, + eventEmitters: $ReadOnlyArray, methods: $ReadOnlyArray<{ propertyName: string, argCount: number, @@ -69,7 +72,21 @@ ${methods .map(({propertyName, argCount}) => { return ` methodMap_["${propertyName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${propertyName}};`; }) - .join('\n')} + .join('\n')}${ + eventEmitters.length > 0 + ? eventEmitters + .map(eventEmitter => { + return ` + eventEmitterMap_["${eventEmitter.name}"] = std::make_shared>();`; + }) + .join('') + : '' + }${ + eventEmitters.length > 0 + ? ` + setEventEmitterCallback(params.instance);` + : '' + } }`.trim(); }; @@ -438,7 +455,7 @@ module.exports = { .map(hasteModuleName => { const { aliasMap, - spec: {methods}, + spec: {eventEmitters, methods}, } = nativeModules[hasteModuleName]; const resolveAlias = createAliasResolver(aliasMap); @@ -457,6 +474,7 @@ module.exports = { '\n\n' + ModuleClassConstructorTemplate({ hasteModuleName, + eventEmitters, methods: methods .map(({name: propertyName, typeAnnotation}) => { const [{returnTypeAnnotation, params}] = diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js index e1a8d02cf36f17..defe5722f29a03 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js @@ -15,6 +15,7 @@ import type {MethodSerializationOutput} from './serializeMethod'; const {createAliasResolver, getModules} = require('../Utils'); const {serializeStruct} = require('./header/serializeStruct'); +const {EventEmitterHeaderTemplate} = require('./serializeEventEmitter'); const {serializeMethod} = require('./serializeMethod'); const {serializeModuleSource} = require('./source/serializeModule'); const {StructCollector} = require('./StructCollector'); @@ -24,10 +25,12 @@ type FilesOutput = Map; const ModuleDeclarationTemplate = ({ hasteModuleName, structDeclarations, + eventEmitters, protocolMethods, }: $ReadOnly<{ hasteModuleName: string, structDeclarations: string, + eventEmitters: string, protocolMethods: string, }>) => `${structDeclarations} @protocol ${hasteModuleName}Spec @@ -36,7 +39,13 @@ ${protocolMethods} @end -@interface ${hasteModuleName}SpecBase : NSObject +@interface ${hasteModuleName}SpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + +${eventEmitters} @end namespace facebook::react { @@ -191,6 +200,9 @@ module.exports = { ModuleDeclarationTemplate({ hasteModuleName: hasteModuleName, structDeclarations: structStrs.join('\n'), + eventEmitters: spec.eventEmitters + .map(eventEmitter => EventEmitterHeaderTemplate(eventEmitter)) + .join('\n'), protocolMethods: methodSerializations .map(({protocolMethod}) => protocolMethod) .join('\n'), @@ -204,6 +216,7 @@ module.exports = { hasteModuleName, generatedStructs, hasteModuleName, + spec.eventEmitters, methodSerializations.filter( ({selector}) => selector !== '@selector(constantsToExport)', ), diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeEventEmitter.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeEventEmitter.js new file mode 100644 index 00000000000000..aa8e2bb752681d --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeEventEmitter.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import type {NativeModuleEventEmitterShape} from '../../../CodegenSchema'; + +const {toPascalCase} = require('../../Utils'); + +function getEventEmitterTypeObjCType( + eventEmitter: NativeModuleEventEmitterShape, +): string { + switch (eventEmitter.typeAnnotation.typeAnnotation.type) { + case 'StringTypeAnnotation': + return 'NSString *_Nonnull'; + case 'NumberTypeAnnotation': + return 'NSNumber *_Nonnull'; + case 'BooleanTypeAnnotation': + return 'BOOL'; + case 'ObjectTypeAnnotation': + case 'TypeAliasTypeAnnotation': + return 'NSDictionary *'; + case 'ArrayTypeAnnotation': + return 'NSArray> *'; + default: + throw new Error( + `Unsupported eventType for ${eventEmitter.name}. Found: ${eventEmitter.typeAnnotation.typeAnnotation.type}`, + ); + } +} + +function EventEmitterHeaderTemplate( + eventEmitter: NativeModuleEventEmitterShape, +): string { + return `- (void)emit${toPascalCase(eventEmitter.name)}${ + eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation' + ? `:(${getEventEmitterTypeObjCType(eventEmitter)})value` + : '' + };`; +} + +function EventEmitterImplementationTemplate( + eventEmitter: NativeModuleEventEmitterShape, +): string { + return `- (void)emit${toPascalCase(eventEmitter.name)}${ + eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation' + ? `:(${getEventEmitterTypeObjCType(eventEmitter)})value` + : '' + } +{ + _eventEmitterCallback("${eventEmitter.name}", ${ + eventEmitter.typeAnnotation.typeAnnotation.type !== 'VoidTypeAnnotation' + ? eventEmitter.typeAnnotation.typeAnnotation.type !== + 'BooleanTypeAnnotation' + ? 'value' + : '[NSNumber numberWithBool:value]' + : 'nil' + }); +}`; +} + +module.exports = { + EventEmitterHeaderTemplate, + EventEmitterImplementationTemplate, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js index f4760f2f7f3cb6..10e3c2eeec9c6c 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js @@ -10,24 +10,39 @@ 'use strict'; +import type {NativeModuleEventEmitterShape} from '../../../../CodegenSchema'; import type { MethodSerializationOutput, StructParameterRecord, } from '../serializeMethod'; import type {Struct} from '../StructCollector'; +const { + EventEmitterImplementationTemplate, +} = require('./../serializeEventEmitter'); + const ModuleTemplate = ({ hasteModuleName, structs, moduleName, + eventEmitters, methodSerializationOutputs, }: $ReadOnly<{ hasteModuleName: string, structs: $ReadOnlyArray, moduleName: string, + eventEmitters: $ReadOnlyArray, methodSerializationOutputs: $ReadOnlyArray, }>) => ` @implementation ${hasteModuleName}SpecBase +${eventEmitters + .map(eventEmitter => EventEmitterImplementationTemplate(eventEmitter)) + .join('\n')} + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end ${structs @@ -58,7 +73,23 @@ namespace facebook::react { argCount, }), ) - .join('\n' + ' '.repeat(8))} + .join('\n' + ' '.repeat(8))}${ + eventEmitters.length > 0 + ? eventEmitters + .map(eventEmitter => { + return ` + eventEmitterMap_["${eventEmitter.name}"] = std::make_shared>();`; + }) + .join('') + : '' +}${ + eventEmitters.length > 0 + ? ` + setEventEmitterCallback([&](const std::string &name, id value) { + static_cast &>(*eventEmitterMap_[name]).emit(value); + });` + : '' +} } } // namespace facebook::react`; @@ -112,12 +143,14 @@ function serializeModuleSource( hasteModuleName: string, structs: $ReadOnlyArray, moduleName: string, + eventEmitters: $ReadOnlyArray, methodSerializationOutputs: $ReadOnlyArray, ): string { return ModuleTemplate({ hasteModuleName, structs: structs.filter(({context}) => context !== 'CONSTANTS'), moduleName, + eventEmitters, methodSerializationOutputs, }); } diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js index aea2ffbcfbaccd..adbc596c38a84b 100644 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js @@ -27,6 +27,129 @@ const EMPTY_NATIVE_MODULES: SchemaType = { }, }; +const EVENT_EMITTER_MODULES: SchemaType = { + modules: { + NativeSampleTurboModule: { + type: 'NativeModule', + aliasMap: { + ObjectStruct: { + type: 'ObjectTypeAnnotation', + properties: [ + { + name: 'a', + optional: false, + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + { + name: 'b', + optional: false, + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + { + name: 'c', + optional: true, + typeAnnotation: { + type: 'NullableTypeAnnotation', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + }, + ], + }, + }, + enumMap: {}, + spec: { + eventEmitters: [ + { + name: 'onEvent1', + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: { + type: 'VoidTypeAnnotation', + }, + }, + }, + { + name: 'onEvent2', + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: { + type: 'StringTypeAnnotation', + }, + }, + }, + { + name: 'onEvent3', + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: { + type: 'NumberTypeAnnotation', + }, + }, + }, + { + name: 'onEvent4', + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: { + type: 'BooleanTypeAnnotation', + }, + }, + }, + { + name: 'onEvent5', + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: { + type: 'TypeAliasTypeAnnotation', + name: 'ObjectStruct', + }, + }, + }, + { + name: 'onEvent6', + optional: false, + typeAnnotation: { + type: 'EventEmitterTypeAnnotation', + typeAnnotation: { + type: 'ArrayTypeAnnotation', + elementType: { + type: 'TypeAliasTypeAnnotation', + name: 'ObjectStruct', + }, + }, + }, + }, + ], + methods: [ + { + name: 'voidFunc', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + }, + params: [], + }, + }, + ], + }, + moduleName: 'SampleTurboModule', + }, + }, +}; + const SIMPLE_NATIVE_MODULES: SchemaType = { modules: { NativeSampleTurboModule: { @@ -2435,6 +2558,7 @@ module.exports = { complex_objects: COMPLEX_OBJECTS, two_modules_different_files: TWO_MODULES_DIFFERENT_FILES, empty_native_modules: EMPTY_NATIVE_MODULES, + event_emitter_module: EVENT_EMITTER_MODULES, simple_native_modules: SIMPLE_NATIVE_MODULES, native_modules_with_type_aliases: NATIVE_MODULES_WITH_TYPE_ALIASES, real_module_example: REAL_MODULE_EXAMPLE, diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index dcfbcaa3e16023..8e0045608a7ed4 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -352,6 +352,39 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared } +} // namespace facebook::react +", +} +`; + +exports[`GenerateModuleCpp can generate fixture event_emitter_module 1`] = ` +Map { + "event_emitter_moduleJSI-generated.cpp" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleCpp.js + */ + +#include \\"event_emitter_moduleJSI.h\\" + +namespace facebook::react { + +static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->voidFunc( + rt + ); + return jsi::Value::undefined(); +} + +NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule(\\"SampleTurboModule\\", jsInvoker) { + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc}; +} + + } // namespace facebook::react ", } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index ad2183e4e3d30a..b5d82e4b7754ef 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -1019,6 +1019,178 @@ private: } `; +exports[`GenerateModuleH can generate fixture event_emitter_module 1`] = ` +Map { + "event_emitter_moduleJSI.h" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleH.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + + + +#pragma mark - NativeSampleTurboModuleObjectStruct + +template +struct NativeSampleTurboModuleObjectStruct { + P0 a; + P1 b; + P2 c; + bool operator==(const NativeSampleTurboModuleObjectStruct &other) const { + return a == other.a && b == other.b && c == other.c; + } +}; + +template +struct NativeSampleTurboModuleObjectStructBridging { + static T types; + + static T fromJs( + jsi::Runtime &rt, + const jsi::Object &value, + const std::shared_ptr &jsInvoker) { + T result{ + bridging::fromJs(rt, value.getProperty(rt, \\"a\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"b\\"), jsInvoker), + bridging::fromJs(rt, value.getProperty(rt, \\"c\\"), jsInvoker)}; + return result; + } + +#ifdef DEBUG + static double aToJs(jsi::Runtime &rt, decltype(types.a) value) { + return bridging::toJs(rt, value); + } + + static jsi::String bToJs(jsi::Runtime &rt, decltype(types.b) value) { + return bridging::toJs(rt, value); + } + + static std::optional cToJs(jsi::Runtime &rt, decltype(types.c) value) { + return bridging::toJs(rt, value); + } +#endif + + static jsi::Object toJs( + jsi::Runtime &rt, + const T &value, + const std::shared_ptr &jsInvoker) { + auto result = facebook::jsi::Object(rt); + result.setProperty(rt, \\"a\\", bridging::toJs(rt, value.a, jsInvoker)); + result.setProperty(rt, \\"b\\", bridging::toJs(rt, value.b, jsInvoker)); + if (value.c) { + result.setProperty(rt, \\"c\\", bridging::toJs(rt, value.c.value(), jsInvoker)); + } + return result; + } +}; + +class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { +protected: + NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); + +public: + virtual void voidFunc(jsi::Runtime &rt) = 0; + +}; + +template +class JSI_EXPORT NativeSampleTurboModuleCxxSpec : public TurboModule { +public: + jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override { + return delegate_.get(rt, propName); + } + + static constexpr std::string_view kModuleName = \\"SampleTurboModule\\"; + +protected: + NativeSampleTurboModuleCxxSpec(std::shared_ptr jsInvoker) + : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), + delegate_(reinterpret_cast(this), jsInvoker) {} + + void emitOnEvent1() { + static_cast&>(*delegate_.eventEmitterMap_[\\"onEvent1\\"]).emit(); + } + + template void emitOnEvent2(OnEvent2Type value) { + static_assert(bridging::supportsFromJs, \\"value cannnot be converted to jsi::String\\"); + static_cast&>(*delegate_.eventEmitterMap_[\\"onEvent2\\"]).emit([jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, eventValue, jsInvoker); + }); + } + + template void emitOnEvent3(OnEvent3Type value) { + static_assert(bridging::supportsFromJs, \\"value cannnot be converted to double\\"); + static_cast&>(*delegate_.eventEmitterMap_[\\"onEvent3\\"]).emit([jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, eventValue, jsInvoker); + }); + } + + template void emitOnEvent4(OnEvent4Type value) { + static_assert(bridging::supportsFromJs, \\"value cannnot be converted to bool\\"); + static_cast&>(*delegate_.eventEmitterMap_[\\"onEvent4\\"]).emit([jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, eventValue, jsInvoker); + }); + } + + template void emitOnEvent5(OnEvent5Type value) { + static_assert(bridging::supportsFromJs, \\"value cannnot be converted to jsi::Object\\"); + static_cast&>(*delegate_.eventEmitterMap_[\\"onEvent5\\"]).emit([jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, eventValue, jsInvoker); + }); + } + + template void emitOnEvent6(std::vector value) { + static_assert(bridging::supportsFromJs, jsi::Array>, \\"value cannnot be converted to jsi::Array\\"); + static_cast&>(*delegate_.eventEmitterMap_[\\"onEvent6\\"]).emit([jsInvoker = jsInvoker_, eventValue = value](jsi::Runtime& rt) -> jsi::Value { + return bridging::toJs(rt, eventValue, jsInvoker); + }); + } + +private: + class Delegate : public NativeSampleTurboModuleCxxSpecJSI { + public: + Delegate(T *instance, std::shared_ptr jsInvoker) : + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + eventEmitterMap_[\\"onEvent1\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent2\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent3\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent4\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent5\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent6\\"] = std::make_shared>(); + } + + void voidFunc(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::voidFunc) == 1, + \\"Expected voidFunc(...) to have 1 parameters\\"); + + return bridging::callFromJs( + rt, &T::voidFunc, jsInvoker_, instance_); + } + + private: + friend class NativeSampleTurboModuleCxxSpec; + T *instance_; + }; + + Delegate delegate_; +}; + +} // namespace facebook::react +", +} +`; + exports[`GenerateModuleH can generate fixture native_modules_with_type_aliases 1`] = ` Map { "native_modules_with_type_aliasesJSI.h" => "/** diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap index 994c04389b79fb..3fafff6f52f24b 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap @@ -41,7 +41,13 @@ Map { @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -211,7 +217,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -410,7 +422,13 @@ Map { @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -428,6 +446,76 @@ namespace facebook::react { } `; +exports[`GenerateModuleHObjCpp can generate fixture event_emitter_module 1`] = ` +Map { + "event_emitter_module.h" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif + +// Avoid multiple includes of event_emitter_module symbols +#ifndef event_emitter_module_H +#define event_emitter_module_H + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +@protocol NativeSampleTurboModuleSpec + +- (void)voidFunc; + +@end + +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + +- (void)emitOnEvent1; +- (void)emitOnEvent2:(NSString *_Nonnull)value; +- (void)emitOnEvent3:(NSNumber *_Nonnull)value; +- (void)emitOnEvent4:(BOOL)value; +- (void)emitOnEvent5:(NSDictionary *)value; +- (void)emitOnEvent6:(NSArray> *)value; +@end + +namespace facebook::react { + /** + * ObjC++ class for module 'NativeSampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; +} // namespace facebook::react + +#endif // event_emitter_module_H +", +} +`; + exports[`GenerateModuleHObjCpp can generate fixture native_modules_with_type_aliases 1`] = ` Map { "native_modules_with_type_aliases.h" => "/** @@ -535,7 +623,13 @@ namespace JS { @end -@interface AliasTurboModuleSpecBase : NSObject +@interface AliasTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -677,7 +771,13 @@ namespace JS { @end -@interface NativeCameraRollManagerSpecBase : NSObject +@interface NativeCameraRollManagerSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -746,7 +846,13 @@ namespace JS { @end -@interface NativeExceptionsManagerSpecBase : NSObject +@interface NativeExceptionsManagerSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -954,7 +1060,13 @@ namespace JS { @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1025,7 +1137,13 @@ Map { @end -@interface NativeSampleTurboModuleSpecBase : NSObject +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { @@ -1044,7 +1162,13 @@ namespace facebook::react { @end -@interface NativeSampleTurboModule2SpecBase : NSObject +@interface NativeSampleTurboModule2SpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + @end namespace facebook::react { diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap index 875476d45acaae..4da79695dade85 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap @@ -157,6 +157,75 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo } `; +exports[`GenerateModuleJavaSpec can generate fixture event_emitter_module 1`] = ` +Map { + "java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => " +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJavaSpec.js + * + * @nolint + */ + +package com.facebook.fbreact.specs; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import javax.annotation.Nonnull; + +public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule { + public static final String NAME = \\"SampleTurboModule\\"; + + public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public @Nonnull String getName() { + return NAME; + } + + protected final void emitOnEvent1() { + mEventEmitterCallback.invoke(\\"onEvent1\\"); + } + + protected final void emitOnEvent2(String value) { + mEventEmitterCallback.invoke(\\"onEvent2\\", value); + } + + protected final void emitOnEvent3(double value) { + mEventEmitterCallback.invoke(\\"onEvent3\\", value); + } + + protected final void emitOnEvent4(boolean value) { + mEventEmitterCallback.invoke(\\"onEvent4\\", value); + } + + protected final void emitOnEvent5(ReadableMap value) { + mEventEmitterCallback.invoke(\\"onEvent5\\", value); + } + + protected final void emitOnEvent6(ReadableArray value) { + mEventEmitterCallback.invoke(\\"onEvent6\\", value); + } + + @ReactMethod + @DoNotStrip + public abstract void voidFunc(); +} +", +} +`; + exports[`GenerateModuleJavaSpec can generate fixture native_modules_with_type_aliases 1`] = ` Map { "java/com/facebook/fbreact/specs/AliasTurboModuleSpec.java" => " diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap index 27f98851161d91..c929bfd55c57b7 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap @@ -172,6 +172,51 @@ std::shared_ptr empty_native_modules_ModuleProvider(const std::stri } `; +exports[`GenerateModuleJniCpp can generate fixture event_emitter_module 1`] = ` +Map { + "jni/event_emitter_module-generated.cpp" => " +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJniCpp.js + */ + +#include \\"event_emitter_module.h\\" + +namespace facebook::react { + +static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static jmethodID cachedMethodId = nullptr; + return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"voidFunc\\", \\"()V\\", args, count, cachedMethodId); +} + +NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) + : JavaTurboModule(params) { + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + eventEmitterMap_[\\"onEvent1\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent2\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent3\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent4\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent5\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent6\\"] = std::make_shared>(); + setEventEmitterCallback(params.instance); +} + +std::shared_ptr event_emitter_module_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"SampleTurboModule\\") { + return std::make_shared(params); + } + return nullptr; +} + +} // namespace facebook::react +", +} +`; + exports[`GenerateModuleJniCpp can generate fixture native_modules_with_type_aliases 1`] = ` Map { "jni/native_modules_with_type_aliases-generated.cpp" => " diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index 72877187166bd8..c2df3b016bc167 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -341,6 +341,92 @@ target_compile_options( } `; +exports[`GenerateModuleJniH can generate fixture event_emitter_module 1`] = ` +Map { + "jni/event_emitter_module.h" => " +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJniH.js + */ + +#pragma once + +#include +#include +#include + +namespace facebook::react { + +/** + * JNI C++ class for module 'NativeSampleTurboModule' + */ +class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { +public: + NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); +}; + + +JSI_EXPORT +std::shared_ptr event_emitter_module_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms); + +} // namespace facebook::react +", + "jni/CMakeLists.txt" => "# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp react/renderer/components/event_emitter_module/*.cpp) + +add_library( + react_codegen_event_emitter_module + SHARED + \${react_codegen_SRCS} +) + +target_include_directories(react_codegen_event_emitter_module PUBLIC . react/renderer/components/event_emitter_module) + +target_link_libraries( + react_codegen_event_emitter_module + fbjni + folly_runtime + glog + jsi + react_codegen_rncore + react_debug + react_nativemodule_core + react_render_componentregistry + react_render_core + react_render_debug + react_render_graphics + react_render_imagemanager + react_render_mapbuffer + react_utils + rrc_image + rrc_view + yoga +) + +target_compile_options( + react_codegen_event_emitter_module + PRIVATE + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + -fexceptions + -frtti + -std=c++20 + -Wall +) +", +} +`; + exports[`GenerateModuleJniH can generate fixture native_modules_with_type_aliases 1`] = ` Map { "jni/native_modules_with_type_aliases.h" => " diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap index cce63ca537aaf3..13be394c79d815 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap @@ -19,6 +19,12 @@ Map { @implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -53,6 +59,12 @@ Map { @implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) @@ -191,6 +203,12 @@ Map { @implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -206,6 +224,83 @@ namespace facebook::react { } `; +exports[`GenerateModuleMm can generate fixture event_emitter_module 1`] = ` +Map { + "event_emitter_module-generated.mm" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#import \\"event_emitter_module.h\\" + + +@implementation NativeSampleTurboModuleSpecBase +- (void)emitOnEvent1 +{ + _eventEmitterCallback(\\"onEvent1\\", nil); +} +- (void)emitOnEvent2:(NSString *_Nonnull)value +{ + _eventEmitterCallback(\\"onEvent2\\", value); +} +- (void)emitOnEvent3:(NSNumber *_Nonnull)value +{ + _eventEmitterCallback(\\"onEvent3\\", value); +} +- (void)emitOnEvent4:(BOOL)value +{ + _eventEmitterCallback(\\"onEvent4\\", [NSNumber numberWithBool:value]); +} +- (void)emitOnEvent5:(NSDictionary *)value +{ + _eventEmitterCallback(\\"onEvent5\\", value); +} +- (void)emitOnEvent6:(NSArray> *)value +{ + _eventEmitterCallback(\\"onEvent6\\", value); +} + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} +@end + + +namespace facebook::react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + eventEmitterMap_[\\"onEvent1\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent2\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent3\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent4\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent5\\"] = std::make_shared>(); + eventEmitterMap_[\\"onEvent6\\"] = std::make_shared>(); + setEventEmitterCallback([&](const std::string &name, id value) { + static_cast &>(*eventEmitterMap_[name]).emit(value); + }); + } +} // namespace facebook::react +", +} +`; + exports[`GenerateModuleMm can generate fixture native_modules_with_type_aliases 1`] = ` Map { "native_modules_with_type_aliases-generated.mm" => "/** @@ -225,6 +320,12 @@ Map { @implementation AliasTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (AliasTurboModule_OptionsOffset) @@ -287,6 +388,12 @@ Map { @implementation NativeCameraRollManagerSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) @@ -324,6 +431,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeExceptionsManagerSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @implementation RCTCxxConvert (NativeExceptionsManager_StackFrame) @@ -402,6 +515,12 @@ Map { @implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -532,6 +651,12 @@ Map { @implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end @@ -550,6 +675,12 @@ namespace facebook::react { } // namespace facebook::react @implementation NativeSampleTurboModule2SpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} @end From 54dadd7bda0431548760aab0fade57f083d716a8 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 2 Jul 2024 02:40:49 -0700 Subject: [PATCH 155/968] fix: add JvmStatic to all methods used in cpp (#45243) Summary: Following-up on https://github.com/facebook/react-native/pull/45230, I added all the needed `JvmStatic` annotations for methods used in cpp code here: https://github.com/facebook/hermes/blob/f5c867514c71b25212eb3039230e0c095518b532/lib/Platform/Unicode/PlatformUnicodeJava.cpp. ## Changelog: [ANDROID] [FIXED] - Use `JvmStatic` annotations for all methods from `AndroidUnicodeUtils.kt` Pull Request resolved: https://github.com/facebook/react-native/pull/45243 Test Plan: Try and use those methods to see that they don't crash on `cpp` side. Reviewed By: cortinico Differential Revision: D59264093 Pulled By: dmytrorykun fbshipit-source-id: 07d683ee38ea1c7d9621ad2e37d04f3d484d3200 --- .../java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt index e784606489e8c7..96fdfb3a7d60b3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/hermes/unicode/AndroidUnicodeUtils.kt @@ -20,12 +20,14 @@ import java.util.Locale public object AndroidUnicodeUtils { @DoNotStrip + @JvmStatic public fun localeCompare(left: String?, right: String?): Int { val collator = Collator.getInstance() return collator.compare(left, right) } @DoNotStrip + @JvmStatic public fun dateFormat(unixtimeMs: Double, formatDate: Boolean, formatTime: Boolean): String { val format = when { @@ -53,6 +55,7 @@ public object AndroidUnicodeUtils { } @DoNotStrip + @JvmStatic public fun normalize(input: String?, form: Int): String = when (form) { FORM_C -> Normalizer.normalize(input, Normalizer.Form.NFC) From 7edc7169c785cd7a4381c8584bb1ea4bb21576cc Mon Sep 17 00:00:00 2001 From: Thibault Malbranche Date: Tue, 2 Jul 2024 02:41:49 -0700 Subject: [PATCH 156/968] chore: changelog for 0.74.3 (#45238) Summary: Adds changelog for the 0.74.3 patch. ## Changelog: [Internal] [Changed] - Add 0.74.3 changelog Pull Request resolved: https://github.com/facebook/react-native/pull/45238 Reviewed By: cortinico Differential Revision: D59263876 Pulled By: dmytrorykun fbshipit-source-id: 0f16d51a01790b4ddcaca092dec7527aab386dcd --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index babea0c2433441..f217cc8b466f2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -416,6 +416,35 @@ - Use our fork of the react-native-communti/cli-platform-ios use_native_modues.rb script ([c884d19a50](https://github.com/facebook/react-native/commit/c884d19a501081ffbc4b353d751ecc3e32d6f624) by [@blakef](https://github.com/blakef)) - Enforce Activities using ReactDelegate implement DefaultHardwareBackBtnHandler. ([a2d277f740](https://github.com/facebook/react-native/commit/a2d277f740d8ee95137d42679a1ffd872962a108) by [@javache](https://github.com/javache)) +## v0.74.3 + +### Added + +- Add the ReactMarkerConstants.CONTENT_APPEARED support on Android in bridgeless mode. ([3c4d7618f0](https://github.com/facebook/react-native/commit/3c4d7618f00751b08f73ffcec9ef1f69d44136da) by [@Kudo](https://github.com/Kudo)) + +### Changed + +- Feat: update CLI to 13.6.9 ([d1e2a35061](https://github.com/facebook/react-native/commit/d1e2a3506152abde9b870b1a63f16d00ec277ea6) by [@szymonrybczak](https://github.com/szymonrybczak)) + + +#### iOS specific + +- Support `customizeRootView` from `RCTRootViewFactory` ([3c4d761](https://github.com/facebook/react-native/commit/3c4d7618f00751b08f73ffcec9ef1f69d44136da) by [@Kudo](https://github.com/Kudo)) + +### Fixed + +- Codegen computes output path relative to project root instead of current working directory. ([d3e0430dea](https://github.com/facebook/react-native/commit/d3e0430deac573fd44792e6005d5de20e9ad2797) by [@dmytrorykun](https://github.com/dmytrorykun)) + + +### Android specific + +- Android native rejections should be instanceof Error ([f4b0fcb9](https://github.com/facebook/react-native/commit/f4b0fcb92263667754348f82030f85cc941846ba) by [huzhanbo1996](https://github.com/huzhanbo1996)) +- Tentative fix for NPE `JavaTimerManager$IdleCallbackRunnable.cancel` ([988bf162a0](https://github.com/facebook/react-native/commit/988bf162a0f36d9919cebbebc1fca27b58be4ae5) by [@cortinico](https://github.com/cortinico)) + +#### iOS specific + +- Fixed Multiline TextInput with a fixed height scrolls to the bottom when changing AttributedText ([e210c7c5](https://github.com/facebook/react-native/commit/e210c7c5741202a6e1b372731b50fdb59a7232bb) by [@fabOnReact](https://github.com/fabOnReact)) +- Fixed border being drawn over children when no color was set ([a2b52af3](https://github.com/facebook/react-native/commit/a2b52af3bcc273cf85f01510c24d4e8da1b45656) by [@j-piasecki](https://github.com/j-piasecki)) ## v0.74.2 From ffd0b39755af3c096df5329a367d5a708a015a48 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 2 Jul 2024 03:25:23 -0700 Subject: [PATCH 157/968] Changelog for 0.75.0-rc.3 (#45244) Summary: Just updating the changelog for 0.75.0-rc.3 ## Changelog: [INTERNAL] - Changelog for 0.75.0-rc.3 Pull Request resolved: https://github.com/facebook/react-native/pull/45244 Test Plan: NA Reviewed By: rshest, blakef Differential Revision: D59269046 Pulled By: cortinico fbshipit-source-id: b5124c1574786d90c4bb65feb24328de86169718 --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f217cc8b466f2e..f9de0318f8ece3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v0.75.0-rc.2 +## v0.75.0-rc.3 ### Breaking @@ -24,6 +24,7 @@ #### Android specific +- Removing `ReactJsExceptionHandler` param from ReactHostImpl() constructor and providing a default private implementation ([fe7e7a015f](https://github.com/facebook/react-native/commit/fe7e7a015f30697c4ccffb2ba6474611efb4c08a) by [@alanleedev](https://github.com/alanleedev)) - Set and require `android:supportsRtl="true"` for RTL layout ([82c6f8a580](https://github.com/facebook/react-native/commit/82c6f8a58056cfa163a61a4e6668a54625b15d06) by [@NickGerleman](https://github.com/NickGerleman)) - Enable flex gap percentage value for RN. ([41a14962fc](https://github.com/facebook/react-native/commit/41a14962fc7adaf434f1634b17f3d66261e30a9f) by [@realsoelynn](https://github.com/realsoelynn)) - `DevSupportManagerFactory.create()` changed to take an additional parameter of type `PausedInDebuggerOverlayManager` (nullable) ([1d26907ca4](https://github.com/facebook/react-native/commit/1d26907ca4d00cfa52f6395624b3121a7e96aca1) by [@motiz88](https://github.com/motiz88)) @@ -218,6 +219,8 @@ ### Fixed +- Add missing `NativeState` methods to the `WithRuntimeDecorator` class. ([218ea5d44c](https://github.com/facebook/react-native/commit/218ea5d44cae5774b1445cbc9e07d1ea3ef773d1) by [@bartlomiejbloniarz](https://github.com/bartlomiejbloniarz)) +- Codegen computes output path relative to project root instead of current working directory. ([d3e0430dea](https://github.com/facebook/react-native/commit/d3e0430deac573fd44792e6005d5de20e9ad2797) by [@dmytrorykun](https://github.com/dmytrorykun)) - Fix logbox reporting for React errors ([64e6721b23](https://github.com/facebook/react-native/commit/64e6721b23e9f3c35d42d5b1f1b68220e46a34ed) by [@yungsters](https://github.com/yungsters)) - Add option for multiple `mountingOverrideDelegates` ([358fe46969](https://github.com/facebook/react-native/commit/358fe46969654932e73af94127c05e6ce5ed7049) by [@WoLewicki](https://github.com/WoLewicki)) - Fix clicking items on the inverted FlatList on the new architecture ([3753b7a0e7](https://github.com/facebook/react-native/commit/3753b7a0e78f8820e5f5150dd9bdf1b53145a7bd) by [@kosmydel](https://github.com/kosmydel)) @@ -262,6 +265,8 @@ #### Android specific +- Fix autolink plugin for libraries that are platform-specific ([20521cc908](https://github.com/facebook/react-native/commit/20521cc908a347e3a2b3ac0fd6710946f18b1510) by [@gabrieldonadel](https://github.com/gabrieldonadel)) +- Fix crash due to missing JvmStatic to `convertToCase` ([cef17ba14f](https://github.com/facebook/react-native/commit/cef17ba14f435b966d2ffd9b3660ccf28fe03b6c) by [@cortinico](https://github.com/cortinico)) - Show RedBox after reloads fail (bridgeless) ([2f8d4f0c25](https://github.com/facebook/react-native/commit/2f8d4f0c253853ec4f56cf01b41a1f73a393f804) by [@RSNara](https://github.com/RSNara)) - Unmount React root when activity is destroyed on bridgless ([33aa83a0e6](https://github.com/facebook/react-native/commit/33aa83a0e6f63d3d50d4803074ad9e2243439100) by [@fabriziocucci](https://github.com/fabriziocucci)) - Better overflow support for ScrollView, Text, TextInput ([bfb3b7008d](https://github.com/facebook/react-native/commit/bfb3b7008d3e83400154b0348e7ab680ee06aa8c) by [@NickGerleman](https://github.com/NickGerleman)) @@ -304,6 +309,8 @@ #### iOS specific + +- Auto linking script of script phase ([e320ab47cf](https://github.com/facebook/react-native/commit/e320ab47cf855f2e5de74ea448ec292cf0bbb29a)) - Fix the accessibility label not being applied to text components on the new architecture ([9922628032](https://github.com/facebook/react-native/commit/9922628032ace4d87257c1b3d70c2dc6c38a60a6) by [@j-piasecki](https://github.com/j-piasecki)) - Fixes NSDataBigString length calculation ([9d637e4622](https://github.com/facebook/react-native/commit/9d637e4622781568b143b8585909b73211a0f8ba) by [@zhongwuzw](https://github.com/zhongwuzw)) - Fix `InputAccessoryView` width on device orientation change ([8597727c28](https://github.com/facebook/react-native/commit/8597727c28d9cb77012f3f4ebb032c335246d589) by [@mauriciomeirelles](https://github.com/mauriciomeirelles)) @@ -359,6 +366,9 @@ ### Unknown +- Release 0.75.0-rc.3 ([15b55714eb](https://github.com/facebook/react-native/commit/15b55714eb4ac0ece5ab9e553601826286a464da) by [@react-native-bot](https://github.com/react-native-bot)) +- Bump hermes to hermes-2024-07-01-RNv0.75.0-1edbe36ce92fef2c4d427f5c4e104f2758f4b692 ([2ab13798f9](https://github.com/facebook/react-native/commit/2ab13798f9636da321cbe5fbffdb47834fc130ac) by [@cortinico](https://github.com/cortinico)) +- Fix type import in testing scripts ([f938e3214c](https://github.com/facebook/react-native/commit/f938e3214c8ecc11d2075494b5fdd535487f71d2) by [@cipolleschi](https://github.com/cipolleschi)) - Release 0.75.0-rc.2 ([668358c47a](https://github.com/facebook/react-native/commit/668358c47ad9cbe699bc3e497f8cae84dcdd1459) by [@react-native-bot](https://github.com/react-native-bot)) - Bump RC in testing script ([865aaeda58](https://github.com/facebook/react-native/commit/865aaeda582a4e7ba50a5e3877058bd3d02026c8) by [@cipolleschi](https://github.com/cipolleschi)) - Bump CLI to 14.0.0-alpha.11 ([6a155dd1cf](https://github.com/facebook/react-native/commit/6a155dd1cf45e7d96811e73db9d455c846e4bc9e) by [@cortinico](https://github.com/cortinico)) @@ -409,6 +419,7 @@ - Fix Helloworld ios jobs ([2a0c175135](https://github.com/facebook/react-native/commit/2a0c1751353d4a245ddd94f1cff6fa543deac7b6) by [@cipolleschi](https://github.com/cipolleschi)) - Bump Podfile.lock ([52db082576](https://github.com/facebook/react-native/commit/52db082576dba69d1fd092e2a5ad13d3274a6fc3) by [@cipolleschi](https://github.com/cipolleschi)) +- Bump Podfile.lock to RC.2 ([1f10d62700](https://github.com/facebook/react-native/commit/1f10d627002d9606bab08a4096a894eab954a989) by [@cipolleschi](https://github.com/cipolleschi)) #### Failed to parse From 258ea84f465a46b3a39f9921566745967c6e83f6 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 2 Jul 2024 04:22:43 -0700 Subject: [PATCH 158/968] Further refine the Gradle caching logic. (#45233) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45233 We want the Gradle cache to be written only on main/-stable branches run, and only for jobs with `cache-read-only` == false (i.e. `build_android`). This changes implements it. Changelog: [Internal] [Changed] - Further refine the Gradle caching logic. Reviewed By: blakef Differential Revision: D59225944 fbshipit-source-id: b6c3a5d4d0d399d6fe42287976925c43f3f12eb7 --- .github/actions/setup-gradle/action.yml | 9 +++++---- .github/workflows/nightly.yml | 2 +- .github/workflows/publish-release.yml | 2 +- .github/workflows/test-all.yml | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/actions/setup-gradle/action.yml b/.github/actions/setup-gradle/action.yml index 20afa2898a1a13..f83ef1ee707c08 100644 --- a/.github/actions/setup-gradle/action.yml +++ b/.github/actions/setup-gradle/action.yml @@ -1,9 +1,9 @@ name: Setup gradle description: "Set up your GitHub Actions workflow with a specific version of gradle" inputs: - cache-allow-write: - description: "Wether the Gradle Cache should be allowed to be written by this job or not" - default: "false" + cache-read-only: + description: "Wether the Gradle Cache should be in read-only mode so this job won't be allowed to write to it" + default: "true" runs: using: "composite" steps: @@ -11,4 +11,5 @@ runs: uses: gradle/actions/setup-gradle@v3 with: gradle-version: wrapper - cache-read-only: ${{ inputs.cache-allow-write == 'false' }} + # We want the Gradle cache to be written only on main/-stable branches run, and only for jobs with `cache-read-only` == false (i.e. `build_android`). + cache-read-only: ${{ (github.ref != 'refs/heads/main' && !contains(github.ref, '-stable')) || inputs.cache-read-only == 'true' }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2bec7b84e7b87d..592e7eb87c9e55 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -520,7 +520,7 @@ jobs: - name: Setup gradle uses: ./.github/actions/setup-gradle with: - cache-allow-write: "true" + cache-read-only: "false" - name: Build and publish all the Android Artifacts to /tmp/maven-local run: | # By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs. diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 6b9a0869c551d1..b7b0031755d342 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -517,7 +517,7 @@ jobs: - name: Setup gradle uses: ./.github/actions/setup-gradle with: - cache-allow-write: "true" + cache-read-only: "false" - name: Build and publish all the Android Artifacts to /tmp/maven-local run: | # By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs. diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 748315fbf4c45b..1611562e76c6dc 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -432,7 +432,7 @@ jobs: with: jsengine: ${{ matrix.jsengine }} architecture: ${{ matrix.architecture }} - run-unit-tests: 'false' + run-unit-tests: "false" use-frameworks: StaticLibraries hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} @@ -593,7 +593,7 @@ jobs: - name: Setup gradle uses: ./.github/actions/setup-gradle with: - cache-allow-write: "true" + cache-read-only: "false" - name: Build and publish all the Android Artifacts to /tmp/maven-local run: | # By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs. From c25246044f51b770ff1e090d6b4ec78d41ec917f Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 2 Jul 2024 05:17:33 -0700 Subject: [PATCH 159/968] Migrate test_js to GHA (#45246) Summary: This migrates the `test_js` workflow to GHA ## Changelog: [INTERNAL] - Migrate test_js to GHA Pull Request resolved: https://github.com/facebook/react-native/pull/45246 Test Plan: Will wait for CI Reviewed By: javache Differential Revision: D59270333 Pulled By: cortinico fbshipit-source-id: e77eb9819e0819638c51e61b1e477ac04680a2f4 --- .github/actions/test-js/action.yml | 27 +++++++++++++++++++ .github/workflows/test-all.yml | 14 ++++++++++ .../GenerateModuleJniH-test.js.snap | 1 + 3 files changed, 42 insertions(+) create mode 100644 .github/actions/test-js/action.yml diff --git a/.github/actions/test-js/action.yml b/.github/actions/test-js/action.yml new file mode 100644 index 00000000000000..c3256264e105c7 --- /dev/null +++ b/.github/actions/test-js/action.yml @@ -0,0 +1,27 @@ +name: test-js +description: Runs all the JS tests in the codebase +inputs: + node-version: + description: 'The node.js version to use' + required: false + default: '18' +runs: + using: composite + steps: + - name: Setup node.js + uses: ./.github/actions/setup-node + with: + node-version: ${{ inputs.node-version }} + - name: Yarn install + shell: bash + run: yarn install --non-interactive + - name: Run Tests - JavaScript Tests + shell: bash + run: node ./scripts/run-ci-javascript-tests.js --maxWorkers 2 + - name: Upload test results + if: ${{ always() }} + uses: actions/upload-artifact@v4.3.0 + with: + name: test-js-results + compression-level: 1 + path: ./reports/junit diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 1611562e76c6dc..e29f7360cbb62b 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -929,3 +929,17 @@ jobs: use-frameworks: ${{ matrix.use_frameworks }} hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }} react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }} + + test_js: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: ["20", "18"] + steps: + - name: Checkout + uses: actions/checkout@v4.1.1 + - name: Test JS + uses: ./.github/actions/test-js + with: + node-version: ${{ matrix.node-version }} diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index c2df3b016bc167..ec844a0ccb92e3 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -411,6 +411,7 @@ target_link_libraries( react_utils rrc_image rrc_view + turbomodulejsijni yoga ) From 818e70f7ebfd7f1960fd6b930cf9513e737df199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 2 Jul 2024 07:58:37 -0700 Subject: [PATCH 160/968] Set up experiment to fix race conditions when doing Fabric state updates on Android (#45236) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45236 Changelog: [internal] ## Context We're currently observing inconsistencies between the state of the UI on Android and the propagated state in Fabric. When investigating the issue, we saw that there are some state updates that were going to be dispatched from scroll views to Fabric were skipped because the state object in native was deallocated. The reason for that is a race condition between: 1. Dispatching new state updates from the UI thread 2. Updating the state previously dispatched from the UI thread on the JS thread. {F1735383134} ## Changes This creates a new feature flag to replace the weak reference with a strong one, so when the previous state is deallocated we can still access it to set new state. The use of weak references was introduced in D44472121 to avoid holding onto JSI references (which could be contained in the state) when the runtime was deallocated, but we later introduced an explicit clean up mechanism in D45905628 that would make that unnecessary. Reviewed By: javache Differential Revision: D59233070 fbshipit-source-id: 018d8935f506430ecab96df0f7a998a37ee0f556 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 ++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 +++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../react/fabric/FabricMountingManager.cpp | 6 +- .../jni/react/fabric/StateWrapperImpl.cpp | 62 +++++++++++++++---- .../main/jni/react/fabric/StateWrapperImpl.h | 5 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 ++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +- .../featureflags/ReactNativeFeatureFlags.h | 7 ++- .../ReactNativeFeatureFlagsAccessor.cpp | 46 +++++++++----- .../ReactNativeFeatureFlagsAccessor.h | 6 +- .../ReactNativeFeatureFlagsDefaults.h | 6 +- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 ++- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 5 ++ .../featureflags/ReactNativeFeatureFlags.js | 7 ++- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 22 files changed, 189 insertions(+), 50 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index ccddca4abb1338..9650cafef4b7ba 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<9a33a6bc10cdb2b0f9fcb15805a06982>> + * @generated SignedSource<> */ /** @@ -100,6 +100,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = accessor.fixMappingOfEventPrioritiesBetweenFabricAndReact() + /** + * Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates. + */ + @JvmStatic + public fun fixMissedFabricStateUpdatesOnAndroid(): Boolean = accessor.fixMissedFabricStateUpdatesOnAndroid() + /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 884795d8109fd9..444f6937c4dd01 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5d67280406c16b01ba71b7b75e814a79>> + * @generated SignedSource<<92ebcb510939039fc157e0f85b08073e>> */ /** @@ -32,6 +32,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null + private var fixMissedFabricStateUpdatesOnAndroidCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null private var forceBatchingMountItemsOnAndroidCache: Boolean? = null private var fuseboxEnabledDebugCache: Boolean? = null @@ -154,6 +155,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean { + var cached = fixMissedFabricStateUpdatesOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.fixMissedFabricStateUpdatesOnAndroid() + fixMissedFabricStateUpdatesOnAndroidCache = cached + } + return cached + } + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean { var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 9abef85cb31492..8d2e3d244e00b5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<154baea748cdf7b8e05a1e4448053673>> + * @generated SignedSource<<2434a09bc40a30291c642a26453f939f>> */ /** @@ -52,6 +52,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean + @DoNotStrip @JvmStatic public external fun fixMissedFabricStateUpdatesOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean @DoNotStrip @JvmStatic public external fun forceBatchingMountItemsOnAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 04d17b77e8cce5..935248b2e16be0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<34bbd584a612fa88cc6adf2d2bc51b92>> + * @generated SignedSource<> */ /** @@ -47,6 +47,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false + override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean = false + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean = false override fun forceBatchingMountItemsOnAndroid(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 9d3d163dc48c76..8d20e04f5cc1e5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<65a88218f057b56211d84b6d473e8a90>> */ /** @@ -36,6 +36,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null + private var fixMissedFabricStateUpdatesOnAndroidCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null private var forceBatchingMountItemsOnAndroidCache: Boolean? = null private var fuseboxEnabledDebugCache: Boolean? = null @@ -170,6 +171,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean { + var cached = fixMissedFabricStateUpdatesOnAndroidCache + if (cached == null) { + cached = currentProvider.fixMissedFabricStateUpdatesOnAndroid() + accessedFeatureFlags.add("fixMissedFabricStateUpdatesOnAndroid") + fixMissedFabricStateUpdatesOnAndroidCache = cached + } + return cached + } + override fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean { var cached = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index eb3e21e12782a8..9809e6de5242a4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<3a0f547e2b68072a76b1eabc28c371cb>> */ /** @@ -47,6 +47,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean + @DoNotStrip public fun fixMissedFabricStateUpdatesOnAndroid(): Boolean + @DoNotStrip public fun fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(): Boolean @DoNotStrip public fun forceBatchingMountItemsOnAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index ab08744f65e0db..13124ea84be524 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -540,7 +540,7 @@ void FabricMountingManager::executeMount( if (mountItem.newChildShadowView.state != nullptr) { javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = mountItem.newChildShadowView.state; + cStateWrapper->setState(mountItem.newChildShadowView.state); } // Do not hold a reference to javaEventEmitter from the C++ side. @@ -615,7 +615,7 @@ void FabricMountingManager::executeMount( if (state != nullptr) { javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = state; + cStateWrapper->setState(state); } (*objBufferArray)[objBufferPosition++] = @@ -823,7 +823,7 @@ void FabricMountingManager::preallocateShadowView( if (shadowView.state != nullptr) { javaStateWrapper = StateWrapperImpl::newObjectJavaArgs(); StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper); - cStateWrapper->state_ = shadowView.state; + cStateWrapper->setState(shadowView.state); } // Do not hold a reference to javaEventEmitter from the C++ side. diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp index bf5c18e5dd9793..6ea03ff22e8a09 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp @@ -7,6 +7,7 @@ #include "StateWrapperImpl.h" #include +#include #include #include #include @@ -25,30 +26,65 @@ jni::local_ref StateWrapperImpl::initHybrid( jni::local_ref StateWrapperImpl::getStateDataImpl() { - if (auto state = state_.lock()) { - folly::dynamic map = state->getDynamic(); - return ReadableNativeMap::newObjectCxxArgs(std::move(map)); + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + if (state_) { + folly::dynamic map = state_->getDynamic(); + return ReadableNativeMap::newObjectCxxArgs(std::move(map)); + } else { + return nullptr; + } } else { - return nullptr; + if (auto state = weakState_.lock()) { + folly::dynamic map = state->getDynamic(); + return ReadableNativeMap::newObjectCxxArgs(std::move(map)); + } else { + return nullptr; + } } } jni::local_ref StateWrapperImpl::getStateMapBufferDataImpl() { - if (auto state = state_.lock()) { - MapBuffer map = state->getMapBuffer(); - return JReadableMapBuffer::createWithContents(std::move(map)); + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + if (state_) { + MapBuffer map = state_->getMapBuffer(); + return JReadableMapBuffer::createWithContents(std::move(map)); + } else { + return nullptr; + } } else { - return nullptr; + if (auto state = weakState_.lock()) { + MapBuffer map = state->getMapBuffer(); + return JReadableMapBuffer::createWithContents(std::move(map)); + } else { + return nullptr; + } } } void StateWrapperImpl::updateStateImpl(NativeMap* map) { - if (auto state = state_.lock()) { - // Get folly::dynamic from map - auto dynamicMap = map->consume(); - // Set state - state->updateState(std::move(dynamicMap)); + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + if (state_) { + // Get folly::dynamic from map + auto dynamicMap = map->consume(); + // Set state + state_->updateState(std::move(dynamicMap)); + } + } else { + if (auto state = weakState_.lock()) { + // Get folly::dynamic from map + auto dynamicMap = map->consume(); + // Set state + state->updateState(std::move(dynamicMap)); + } + } +} + +void StateWrapperImpl::setState(std::shared_ptr state) { + if (ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid()) { + state_ = state; + } else { + weakState_ = state; } } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h index 3aac2e0a7e923e..542f78c69ae9a4 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.h @@ -28,11 +28,12 @@ class StateWrapperImpl : public jni::HybridClass { jni::local_ref getStateMapBufferDataImpl(); jni::local_ref getStateDataImpl(); void updateStateImpl(NativeMap* map); - - std::weak_ptr state_; + void setState(std::shared_ptr state); private: jni::alias_ref jhybridobject_; + std::weak_ptr weakState_; + std::shared_ptr state_; static jni::local_ref initHybrid(jni::alias_ref); }; diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index d5ad1a7f1c8bd7..864feb38252dd0 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<88f5b83b8a3d7902eaab333246b59ed3>> + * @generated SignedSource<> */ /** @@ -111,6 +111,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool fixMissedFabricStateUpdatesOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixMissedFabricStateUpdatesOnAndroid"); + return method(javaProvider_); + } + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); @@ -253,6 +259,11 @@ bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabri return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); } +bool JReactNativeFeatureFlagsCxxInterop::fixMissedFabricStateUpdatesOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); @@ -371,6 +382,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "fixMappingOfEventPrioritiesBetweenFabricAndReact", JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact), + makeNativeMethod( + "fixMissedFabricStateUpdatesOnAndroid", + JReactNativeFeatureFlagsCxxInterop::fixMissedFabricStateUpdatesOnAndroid), makeNativeMethod( "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak", JReactNativeFeatureFlagsCxxInterop::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index f9e1381671a8d2..c56d27ac58109e 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<66b47850d8e211f78b3e3dd40b6cc37e>> + * @generated SignedSource<<7e9c48995f6a5f4e0a56c0f2ec784def>> */ /** @@ -66,6 +66,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool fixMappingOfEventPrioritiesBetweenFabricAndReact( facebook::jni::alias_ref); + static bool fixMissedFabricStateUpdatesOnAndroid( + facebook::jni::alias_ref); + static bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index ce3f391dffb348..0e5aa5d0d3c079 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<91a56189178d461874bfff11b14ca318>> */ /** @@ -69,6 +69,10 @@ bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact(); } +bool ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid() { + return getAccessor().fixMissedFabricStateUpdatesOnAndroid(); +} + bool ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() { return getAccessor().fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 014c51420923e8..6d285f927f7bf6 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6683bcf499d88e4449f570f38b7d8b2f>> */ /** @@ -97,6 +97,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); + /** + * Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates. + */ + RN_EXPORT static bool fixMissedFabricStateUpdatesOnAndroid(); + /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 179d23099e1b3f..88938c188ba388 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<44087cc6e946a05884c8761987878183>> + * @generated SignedSource<> */ /** @@ -245,6 +245,24 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::fixMissedFabricStateUpdatesOnAndroid() { + auto flagValue = fixMissedFabricStateUpdatesOnAndroid_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(12, "fixMissedFabricStateUpdatesOnAndroid"); + + flagValue = currentProvider_->fixMissedFabricStateUpdatesOnAndroid(); + fixMissedFabricStateUpdatesOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() { auto flagValue = fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_.load(); @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCa // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); + markFlagAsAccessed(13, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(14, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "fuseboxEnabledDebug"); + markFlagAsAccessed(15, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "fuseboxEnabledRelease"); + markFlagAsAccessed(16, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "lazyAnimationCallbacks"); + markFlagAsAccessed(17, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::preventDoubleTextMeasure() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "preventDoubleTextMeasure"); + markFlagAsAccessed(18, "preventDoubleTextMeasure"); flagValue = currentProvider_->preventDoubleTextMeasure(); preventDoubleTextMeasure_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "setAndroidLayoutDirection"); + markFlagAsAccessed(19, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(20, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "useModernRuntimeScheduler"); + markFlagAsAccessed(21, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(22, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(24, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "useStateAlignmentMechanism"); + markFlagAsAccessed(25, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 092b983a4ce39a..15292516808ccf 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<45258896e458cce165b403e043356eb9>> + * @generated SignedSource<> */ /** @@ -43,6 +43,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableSynchronousStateUpdates(); bool enableUIConsistency(); bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); + bool fixMissedFabricStateUpdatesOnAndroid(); bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); bool forceBatchingMountItemsOnAndroid(); bool fuseboxEnabledDebug(); @@ -66,7 +67,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 25> accessedFeatureFlags_; + std::array, 26> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowCollapsableChildren_; @@ -80,6 +81,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableSynchronousStateUpdates_; std::atomic> enableUIConsistency_; std::atomic> fixMappingOfEventPrioritiesBetweenFabricAndReact_; + std::atomic> fixMissedFabricStateUpdatesOnAndroid_; std::atomic> fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_; std::atomic> forceBatchingMountItemsOnAndroid_; std::atomic> fuseboxEnabledDebug_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 8af86e0d7383ca..71f852585305a6 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0f6ca616cc516096ec250d61be440952>> + * @generated SignedSource<> */ /** @@ -75,6 +75,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool fixMissedFabricStateUpdatesOnAndroid() override { + return false; + } + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 87d9985fa20fab..c1d0b662c97959 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3da295d89796e905588eb863a51c2054>> + * @generated SignedSource<<57b9e4f683df27a7a5770633e88f8b22>> */ /** @@ -37,6 +37,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableSynchronousStateUpdates() = 0; virtual bool enableUIConsistency() = 0; virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0; + virtual bool fixMissedFabricStateUpdatesOnAndroid() = 0; virtual bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() = 0; virtual bool forceBatchingMountItemsOnAndroid() = 0; virtual bool fuseboxEnabledDebug() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 6951bd603166ce..7dab29de35d7e9 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<82399968da4f450b87c908031466a38a>> + * @generated SignedSource<<58b0c0c49dc6cf2ecdbc2c3038395e4e>> */ /** @@ -97,6 +97,11 @@ bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndR return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); } +bool NativeReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::fixMissedFabricStateUpdatesOnAndroid(); +} + bool NativeReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 2266b2292037af..01e02bc206374b 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6b8504e42d72611f4d4b6606d69c42aa>> + * @generated SignedSource<> */ /** @@ -59,6 +59,8 @@ class NativeReactNativeFeatureFlags bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime); + bool fixMissedFabricStateUpdatesOnAndroid(jsi::Runtime& runtime); + bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(jsi::Runtime& runtime); bool forceBatchingMountItemsOnAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 79884fb2b25019..8ae591d78f35f0 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -93,6 +93,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React.', }, + fixMissedFabricStateUpdatesOnAndroid: { + defaultValue: false, + description: + 'Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates.', + }, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 56cb85ac155578..0e252406c647f0 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<522f11a571457cb932f451cf81bd384a>> + * @generated SignedSource<<95a692d91055d05301a06fd33636d3fa>> * @flow strict-local */ @@ -53,6 +53,7 @@ export type ReactNativeFeatureFlags = { enableSynchronousStateUpdates: Getter, enableUIConsistency: Getter, fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter, + fixMissedFabricStateUpdatesOnAndroid: Getter, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: Getter, forceBatchingMountItemsOnAndroid: Getter, fuseboxEnabledDebug: Getter, @@ -161,6 +162,10 @@ export const enableUIConsistency: Getter = createNativeFlagGetter('enab * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. */ export const fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter = createNativeFlagGetter('fixMappingOfEventPrioritiesBetweenFabricAndReact', false); +/** + * Enables a fix to prevent the possibility of state updates in Fabric being missed due to race conditions with previous state updates. + */ +export const fixMissedFabricStateUpdatesOnAndroid: Getter = createNativeFlagGetter('fixMissedFabricStateUpdatesOnAndroid', false); /** * Fixes a leak in SurfaceMountingManager.mRemoveDeleteTreeUIFrameCallback */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 475f8fd79cf98d..c826385896be9c 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6715ba4954b31464c591597c53a2a0de>> + * @generated SignedSource<> * @flow strict-local */ @@ -35,6 +35,7 @@ export interface Spec extends TurboModule { +enableSynchronousStateUpdates?: () => boolean; +enableUIConsistency?: () => boolean; +fixMappingOfEventPrioritiesBetweenFabricAndReact?: () => boolean; + +fixMissedFabricStateUpdatesOnAndroid?: () => boolean; +fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak?: () => boolean; +forceBatchingMountItemsOnAndroid?: () => boolean; +fuseboxEnabledDebug?: () => boolean; From e35a2f4a7c58905f1d2b60720b91cc1daa8c0194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 2 Jul 2024 07:58:37 -0700 Subject: [PATCH 161/968] Set up experiment to fix incorrect state updates in smooth scroll animations on Android (#45237) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45237 Changelog: [internal] This creates a feature flag to test a fix for an incorrect state update dispatched to Fabric when using smooth scroll animations. Specifically, when starting a smooth scroll animation from X to Y, the scroll view would set the state to Y, and then all the range from X to Y again. For example, the sequence of state updates when smooth scrolling from 0 to 5 would be `0 -> 5 -> 1 -> 2 -> 3 -> 4 -> 5`, which is obviously incorrect. This flag prevents setting the final value before it's actually reached. Reviewed By: javache Differential Revision: D59233069 fbshipit-source-id: 221602d7d30635070e7776ce756e2ef438edf638 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 ++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 ++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../views/scroll/ReactScrollViewHelper.kt | 5 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../featureflags/ReactNativeFeatureFlags.cpp | 6 ++- .../featureflags/ReactNativeFeatureFlags.h | 7 ++- .../ReactNativeFeatureFlagsAccessor.cpp | 50 +++++++++++++------ .../ReactNativeFeatureFlagsAccessor.h | 6 ++- .../ReactNativeFeatureFlagsDefaults.h | 6 ++- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 ++- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 5 ++ .../featureflags/ReactNativeFeatureFlags.js | 7 ++- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 20 files changed, 140 insertions(+), 35 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 9650cafef4b7ba..fc5eb35082c3f7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<1cad606bd06ab650004955138228d227>> */ /** @@ -94,6 +94,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableUIConsistency(): Boolean = accessor.enableUIConsistency() + /** + * When doing a smooth scroll animation, it stops setting the state with the final scroll position in Fabric before the animation starts. + */ + @JvmStatic + public fun fixIncorrectScrollViewStateUpdateOnAndroid(): Boolean = accessor.fixIncorrectScrollViewStateUpdateOnAndroid() + /** * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 444f6937c4dd01..7cffabd731b093 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<92ebcb510939039fc157e0f85b08073e>> + * @generated SignedSource<> */ /** @@ -31,6 +31,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableMicrotasksCache: Boolean? = null private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null + private var fixIncorrectScrollViewStateUpdateOnAndroidCache: Boolean? = null private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null private var fixMissedFabricStateUpdatesOnAndroidCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null @@ -146,6 +147,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun fixIncorrectScrollViewStateUpdateOnAndroid(): Boolean { + var cached = fixIncorrectScrollViewStateUpdateOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.fixIncorrectScrollViewStateUpdateOnAndroid() + fixIncorrectScrollViewStateUpdateOnAndroidCache = cached + } + return cached + } + override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean { var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 8d2e3d244e00b5..77d9a0630f5167 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2434a09bc40a30291c642a26453f939f>> + * @generated SignedSource<<1b39ae121d8238bbb34c54330700c9e8>> */ /** @@ -50,6 +50,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableUIConsistency(): Boolean + @DoNotStrip @JvmStatic public external fun fixIncorrectScrollViewStateUpdateOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean @DoNotStrip @JvmStatic public external fun fixMissedFabricStateUpdatesOnAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 935248b2e16be0..46b8ef93e62646 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<0584cef0a5e682b2b3ba6d46161e0286>> */ /** @@ -45,6 +45,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableUIConsistency(): Boolean = false + override fun fixIncorrectScrollViewStateUpdateOnAndroid(): Boolean = false + override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false override fun fixMissedFabricStateUpdatesOnAndroid(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 8d20e04f5cc1e5..6cbe14bc7a7a70 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<65a88218f057b56211d84b6d473e8a90>> + * @generated SignedSource<> */ /** @@ -35,6 +35,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableMicrotasksCache: Boolean? = null private var enableSynchronousStateUpdatesCache: Boolean? = null private var enableUIConsistencyCache: Boolean? = null + private var fixIncorrectScrollViewStateUpdateOnAndroidCache: Boolean? = null private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null private var fixMissedFabricStateUpdatesOnAndroidCache: Boolean? = null private var fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeakCache: Boolean? = null @@ -161,6 +162,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun fixIncorrectScrollViewStateUpdateOnAndroid(): Boolean { + var cached = fixIncorrectScrollViewStateUpdateOnAndroidCache + if (cached == null) { + cached = currentProvider.fixIncorrectScrollViewStateUpdateOnAndroid() + accessedFeatureFlags.add("fixIncorrectScrollViewStateUpdateOnAndroid") + fixIncorrectScrollViewStateUpdateOnAndroidCache = cached + } + return cached + } + override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean { var cached = fixMappingOfEventPrioritiesBetweenFabricAndReactCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 9809e6de5242a4..9491dc6afa7906 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3a0f547e2b68072a76b1eabc28c371cb>> + * @generated SignedSource<> */ /** @@ -45,6 +45,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableUIConsistency(): Boolean + @DoNotStrip public fun fixIncorrectScrollViewStateUpdateOnAndroid(): Boolean + @DoNotStrip public fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean @DoNotStrip public fun fixMissedFabricStateUpdatesOnAndroid(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt index 879c7a70e6947b..633b26dd1c59f6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt @@ -19,6 +19,7 @@ import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.WritableMap import com.facebook.react.bridge.WritableNativeMap import com.facebook.react.common.ReactConstants +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel import com.facebook.react.uimanager.StateWrapper import com.facebook.react.uimanager.UIManagerHelper @@ -249,7 +250,9 @@ public object ReactScrollViewHelper { if (scrollY != y) { scrollView.startFlingAnimator(scrollY, y) } - updateFabricScrollState(scrollView, x, y) + if (ReactNativeFeatureFlags.fixIncorrectScrollViewStateUpdateOnAndroid()) { + updateFabricScrollState(scrollView, x, y) + } } /** Get current position or position after current animation finishes, if any. */ diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 864feb38252dd0..d9f26254dfbad1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<2e4bde6040e04475ee137722c9d2df24>> */ /** @@ -105,6 +105,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool fixIncorrectScrollViewStateUpdateOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixIncorrectScrollViewStateUpdateOnAndroid"); + return method(javaProvider_); + } + bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("fixMappingOfEventPrioritiesBetweenFabricAndReact"); @@ -254,6 +260,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableUIConsistency( return ReactNativeFeatureFlags::enableUIConsistency(); } +bool JReactNativeFeatureFlagsCxxInterop::fixIncorrectScrollViewStateUpdateOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::fixIncorrectScrollViewStateUpdateOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); @@ -379,6 +390,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableUIConsistency", JReactNativeFeatureFlagsCxxInterop::enableUIConsistency), + makeNativeMethod( + "fixIncorrectScrollViewStateUpdateOnAndroid", + JReactNativeFeatureFlagsCxxInterop::fixIncorrectScrollViewStateUpdateOnAndroid), makeNativeMethod( "fixMappingOfEventPrioritiesBetweenFabricAndReact", JReactNativeFeatureFlagsCxxInterop::fixMappingOfEventPrioritiesBetweenFabricAndReact), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index c56d27ac58109e..18f195971a9d99 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7e9c48995f6a5f4e0a56c0f2ec784def>> + * @generated SignedSource<> */ /** @@ -63,6 +63,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableUIConsistency( facebook::jni::alias_ref); + static bool fixIncorrectScrollViewStateUpdateOnAndroid( + facebook::jni::alias_ref); + static bool fixMappingOfEventPrioritiesBetweenFabricAndReact( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 0e5aa5d0d3c079..68f7fd2c5745c9 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<91a56189178d461874bfff11b14ca318>> + * @generated SignedSource<<4f7eb0f1d6cb613d81c9cf5d05a7c6ec>> */ /** @@ -65,6 +65,10 @@ bool ReactNativeFeatureFlags::enableUIConsistency() { return getAccessor().enableUIConsistency(); } +bool ReactNativeFeatureFlags::fixIncorrectScrollViewStateUpdateOnAndroid() { + return getAccessor().fixIncorrectScrollViewStateUpdateOnAndroid(); +} + bool ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact() { return getAccessor().fixMappingOfEventPrioritiesBetweenFabricAndReact(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 6d285f927f7bf6..53535de39548da 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6683bcf499d88e4449f570f38b7d8b2f>> + * @generated SignedSource<<70c78db13887af269fe4d6b2113510b2>> */ /** @@ -92,6 +92,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableUIConsistency(); + /** + * When doing a smooth scroll animation, it stops setting the state with the final scroll position in Fabric before the animation starts. + */ + RN_EXPORT static bool fixIncorrectScrollViewStateUpdateOnAndroid(); + /** * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 88938c188ba388..0ffad6a66aa82f 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -227,6 +227,24 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::fixIncorrectScrollViewStateUpdateOnAndroid() { + auto flagValue = fixIncorrectScrollViewStateUpdateOnAndroid_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(11, "fixIncorrectScrollViewStateUpdateOnAndroid"); + + flagValue = currentProvider_->fixIncorrectScrollViewStateUpdateOnAndroid(); + fixIncorrectScrollViewStateUpdateOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAndReact() { auto flagValue = fixMappingOfEventPrioritiesBetweenFabricAndReact_.load(); @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(12, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMissedFabricStateUpdatesOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "fixMissedFabricStateUpdatesOnAndroid"); + markFlagAsAccessed(13, "fixMissedFabricStateUpdatesOnAndroid"); flagValue = currentProvider_->fixMissedFabricStateUpdatesOnAndroid(); fixMissedFabricStateUpdatesOnAndroid_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::fixStoppedSurfaceRemoveDeleteTreeUIFrameCa // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); + markFlagAsAccessed(14, "fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak"); flagValue = currentProvider_->fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(15, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "fuseboxEnabledDebug"); + markFlagAsAccessed(16, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "fuseboxEnabledRelease"); + markFlagAsAccessed(17, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "lazyAnimationCallbacks"); + markFlagAsAccessed(18, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::preventDoubleTextMeasure() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "preventDoubleTextMeasure"); + markFlagAsAccessed(19, "preventDoubleTextMeasure"); flagValue = currentProvider_->preventDoubleTextMeasure(); preventDoubleTextMeasure_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "setAndroidLayoutDirection"); + markFlagAsAccessed(20, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(21, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "useModernRuntimeScheduler"); + markFlagAsAccessed(22, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(23, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(24, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(25, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "useStateAlignmentMechanism"); + markFlagAsAccessed(26, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 15292516808ccf..5a2c01905d6725 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<8b86c11a06dc9f53991482cb6640d806>> */ /** @@ -42,6 +42,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableMicrotasks(); bool enableSynchronousStateUpdates(); bool enableUIConsistency(); + bool fixIncorrectScrollViewStateUpdateOnAndroid(); bool fixMappingOfEventPrioritiesBetweenFabricAndReact(); bool fixMissedFabricStateUpdatesOnAndroid(); bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak(); @@ -67,7 +68,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 26> accessedFeatureFlags_; + std::array, 27> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowCollapsableChildren_; @@ -80,6 +81,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableMicrotasks_; std::atomic> enableSynchronousStateUpdates_; std::atomic> enableUIConsistency_; + std::atomic> fixIncorrectScrollViewStateUpdateOnAndroid_; std::atomic> fixMappingOfEventPrioritiesBetweenFabricAndReact_; std::atomic> fixMissedFabricStateUpdatesOnAndroid_; std::atomic> fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 71f852585305a6..50093b6f764154 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<79318071dbc264dabddac64a52bd5256>> */ /** @@ -71,6 +71,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool fixIncorrectScrollViewStateUpdateOnAndroid() override { + return false; + } + bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index c1d0b662c97959..28eba96b129c92 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<57b9e4f683df27a7a5770633e88f8b22>> + * @generated SignedSource<> */ /** @@ -36,6 +36,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableMicrotasks() = 0; virtual bool enableSynchronousStateUpdates() = 0; virtual bool enableUIConsistency() = 0; + virtual bool fixIncorrectScrollViewStateUpdateOnAndroid() = 0; virtual bool fixMappingOfEventPrioritiesBetweenFabricAndReact() = 0; virtual bool fixMissedFabricStateUpdatesOnAndroid() = 0; virtual bool fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 7dab29de35d7e9..3979ba78c8b715 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<58b0c0c49dc6cf2ecdbc2c3038395e4e>> + * @generated SignedSource<> */ /** @@ -92,6 +92,11 @@ bool NativeReactNativeFeatureFlags::enableUIConsistency( return ReactNativeFeatureFlags::enableUIConsistency(); } +bool NativeReactNativeFeatureFlags::fixIncorrectScrollViewStateUpdateOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::fixIncorrectScrollViewStateUpdateOnAndroid(); +} + bool NativeReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::fixMappingOfEventPrioritiesBetweenFabricAndReact(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 01e02bc206374b..50bd7f6b07d7b5 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<426ae84f1b0deeb7b0fda5fb29042909>> */ /** @@ -57,6 +57,8 @@ class NativeReactNativeFeatureFlags bool enableUIConsistency(jsi::Runtime& runtime); + bool fixIncorrectScrollViewStateUpdateOnAndroid(jsi::Runtime& runtime); + bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime); bool fixMissedFabricStateUpdatesOnAndroid(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 8ae591d78f35f0..bbbc009dd0810b 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -88,6 +88,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).', }, + fixIncorrectScrollViewStateUpdateOnAndroid: { + defaultValue: false, + description: + 'When doing a smooth scroll animation, it stops setting the state with the final scroll position in Fabric before the animation starts.', + }, fixMappingOfEventPrioritiesBetweenFabricAndReact: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 0e252406c647f0..3006b71891bdce 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<95a692d91055d05301a06fd33636d3fa>> + * @generated SignedSource<<250a4b89541fd36953e204c580123895>> * @flow strict-local */ @@ -52,6 +52,7 @@ export type ReactNativeFeatureFlags = { enableMicrotasks: Getter, enableSynchronousStateUpdates: Getter, enableUIConsistency: Getter, + fixIncorrectScrollViewStateUpdateOnAndroid: Getter, fixMappingOfEventPrioritiesBetweenFabricAndReact: Getter, fixMissedFabricStateUpdatesOnAndroid: Getter, fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak: Getter, @@ -158,6 +159,10 @@ export const enableSynchronousStateUpdates: Getter = createNativeFlagGe * Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution). */ export const enableUIConsistency: Getter = createNativeFlagGetter('enableUIConsistency', false); +/** + * When doing a smooth scroll animation, it stops setting the state with the final scroll position in Fabric before the animation starts. + */ +export const fixIncorrectScrollViewStateUpdateOnAndroid: Getter = createNativeFlagGetter('fixIncorrectScrollViewStateUpdateOnAndroid', false); /** * Uses the default event priority instead of the discreet event priority by default when dispatching events from Fabric to React. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index c826385896be9c..0174131de20c3b 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5436af4d7f25024a57ef557827a02ecb>> * @flow strict-local */ @@ -34,6 +34,7 @@ export interface Spec extends TurboModule { +enableMicrotasks?: () => boolean; +enableSynchronousStateUpdates?: () => boolean; +enableUIConsistency?: () => boolean; + +fixIncorrectScrollViewStateUpdateOnAndroid?: () => boolean; +fixMappingOfEventPrioritiesBetweenFabricAndReact?: () => boolean; +fixMissedFabricStateUpdatesOnAndroid?: () => boolean; +fixStoppedSurfaceRemoveDeleteTreeUIFrameCallbackLeak?: () => boolean; From 27ba369f2325db5678aaf6a18927c127921840e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Dr=C3=B3=C5=BCd=C5=BC?= Date: Tue, 2 Jul 2024 10:43:29 -0700 Subject: [PATCH 162/968] Add onUserLeaveHint support to ReactActivityDelegate (#43658) Summary: **This is a resubmission of the previous PRs. We are trying to figure out why it causes crashes in some apps.** This PR adds `onUserLeaveHint` support into the `ReactActivityDelegate`. It allows modules to receive an event every time user moves the app into the background. This is slightly different than `onPause` - it's called only when the user intentionally moves the app into the background, e.g. when receiving a call `onPause` should be called but `onUserLeaveHint` shouldn't. This feature is especially useful for libraries implementing features like Picture in Picture (PiP), where using `onUserLeaveHint` is the [recommended way of auto-entering PiP](https://developer.android.com/develop/ui/views/picture-in-picture#:~:text=You%20might%20want%20to%20include%20logic%20that%20switches%20an%20activity%20into%20PiP%20mode%20instead%20of%20going%20into%20the%20background.%20For%20example%2C%20Google%20Maps%20switches%20to%20PiP%20mode%20if%20the%20user%20presses%20the%20home%20or%20recents%20button%20while%20the%20app%20is%20navigating.%20You%20can%20catch%20this%20case%20by%20overriding%20onUserLeaveHint()%3A) for android < 12. ## Changelog: [ANDROID] [ADDED] - Added `onUserLeaveHint` support into `ReactActivityDelegate` Pull Request resolved: https://github.com/facebook/react-native/pull/43658 Test Plan: Tested in the `rn-tester` app - callbacks are correctly called on both old and new architecture. Reviewed By: javache Differential Revision: D56015911 Pulled By: cortinico fbshipit-source-id: fc41af30f697da6fe7db3dd6e579a702f90cf218 --- .../ReactAndroid/api/ReactAndroid.api | 10 ++++++++++ .../com/facebook/react/ReactActivity.java | 6 ++++++ .../facebook/react/ReactActivityDelegate.java | 6 ++++++ .../com/facebook/react/ReactDelegate.java | 10 ++++++++++ .../main/java/com/facebook/react/ReactHost.kt | 6 ++++++ .../facebook/react/ReactInstanceManager.java | 19 +++++++++++++++++++ .../react/bridge/ActivityEventListener.java | 4 ++++ .../facebook/react/bridge/ReactContext.java | 13 +++++++++++++ .../react/bridge/ReactMarkerConstants.java | 2 ++ .../facebook/react/runtime/ReactHostImpl.java | 12 ++++++++++++ 10 files changed, 88 insertions(+) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 99b24343aab50c..f3be3b8073515f 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -111,6 +111,7 @@ public abstract class com/facebook/react/ReactActivity : androidx/appcompat/app/ protected fun onPause ()V public fun onRequestPermissionsResult (I[Ljava/lang/String;[I)V protected fun onResume ()V + public fun onUserLeaveHint ()V public fun onWindowFocusChanged (Z)V public fun requestPermissions ([Ljava/lang/String;ILcom/facebook/react/modules/core/PermissionListener;)V } @@ -143,6 +144,7 @@ public class com/facebook/react/ReactActivityDelegate { public fun onPause ()V public fun onRequestPermissionsResult (I[Ljava/lang/String;[I)V public fun onResume ()V + public fun onUserLeaveHint ()V public fun onWindowFocusChanged (Z)V public fun requestPermissions ([Ljava/lang/String;ILcom/facebook/react/modules/core/PermissionListener;)V } @@ -171,6 +173,7 @@ public class com/facebook/react/ReactDelegate { public fun onKeyDown (ILandroid/view/KeyEvent;)Z public fun onKeyLongPress (I)Z public fun onNewIntent (Landroid/content/Intent;)Z + public fun onUserLeaveHint ()V public fun onWindowFocusChanged (Z)V public fun reload ()V public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z @@ -223,6 +226,7 @@ public abstract interface class com/facebook/react/ReactHost { public abstract fun onConfigurationChanged (Landroid/content/Context;)V public abstract fun onHostDestroy ()V public abstract fun onHostDestroy (Landroid/app/Activity;)V + public abstract fun onHostLeaveHint (Landroid/app/Activity;)V public abstract fun onHostPause ()V public abstract fun onHostPause (Landroid/app/Activity;)V public abstract fun onHostResume (Landroid/app/Activity;)V @@ -268,6 +272,7 @@ public class com/facebook/react/ReactInstanceManager { public fun onHostResume (Landroid/app/Activity;)V public fun onHostResume (Landroid/app/Activity;Lcom/facebook/react/modules/core/DefaultHardwareBackBtnHandler;)V public fun onNewIntent (Landroid/content/Intent;)V + public fun onUserLeaveHint (Landroid/app/Activity;)V public fun onWindowFocusChange (Z)V public fun recreateReactContextInBackground ()V public fun removeReactInstanceEventListener (Lcom/facebook/react/ReactInstanceEventListener;)V @@ -507,6 +512,7 @@ public class com/facebook/react/animated/NativeAnimatedNodesManager : com/facebo public abstract interface class com/facebook/react/bridge/ActivityEventListener { public abstract fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V public abstract fun onNewIntent (Landroid/content/Intent;)V + public fun onUserLeaveHint (Landroid/app/Activity;)V } public class com/facebook/react/bridge/Arguments { @@ -1139,6 +1145,7 @@ public abstract class com/facebook/react/bridge/ReactContext : android/content/C public fun onHostPause ()V public fun onHostResume (Landroid/app/Activity;)V public fun onNewIntent (Landroid/app/Activity;Landroid/content/Intent;)V + public fun onUserLeaveHint (Landroid/app/Activity;)V public fun onWindowFocusChange (Z)V public abstract fun registerSegment (ILjava/lang/String;Lcom/facebook/react/bridge/Callback;)V public fun removeActivityEventListener (Lcom/facebook/react/bridge/ActivityEventListener;)V @@ -1299,6 +1306,8 @@ public final class com/facebook/react/bridge/ReactMarkerConstants : java/lang/En public static final field ON_HOST_PAUSE_START Lcom/facebook/react/bridge/ReactMarkerConstants; public static final field ON_HOST_RESUME_END Lcom/facebook/react/bridge/ReactMarkerConstants; public static final field ON_HOST_RESUME_START Lcom/facebook/react/bridge/ReactMarkerConstants; + public static final field ON_USER_LEAVE_HINT_END Lcom/facebook/react/bridge/ReactMarkerConstants; + public static final field ON_USER_LEAVE_HINT_START Lcom/facebook/react/bridge/ReactMarkerConstants; public static final field PRE_REACT_CONTEXT_END Lcom/facebook/react/bridge/ReactMarkerConstants; public static final field PRE_RUN_JS_BUNDLE_START Lcom/facebook/react/bridge/ReactMarkerConstants; public static final field PRE_SETUP_REACT_CONTEXT_END Lcom/facebook/react/bridge/ReactMarkerConstants; @@ -3794,6 +3803,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React public fun onConfigurationChanged (Landroid/content/Context;)V public fun onHostDestroy ()V public fun onHostDestroy (Landroid/app/Activity;)V + public fun onHostLeaveHint (Landroid/app/Activity;)V public fun onHostPause ()V public fun onHostPause (Landroid/app/Activity;)V public fun onHostResume (Landroid/app/Activity;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java index 75e8f255d77e08..864b0454d5d0f2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java @@ -113,6 +113,12 @@ public void onNewIntent(Intent intent) { } } + @Override + public void onUserLeaveHint() { + super.onUserLeaveHint(); + mDelegate.onUserLeaveHint(); + } + @Override public void requestPermissions( String[] permissions, int requestCode, PermissionListener listener) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index d70d1c5187813b..a97ca10328ed73 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -138,6 +138,12 @@ protected void loadApp(String appKey) { getPlainActivity().setContentView(mReactDelegate.getReactRootView()); } + public void onUserLeaveHint() { + if (mReactDelegate != null) { + mReactDelegate.onUserLeaveHint(); + } + } + public void onPause() { mReactDelegate.onHostPause(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 8d3871dfe6c54d..66ba98fc91c6df 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -122,6 +122,16 @@ public void onHostResume() { } } + public void onUserLeaveHint() { + if (ReactFeatureFlags.enableBridgelessArchitecture) { + mReactHost.onHostLeaveHint(mActivity); + } else { + if (getReactNativeHost().hasInstance()) { + getReactNativeHost().getReactInstanceManager().onUserLeaveHint(mActivity); + } + } + } + public void onHostPause() { if (ReactFeatureFlags.enableBridgelessArchitecture) { mReactHost.onHostPause(mActivity); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt index 377b22b768a58e..531482de97d64d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt @@ -64,6 +64,12 @@ public interface ReactHost { /** To be called when the host activity is resumed. */ public fun onHostResume(activity: Activity?) + /** + * To be called when the host activity is about to go into the background as the result of user + * choice. + */ + public fun onHostLeaveHint(activity: Activity?) + /** To be called when the host activity is paused. */ public fun onHostPause(activity: Activity?) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 1f719d65b04d36..bd0454369a42cb 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -597,6 +597,25 @@ public void onHostPause() { moveToBeforeResumeLifecycleState(); } + /** + * This method should be called from {@link Activity#onUserLeaveHint()}. It notifies all listening + * modules that the user is about to leave the activity. The passed Activity is has to be the + * current Activity. + * + * @param activity the activity being backgrounded as a result of user action + */ + @ThreadConfined(UI) + public void onUserLeaveHint(@Nullable Activity activity) { + if (mCurrentActivity != null && activity == mCurrentActivity) { + UiThreadUtil.assertOnUiThread(); + + ReactContext currentContext = getCurrentReactContext(); + if (currentContext != null) { + currentContext.onUserLeaveHint(activity); + } + } + } + /** * Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do * any necessary cleanup. The passed Activity is the current Activity being paused. This will diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ActivityEventListener.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ActivityEventListener.java index cf6c9bbffe6255..e5cd5f94a0c7b7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ActivityEventListener.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ActivityEventListener.java @@ -22,4 +22,8 @@ public interface ActivityEventListener { /** Called when a new intent is passed to the activity */ void onNewIntent(Intent intent); + + /** Called when host activity receives an {@link Activity#onUserLeaveHint()} call. */ + default void onUserLeaveHint(Activity activity) {} + ; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 3cbfdf6588dcff..c67274d3be6f1f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -265,6 +265,19 @@ public void onHostResume(@Nullable Activity activity) { ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_RESUME_END); } + @ThreadConfined(UI) + public void onUserLeaveHint(@Nullable Activity activity) { + ReactMarker.logMarker(ReactMarkerConstants.ON_USER_LEAVE_HINT_START); + for (ActivityEventListener listener : mActivityEventListeners) { + try { + listener.onUserLeaveHint(activity); + } catch (RuntimeException e) { + handleException(e); + } + } + ReactMarker.logMarker(ReactMarkerConstants.ON_USER_LEAVE_HINT_END); + } + @ThreadConfined(UI) public void onNewIntent(@Nullable Activity activity, Intent intent) { UiThreadUtil.assertOnUiThread(); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java index 74de7150a139c8..cd8cf01657a7be 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactMarkerConstants.java @@ -52,6 +52,8 @@ public enum ReactMarkerConstants { INITIALIZE_MODULE_END, ON_HOST_RESUME_START, ON_HOST_RESUME_END, + ON_USER_LEAVE_HINT_START, + ON_USER_LEAVE_HINT_END, ON_HOST_PAUSE_START, ON_HOST_PAUSE_END, CONVERT_CONSTANTS_START, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index aed42958adc7e3..2f580dafa99910 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -282,6 +282,18 @@ public void onHostResume(final @Nullable Activity activity) { mReactLifecycleStateManager.moveToOnHostResume(currentContext, getCurrentActivity()); } + @ThreadConfined(UI) + @Override + public void onHostLeaveHint(final @Nullable Activity activity) { + final String method = "onUserLeaveHint(activity)"; + log(method); + + ReactContext currentContext = getCurrentReactContext(); + if (currentContext != null) { + currentContext.onUserLeaveHint(activity); + } + } + @ThreadConfined(UI) @Override public void onHostPause(final @Nullable Activity activity) { From 3fc7ebb311e86cf2e3e78efacb1860deadd54216 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Tue, 2 Jul 2024 11:26:11 -0700 Subject: [PATCH 163/968] Don't include C++ bridging header in RCTTurboModule.h (#45251) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45251 https://github.com/facebook/react-native/pull/44914 is causing some iOS build breaks ## Changelog: [iOS] [Changed] - Don't include C++ bridging header in RCTTurboModule.h Reviewed By: cortinico Differential Revision: D59280331 fbshipit-source-id: 489bc94ee0e5073129205370245c0093c0754f58 --- .../nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h index f092e3377ad25d..f54e1751fb9465 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h @@ -14,7 +14,6 @@ #import #import #import -#import #import #import #import From 24d7cc15dbd04a1f25578a9ca889452f3acd9aab Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Tue, 2 Jul 2024 13:44:58 -0700 Subject: [PATCH 164/968] Parse raw box shadow props (#44882) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44882 tsia, nothing too fancy here. Just taking the box shadows from raw props and throwing them into a struct so we can read it. Changelog: [Internal] bypass-github-export-checks Reviewed By: NickGerleman Differential Revision: D57617028 fbshipit-source-id: 29cf683b663b4903721d674efbf61a200eaf3a64 --- .../components/view/BaseViewProps.cpp | 8 ++ .../renderer/components/view/BaseViewProps.h | 4 + .../renderer/components/view/conversions.h | 98 +++++++++++++++++++ .../react/renderer/graphics/BoxShadow.h | 25 +++++ 4 files changed, 135 insertions(+) create mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/BoxShadow.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index cb8e771ea9926e..6ef4c07522e640 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -150,6 +150,14 @@ BaseViewProps::BaseViewProps( "cursor", sourceProps.cursor, {})), + boxShadow( + CoreFeatures::enablePropIteratorSetter ? sourceProps.boxShadow + : convertRawProp( + context, + rawProps, + "experimental_boxShadow", + sourceProps.boxShadow, + {})), filter( CoreFeatures::enablePropIteratorSetter ? sourceProps.filter : convertRawProp( diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h index 21c569e5ea4c48..218b972110487e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,9 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { Cursor cursor{}; + // Box shadow + std::vector boxShadow{}; + // Filter std::vector filter{}; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index d1cd9b9ac0fc85..5e9bb59a0fe574 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -929,6 +931,102 @@ inline void fromRawValue( react_native_expect(false); } +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + react_native_expect(value.hasType>()); + if (!value.hasType>()) { + result = {}; + return; + } + + std::vector boxShadows{}; + auto rawBoxShadows = static_cast>(value); + for (const auto& rawBoxShadow : rawBoxShadows) { + bool isMap = + rawBoxShadow.hasType>(); + react_native_expect(isMap); + if (!isMap) { + // If any box shadow is malformed then we should not apply any of them + // which is the web behavior. + result = {}; + return; + } + + auto rawBoxShadowMap = + static_cast>(rawBoxShadow); + BoxShadow boxShadow{}; + auto offsetX = rawBoxShadowMap.find("offsetX"); + react_native_expect(offsetX != rawBoxShadowMap.end()); + if (offsetX == rawBoxShadowMap.end()) { + result = {}; + return; + } + react_native_expect(offsetX->second.hasType()); + if (!offsetX->second.hasType()) { + result = {}; + return; + } + boxShadow.offsetX = (Float)offsetX->second; + + auto offsetY = rawBoxShadowMap.find("offsetY"); + react_native_expect(offsetY != rawBoxShadowMap.end()); + if (offsetY == rawBoxShadowMap.end()) { + result = {}; + return; + } + react_native_expect(offsetY->second.hasType()); + if (!offsetY->second.hasType()) { + result = {}; + return; + } + boxShadow.offsetY = (Float)offsetY->second; + + auto blurRadius = rawBoxShadowMap.find("blurRadius"); + if (blurRadius != rawBoxShadowMap.end()) { + react_native_expect(blurRadius->second.hasType()); + if (!blurRadius->second.hasType()) { + result = {}; + return; + } + boxShadow.blurRadius = (Float)blurRadius->second; + } + + auto spreadRadius = rawBoxShadowMap.find("spreadRadius"); + if (spreadRadius != rawBoxShadowMap.end()) { + react_native_expect(spreadRadius->second.hasType()); + if (!spreadRadius->second.hasType()) { + result = {}; + return; + } + boxShadow.spreadRadius = (Float)spreadRadius->second; + } + + auto inset = rawBoxShadowMap.find("inset"); + if (inset != rawBoxShadowMap.end()) { + react_native_expect(inset->second.hasType()); + if (!inset->second.hasType()) { + result = {}; + return; + } + boxShadow.inset = (bool)inset->second; + } + + auto color = rawBoxShadowMap.find("color"); + if (color != rawBoxShadowMap.end()) { + fromRawValue( + context.contextContainer, + context.surfaceId, + color->second, + boxShadow.color); + } + + boxShadows.push_back(boxShadow); + } + + result = boxShadows; +} inline void fromRawValue( const PropsParserContext& /*context*/, const RawValue& value, diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/BoxShadow.h b/packages/react-native/ReactCommon/react/renderer/graphics/BoxShadow.h new file mode 100644 index 00000000000000..e625550e29d52a --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/BoxShadow.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook::react { + +struct BoxShadow { + bool operator==(const BoxShadow& other) const = default; + + Float offsetX{}; + Float offsetY{}; + Float blurRadius{}; + Float spreadRadius{}; + SharedColor color{}; + bool inset{}; +}; +} // namespace facebook::react From a3cf1624d0e70f0b91a6d6289bb52b388eadd16e Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Tue, 2 Jul 2024 13:44:58 -0700 Subject: [PATCH 165/968] Outset box shadow impl Summary: tisa. Algo is * Draw offscreen rect the size of the outset shadow (so accounting for spread) * Set g state to cast shadow in proper place ON screen * Clear out region in view The rects need to be offscreen for the following reasons * We need to account for spread radius, and CGContext shadows do not have support for this. So the only way to create a bigger shadow is the create a path that is the same size as the shadow we want * We cannot just position this rect onscreen with no offset (so the shadow is casting directly under it) since the blur will look unnatural * Offscreen means we do not see filled shadow rect but we do see the shadow it casts by offsetting it in the proper location Changelog: [Internal] Reviewed By: lenaic Differential Revision: D58881588 fbshipit-source-id: 2ea1b8945a3b9f182c4fb11668ac91a0ae7846ca --- .../View/RCTViewComponentView.mm | 20 +++ .../React/Fabric/Utils/RCTBoxShadow.h | 21 +++ .../React/Fabric/Utils/RCTBoxShadow.mm | 144 ++++++++++++++++++ .../components/view/ViewShadowNode.cpp | 2 +- 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 packages/react-native/React/Fabric/Utils/RCTBoxShadow.h create mode 100644 packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 77072e5848e15a..89e659cd7d4475 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -13,6 +13,7 @@ #import #import +#import #import #import #import @@ -29,6 +30,7 @@ @implementation RCTViewComponentView { UIColor *_backgroundColor; __weak CALayer *_borderLayer; + CALayer *_boxShadowLayer; CALayer *_filterLayer; BOOL _needsInvalidateLayer; BOOL _isJSResponder; @@ -394,6 +396,11 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & _needsInvalidateLayer = YES; } + // `boxShadow` + if (oldViewProps.boxShadow != newViewProps.boxShadow) { + _needsInvalidateLayer = YES; + } + _needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer; _props = std::static_pointer_cast(props); @@ -761,6 +768,19 @@ - (void)invalidateLayer _filterLayer.zPosition = CGFLOAT_MAX; [self.layer addSublayer:_filterLayer]; } + + _boxShadowLayer = nil; + if (!_props->boxShadow.empty()) { + _boxShadowLayer = [CALayer layer]; + [self.layer addSublayer:_boxShadowLayer]; + _boxShadowLayer.zPosition = CGFLOAT_MIN; + _boxShadowLayer.frame = RCTGetBoundingRect(_props->boxShadow, self.layer.frame.size); + + UIImage *boxShadowImage = + RCTGetBoxShadowImage(_props->boxShadow, RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), layer); + + _boxShadowLayer.contents = (id)boxShadowImage.CGImage; + } } #pragma mark - Accessibility diff --git a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h new file mode 100644 index 00000000000000..9c432f2b6a5bec --- /dev/null +++ b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import +#import +#import + +RCT_EXTERN UIImage * +RCTGetBoxShadowImage(std::vector shadows, RCTCornerRadii cornerRadii, CALayer *layer); + +RCT_EXTERN CGRect +RCTGetBoxShadowRect(CGFloat offsetX, CGFloat offsetY, CGFloat blurRadius, CGFloat spreadRadius, CGSize layerSize); + +RCT_EXTERN CGRect RCTGetBoundingRect(std::vector boxShadows, CGSize layerSize); diff --git a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm new file mode 100644 index 00000000000000..74c642ec2c2926 --- /dev/null +++ b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm @@ -0,0 +1,144 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTBoxShadow.h" + +#import +#import + +#import + +using namespace facebook::react; +// See https://drafts.csswg.org/css-backgrounds/#shadow-shape +static CGFloat adjustedCornerRadius(CGFloat cornerRadius, CGFloat spreadRadius) +{ + CGFloat adjustment = spreadRadius; + if (cornerRadius < spreadRadius) { + adjustment *= 1 + pow((cornerRadius / spreadRadius) - 1, 3); + } + + return cornerRadius + adjustment; +} + +static RCTCornerRadii cornerRadiiForBoxShadow(RCTCornerRadii cornerRadii, CGFloat spreadRadius) +{ + return { + adjustedCornerRadius(cornerRadii.topLeft, spreadRadius), + adjustedCornerRadius(cornerRadii.topRight, spreadRadius), + adjustedCornerRadius(cornerRadii.bottomLeft, spreadRadius), + adjustedCornerRadius(cornerRadii.bottomRight, spreadRadius)}; +} + +CGRect RCTGetBoxShadowRect(CGFloat offsetX, CGFloat offsetY, CGFloat blurRadius, CGFloat spreadRadius, CGSize layerSize) +{ + return CGRectMake( + offsetX - spreadRadius - blurRadius, + offsetY - spreadRadius - blurRadius, + layerSize.width + 2 * (spreadRadius + blurRadius), + layerSize.height + 2 * (spreadRadius + blurRadius)); +} + +// Returns the smallest CGRect that will contain all shadows and the layer itself. +// The origin represents the location of this box relative to the layer the shadows +// are attached to. +CGRect RCTGetBoundingRect(std::vector boxShadows, CGSize layerSize) +{ + CGFloat smallestX = 0; + CGFloat smallestY = 0; + CGFloat largestX = layerSize.width; + CGFloat largestY = layerSize.height; + for (const auto &boxShadow : boxShadows) { + CGFloat negativeXExtent = boxShadow.offsetX - boxShadow.spreadRadius - boxShadow.blurRadius; + smallestX = MIN(smallestX, negativeXExtent); + CGFloat negativeYExtent = boxShadow.offsetY - boxShadow.spreadRadius - boxShadow.blurRadius; + smallestY = MIN(smallestY, negativeYExtent); + CGFloat positiveXExtent = boxShadow.offsetX + boxShadow.spreadRadius + boxShadow.blurRadius + layerSize.width; + largestX = MAX(largestX, positiveXExtent); + CGFloat positiveYExtent = boxShadow.offsetY + boxShadow.spreadRadius + boxShadow.blurRadius + layerSize.height; + largestY = MAX(largestY, positiveYExtent); + } + + return CGRectMake(smallestX, smallestY, largestX - smallestX, largestY - smallestY); +} + +UIImage *RCTGetBoxShadowImage(std::vector shadows, RCTCornerRadii cornerRadii, CALayer *layer) +{ + CGRect boundingRect = RCTGetBoundingRect(shadows, layer.bounds.size); + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:boundingRect.size + format:rendererFormat]; + // Core graphics has support for shadows that looks similar to web and are very + // fast to apply. The only issue is that this shadow does not take a spread + // radius like on web. To get around this, we draw the shadow rect (the rect + // that casts the shadow, not the shadow itself) offscreen. This shadow rect + // is correctly sized to account for spread radius. Then, when setting the + // shadow itself, we modify the offsetX/Y to account for the fact that our + // shadow rect is offscreen and position it where it needs to be in the image. + UIImage *const boxShadowImage = [renderer imageWithActions:^( + UIGraphicsImageRendererContext *_Nonnull rendererContext) { + const CGContextRef context = rendererContext.CGContext; + // Reverse iterator as shadows are stacked back to front + for (auto it = shadows.rbegin(); it != shadows.rend(); ++it) { + CGFloat offsetX = it->offsetX; + CGFloat offsetY = it->offsetY; + CGFloat blurRadius = it->blurRadius; + CGFloat spreadRadius = it->spreadRadius; + CGColorRef color = RCTUIColorFromSharedColor(it->color).CGColor; + + // First, define the shadow rect. This is the rect that will be filled + // and _cast_ the shadow. As a result, the size does not incorporate + // the blur radius since this rect is not the shadow itself. + const RCTCornerInsets shadowRectCornerInsets = + RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, spreadRadius), UIEdgeInsetsZero); + CGSize shadowRectSize = + CGSizeMake(layer.bounds.size.width + 2 * spreadRadius, layer.bounds.size.height + 2 * spreadRadius); + // Ensure this is drawn offscreen and will not show in the image + CGRect shadowRect = CGRectMake(-shadowRectSize.width, 0, shadowRectSize.width, shadowRectSize.height); + CGPathRef shadowRectPath = RCTPathCreateWithRoundedRect(shadowRect, shadowRectCornerInsets, nil); + + // Second, set the shadow as graphics state so that when we fill our + // shadow rect it will actually cast a shadow. The offset of this + // shadow needs to compensate for the fact that the shadow rect is + // offscreen. Additionally, we take away the spread radius since spread + // grows in all directions but the origin of our shadow rect is just + // the negative width, which accounts for 2*spread radius. + CGContextSetShadowWithColor( + context, + CGSizeMake( + offsetX - boundingRect.origin.x - spreadRadius - shadowRect.origin.x, + offsetY - boundingRect.origin.y - spreadRadius), + blurRadius, + color); + + // Third, the Core Graphics functions to actually draw the shadow rect + // and thus the shadow itself. + CGContextAddPath(context, shadowRectPath); + // Color here does not matter, we just need something that has 1 for + // alpha so that the shadow is visible. The rect is purposely rendered + // outside of the context so it should not be visible. + CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); + CGContextFillPath(context); + + CGPathRelease(shadowRectPath); + } + // Lastly, clear out the region inside the view so that the shadows do + // not cover its content + const RCTCornerInsets layerCornerInsets = + RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, 0), UIEdgeInsetsZero); + CGPathRef shadowPathAlignedWithLayer = RCTPathCreateWithRoundedRect( + CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layer.bounds.size.width, layer.bounds.size.height), + layerCornerInsets, + nil); + CGContextAddPath(context, shadowPathAlignedWithLayer); + CGContextSetBlendMode(context, kCGBlendModeClear); + CGContextFillPath(context); + + CGPathRelease(shadowPathAlignedWithLayer); + }]; + + return boxShadowImage; +} diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 666702d1625a81..9df83d2270b1b3 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -66,7 +66,7 @@ void ViewShadowNode::initialize() noexcept { bool formsView = formsStackingContext || isColorMeaningful(viewProps.backgroundColor) || hasBorder() || - !viewProps.testId.empty() || + !viewProps.testId.empty() || !viewProps.boxShadow.empty() || HostPlatformViewTraitsInitializer::formsView(viewProps); if (formsView) { From d99960744c7f28b7933690103538ee5c02f8f0dd Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Tue, 2 Jul 2024 13:44:58 -0700 Subject: [PATCH 166/968] Inset box shadow impl (#45242) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45242 tsia, comments should explain how this works but tldr is * Set up cropping region to only draw within the view's bounds * Draw 2 offscreen rects to cast the shadow. One represents the bounds of the original view, the other represents the clear region. Fill these rects with EO fill algo so the intersection is clear. The disjoint will be colored and cast a shadow. * Do that for each shadow in reverse order Changelog: [Internal] bypass-github-export-checks Reviewed By: lenaic Differential Revision: D58885576 fbshipit-source-id: 2f3a5de75e93c7d34676128bbddbe38d64f1fb59 --- .../React/Fabric/Utils/RCTBoxShadow.h | 3 - .../React/Fabric/Utils/RCTBoxShadow.mm | 316 +++++++++++++----- 2 files changed, 228 insertions(+), 91 deletions(-) diff --git a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h index 9c432f2b6a5bec..b9b89b5662dcba 100644 --- a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h +++ b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.h @@ -15,7 +15,4 @@ RCT_EXTERN UIImage * RCTGetBoxShadowImage(std::vector shadows, RCTCornerRadii cornerRadii, CALayer *layer); -RCT_EXTERN CGRect -RCTGetBoxShadowRect(CGFloat offsetX, CGFloat offsetY, CGFloat blurRadius, CGFloat spreadRadius, CGSize layerSize); - RCT_EXTERN CGRect RCTGetBoundingRect(std::vector boxShadows, CGSize layerSize); diff --git a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm index 74c642ec2c2926..eb26396476d5f9 100644 --- a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm +++ b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm @@ -17,11 +17,13 @@ static CGFloat adjustedCornerRadius(CGFloat cornerRadius, CGFloat spreadRadius) { CGFloat adjustment = spreadRadius; - if (cornerRadius < spreadRadius) { - adjustment *= 1 + pow((cornerRadius / spreadRadius) - 1, 3); + if (cornerRadius < abs(spreadRadius)) { + const CGFloat r = cornerRadius / (CGFloat)abs(spreadRadius); + const CGFloat p = (CGFloat)pow(r - 1.0, 3.0); + adjustment *= 1.0 + p; } - return cornerRadius + adjustment; + return fmax(cornerRadius + adjustment, 0); } static RCTCornerRadii cornerRadiiForBoxShadow(RCTCornerRadii cornerRadii, CGFloat spreadRadius) @@ -33,15 +35,6 @@ static RCTCornerRadii cornerRadiiForBoxShadow(RCTCornerRadii cornerRadii, CGFloa adjustedCornerRadius(cornerRadii.bottomRight, spreadRadius)}; } -CGRect RCTGetBoxShadowRect(CGFloat offsetX, CGFloat offsetY, CGFloat blurRadius, CGFloat spreadRadius, CGSize layerSize) -{ - return CGRectMake( - offsetX - spreadRadius - blurRadius, - offsetY - spreadRadius - blurRadius, - layerSize.width + 2 * (spreadRadius + blurRadius), - layerSize.height + 2 * (spreadRadius + blurRadius)); -} - // Returns the smallest CGRect that will contain all shadows and the layer itself. // The origin represents the location of this box relative to the layer the shadows // are attached to. @@ -52,93 +45,240 @@ CGRect RCTGetBoundingRect(std::vector boxShadows, CGSize layerSize) CGFloat largestX = layerSize.width; CGFloat largestY = layerSize.height; for (const auto &boxShadow : boxShadows) { - CGFloat negativeXExtent = boxShadow.offsetX - boxShadow.spreadRadius - boxShadow.blurRadius; - smallestX = MIN(smallestX, negativeXExtent); - CGFloat negativeYExtent = boxShadow.offsetY - boxShadow.spreadRadius - boxShadow.blurRadius; - smallestY = MIN(smallestY, negativeYExtent); - CGFloat positiveXExtent = boxShadow.offsetX + boxShadow.spreadRadius + boxShadow.blurRadius + layerSize.width; - largestX = MAX(largestX, positiveXExtent); - CGFloat positiveYExtent = boxShadow.offsetY + boxShadow.spreadRadius + boxShadow.blurRadius + layerSize.height; - largestY = MAX(largestY, positiveYExtent); + if (!boxShadow.inset) { + CGFloat negativeXExtent = boxShadow.offsetX - boxShadow.spreadRadius - boxShadow.blurRadius; + smallestX = MIN(smallestX, negativeXExtent); + CGFloat negativeYExtent = boxShadow.offsetY - boxShadow.spreadRadius - boxShadow.blurRadius; + smallestY = MIN(smallestY, negativeYExtent); + CGFloat positiveXExtent = boxShadow.offsetX + boxShadow.spreadRadius + boxShadow.blurRadius + layerSize.width; + largestX = MAX(largestX, positiveXExtent); + CGFloat positiveYExtent = boxShadow.offsetY + boxShadow.spreadRadius + boxShadow.blurRadius + layerSize.height; + largestY = MAX(largestY, positiveYExtent); + } } return CGRectMake(smallestX, smallestY, largestX - smallestX, largestY - smallestY); } +static std::pair, std::vector> splitBoxShadowsByInset( + const std::vector &allShadows) +{ + std::vector outsetShadows, insetShadows; + + std::partition_copy( + allShadows.begin(), + allShadows.end(), + std::back_inserter(insetShadows), + std::back_inserter(outsetShadows), + [](BoxShadow shadow) { return shadow.inset; }); + + return std::make_pair(outsetShadows, insetShadows); +} + +// Core graphics has support for shadows that looks similar to web and are very +// fast to apply. The only issue is that this shadow does not take a spread +// radius like on web. To get around this, we draw the shadow rect (the rect +// that casts the shadow, not the shadow itself) offscreen. This shadow rect +// is correctly sized to account for spread radius. Then, when setting the +// shadow itself, we modify the offsetX/Y to account for the fact that our +// shadow rect is offscreen and position it where it needs to be in the image. +static void renderOutsetShadows( + std::vector &outsetShadows, + RCTCornerRadii cornerRadii, + CALayer *layer, + CGRect boundingRect, + CGContextRef context) +{ + if (outsetShadows.empty()) { + return; + } + // Save state before doing any work so that we can restore it after we have + // drawn all of our shadows. This ensures that we do not need to worry about + // graphical state carrying over after this function returns + CGContextSaveGState(context); + // Reverse iterator as shadows are stacked back to front + for (auto it = outsetShadows.rbegin(); it != outsetShadows.rend(); ++it) { + CGContextSaveGState(context); + CGFloat offsetX = it->offsetX; + CGFloat offsetY = it->offsetY; + CGFloat blurRadius = it->blurRadius; + CGFloat spreadRadius = it->spreadRadius; + CGColorRef color = RCTUIColorFromSharedColor(it->color).CGColor; + + // First, define the shadow rect. This is the rect that will be filled + // and _cast_ the shadow. As a result, the size does not incorporate + // the blur radius since this rect is not the shadow itself. + const RCTCornerInsets shadowRectCornerInsets = + RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, spreadRadius), UIEdgeInsetsZero); + CGSize shadowRectSize = + CGSizeMake(layer.bounds.size.width + 2 * spreadRadius, layer.bounds.size.height + 2 * spreadRadius); + // Ensure this is drawn offscreen and will not show in the image + CGRect shadowRect = CGRectMake(-shadowRectSize.width, 0, shadowRectSize.width, shadowRectSize.height); + CGPathRef shadowRectPath = RCTPathCreateWithRoundedRect(shadowRect, shadowRectCornerInsets, nil); + + // Second, set the shadow as graphics state so that when we fill our + // shadow rect it will actually cast a shadow. The offset of this + // shadow needs to compensate for the fact that the shadow rect is + // offscreen. Additionally, we take away the spread radius since spread + // grows in all directions but the origin of our shadow rect is just + // the negative width, which accounts for 2*spread radius. + CGContextSetShadowWithColor( + context, + CGSizeMake( + offsetX - boundingRect.origin.x - spreadRadius - shadowRect.origin.x, + offsetY - boundingRect.origin.y - spreadRadius), + blurRadius, + color); + + // Third, the Core Graphics functions to actually draw the shadow rect + // and thus the shadow itself. + CGContextAddPath(context, shadowRectPath); + // Color here does not matter, we just need something that has 1 for + // alpha so that the shadow is visible. The rect is purposely rendered + // outside of the context so it should not be visible. + CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); + CGContextFillPath(context); + + CGPathRelease(shadowRectPath); + CGColorRelease(color); + CGContextRestoreGState(context); + } + // Lastly, clear out the region inside the view so that the shadows do + // not cover its content + const RCTCornerInsets layerCornerInsets = + RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, 0), UIEdgeInsetsZero); + CGPathRef shadowPathAlignedWithLayer = RCTPathCreateWithRoundedRect( + CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layer.bounds.size.width, layer.bounds.size.height), + layerCornerInsets, + nil); + CGContextAddPath(context, shadowPathAlignedWithLayer); + CGContextSetBlendMode(context, kCGBlendModeClear); + CGContextFillPath(context); + + CGPathRelease(shadowPathAlignedWithLayer); + CGContextRestoreGState(context); +} + +// Just like with outset shadows, we need to draw inset shadow rects offscreen +// then offset the shadow it casts to the proper place. We can replicate the shape +// of the inset shadow by using 2 rects. One is the same size as the view it is +// attached to, plus some padding. The other represents a cropping region of the +// first rect, with the exact postion and size of this region depending on the +// shadow's params. We make this cropping region by using the EO fill pattern so +// that the interection of the 2 rects is clear, and thus no shadow is cast. +static void renderInsetShadows( + std::vector &insetShadows, + RCTCornerRadii cornerRadii, + CALayer *layer, + CGRect boundingRect, + CGContextRef context) +{ + if (insetShadows.empty()) { + return; + } + // Save state before doing any work so that we can restore it after we have + // drawn all of our shadows. This ensures that we do not need to worry about + // graphical state carrying over after this function returns + CGContextSaveGState(context); + + // First, create a clipping area so we only draw within the view's bounds. + // If we do not do this, blur artifacts will show up outside the view. + CGMutablePathRef outerPath = CGPathCreateMutable(); + CGPathMoveToPoint(outerPath, nil, 0, 0); + CGPathAddLineToPoint(outerPath, nil, boundingRect.size.width, 0); + CGPathAddLineToPoint(outerPath, nil, boundingRect.size.width, boundingRect.size.height); + CGPathAddLineToPoint(outerPath, nil, 0, boundingRect.size.height); + CGPathCloseSubpath(outerPath); + // Add the path twice so we only draw inside the view with the EO crop rule + CGContextAddPath(context, outerPath); + CGContextAddPath(context, outerPath); + const RCTCornerInsets cornerInsetsForLayer = + RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, 0), UIEdgeInsetsZero); + CGPathRef layerPath = RCTPathCreateWithRoundedRect( + CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layer.bounds.size.width, layer.bounds.size.height), + cornerInsetsForLayer, + nil); + CGContextAddPath(context, layerPath); + CGContextEOClip(context); + CGPathRelease(layerPath); + + // Reverse iterator as shadows are stacked back to front + for (auto it = insetShadows.rbegin(); it != insetShadows.rend(); ++it) { + CGContextSaveGState(context); + CGFloat offsetX = it->offsetX; + CGFloat offsetY = it->offsetY; + CGFloat blurRadius = it->blurRadius; + CGFloat spreadRadius = it->spreadRadius; + CGColorRef color = RCTUIColorFromSharedColor(it->color).CGColor; + + // Second, create the two offscreen rects we will use to create the correct + // inset shadow shape. shadowRect has an originX such that it AND the clear + // region are both guaranteed to be offscreen. We do not want some combination + // of shadow params to allow the clear region to showup inside our context. + // We also pad the size of the shadow rect by the blur radius so that the + // edges of the shadow remain a solid color and do not blend with outside + // of the view. + CGSize shadowRectSize = + CGSizeMake(layer.bounds.size.width + 2 * blurRadius, layer.bounds.size.height + 2 * blurRadius); + CGSize clearRegionSize = + CGSizeMake(layer.bounds.size.width - 2 * spreadRadius, layer.bounds.size.height - 2 * spreadRadius); + CGRect shadowRect = CGRectMake( + -fmax(shadowRectSize.width, clearRegionSize.width + offsetX + blurRadius + spreadRadius), + 0, + shadowRectSize.width, + shadowRectSize.height); + CGContextAddRect(context, shadowRect); + + CGRect clearRegionRect = CGRectMake( + shadowRect.origin.x + offsetX + blurRadius + spreadRadius, + shadowRect.origin.y + offsetY + blurRadius + spreadRadius, + clearRegionSize.width, + clearRegionSize.height); + CGContextAddRect(context, clearRegionRect); + + // Third, set the shadow graphics state with the appropriate offset such that + // it is positioned on top of the view. We subtract blurRadius because the + // shadow rect is padded. + CGContextSetShadowWithColor( + context, + CGSizeMake( + -shadowRect.origin.x - boundingRect.origin.x - blurRadius, + -shadowRect.origin.y - boundingRect.origin.y - blurRadius), + blurRadius, + color); + + // Fourth, the Core Graphics functions to actually draw the shadow rect + // and thus the shadow itself. Note we use an EO fill path so that the + // intersection between our two rects will be clear. The disjoint parts of + // the rect will be colored, but because of the clipping area, we only see + // the shadow projected from the shadow rect, not the clear region rect. + CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); + CGContextEOFillPath(context); + + CGColorRelease(color); + CGContextRestoreGState(context); + } + + CGContextRestoreGState(context); +} + UIImage *RCTGetBoxShadowImage(std::vector shadows, RCTCornerRadii cornerRadii, CALayer *layer) { CGRect boundingRect = RCTGetBoundingRect(shadows, layer.bounds.size); UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:boundingRect.size format:rendererFormat]; - // Core graphics has support for shadows that looks similar to web and are very - // fast to apply. The only issue is that this shadow does not take a spread - // radius like on web. To get around this, we draw the shadow rect (the rect - // that casts the shadow, not the shadow itself) offscreen. This shadow rect - // is correctly sized to account for spread radius. Then, when setting the - // shadow itself, we modify the offsetX/Y to account for the fact that our - // shadow rect is offscreen and position it where it needs to be in the image. - UIImage *const boxShadowImage = [renderer imageWithActions:^( - UIGraphicsImageRendererContext *_Nonnull rendererContext) { - const CGContextRef context = rendererContext.CGContext; - // Reverse iterator as shadows are stacked back to front - for (auto it = shadows.rbegin(); it != shadows.rend(); ++it) { - CGFloat offsetX = it->offsetX; - CGFloat offsetY = it->offsetY; - CGFloat blurRadius = it->blurRadius; - CGFloat spreadRadius = it->spreadRadius; - CGColorRef color = RCTUIColorFromSharedColor(it->color).CGColor; - - // First, define the shadow rect. This is the rect that will be filled - // and _cast_ the shadow. As a result, the size does not incorporate - // the blur radius since this rect is not the shadow itself. - const RCTCornerInsets shadowRectCornerInsets = - RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, spreadRadius), UIEdgeInsetsZero); - CGSize shadowRectSize = - CGSizeMake(layer.bounds.size.width + 2 * spreadRadius, layer.bounds.size.height + 2 * spreadRadius); - // Ensure this is drawn offscreen and will not show in the image - CGRect shadowRect = CGRectMake(-shadowRectSize.width, 0, shadowRectSize.width, shadowRectSize.height); - CGPathRef shadowRectPath = RCTPathCreateWithRoundedRect(shadowRect, shadowRectCornerInsets, nil); - - // Second, set the shadow as graphics state so that when we fill our - // shadow rect it will actually cast a shadow. The offset of this - // shadow needs to compensate for the fact that the shadow rect is - // offscreen. Additionally, we take away the spread radius since spread - // grows in all directions but the origin of our shadow rect is just - // the negative width, which accounts for 2*spread radius. - CGContextSetShadowWithColor( - context, - CGSizeMake( - offsetX - boundingRect.origin.x - spreadRadius - shadowRect.origin.x, - offsetY - boundingRect.origin.y - spreadRadius), - blurRadius, - color); - - // Third, the Core Graphics functions to actually draw the shadow rect - // and thus the shadow itself. - CGContextAddPath(context, shadowRectPath); - // Color here does not matter, we just need something that has 1 for - // alpha so that the shadow is visible. The rect is purposely rendered - // outside of the context so it should not be visible. - CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); - CGContextFillPath(context); - - CGPathRelease(shadowRectPath); - } - // Lastly, clear out the region inside the view so that the shadows do - // not cover its content - const RCTCornerInsets layerCornerInsets = - RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, 0), UIEdgeInsetsZero); - CGPathRef shadowPathAlignedWithLayer = RCTPathCreateWithRoundedRect( - CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layer.bounds.size.width, layer.bounds.size.height), - layerCornerInsets, - nil); - CGContextAddPath(context, shadowPathAlignedWithLayer); - CGContextSetBlendMode(context, kCGBlendModeClear); - CGContextFillPath(context); - - CGPathRelease(shadowPathAlignedWithLayer); - }]; + UIImage *const boxShadowImage = + [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) { + auto [outsetShadows, insetShadows] = splitBoxShadowsByInset(shadows); + const CGContextRef context = rendererContext.CGContext; + // Outset shadows should be before inset shadows since outset needs to + // clear out a region in the view so we do not block its contents. + // Inset shadows could draw over those outset shadows but if the shadow + // colors have alpha < 1 then we will have inaccurate alpha compositing + renderOutsetShadows(outsetShadows, cornerRadii, layer, boundingRect, context); + renderInsetShadows(insetShadows, cornerRadii, layer, boundingRect, context); + }]; return boxShadowImage; } From 0ba2e9adf2cf2d27f9506afbb6b6379420b0465c Mon Sep 17 00:00:00 2001 From: Thomas Nardone Date: Tue, 2 Jul 2024 14:16:32 -0700 Subject: [PATCH 167/968] Prevent View Preallocation (#45163) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45163 Avoid view preallocation when rendering on the main thread Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D58833983 fbshipit-source-id: a942d1fac684be5a8073941dbf043ba1d738e3a0 --- .../com/facebook/react/fabric/FabricUIManager.java | 8 ++++++++ .../src/main/jni/react/fabric/Binding.cpp | 2 +- .../jni/react/fabric/FabricMountingManager.cpp | 14 +++++++++++++- .../main/jni/react/fabric/FabricMountingManager.h | 4 +++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 6c28d95ffa6744..74c0e64d1889b0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -764,6 +764,14 @@ private void preallocateView( isLayoutable)); } + @SuppressLint("NotInvokedPrivateMethod") + @SuppressWarnings("unused") + @AnyThread + @ThreadConfined(ANY) + private boolean isOnMainThread() { + return UiThreadUtil.isOnUiThread(); + } + @SuppressWarnings("unused") @AnyThread @ThreadConfined(ANY) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp index b1d443cc26537e..92c29f80f1a601 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.cpp @@ -513,7 +513,7 @@ void Binding::schedulerDidRequestPreliminaryViewAllocation( if (!mountingManager) { return; } - mountingManager->preallocateShadowView(shadowNode); + mountingManager->maybePreallocateShadowView(shadowNode); } void Binding::schedulerDidDispatchCommand( diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index 13124ea84be524..0246cb74f8d1d2 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -784,11 +784,16 @@ void FabricMountingManager::executeMount( env->DeleteLocalRef(intBufferArray); } -void FabricMountingManager::preallocateShadowView( +void FabricMountingManager::maybePreallocateShadowView( const ShadowNode& shadowNode) { if (!shadowNode.getTraits().check(ShadowNodeTraits::Trait::FormsView)) { return; } + static thread_local bool onMainThread = isOnMainThread(); + if (onMainThread) { + // View preallocation is not beneficial when rendering on the main thread + return; + } SystraceSection section("FabricMountingManager::preallocateShadowView"); @@ -844,6 +849,13 @@ void FabricMountingManager::preallocateShadowView( isLayoutableShadowNode); } +bool FabricMountingManager::isOnMainThread() { + static auto isOnMainThread = + JFabricUIManager::javaClassStatic()->getMethod( + "isOnMainThread"); + return isOnMainThread(javaUIManager_); +} + void FabricMountingManager::dispatchCommand( const ShadowView& shadowView, const std::string& commandName, diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h index 03457b4440f280..0a21a2173481b5 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h @@ -32,7 +32,7 @@ class FabricMountingManager final { void onSurfaceStop(SurfaceId surfaceId); - void preallocateShadowView(const ShadowNode& shadowNode); + void maybePreallocateShadowView(const ShadowNode& shadowNode); void executeMount(const MountingTransaction& transaction); @@ -55,6 +55,8 @@ class FabricMountingManager final { void onAllAnimationsComplete(); private: + bool isOnMainThread(); + jni::global_ref javaUIManager_; std::recursive_mutex commitMutex_; From c247e8c8c96535578905958d34e1a82f5b5e922d Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Tue, 2 Jul 2024 15:14:33 -0700 Subject: [PATCH 168/968] Fix case where absolute nodes would sometimes not be cloned (#45240) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45240 X-link: https://github.com/facebook/yoga/pull/1675 There was a bug where some crash would happen if a tree was cloned that had static/absolute parent/child pair inside it. This was because we were no longer calling `cloneChildrenIfNeeded` on the static parent, but would still layout the absolute child. So that child's owner would be stale and have new layout. In React Native this would lead to a failed assert which causes the crash. The fix here is to clone the children of static nodes during `layoutAbsoluteDescendants` so that we guarantee the node is either cloned if it is going to have new layout. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D59175629 fbshipit-source-id: 4d110a08ba5368704327d5ab69a8695b28e746f4 --- .../yoga/yoga/algorithm/AbsoluteLayout.cpp | 42 +++++++++++++------ .../yoga/yoga/algorithm/AbsoluteLayout.h | 3 +- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp index 81dd9128ad374b..d68b4fa91c5282 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp @@ -474,7 +474,7 @@ void layoutAbsoluteChild( containingBlockHeight); } -void layoutAbsoluteDescendants( +bool layoutAbsoluteDescendants( yoga::Node* containingNode, yoga::Node* currentNode, SizingMode widthSizingMode, @@ -486,6 +486,7 @@ void layoutAbsoluteDescendants( float currentNodeTopOffsetFromContainingBlock, float containingNodeAvailableInnerWidth, float containingNodeAvailableInnerHeight) { + bool hasNewLayout = false; for (auto child : currentNode->getChildren()) { if (child->style().display() == Display::None) { continue; @@ -514,6 +515,8 @@ void layoutAbsoluteDescendants( currentDepth, generationCount); + hasNewLayout = hasNewLayout || child->getHasNewLayout(); + /* * At this point the child has its position set but only on its the * parent's flexStart edge. Additionally, this position should be @@ -571,6 +574,13 @@ void layoutAbsoluteDescendants( } else if ( child->style().positionType() == PositionType::Static && !child->alwaysFormsContainingBlock()) { + // We may write new layout results for absolute descendants of "child" + // which are positioned relative to the current containing block instead + // of their parent. "child" may not be dirty, or have new constraints, so + // absolute positioning may be the first time during this layout pass that + // we need to mutate these descendents. Make sure the path of + // nodes to them is mutable before positioning. + child->cloneChildrenIfNeeded(); const Direction childDirection = child->resolveDirection(currentNodeDirection); // By now all descendants of the containing block that are not absolute @@ -582,19 +592,25 @@ void layoutAbsoluteDescendants( currentNodeTopOffsetFromContainingBlock + child->getLayout().position(PhysicalEdge::Top); - layoutAbsoluteDescendants( - containingNode, - child, - widthSizingMode, - childDirection, - layoutMarkerData, - currentDepth + 1, - generationCount, - childLeftOffsetFromContainingBlock, - childTopOffsetFromContainingBlock, - containingNodeAvailableInnerWidth, - containingNodeAvailableInnerHeight); + hasNewLayout = hasNewLayout || + layoutAbsoluteDescendants( + containingNode, + child, + widthSizingMode, + childDirection, + layoutMarkerData, + currentDepth + 1, + generationCount, + childLeftOffsetFromContainingBlock, + childTopOffsetFromContainingBlock, + containingNodeAvailableInnerWidth, + containingNodeAvailableInnerHeight); + + if (hasNewLayout) { + child->setHasNewLayout(hasNewLayout); + } } } + return hasNewLayout; } } // namespace facebook::yoga diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.h index ae84e6da9f2bc0..584a586a0400c7 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.h +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.h @@ -24,7 +24,8 @@ void layoutAbsoluteChild( uint32_t depth, uint32_t generationCount); -void layoutAbsoluteDescendants( +// Returns if some absolute descendant has new layout +bool layoutAbsoluteDescendants( yoga::Node* containingNode, yoga::Node* currentNode, SizingMode widthSizingMode, From 3c6762a5f8860c04043e2217a00572384c8d423a Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Tue, 2 Jul 2024 23:37:15 -0700 Subject: [PATCH 169/968] Pre-suppress errors ahead of v0.239 release Summary: Changelog: [Internal] Reviewed By: mvitousek Differential Revision: D59308716 fbshipit-source-id: d741ee004e153810fc913da96505706e43814ec1 --- .../src/commands/bundle/saveAssets.js | 2 ++ packages/react-native/Libraries/Alert/Alert.js | 3 +++ .../Libraries/BatchedBridge/NativeModules.js | 2 ++ .../react-native/Libraries/Core/ErrorHandlers.js | 9 +++++++++ .../react-native/Libraries/Core/ExceptionsManager.js | 2 ++ .../Libraries/Core/ReactFiberErrorDialog.js | 3 +++ .../react-native/Libraries/Interaction/TaskQueue.js | 1 + .../react-native/Libraries/LogBox/Data/LogBoxData.js | 1 + .../LogBox/Data/__tests__/LogBoxData-test.js | 3 +++ .../react-native/Libraries/Utilities/HMRClient.js | 1 + .../js/examples/FlatList/FlatList-nested.js | 12 ++++++++++-- 11 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/community-cli-plugin/src/commands/bundle/saveAssets.js b/packages/community-cli-plugin/src/commands/bundle/saveAssets.js index 1aae31542fdc5d..d4fe5187789c74 100644 --- a/packages/community-cli-plugin/src/commands/bundle/saveAssets.js +++ b/packages/community-cli-plugin/src/commands/bundle/saveAssets.js @@ -111,7 +111,9 @@ function copyAll(filesToCopy: CopiedFiles) { } else { // queue.length === 0 is checked in previous branch, so this is string const src = queue.shift(); + // $FlowFixMe[incompatible-type] const dest = filesToCopy[src]; + // $FlowFixMe[incompatible-call] copy(src, dest, copyNext); } }; diff --git a/packages/react-native/Libraries/Alert/Alert.js b/packages/react-native/Libraries/Alert/Alert.js index a6a0ccbfecc5dc..a6b0585f7865e1 100644 --- a/packages/react-native/Libraries/Alert/Alert.js +++ b/packages/react-native/Libraries/Alert/Alert.js @@ -98,10 +98,13 @@ class Alert { const onAction = (action, buttonKey) => { if (action === constants.buttonClicked) { if (buttonKey === constants.buttonNeutral) { + // $FlowFixMe[incompatible-type] buttonNeutral.onPress && buttonNeutral.onPress(); } else if (buttonKey === constants.buttonNegative) { + // $FlowFixMe[incompatible-type] buttonNegative.onPress && buttonNegative.onPress(); } else if (buttonKey === constants.buttonPositive) { + // $FlowFixMe[incompatible-type] buttonPositive.onPress && buttonPositive.onPress(); } } else if (action === constants.dismissed) { diff --git a/packages/react-native/Libraries/BatchedBridge/NativeModules.js b/packages/react-native/Libraries/BatchedBridge/NativeModules.js index 612915f6ea0325..a421b0b82a7000 100644 --- a/packages/react-native/Libraries/BatchedBridge/NativeModules.js +++ b/packages/react-native/Libraries/BatchedBridge/NativeModules.js @@ -102,6 +102,7 @@ function genMethod(moduleID: number, methodID: number, type: MethodType) { // In case we reject, capture a useful stack trace here. /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-type] const enqueueingFrameError: ExtendedError = new Error(); return new Promise((resolve, reject) => { BatchedBridge.enqueueNativeCall( @@ -171,6 +172,7 @@ function updateErrorWithErrorData( ): ExtendedError { /* $FlowFixMe[class-object-subtyping] added when improving typing for this * parameters */ + // $FlowFixMe[incompatible-return] return Object.assign(error, errorData || {}); } diff --git a/packages/react-native/Libraries/Core/ErrorHandlers.js b/packages/react-native/Libraries/Core/ErrorHandlers.js index 036175bf9b823f..e98246970acc86 100644 --- a/packages/react-native/Libraries/Core/ErrorHandlers.js +++ b/packages/react-native/Libraries/Core/ErrorHandlers.js @@ -28,14 +28,17 @@ export function onUncaughtError(errorValue: mixed, errorInfo: ErrorInfo): void { if (errorValue instanceof Error) { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (errorValue: ExtendedError); } else if (typeof errorValue === 'string') { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError(errorValue): ExtendedError); } else { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError('Unspecified error'): ExtendedError); } try { @@ -58,14 +61,17 @@ export function onCaughtError(errorValue: mixed, errorInfo: ErrorInfo): void { if (errorValue instanceof Error) { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (errorValue: ExtendedError); } else if (typeof errorValue === 'string') { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError(errorValue): ExtendedError); } else { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError('Unspecified error'): ExtendedError); } try { @@ -91,14 +97,17 @@ export function onRecoverableError( if (errorValue instanceof Error) { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (errorValue: ExtendedError); } else if (typeof errorValue === 'string') { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError(errorValue): ExtendedError); } else { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError('Unspecified error'): ExtendedError); } try { diff --git a/packages/react-native/Libraries/Core/ExceptionsManager.js b/packages/react-native/Libraries/Core/ExceptionsManager.js index 41186fa3626d51..eac2be19b981f1 100644 --- a/packages/react-native/Libraries/Core/ExceptionsManager.js +++ b/packages/react-native/Libraries/Core/ExceptionsManager.js @@ -154,6 +154,7 @@ function handleException(e: mixed, isFatal: boolean) { inExceptionHandler = true; /* $FlowFixMe[class-object-subtyping] added when improving typing for this * parameters */ + // $FlowFixMe[incompatible-call] reportException(error, isFatal, /*reportToConsole*/ true); } finally { inExceptionHandler = false; @@ -225,6 +226,7 @@ function reactConsoleErrorHandler(...args) { reportException( /* $FlowFixMe[class-object-subtyping] added when improving typing for this * parameters */ + // $FlowFixMe[incompatible-call] error, false, // isFatal false, // reportToConsole diff --git a/packages/react-native/Libraries/Core/ReactFiberErrorDialog.js b/packages/react-native/Libraries/Core/ReactFiberErrorDialog.js index f9e783c5587bae..ceecd9d9fff7d2 100644 --- a/packages/react-native/Libraries/Core/ReactFiberErrorDialog.js +++ b/packages/react-native/Libraries/Core/ReactFiberErrorDialog.js @@ -32,14 +32,17 @@ const ReactFiberErrorDialog = { if (errorValue instanceof Error) { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (errorValue: ExtendedError); } else if (typeof errorValue === 'string') { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError(errorValue): ExtendedError); } else { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-cast] error = (new SyntheticError('Unspecified error'): ExtendedError); } try { diff --git a/packages/react-native/Libraries/Interaction/TaskQueue.js b/packages/react-native/Libraries/Interaction/TaskQueue.js index 0f209a7d945109..958f8415dac574 100644 --- a/packages/react-native/Libraries/Interaction/TaskQueue.js +++ b/packages/react-native/Libraries/Interaction/TaskQueue.js @@ -116,6 +116,7 @@ class TaskQueue { } } catch (e) { e.message = + // $FlowFixMe[incompatible-type] 'TaskQueue: Error with task ' + (task.name || '') + ': ' + e.message; throw e; } diff --git a/packages/react-native/Libraries/LogBox/Data/LogBoxData.js b/packages/react-native/Libraries/LogBox/Data/LogBoxData.js index 28b185bb2b7d0f..04f9ba2870bc47 100644 --- a/packages/react-native/Libraries/LogBox/Data/LogBoxData.js +++ b/packages/react-native/Libraries/LogBox/Data/LogBoxData.js @@ -419,6 +419,7 @@ export function withSubscription( componentDidCatch(err: Error, errorInfo: {componentStack: string, ...}) { /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-call] reportLogBoxError(err, errorInfo.componentStack); } diff --git a/packages/react-native/Libraries/LogBox/Data/__tests__/LogBoxData-test.js b/packages/react-native/Libraries/LogBox/Data/__tests__/LogBoxData-test.js index 0169b214f1716a..36af8c97d871d8 100644 --- a/packages/react-native/Libraries/LogBox/Data/__tests__/LogBoxData-test.js +++ b/packages/react-native/Libraries/LogBox/Data/__tests__/LogBoxData-test.js @@ -671,6 +671,7 @@ describe('LogBoxData', () => { LogBoxData.reportLogBoxError( /* $FlowFixMe[class-object-subtyping] added when improving typing for * this parameters */ + // $FlowFixMe[incompatible-call] new Error('Simulated Error'), ' in Component (file.js:1)', ); @@ -685,6 +686,7 @@ describe('LogBoxData', () => { it('reportLogBoxError creates a native redbox without a componentStack', () => { /* $FlowFixMe[class-object-subtyping] added when improving typing for this * parameters */ + // $FlowFixMe[incompatible-call] LogBoxData.reportLogBoxError(new Error('Simulated Error')); const receivedError = ExceptionsManager.handleException.mock.calls[0][0]; @@ -697,6 +699,7 @@ describe('LogBoxData', () => { it('reportLogBoxError creates an error message that is also ignored', () => { /* $FlowFixMe[class-object-subtyping] added when improving typing for this * parameters */ + // $FlowFixMe[incompatible-call] LogBoxData.reportLogBoxError(new Error('Simulated Error')); const receivedErrorMessage = diff --git a/packages/react-native/Libraries/Utilities/HMRClient.js b/packages/react-native/Libraries/Utilities/HMRClient.js index c1d0169ecb620e..8a772abfb8bc27 100644 --- a/packages/react-native/Libraries/Utilities/HMRClient.js +++ b/packages/react-native/Libraries/Utilities/HMRClient.js @@ -379,6 +379,7 @@ function showCompileError() { /* $FlowFixMe[class-object-subtyping] added when improving typing for this * parameters */ + // $FlowFixMe[incompatible-type] const error: ExtendedError = new Error(message); // Symbolicating compile errors is wasted effort // because the stack trace is meaningless: diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-nested.js b/packages/rn-tester/js/examples/FlatList/FlatList-nested.js index 6a3f27905a312b..be2f8eac525e29 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-nested.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-nested.js @@ -116,11 +116,19 @@ function NestedListExample(): React.Node { Inner Viewable:{'\n'} - {inner.viewableItems.sort((a, b) => a - b).join(', ')} + { + // $FlowFixMe[react-rule-hook-mutation] + // $FlowFixMe[missing-local-annot] + inner.viewableItems.sort((a, b) => a - b).join(', ') + } Inner Rendered:{'\n'} - {inner.renderedItems.sort((a, b) => a - b).join(', ')} + { + // $FlowFixMe[react-rule-hook-mutation] + // $FlowFixMe[missing-local-annot] + inner.renderedItems.sort((a, b) => a - b).join(', ') + } Date: Wed, 3 Jul 2024 05:01:02 -0700 Subject: [PATCH 170/968] Add missing invocation of item dispatch listeners when forcing batching of mount items on Android (#45264) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45264 Changelog: [internal] We added a flag to fix some issues when committing state updates synchronously from the main thread in https://github.com/facebook/react-native/pull/44015 but that implementation was incorrectly not invoking item dispatch listeners after mount. This adds the missing logic so we can unblock shipping sync state updates. Reviewed By: javache Differential Revision: D59319230 fbshipit-source-id: b0ab7e7c79a3315ef29dbb024e62c10444192509 --- .../facebook/react/fabric/mounting/MountItemDispatcher.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 53c9ce0eb54982..22dc4a682c0fd0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -117,6 +117,11 @@ public void tryDispatchMountItems() { } finally { mInDispatch = false; } + + // We call didDispatchMountItems regardless of whether we actually dispatched anything, since + // NativeAnimatedModule relies on this for executing any animations that may have been + // scheduled + mItemDispatchListener.didDispatchMountItems(); } else { final boolean didDispatchItems; try { From c0977c39b9e2f6887edce919bc850b2958e6905d Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 3 Jul 2024 05:49:47 -0700 Subject: [PATCH 171/968] Migrate analyse_code to GHA (#45247) Summary: This migrates `analyse_code` to GHA into a single job called `lint`. ## Changelog: [INTERNAL] - Migrate analyse_code to GHA Pull Request resolved: https://github.com/facebook/react-native/pull/45247 Test Plan: CI Reviewed By: NickGerleman Differential Revision: D59283393 Pulled By: cortinico fbshipit-source-id: dcdc4828a551062b3706e6450614b8c94e1a7e81 --- .circleci/configurations/jobs.yml | 6 +-- .github/actions/lint/action.yml | 43 ++++++++++++++++++++++ .github/workflows/nightly.yml | 3 -- .github/workflows/publish-release.yml | 3 -- .github/workflows/test-all.yml | 15 ++++++-- scripts/circleci/validate_yarn_lockfile.sh | 43 ---------------------- 6 files changed, 57 insertions(+), 56 deletions(-) create mode 100644 .github/actions/lint/action.yml delete mode 100755 scripts/circleci/validate_yarn_lockfile.sh diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml index 59e51e16f8d712..b97865fc45061b 100644 --- a/.circleci/configurations/jobs.yml +++ b/.circleci/configurations/jobs.yml @@ -58,10 +58,8 @@ jobs: when: always - run: - name: Sanity checks - command: | - ./scripts/circleci/check_license.sh - ./scripts/circleci/validate_yarn_lockfile.sh + name: Check license + command: ./scripts/circleci/check_license.sh when: always - run: diff --git a/.github/actions/lint/action.yml b/.github/actions/lint/action.yml new file mode 100644 index 00000000000000..bfec4d5814ab5f --- /dev/null +++ b/.github/actions/lint/action.yml @@ -0,0 +1,43 @@ +name: lint +description: Runs all the linters in the codebase +inputs: + node-version: + description: "The node.js version to use" + required: false + default: "18" + github-token: + description: "The GitHub token used by pull-bot" + required: true +runs: + using: composite + steps: + - name: Setup node.js + uses: ./.github/actions/setup-node + with: + node-version: ${{ inputs.node-version }} + - name: Yarn install + shell: bash + run: yarn install --non-interactive --frozen-lockfile + - name: Run linters against modified files (analysis-bot) + shell: bash + run: yarn lint-ci + env: + GITHUB_TOKEN: ${{ inputs.github-token}} + - name: Lint code + shell: bash + run: ./scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml + - name: Lint java + shell: bash + run: ./scripts/circleci/exec_swallow_error.sh yarn lint-java --check + - name: Run flowcheck + shell: bash + run: yarn flow-check + - name: Run typescript check + shell: bash + run: yarn test-typescript + - name: Check license + shell: bash + run: ./scripts/circleci/check_license.sh + - name: Check formatting + shell: bash + run: yarn run format-check diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 592e7eb87c9e55..fdc1f6109a09b1 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -564,9 +564,6 @@ jobs: GRADLE_OPTS: '-Dorg.gradle.daemon=false' # By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs. ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a" - # Repeated here, as the environment key in this executor will overwrite the one in defaults - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: ${{ secrets.GITHUB_ANALYSISBOT_TOKEN_A }} - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: ${{ secrets.GITHUB_ANALYSISBOT_TOKEN_B }} HERMES_WS_DIR: /tmp/hermes env: GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }} diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index b7b0031755d342..409b3533882257 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -561,9 +561,6 @@ jobs: GRADLE_OPTS: '-Dorg.gradle.daemon=false' # By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs. ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a" - # Repeated here, as the environment key in this executor will overwrite the one in defaults - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: ${{ secrets.GITHUB_ANALYSISBOT_TOKEN_A }} - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: ${{ secrets.GITHUB_ANALYSISBOT_TOKEN_B }} HERMES_WS_DIR: /tmp/hermes env: GHA_NPM_TOKEN: ${{ secrets.GHA_NPM_TOKEN }} diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index e29f7360cbb62b..7a67f4a89a2103 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -645,9 +645,6 @@ jobs: GRADLE_OPTS: "-Dorg.gradle.daemon=false" # By default we only build ARM64 to save time/resources. For release/nightlies/prealpha, we override this value to build all archs. ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a" - # Repeated here, as the environment key in this executor will overwrite the one in defaults - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: ${{ secrets.GITHUB_ANALYSISBOT_TOKEN_A }} - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: ${{ secrets.GITHUB_ANALYSISBOT_TOKEN_B }} HERMES_WS_DIR: /tmp/hermes steps: - name: Add github.com to SSH known hosts @@ -943,3 +940,15 @@ jobs: uses: ./.github/actions/test-js with: node-version: ${{ matrix.node-version }} + + lint: + runs-on: ubuntu-latest + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout + uses: actions/checkout@v4.1.1 + - name: Run all the Linters + uses: ./.github/actions/lint + with: + github-token: ${{ env.GH_TOKEN }} diff --git a/scripts/circleci/validate_yarn_lockfile.sh b/scripts/circleci/validate_yarn_lockfile.sh deleted file mode 100755 index 5ef993ed9ef453..00000000000000 --- a/scripts/circleci/validate_yarn_lockfile.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -# Abort the mission if any command fails -set -e - -# Allow the script to be invoked from various environments -if [[ -z "${OVERRIDE_YARN_BINARY}" ]]; then - YARN_BINARY=$(command -v yarn) -else - YARN_BINARY="${OVERRIDE_YARN_BINARY}" -fi - -REACT_NATIVE_TEMP_DIR=$(mktemp -d /tmp/react-native-XXXXXXXX) - -function cleanup { - set +e - rm -rf "$REACT_NATIVE_TEMP_DIR" - set -e -} - -function msg { - echo -e " " - echo -e "\\x1B[36m${1}\\x1B[0m"; - echo -e "\\x1B[36m${1//?/=}\\x1B[0m" -} - -trap cleanup EXIT - -cp -R ./package.json "$REACT_NATIVE_TEMP_DIR" -cp -R ./yarn.lock "$REACT_NATIVE_TEMP_DIR" -pushd "$REACT_NATIVE_TEMP_DIR" >/dev/null - -if ! $YARN_BINARY --ignore-scripts --silent --non-interactive --mutex network --frozen-lockfile; then - msg "Yarn validation failed." - echo "This means the package.json and yarn.lock disagree in some way." - echo "Try fixing it by running \`yarn\` and committing the changes." -fi - -popd >/dev/null From b1ec698dc4baf34ba2e31b7ad43dff97c229bf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Knutzen?= <2263015+hakonk@users.noreply.github.com> Date: Wed, 3 Jul 2024 08:22:26 -0700 Subject: [PATCH 172/968] Fix data race related to RCTNetworkTask.status (#44694) Summary: Fix entails using non-synthesized getter, such that underlying backing is an std::atomic. In the greater scheme of things, I believe `RCTNetworkTask` should be improved as it has several `nonatomic` properties that are read and written to on different threads. Thread safety of this class seems to have been addressed on a per property basis, judging from the employment of `std::mutex` elsewhere in the implementation. This is an attempt at fixing https://github.com/facebook/react-native/issues/44687. ## Changelog: [iOS][FIXED] - Fix data race related to access on `RCTNetworkTask.status`. Pull Request resolved: https://github.com/facebook/react-native/pull/44694 Test Plan: Added unit test in class `RCTNetworkTaskTests`. Reviewed By: cortinico Differential Revision: D59217353 Pulled By: javache fbshipit-source-id: 1af77238ddd99db21e2e53f174a81e207d5832b2 --- .../Libraries/Network/RCTNetworkTask.h | 2 +- .../Libraries/Network/RCTNetworkTask.mm | 22 +++++---- .../RNTesterPods.xcodeproj/project.pbxproj | 4 ++ .../RNTesterUnitTests/RCTNetworkTaskTests.m | 49 +++++++++++++++++++ 4 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 packages/rn-tester/RNTesterUnitTests/RCTNetworkTaskTests.m diff --git a/packages/react-native/Libraries/Network/RCTNetworkTask.h b/packages/react-native/Libraries/Network/RCTNetworkTask.h index c7df9198e070a5..a413a2888789da 100644 --- a/packages/react-native/Libraries/Network/RCTNetworkTask.h +++ b/packages/react-native/Libraries/Network/RCTNetworkTask.h @@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, RCTNetworkTaskStatus) { @property (nonatomic, copy) RCTURLRequestResponseBlock responseBlock; @property (nonatomic, copy) RCTURLRequestProgressBlock uploadProgressBlock; -@property (nonatomic, readonly) RCTNetworkTaskStatus status; +@property (atomic, readonly) RCTNetworkTaskStatus status; - (instancetype)initWithRequest:(NSURLRequest *)request handler:(id)handler diff --git a/packages/react-native/Libraries/Network/RCTNetworkTask.mm b/packages/react-native/Libraries/Network/RCTNetworkTask.mm index c89e2b7b350aec..a82671b7c87fae 100644 --- a/packages/react-native/Libraries/Network/RCTNetworkTask.mm +++ b/packages/react-native/Libraries/Network/RCTNetworkTask.mm @@ -17,7 +17,7 @@ @implementation RCTNetworkTask { id _handler; dispatch_queue_t _callbackQueue; std::mutex _mutex; - + std::atomic _atomicStatus; RCTNetworkTask *_selfReference; } @@ -36,7 +36,7 @@ - (instancetype)initWithRequest:(NSURLRequest *)request _request = request; _handler = handler; _callbackQueue = callbackQueue; - _status = RCTNetworkTaskPending; + _atomicStatus = RCTNetworkTaskPending; dispatch_queue_set_specific(callbackQueue, (__bridge void *)self, (__bridge void *)self, NULL); } @@ -45,6 +45,11 @@ - (instancetype)initWithRequest:(NSURLRequest *)request RCT_NOT_IMPLEMENTED(-(instancetype)init) +- (RCTNetworkTaskStatus)status +{ + return _atomicStatus; +} + - (void)invalidate { _selfReference = nil; @@ -67,7 +72,7 @@ - (void)dispatchCallback:(dispatch_block_t)callback - (void)start { - if (_status != RCTNetworkTaskPending) { + if (_atomicStatus != RCTNetworkTaskPending) { RCTLogError(@"RCTNetworkTask was already started or completed"); return; } @@ -76,18 +81,17 @@ - (void)start id token = [_handler sendRequest:_request withDelegate:self]; if ([self validateRequestToken:token]) { _selfReference = self; - _status = RCTNetworkTaskInProgress; + _atomicStatus = RCTNetworkTaskInProgress; } } } - (void)cancel { - if (_status == RCTNetworkTaskFinished) { + if (_atomicStatus.exchange(RCTNetworkTaskFinished) == RCTNetworkTaskFinished) { return; } - _status = RCTNetworkTaskFinished; id token = _requestToken; if (token && [_handler respondsToSelector:@selector(cancelRequest:)]) { [_handler cancelRequest:token]; @@ -108,7 +112,7 @@ - (BOOL)validateRequestToken:(id)requestToken } if (!valid) { - _status = RCTNetworkTaskFinished; + _atomicStatus = RCTNetworkTaskFinished; if (_completionBlock) { RCTURLRequestCompletionBlock completionBlock = _completionBlock; [self dispatchCallback:^{ @@ -168,7 +172,7 @@ - (void)URLRequest:(id)requestToken didReceiveData:(NSData *)data @try { [_data appendData:data]; } @catch (NSException *exception) { - _status = RCTNetworkTaskFinished; + _atomicStatus = RCTNetworkTaskFinished; if (_completionBlock) { RCTURLRequestCompletionBlock completionBlock = _completionBlock; [self dispatchCallback:^{ @@ -205,7 +209,7 @@ - (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error return; } - _status = RCTNetworkTaskFinished; + _atomicStatus = RCTNetworkTaskFinished; if (_completionBlock) { RCTURLRequestCompletionBlock completionBlock = _completionBlock; NSData *dataCopy = nil; diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index ce240545a6a775..0be05be2aa3f45 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; 832F45BB2A8A6E1F0097B4E6 /* SwiftTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */; }; + A975CA6C2C05EADF0043F72A /* RCTNetworkTaskTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */; }; BEB82277FE76227A15DED9EF /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 77E101C7D8E22A8E70EE76DF /* libPods-RNTesterIntegrationTests.a */; }; CD10C7A5290BD4EB0033E1ED /* RCTEventEmitterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */; }; D626973C1F0D4ABDE2F9028A /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D8DE57E3292D41E28251988A /* libPods-RNTesterUnitTests.a */; }; @@ -98,6 +99,7 @@ 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SwiftTest.swift; path = RNTester/SwiftTest.swift; sourceTree = ""; }; 8BFB9C61D7BDE894E24BF24F /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = ""; }; 9B8542B8C590B51BD0588751 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = ""; }; + A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTNetworkTaskTests.m; sourceTree = ""; }; AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = RNTester.xctestplan; path = RNTester/RNTester.xctestplan; sourceTree = ""; }; CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventEmitterTests.m; sourceTree = ""; }; D74056A5352F0925816E50E0 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -341,6 +343,7 @@ E7DB20B022B2BAA4005AC45F /* RCTModuleInitTests.m */, E7DB20CB22B2BAA5005AC45F /* RCTModuleMethodTests.mm */, E7DB20CF22B2BAA5005AC45F /* RCTMultipartStreamReaderTests.m */, + A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */, E7DB20BE22B2BAA4005AC45F /* RCTNativeAnimatedNodesManagerTests.m */, E7DB20AD22B2BAA3005AC45F /* RCTPerformanceLoggerTests.m */, E7DB20C422B2BAA4005AC45F /* RCTShadowViewTests.m */, @@ -724,6 +727,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A975CA6C2C05EADF0043F72A /* RCTNetworkTaskTests.m in Sources */, E7DB20DF22B2BAA6005AC45F /* RCTImageLoaderTests.m in Sources */, E7DB20D222B2BAA6005AC45F /* RCTModuleInitNotificationRaceTests.m in Sources */, E7DB20D522B2BAA6005AC45F /* RCTPerformanceLoggerTests.m in Sources */, diff --git a/packages/rn-tester/RNTesterUnitTests/RCTNetworkTaskTests.m b/packages/rn-tester/RNTesterUnitTests/RCTNetworkTaskTests.m new file mode 100644 index 00000000000000..874875ee0f9199 --- /dev/null +++ b/packages/rn-tester/RNTesterUnitTests/RCTNetworkTaskTests.m @@ -0,0 +1,49 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +@interface TestHandler : NSObject +@end + +@implementation TestHandler +- (BOOL)canHandleRequest:(NSURLRequest *)request +{ + return YES; +} +- (id)sendRequest:(NSURLRequest *)request withDelegate:(id)delegate +{ + return [[NSUUID UUID] UUIDString]; +} +@end + +@interface RCTNetworkTaskTests : XCTestCase + +@end + +@implementation RCTNetworkTaskTests + +- (void)testCanReadTaskStatus +{ + NSURL *url = [[NSURL alloc] initWithString:@"https://developers.facebook.com"]; + NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; + dispatch_queue_t callbackQueue = + dispatch_queue_create("RCTNetworkTaskTests-testCanReadTaskStatus", DISPATCH_QUEUE_SERIAL); + id testHandler = (id)[[TestHandler alloc] init]; + RCTNetworkTask *task = [[RCTNetworkTask alloc] initWithRequest:request + handler:testHandler + callbackQueue:callbackQueue]; + XCTAssertEqual(task.status, RCTNetworkTaskPending); + [task start]; + XCTAssertEqual(task.status, RCTNetworkTaskInProgress); + [task cancel]; + XCTAssertEqual(task.status, RCTNetworkTaskFinished); +} + +@end From 30a3e6e8dfcfc9597873578b8332ec027ccf1b84 Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Wed, 3 Jul 2024 09:14:02 -0700 Subject: [PATCH 173/968] refactor(dev-middleware): drop `node-fetch` in favor of Node built-in fetch (#45227) Summary: Node 22 doesn't work well with `node-fetch@2`, as one of their polyfills is using the deprecated `punycode` module. This causes unnecessary warnings like: image Instead of upgrading to the [much larger `node-fetch@3`](https://packagephobia.com/result?p=node-fetch%403.3.2), this change drops `node-fetch` in favor of Node's own built-in `fetch` implementation (using [undici](https://github.com/nodejs/undici#readme)). > Note, `react-native/dev-middleware` [already has the `engines.node >= 18`](https://github.com/facebook/react-native/blob/c7988c9c82793b6b41d4c9190a28ce1202410fa0/packages/dev-middleware/package.json#L38-L40) (which is required for fetch). ## Changelog: [GENERAL] [CHANGED] - Drop `node-fetch` in favor of Node's built-in fetch from `undici` in `react-native/dev-middleware` + + + diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index 6ef4c07522e640..939690249352d6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -166,6 +166,15 @@ BaseViewProps::BaseViewProps( "experimental_filter", sourceProps.filter, {})), + mixBlendMode( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.mixBlendMode + : convertRawProp( + context, + rawProps, + "experimental_mixBlendMode", + sourceProps.mixBlendMode, + {})), transform( CoreFeatures::enablePropIteratorSetter ? sourceProps.transform : convertRawProp( diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h index 218b972110487e..9602c719cddc8a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h @@ -62,6 +62,9 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { // Filter std::vector filter{}; + // MixBlendMode + std::string mixBlendMode; + // Transform Transform transform{}; TransformOrigin transformOrigin{ diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index 9df83d2270b1b3..c3ca8496af6c38 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -61,7 +61,7 @@ void ViewShadowNode::initialize() noexcept { viewProps.accessibilityViewIsModal || viewProps.importantForAccessibility != ImportantForAccessibility::Auto || viewProps.removeClippedSubviews || viewProps.cursor != Cursor::Auto || - !viewProps.filter.empty() || + !viewProps.filter.empty() || !viewProps.mixBlendMode.empty() || HostPlatformViewTraitsInitializer::formsStackingContext(viewProps); bool formsView = formsStackingContext || From fd94033dc1f2814b0bfcdd33fb0d176693c626b1 Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Wed, 3 Jul 2024 20:55:27 -0700 Subject: [PATCH 185/968] JS Pumbing to get mix-blend-mode into native (#45051) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45051 tsia Changelog: [Internal] Reviewed By: javache Differential Revision: D58753970 fbshipit-source-id: df3cf8852fbc5f2a95f442c9067358608321ed20 --- .../View/ReactNativeStyleAttributes.js | 5 +++++ .../NativeComponent/BaseViewConfig.android.js | 1 + .../Libraries/StyleSheet/StyleSheetTypes.js | 19 +++++++++++++++++++ .../__snapshots__/public-api-test.js.snap | 18 ++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js index 0a73eb53c84707..1fda63d5945b2d 100644 --- a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -120,6 +120,11 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = { */ experimental_filter: {process: processFilter}, + /** + * MixBlendMode + */ + experimental_mixBlendMode: true, + /** * View */ diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js index d2947cc9692bd8..29f303eec7a5ee 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js @@ -169,6 +169,7 @@ const validAttributesForNonEventProps = { experimental_filter: { process: require('../StyleSheet/processFilter').default, }, + experimental_mixBlendMode: true, opacity: true, elevation: true, shadowColor: {process: require('../StyleSheet/processColor').default}, diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index 3a438013655c8d..90e100576a0f4b 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -713,11 +713,30 @@ type ____FilterStyle_Internal = $ReadOnly<{ experimental_filter?: $ReadOnlyArray, }>; +export type ____MixBlendMode_Internal = + | 'normal' + | 'multiply' + | 'screen' + | 'overlay' + | 'darken' + | 'lighten' + | 'color-dodge' + | 'color-burn' + | 'hard-light' + | 'soft-light' + | 'difference' + | 'exclusion' + | 'hue' + | 'saturation' + | 'color' + | 'luminosity'; + export type ____ViewStyle_InternalCore = $ReadOnly<{ ...$Exact<____LayoutStyle_Internal>, ...$Exact<____ShadowStyle_Internal>, ...$Exact<____TransformStyle_Internal>, ...____FilterStyle_Internal, + experimental_mixBlendMode?: ____MixBlendMode_Internal, backfaceVisibility?: 'visible' | 'hidden', backgroundColor?: ____ColorValue_Internal, borderColor?: ____ColorValue_Internal, diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 44b4cc511f295f..7ff79dfe92a296 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -7700,11 +7700,29 @@ export type ____ShadowStyle_Internal = $ReadOnly<{ type ____FilterStyle_Internal = $ReadOnly<{ experimental_filter?: $ReadOnlyArray, }>; +export type ____MixBlendMode_Internal = + | \\"normal\\" + | \\"multiply\\" + | \\"screen\\" + | \\"overlay\\" + | \\"darken\\" + | \\"lighten\\" + | \\"color-dodge\\" + | \\"color-burn\\" + | \\"hard-light\\" + | \\"soft-light\\" + | \\"difference\\" + | \\"exclusion\\" + | \\"hue\\" + | \\"saturation\\" + | \\"color\\" + | \\"luminosity\\"; export type ____ViewStyle_InternalCore = $ReadOnly<{ ...$Exact<____LayoutStyle_Internal>, ...$Exact<____ShadowStyle_Internal>, ...$Exact<____TransformStyle_Internal>, ...____FilterStyle_Internal, + experimental_mixBlendMode?: ____MixBlendMode_Internal, backfaceVisibility?: \\"visible\\" | \\"hidden\\", backgroundColor?: ____ColorValue_Internal, borderColor?: ____ColorValue_Internal, From 261f82e897d34196d743d8f81bcae7fd79831643 Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Wed, 3 Jul 2024 20:55:27 -0700 Subject: [PATCH 186/968] RN tester example for mix-blend-mode (#45052) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45052 tsia Changelog: [Internal] Reviewed By: javache Differential Revision: D58760458 fbshipit-source-id: 1aadfb000d94b827ed779170254438ed4c469a52 --- packages/rn-tester/js/assets/alpha-hotdog.png | Bin 0 -> 980593 bytes packages/rn-tester/js/assets/rainbow.jpeg | Bin 0 -> 2386 bytes .../MixBlendMode/MixBlendModeExample.js | 131 ++++++++++++++++++ .../js/utils/RNTesterList.android.js | 5 + 4 files changed, 136 insertions(+) create mode 100644 packages/rn-tester/js/assets/alpha-hotdog.png create mode 100644 packages/rn-tester/js/assets/rainbow.jpeg create mode 100644 packages/rn-tester/js/examples/MixBlendMode/MixBlendModeExample.js diff --git a/packages/rn-tester/js/assets/alpha-hotdog.png b/packages/rn-tester/js/assets/alpha-hotdog.png new file mode 100644 index 0000000000000000000000000000000000000000..22152504d5153a8878aaa665107b758859e19753 GIT binary patch literal 980593 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
o-f{aAe9f_)S^=VOjGgzlXaPpLM5Hiyt=rYGNgm z_34>UR3>L-fRn#w94g37`8<*oN+mJSg6l@)$#u2La*mLikd%*RGwSLK)C3_r*YJ2S zt6T8BfgS$pN|?{8r)GbzKH{r%NT6L+2T|2)E1D!oL6pQ0a-pwGrnDTMcV)Z0TMkvc@gu(t^>S)U6JY&m@nT3QQW+XgO%a zxE&gjMNXtsH(ed8%4FbEK^o8rSv0gr)TB#_ifJVDJc6ah0rQ>oAhc?SkIAB_PA&a4 zv9@ z&^^ZePAWu`OPMenI|JK~oBd_>#VeyK!3H-whiHFdd{g{C#m{Ao#KyKPylSs#_7WDc zDlQ9e>W7(SNosA~%|@PB$oWp*P3~Vld;(eU(Ycii^5mUnxoXhI3U{zv<;_@pN`x^g zF!KHwhDZBJXlD=&dXX>d{sE7j)6IO4=xYXxbTTByiqch3Af9aQ=kO}TH(HTxd>~#s zcFdECdTUk`zfH6h`q4b#n4Y<@yK!Ct@yCQWj2o>}A5U2n#07K7*B|$bZ3bMi`GTTn z0j0}ZF=XXFkgB@3DHjCls8-DTkoj;fER~olQJ&llkO|gU`@r8;30a}E zLP6+9phE7c=3!EE$lEJnQFl1!1X zh^jg(=z7)kF5ta5uS8JnImJJRs~)C82==0DM3VAlpvOplV9qr&4S@&~bIz)^YH_KU z2lv%OnNdfvRyhYD8Imdng%$Jetv!b&wUITH^8GIA#mOGR}Cn@lQE6c~(dUi`IQy>Qh7hBA8p8bda@ zW?Bkn$B1Q`8BP6KN;=-1|BlNKa?ycOITTT2tD+M8tQ9%?hz2k(TL6e2%jfx(F||nN z(4Z;vm6D%~N*Z66Lt|jLc}KtL6d!E(CfcN+iDu25PhM8V!6_hL$RS~+p`ZUOvNl-d zS2CgD&SB!oAkV+NBA@PT!`tuGk6_8jXP4WpKuKKLJM{F_6uI%S!pZ?>XFqy4|4`A#`apEtB*_8l*a; zat2&8v6Nl%@jW$p+YcESSsScJXXab)p?d(15L6F^pRzjuMvCJuS#jbEkNE0^#cNyy zs#SBL0i=u$5KEaBBrIcG+Xi(fo8s6_w`;ds3<@X36J#`x(#xk*;d1OysJE*heSM`A z5Nh@L9;Ov7oIV#`O?B%YsdH9YF#z6U3)ax^N7Uh*_@V;a!tsp zz}jBD*)$3P9vuvCZngO4!9~kYz*J`es)VlYX4Gl9tW$_x81sv{&ytjw(ep7~&{l(0 zpmkIm$j5~9RcC#^+9$(f$jhH2H{*6cDvZk{6U3E~77R8Kn@e#6eWXv410)J=UfKN0 zbOj8C(@qoj7~n&N%eUpS@Md**H!+!TZP2ZQyWvEb<3j`v`LE_&lkX!->~li$Gu%cR zN-F#IrMO7N%%p^hR3i(CFA0y7(wUA6=;7fy`{fsEX6XuZ|$L7@cW(&06UQ#mvt(yK1 z&pJ7@IeYvvH>@tVW9I<>PI(taW&Xw=w6fIvg@=NK5^Q7)(1qe{nn^Lef+O@lJ0CX# z$z6>uOu5p6uQ{xqc`pxfSWNL_8WV$pp(LtvK)V1$HD8>2P{3fS=evsgA+ z66eZkAfzG_0ph(SUuF8GSS`OID2O|Ihb&n|@#`70v3ckfx`>s(qB4Pg3Ae-59kLkt z&%m&AFpF=oAN`eB|C^l|f^Z$ufmiiQbw`rYI}~F<@u^KocwD^J)mtudkGUom`G;t= zi)YwXh3{n=(Rm#oF+HHniq~KXu5#4nYIYInmi%$WS@uC%t&VOlGKfh2nA*3_eDRe~ z+kUau>$2u}3x+u?fmQJ}xl~|*;%7zO0Uzh^HmNc2%pr}F1rnM=U;;rZRh)tzx*VTB z>F|P4*N~fm+$r#$KtojLDLN=vlTz_Oymh7L)lx9ZcTL&|3r`tuXrxlpTH$%FiQDh{ zEqB72SJ}LWk=TI7C+v!J!Zbp*VgnD1;#T{{WvleSpE;Rd~YR zlo|>$aj6o8S9QiB4?%-nGPZJCVb)RBLbD~HT1N5 z)43cZ9$Vbi*%@%|d+&!6GU(k3Cw7Iiu3AZ`V7;qj=Ub~ zZ;|>8mB&8Mt)$^F*NvCQaBNWsqR(B^E$nd%fuvGZnjWm|8=WfomrlAV=@Tq(K4Pw* z9bwq3$3=UH7F|<)toe8h+cwkWP#k@9#-#hWrFHnRO)@qU>DpmdAjQp93(u!bdR(sK zO*ax}jD=)hCK>s$mIQuTUdn!15*}2ZMB1ISA2yw%Y=^TOx|xuTBa-{uqkkx>nC9xu z0a}EYX=Olr2g7H#a@Ck-k}WK6Zpf-OCKo*0^0fvxt=sfcA~m{7YsqpAgTZfFeqtU} z0WFUL``;e%mtz0y)hS8V@$OtTV_$+=DHn_Y+o{{_iM-$eLf*xkM}`Q+IS1g9{elIg(n@uhEV9exnQs0?rDsRj8A*CY{UDv$? zP*TV7d=u~Vg_wnQ_FM;ApQBJ)B@O8xZ-WSL%KZ|)l4BGbTh3YSkXG;;GrX~kx5IVz z!mi>5y^GYr<*J$%-EL*8YSJXw9vK2quII~7pE9Kwx`3^mSyW3s14%7D)+^2+e^o@> z+gOVe*)i`VTmlxcoJ6I;miM5>cIFBjj4aBUtTMHwgxP=AVX z53)`Apz0YWW9b-=VOQE7~DHa;L@NA2G^r@D0LCRq?TQ`Kl`~-8o@*~HP%SZ*&b8B!O!++1WFz4HfJ3M=kfWeNF!SMq2i8s z*t(5fK+vz3Uaab1MH2rGf~EBz`8}D7ZwX*!tzxlji0H zdRoRWb@aC(8!a~&{|%hL9SHxe9_TtPWn7XuwkssC%$;-@>>W!o?oo^bBJ(_-j+#PR z#y3OFp5b2i0mEbdHAX+HdQ4nGSf|)7{LtC$o?hugPu>jAP;C2Hu4%2J+6Bc;NDgF2 zwci&N+cD;yW@=g#jNy3te%8`z8h8K;s^@G|Rf$;Hs;a9@+(Jy$Zc$_kE|9B9I8=CV zcXqKnlpU8MDCpO}Oh9-6CfNSLQb$Bp9YwRwTkeGz!vTsT;ez4D;Gt9^{lJU6hi2C( ztT$&8MFT}T(wOd@4C-#=J1muA>Gu!pHFcXzIlSFyvkaYmMySiWqsYp>5Eou!K?V4D4x+R-v+h93^!~@qqCu@#eT=-t`n`#c5#Mk;(VHH9u-Pa@BkmY+wT^1&~-$>y2Z|qwpLHN z9}N#OPk-+MB_AwsyRKHd7Q+8C-$2AuTy=B=WH3?C3vY4FDy$97bL$(oQ$&HZ{f zG8{5UrBcB)w9EI#q3k}g_6g&k*wGcJ1jR|TV5Vt&ELr?B#EjraXS^xf#rxjbSoaDe zkuM_rXHv0lJTtMW0X)t*A@XYB$#G4uDhQ`)cypA`K`fmLW{R6cI`~el(f3jkG}qE>N~hL zfZ11s-B-mN+cHpcMP=Y}#4sSGZ#$qGNr6E3jGMtnM)Wu8DE7y}J*;|YzOUok)YOW5 zT>e{O7{0MqW9kpfah4ts`%8XXSv7ngnjV*k?9BfQR(ly;GO0yZK88C)!y&2lN2$rD z`HX@C_&Q@TKyF*I^zZ&`D>^>|F1_}k*wG1kCRS@lznS=up=O$Mx*xPo%6QcXHo<#zt{6<;1SYBxf!b@Zvn)$B$nX(PmfVu;|FRBAy zGwAVVgL*Xp*{?@XydKC|<0i<7*e?O9Az_VgYN_)lA;=tP4%7w9^v+N{sN%5dz(JOa z1kXDt*I%)@6aEFU==iCp$3wrn&rgrgr=!j1d%9kUlsp{;WJ>~v99vf zSC-|u30f50h=t&Sx^%{32{ozL5k->UwhsB+<0%2~6^1UW^^F&=I5;-5f(t;!Ma3=FJyk6fJ~@W0KRpWGf?-by)rP zi>?nJX)ao1ww82*3 z>J48^HsRdCOvu>=j)0e+So(o38_!v3nH~{|ZtQ(h6Kn$VqddvZ&{@#iPx3h=Kw2Pb zbu!;XYKvAWD$P0rnb^U*`uaEQY7j|YuXUCz0tc?n=gdshKcGRg-*cfe1e~0<J;JMD$-g?BxV**hpPbDv9~$9j_rh`?xxn2$_zd^uY8Kj0FLM4OihQP{@W!aZ zv~scNf}yX6bvA=1$^J4&5d1?!?m6v|Lu?@gRHYb8AbB2H+oqUy;1}q@-cD)G8w;xU!gO1&U;RViS z^8V2s*&JB)Nk&_WaPoEEJ;~NPtw~tsBx+-Fl?5RpH^pFuW}V#kq4v)Dj#8fJ)oFw z7o2_3_dM)%`TS7~vC+4;cVZ#-7}0f2_rv0`B5$C`n9qRB>Ls>dPHO^l{XO| z;?pT#>#~P`2b$T=BkhKb_ItIn<&yD`Hkn(ka?VyM5BV-`@My5l(1>)E*$%YHaC83K zb|eb+Q?9^u?vyS~Bn(u8O$QYosZ9{@<|Vl+4eQ-vrxPi-)_q4R(b-ApSdlf+-XZ|6 z<)4STyq=Zo^l!H_G|b4fifQIASwW&Y^5|t9aFImwjQI|$3s9WL(HFAyX{Im7AW(FW z2={^xhCq^;Ot5BAN8GeMOJ`NLEsKMT!@Ztm8r_eKv*hPBnvAzww1e7(&A8GcA=95W^a<8qq z=Ji}|iK8QH9FDvOMHz<9-4nD7QAWy*tiik!l4aj%w+;L*u~~E{#8R>j1+=cQ9TY{M zBJDaDnhifzjk9du<7IBrmJ)?C7No3%x-^kLqfq@Q_h+7R8}{zM&+z(%?!e>18*kkk zzW$EU9~BNNZR@|uDEFMbrv;&DvpgijgCf4f{#EBH>&?${P2<>?t2NxAuEY32RcqH> zPj4^NM_JVuo%kD%yhw?pJZcocV=1rIpfH~SaY4qi4pni$>G@%NA*M1B`NZ$incs}- z=8N+6tWR|~mwG*{qo7|-ye5efzb&b{=Z1>W!9~LJtpm3~NNToW>f&}Z(C(U?@g<~@ zxh%+(0G0@JG(i+307gfBnLBE4tSDb2QXWofnzUZ02W%UVpac8V!91teeYoFU`ax&d zeQs+)!kAzZPv5}y-(U)(J*GynzTdnpfUh|tGjeIZi$4qRX!&^7d6$$L4T;6J8XZRI zlB~}N;$F*>=5P^zEx)FqBpU`EV>60*nb1>D3l#cv-*Z;c)V=?Fq!jC$$|p@I(={+C zSj75o)N;(G&Al2`Sut)cIi2Zzvq#XO+KGB-LS-T>6LOos#XLZpPmq# zf;y!CJ}Q5XJ-=bgyogRAWfm{%x-UxQ!_Pp^S;fDks7CgtVVtThEbquqw5U&TQ`QZ$ zuJB;o6~gzS=TtkW80#14DnhYpc{X1ZHn><1cVhQuFpMw&)JyMEOv@POeVo+2piGN2 z^*4JC_cI|_4<4zqAn?%~zDBuR&}%@e-r#&qTL(y_dFc>sqx0ljNqrg^wwXrz9;V~7 z_$Ojnt6qlMmx5UWwJSL1Ow|oS;gVY?3q3Ozpp8A;_nU_-YhPls zT9)E$0ixx;;Vn)^pb4*O+k|;*mY@eJeTqoQ+IioT10o*anNALSwQcI*|CwfTxE?tJe|2^{8jp74naq6GcpI0?kB~h@LbXa?Vx6vs&GAarrE>|?8YEv4s^A5{oq zJ8mN>J;9N_z}6-d3Z;w4xyo>Hrc0a(@!xo4-FRUOjx9y$xW^V-3#LZ`+M{GfhU6=u z^I4Tqh2f13RsPYu={gR2IE)u}*q@6aeGi)MkI}8{B#M>0?()J{kXv%+=D4gjR5`ehN zAIi50Y|v~QV=|K`2@Rb8a23OIFAwrNi)cHoMY~Gq=ApV@--n&2?_eJQd8aD;HO*<2 zw9kGq5l`t%7Vje0&~^KH1YvFh8;R@fZH+cZqc^5zJ$gY??#DQu{#au;X$gXKx-;1} z_tCpof+ne30W0>hJXB7%pcX&Ty2vx)R@I+5!!zhrX8G?Kj!fmy0-m>cji6YW{01OF zlm4J?bS!cCv;MxR7AWk^-a}0Y*o8afQ{yvJh!r9x1lIII3DY*Rcr0yicjW9<{~rb( zyoTp0FeE5D(ITW~^j>K4`QZ7Yo%B)F$|$Oxy5jI#yyx1Gf9al-I+0xq`WM;-vr9D) zIQw;@OHvY~p{G)og6ne*n1kv+!$WXZs$@muf4cGU!wpwQ;?y_EEKTR z<*Z8u(Pz;3%oO!u@&Xvw3-$oS5uW@UH2A+3gXPBM5;fUd&{-2!wVJ#CaVLovvgoKH z-z3#&GeORk-a59}ze5#mkoAi91TX>w_0*mS8Hz4pp@LrD4INh)P9evl<(ytGw3xf* z*GB`Y`{>1TgN62`0z zAxmlnjBHb+N)G)a0mUf@aqPAl7xFY}1-r&t|cKFR28iA`I1 zR_hbppSD#eJ?n)g6b5;^WF#$fnez)Emhu7aSX` zkKbk`zD5v@Y?G($H<6QAe4b7nqNdiA%Gi(2Fb49@=N!~v)IYu=CdV58bt`B6EdvIdX?Wo^u_~JH8O<1 zW(~c`)R44le?HO#ub3e?5MSC`?!M3=VAmnrcOefKO+uOv>pNfeLD>I+RZU1nCBY_E zXLirNfbE+J#Smzf$cG%;Q~r1NzQLbFKwT!6R?ysG-tC7(Y8=5;cf^_CoZLr46yGpM z*4*I4Ihn>l{FuqG6t|Ht`KJ$y@mW8aM+Nc+wp&4r(ZuT#YhGU!3L| zN#%eteclUS=^42({ElWZOOFgQk1sN=l5iVr{en6F&Mrq0m@0>zJyP;&THYhsG21E) z<~u0~S~-^v%EYc0dPfE;I@D-Ub-%Mz(Y(&h#&HT5SKxtTz-@RiNHw;f)Hwf6V5 zifu|+DAS3S)TQVonj?9k6Brb>vg!^3+(uopBucOz4W(7>$^olxAbHO>JmN&IRgybZ zX4vo;7*nZ9o}@~yb>h5EOB&FN%%i8QbQ}6xx{{u3@rkfcNrE&Xn126?JiIiy7tJQm z8lgl9)4mP2#Ifp7@WN`9A5+5#bg}5RElx0^IwQ;5YEQ|Lj-K0&w0Kv*%JjY`632-( z!MNOBwkbG_pkTg9&%Cw|vnbq~)*&E4bJiomo#r)wrDm8fSv|`3@IxdbUHk+7HU8^T zAEldAj|h9!eaX`FSe7nX4B;BT2NCn5TT=>h@A}a2I!yce8D&ouZs*292t&c4iEl&rqtxhH06QlYt-g47`qU zR`-D1X7rpfmsy8FNS4`nS3V39?TQ&qJG(e#%f395UXT1KK6)Zn_12$@vSSO8N#e&B zW`kJO`Mt9^=4uydL@DuOiut!-BRw`G0=e!scDQ6*US7`S*A6+jsF_;6VSh=+M7~@N zHH*)9GYz_y#}6zaBNSauD5(M}6E~n33rW?@mr z&+%U~2yFXr0pFH&kF#`GOD{n%$sl<<*!<(;_v?U5*e3VW>KNNH-Xm;eUHGY}>vp*> z;PUH@n52u9<$q>&K;*nikOkuI(hpYUPSG%$!E)TC?(?m*_wW(+H1u=xMGKdoKmwy;-95_O! z^{rx)gAm{?!njLn)_sM%85bm)e|~o-k;229a&%&290fSW%*+jFm6t&ej+xM802SXM z>qD_&+6r=n-lL8xi?db>WT{>M4id3Gxj)tFS)S;LF z+3&cQPz&%5Mn|c1&!@0OyDq+`Wg>H|w}g!t_n@X?MJ5vS4^kvFkT*z=Fe{VWw@Vf+ z3l@i_^Lx@JiCP6fugRG4G{o)6@f*vfG|&QI1Eg1H9{k zlE#k)wtv$SnTF+xui^gWEUw~Z&?!a#L+n0A!8XO=Jva<*oYd=Jc3>G)OUET*WPQ%* zO*Ug3jdf%cU8jFVjkM!28!IsEbR^Qqkkc` zeYX9|zSNL|w-_Un$8Ds-l9)IONQrU^s5el-ja=!wNLP`IrXg2sN9QG7ve$dX2PH1T z5UV%cX6-3OKl-RJN-#a{H9F2+XWS8#v-pqu%-vpvW72CF5l*Ip3g#&N1zw z{XF(TeQ)|33cQb_&D#$bPUJVwYey$!&!?xmZ$24)YJS2SJ^uQf_IRMoiTnP4P{U_N zw4io6$(lo3^=6cc)WbfBZ)=F?^g6NUzURBb^lOVB%HiBu9=<2(o-4P@Q@j_c@9(pN z0u-~mVF;T*XOVjGpb@VS%`77Q*AhmEBlO5emLp=1o*Fusm2!JoaZ~^Mg1>UgSvg{A zP1Z9s#)EjX6kA826da@YI%EoqhMm~@d*bRR_fK;HJT+Pk8(&IrX$04${msOxR;A9S zYB9u@tq_saiL(uT+-Z!rkR|Z1f1`=ngm(lDCY!w^lyo2WZ+SFRuQ~fMUUuN@m!EZ` zH|7DlM>`S{0>;y;G;0lpcS+rF<|yR&cX`ERhMa#g&xUAp2+NumO)^mu#Lkj;|Ks&3 zNDrUqmuJ|;3BIHCZz=sNmJrxIi2E7Kn!hwb$(y{XbROp&=h~XC2=4@`LnI?~#(S3N zKsN~p!n0+AOxlWVdfsFD_|bz`QZADlZptr> zF#S7O-k?`Drc%>`5?<>5wJA zT9Pk>`qVn0MkAes%(KYgZ1&S^W5AlERpoDEhIHq2X5o(f1_A>z>{UGD3m{SAU5_OK zGZ{1}mwr$o!n8#|hg5D~aFCFkJ6TgP7@mXQfy!m|xOF~cUHb&=42+AjuGC5gvVc1~ zulal5{T9`6R!pQR$jRKM+Cn7m_BB$$@M;VUB@ub0hX}Wvr=Iouyedg}M(}IHucRn% zK}atDg>p(JNL#=!hVm8;*Ggw@r=P4WE|=H+o=rn`Tj+W%Zu+>(U3u#rB%X4q+`9gL zwX8VAjTrI@+!9GnT&E9K9Yr&L;@y7Kgj@p5yBu-}8*N*0iZ8+PFs*ePHO>F+>F&nQJg!+zmG)*MaD4>U)zQ{rpASN!S70k_2SvDvx0s#4H} z%z#3Zfg8GlL$nG9r(2ZoSo4@VO+0yrE1`3_uZdXJ@|mk#+^zDXJ`uyn%d;pT6RhE3sx~_sTOniYxaDc(b;L$#y|Sp zjjoLB7-_N~ApWoh|1#cwwn8!X0KSjGUymvoI2`VqRj;;qO3Ld-VEh|p4!X!rPNxk{ z)~_?h2g^hXe9kGhUWuM_l44FNqj3I3&NbkY-xV4ltA=jmgCFp7S?ikCnKL>xa-SHe zWQ31eLG$iaGeL5$HwJlI55423hi2BVT$#w`@(Jinfxp4l26`RRt&y-_zHivab+UaXYBBK1F5d$hi}xVg$ucnMZCyxJ z)2iBwgv6)Cl`w&1<`xnz6F~e1>->2j#_;cSJlx4gEG-)x?5 z|C`rxn=UCNRCb8S!fr9OxyK#Bf?tKsBili-bA=`G9|0_M2MJ~UcZ6mSuoU_6Xgcz1Q>kkR*4ljpj(4n|D6JsTK3UOWffrLjpmtuuW6-|W~4x~in9 zgBS$Ok@fN6EjxUqbGB{0{Jb>pX?p$d+~3FDc6_IMUijVMH@EfEnV<9?noVuRN9oy7 z@TYyXA#`SpLExHRPGDT7+$7o#&f%IYt?}T(Y~Pe0{l*GzQLI;cfXnR_EzynFqp#9_ z4LgRQw;Bhs1A-@cEKopntKQOpVts-b&nH;k5Slu`Br#J>=o2V!o>;DX5z+IRXcRD< zuERG67GGPpLGqUx1F_;MdDAQQ8)5=0U>w;5ZStgH#pN2cIlO%&DP+tqH0)54%pmCs zeuL8_v)^YxAMYqGw0Wjx6p?}w%af^ckwWh<#trU|tF%Oz6_cqVo1zR;M3c8X;vp_} z9ZxYz61qNbejk;4Mta2vt4`AtBYz3>_~w3$Wos&pUOx#DNy!L-cw%*Q6%DIa`d|=U zoRO{o>o{knCn&1qb6AMOf}^g)@S$}i$N#oJ@WC;;?eZTTVY(AE9o9`3oYOQb zCDS0)n=ou)*r5uBEis(dtYvm z$4%xEkjmk_RH{*C7P46*qJ%k&KA$gZh7Y6lrnFF<71^`k2q_^m%YWI2;@i7wn63yG5AK~^!I{2=suiNvxj+?h{j7i3R%Z{WAuQ9Q{oY`G_a5sJK-sUY?M#30PfX-HsHTf@cbKMir+#0VU z%Lu@ZVE!p`ZrGoX-hx+U$nR?b2BU+m8f4Wfk92Q9`yZy8!OnT8JH_=IC1d3^>)~0^ zP|n3pMbuGooeWe2t@&hXo%NU!H)>#AAHU9mmM3(J;I#q`YD6)*ioi~g0t;h3&ylHt zYm9?>X-Y|W8v|&8*=@s;on;G=EijJ#*3v8L8^9(PcxhO?4LT1hy$4?fesrsAN%|1u z9S1481J6-QVU`3`@oQnv*D!oL8w;Nmtlx82r<3L7tb9FKqvapIRAniVT(&T*W!0om z#N;d1oT)t%X5sE$H)LvOvWA?tVfgQ@CPv?WW)I&Ln0>bO1=|F$TN96j|1Rh(tVae3 zKQC=BfY+JoS?wYkG%G6T*EUwLP-@q7uX6=N<+=tU(Q`snG{Tcj^_mFvLP;b_ zSKCq8N3wORbo)1d$~Mj-kcg>8ZP6pTy70!P3Z7%)T0!6>x^+xo zEXg$KP@K3kYc2t#m}f+G)oQ_r2{ z{@4(N*<$3`EanpyOg5LKjLB6K@T<+b4>rTL-UY`g!+7`=*CSKbsJhJ$koUN8s)pW)m#b$RF&PM{t99OMQ5~C2iz?i+McZP`>2R2?v)h zJUa~bWu<@~Z#b;ltoL#~?xkR2Kie1=qS8pMy9&7CCYw?*0o_3edH#BxMz$0nH?O{` zQMK`hrg2ssSmLlta=ZiN_0j2YLkY3gc5O`5+yH6|%;>aJ+DQg;mU#n(UrGcA>dUzc zx#Em799`0_-Y8-GinIDLmQuDc)>g>RGg>qS7YJrM@GB0Z4ALQVu?#|`mW_-lm23VH6N1c!sYNPbbY%`~PM2rX(= zxECbyvrv%#NYalHggV#gOQ}J}*=Eh@k^3=?#f0?*)~p{!5lO?^A3OR6fx&gS&;WAL z9i7@oT>ngtf}!j?KmIF5%Q*Q}Oe!=)r42ZUOw%gpj$&x3kkH87#m@u&DjB@>`t|l3 zLcI9eo{LEQwPaP6i6|!=RngxMf{c&bJMLg`r-Xba48}Xj*tZ?$dB89g)%^cZbrxK0 zM%%hB#i3Awy9Fsli(7C=km69ZxEF^4!98ez;>Dd}!KD{VgI!Iv9#4!32*NfgJwyS!_ zNV`Aa)#U=u{yLmVOKfYkf=mGB&Nusmz&t+V;tJ7 zVE;fm)1SPG=r?MU7>;oJ0nq_o%TTSVGZ-Hb#R?DtYO+2wOAlig&~)7P`yU=4(TI8p z1NB&zv46CM;v*QKQ7EXO*l$s@cVD( zpD;(kqDkeLBe-Tbqi{l3Sz$wIA=+idphc6PDy10CK45lKJJ$DD(7tohR_o7PUa!TC zyIGBMtaFpo20?ABW)I-$5?EXRcDC9P=eG-h9nK7?68qLmsJ9v)cE^6^R-{j&^ioj` z;^Qj6*1W-*@Gw>`@xrZu@SmYBXXZi3uhdz z6NRMPB>5v3a9qj?!ciG=h`6xJegVTk{G=g4Unwr1_@*it50OVR1|$)+;7Gb3rhQ6B za|7DzPg&{wT>89h2?CTMMluP3d^ zZR@Z@P@8@j8uEm7@=5a}47oavIZ6O@N%VoBNN(_5!FSYdvjNngUkj$fil5O6V)1gQ z@l9DBaN1OQdUH#Ibtb0R>to>`C%ZLl$x0b(UkYR~1HHt%l*+LXL$y5gPvbLK&s$iV zB0*m>OvCXk%yn_F*Y|;8$M9-$ zZJmP%%I4;OEbcxXcPA4k-YtGZmRDHLnDI(1fQm>M(vlfV%Sx`7l%aW=NfvPzqVVL# zO)}?wAzMl4rBlZ|-;1`4y2-}4O3-hYe1|+uVXKffInQvvi~*LWq5$b^3a9_>#$DO-UD0#xbNqv?9k#>Mo(*fq|MYpH z0#v5<6gJrzFN(E>v&Vl-dj=PIE3ZBr`Ll2q8)+T=R%9xEE3)~^$We@b7m^{yMdMI% zm$hwT?)A)gw~qUKNK_LgC}I{)wC|6}2V`8%!yFH&&d#$4jpb2yU>Pph=)`XMv;IIV z^q8UkIhd4p#bl6?4;&Y%7krSlaVV1uM*r8OtltQk2f85F=WDC5Q1{X@0_-G5-h90h zyb3|Bxcts~XglU&WL#?ezUAEyq6w@iOlQm~ag%ClAc3}U(4uO;ow@F~1?c9wHOh=v~|rm4CuqfUs=)pd_o z0E0O5GMVgsNSVb&Kv`(yqFL02Ej(2zNuR;qn9Z6*O+a z#MeGFaAn}Qe(N=xM((h{@SPok>Z>zcBk(RuXmq|6Z<~F8)Ep}hRI0b{SrqGdR>ZuW z=GC@t;sKava?p?NB}WGo%A6m)3%e;(or9e<;^MC9h}929f32->6i-mt0oQb6ZpkQVh$*mt5{7*R$^o8SIF>e zl_v-Jk>b@di9X|6+T*!`Tl}P(IR<{18uS)grMl9q0QuheY2XRP*X{a!IQ_ZmY4i3{A=ph%j7cVX(5rbI2mTzi4CBC{@*bQ*)y-`eP>rv7BP8O+Us>%D;NDCNMf`tg`)Lg+MeMQ{y|rPn{y6Pfl+|uY zPEw$WP*MA~ck{hJNv?L?$NMA5S2pry_y!O`z{gf1B(9vDid2nBb1nExHF!>7Dztw8 ziS&X+2-UQuZv>ct)nFjaiSUz;;Mtmk=>si8+2*W4`RRB!C`l)An*n>=7V_3YQ%B-b z$#&8D8Z};Dm`4c6RZ1>TqqK$xv3o@G(*39TDn1WOv zhGZIe>U|WP^h+EO=j?q<3R)0g1Dv6@lMsHzqlK(4f`xXP7>Ab`I9KxJ<*U(<*aysD zVp7CqA(gNq+)~FSp~2HZ3qbkza*0r3(-wA)%lTYp64_-d7-fh1w42-kx^1(Z9sF%t z2EHzGBoY!P>d)K$hLbc?bbcJwu%m#!Wl-k@kcN_bF?xo zNupl|^m#sgs5qy}c{_Sltayh)or9FGXAjgTqu|Wo^>M^%FwYzWlyQnpKuh(Ldyy5} zfo>`j2@|r;UW(}_G{GZoTZE49&XmMhdMi7`=n4Z|K@Qn#MZggvMVTOGF`Z%Vygt(# zBntS}BE>YSdUHnwr}IJ9xl@diM~T5}3RT6~!SmyRCQ-aD)GMxd_ZUNLD^af%)64tn z@*t$L*W?p!0SJ1#oIdYE1FkD9i01O9Phn!jd#Ygft#?~K$U5h2i9ZGgC+$53b|OX5 zTTCPlT^0BSzD4!{XFs|9465%{qUt3Kiwg8HaAFR1>RJrA8r&kd;$D+C_jnZ4N+B^X zH7DBNS`*a>Bk~i-*@=Fu5`d(kOvpLEPT=!Q_`~=RO&Cl{WvMhhMZv2VxoX<0S_GiT z%IVDO7m17=21jwAw`No)cs`(H{W0_!yf-`CCJ1{%Eu@zJP0)~~W0Zd(GEV({wC9Yk z@Yv~?T)w?~;wp8&+C=(@k{-E%HF|UG)FJAIB7}&~5oU#c3>o1m)d~7(t_%Vj=6K45 z_R0+7V>Vl{gys7Ovp2d$b$jI&=_gxbRC0TR9YZLw6(h~5boK(+4xZ7y{m;uDSGI2q zPp*#qMrICwog8QU6WtXxY#!Wh!Y44r2SeV((Q6G1hmrzSZwXS(x9G@dAxyLdkT;|j zeQ}b}C}`oN%ndKe=u&9Q)XMU4<<6YX_j*zT_$~~OIq=|$Wa(yhc4hUkc~*~xNpYOh z4gc>#Y&}~lYf8krsEM$u6ceXPVvb-tox4?^NsbK)U>c19Yk7n<>!jW6ZoM(s>Z0+1 z)5sY8-;Fuv-Mv)PJ?DPQYajRj%$1S--y3H?HR|Vyu|b#H@AY4w4V}-y4SplSnWgDI zmshhlfGnHtwxBVL;T|0^km+bW%f`AOTK8fS= z$hO@!#*EA;@V_^6tlO4F8`@f_4DCuIe>R}66g z3mkT$4;GY?cEYUwQuTs=Pt+nzAMMsg1F$S<%G*TL_*_;GFvC!Ix&kH(pQ zvRUjI{GUg59F)t z`nb_~+gs0YU1_0B0vPr?3WM8#Gc#N7u)B4SZyJ#*f#b`x{P`SfTd~RFCL)_i{Vsoh;E+O^en|3?4wx#|urV^=4F@OQRgHfKd`O-5i zaV5Y(CuKFrPqEQ^2r8(S;@uOyv{E}8#1X$n&PP(7#UeV95r5AaF>3afhNTeUmNWoC z#JUd2cyzl!neI@3Rl)oVG|@lcspp-&-b*AV$@7?|2}wwDm~#p)rbLZj{n)z`!ol1F zTL0R3`&8U?`Fh4GJ!8C|ES}<_EWj1}DjYo64b`QHr5M)MevVwhN|PaN(9w-6FVWYL zg;d}N&@1T1RFVt}J>+c_MOQigzIxMuUtuOpYB74NLuU^;icrVmZvZ=L#irT(!Rvpj zNoW&Y@8`L$VgA~#V*j!`3yT{=k^c##yv`#MilH>Hwa?lcZB;m zHlQ43x7>Mcd1`+h9GpC*NdErfI`kXEAp91*Oy^{0!=7`QT}R7Co4kF!>j)^_x^<}UwKvC?%DBnJ<30S{d7;j8e{@(rXX3eSb4$N?EB>1 z1!_}&@a<|0^_*JYB=9;bpxX=s&B`r6$DsFtvwre3LCIMLJPvp1#P7F-0vA>1i1y>P z+B)1M4yhc3b3UkU^OSd-UsB!GnNnhyZTcv966vWau@d8N5Z6_%QS2S##PK}J|b(UYjt-X4Feu7|-0#kl|>Jn|2P9abh5k_{cIva|>YcDz)#Y6LH z>VJqe$U@9kzlbM1&B7V744_<>zTN=X~if)YK0sazDuvXPLx3%aTc;CO*#&@g5Ag*8+4Ma#Axhhjh;uF6~?oE)FF<{?Hz@Dot5UE=itiHw|UL zaa0`@L}ey&6>lfhX_8=xA#C8K&h?H7p+5P%wvFaKc8dtlkbeSeV);G1S+(af1c*!) zZ1h*1mZHDxypYUNd&x^87N0N=sWfUG_q^CNLUHL;q{uC;A}}ci_q8dZ z$Vk#S(~pygM$9>1xp}6CQ;E#?7wZ6h_`sKtdXvwR(e*6Ki6$_&k50k(9u#bpI@HQ_ zyAjLqCl&`!*$C?S4~I_yEn;Tsh}$K%lA=6{ zKjWw0$DGhuBv=sRT6&DGTy*v+p*;5Y6*-)0Pw~Hdd}exjIC}oP1tmD$Cx7+X@IUi7 z$9MXV>({&f)h8wPrxBOi+OzeO2ggQ>yTjE%4X=YurL+^4V$?#jv@Eips8bTI*=8~s zCwTZD0+Qu~d~=eJLr5SZYFX6POeK~(+n*BeFb(;emRVbl`Rd#H7nm7VRY$YOFOd0V zf-9pYu->J&D_EwDto#f!y@FK0Ep4QLdOMf)R~>N6@}VJy2&zxx=E}Y@`fT z1o?;gbxH;Q8nn_=Fi4~xeKl$UXACJhamdrfE=T@>mYlz3>ou1mTMRV zG()-Rnu5(dmH6;B#G$P#TwjxCpZ@In+QkeG3Z3TMZju!lQ7{L>_jcciz5;llOpi zkruqTr(}L#`PzsDu?@D3fBMrxc~`Vn_h&p1z#;Z+~Od0lEH?L`+>VH`d04W@@@8ndJa5>|>lz9c{s9U4n zY~q%y{tR)Wt`D2O@${F*rq&JR2AS3u@98V3sVkMV_S-X=-hc}}aM85w_}m_=TXq7z zA&43U8*|McDh2b4`;)^jSR#6LU)TZjBTf}?;DIFB13JuL8z&wVEci$};KkITgXoRc+x^x#mx=rWTo@yn_4Z5qk^;Vy3@>^;DaISD~pqv!WGV1sY!t@#OIwPZzD+^mJ(` z__N~|B`C%F3vpIx_V%+j9ozFWjcu})$W61_1cIVHFXs0!KN2;&j{D{`$Rq(Q3YEs1 zUUr|CJ_+@@sQ<@Fl_u97Lh~<)Et9d><Ak3sUs-vgrkkb)|e~4&+VBQ$k)@sb``t z>g^DCtb(Z?uI4ZFe-hl*cWK(66COjRt1zzwm4CEN;ynZR1P)~YpV;-?O@0|CfCoTJ;=-S=M{R`H=K`ZU(s z7{|$L=q{k~1qFye!I27QG2Z!r6Gdt^dAQ1u5!mnFNq_&Y$iJ~8e@1^d9HgpBq_vs< z8UGoR?6m2s_J4L3UJsM<%@d-JS5r67aQ|i{6@UB8!K1q=Z`&ud>JzmC%x+?KDtF%? z!Err{-vnZpo@ty@RI}E_D&-l7uQFel4voI?Qw(;4%e|(b>6n62;EA|B+_S=?Dl}*3 z0o$nJd_F$mCyDj%Q1DQFkZz)pxjJKMbXT(nj)+I$x9enOJUS9vXbad6mPHl7?FV)k zVitzuXe=}i4v)#sw?X|?ycNX3oN(ym67HUz>)Q9*+x%-!Q?a{1Dp>;)gAxX714rtL zhHXH@#x~IxAf4u{jobm562+gGxsnoNp z@okPG)~LF|gbzQwv_@2T8*bN8eMvB!Wk$!$Z^-6ftG)x1~bv`~nF_;UgV(rwDTB_Nh(vcfBn_TZESm5x$ z7$KZt|HyM$#q~ZRNj>Kr!=-=?I1r>~tScTT4101_-c3XN+5Fkz5_WZq+#r@q&IMAP z4aF1I6CZb@SBY7pVr*l)4Rn8!83J+e_qY$&=MF_usnkh#-3K*EsKQi?cvAG)0u+HZ zo`KiY*qqMgJ$|`joGBg6mgk!UI}{a5Q^`QFuhv98%1x5GbAhutbFpin16xv@ledCo zrG~v8Xk#(krw{{jhiAs+>##Em<19%-Nj=&OZ7Bhb?~^~)dI0=HT@?EXCXKQiu&_OR zm)}%$7|odxbTznv<8ohagWLuNG~=$Q&#?Q`Rrv`GOM2f~^e9LC9HG{u69;_|2Tkw? zt}uQ%|7#i5?j_yy-CBcgAol*O1FBv}Hk6CEKll<@CSLH$ai!6Y zY7BIsd`I=Sw7Ze$tbMC>>~@58-^&t2Rf-xNUCG1oPMvCl+YZN*Wx5mq?abu4OVxEV ztwpAJLsUq~wDo{gj90713elMm1u_zButx*SH1s|wv^=n32~AEa7G#`#sMQRo@h<4J zWzPFlu4!Ar`y6k}>2%?Jid{kMmX27=s>zT?D+mh>T79ciS;rU5l(z`zZ&xY@`%S9iXRcFg@dwgezXShaoboyJ3n!$*=<^^L;L7j95LMa=;60 zl@cqzovuY@D%SL7OMTwH4aM*S&1sFr&HJ@Sf~l#u!80WOWxo{sjaNCJ74Pz%rw*bv z|G!rgSDXjWH7nuv_A;;g@5RrD;!us`sdjfi&o<{awD=E6cM^t|H4E<}Hs_uFF-BrfrE|!#U{`2TT}rt zlZN8*lX!KmhQB#$D{BeB+mQW$Y0Q2U?vA_0!~`dI_;yEvNXsoMLv97`sEQ!V@Q+K7 zrdm3-=G>H9|2sKs+V4#7=Jbzs8SzV}KbeEta_b>NN+C`C=I}ZRk>$;;KX%I%`)>C^HPvRjqF3C^dt_UWJBNkW4Yk8DJz~1n7J807UBqXSfV{pia(KOp*<)1j9RX~D3Hi)#%%V( zU)erqS4ES>+S{^1Ax>t7>^G>APe++chQU`(XO$<#DxH6ypa~B#rJzreXa40k?~4Jv z7W>6}LpXm4@7NFSY@o}Re@?ECztScdX2r`{w--`@b_A4@wF`&QITYQ;LXcJoyy31f zUy{sm8vo>0fEi8sRA+!6OI@TrZh&1;bGL%3-H}sBUZU$2E>J@CR2`T6hMPCO^vPMX zBn-H;Ji~I>)H`7m%mZ0pMV(Gl#G6v;@hlix? zZrby785@cItl;Z+Y5~3BGYa}*_+lI-_SK8*?`3P8vbbsDZDiFVM=uFo?6+P%U@)UbYtHYr0=7!& zvf@gj?4~*vJ2Q7?=(5zoz#T-xq$12Uk{y`??6z5*+y20&V`*UL_J|{>^Bu9kldmlJ zzEW#R4=*kC7-yAP>XjYqb|`%fzKi6So_z(8=T}&aUv%>}TJE?(OOF_2mKoxkX8rU2 zvK(*A?~n(BR+qVU0<;CI+Bl#H}Y26|@fF6gLIA>q{!7Y||HxwD0IxC0|>3 z2H%GWF%C$OuX3kEHbu}JaQ`gi6O{NWHl>t|2C|toF0gQiIp}@qqoPk-&T*^X`6o=9ru0opjEWILw$wth zfg*&8PKlPv9fuHy%`5LkA22+#i8`@zqKI7HSl~q5<4y@^5(Tjv$HB8azx_S&%NF(x zR)%8I$8M{4OgNEikclxDap5lo@?~I*P9+B=6Se;%lcTRVIqPR0mfmZ)2$+h7^e%N1?M&gjcg8P|M8^-T*SW&Cq;-E?X~CKkPz? zC)aGG!K`r2tJ_&T-=5V6SfmscY#n=vYdrZz@F%ld~#zgwKMz^k6wUUYHp_S=UuDj)r&}l{m2T{-iu;(P6f3iH!4dV0i&@*lv zH8xq~?ZrNb<{xFNQ)jDj>e!bn$}Qp=erlPH|CNt#-J1iI@+|5_+KE;Sgc=By!*#@@ zNFw%hjh6P4>qIXxM=URMm4E5|ec0RFp;BD%&ywLA<_(*je?pO&at75H^7&rmk$gH@5#@oSaGC6P z69fV{eyX#7Fy3`CrepNP;vs8MRq{b~b+eF{1T~rH36!y70qumdcQUYuEs85mW3ut- z_55+MWddQTr?UA+g%9pKP51MW+`s1a-q^b=c3Po558(*4aDo`&DY~t*&uG2FuBhDN zn);1)hTKB!G$k_FT#e}UviJ_HevUSIbGb>;_fw#5*3<9iz@N(Xx%26%scegK<9w9N7>V(O(|~Jh&vPO=>eJF_tinXpUegZzV+QXIN>*pEycYJQCU~; z*OTckip3uT2N`?A9&l}q7 z*Vj~HDEphk=2l%UMXQxMu+*wVANVdA1Ku3)dL20_a@9{cl6ok`Qk%I7c9yk|jnCg? zQ8WOmhOd2HqXD4v3op^qA~^^B3F$+vCX+eK&tHJefYV8&hGFm?iy>1uZ(}Y2V+?8x zC#S%x#gHG}?BEO@>lXuOWkbNRdKdjc2Z50NB#km2)THE=eJWj81AbtgCRe7ZM*AzJ zD(MsE9DE~=p)5~@XSi*HhyCU1rkD~~B2G#un zHoaLV`=S0g#`TjqOy3FUP!h7uc(Ca>zFyq3ej_25;TJWq3tP$&HMx?(pkVL`8<0t9 zlPCnviGw3I{$;Dx7h5pON?(O|oM4=x(gU0oe)9~V`!ogG=de4b?w;&9K(`R8wctrK zrB~s4eM!hs%AVharg@|nUbu68N*aE1I|r)1IhM#HO8w82W!alstO}o11K%et;JTU5 zKhyQT_jasvDQbvp{8ZPQdJuF)ck zRrSeb$MNth*nu$?Ch-&s`Pd_f(^wMoOGbuL{OUM2$u--xEiW}3$o=K*#6g>HwKhX3190Kw& zb&JvB@Taa)w9uw2&1o^607j`T#?x9EaAjZ}a3_S}JS8Ff7GyHx(!8i5*?^c49Pj20P0YQcrBcPtsgFWL0oP^kNdP?#_J=u#%)$BRp}((F=ak{d&SDlAbfltH)zh zU5pmarvd8$dJ@%9VcE<+htt$0MBXcEh6s+u;`M1chkQh2VWJDN~LW(gTry|9A|jk zJ7?sYwOJ$0aOu>SagzcvvIIG3_T)<1)PwWZ z!)ECJ;<8XLMXC#Ks}wYtZnF;}m->$&yd-tAb+S&L-8mbdT}2k!*?%5<>?pH)<@x_S z=4a)#7xQ^^^{Kx~W<%TB-{slk3GRsZH19>`(_$e+?JEXaG0nQWgK@{-V|@*`>_F2D zz4PhVp*f{cSy)n^6)$9eo2sazOz7WLp3h;02&k7@3+clJ2C+-XNOccZeZWcVG((|R zIE_374*#Ot#n_(P+HIGp%}xGoPrskl;uAjQt)tC`N#~=2oq~K>!0szfE9SysB>fMP zDaKXGHILRh?jEQ|6hXA>*l~n;q~yxF!d)ZbN;Ug}B;E2~}oo zYBtFd+u#F|IuG)S)HDPf#3KISmvslx>7`o1rAwapmL4!z#PPz2j70IrddSDU0(sZ? z1J#6mzL%_%dCFPz6pHu=X)Fq)u1GkH|7u1NE0=jqTVA$tkFm~^LCBDS;KFZ~ydvPB z`8z-t=q_g`GHI#!Lh%v>Oi`r!n|nRAZ%orI`@a=;yFJzDTZWeoNsX%RN6*FL zwK3c(ogztvSBV#fC>^#*Tmg7`A=Ak$^=726>5hM2AXikR^84(cQAgTYKaw?h$DMSL zCDSMra_JHM4TkXXmc5AFIdBt|GSGOk19Leo&Hmpw@k` z>8zDj2hWno_ztx^V3mR+y)Her-*1RkXlnEIT@U<7GX?z{VQmp~@p)S3j&DRwftQc5 z3TX!&<*vlfF%Q1n6+#h$EAY-9EpkFua+e6l3L;=^ocmcj*RX(tAotxUg}qoVL;2T` z??g(aM*);f?*{c6J#8+5YviavYdRF!3{x`OV1%OEzxaE^IQ6GtCb`wq%l(a3nX$rPZN)~NUN&Q*}&bd2+KGhmxQ z89RnkhnZ2{Bo3xCX7XMznijXvDvjI_*@|Yoh_b9R*t9Y?y=fUIPA;;e=q;N?VT?C~ z`atwi`Sds7rs_9}ly~@xUH>Vv4drJuVWDTQyzvBV?S%wzg{~wzW7#!Ya)VQhWG6*J z#YnDu#r^9GsM3%LnT}^Ha6HlNB4|HRHH1+mXWWCGwaL<0QKGxCxvND9=k7*+93TN0QP7;I(n0v`B^01317^;-(XN?lDQ##Xi z?yw3_Cnof28M_hnWz&&nCVI|1aqOjD|iBUh%oQ{LgSm zW~ZIzh}#u=REyT;dOv-0xxLzXqIsZs(o5U*|IHwn(GF_!2kWYQ`Ru2>V7{|SCi1vb zgXR9zqt0!^=Ju$s#Gm+b$&9cMO3SKrLEbrI9_o-v9Wj8U)UK;vZV78aSV^ou^C^gl z*(tII_J{i2+GuKf?@~Y$f!J~NIwSN6*S)=v51xWM^{E6jJ}ZR_XQ1McC0Hl^^LCsc zrksdYh}|Oy_}+oJ0PRXQ@#_vl)x?W#X)9&~V`P6@R@~q>72*kr*KSBzbGR(n1YI`X zrg9v_mgTd{8TasW#yi2c;F|4|zo}=Ex(HM;9aJhk3J?~4ezehm69G@5Z|WAKfjOAs z*bAdgzlx(m4J=*MW@k4SqSql}xku|Y_y^!GXN2sDUm!njdCm6eNP74XJYEWT#M68Q zeTv^Ky&38v9*=Q;@U)QbfMrDS`Rm@8GN)f!lW;xbNBvV|>F?WYUF#-u26PTwMEB~y z3B=oLK_WuFCIukMH$&HynDH=S>26_1z$o_mS1&Uc%u9%1nhjVNY}JuswsIN&p2gV|Qw zxG#LJ>6U=)*=)A|IiuGfTun9vfB zCqg+C;n!o!bQLi>x+YSm^-{BE^_rTnhw6MP;E_Rg(eA03Rx2@u9gue65NmghBqz7` zyj16rv^u`EZb+Fn1gOL_5FFG^Cd)wAG1Pt^oOHSVQdD>G=iJ zNp4adaBCFNXD}tOmw3x9v-;qr3+Ek;I|X0ITSN$6B<}J| zZTc%2QrTuD^7mAR`-W7SiB-J$4q9Q}zkB1Jr&pA|KJ=P%PCi;Pf+Ubrl5%f8hi?bd30vJ^(_<;e3Hb&tsajE6Iv^LTrxglI1+8BzKBleLh zSaitbI}64X)HL*cFZx8Dm-Ar*?FuX-uKv46kk&BpBsrWZWa1&Xsk3 zl(?CJ?}`13wx)8}e0MLjS=qnx7@gfhuyS3uyDi{DaP;9$AEkN)W#G~Pv5sDrhX1wU*c0g#0VA(-c8xpraUV*Qa;Cn z7FUxge$SCXa*ulDL!%3Vm@C7 zY8eHT39beUwXCD9{wf;fsUyQ_WGgh?eM zIH_&zN>wqOPS->nqMHwIyrR}QSbvu#C`z`7JbVP}1EXT1ugFTN%@pggUT?^mU%(Lg zDS)ZS_d0hld;lgMRjG20c-%ISop3V2#wHw6&>NAylF)*?05(-qn9s>;dRHPYEe14! zD>{}8ffiy1D9;`h&F5+Na8tCU0=ccu@9ca$&>weioujg-@QI!D3&bSm*AfC85VIY` zGAMI2lH`N97>Vcc?{FL2JKa-e9I~I@m-*0N;@G2F1=<29;B|b!nhnFAP{15FZtfp~ zu)G<_vH}LDq+`eHT<^dVNk6GBX1&D#0V(nEVUrQFtAI=K?&d}m>a$1B=CNX_5o~&^ z**%)gmQQaSpZ`s>HI4JcHqug6$Yc=ofK2Wn_NehlCPg!0aFAS&H@psP@G7FJ8rqeD z+AlE_BO5(ZSxn&vZ^fXaRC9;5GU5c{0WF$}6KP!UFG&V2vNu}@9B#~*yd~gPvkxkG zejSCOEvrF?PAnRiBCT1a_V5(6b0K_slhXOih;I%$#d0pIx#2*+1CuAls~y*Achxp4 zkkaK@>`1ag6AOD_eo@&V&_gKD+{B-xMeNBhBBAG-{eu| zp3USfxGRshneh}dm10c_^UJvjZ6)nxF{KG$uZQ-$u2=36GCM$X1@@5Su-2Bza5lL$ z_uh^@8AcJ+K77?As*I`NHH;g6N60hi(ep!q8Zr4++tVO z%1v|LdRT15{;=9KTORsYZB82Xy>+{VH6BSJ3sz~O5#Jy! zZR2Jb@i<`N(F;SBqKk0nFbgT2$VMzn9#|058fnRr7bZf9RHn5NnP69Cf;qR z+Y5w>ecRACzlazg)l~E}a*8tc&HYF)B0Fm%^(CmOH*I~2%1+ts5wwhx^3#bs|0#N& z?1#w#aD-1&TkaXnCcX%)E%u^ZidOZIBIq`YnFpZ^ZkYSvY3&!IhzKJ~Gb_GuJejA> z`}g)sNWq>wm;JV;_^*N%BMK0)sZ5U;e~?NFX`!yg6yboBG!<_2fo{=uFdbf{Af{mg zRn89K4c<$L;=3%ptPgXrJz_}HU$ryU!ENR2cL@%qQ201Tg0(yLadh$I7WGuLhXPL_ zJ5}{R7Sl0nuh&?~G|s#XtsVU!8Lq^l2tvO%HO5P3+gYRDHJ=J%Ad9r_a<`0PkBo^( zI4>Er5F#t9;Y_@r`R#ipUWMA7JKm-#B?+YmP?n}~1r54h08e-U+G*gM5Rvk3tE*+B>HbJ=vY% zK9n%Y08Wc7eUr{D>LluCoJvsd*P$HKApB#rZU*ou6Bmgi_4O;}vpINz{g?1`Vxe!i zZC>`LFKUMD88(;H(h%h|2BX>SIQ~R_To5GAkcYzNFwTj_ZY|6)h$~cingq^N!XBKsn|p zmUN`fK{XSbYoE#dA5{^8H`F?$36pxc$qEi+ADnh{(k846IL6;3DizkG0vJr&`lsU7 zKG6I&f8m}^2mRp*1JbYY-$IMnSgAU=)_a_MO>g%|3Iu77y$3bpR5|54>{U{!?jJpr z!r_N99Y;DNh7No3n|HU--)ZDEF(?YyTGyl3SQ1v5j`zYZ+yAT zY%X$+WjezGU72(Mze2slrCcgEhe-J+?x6mcM7)?x#>-7DCDAgJ_vR21QpeA0j;|Nj zu{E`4??8H4I`FZ?e&oA<;_c>Ee%6>Ks{Vo|2996tRcT@jrggcW|^cF)T?`NS! ze!ZjatkLEyFgN4(7;^^Udz^#Spy(2x&=3(lzplLe6fIK_FDRB6j-q z3VnU1u3>0Da6dNXH~juJ>y4m%!7RdE?lSB}GNBv1>3M{+xB_?ILi7PK z(|HAMeH1#BrN>Av5?0dc;dN=25jJ9-+?&D0wV};~8LV#fg6QmSI*V(4)Xvl**?=3E z7rL0*V_G?8aa!_Nxd!Sp;4G=3X^35LqmZ2+Wjb@9g?W(u^Ue@E%cm0Q9y|C9EalbA zxM;pf4@vhd+PROecvsb@ZSAn$e#!6P=4rEeZf4**7p~V=Fb3k4o@X&_=2dSV? zsReJh-P2OwZNLKN3Hp8F_-Jji{=$Voh?pwg(tR{Mo69SvNv8dob?c7$ob&9nn#13W zViU;iYZ@a7j;(v_)&r+axJ`ZcLeN0uZJ@(HGP=*&7jD0n$jh!1W>M+KNHJM)zkwzh z<3hOBn*yO-2FNFpZS+iVSM>X%ENub{FO`b+&S4Da)^eJIh!#?oam1n$ywXl8JB%z4YLI^u%0eughoStF}tOF)y&E&Ifz_ZUgyoPl|pwd z{|l9B%~!_W%{WWmbL9Vfj>bx3jc)NdyBaR_!hBxISd>huo8Fz}7DLzre?6b-P z@`qEdd{|`1Sfljpb_v>v-xB;7Kk;c}9&iu&8(N5_H=^Sc>=o+6fYJ1M4?5;_Lw5d$ zWd4ta-$k(w%5EZpm@V*cq({W)XZrl{QKU@rbqm@1xh7Y+9)ROb2Tp9n`DI9Gm^S#) z4Zb8dEV|sr+;#_euW$Pp!pbv~70QV zj845S?u~)yMlTn0Q(TE_r(*a8Yavkr1uQCm{oOk89M-$deApq*YI=S*q;6XJpoE0)_;s zfDTxUrIFk583HjXKXvI%yy_7-9oI)|>`ijJQw{zM8%bW0@yIAXq^TnlhsIZHnA|h0&sEMKmC^NOR)Gx!mqWZ!jO}E24xf zK}G3o&KdAZa)n;K(ve%JENBkF(_i4xz*p-efAVA@csgsH*qorA@VkhMo$7^2J?4U+ z_&Z>%N&W+PGU|ksh*aMO-s?qgTPiQ9tD3=ZHVpi#kep*uI>g zAM{m`HsA9b$R^s~z??i5N$O+zs<_U#g6W8KWFL$@F*ZrT zo+aVPI@oSRNhoUb^1_rSeLE>_&tQ1IHF+}!Y5M9ypE35VT~n93M~+H+Ktu;Lq7Ewv zd&%wVXJN3SQXk=Sm8{4+M4|}I<0dz4c-rantM=`a7r2Si8Sd`;sLxoDUMa5{j*(~L z@g(Uy(E={_kJN4MnP2-l-?F&D)jE~ipiQ*0Dvl0QB&iK$1)z*$f=F9TVn%x~&#^Uv z&+3k3SR`N`?F+pYK-}pkuIYCM=6(zc-lAV-ygvGfk=0q4N|`eWgk7PO$oEMX&N-0V zBiAr{#tBJ6u&FOhR?%CNWO20f^{xnmKn^KPoT}qR4h8-6U+b?^&!oJn^uPldI%BchM$=^^0OJ!l#a1WJzqXuDlYy>vrv*6}4@#R%p(#j`oEY9{(*L*^Y^( zG&k)Em;zr7MCx$#&1wbJbxmJE)Wt>hM}0~fKOSSXJ?tqN;4@bku?k@ zKra72o>?Hw+*_f9s2tojgpn#M9_?2%6dB}MmESe}2rIvq{|)(}8f_tZt|mOP99^^= zrCr%^rSdzfE_TR6cW29_bEeZG$D`mQh?(z&l#oUPl0*qu$hqi+{ERM&|aws zT)tTG@F)DLE`cTKtbrgp)V8C6u;S5ozcETEA8D9ZO_tH49YXdS?{z^HWy=ge;vGrt z9SXJlz7sZ0Vtnk|S;sd@udIYcPqI0hd^AHz0OyYpe$E~LUh#>J4RS>L7*2NZC@AU> z9Cd`y7wo_{#pTh-B7vC($sDt;;cpNBTBbvilZ+O%4}dGQK`3%B1KZOkR&jyy4ZJ?0 zYg9)bn?wz$bG$%7<{Wt>@;(|-9NnQ0W04HFr1p$5_$Vm(p04~lcoRof!e5I}nzK)s zsUqaY0a>r=8=2y@B_us^AOfO^NbK@U|yH0>dV);OlDfMBc zx^eNc5-&^K%CJEOXc$ZUoiXDFlPpvG*>Jph>ojOA{w11j{oLI$cMIZpFJDStdzkjm zRQs-@z$GQP3hze?emd)Z$#t~7jemdb36vT>p2aO9^z_SL3ws57r4GuJmX3Ze+r!GT zt`ABZMB@M-Dhrl)3awbWNGc7~+)@!lmS>O%bXvO_pJVXJ146Y+Eve7IF_CF^Ol1Rw z$mX3urJ4Q|u=%#)MUVomp@}LVL$~W;33x#S!%?E{n6VXzxh?637e&&2X8WNKpi zqiVy))k^TP#k{4_!XS1*spmwl<4dTCWuZExc$o3zw^vS`MQUYa0>3!RbMc-t@Hatu zzlzaU-B~%NC#*9%jf46BEy$O$B#45KHgLC!%?pjXt|6l>U8^+L0I@s#VQE5f#3m(v zV!!*>l&E#QsV25Fdgss!U^2ctoy$3nDZtLMQj2RFwZ#mGaE<#NTF3mzFEXH1FWps9 z`)>Nqml;0aB~DJ~jJ0~NAZ&{|#<2IQH8)Hhc^)7n@`Tc%>jt$IHA9|%8THfe^GRfd z6im1~s}KV1z<>tw??p1+r)Aldb`Tc(X6QTEPckHcq$ zbM{GgBHivkCL*7xw>(d|$cVehPkyz9Jc%87NGxF3x$@&A_zsJn>OH1L-);+gTrG!x zVPuEMO1i5gt_AzqPLy?AM5TxM1ayCO<*xm1pn(w^xklI-Upv8eL!Nm}m_+P2xu)ya zUd!7_-%^!GQAwIVX6p7$d~?wj{1gm+H9SUDTof)phF5BnasEiTsY}da$7<%si&fdWt1ScDYNm{>QT; zjhdJs!&}d9Fem19%eRaYqpBq)l<2fj9 zEa+0h5WGFY73%ANh>_%{h<6HtT80d`634TW<0xplhsKL~jcEL{w5QO2(KAb;iaQ~s z+%eptaYS}F)1+erQ4-L3kYgJug}>t4LPiK%3bhBI0EqL_=`c`JT4uR#U>PXH4xOhs zy3}wfmH)Wv2IHfg>oby0_Q7M4br2ALt(rfr@)AJ7J9zR(B|D1=$PqHFQuW#t< zyQS_9e4$~j{SxWkXKI>_X54!nJm1+X4vJ57nEpsc7#48*=8zYg*7Z^@Q z6QTvamlr6=yFIL0g=PG5`axiy-)y4LR_jCX$uHN6o^_&dtTDc`Mz%G-{N3Uo@P3H! z0A`fp?#DlNQI=N8Mh#3?-ZA1Wvupi`)A^=bxE?x#(yRNs)$gs$a$H zWz&K;!KIYut*5?f?t9e<6qH{6=q;0XHzc1Eu~`>S@ZAR_g(G20L1#oljI zdS8AD`7E7C^q(?{@q-D4@z$7%9Zse4VjPOR(o=p`Z4nsE0>oiD^Z?)|y$m^MsNAY_E|9D7P5C-fL+{O*GHMBH1tY%;hsbv{#&dU*+`N^8iQ z&_^`X(rMJ=>kIp#Q$=w@6r1`X>LXVFKTk$B;2XfcSUiKbF&bAQFrOEa#uFo=C~iTt zJnhoF)J`_DV7>)tCQ7Tme0CI}Y)@W!uI8Q~Oqhi;pyD1o8#JWWGtyM_H8@QEk8`B8 zt{=81!qlKdBA_sXxLt!{_xLVM*cCv8T}tw z3v>t)h>`$2Q~a!Bt-$;5EV??B>tCzA!W`fOHBV@L(#MaSVd#tz;on9b?){sP^l6u- zf8Q-j7};ZBWT*35R;<^`VoSABI^T%ev>B(>xK^Oqu4{HB*FZ?p-(@;{H)U5DVP4eBA>#YKzYlB0{@h%c{Jne9r zUj{kveQ(`UZKgIE`$!Vzx2P1e_iUH^OW#?CdP_&Q0q7S0f6I+F(@hG{t_G2H&suMo zewzm)LxP77JWv*0C~BCRUf~MadQ^Kp`y!HvBnL+ejQq~68X--U8P>gl$zC8+q(7J* zk-|hI12uocLvJ%I2-*ezML^D)g{l@u;&6~;Rc?~Q|B}+;rqhmS1bFTw%lkqNy2yXo z^+#>elZH%kYk0Cop4~>PlO7S%IJp{k?1g>veSed7zpt7lcV9H2nCHM`01f9;P@Z+m z?Skj)LET$LF!Ygr-zB~iWs&H(uvLmt-H?4n&8CXkOh+E;F}(`hiE;w+@-i58;42#^IoYhlwBVLAx1?wwdBr z?z??5UyBG1A^h_8SrxKE0pF4Pcz-h`kF8;;;mCPnGpobky3<$c9|6ciPIu zLCffl!4-d95dZn#}W8HuGlez2? ztmA@u)_M1hj!6jLBIxsn2(1ukO`Vd9?VV)RU#%Ui1Cnf0fKCH$8-K7AM%`BW%T!ct z@45BoDiQQz&KapSR;fspbt3@#m#vu290b(F>Ir`7CE;2rrnT-ham`mR3+UFw6|=ny z_QLuYB>yAkMNsZKq#ba_En0-B(q1P=ZrEr=%yGB}yt~@NslUp)|I7j!1@mrJmQ~`t z3da!4UPVtrJWYGI2y(NE2NUX1Een)RV$t^2kl}BOmTNE94hgIODY;}8c@d923hul1 zl=Dk5Jp}WoaYQvikz?@6H~GM=`K&RT$vD8eFUlsr;n_RP!PEY-HZIYZx-zm1?ARJa zMR2zp1S)O-t!VOM!r18ZL`9D*{g~WRQ=X=>3t6G+AFXM}Kh#VKVbC(UJWPoB4b1^9 zFZU(Z7S-Ms?dJDNj;=EtUXk(F-S$?lz{0GdeRC7n{aBZiC`@R7Xch~I#h@rvqPbPc zpbt<^Ubzh-Nj!V>Io8pv96_1O_tEnWYiV>c(bq`R@Ks&`zW(_3XsYk})pjtS!;s{KJ>(?cXiBC__6mc&cNH z-B+u0h!Wqrlzj1TpGPn}Rc8`=U7`Ex;Rggwd6 z!sanlt|D(-$RB0Xm?2$8zhPb;`~InQe)-6Aik?`VHge)Leg7Zc*;>S`K$FvN@7gsy7tbQ<#==!A$(LGsX$&Di42h0B8{99-oEpg zwpQF`^JG3eHlDvF3OEiPNe+1%C$W$Ih#4gOIZ_8vACjnn_w&^=7vo!%ki4?>hfV$3 z+I_^DAqp;Doh}jUktI!Vi^oyLc=&I!q(};ax0l!&Nn!!=v&g#CNf|yz)acSF;W^S9 zJ$OL}PvaR8$N~PC9~H>9y<(g^hO~*7B~&xp9U&(}zJXQPJ7MF&ee|<5lN?_T48MT) zy=pmoYZZ!Y48Vz@)A(nPs#BfBNxjaXa0iiU_f_tR69S88{?p@)@r@Dt)UtT2pqH-| zHD@_x=M$tX$-r(|BUj-12BrDroTwG!2_mV#OSkeJCi}^CUK5E&^OQHhW-r?-*s9v5 zvv%re!Ds;rVf}{u@uTMj+Y`DAR#AQoSC7M`|FfX_Xdm*~f<1as*9IS=TB9@!q#EDYsV+ZAj?Dnpf0D-$56_kVcmXuc4mhEO{ci)H?uolA~6)CDNeUa+u* ztDKuNJ&0f1|IE0TmJbkb@ z&`i$XseTFBq_?E`;c~&*y#4F^Z;^%-8uT@M&sRVLbGh0EtuB+!b0ocI>V3L6Z`@<# z)-Q4+U5Zp&$F?cPLzFnWDzeI}@@W$A1GOB()p>Y4d8fqdl-AP|O;&6M!(@WVJ={i@ z>$ixW;aYa+;>cMT(zS5p0-`|0p0JBWAO3?l!1Pr)+>3q@*9g4Gjvx8V9u<<`J1NGy z&&t_<3!AW+ogA%(yFIA34+dW?x?T-lU^e=?V|QbI0$*9et0*<#_2r7H5gX*l*^gJp zw3YbgQe_!{iIuGk|cO8ygHB??f);lTbTPrP>93Im5CE}JoSLr4uL7U0rcpKntE&Ug< zL7mlG9@OrE3J%>hL|b_2f$w}WI9=mpyAqB}GUA(M7>|e}XkiMx5EdzyCm~ zK(_Cr1&)uSnXqWpwo>`r_n;8WztwheS1-3+=#d`0a(5SBBa zh0NkQ+lUUKn!Ah@MMp@%c7*bZ?UYbW)MBVQ#n89R^1vXEtiiDL)Iw@L`V_pq7O17- zbHUxeWf|G=bVMCl-xfdVBk>$M1}N!W2uS41EgU{ZP`Ex5)!qq5z$prnQAkoRB|OaA zkqp!wpN4g_3_vF*3A_)bJFgYPG-^32%rXv<2dR!T8~r;y1y|f6HbwqsaqVzSo*>_5 znCh!|z4y(UR#A5HnxYJTM%ZY{FJ~dv&Nf}dQOy#oE3V?r78u<-ZQhUKmCm|%f|60} zz`jQ9Fgm1`Z{`>FYLr)Yq~&~ZMSjE1eY8y}+k<{K1E}PvDA*blP4hmVIb0&u`^BGs z?e-ob_r;=+bdeR$O)~E;DjZVkR9Tg~0HrFEX_Xm$)ic;;S8x8;T+Gtg$`0%I+3XDc z1%)_Dg*#LQZl&b#f_vhSh^ywAy|-(%9b0Tz$+K`SVG~(^=wmCEN69bu@%AiCSH7`) zK_IaQJ~SL-MAea=#e}Gd45v9C@;rnyyW}jiZk#taEs&PW zkvGtMzzb2LpYns?LsR_g+{L||{KbH9o-vMU`Z1cBrl5}dJ-z~rOjb+8o?0(fT&UMm zH+&*Ou-@J_#j}FR)Mp2&>Ds%|d(?5zp7tvrXalpc&3b==5#u13J-%S6PJV{c>tMQ5 zn+vf=Aw9;?kv>+B|1obWq_RQDKdekUA|!CWT#aLFDzbJ#yK(6xstPd6s36=gIpUzu zA2vqwz9Ek(h+PfOj!`#{7^=vbq9S=O@1>I8LAHgDkrR@;?>)V;VIwfgP|)w&gbiY7 z3z#^z`$_eHa&pU--E|7P@`FHanqvHdPfHLFsqqE(T5?QwP8V26-^j!u4l1Eh2^y>K zoqjR4R6oIg_hhid10+1Qm2Uq=VS0sk)hnU@$oc3HS@on}x>_v389tKgc18JcOWzXk zsfbe29rxkIAAUq*(RbEKTis4jksQn&{YnWM#<2A`9Gq{wD#|}~)|pLkyc+nzZSSsJ zI)Y!QUV<;Z1ycJb;7989kUsdg<;la%)c73FFYJFjzZ#GG{+}xd>%Q*ZJUy^?XRSY| zr)J}!&Fwb*eo6dc>7lY}K|OPp&-V$vtDijd{rzc8<#Fl6 z&Yk&nrr;62eRf;B2k7_QW=d~$R!M=Ne%A%y3r~o+L>%HR!b{vm=ew|v^t!(5&mOrk^{!ww0}qyZ>6w@>P0QUb^Ia(u&qZl zkbFy}U%H7-lV_zYTtuBX@d|0v2w|kF(0=%D)2Z@1t$Ox|W|qIKdW-h6khXY?xP&uagX!^V+OaYmaR)zTFd`7=%c!kEsY8EgnaPxlJ{&5VLG133ldBMGcy&szon(b7ts9bSxBQejoXkEX*|{VI zP?+NeIzK?%Wtoy+Iu*RdS9!g941H~b#wm4A#|rcC37{; z?~s1qs5B)Ki0$L-kPxS@>9|ve2!Pri&UigYpx6 zul&CIcXt@y*2Z@yO=6dvK2tZ?wB3iLa{-7$176Ax1AQ_j_;GCBnSjlsSCi?w!-3g`XT&Cc{ets?4}u@B{kvBn zD>uLX+yG+`f3Y-)`%gG{35DqO0Cvx=pRh?sHG&ppM>LWa8q_YvDecffo^-oK#(x_WvjZ|fH>@$n}QpOeGnQa#58nUKQTz$~kJ z81IlC?PKsYhPtILujMBBYzsL{(&j3!R$OSnlQ{mg9|wew5yO}kFVV~f--s-S_eXhm z$MU$%ne-%kDxcuY-D2N2oc%Lx17v87Xw=3@cs+-JKrVJkwUTM$Z@jm$Z}#oCE0*l7 zA3UvOA?9ut(pG#CupwscnfA5c6CK> zFEFtdJ(;RAgh{6orKoImHFu=$7y0V1`UO}hSCPp=sH=mSI!F)v6cO#?6|<^uIX9$V z<2t?KSRhA-q~4=8^qewJTBzCWR+D-k%J|~ZoHmD_Bmb;8Zg&|_m@tdIqixtvl*Lgw zH<~a#Wj8kTk5M`HiFhVbw zW5hdUgxwd*C&Tr7dH`xk9`~VxfclJIvG*^^`i$!vfF>9Cdl_q29FtdmBa}ywAJVjP zk4@TVROfik zd}vj;1yf6?zkixST^jVc(zxuYn}W>JIo=|!J)=Eev7V6^&JjfAMK@BsW4$JEKh@>N z59!@Mf1ky)NI69`_du-;0I_d+RjQAkgaSPixxkKA>CDsH;7@_1kKJX|)Z+wG#t|W# z0|JaAj31K42y~ukCJ6H(s4VtT2js1x{o#e=w)24Y$95n;jEw#-=q+kZt?9`EAo*Z( z88}&*X!J{a(X}&*t(x*Ybr#=WXPF{?b>b|QPTXRe^M&@fIKnjHx zsIg-%A@Qfs^8Wc^?jM|3bSd;($sTcT+@?DD={rizmewg|O>qOv#2GB51^bovHl@gf zz_+&}qoZtw@-)E)?jS_g4ILi$GhsWi-T7_oqMp~&^hjo{Wur7*RxUAa18aB zQ^ZJuTZ6LS3RyuBqkfsPAx@{XK~U~Q%(Nct37>5vhbPd=7yVPigjUyj)oZ!%!HG0K z>B*Q2Pi3{mdGIjK+9{)hpY?cbvGn9tWKsVwda1VUJ~#jO-o^=hE_MFarFb^^!sZ+{ z<&mNclJjNryRM6)vBN0q_fwS1fYQL6?a*q1O3pSLT~;Kc+d-Mr1Q(@0yH&?mH1TFF zYx$DV2u*x7xDqz|(qBz~)E`1=nbY)Ml&%XmHFIks!D)YscSM764BPx6{LC5+$SWlt zGi8l=2mRN&EN3wjS>C~I@YullZCjC}a~sGO-bl#0nNkh4-p5eduO46OV=Ce?MLS*& zXRQ^EtKQ1Nn|{8Ix_i?q3THGikT;0|vn$Wml?a`9h0WKleZJ)Hj$zf&N4}OXw9yk* zt|cQ4W4zWqngjl5yF7<1cz@a<#>7mwpu36tg%kQk5@Q>Oq7^&G362-C=)k244ZM}( z@Ys}LjG64~1tBlJ#nE{pG7w#Y+6ZDKluW$STe0KSLhw)GfYe_Hsl}>FII>jb| z)08=Z4AJX&ua>x3onkE~&O$wbuZ9yHb6wwgDs&=Dx%3E`U0&+)Xyb4CaZW`@TC0?) z%u34c9zHW@h?OF!FC6$gGK8x8;?er%SJNk9iXN5vhqPuO;a`x4)scW2i=6pJ3|YiV zn3YL6UsB+J1(&o?Mi`xN#S5{Ik6D4Rr$S$@jiI|*Ep_LqMqN;X67ZQ< z@o*vy5vNbFL6Cg9&UcE>U%G)S0)ORQ{Y%`PeM5J-JlR;V?+#zCJ{q;&;Z+Q)k+_>j zm<7W6khbq`8sA;3F)+J?1?sv5<#@6bGeus7Pd_}p+M3d`<~^?^sJ=#O40n2b+Q;z} z$>HxUX)mL4`m1B-zC~J?q{CnPD|l%QPdW%6Yb6|wtD54-SDs=VH&xp z>pb=6mWY0pSRQR>LN`|2f`JV=6SMp4Afnq}W}3eLqd*3&*tXmavdkV^D&K@$o)7n} z-OR0x%RRtrAB=ZSi|>zJ8ZtEpH06E|u(TyfaQ?*U_Vi#Guz9oqGkxlKPvWWU2ijYV zUqujKAU^6qDqg;b!!Z)Bk{#Cw;X8E~C#A=BFk4!SHVW&&O64wL{Idc%k!(Mrd_`S% zg;yOqO>fUL$d76SvpBtzZgZgyws4@xSZ=of06C!K+dy^xZ|Bq1=w^#Er2X(DmHB+J zM?|TBHv-l2k2&%RNTr-C#deIC@`zu20^T<(v+Gt3Yy31B&%d&VJo9qDrslG$biio$ z)&zB~-Toq?%*~j_>lw#M1|2N6732;eR4DLsIhO&0fYSXEY;9*3y|jBIExeIZ;}2eWhu2|53O3a1P3*zu(oOA9+cp+E9iXJqf_50Ly+HWk`><0`&a8Om zex=oYAnYIvfU8N*ZUKH|YCquUW`)FNG=nZVbbR6UH`M(zBN;*s@yE<10wY}eq#Pj7 zR~`A6p)BS6;AM(uMI9S(TQ7re6fDK#cvEqm=|SoB5S^yrpikRGznQ;njx$bHur}OF zVYf!%a0SNLw_>PH9t&aHHvP#OH;w1TRK-m#oC2ys7$!r)#1hy(`a`wSBrjEx^xqT+ z>n?MrA7Uvh-(NXv^3Z(!WWc~DhmTexh4_SlP%3`tv3t_wwa+K>B2fgLu^6PG1%f_n z@(4%ws^<)lPw4%^;gVVg7%WH}FcbcGtq+pY4Tz{#nG&Boli$%BNzK8&L#-hwEE{Aj zvAU1sf8p1JlGQjI-800gfuRbjP0E@#ICIq_3kyrw>iWC2V|J}KN#)9of%&yiH|QdY zIC0XJfk?>w4c-1v$^#n4@|FmX+$$9fqefgI(0tx95Vjrmh9Ea|gcAN@5NkD@NwXMY zzJ^auAj*-ynCFQWDKY>r#KNdv|LJtGaMYrXQpCjU@7teyL0+`P_sMIS2e_({>1NU^ z=k-Gt_`x^f@7n|*fsAyX-E-rq8x?56F@}jS5AEt&3e3uR`av&K>X3j8AACa7dy}h_ z^2L%-JgEFnH$MrAgI5C9#h7m%Q9M?iv>8e9SKH^^5wHVIWn^KWYR%G0Ya#V|fL<7p zZ5Ye(q3$2^VKZ2;!jykteB}Vyj;f&Y9I7sz3fskAU-4Lw4z`D_*4OWRvDIrMcphpS zR=V`85qFd3ySu&@hEYjGap0S7l+ApWHWuh#v&9K?;AZC&9Hy2s8K$F%&Wjc+Hzf;A@x zd!3Sw<`)~$_mxCnJ@Q>NrxX&S{a$p31kf5bw){--dy)TSg{-cj%l^favBb%}5lQW5 z;o5>McE-VFU&#G*m~E|V8~>$o{#g19q8k?;Z>k$vAWQUArfTv_mLr zp*}&4c{x%`LCG( zqVPGtyk|$GjTo)U>lhI&K6OyN7FzmF7QBW#TBh1YN2I5am@FQ}&?RvCNMwc7FN8ds zl)P;?Un%-^Hb*YklJ&$4ul4^OC;so5;zLV^+>~79*2k>uY_GANpn+?F`!?UKeQ5LE zklFohc2xm0;U_k^zdwuM@)ULsDd5s9u9MU=;ZPEUKeX^{o8OM7`dHv!CYKzT=Ey}+Jt>!nKO4o@@!X&`LYPXYOBK2ec}4p2XZiFYqzPB= zPHo~qo}@-CA7f$SG?>83P9oT$eOp33GbEQrDF||6aI}2qg%0JA6 zncnDKszB%d6HoTd8iO0PeQ_E?R5IPl0F6|oUz||+HBt@VsvylQQ&U>e*lQ1Y3_m1B zfksg`C^F}nM+^#xetWnFNCq4-Z_u-ViDM{7h6Jm3t{tX9imXmGS~=GVx!tBX39wNY zYO1${JJEJwBk_Ag$z)TEn1iDe@F>YO4%Y(PIAG7M(2--FrOYvmi*-4)HK7zJqY*xZXWP!+Kp5d2pzPC5nF3 z?j{J%Q?$$P{LKrVj!M!*N`UV0>p40ZG5DguS69r=JXNs{N`JP(HyN$2u)f*Z(1{Qu z?(cX&{1G-*%#$ z!#AY;wP*d?rot-r%eDT<~b9QQp(8N@;$&Om6M8zg;F(Y}@79{4VuXKfx`O3~e2Ev5&doC9Aw z=t?UzSfy!J8rT&aLRo!#G!nmvO%Ain0RN5`LG9&M*67W+3;J!nK4+T6M`()DRy*eH z{Efc}oot;IgNi~)U|WvFob(sa>3gr zzmB_^&=huvfr0qXpS}08FiI>lT|u88rlu~AeG%lZaqzGTybl#GLWbCCPT6ZQq8U7+ zc^i^E4JDHz3%I6%4bz}K>@99=e5NEw^P7y;iA3GRzxp2@phI4^_2!vo5<_vgsgag2 z&v1ye(EIN6FvlMV#OVU5+h%H^@*)euJfa{>Rl34NW5NM7pV#J^Zg($I=kZ)UQR<_~ zL~|PnZ1+3Q)xabb15VxIN>|Xvb{1hFg>TNXC)WPRqymA7i?1E;Ph84LDI9>%9+tTY z|1$u7Ofea<{L{Lv@u-nue^?@8{hX^5QIDn^m`X@|y(rsd4lPmbG;wI3d_qr})Nw`$ zXa}ESJw9NH4>={jE3^Z8G(fY_`SN|FydoC1f*7I|*)I(tqWEsx)8it;Hr4&GUa(0` zPaiQUxL#{Wd1GWc0s4H9xTj#`gQDbXOV&)5KWm|UB6}O8AKv@;zfWb?@y>602zi!a zopk#XZfu^uZhzJ$JF>7(xB)KMOOTb{q%)BG73v4~yY$}6$zYkOMqHd5>v~NLmRG*@ zQ|pNS{UzMEHaN4TtS;|{@tgjK>&S2C1~+7jQu(LTvboJTRE`1d4Iw|ExA-Z>NCFvI zv#D`Kg${jOU#VCG1+{1A2!@|zi;hQJ^|K9?}^y)!!wJ=W;zRV|h#Yy92{1 zsLE4+CByrd{YI_6qPmTL&Ck^a{~cq^F*Q;|AXQ($I+C-N#d9tuu92_UH-STBqy%qc z&KuY~N;P@MY3uz}GXp!04~dRrTUFxya_`k%g*o**>}Vo%XKiuqie)XSh?>6ah5F)3 zgX`Wd$cQaj{KH!c??wGe?GCqkaZTzmLt)HnmH&K#96^>*K(R(V=u}y6N~)MR<$)Ebs(5PF#>XlN|u%vqFy#A%eCdJ9DWeDkkUwl7*HIBafaO*}qlB z#=a3*_jB0(li6`dQ0bFa`dR)T24hv|t9S?G zS_EO~1QP5T?mXEFT{TYgXvN8m6m^)eLi29yXd#J(<-m0m;V1!0XZi#p5=<#ZY4bT4 z^fdz45&x9CqMEq6>0h-;rq+jI>qb7r=FvHhHMKoK@)@#wbbVC1Q~b*SElfZPcj zO}Pi4g&E=_+95nvI+Xg`Fs7ntGB`7N*0ah{M!&CO_W;x9m<5Q zG`ObKO1qtHVA#ySr1)jLZsZOE{!jSDa5wTpti2?t;m$$h$!g`s)e8WX{3zr8v4i;)V3oQL3do zzw?_I$GwF2@9S)Qd~!3{C-mQ8$ypxLphtJWM&J`yxRm>;Ie0C^KmBMtb!!PL)A`Zv zvyOLSgGeB(Uc^CmG@01G6yvG+;`h!0!nokFkNtqIzxCQbmp^P7|3gm9HdebD+U6I~ z+v<~jb_uN(hYPEyt+^sO1QN1Vt3#W&uC|Zg*Y(Y8h~zGkf!lnO$P03{gLB68XAUgM zZ7R)QL~od=1)kJX)1<)trSIk7QD%X17bU5c7o5M{7JHGa8|pmu(wr71jA-pVddf`N zg0Yp!SqR=jyj+`zow843+MMfU_z5lgLsn^lPm=JMb89oHy5!E=3DT*F8Pw!G>0VoP z_sp-v{v0A&=?tSE5gVV2(oU_36l-2{s)4Vg3Q=2#VruccDwTa-H|qKv_q(hK`1W~g zz3IZTf}j6mNPwF}4%hFu*3X~LHo>bSOi*g*V3YUC42y@g5=Od;=dZ+5@mzgD_2KLLFRIS z_j21c2SL6Nh32Qh|Npv%=b@^TXtwWau}S8BXMf50J})Ra+?jmA zspt6C%i+Yzq0mI~0Y%Uw-c>_j#O1IP=I94HeFzq$AEGtL;@qJR1$9UpH7QMV7HFqD zcGKO|HF1RS?Mcv;u|FhNz4#vY(VHY<1@$-ACn5#FPaBmzaw-D4Fkmp3)S3&MU}#9E z9)#?yD5tWNv+p`D=7Gw6UTlzQ#!iAmfR)%sI21$;;Zq2@J#Hf*G#5xG!KY9qKMc4{ zj*!Ud5TEdEyQ6m&iPE;$)K_kdo9fcAHZpW|4Sn$pUEZ!_%TEZ=d1}q0tyh**{XW@F zp*m7V6bZpF^0vBsA}3v^&Zd=NZ!Px-J&9Vdp4C%Oj`wT4gUymUj3vxvHI_QKeRcwZ zvN&JG>%2-4u$669?@_nY_0l7cHjI~YtGiWmfs@@GT*vu#&w24`KC&k{s$kEX8&tMS zdZan>?w1QA;fe_JTD>Vf@hmxAT&prq5bho-mdxF@c)HpY{@Miw&|X}+M+s~5Qh0h5 zvs(m4^pk7dIL@wdv(#{7SNMT!uKSpN#RujOLiWQKf^ln@B>wZt+XXG(?684YB zF$kxhw0eLul16r97djuJ`pE-SIb7*saeYfat8x)D`h0}cx!n8toWK#fXHR_7Jtk^0 zP;){=BGD=rLY&1Q%joO%X$AZB1QrCLbGvX69hJXKUovsj}P0k2Y)M5)D4P>r$F z*8RG~QG1yyEaa~I{+(k?DG+2GIxn0gUllvoRtu3(&8(9+W{O4)pYY>ojiXI@|U6N z7A70CwANU`oART&5E{iuC8gI=bWLU`jwwYd#uZA>#@lXWf77J>VkLT3>DV<}W#%d^ zIiUPb^EVNB(w)L9#fS_kw*|@ug;Qx5A%c_1pQyogE#S4LI_CcreNbw@Gvc=&8v>_y+Sg@tV7e-Cp|*r?YOiV;yrg? zvspb+{2)IqLc-xDEx5}~Gu#=VnZ0jV0P?`sZuiW2(Uo4t@=nHGbSH8HTQ<);!ai;{ zV-x@5%CWHahsSin-Dfi~m+8i{TOne5LOU)y^g3t<#(Ely`hQBJPq+xF;PpPsw?{;8 z6NGZn=nHVm?SBN7i`qZl35W=hRYsUura*~AzC2P#prUMv%)}$77YD++3L8mEexl6f z=CE+_=!=JVnRy*rOG$`Mb&H~L#Kg*fK&D4kFFE24lBJ1RG5eiNl!UGLq=AEpY}rjQ%IxbgX?phNT^1c$cTFdwS+$tmD3xeS{&#G( z?ERnPs}sh5j~~$gK>^vbo(DAFE}dT${ZzTJ)DAR1IgQ(3c^D5eu)nKueB@f0RRgv) z%mP<0ucCL%+`NAiWVqdT`qusYQuv5FJ@vRUR`Z?g$6uqrMSS+_jLko$93r3C$N9jK zrlDn~WrnIYw^Ci zRH7(L_ zwj#&+UwnOtp!_a&HFxdk5TN1?HP@}jGs>o(IYQg`oycn?0hKOHTj8 zWkz|-v-561hUm!iF=(jj%_e~b)wZ2N1CWYQ9k?Rj97)LPs;o738O};8qx{?^jXM7( zb(MIXMJp==g*+(sgkF%3cuu&hCO#cJqDi<0*g}`9;KMs`o$N<%HFa=g@HV{Bq?NYY zTQSD@P)es?lhb#vaU6(}Pqo|ggVuu9q0=@-KB`}(Rqp&m_eR|#dH^L0%OyBW1w{uB zbfdx7^hD5o0^MQEj@quWsO;;Vp2wY!8Y{iI<`02p%}}m8PeX zdae(A+%{=1{pVVTCMX0S+NG#}{_M5c&K(h85`a4dvLkJ-#UH`n2M~xf*u|%=Y)~%# zhOv>9PJ`#^94?dHe<%=ZhV5Faj<5yTO45V}yMwXPOhWEKGW&l0;gxMH$p!Cuf)=qw zs%3WMar+0L6Y&hGmsOt4Sl>G@v8Tk>Yrp(-A?MB` z>^Ypd6EKZf@-U;_E!iJDE^=0!w@-6(v}e|{oYdZCY2q$y)Ao!W~kE_$3=_6XB6wQw|Nlvi24E}B~$UECe$l-D)<$mELk&HEq(coQjRS%-12Q9^got#)_t)&HM|y{lLasGhRl2A4)GlHHn2{O$4s`U-qUU{ zBvFSEzAl-lA8|IVqWxle?Yy~3cJe-nKWM((Qm2%p$%i_$2vXHPN1pO---NwDw+c)q zY(jIaz8wqSRv{pXzRx@dWkk4vfmIfs-pz06?%&Ql0$=4wjN%Om)N7V)j3;+??5g$HvX)B1~2gO7=EBwF`@{27_L zGR?u>q>DkEBE@^q0BWI9XR%ejxT&vx@Z&A(+}iXP8_HwQw&iSGDcYqD3y#G1aW#VS zvi$&EYXp6aoUD&OZkHx2<$w&Y0nX1?F^w@lcDT4^uXhs*6(>k-rm`-8QF!IVK<>#4 zlu@o4vU;VYr{{^V@mRTfD{dI8vxXB@Ra!X`b(bDQeRuJlHOBo9%9-?#DRTd*xNsj; zp+wdV)mHFaI{pa*km8E4rV)Ot%*en={l+o&yWM904TEwl=ae(uwQq$sx?>k%#eIkg41}Aj}ncJUenx$1IB^tjsVc_|lqtOPY z2kae^TCiZTdtII|>OMASp#Tbc7R zR#;iY#E-yD2oiDB8@dhlE}ZU(`uzKOs~P^p3fNbfhfD`;>=0UT5AjwQYTek6ICosH z4g-Bz7kqmy%%E`~Pj(96;Sf9&um)UcLTznJRT3 z+<(cxEtPEx>3phWk=6oVmM^x$K<)O#?qZV$1f@Z<$a&~1cIS^xqJ6}jM~GX={=wL_!=tjx;*z%kaovf*dJkj_h zHR$Q)#D(%HSWqk*M&zYR7RhROawS}X^Ic$6+pPFm1tW&G@x69n3h;go=lfZDxpQar zh?~IDA_d9O@eSAx_+!N?0EzgTaP$~_8s!&homm~gq-e)swx7jbldSp)SE_P~Lz({e z_EPBM)b-PTXbJ38+)0sjr)W|Tc=mJ*EJ!-tb%g(xV*DEF0{A0R4pgIa`CJ!4=@R>T zkiXDUc{y56g?o5~LzA|5QCGt&P*`)A48`1fcaf=ioLab!iTS=rin(nm@JnKtux| zI$3Z`z$9HV(J2vuYm<==J258gS7_eFYeZEstF6M3TUu2EvSIGy*nG|G8Kn)Gp?I4$ zR^chv6Tl@YK0Dr$1hg`(Jx6jBe(H8?^7T^{tqrRJl(cV>tqZ>e%LV&JS+ONpetur| z@k!na7@J&BGyk-+l6bm$i5w|o{p^QRMN(W^TpZ@SeEKoy9lKGh6Kt}S^o1B(KH@Fy zAL0yVpiT9d0abaQ&L;`*wtd`nPI)?2dw<`z`|!>q$5*?w!L>))rlu81G*6ep4;{X4 z0UDWKrjd4TY8-8MFxc{kpT_i?8%tuQ56t}1azr*u<#)WR_mU#^7%o7Vroz+))LI-g zW%)U&yk;~kCv7ZZS$)!R9;s{klQiyMpjsJ=!@>s<0BIaM3W?AY806WA5%iWz;CkoR z+TO0%IiEfymMrqws`Gt09W+4NM>6z(jtVC6eGTUr=k7jyQrQ|Zz4|q7cpvh3aDI1I z&D$ewFf^R=E^5)qu}M}5vc}DhDIEqR;{LOfap~|d_Py3^x*y^MQIuNd`UIR&ndaJx zFWA-d(d!kmmGj`uT~OG;lq3)Sg&wRz2IKj}9521x!4?0ei=mWW7842wL|4QDl{|QH zL3%9j+*Bh`&aFP3$nqhZRZtD21zX>ya08_R(s0qmHVIM3uo{RIC! z4%cOUQ?v8nsdUgawtTWC%JSH7Bo7M~m4Kdp7Eh5zl`L!0`G<*{`R2U4a|FD48uu1|o46d<8CCh4c=09tZH@DgMsW(+oTW3aV~# zn4#tG>8ykIA~$i8N6tlZ?MQ3Lo#90yfB7=GX67nv;3f{;RiImpim!_5t!ZaF$T5Im z&K&0R&ExAiETwF1Ta1S%p?9mNWy}0Fl-cD>j1P-B3-_ZtvW~Q zSBz7$WE?YfJ`i)g*WLSU! zpzgxH2`mC%|CIDdcu`@RW}syYV`IvvQDlspWkvyH3GDcpB09nDaz%RH@@8x&z%ycU zlIT?1rR|RNk>#Aqg15g*gHxE#-0e|WJ&I=fL!5XMfaIqeXO~x7gcq*x6g&4TXA1-B z20K<1$#(e);>D-Y4{;_qmk`8yHohj zi({64B)a)cqrxwAZukUtP3!`a*Z-5*mzp0lq7-tFQmi%HFK=#Q%IS-mSAK$i8f|5G zq&NE?h0fFFKYgLDn_De^5_zAfDyW0G4cIu$kA@fl>wh;h{3xG45LB}{wzfy6y+~J! zVwFB+f8nyP+W(g()STH3G~P+YqRpjK*1sPSCM>rJd?)!a-dvk(RxNovd3_f@a2tV^ zKRif#6Ff*m7&z<#256`TRG6VRP?1B-wG2lFl><6%Mw0HEqf;XhZZ{#_6 zXbV`kP8xGmf*P;6o*KM@i9Bs*3CdMWB4BUlqf~E_J6ewY@KkMgc4Q`cHPV7!Hp>pW zH!HXkeFJDbhv-u6+Vxyri1WPZ+l(9MD3((DA?C6W}adwIE=}||7kPZ z!m|h<&p0W#dbyChxPV&c>)W7C1?xa$)-LTl!}gT?J8_u0kX>TQh38A3|1m=7|K>&d z5Tdnn4D-3RUa(*?nkP{@$e6piJCc4le>|5SsauSjb(WM|<{N$l?nxNut<6Jc5T+sB z;5b5C51GprRz}}9bjvdIFA^AET$HskAiuQJMvp`{eSM{R0Ge-x>tqE<_H~Q-bk^eJnBcf+odm|EKQiEgN}v(Dvxk}D3NvPbxh6eaJqxUqi<&67Q^j+&v0 zo}m~(HgLp&*P?{1<2I7aEK#H*=9pvTCoqpVJ;By#xc*F-)xLYr3FuXZ@{r zcnj1`1BpwpWFRw()9)nnlI`Pw8ZS9TrUJ{VXS*2j&zEN}LGsP)W^H@H3bK0?I{esn zFD5yC*)P1t^rPki$XqF3Ll$wEVR!xs{&SX0|?7Z1NyewK3-bXSy)_Z$7359CHP>FhmIb_?@SnRVqEwg?9F`(T?s1umI>RvL7*y z>IU%v@u_Fo1h4nYWs$LM5Zn4peEr&vw+JgF(un$pZSTvR6YgG-@?!KyBbgrYT`?JV zStr?h;)*EzsNA|11vfb(-S=p3+_qt_!f}y?1kq`D<|J4?CV~bzpl{ZiWR>(A>R9ko@6X{RVWx1 zn*Ct=W=-<`kXkEzfS+QcfMV*t^|PheJzITQTz`06zzbg{15NLHcEC^CSo24VOpd2f^p-1A5J5(?NC1YK>^!;X7wmX(^MBK)LpGej#zt zI!to8J%#>nc?*H?JZ%jSvU;oQyd&_{-A_e{ySg9c(Fyn@SS~p>6tr;?R4EbdX1~3J z+fFuGZt0t3rCDBbn|3_Li7UvXF>E8R_V|y`fV+r)Zd`A$g=>CEv>6tT7?SuU}O!d^UDKyi5Gae4b#E;=?s)kxqEI zoEPrAAZj4iFhwD`YEbx<#XNJ*{uuYSv_a!md*mc}$%R>{dr@)8n$Rw`?rc^TxfeQR z1fxm8`Hz0>z+X##z4ajFC@~|_rUtaeFdv>Qo*j<#X%}AQCI9%OWA4de9iBYEUH*4V zX~#V5OV?syRwb_@(G%B*88}CGygBg7BG;B}U!ev#bsQ?SWbkP~4x6Zq{x(ijx?YaEs~0E-pKzXBN8^6U|teh=MUlnt3Loq#1%Klu%QB zSV=XQcMaVYuIz|@_AvdJZSA*?knZMy`Gl5)E*szlM^1jf(CDmNlG6aP$LJYDB(I@qffBnYf?LBk z0tJa(Hc75H$4X(8!5+4cIRP&c?A;+gpq;+en+*E}INKMU;JP!%bNt}1>c{HG6DpBU zI}tEi^m>XlNBtv%Y>%_x2vkyck^2|pjW*DZjur~m)mSGHKhrhKzhP0=|Vol5o z=csGqebVARQmvF|M;7GQD(NtQO5AD*5`^<&;>3a!tMaDM^=U%xZ-EDo7%C?`YlM>nQ~cW#_IktI#endIYV$rym&h z>!1=5l9IWEadYd^(z=Ocf=doL4+0fgao-4&-{F@ES?3;ppJIohCtLzwG50K2Rxgi{ zJjyNjy+K2{#BF@@hj6SE()bc3nRh(Da9#T&g0!L+k486Doaa7#QD~57A+H`8igFK1 zZe~$CzIyhNI|gQVq|HykOpjD)x~7;*h}86zp96h^tiA&E1rIFCy}e54ciHA}o>)f} zV3k34r>}haXt~NorcMJ+IdVudiavY|A;qpYQj6&iB#u$_f^nhswG62S(jN5cBqa5N zmUEtf-w{mV*<9hU9lo{hn)iHWvPmTUQM|vu411uDVV#cU!l6outRa(G`1uiwxlTOt{N&3S9W|deoyWW z#?hHN@j`fs;)}_QMa>)S@5Gjw!2QZ6@wTtL#baatt5j?8-s~^nz)TvprJK6kjz)=h zYsP8<6>z>NJda0dw|`yZsuQ*K0G!o{XO7^S+49h7Sz<2dbW={Q32k*ppIaR?4Dc4H z=sAVB;i(V&<@?18S5^pQSG*5I4x7{c8E?tFeJ~_nYJ&Kl2MCbNe2Ch#GoLLmhr9oi%ySyZ7A++);EI3`V zjHLAw*75%<*kcm0kGjWRoVCr~H&c7I)B8Ka?^~{;9>Jq$%O7d$BM=CE zc`8W06Qgr{L$MaW2AoZ=FsoZ+IR}-|Q_=kzB=TggGnO)C8>#U>692bqt?s5Y;C6Kb zF?f&A6~F@ZOq78?{DY?0(TMaq9bAJBV`gNV-h61C4(m(jqSn#hxev;&%{`P^Q9e~D zGVIM-bBeO%uOc2$2$bcOuIP$*et~Q<*39E2jta1wX5LUHshz1Y{g(NloBKWycR)mE z_xOy2moOG`ww$>~yO)md!o&|vzi{4b&F9|0yjykOY&(9NbzRoqY)5u7zD#}M8ZYO$ zwt27Cp(Qv%n%=rvI&7}s7hIp0*U3lEINWUuOFs1&-Vqq4jY!2-x2iG`Cz2L&aUUVl zvKHl)39Fv?ek%es1Y)uSenIinS{90R93&#!$6kp?+UG%uZZkJ-TDouVMG|pXn=&8d zIiL|hOt1BUw=1I+QpFez#JGbkQ2)Y_@ZDyG{Q$m4;3QngrxQnciEJ$L@HjxgR!d2! zOtponp5-LCp_%DjsR=Ytb>w2&eV z=UDKRaAvanyy&2?;Dw4`$@G9vp~7;qSX{8`jW)13=R5<8r=@D^W!>2^m5W6ZYsK&| z1Y52yYcuoZu$FiQFH>?NpJ8I8-yj|C)39fWQ5+^sWYuc}{*?oaC%8&!wAaa#C{}xX zV^jTy@Aa-I_qIc*x@Yka;*oe1`rmV4y`_dF0f;x=gnEh#wXVXW66AdP-Qn_?sak#q z*j3XeV#YDhH-Av^^-yPX_FJ`3)L(%#q*BgCa2X-jih35l(s>njwQTqm26x)w2|cuC6M$ke7K4$)B47W{KITB%7wq$0d(u53h|e zp6<9uTuz*xiEx}5L>HdjGbF+J65w-Z&?+#)^QN2|*9bB~?B&8e!o4U8L3zb`_;N>&tEEe==5h zc9{OzucVNyr0Vi!LnvH;(=0US1>Pdct{ja%bB9Jq9mcTxj}V|+WETEwl8xjUbI=Dp z-NefUi~3#*t1+L6cS7G}z8{|1k+=5B4~Z9gvIksmRkv*5ic?1xWxo~p+8PPNd1V5e z(GHcfcoA3~dSKpmADV?dCO~%HYVrQ0+jWUk*R;Cb=$Wm!30)CQ9uBLEvuU@riLO23 zmy_pRXm@zNXGD1z$QxiND9NM)0@l4@{U|R}1F9z0?6AE}>#FIPyU^?-iSs8I2fj3o~{r+|z?OKiJKv|I~$8Pn;E7%#QZrlFW!3@*}tx zrbv9WoPGX%!5lUxV^L$C^XkpVorXvk+wEO+$j_YWW&tpDuEt!p4X3(Sr=72itoXL0mfSz^M$`YJPTx}liUs}SEf9OPDJj3 z`T}p!L=mN|#WtOZp&h&yCpTo3qI}@Dba{L>wh-)S6PpWv_TDsAr3R_o3W`~-QFg`0 z$nslA@G5}MFT%N2=$lYV*|c%lO2jtSIIxEBys|vBL&8`%Q`TQHeYctbf>+$wkv&pN znkXSS8I~I9oDzEj-|X=_KPrCQeY}fm@Vh#?@1Gt&{Q2bS|F-|R%kD(pZZ}@>ez={g z<>wi0IfVILT53++CbV3uJjkAJv}}Demwa^ax;}G5ii|DZL3Z!TtmaW6q@4o)8~z{f z*L4@&D`M|RYt_$zPq^XCPK38YW$4?lqr$Y}k{29>UZ@=M3vpzf^J?-@XedK0VwFX@ z8hubm_v<$o&km8!PvN3^NH1^v&9~WwDgz~z^#^2eBQ(v(CjdnYBSRS{2RM_#e{mv! zWl&=vf+%qid-m8Wdsl{LiF_(*S}0m1*{?m1#kzH7TsTiD;QY)VEEY?B_76zt)mgS^ zQoZ!6%dPj@ctLQKf0Ld)K5*cVk67AtslQ z1r|%HK{Wzwa0@Rb6H%Y8xH?*&2mIl7eTZS_pV1g$rVwY|&~>IcsV*p%Hhl=s_k(Tw zy|HY+xdLQ02Jww80q2f2ZT)V$%Bj;EV z%WKwo1DM#Tot1S+?a_%ZD-xdYNV6wh=@j9;bFB1F%G4Yp^2XLEg0b*i{*>4_%f|1m zgXM;QFUe%@rno#)BM2`K(nXSqND0Aw|o&YQ(|AtPz8JCa!o) zW(8SaCi-Q4XV_t1TR6^kZ&|Gjnfv-k6=lyvj7`U^9Cz~!#W2b*gVD08Ic;J4V9ipH zxY_)9A)M(11E5(KAbgV9{lauw48S%=Mym(N-&)lh+RSQQ2}*tHBfkJPOV& z%%=B3e}G@h!}dd^epM5unJrjqJT-Rv>dw5}EPJE7$;hbY2WxK)W8o*<5MrK8N&pTZ z)7wy-q;b_-?TC_y!8Ad_u_0BrGdGdeK2OlDxe056NK2AxXwrQ<+ zrhfP5jyXU9Bgdvoo>F(i;Pjg>r9K5O7u1Dw_Mq?R4Zxo}ZM*j@pTnJV_4wqE5RLIJ z?+VR=55*44DSwlEnhDl1Pas7-FE2zw13A?9PgtGLtu-KmjM46yif!{w;3q|)WH0G7 z0~MYJkZo&gCG5>8yTEI=tm9g^Y#UXTy80nfXUJ`>sXiIfU2M8F{)yQn?oLXiOBRS` zEvZIW!e2MD8Uz>cv#3zehFm)_TgdGLckoz`@K?Xb1y$48VuDexR3FniB!0~SvqtA4 z*DFTnpft#PSP@Q5yw<1vYYIbybQ-g41v$joE$Ku_i|ZQgRbHclGk7jv$WK86Qd6M} zpK|DFeoQY(MLWS8v<1ZWAG?+^_UEQ*c9KTUnF`Gt>y4vr-*CO$$CP8aFCH$IekM+GF0FYW2l&Nj z<({r8Pfae286@jiN51ayifS~HxnWRgjZiJvpo=*?1jVTn{R$QxzVOAf;NfskbBx^y zWMS3xQrbRhllAdNeTB>gA70>2#)$D>ITMm7)30zIP_#X-12G!?)?*s38(D7{mIddk zoUJ~Hy?VwnIlQ9qc`xfC)jMlLrEWbe;h6OE;lucK*~8$Y)0Md2T_x@v%ai8gc0&Fp z%<>pPc`LQc|F6Kl(c?ZpXW?%AdS}?c=Vtmb!7%vYf-%`ZE2HH<^}UFlKm(~t<)96x zwzFPOch<6bvHBgL!Zx|)Pc6nv3r>6`>;J-|;# z?f1p4d~Md>cn9w%Zr|$Z@d?(cjzo|&$N#7n34}4fP2ubE-$YO+q>k6~RJd(`<0P`06}GR$7H7 zTEtCAdd(Y>YgsIzx`j9Jf_nbf3FJKsD!ytb`hY<{f`+?U!qiylID^@h)NE~q?A6~q zla1P5oie+=!>vT=_4cTk!SGT>N5=+Noon8y`_wwO38gH|UF=MtzQaEvX3(uX^v!}K zB6H)2>?I#%(;$<=uTV}m|CRgnq{wuvssNR`!zf2S=9Z!?U*MrQDiFueY#vM{E(P$3S+C zARyWD4I3eItis&xCoq_O(SJgmQD_V2gQOf(Klb$pMuAMf=BW28S1W8c%j-5b5aS%f zZw9#)>&ZUIryB8&Oree}9Dq5hKVweCKYPGzqb!XEDYCq>tLaf-Q+MJ`fvr&&mDkU9 zf20n6AzKv z+@Od-Tb{d3Miry~V*b+guRG``>8B$TLRlhXrAOa;-96wY5S&QJYW8*E`}Aeo)&;6K-cpz1cRS?H zDf02tRVpo64S;HI631M^Fv$8X2{ra0Q-X?Fz`g1e)w* zc6Ki-er1|pc*cZ>1iDZRu{G`Qu#NDnjbnaJvpiL}(<3rQ1<5YT%GY*kgMI|&2bTrJ z(S7_hwH3NSxswel)LK~A%a0E*Q7P0b6#L-uhWaqNPPJ;yrM0+{(Q@eLOMYmVExO@% zcR|_+cBejLv%A~3QyfPu-oT^|aX5dOaTA*zJa{m&|2jNrEX?>ngGEcvl8>s;_HfR09E$0hl;gcojg+ZYPc7XQs@N z!hojYYxRtHO>Anhsn-kGGTSETs-B};lWjV8%9rZx~&kD5iOcD?Q@x>My{J+aH9 zY~|9YPTYlQ^P$ZZKZJ|($Pv*`VKQfk6b8pUvNi6?x}SBM;mq#dGtsyqyPXYY$#m)# zdbRLiNgc3b67WFgg(V-R4^Ltfo0Gggdl2p0lb>P)dg;KIBqsZTE&hmRNW9yz8&p&& zs}bWUPZo}_5p)LB{q$q7@S~6~u8!kLU;==b zw6hIT!nEW-j^6pA?yls>h;QLe5$GNI3#THfGx9rNcq=L{`9ZDr_oE@!<6c7JIyKgD z5Ve8(DrUJV``LSGeDmhv>>dA~2VZ@uhaO&)iCArZrMqLpyNpMTxgA%rrvEll?RL+^ z9dL3py9Dfj_w=du_$y5i;!6$Tn=8{!Mr{&5l1jM_SUNFB`Rs4@t#EFVQw;S)q)G?b ze~JCr*^nCTk?AaM#MT`y95fDmhsW9kTYRG4_B$(UW=EuIotB$;`gK#I@qb*lzPWu6 zO&lv?U6E+;61d`Tv_lBtN-T3_K@DkP%BTn739h*0I_3zd&8kN@BSeZABpp5C`aU&@c2%c={*# zmTosJ8`!|Q-2>m68z!+jwCpdn-nFi-QX-Cv*PJT&6Mfq_am=k}-8o35C!-T(-W7FE zYTb&-=PI_^GnDh7@y{}t?eeB@s0nn)+w_$leePoCsJy9W;eX|p?v7KQwcU+9vc4X1Im!Zfj4&0>=kNitA&1Uo^ccx-fVG#cL zRWZzfYR!&i%l_oyA!K?cfD-1}ieL3lo^Kd=Fv5IdrjkCZIm- z;aA?Qk@TsDe+r=EI%JxG3#OZ;urofV#~<)r-X43&=hEt|{_cw00vy4IgkyEGdys^0 zV|^6C+;yGN+y~(g z%D}_$&rw&k?yuFwa0)mXnks;9XN|hvwV8te?!{8s1#)2lpO*k?D-G-;$fxJ%_`rj^5xHwz|O)r4}~e96|Nu| z_mw9&IF$T^{R-($K4vdahEx(=f_b)k!_fP8ysB!pM7QGj^m-q3yod$K)lKweeyQ%k zo?n=OPh>-Vvr0D_xb~@{TZQlj2!_ac;4i6p&f<0$riZ5KzOF>$3(|bF-1nBBM7FJl zsg2_@*4o&k$jA|9F5EYFsC25-H<|&HK1@hcVHE^GDx-dY@C7axhIG5c%?15Mp!dFb z>rylVF=sG6Q;qSts1JP-bP4LBm74iT)}N_lz9pIBo9`0CM}jF-v90tY2$NRGr(Oy& z)>9rUpES!*{ux&ouBFd4;x+ z+Mt4Iwb)(cmyUvXF_B&8wznA5)wF2Y_@0+vb3^UzaOreLisf2oH-ZcNQ+uvFIw0F83xP0%Z&+rH@DH#!B@OvD7oam>n zEsd1>vw_YD7-GiDIM{x$rBs z1-==mm~*`h+QRx4KlKdbN&SXf8WRO)mB5O8X|I)!_Zc4{Vp2zZ7H>~<0HbY= z?`6apImbDENHNI|qyzUPt2K0v%|g!(+z(_^p7YXr5(&MpswjY}2#n5WHkX za>s`+*q~j$Mgr71SS?aZHFl19O+47UgHa@t{la5O0hOv_;J42`u8B)um7mb{J3>k+ ziuKCx!mnBsyisa}9V);vP(Nzv4qMw|e>LDW*s-~QzJ{jfC-Q6d&lM4HAFnS>`39Cg zbjW4mqd+~GaA0G{uh@Q|O?SQj7cdo-QP(QjG{$&-{p9fiqG z-cIaw)@Rb_aHAMJaAehK$`qC%8(36JfHZ#?@xl~=mjdS38z373hU@5iYrPwyaZ8De zQt+FXCfDCrNGGlsf-~0gdh&t)XlYwmt{8$%rlIjc? zP`NsnoFpu5fh&`_I?wAm`Ql2BZ!UjrDWJC#^a!H4Iu@R@)3)ipOI7EvjyYT;9t<-x~xGCrw2qL-S2M`R@upb7ZV)> zq&R8pB&)QW!6{TWTA7SRD%@Sdo}UsKKC!?*FN}$TDpmL7vnyPuFMpH-lrE1^89Na+ zE7g@4*_qvxj_uR+pUOA+ACZ@jc#)Q_n0DHezoXMnD1W(dD%rC3VwZb;s?tEKUR)JSMSy!(Nc1owNAnW`Qo^V*}jVn7hIbC|}?E;<@0ZhWnZKMc!OQ_Efk zskdJ0{@ac27q6rl9o(*uHfP0Fu_9E`w&E&$M6}9Di9_JOICTihd?xU=;am1ufXN0wNx;m9J4F~s<40|!gtHiEf^7q_IU+A zQ&}s~iLQ*yk*opaP#z6sHfS-O6I;i63oiLc`Bgo$d25Zi%d1m-muKR9E+8c8iV`UH zMWWc5QvDnD9;X3k&DwtZj?KaX{wPPFbMXgbeJD9Lf07s>3yyI>wg#h?QXV7x=1`bf zuiQ3!Q~4JL3Z-Eg=CT6L;;j;Ngn-)!c=4RlUTeyxu19F-X=~+&5mJA)T!DP1&!zqK zMyz%XS-2NnZ$RxAikjfe>+oX!yy;{RQz*Y|$oP2|=O}A(kQBhlJtB})_HCGtEEseO z{=p&9=c$^ipu6VtQR?kl= za2wWwPVFRBF*w$Wr^=l9k%od3SJ!x}0C{#~wE~P8ZO_Aug^f=!3ZKi|2iTcz?tLtq zA5%VR5;8BVy%i+k!h~f-{Cc>myse=n2GR)IpX@v}s2GD#_QHh)Kf~)hn6X2qVfc7Naw#20wcDQU)khUPBL>X(;CE8x z7FoJ(xwoM&?a9uss(KFmP~mXr8{Q!t9--ci8)#AQ1+QJBDWjcgqh9~?)+L(K`vRXr zG|J5%>|pf`C9-`+5&{Zg%sQ7WJyN|+^}Oa)=Vt=hLz7<#)k3aNUn1*#`gO2V_?++k z1t}I7nJIJcsWVB1ln^&xty$?>51BpI9N>lV)z8T;amWu(e)rV!mK^vK*|ieMzwfNd zQLA`D=cgQ}6teOvdxyU=NEh>QAmZXDsSBedv$X=aCat`ZLsGr@kU z#9ahv672oLt1Tc5s`Q3)N7kPsf9Fkv?p$GU5G)c`p?V585K`1SGZeRq>2$sRjN!YM zLpwuBysB#cq;#m;2tqpZpGs+%~+ZG_p0zIv3o`fykF&HA4rfv8s`J z1(Agn=S)6gZ}?O?pV){@^T0rYa)QK~t4wAM$CRt_G4X#fb^^}m>BOUrUJWW8<>LQF z7Z*pWu;}$D^%xy4VK=V%$|9Wx==(^WPdd%f!65NBl?+WCx zR$Hy&o;T*nq*ZhHuYO6~M<%j30yb-_x&$ttyxqy}$=5CBlBLe}EC%+k$IMbWsWsT; z6N+ornnyoN;5d$dA);|F%&<(mw75c^8>t^+8bp!zJ`8#+0l{czd68`G1Et4S*}O94`87;aYjb8 zVhnZw z8p*hA^g7#v$KH5rV370yz9P)}A+JNMsTCc_x_<&5HgP`@-^sW4){jKEt%&J~P~-`w z@fUMrurDfQoJy5#O%lYs&%8bDa_ctOsnk(5Cvm3(QZ&u4 zs*VtYj_SV^Y(cI5fm5_$#&%Ci=$ zS23S1z^-D@WnUJbhmhQpXM9Z!k;#+ceS$0-nopkiKY1%Js}VHgBX<$AdANN8vJSh9 zY0^sznn}_lO-)cn=)&qDA=v*UyVB4X$)CZeH=#{;^N#w#k0m}lkIGA(M}~*ZhM3L& z|BhnZS0Cq1mM{DHzZbMDtkyo-_&iKYS2{W6J2-R0e+Me^^_t_>!+NJX^zGQ<9@%yOjcymQ|E)t9eHWjA>FZsjen)%{u{KMUzkGXFMQnq=jc;6(MP(uX)TNfOlDM}lE5`s*l@kB>%Rg-9cbXym5b~(@z|ms zskDYBNAAd~wO>S$X9%MoYL=lI8X3rVkbMWRSDLsQYI^IJw=O_mF3c*$y>2~8W0#r0O&11@A_|H_YBemCz-fET~ep>ldXo{u+oCcb@9 zSLJV!x}0@5ASO9JCw}L&hVgp!llisM81NBwFfd;7)R>D&mOrQ7B@ay-sR6qV zN%;L&)N=nN_vo!D^V<+X{dLry{htgv7pbxC`$^hVT=o45f`;a{8w%IdAB3WcP|y zP)S|Bq1EI94cQ4t(XU@{1ewL)(yc>^NQY0L?5KC#R2R{E;{SwV3cQ}j&`8DDDiP4L>N#|zo8jG+ zn_iAf8^88jyI#k8&uDo!^9Aa9l`_Bgbf=+fT5<&WvFKVx(m-IALf`l!o2A@B*x)es zQz`6Z-eTMQ?cg+`I-4qohSDNSQ(ws$WwAhD<^(9z)Hs6;{0uOoT z=lMN6Gdw)6WHv96lK;&s3cvXhB3!tKatjKOKNgQ}l_>kGy<-MblwBbClEmk_a0G`r z)VYUDhW()!^Dx=NH%WY-iM93o{WDwcHi;sURCcQ0Ok;*Y?N9y$u&YwAy7!R_ezhap zeQA1*8NK_o&ppNeUP}6=T`Y@X;F+Qlx&?9p*(4m~vcMfsmHag{!XU60>KTEW&QHXn zrk)TsQpkmnT#nfJkuh=TiDMLOZ^d+U)d(}Gr+&e0jO_xJRL+)6b+qOok|a9@>m8Bk zOwZP;7ESiL6EQkiUF6%3vg#ql(_R5w^kOZQJRCzkL4wQW=hKnHW2Ev0daNusYpJjM zT|l)|rt>9LA4e8w^qA|zlGk5(bkcb=UsR}L@C6?}@HOWMZ#3h^GFpkaY4u;#KP7wt zd<};g8)S;D?Ce50=-t*iO!&^<)l57)f@;#AvlJq#k} z@`~jV4KI#pw$-wT-*LP?a_$&^Y-i|ye1B-_ThHzH|IKqANk@Di8x6PrmGTF1E^a-B zyLy!D^*DH5@;^HJJ{;)l@4b_hluc{{|DjG)u`C`$AW|Aq1Bf0#zdl8`C`^aBWvnkC z(3x|;hB!X^vV=U-W#8?%oFLG@{9jC+1yfvIv~54!wQ+|gNC?`vr)eZWa0~A4?gY|k z@ZiB6f(CaF1h?SOxVt;A?|W6RZq@k*yXx%PYmGSvyV=`21xlN6tX}XBP$SKSnJhX? zy~JxBxy$fBDRYQ}#R}%yJ394G3&%A)ph;)t96BQRX6dk|`_ly1d(=bfTie1dY&*yv zz(mA&+}b9*fMLXG{T|hTaOS~|h1C2CxOvKc^{ALZe1UV5J%HwKfKG4F=HyQgjkPc| z?#$i7X{2_UL7K&2AMu!)c2FVx8c~7gO`^LzGl-z#PF?zYbL0+Q>BTjp=uD#0QRNmk zKC^#WM4%*;&fLs$vvkCAXmF4jpj5q;${fp`LsIu;0|sV4M<@ zINB`Zvc~Syy1Y{V9pk+>!8R?5^@?7dP;D_07K8hhoPQ&t=wVj14}$RmKNfE4$A$XM zav0P65@;s6SgtN@onDen3g(lTippO_u?tz4Px8#SfsmoQYX}hb#YH+uHsbB?1e3j@ zx62+jO|o^qWd4S0e`AZ;I963$2R5S=0Bep3%^xjLwD)`MLcG$*VsI-=cG3??`d44* z`pMTYHgD4&?DP#9(~j_))D9EyPa{`x(fZ?^Pg5*jB%^`FSe5S}RgT}uBuWmb;T_*S zXBQiTvzHJ%pm_VAC-TzS;}&62RDGhMWR8GODNr|As$Ml7R%E)|*1i_NXYE-+yR{7i z<9$E>>x%EH4N@b_;HH5m_7Zdjo}vmBq>KJe+L*g0q@17f!UIm3^!7O zC*MJo;)6{f7ZF)pBJfu@pXq7XI@LG>A?eD0l>xE$U-c<;l`>PKcChAzZO`v#RSo)g zLq4E1;C!}9!8@BOCVC)9%r@y*Pg5aRp$i2yFv_EAIN0~ukr>36@8_DI9E?!o44pjL ziE0RJkBqKkjrj7At3|Jf{v9!@Iz4B6TiEzeXC&MXEr&*0sSO4{Fn>)IZID*dOaZz9BYHq;5sFf?*zzE?}!b{Rq;y!N}{N^T}_2L!4x} zPAV6lo!fui_zW{sEPQ}J2()PRG}e@OCf~CO9W&9b5PtRu&$%KR2vz7&#oRpHO9dI` z?ni$qUW5p0>ifnt|7TEm1mu=ppy;Gr_(#3B$9(&Q^UtWDf}Qmz1q;9N?@cnv&VEz6 z)}w}M$8UAR`jpvn>j(g@92alJ&|=xk9aL@0(a+76+cO>({5VbagV`CxlzB@6+glh) z${$7`0?11?GQx2)#M&UHC}llsI2!2E!KIu$>!jLLRAHqCbH?~^e4)geLO#o)=Irjy zO)r(l-bR~g0#H3AIAf)Vcb3tIM9AIfu-$wAX~Oz=%33w$nr}#xi!zEPzc@vdDdd0n zx5XHBy^0TIh|hA#k`ey6?%Ns^(LMSK&v4caCC0R{KAr6P#{7wH3QI*u#+@NQ^SXXv z(;d?XR)qW`u8tj%PBX9+lrT7Ae)RTedJ5B_pNlQS;K2I!(;4E+oQ6EhfnA_-B=_s! zFzUz(LQ3+0J;S;9S1}g+Q#ST2XmEWzjYE)9j-^Ai)~~H+8mI54-{Xaqzo(D!<9*~# zTW_YwcnK0audPZHwmDv(HS*ry#jg?7p*9__G@6zic|Ep*MqGp?n5zqbE9isbzL*kr zTG}o_8K6JxintCT0mFg(8u?RI?9-%FV82c`-fUyOeJRQ;rDD2$@PZJyiD!be_gYa- ztTDUvaM4y)F(=_sp#60dww1}SNTJXn$xf7ByG_1CDIa6bR6}F-rx>g7jNTF7N4hSo z1rV9@W5Lw7&%eH=<>5AH%QWD>*E>$HBTmHi|3}rp(V91=TXR3X`JB{|D~ZahYFO^O zO!4O%iL$Hkwnn0|8z-k(LJp0?=ON*-`TQ%mIp*f@nLAE_nwQJ5o7!0%xYT`yekZ}O zM`_!ka%p6Mhg9{AH6+WWDaykL|282zR7IrT3$kd4@|SOF*lQhLUSi$i2@>*Cb^%mL zYY-ArU08mrlM(OgOR>tlCh`jRmThEK)6%EnZb5s)Yz9of@buEiB%OH$vay?lbpYU1E9ANp*Zz2Ke6&@mL%P)(KkrkLeq#gaL;6B zX=-ijJ(U0AH4~Y*F-8!!;mi>)5mlM7_u;aU7G~yg_TLK~8Ui*c>jS0GLAJr~)9Lj5 z$y9>Aud}jm`1Smac1zHgn5tN348AHnWdkoUaF`94Jdi6OnZ~7Em#W*B6RjBxEWWy3 zKIlysmw2-Etgg4=sEIJHOooT5(L;cH?0*2B4s3my3B7ivcjO$a@WtLf0kg3veg+*x z_eHFMV#qEdRwn>F0=^^G(l>lio)WFx0m(nG1H!SLE*tbdMW08f!_&M4M_0Mj zL*sMOF+Reca{o1XvjFrQXJ0_>UZ@IQODPw3-`k3~DQ6Qtq%C-d!Q7kC1^!Idh-Bel zt@mkbg8PB}s!xEd>rdm`f5b(Lkv9i^<2L}!MhFN_pU?G$x~@$>%8`O9`E1)J+sKnc zt^~{}%N`UmETiop&JWiSRcyZ>$bDQsTt*)n(VZN|>t+CD!bJ?|PU5T9XM9gQme*>t z>1+!gmyg6Je0!V(nwtj)Xk762-NBxu#}9HM0o}tK(CS6;i?t1HvG8o_Q=?8fvLUU(x;BGc&YXv3G-4qQ$@CWiHhiXjo7 zkhYG+MLyw>%Zg15@oYGlpd;xFv;bylOyW$v@4jl9WW1-w$IhUkyG^Z20CU?&$EdkxA>5PolqdH2w5jZZ?H8Q6~kL>j7LaW9#gn+*bl0>v#vW3}I zWb?%e#B+}jZ%|c={c~r5hKTvNj076wX1x!{79SIXeV$#x@77>~6{KhToNv%reip(%s7I5uun{>r?*<78h~-B9tjX*p|KV znquH3(pT|G;<=l2^VE;##N!FFu)p2#o*TI`f) zg1is-ICCR-3Qb{^IDl`Sg|vjR6Wm^T4T`Kdf?UQG+`nUR`HC9Y+0hDVCJ&&vP0^oh z0wgoIDXhDC{Edw*#W}1q$p**xY#n2Ju*MMU$^S1Yd8~x4>>~nuex%A$>5D=q%yJDZ& zifk0G;edmh?u~|MBE6%oh|;RT^yqsd5N78yF?H4_`flgD+(e zYq5-p=G%lrv6Q4FybqTdMA36RtS5hcLba;cU@Vnls+P*5xHx`G?ezcTBUCOi&cw7t zmP+FEw-v=4$(=fluLfWiPmgi6b7{M0Tq3F|Vb_3?J|k{w9`0*0g!;jGg4(Y>d1jJX zeZNZNEgh7bc~ph)#n+;}@?OoJ3g6ItPUceE?*I43pgPJQ*6|kl>G<6#Er#PTUf0u1 zO3oWVPr~_iRpL#0<~r`MeP!GK&jF+iYv-BTS6r>7@0f2qi}eQhC(6sO-S7Kuzi3c* zC7a{&x0Mj`mxa3Bh{ce7fh2{n)^7dMO8OUsXUcx;{yc?&<9X|mg?;WSr5eY5mKLdZ zg!*`&Yj4mGU3i_vQmo29Dq=;L_~KO(JkFQ0Iu~PkLDIRzt-gRF5mG^)tt!s&?e?z~ z|KiRd6~jHyG)?eQV@Y7GX3AA$NhPyK%r;_w_vN`r2p@i&4Wx4F%K%87gB1K0)h_&K z65gaJCZXomH+aTsZzImlm}mL%D#W|Z^R6%<7Z8i)+D3mI7_0`_!}Gv#}9Xf5B-HofHZ`5|=H7ys?+-tz(UL7JUwbTO&Z3 zROcC=`r@jp(ry4fCtor8W^nX|{qy3oEz|#Kw%b~8Q{ct60kNPXdB$TOACmc zqyBT(uX6s0<%oIo%*9nokJh<$atS&_!#T_qh?{XYD@hBVzG_i@tTHksL&>`r)_P8hj2L$G8<54w9<;MiI zx!d4Pfvu2Awg!t?3eP|p?Sg+Hw3r@?HB{nL!;0x$#lO%Lb99tR=k~x0{sRSfTt@LX z*e>5WQD=}Uzt>l}=xTW$pfYQRE6&(OD;=;Lc_@Y*R^d()PFXNi(_)xG+kv+U_%gk@ zlSWmwo97hl2=Kw+hp83P>y21jEa7JyLXo-Mjo-#!zR)tY=7`S37^#Gli%irXNIE*9 zTg2T(vE%qlN12@Tx|6It%Gt5m-FUzJ^Z3^Q3lZMk3*GgbjrI}e)?T=WPCPscBR94V zBn<5&l#ROg(7*B(jE?4~X;aZ!Ynd$7W@4^MdrociM(W>HH1_<(Xi!c&mZQ&I;T~gK z6a%6bIo5I!g8zJ{^Rf8HEZoIKF@$k=ELh1b|AjkxDO!tCmEYaViQMs2M+uy*eK<1@ znco)>3tUj6v6|aU))G~V+0&G}{pv} zD(s^1Q_@%eBz~lKfJ3g-+W|sOE*OCh&+ z$?E()iSUti#Y)Fs8u~SD^BCF%^qMc+)8OMJrCg6R=t15U%_2KyH-0M z`X0v%XX9Ho*AwJgz&xgcN1xi)qR6JFFn$T{s4qbTo3VkkqIHvO$?HNbqIA5?XWseJ zMXXOF3n%tc(+fkf^Lgi;v*0NuyqGnZ>I;D`9TbX9YFmj8c238?6{JO{WMKqb>+tLT zZ8mQv!QiN!mFJLc?bIJo-(E7?!+u6d6_A)E@V5N~HQv8vUrRD+2cpVm6H_EO=6*^YNnY1jg%`ySFqDZ0cB0A49AxX0)& zayW%Yz`n)!!}XS;SYO+}8C%QTTEAqnF6@<;tS0~0v!LPsFHd2>ayuuWavGLTzkUREti_$hs+BmPYrL1xDRt!k6GI^qLI zLyrhOe^zry#(pi}1u}*=Yb(}qL&K5)o`Q6PG(K;^TP1+DiNHT&q$0O>)nzl?ErESI zuJjVr)qkVr60ZDs{iXx^2_%syC_hJsg%F`r){~_^%-8!%9j{6#^_^OE8+EK~bfJI! zzqJ1UyeonbVP;RE*{`-b6UvH%NUOUyFm8vpLiRttRU1!Tuc>e53tgR8ueaKjnG(A< zZEyF_7xMw=n4JZR1hlg9ExA_+Zdg5W6|F^ZFOd%;6ldXf=_3iS!C|sh#kHRui{6n- z+uBzq!}Ju;xooUZJVsY;E;6$@#Pn{3Yg!4O$$HSseGhN`K1aJZ@S9-YF1b->s0Pcg-uK3c zyqR}`jr$LgYM4vS!c-&VWu*Ncvu-jc>8|NzHyHD*zS}PoZ(&9e&-Gnr*Topqwe|`hIj<7jBOw`-A@q5 zZ$;RN)z98v0WOfv+VrR~x?>r9kCz!04GidwajLrL-f>b*zu@?BMDhcnm*46I5 z7&1SEpl|=k7e^Vruuk2m*rrchY-EWC><7YeDnF#raJxl(^LRv+m6ce*Z*xA;o2B_j z%!&VqV-XX9X&E}bw%$T_k-e1tQ8<&awI+U<-QW!f;UAi#=P$U4mf57NlCyN0dxV%A-RYW1~Ab&_0yT`p;0ME(;@C)f2s3Kg#tmP@QwlWu| z#Ogf~f8~e0u;n$AO0JV}h#2?Y!J)8+)yghgKCfKKbl0p0R9Ggn6F|Z-@Z)Pq}O*>?Q&1oK?a&(v&`& zRGW7s^bHtaX#VoeXvi6a+n8~OYLRzzaTIW3F;Iffy%#431$ZAK_C|L!SQoo1=kuto zyywq3j6(a2?R#n5m8-DAWI>91-L3jd>9YN2zYTC9y)Z%zc-T^37%}Ze$xiy29Lb0%lv(Tc(7wiuu zDf@R09|j`57n?@@7bWmkSvh$iQ8K5aH zd3&rqWG|q!PU`6OEaB)P(jS-d1&aWdz7DZ12+wLl&d?q4dO+?qjX3`V7-Cw8@-fy# zGPGJ%C5`Fywb`^jbSLB*F`Y5BDkI~ zp7PJC5fH`1G>i$lRY;c&#(u0~a6LeBM>@H%Q<@0+_VexQD(7p`?gC7{MOP zWzYOZa0txGE^}1)MOlpct)2N1njGP_;Y&87S7CAah*N>!Cg0o=6*DH@7Y9eC^L4FV zdL|-uv0*nUr)r4$#0irn(RBbdnf@Quqy6!QNccS3;@iG`VYi1FWR!cG~|l zfA1-47?+F1y}C89pcMhhg^JWU-70(aQe8 zal{c}D`P!}AcBQtUH1<12x#YmoEqfU?Oq#k3tx4-WsF9^)52a#CExgN|qw9q&*R*XS zLg1qHye(7bsMnuAV3GDbcmURfnxolUQ>Uag*Z#Ok)IJJ%R5ARu=b;884jh&&fW-)8OwOU z^Ump@GL8yq{O@Go_>eNIs;EMwDOjR^T&q>_hy4og*a}NQbA;R{t|m2 zHmF^SOnO-#J3CICkV@>uy)qk3c~#%vyj>YxX^e}u*)a;27G$UuZoW(GZ_c#_>5BJ? z*A9Or3jd|NkIzcPBmyF|cFd)NXu9*Q+(&p(@;XHvkb{7a)b#e&?~vy0F!+%1y9O1I ztdd*}Dhx-W3#?Qp_EB;;@A=i(Yg337%O0WBu}K4U4;MK#9e#a@UENEHY@}*1IUa@; z0}+;0=gN8qEG=S;WG>9e{z5Euhhyoo8KLBZ3yI%xClbj5ukZeMmN*D!pabuwM6fG= zheq8dwF~FS{kdfBc+6LbN8&Bp>9zW8FbD1F9OmGtY!GK)2fNwB16Twiwn>4_o7Q7Mn6eE2BT1AuD|4OmtxeM4AcZ>3bax1gD4=x>c?8u+{Nr~)>Y*DzveOikoS~py zZ$q}b;Ivwg7nrmQjC_4T(4^!IGa*4AE45u`I69R3HmLCD)(Br9Y?inL>sRBEu)Ti_ zx=O4@lgUDm(w9yq<%!vy;AWw3PlyJzIvlV>Pp5r{5nrGFfvE2S3zi6Oxmabi)+2WH zG(DCTRbQn%@*7ZpOBWH`1+zTaZM$c4b3&`|d#N{NAn&imwoXB%>-TJhFDML@QPp&K z(RbD72(2dHl4w$yMo;27=uF-Xp@O@6#iqvP0*b2u{S(y#kGeXWr0a3__kOMWs^t4C zq}z|tUIK#f4G{V%PHD-52z0_aGx9N#g?uHtkP^H^Pngg+fF^5)`GO?A@=cnG28VjO zTJR|(El_3(Sm}?{Y3d*9EW?W*z_1765Pm!*p!Tj&v$5%A(ul3HTZKe}<%ll^iV zBp+&{2o?!nfFCjUT3av)-AA$Po2Ug07)6wK0a;hpnTywyo4c~jtz0|FEgzsM-ApO2 z=3CgGot(1@YNfTT_pt54&wz%0#SbFjc7#anivcWX1k&TAfrQ;sN=<+?DM^?(Llv`U z_R9D+Iqn%@0mlbC<%&IG0pfb^STtE|gbhSNTk?apuPu_?^i9O@><9BbHHR=mG84$f zEAC3HGD~%ww=Ga9k|=|s{LXvXfV#O=jkDT1r4&2De3orf8yec;gCG8>kE{R8IED^Q z@w#=rk~HNecD185(SGXb&%ug=ep0b1Q4cZIV}*z8=2DY}r+OG{jb*{O~nZtTuoVHIK*i z6}o_po#rXXY|Uxk8XHBZj;H%k1iWAB@zEJNsiTYr=KR{Hs~jyumMkhD&zI6rutV%Y z3PGwwskfZvs8Gn;W*%NdzY4_{bs#a{+b;-i^W@I}fRAc*F~n=;*clEeep(bghAE>8 zGyJxQU=tr5a+Bs{Tch(HEJRTUetP$7^EdM%K={@@Yx60XRb<$Lo~R(M_t?)l-BBF4 zcHyj=`Jun6S5!5{Yj$17s>WG1mBgKOyL{!2;B#12GMS%e-`5%0!+}z}K56Ahkwlt< z&9A;J@8XF#_Q?I|WCk6U0Q}BZ@a@O|`|^a7&(n`TtIJ)=O@5)fFfMi+HkjE+Xfc*U z7KTk8aZv>hE#muJhhE)*u>W{WdKO-{t)8EQZc+H3k?(?@D0j)*$u?z#C1(2Fs%rYs z$5}qJ`s{i`SFsI|5xeOf*+jk^S0R$({NxPmUFcq## zqETWPe+$qu2i(LKmT>lL~u&7gDvrqyh2prAoQcvfP&>pn>3kR0pn>+;Va zxfJB8PMydnwm@9#HSS_=kz1=87m}imQyn@VIU*k#!@1pO5pd{h{U=LdYZ;L@1R}cGb z8+er@tf|RYb!*!X>B0fft1bp*tQ6|GxaJL97$-}0?swjn!KW9#-y6Oaq97yjypykW z^Ys?sOL%Djdl#BP?P+$yN!p$f0gl>g&vm30vtk_GJf+P=^&i#_g&i&;Q2KBV8J*rE>!Ge zteltZ542405an$x^sO*8Qt#GvMy`A8Ix7R7fs+VdNWH3i&zIg7PU{k8bd@<=&KSpQ zWY6szY`dPnU#BDbvNbv9RWTy%r{xW^onMJtsU=A&M1dXnbJ`1{CT-;BY2Azl=J;HS z%X^`-v>`z1z6Rvm6rj1lIYtbW_H{OpoM!HhF9BmQ_jfSFdTB6YKhf9`&mpTb9U@tL z=pRc>D(cIi?*T|D+u>;^-0c#Z_<#Ql%l&Y_DjU)cK4JDwztDJ(vnL>^op4S93iat3 zPA4*aJ8wEb-ykNz@j$W+iE9!J7JP5VUC*u~LO%|4Ri5uaoHzJBIQDIMb0j1z$JjMy zjc;|6N+)Z|hv_sBTp7Afq!H1Vs&i${KT6`yCEU_8ny`tZo8uzb?{uzWs6{*(yV!~PMY0dQ1#Hs=Lu)tJr_xE4XFr>|#Z3TyhN;AXge25Pm@`E;wynqj+^DuE+{>VxxTL=7mitJ0 z&wgIu=d?YnB?=z23|gC2xB_rA=_8UuM#6JK%W3?+^>pbmOL%%_^1{Hcg3rhe$PZvu z;6mihHPkw8MMyt@=`d_SIMZ7nv(N;~bQCWqEhndTCcO+JPry<9iH}d<5L24)WCpGA z38U*IcX_>++NC*k12rqhTCbpmI!k+Q3uytkVQk(cy%^8C1*RK_ozmnPmhZjs>vay- zDy>vKpUs$T5Ahw<3c2w{1kntpx^tL$cK?zMkzJLv%C-eZ$e7Vxi-Zy7vL5;(@AJTE zDQojp59k=`e2|PjP8@gE#B2sxG01X8v);(cQ%wg2LP;nvyTtO4u5EO?Z?VB8roI$; zJaOOHr-9GBF4EelG9v#g3br!&AmbRk^j@CvQ6^qdPT+$AgFU7cg&?&u)$mz*F*~1x z>T-0H6px_6#Z!}{mq!hg>>;8Sw46Edtn8G=CYdpT%Mi_Pl+^!@WS&o0s8&2sY9uc0 z#(Qsnx%)6yV?Ovg$u`=iyDdS%h4(YQRy(_fTN=^`TW+)AWW)MNGzvactWTpb78bMB8R1I78eya-%_jbA%=+A3b_I`!JXQN$6!Hg>Janj1%`Lsax?SSM}dNqQNtJu!MR*hFdJ=r+sy{#@f&OH4T2 z4j>S-g%Tv?b_I+2mk18JgwDwM!v~ulkh&_Wl35bx0vycvln4J6=!a zt8e~~yGGA_eRs64ertTgm;LU6`}OPr*}kn80)k!&m1wPu5sKT`bBLRWl^v!+ob|f+ zulSoz^x`uPut`YSFR4vb)-&f60+Gojy~C?6lP@uIL|+22eh@s`*#wRNe`m5Pvw5Vk z(wmGE3{(5y+#k$0pW*~QVh*WA87jjE0HFAKf)BaMq0_?W%mGttgqVp@dd~ z^1dR3GnnB#Xl17J*izmt+(k(+D%W-^|{Z=rh38 zNRL46S)IC$NSpG|8@19&Zd^1oQT`74Orn2!p100UU4{w*H6u+V8K-T#+b|j+dXn%CQydJuh+~Al!^laCD9^&Q zgvo?GOo^Qt^s9ijh7!FME;G3D9o)Z!2b^QdSjU@R70qQ_mqjaWUd!1U5gchLln z{v-b35d+A7{JF`Hq$?@fb5~KciLWEBcIg$pOlyQUItVJFn!3dh%oDtPpiUj}`#_xN zosTCcS22k6Ls7>^LBy!^3gH*b%;4K(?PKgE?~K;K5|qE^q^n=LphEB3we|KmX8kIn z4y3!)0I&yfwK8x2R+*>%fs>Y5<}X`AbB$HMD&+yKD@g+Un@Gc8tz4%_ExD`TBOYb( z&1+Pw0tRM21l8U#cO*IA-?$t@_2a7FZb`C7 z%O9Z$#}8>&a#^*$LSN02pDXHZEVE(L+gH2GH6Qhv-1UfLyWU9JtpWqhSM=#UOm*3W zIE{yG@u0k$%{v2LLD6xvKCjn)8m9!z+uwet=qXCjb#55sseaKRXzG(SA@j{-9XyCE zMoVeL4|5_=&8T#L<*QUALz(v~6`OQm3M&aMqhJb&nDp;{qO9l3$zDLqw!a?Yt^8eE!(jQ%lB(!RLgO{mvmucIfPm|WSBeU;Ih1H_rYM^>Y zFalCo%r6-wLt1)o;IM5I{NM8WzCz)!++J*dnzg-i89gEQ$i1V2yBIIpY8aW)?3LKm z8Cf`6rfA(9_Hwc#*JjP&hs~$-1%oXE$rtt)2l`f^rbq_N;C-i0IDT_ttk!#fY>go4 zbhbvpLmLY*r%!&e?4gYs&Sy0l>6#c1c%`iL;s*NzJc)YYURbM>EJvvARv>$u9fUDr zJ<>v_?T3hobP}ZB;_Kl2rKr34^|*BgK0kL|XNQ6C-h5JUi$(#_fVR}n-&ffrgo|a&XpZ`s_K< zEKzd+==A$+@Tf4>fTQsuS=rU6B#}=}LR6hP@ohXn$>NWkJMj(9Ovu?O*=@p1U(`RW zotK%m9OJG1CW)=1uD6m=h3yyk$V)5d(^Q(4bUVX%Ej4umIiCP8--lkc?o1$GpUoCy zG8svQ4rT)MgCBXX#zrSeSJ^1u-`BI&0a=V$V|-yL$GAQ)!2X(ys)0>nju=L z;Qgz=k2z(QU@pN7?VD!5g+1#%5i9D*vhwVKL{Y#U(o6LlTKoL~T$kW8w)G-mVIyG> zaW2)pf^p%6Eb#jgF^w9fkiWe&iUzz~w{_iz?}Z0l++76bZp29N4t9R>rn$P(`b#_6iyyV@FA&oS>V)1?AEdG@3S$JcM z97Z(nQNLu2NhbU3DOp7+j#WujV6aaY+|W!h6A8R3lCnVMcOlUfBeQ6177>a6Xj7^*UXkM)s`k5lz|sxA~`-G=FywrohtWWlj6n0)JiZ`2D~pmmStF53_KBk$4!+m(d{{*=hJU) zJ*IgicZo}NpLkA~l>Xfz^Agd7WEh=~!HGdzRrVm)Aag0^9-KnC<3CXYpZW1EYWfTR zha~>Oeh%zmO9t^t5KMc)8%mU7AwhIu#8_|Ctz@b}kQwT6;#rET2Mo>$@3Tp*|MK8T zckj?LG+|R;5Bky8$o{5Te};SL9a_I{{fX-8mU=-$L_PRdxWeHCCYKRm7)1B;=nOeC zwGz=8;-;^E8W*2^C!)}g5H;O6lDH+=M=9Tl_G(CI%}%tqk@e6fKQ)en{Vm@ek8Gs$i*u@=pCmJuFRS91?E)U48@ZVke|8YIHT?1fet5hbecCD7hR0o^FZ zuA<>6E#+hCBJnMAq?xFKbzJ5O&AD$SUu5?fHiS2?WO*I`=5etj9RfZ#3U*l-=PJk- zsgyyl`3!SR(lIQQd+;$ADaH_`(EE=F=6gf$^~E|hg{he2ZDJV7zsHO-Ps+mt2vacl5DDcwrOF@lR*Km!KeH9)GJ3;j&6aYA)R* zR|4+b8y69bVDEwZ!`N32x5tG9+URy+QD(aJ_Pk22E%Xr(inFO5LX`Lv#&Mg=<|x2GQ(U4v+Yo#*G^LY6i*FT?Gc+ivuguE{yqu{IA8UMsij=eel%NNX&xMoJ&&UxQxER<*KzDj&gFhT4f z3{3o_APLXTrzV{nQ`V1Hxc%8ZK%6@8~G#ER$dA6Sc7Cvv7#Oq*a9%R zSITuDxBI=I0f$>J@e)5e=aPH@CQjcM$!#dN$uohDpl_Kap{ibVM`@oyr!kI|DgUm4_>Afo zpXWyKTAylYi(sRHl%H(&HqT#fb0}NsWZ^U-cEF$-G%cDj*f~3r@Z8XQE?Y_{uacX0 zP#?)nTs4bsGhzXSaaU|Sct}yPrfT>@tfm-A^`w?{czOX?STGY^&zMKb_TAp7n?W8P zwA9||bm11rkWd)BK;CA=U)8z9wFdDtl78lzWFGXy8V^#K!O)Yj)r8({>zB@nODP{( z1ZlpXL>RW9?XUS{L!&=AvgI(b{e^%^EjS(_PV5<>gR=SIG}Zsc%kcdCC-W(692swy zLMa9{9;<@_OQmpX9-tOu#uo7zTPj~8oLS}bxrS#R&xUFXf?ao{DhW^ad+pIzMQgT7 zaz|YqaDFnho|%OG-o%&#qaiG+?@7$Zz*^X>6>M#dlWA#v1)vtQQN*V@G*a6`?0Slv zxmG^s{vGsix8U%GE^*V$G3g+-cdO^>2N~Ns#7&h!_4$@WK7zG+j>(BssWe)0c_!!m z0z-QJn+o{*zb~b?02x@_$@O`7PQ!uU(z8K)<@3}2YHU?kN#;DB>R)e~o~XZ>22K2PKF@>N&a?@{dLJXLWMT|E9-&woK> zHANR>@`}(1%Xj?G<^GgLkF6YrzbV#eet3bl3m9srR@hao zCY%Pb{u13!N3Y@P)x!-LerPe30fwmCH#XkZlR+*`#W)3A+suiB!9Vp z>`-|YrSOG~!fWWBQc>*o!7L9e8}1W-;j`uZ2r<0JH>Rt{dML-R!MU%Zv4AN1E;binfxE~pBLhBoQenLLt)btg49Vk z*TJ4Q65-DucS5Xk@iD@&MD zCpQcHFoMv?S!>ZV7bPL!?>>Yd2fYfh zD#jvkBk#&i%aO?c$*yF$?m6#nW}bx?tz8|DM?2-oln#`jFvL3HrN2O_)WGB`e72o3C9{@Z~(+|Hc4ljx0w;LZ3A5wk7^bs>kOjal! zARkHKINmp9ycVmE%?&gAKBVZz)X2#DkAex@hr;T3vi+1O6HL;HXm*&4 zhR1|Q<@G!~(FB|qi1g0cj#MmeQf9padaf>|mW&#Om`QS9wEHQSDe2dQ90NNC@Iscm zYuK^pfgJ7m-y>I7Qzji)$ic@h2T`u>a(>8E)(8^86wN?-`-Oe^!)P^R7+arn*-@0e zb=R?vueWKIU+3!?f67i2yz1xmJodnBb#D6orrQ$O(&q)MZEOAG&J>E~56#SL z0PUld)7b2J&6=(QEPN#uF+QTxtMHTxXIy!!hiI#vm3?M4JbzaJZ-R*IFqB*KEUR6< z3{G@xeqA=YIIK=Sc;FNqb*6rgcgPX+6E%y)+SGt>invkAdUn3Nflc(b_sWTvuxM-9gjtx6B`MI0>3jUNaZL*CojQzJlAb|vvvS<4a!E~ z&dsj%H+4ic>5tKFzK)Vof4o!neW_I)UkN5-+Q|D{rH7Ff-ls zz&p+$N42-`qX#*mx6oNy*r}eXE&J?mwUp=~NF}klBvbp5oDh7PGW!zk@$imym0r<( z8Qn)ZlQ}k4_YKv+w~&hUibjBGHoN9oF5PnXdA@m0FpFvPCi}F!pg~T6MT;~EuxL2V zyDs&y5$6oh7}#wc;U~=s=zOKAFkWVpUm)yr{iHQ3P;X0SRe_oHv-S}Gq{hZ_NabEG z0{CqN`OTlcdYXWd>%$q{XQJgFTQsRW2G4wBXgY7?9%36BE)HRV{ox48^sNyN#Nhn; zuXSLtx3Di_;@?t3#o4`s21g~SnL^t0JYx81BgO!pO@$Ur)lT%s_)Ph*^_A=;rDoBM zuvijOMu_{^JvaS7jyB)+!MTWC3~e@Sn$?x5f7s>Ds|Byb;&1Lk?n!`v(bPg6?{CNj zC?*YhGMs6h!Owg9t)?3&Qv31y+++9K+*b8k=>LbQvuuj1X}k7?yH0So5L^a_88kS- z-62?TcXwxS2<{Lx!QCOa1qkjMbZ~v=`SjjZ`v>g3tE;+KpKGmyU4pH3=GPa|?GZex zjb0e*s!8H5Z;IEgYsdgjm%T%tO_iajFX@5zqpw@gOknJ{$Wgo+Ab5&M&3T#2&X_J; zc7tolwhC659unK~uxH&c(g7mQ3<#9dZX?pD342vgL{csk=yP8Zi&TNQ#oxmT21Fi9 zEm}P-8jAr3NWO+zOAW+n3|x~yDMm>+!p%UF3=*V$Y*7ZrRpzLR-~!Fdx1n%+a+xt9 z`~fuUD9Nbba?Qen^J{)qgat-&l8jo^%A!)Ub1Xf=B&SLYA|%jO%78Gg>O?$| z>wvFb7Tz%j%9&65jLd4-Ot8X(!`IbyTGXZ>sIS&NrF~*1R;K72mLqWlnY?$IWrv@V zD8y>i0@?fHp_D$mTuXTG3ZSL7WfIG zYchGlKZ$b%cz0R;vTyzJ*A7Ndj@!)|$ho3)382S>H4efvne2`wk*&nxI&kvum?J#~ zDb!iJ7vz266y0u7`9+&6x$rB8`yf!_Ov1)Kae9!3`=5*p8+o9YOeGB5HFV)P1Fz0< zlWSgs<6qb& zpaqUc_LwotaFgJ5(3_ut~`{DQ(oA?Me416DY^2-llb(#5uevd(}d5z@G?uoLcd%lCryh3I_ zq*PCS6`y*BIVEQAtZSFJgv}*+DY-z>q65ff8|KU+Q}Rp=sOj}qw+5r;c2TSsqiEFZ zBr#Y>Yau)Uq@wXuD1t-@S%Q1>lr$=PDk*Z?ywn z2jjHxVE)W4Be^JzX-S%d6Y!fvZeZvZ6HJ8)S5L7{hYNJl$GgCJeMPZHCR)A-m=er6 zHlL2brZW2V@|99@((s<5+}mzNPQDs~Om z*~SfHG9Df7Gfw{~uinW&yoVe2nd~z>8H`OXAH`T7G}X_HQWTF#14mSl3>c9{AJ?nQ zZK%mmnly`8Ov@C(i`szv0ryPtO&|^bH>>FvRpIUCw!qzhH(iXDpy2KWVM_xf#|11y z+GWXF{yCBw^5fNot=D0D1=5ygxnT_4@(vswC*wZ@o4Y^rx_W_=GkOMxkU%W)$7=o_ z8B1+PWRsY@1*D~W<9@-!Rd|CHlf6E3oF?;hgAmKSY~?+J*@IqqhXAR^x~O$3==}w4440i-bAynyB%SLhlZ@yT5bbH#~1BYn-hN1P})V8>N&> z2e1eByg5CsZg-sZJh_BC{_j2|%Ku1dUw)V$kcZO)RpNh_T`K2i!|?9%Ox%3md=nR( z-c+2n<#+*bZU~^q48tUn2zgMZ-$K-llt*4BwHP zmRO<6I)Z?am1RdZivl>2&t6;>%$Y#J};9(|e?tDo9CN ziG#l2-9(cnBEmsKVwYwd1zl;qtWPS*FM07SN@^2Zd3M*4weuTPP@Q`_Ii=|)fH78m zpAd^|HNteJTAh?yHg}O0j}dGQ<-S{)SezRH${7!IFIBCZY0u$$sPH^xgu%i3T;E|Q zA(!YA#%!Li9Ru?HV-l-`If+qkm~OO#`euJa-(}-SqQhZOM`bVHqVS+gf^K&e^hIv= z;J;b8d|ux1%knM9uy$oVYys!iOYDxeh<2Gn-x4Eiq;8S9{~*C`zOk*?Y>Xi{Hyvcx zcluwwegE>=0(Q8M!qZRpMXd*aPy&kqF8_9 zZGS|*A) zW<1&d=q1ZxaKdvA%Il@wL81wETexGRMPjq!9P-?Dy{>~~Y|gEq5*xOZa~twK?{RPK zbqII%3=f5*0BZQsp;=nsSuBcCiXG3v4b)}^kELFWZ&(xRGW?jbUUJ`+Go*?b5^y$) zZ%6eQCHzfv;Wh6c?yyCD30G&*9qXUa48@PF@6&R~xISD)NJYA_(1=sOpS>vR*5T@k zBb46i7+ujAP4pXNQjrFDepExvuGk0E*ltPZFbDiQdX2W&wSL96szV*=kO`baFs82L2Ug$3D1))$fknv^5*i2bT^_?f zr~T-kUk0IY-%Z(&E|kNz6Bf~Jv{u%f%6K}4?g0u2EgePCR{kNoS9!-bbh7=CqXFPw zdea8VkMl-IgV>fyz&9QvA(f6;NsuT^g) zHa_6no>~Cv6*I;Oy`yy*8jA`J?+bhQKY8{hupa~PB!HM%L z7Wl5UJjxv)mA82OES zg=LFGB)x?UvZ4=hqs;QvfLd(UYmT~9o=&qI#H$g8ObKY+g>oT9+Df?PStAJ}t!&ZQ zF_l{had$^%vOC3Y)yX+X?74mxy17|pNzS)+?;nzG98*IVL`fcZvxzNm!>e*#CP!V5 z(oH-faV4NHa;JX|-@C`uPWWzYf4qtK{p#nrm3_gcJ0;!2cD&M^4CM;x>5{|I{5mjEY_;{ZGIDFol9xZaO+!8Lw9wdC62&ZcpBP;@m? zK`&%?73O)nn*j#Xi>nIasSlAVSV>{A`omm+1LX2(L2bgN?XQCrmResl+!3J_D@bPW zn3Jl!^*DKzA36y`?pe{5I4pO;{kN7NU;^UkG4k?_%yBeS$Xh`NY@!4qsBKSo= zSJ4J6zq)!V_;fMa2P!lIw!e*dxx-EJwUE$eL8>(ZV6;dNnPG!a_?4znizeL-N zg<{lBUetit>@PTUlk@3jt68`jO6%zYa@&SOT({^D4p6llVRaCUia4JB?|IiE^T#>MXcn=+Le+Z?zcsrtc z+@AdYSl;u(KArep3>#W;Q`|kLZ>pDVZuhsiJpfOMJC9S0tv3=3UrI z!N%WzW(!a9Wm8h~=u6UDT)?|k>Kk17)-v^Ya1*O_rR=1XE&b+f2>zY%uAfPkaI-3^ zb0~&P(Q{ZW9VP}+S0-@--g8hB>Oe%Zmj+R_MRhLftkVGUTEvz}AJzv zSEjP(W|4bI4S`{xgq)84%%9!C?IG(oN>NdBQ(rFbe)+=kdu^$}A{+X!@XR;%aacq; zPesWDSlAOTvP-YJ9>Q%nmoY%$kHR3+==XU&I2OXyCBdUUC2Hyr+jKABNqYvE>_V)) z5?6f>X?!QCdBFy~@yZXCiVj3(=yZ&P1GNw@jMe^xPGPRwRt#6s!QXV2jxi3thJ5NN zyHfna=yQ1aCe~YQK;yyXhBwq2+)j&>;|rgG>YJz_{Ot`pjUwPNtdxQmr5Xf_#V*IB zhA-kz^>hZwx|tq<@EtF~=FAJ7Lqlv%axu}+hhsZ?Q@0W}nS}f|K?Xmiy}{#SlysMZW~-e?RQvJN z#8wZfy|@SMxbI}l`X@dG!%-KQM2P7VLiuRBV*Gxe$p}R-0t^fFE7Z-swVGFv*C#}n z{BMr9@j}(Ev4<(I>dEVlN(am$r!agTdfV7F@B@~E!1K2R|436ZTEVJ|aX9hfC=#7C zZoy|yfFG1{2fF#RgdWvGLBc;*69xkmCPCh<$i_*X_nv{G)HcYTlSeX(22PJC zV<&>F(nROZZxJ?JC7R7k{4gtSIa#uz4wX$Qw4;Xw)Crq5^X*G8G16$ltN52o~ido|L;KYoyp~l7A39 z^jfwDJx=MLN<`KwMzW^#RM7B}cAt-OQk6HwvwC4_)*JKTamOK;3Ej$Gj&3b@EZVG( zVJ@`jLDZFu*2VQQw?T`EZm*+iC^^QnBHaI|Il?WthG#g}@zfb+qB<1k;i9+3(b%w# z3qb{XBQknbof5`5l zj>y;ot14Jzu{euJ`X}<5E(b{3PFv^pX}S>=LdqDjMx>VQfKR`L+Ru~ zac4|T?u!o36S0>AOw;=L#Ctpke>kGO5j~vKZFny1%T8SsQtCERLxU}GpMgx$W7ViJ z09+1Y`6*m@f%nJsF>?Gi`r0n5<@My+H>EF!J+y6E?A@ln(X!rxzO%$^cjAYbPX%`( z$K1H_`x-dKJxh_+W-T&?5Lu%^vS>aHg?$5+f%^AE&U*E~54!x(zr1JZgv+;$JST$yQPYQKKoQg`h* zL;6&@YzI|Zox%wWhYCc%*lZMCYJR|;21UTy%-I{I5lH+#)$L;|(i~_kfi!NW2Qiiv zO0rMq9o=~QLUrQwrX2LXo{=*B|HoZ#t0p&Hbv>+!7yJ&H4Sp92$M33OkU#Xi=SBHl zd~&nrlX8!^JIsMH-`(-VOU*j1Vp}q0bub_Jv8A$qb zu69t*@s@6RNP2zZP~>^cG*6~xZ?OZlO31FXY*OIq(h>Q+^mK4fovf4{AYQ(oN$Uz< zkS}}Tco2PK~3pIV%#liJ;BHG!rORE4_4`b2MV)^xkpZ~mV-sCFDt7552 zY^~pUA;2nzb=BYcN_-leMAhsynzIw@XKS_UcM2^d(($Hsqcn{r3y65k(qb0Uo4qc*qO zm!deffcU*ipfLSW>MojNmO)2OtBlva4LJE+s#&e1`XMBlnIK+-@l29N;6rfxOORHd zT;$&|5fEMSky)Eaz@*a-i<%GqMml+NP} zT)F^npV-eZkWVGcM-nt)1M-SPq~9|CtXWrf2jJH2XDS7 zvQdYzfB!JMBLQSigzcF3Y=+y#^y6*NGh;EGEthW^ci9Xz*3Of88m)@ciQJf6-1$wi zZImh0bDhMUUI~6lwddkV(zZsqA+*QdSe07Sv;o2#Fa1qtBi5(G8hU0}i$_X@$F9UC zN#3{P;>p%p>FkBq4$v_|JhCWF7wLXdI@RF&Q4cygbJuS&5z=v6RSOK)%-oF58zd!N zaRXS3&M5GWcV7u-(@g)#@>4K*%-Ewg49L^nv zjF{_KOf^T0rD+(NEo~@w{0QQA3x~ju(LZy%eVz$LZ|sa-x!AQ{0!D=V`yYoh9Y*2( z!>X{fhZVAIf&)4V|By6ECr6i(f2tL`QVfWI0_70;cz66Pv(Nj4?9MLl;_48l6M>L$ z=gTk^E}$CvRx|5C1^tO02?|41?sKO%q0;@u;NTm92nV%}(3E8l(;M$yIoh=GE@#Yn63I1Sd zZ!*6w#jlFWxpib+@j3qrEn`^*(FALjvIk-d7(B%kku-(W+<(eg3e_StX}re%gOo@M zHak-UTS#c+xJ``Q%i^ZHA~Bb_Jhn~Fev^2DOG(=*_yU`!SkI$qWpHuq4W;y>@3JUj zEW#wQvHEKmTTdxQ+Szww&JBs@l))c8zqY^k2wgwC1`l*(UDjF&ewsHel{IGzfl_eA zrQS`H0TxI!Ddu(mA||?mG__U?ve35HhD->N^#A&bcR5uJr>1RTQl<9!Qf5p9WPZ|k zNkVNhD5I`+IgQ6h*2Diaf+3}NpJ@~@eZn)3VBr_tEC%*3kPRok`u)ovu)JYM(o z>n7sz2dBiO#9le$yuNU2EhGcLP3Y&}%Tu3W4-d8iX;{I+5CdH@K*LHIMINaM#sI{lIeM{D<#aG+EoY|=M zLnidUyqrE_+2&*?kvh;U6A**ZwejG{%2amgQ(CD{NS@p}@=L@D{<6zoYr@1?^K2Mz z23M>0A_1nM?XVkL0>Ah`v33uz$|SBiuHHzTMQJC2-)Fxe$M>Fxnfnxl=ox-!}i50a{$GzO# z%GHrTc9QKAJXf?U?TqZywQc``(U?@LHE0Z!G9rfKKGnk1t;gh+qq5E9ahv;JKEWhl z9497rI-{ob3GYUVyt{AFYUKtE%@N{dnMQyoV=^RBVm)*W(aAgdhm1yIAKoCuD)1$g zu{DEeU|c%gSy{3-fVMemRJIo7WuvcMJYUoZoBbzz!VC%6?#i|oNhT#kAHzb(O#ITH zzELqNtU4n`Gd6+H;kcT%8r9^)`YGCygs8TFJj(g29H@pq4&X+Y7ghp*7tpman`!n! zH_e?Tw!!`sJ|iT-Jz<~pJky9&*k?e zrlyykM+e%hw`hkPzC!I@X0aw91EjB1eMYq8&Ms0?HflO668hM!UdkClW9@T#^f$&d z*?9QhfZ#WHhMDMrf5?ZMutL-nEkQ3X(YGj+U^h43Ym}TO-2`l1Z z3?u$@jbCF-w>EduLoYitN9bxYkMxDsEK@10)sK%e?}*oYY8Gpg7Ty+IWGJN*jCQpN zA8{Neo7jZJ+54%fsHSipKnom>xd(v}8!eqEvZ+)F=;L&Y5BUM~06VqzSak|Q_?8yh zX8W`Dd3F;5KgWW8pH;XhjOJe&>{7l1$8@>E)huuRb9lzc0fqV%OiYieIWhb?@y*7l zmV;IDPUH#t`_N*C98*~2jqXp>^9fMuE>UbyMMGisWmhi|yn&Fx{`T{%f9dR&6YsKy zw6JJ|p452A3c!Y-x~I4@6n%U*T1eaAcCe;gX)LTZBH6-PXRyI2?U? z;%dMji}qKt1;J~fE$F?@$yHtV@Q;SteAKS`*ZsPNc{+RDO7-c^3B~*X6!uNwVT0pg1hR6c^Pl#7klDC}ZT&8fK46|RROG~9 zc?5E~+p`#H=Yj7ky0)KwM4dn^bfb59OVKUke@+}h``d|4ca!#x`Rk4(TQgf(bH*=h zZ2!BOc#I+DUY)|r0F3Mcl=yY9W#1Jw5pIc94oDVShR+FB<{zAC$OXGkt zA;k=5N-WI+X=9LAu?6R0A@g`Dmwg3}0B=8^i4xPHFQ>WY&`8uHdaX-9K#|Z9zzbBL z!@LX(k({~&O_H2&?2JAdsu_@$eWw~*YGL&eC;|b!E$KtVk+Sne{Vc81b^Ne#SgtQr-?ECMk58)($5!a+`#541V zlF4S=J}a{9+k6&GSqF@_&)F7hn!`+W%(-kISTq>po)cDyK-!z)Yjv$>F`IXBk_A-A zbAKomSS;Qk^exuBdT$hy%Bd&L;G!>4zx}(zfQtVl>K)+CDoCbaji8bcQk_HDxcDRS zCrE&2>|c%~T&Lqi)O9hV?vWatqi<2fO{D&6Zjk8<|Cm~tD$Tir^mVd{Ba&JvFL@ElVJFmLIM$U}kDfUlEe+2JfsH&}8HKi-9Q7pnA%kWIR zLM?rjs!cTPvsm)YAWIe{tDj$!T@gc#2&?0g?pPJf0r{h+qqCnSblc>yI6y-m^gdFZ z>rx8Ojmu>BNIOdVQA7#u6iMzQY*;*<6L_Nw_#+2yiEPf7(lr1Sjjvx`=tQa;s{-#= zRsu_U9z|a`*6QB7uJ;>n{%7Aa20nom|4-iWF+bTxulKAj(owxX^*A}c|9!ur^78a5 zbU!a+d}gd z&_X)oVD6+P;2e(Zlb{G_PR+vSDfp^tH~b8*{bB~1rIP0?WWFCmajqVz=B{K_8#o2GQoDn{fE%;Ph(7QdX zV`RcE5>Wd2>QgC}Eq0MvGO4aQdXUscPXWA0PcOn%0$;ttg)SFqz(#5u4!we$&u(18 zrxL#)LTnGtuui56pXz7ex94c;jMT_qbj*M+wMmO9`u}YhRm9fNg+V^la?l?=lHB5P zaNvE3;s~>BeDV!>C#2gk6x*RF1egnI1ios!Q@vs(H^=BiD57 z{rqCUG(LE>tAAa{WmhY>I`IuyjdhE0?Nz{~?iW!rz=yE?l6QTV1?{8u&bbiCFKqEN zc$t!@#ldVC7#}<#j6vn)$jRgOC%jvNl)j_$BaR(Y2=cE)Mk~cc`ATGn9oJrA>tThp z7FQJy1BVG3!*PuZ;d6Nt)CVB-LT0&i5B>7JO;#bsqppK5+QizUF1=-GTIAp86i6>i z@y6v-DBhkD&QH*>NE&z2rN@pcqJO2r|JNNF=4!F}600yqkZ)xX}3az)WQtZy$GcasZD z2ddG6=|hBG>P?q#A3S}px7lnBWebZJKw8FIPvN}Nh;myXZzj}uYJjFzf7{mARx#7A z0nWv?%a`rmvPdWQ$r*pMc2U)!0qDhyrXVFo7$_H$dhB=?aC(f8Ni!0DX4$(M!>gPx zoZh6e9{dxG{{yeIcx7-02Xp&8IkOu0rFOP{=3A*KDCtqrENzsSR^5Fpeg{}^rXrjU5u18Ct&8tzUU{-eRvg?o**D}`y zvPrgZp(hjz*s(nv_b$f|nxIn9#>)W%09T9iCkTlt4Rc=3-yfc|moQglJ9RJ3Kb9aE z3INs!Y|kep3Yy8@QJLYqj& zdiWQ62g$WSCDCqLte#H0muBQQZA^~th;re^H^AZufJtzW=-~J6+Wx6&2>1313>i`4 zZx+bt_XLxn$#e3IDp!L#nXx;QPG6GPgP1H-+f`A!cQveB)a5m^T?I6$&Hq%;5=*4W z){q>+T?popVK6p#N#=%3H11rvnB5TkAh6Bi)JjTdlQR1-N&sOTByS5&52Kn=EKS}+ z*GvpgGl3k7%-2zFq8N~Vx+!TlUG6OTBU<0g2nOe(nih;se2Q1wggQNOkQ{;t3H|^b zNCZSdb6BEpkq<{ZiX5=ROg6^<1B zv`vI#v1WidwvMpmm*qR8Da~&eg@!aMIvpVYmLcD8nB-YX`x)#p5B&H3!P95Nulum^ z&h9nX=})11@N&wf3EYqPT1w8_y+)aJP?v_3kVf5ay#~Q;x5B?!qcKe&i`OvQa|w-_ ztp(F`P8$J36;BzRFTG*NsAZXM3!OVnYP%NBY+B)WVRrmdXcatqpR9Gcve@_jm=-KW zEGuebENEx6{|Kb69|#w7mFXPU+2EW2o=`E_l;zCUu< zoIBrzje%O(D#~l7QKJtW(AZ6c03BEh(btz5Q78s|j$cOk)TZN`gC6CRu&pruz%C*+ z$YH#V1Y&Lae`wwkYGP}=mKl<{ZN_**sL34s&|ONIzJHKb|ACp$8hoE5Y(+yhiZ=k& zvx1RrAt#_T;7(z>jKKr;Lh)1Fg^v!U7^5}L@<*`;l1ZbTYZ)JMdgYtIuzh(JIvUD) z4YYB2eahZ@**Jl^#%sz?#BetN_E)BK;DJnzr>r-Oa4Mg2ggQDB0i!LQ#LVLPFjbwZGqXQF%L z9}?H6VQgNS;jlTnpR@rO`8cc(wkz#hU51K%cX;lJi0=_)989M&Cyx}n=VaF+#?-Vf zy<=z`WJzT7{UQ_%cfo!E1!)P3*dJa&f4YOAQeZ!2sD6%@UY^bh0h{C16=Yx@AsI7+ z@CI>aegmV1rFvc_IrOLQ_7(raF2!dgrNp?>nNrX`PvLnsmv{R)b_(z@_0xGe@kgNx z>(eOvx=UkYfNWSKu#Hr5g|00~IRk5;Qqn<2`j|K(tsM*VG#D398oSJ-s{Q$Jf;F$P z%hC`tHjj{{ow<*ZzH`uQxGCB$MAhj^)=)?UVa0pxF8dRPZMRwH?a|EcGuES@G!DuH z39oj$(r^t@I>Ly1(S=VschYi!dRZgm39Z{ei&xgH3-z490zp|w3IYm_y-QfDnKtOJ zVe)Sa@3M!WBSoFf*)J$x1(Tbc-)#H_T~D82<|+wQt=uiv zB)3rK;p?hQ5vtZld2sz#nG5ZRSHj;|a1vgU$#h^uR=3Pu2{tTBG>~ESL>cBQ7XRi= z&g;a>RkR)B1RpiyjX`Dh6I7FJi_)kWzGeDeEtO@i;3( zePd8XLk=ZVyNO|h1kg}FXkJuE!RdG2#X0h{8wkP-Nw?x9X?`Gj`pvG-Rcw?drwf_4C7`+UjM!2dSJv<1$)|JkvZ5>IR5 zHBJS#HA?(J8-sY;Tl4N5L5P`RX->DHmdq9ZeU6%~KVaH7n+nHPgnO~N_C_LTB(ZJA zFy#}HLWD#x=j4YiFx9|+HK2-~QWa&KuNJH#$U*KjBn9Ci-;}2Q*^<8VC1F*xZRh+VVEVPkk6QFXchh)&*}U7dx^r#a^i)C@Tk-9yp{n6;shsIO24nVx zlYM8UF4Jxm`2nHr{qelI?o}6P&5pV_f10!CPAH?H`(Qw12_*ae0UyR>nC|K5?dpfq zj!RDCW$`~$1%e~_IikO`sYIwVX12x(o&rvc@mhR8G4gc;hMxW5Xm|nDK9kTY7hq9^ zw^QOSePZA0qWe?xm=ap3`pIWAQO}}Uy|&&6rx)pF=D4+F)`_3v@vrL`#Tvh3hWB#BjOnl3v^)4 zM#0yFC`Wkd@B#*L6-4+GW20$4@3@%2ruw*73??vbU?NPm&qEjB%cUF2<*MA%H87;_ z_Q-bolHQNE)I~oY^cw_yk!_%;AzOB+JFdfLW=z1*COa&DcVDA;cR9|>5d z)UEuOkxs>b_CnT6!~W#1^uBTY=GYBGVZA@yH>GPI#Z{K?6U=XxxfkNF|6&cK&IdP$ zyb(6B4b}xAZ8~zUs*goH-e8vlH64j_Ac@Kv#!(ICx?tP|KtJ*cLM`tiD=|v7JvD14 z8d&0nY{hT*FWp>^#Po&DBU?>v>kZnOPl%tAp7O*k=G*Ndk75xt;w0n}VX;Sg6|zV> z;8TDY`k+8ax)%on~-}& z1iQdrci5Rcz@HWD;NQJE|09j*^8CEOF5kTLN2 zJj!xF%V+1TrfWZ}4Ewemo+SAr+_@K9NVV?LeRPr(94us{D}G1XXuC0Pd|)j^vaGwP3YjY z!r~n~gClm`7{AJ-Du4kaDyWt!8mzh!%$x7*5SjAd99{>-BIT7hq`s%I7*z*knjQs; zihC%jc+2r#3C^9pPT;N~PZu>&vPp5)OT?@+tud@9Nsp?^NyM@4E>{X{Eh%}@Ry-YZ zdBIxOFnx?lB&dmR@>p;x!h-0KonFO_12z(mgi^{k3*BRv#TMxv&^%RKx)|aiUJhOq zDx?~p*Lc@I{#;a`nEst`M7}{Hjz7l@%}L@@2a`5lam!L&Tq^8hE@;tgs$K)x-$$J{ zepP2pi5BWQ<6l-Xp2KfzWZDgRh!*#pk_an%dyVMPZ3sqCC-Je`ihnDZRDqIMq0p~w zttIe?*`xSf9P??1okeik>Eu~W;Q+i}qZiTD0u$01)4PjnC=5@czmw&h;ZgqX{+Wsj zdvl;5V-9~Z4yMmuYv&=8x0{jk8%z5_3X$pSTX3Vm7e;Zu1mgVV_84_*!yP;2!I4A_ zBiy^qpT1DGNy~o?Mf+i1Bg7oi-b(rcWUh}21}nwTF_+HrBPSZ!C21Cb?R``(hJWBl zYjkR>xi!C+w^^J?PFH$B#)p(_?iXx^9nVqcxQ0P4d81V&4w6|dJcOM!Q9OG$!QYl}$x8*R zJ~&aBA1w#w{(ZleiOBG6{;uz^`46p|j(^w7D{=G!m%rdHojV_I)6`xX*tlq|InyR~ zBTHpENxVhz@ZUCdK3CYX=m5G`~VXe2jb5x939e(N0uCBMXM zYBY18kN8^nbQE_gPvi@Adj9hyqom3g$R*MusOCwII(9!_E*weee}pyDV$x8wk?0RboRQIb(EVR%X=PZ9lqkDwQr$K3?fO~b7ybz5n%Ge03BcLfZ=!nTwJJV3(%h}C1J?=SpXRZaD-nj83XehdS)Y}SoG{&~7V zJJgM$|& z20j)$El*49M2Ndw-Vv#AH^(;wq(03e{^4&IbxCk0clo@d%?Z2jM<^ZJTFMJc#1F^6 z!WP~ELFkh`CXg5?+)ET2Reg2^`r2tM_fT6}=u+xJ z*(x0u9x)wocn;D@+)}oA%F5BiW{>!XfJL2_ND=YU?Ec| zFlN!?mDI|uVkw7qR+9u;D^;!+_DL7 z?hH^~tnMGmgDeqBDLB!2nQ82~#*dyPu{|9A`!DD}IVo|Cpo_aGVDdZ3ijfg>^%EWp z(g88}I4Z%OFg-+d!Iso%|+IMbW7WC z6PD0xdehf$rvk94@*#;X`U+X?)PqY|D<0G{V*r|JLwac}n4GV>X|*_#=(aIm8yHNP z$4O~Jsn;gv#;VmxZv6x^Rmc^Ukx8sINX=x+*+`~|IYB<)Gt{<9mMt>!Xlcc!+DIo% zw_cGpKulRD#>dn|^jP#RNbLL4r6;4SUMncf83lzZbN8OzptW0bXW4nbxN$MN*5bZVvl? z^c#O{Rk;Tsc@Pne1`n9bBkB6#MN5Zg;=S)^4@ZrSMBd@w92%nhlx98)pUZLkg`E( z7JvWPCkhu{ZmH7Nv<+dk)`Ltk=T^I{&yHTb^hRny+Y%jEZ($G}*J3DMPafBW(-(-! z(UUfexrSJMT6s)aWzg&l3zxENunACcbGPp!^Q7dLOTW(#gb z>IarHQOhV&N2B}M`_xAMjb5{bjmL84j}_ni6GAPJ@5LkZka8PO+!9d|p9X?UELSlt zD;DzKE8-p6ah)s{-yao8!%8Mx6NoIm0v8=O`u*hzf!4;!hYp>g96LLOW(L_1=I?Bw zS=%d3vGJ}`Pm3?ZoP&$VMGXi3i*fEA5~6-~ODGqTHx^!zo8ev*mZ! zlJ2Au6J(o^R%UaxAgkAluOZn-Xe}xT0T*wro-cZoc|T*ieaO*&j41;0=Br$_?t_>n z6cs*V87CP;w3Y^P{R$+^3S8mpqVj%mw`|{R$YGz@eY&@b3!RSo7rh>ITJU{?E1%4Y zz=129ue=3{&Km$`9)nt%6+MY$o}yc0oK5dq?*m<|cJ$ai*t^f#JRAueTI{uUt zHQ4kmu3VSq5sLw3(DB&eLrX`2^G9tuZ_Z{IfCJy{JX)fZx3FQWG09dM_e-n_a0~u> zZn2i+4sVwz#G=RqmBd-X5MI_IJ2l{xlL)mNZ?XcbdQyr^w=tC1X_9L)zTO@2P#jrN zW?{-&ZkaoYKiXb2X$Q-~2$hD8#tFuaBPID-h7&?bNG@tYviYkkd;sdm^h8E^8(iiY zrGCU*OIguSa4z!`DaSAVK)$IZQX-K}1K<7Y zjJVvf@Avg(OKQ=kp2xdU9ylpOX5(e#{jjdOw8#3`GXP>Z+U8Y&-UjL+TQQ<=4kcSd(&LmLrj`IdwOmz{7>Y`r(YE(>ZMSS?Y zzZA#t;|sOEfz-azgdvxQjq58SoJ@c15nqj(w(_&paitecIq*$)>Ti=6nqQG3@-^Em z%(yq`X_cs1;Zfw@*MdhkEVmAvAd8>CKZDg@3=?eU&{}Mgpkv^%kLoj zJQ#PtDvC#O)4WjTfQ(++&zS215aQsXW#|P#tUv7fIqHhBUgv& zjsO>85K1-!b!@n%Y>}IxigJjpk}TO?r9@jQ5T%~SP{bAxompd(P(Io)eUh5T%lC-V zJc9G?{g?OQ{R5Lc2ARZ!T?CebM`l1lZeP1BD#Axbr)gZ@{Bjd$z=;|foM0j2Ir_~Q}Y zGi2=Bf7n+fMX4rgw!kUV$>OaH*fl5#qA+_6HTc%9%{1ivM%-ev|- zlWy%Tt}5&4JcBcEaB%mOw&?_R$Xdb1BCr9HX;+|wFL1BO zvGY=~|1c(ghgxBzrHr`agvL-5{*UkP(fv^z`0 z!!pPtEJ0F~o_l0tCvydbvLZI$tOq+a4Nc2ehF^Kf{OrHRk&yj=0QEo$zaK!1t_!$B zUF9%V$?qC|zNeN)au-Pn93J8U=i!nk%JPWGh=xGqLh3rYuV1m*y})-1m!~JR`w4y< z=;}l{e;`j2QIvc+(^{o_evK5 z2wR5zGpwEP=8<^M_(3^N4+MANrhZ9(_?p5@Ti(EY#>Llcx@&S#s#Nmj5$YK!k8}!@ zhAvOIX|;KVt>KFxAyV~`GARQmb}16QC;N_VS16i^B9tW)2V=W?h0Yy4_jDatt8{51 z`D^yQV4BIfquPeSg>{R$HOxk`9hs{Uq+i)*-Im@@$ha_v5wo6(5WA5=28+1 za$%WHpYRJkb!u2Bgs>-e3uX&*KG7-&36{!yzNcy-UV}}I%7A0xVVSAyklk~(uV{jng!Z1YJYdZT$s?{YUldhVQI->$8r}yifLOm8 zWNiW*wKZA+=Y@W=ikfV79pSxDt6&Pj3~}q9Yg5cQLNCw^6^A(?I1mx4U9aq7F}x_w zWm**s`^0iH#Dv<`bwTf;Rl~>i`!Knomh~BKsyKw;Ax{nK9%0Fp`LxQJ!gJE_j3j4b zI5PZnL%ivE`u!vBeqiwn)Tmyg40IR#(Z3v zu}O^57Md9nI&Ovod3T`I5$_bn8P$l+j(9cF-v;(CuGoBiq2w8MTS8i`(_J*Y?y%{| z;upjVX5a!V_b;!Xg<7q6?{HzQV7s7bS%XvO99kVq6_OWX$biS_=(7^%qoOAtKTt{!G(}mJKywS=J34$pqXZmVy5SaE9+@s5 zndT7@m@b0bLI_51Krk8=CjkkC<{i>JVur{AE7Hf|lSA8r4{p5(3<)c6$|p*m7&Zfa z7*-ih2w;uV{YS#%M_j9%p6$5$VnZ5wuCD)t`ShO4`~wsRu}8Ad=@U&9wShgn!$83@L_{jWpOeJsoGX4WmzGs;)dC&VpS!@Cc3<%pDydGi&rU!Z=6 zv8U?|8%|h`2!{9b%E<|VB!ZJIE(CN@mTrspF9^$-8t#zl!93&#++b)}@VyZms1-ym zz%vBJ#fGLmK5p5j2`e8~xk@--vQU=)iV!?WBCflpaD{Opba%Ki(w#FoblCnS&dqrL zb4q(!A3!lgA{)1X&7WfS1JR$UT;s!ApivB5y2iXuvI9KTCvbOIy~g*?kT6omx6B`Y zOMm@8LAn>9Yh4+ek#LKNLt+JS48yl*`&7U4721*7l(_qfrhAMT(}ItJ_diE~xhURw zy2H23c|>)_JHfdV!?puDnl88y2)4)JnDP}q?MdAhu`RV;$YqCFM{5n|49w83V#@)q zYt7CLVD3379k4b)Yb%$~ceFNPdXJPs@dteTW3V4FJEPXq+DywCr=G@-c=sCh1M~5T z);=QPYkZeh4rSVr{59r3;^Q~e><~8r6SNM~fa6TQe1}#ebhli_J3N_ECnn7-ddGa+ z5%LAsj#xV2;sf5lq&maNPiRz@PyO; zu%h^G!L@hD#X~W|m8VrWy*;DlM6u`iX5@zloF&GS(5hj6#N0?(luPy;f>Kzp6o`3b z$$LtB&(PnZ4Ti%&xZWdKXqQZzCM5JUo53D2d4Y8uUIoh_al^)WN;j}v0?lvNu+ld+ zn+@G&K--bdT`2j4mB6A``1%n?M|~>n_BXVcu=0^4fhF!KA%kw{ON8c`(;n3kFBusd zbDN3XYC-kx8B6P!mu|Ij+Jg53E?qHPMbgy{_u+}l`NG(GE*BUM6)hK9JkafL>D)&c zBDNSc7B;&`<`toTL2wVWdS*P`b3Qs!pHaPqwj*&QM2C-Gu;0BR^*zho_skc?c_qZ2 z;i?d}ugKFxD`$NFiurWM<-0SfJW*%iI5+yP;X1*RQhTMdEiO2=vBP!OFx_)HO$Z6` znc+HOZNW@I1NmJgAKycqsq=+5fBSd5cyYnq42*A%XLGLvVyLvn(e>3)$^~fYuXB zJ)tJ3uE9?idusNWJ+4Oiv_YCD1|h^q8V+pw8>Ako{)w!GE^IMdH_@DVLI`L*(uqf{ zVsb-MMRj869B`mHBX~g#LQLy%E_8SS$3Qh>(Fv&&b9tmS`&2cbsO<{jj7q`sLM{hd z8-Yp)k>)Gdd#0yK849W$R%b*rm-j+!!cl~%mD&sq9)CJ9nc_B){_2Vse|qNnkKVC= zIS_WQxw_ip{TX$YI{ygzgqD%g8a0oYWz5_v>aez!CdJ`{;iI8vs9KRM#8j~8KJgNT zWD$|PZobWc3Be19qVzZqCIvIYxklq(1&M|jnDvM_#1(332ukQrY_4xvj`z${CdE%u z3WHXli*4QH6afTNWm$|QLUck*Pc#MBGTK(Qs%k+*vB{%Fm`bMa8xqcpyu_1}a zvWA_CGKI$WHnEQbtrkiP4hh2V{iP(|eXNP|F4<%ew9L|^(}`KOnDscP zw06Of$;H-Z@Dty!ltNR7ca9JYv5736=ywF0nAC%JEIE++$kl$w&|M*$MCTWd$IQc6 zsnZ2x1c^{LxCDcb>z4Pau((G8igXov$NRMB)gSzv&Gk>Xp8k~jc0p_;ESc(in!7^n z0m>8OIni}{f)lEpsPhHk=FhR)|Fzxgzc07$vk>HS0Qh-6&*%9(pXa|1`979!X}VwD zPdNWOEc$Pk%j3USr;#`R(f{E~E8#EZrz}+;4kC$K9pm_cdHN139nl8D`FBk69ZUEE zJJ0Cm9Zecu{*acz)rRSrI9yYvN3t4j)8QmjrtgSnhs#Q94>+&X+?dNuUe5TEaUp>I zUkTgi;P=dnV>$Qaa>4w8w0{X4X-kh^j%2yeg2&lHPG_oZaT`yQyngt&oUyj2YQ_3hDJmqtL!W+!?H>q92wR79-_U9z%X^$}BoWGdA`TTzUm;l#PHVlw zBCWqB;Ba~-Fd_X8*Ba@%V`+^J2eyHs$JY$CVX{HJBEtsr4|L)0P5S-0eyIXInXGeE<@o6IsS{=}` zLE2lw_CRwJp5GwhiYC_}hT4M7N1RW%G$CAL?E}~ul|3RJN5SJs@`UPX6-4MA!6uX$ zlT7cfaNz*`SGZnTrVBb<@Ppvo7q}3puF^t8YL5>N$%0y;)Q?23_%0!Bv+{#%2UZb2 z;`z9-65PVO^It)msBHl!4E=_ZN5l`*#bITpwH>%e#^b+4+Yuk1 zA@LqZ@j1}k_gw6Zg{ze>={A^N zsM86rj#?rEsJ)!ip5(smplnvJr zXuuRP*AuplW*x5ka~8eedqZ4d{_sntIpM}kl!k~<+L35R7EfCyss=jwiY09*#o@HD z-4#NAL#quPe*nLsD3p_Np5CC0WSt3e#C6x?>{uMs4^JRaO2hk+A?;~-kBL$2fnaOZ z*ZD2Ejr3wT8xbD~ox@HSf=eJC^-$UtFEjlCc3=Js?{}QX_fQJx6VfeM=#aXQxZwJ4 z7`8p8Go^b;{OTj&uA|#*@$w2M&l%tR7NkSV!o&$L9=8aWdV)ByH{tvy;awshFXS0& z_(*xI>$a2$`S^hI!v5JU$G1oB9zL?^ludWdW;4@tVwn$!M*3kx+V!~o!2YXmKm+IB zIpp}axH_Y1Oi%A1zhyd(EXR>qD&8i7RKi@C@85Aej`$?B^UTrisMAbWzzDcn2_(!C zT{9d3TqKG|wgXirdbjc^)kT8508w1LkgTK3nV1Zt$ECt1zM$!h=}gtYuzP{Fds^6l zUK7$SF?=A;>&CP_oUvg@wrP~I&XV>)oE$tFGX-}OOvK>icoQ@SF zGwdTx_jtEZ$}_?y;>raV3zB;BoQYm2>S%dH-4SOyM2u-V;)AD74Q+~qMso|Q9+^I% zHIrjQ^vpD8rqj$ObVz3~?4Wsq&NRt*m)1>mztG5(VzeSmR`C(i7E1P%>Zq-WMPxx3Q5RNrp!2Ix$?=Jg1~|8x)WzsJs0fw~w2-Iu_r!y>m31eb!u(7bDUe)4VYBfnk?O zn}*khhJl_3BoH&}UjZz?X4Rvl6mzW~) zE1Y{qxn$6hv3$ucJtv?30a<=R+6eRG-!LBk8Rl+Sj_+BfBdrYtzahqjd1_c&Ex@G| zSYtuXOJqwyr+X~DLY_@*jvqLm9ZySIn;}EQ^;^_T39b8gW|hDZV_t1IqBh$n68m=t(IMLr1NTTuy)UPtue8hrmDmeA@dQ0Dhj& z^Lakc|9^#ilWpzc!_VjYf63+U_ip$4-~J~pho9*3JGuYWKmB)2+$*a}ofU0UTE?l@ z<&MkUFV{`E_!`%bgm4A2#qtqrdxC4s$M+1Pg#91WwMum#nPhD1F`{=kxmvde^hA_9Vt{dg(hSZ& zU~VJ>oZcg$phLyuNcMnE4Hp)y+fipnHjl|GngW)wl4E;u# z<9NEm=SmC!EK`1OKcR}@*cAhn>rr-hDeV9niopGpz?@QPvJy&eZ(h0B@y}q zPBxgHnCT!ld_Ds`o5Ez|lZST+oOkE9z~KI6%xJmGddY+j?q z5c?gmyC(Nvk>V5H1=@K-urnejoNLr=B*dSRy8kK5+X>`b*2q%B@=asCSG1C|=3KStsRJQD23 z6{HA~MkQ5&R&R=UF|{v{ zc0}EREr~h`;cAPy2bvnKt+rK3uZVJ@)IGKS8l*>S#M_9A4h^rM3Dggi{Difi;AAF9 zB3;`#UN;|?g4RdGe?_Y^)0m0w4sAwC9c`>k=R)clvD{Hxhs+L3 z9%-4PPw2ET-CxkSBgGBoDpM`EZotNoTxW((NPbI+6N@vl&p4kECR)3p3xPTbY%5o< zV7gnk{mu_ccNr++h6GhJq-4)CEfz)qs7}|QE;Bm}4(>YHKMlB~?tu)=!hAndS74%!u zG|_Gs+;~AuQM(}S3?|GE?}*_R=`(dHv?kPgVe4n+YosXD!YE^7L(ff)mSB$3#mj^=cv3KuydiNtAe|QJn6YB=46L$VRO^l^% zR-dkbc3V;s~1{(pv;LV zGkM9>x}X{{ALw__p$)`foEO8E2g-DTI8aLjKj5sRwF}-Ne!Qb#9Ab`E3=G79 zbKoRk3QbvqJAs-FN5%UAm4GCr6-Np}ZZPa$(shNWyL&`VSa8qBoVx2%=xozW;&C!yU82u8(*EtrJqWqpyZL9;u}e)M%ln+RW~- zA)8W4g`|j%Ol?H=!tTq!_Vo^FM_MiT2>mvZx=0uf1o;LRXIlMdNXuB=pgz+|!8sxJ ztecUh)FrIju)})!Vx~j`5iqL&#Lj4{)J1X05!?>aD?~h|KX9G{o9%0cs~0S%Yg~Me zws(~I9n0g1c{)+Dt-Q*b$yE>n-g^YWm_M1F0cofyu*duj&LSd(<|l?ekavya(U`nHcTa3KJ;P4k>mY4h7Y$0iQVp+a=vAj1a5fB888{2Ty&p3n1nKF|MehJ25G2)48Nw5DQ@lPWkZ8+yG-ho3j4phGa1RLi{5O!_5Z$-5 z=02HoBh4Mi;&4?w2Yj^+YnPY}cNi33s|Nax=$mABY;sny z<~DTg2|cg3=eUZ6NAS;~3R*pSz6Z_J^Ojr+=`dieP)%uBa74siU{MO5R!8yzE)2M$ zg#2rQO(Z`PoFH;b7Kd`Auflw}r%P81?gc&^u=F$Z@?R3lOm%@-6QMm4X(V}ulP6^R zHMpNZ`88J0bP`#lhpVp%Y*7*NW+df=8zRzIWZUD*2s&e((GOqX+(28tN8C(Y!9!SZ zXm_ABhuN9XrB7_OEq?P8QhY%fe~IN^;`}d&+iy@C$#zF?k1$Yccd<%`G9PmljVxQ1CAr$>HU{fop4gY zMiy1@S2(sv+92I6K7EN0@#hbSyg|c)=m(^J#ODRuy~d|2nhL59L>D2x#OxiK63Rf3 z4Y0#48SPoc76N&3g#L;U25P+!BFM0#Ha=CnPM8=&|F41DqIE&+3zjxPam2ph{07y! zG9TTS%$JXpCiJ^oHmNet*VMYBwvVJ}h>M7w&>BD4t6$)|XJ~ywbi_pI2EheEbzxpI zAsled*lYsG9@VRL8=$O}pE7?>vllcfv^#RSptIuXDY+7gplxQ+5oryf$A=yB-N%*f z=k}QE*D5p0GIc;EbXU~rj2DG4L;41%O49|)kIds8HbBX1`0m}X@|;e0%%?kiTR@gi zrqT~Qoq$O&zro4Gl21sUL0@CuqfKc~3shlpCraq?QYmLa!gC}zT#VQ_(UuRG7?M4? zK0-W@=MHge;4(fc8ig<%+fSjLX?m~bs({yDy1FA$t|h$`Zs@Ajz7WZTfDUjEi8GSZ%18?bqA0}@YL1wc%R`|q8A?SFOdYXbsCK~(39o_eRisT<=+O|Fi1k92 zM~42Er!m0vk*m!f35i_9Ih_#S*j#yX+`?3eaYn)p9cSiwB%~i1%6q1#Osnq+ER4FP zrGYYKLb+i12ok8g$4`R#E6OsnJlvy~#I(#rr#L2>O_W^lL@W-3B)HmBfto$)rxl{# z3duV1a-n%+(S)Q(tuxEz?|_814`}Ha{5#sxI4y^8Xw>Qk9}QwaONZJ_>^(ykz_2DDm0Um2$BAHj$}&^( zi8{chza@6h5T9wbAnbAS#4;aQriR!^y)q9+G>^Cpi^b@sB zI4>}snaWzl6`Qe;h%~0LaBh`;0Mxh%o^aLS+DM$0IXU)!ocQ7|w%q=_=lc2;_^;M& zeoi1;a%p&XkF~edIku)zZdnhg5t=Eechi{Q>?g#Lm_}QM~Dg-twKLkOg+oE+KYp4NL57K`r2fkpn}brRyvk& z4?f_kkW!_O4&jDwxUl_l!0#Wi^T_!I0!meczL3Xb6XcV_HBLk8ZXs(@c!_cvmTlg7=sT-YY(K zB%kS|p%Te8laf%XLT=;=<=p7DBSDnZV6jRR!TB>;9abF9RZdSZ+5;LJ*S9^IXP7%Q zuQ-(MYGBiOrkshLL$ff~4$}pZO!P)Bh0E!Y$M^5p?!F}Suh_~r-w+uI{ub< zy!_OK?O&oTf914%_so^$h#SQU&KD!8vMvz)7N)2doN}h;tDy z8E=kmvl>S)(+NMnrF?>UaJ*{5o{4<=}viLXDCiMNcEYq+a2&7*(J6%WWj5O>) zB8s58L-j|niN3q0c}Hn)=!SnA+!by90heyDoLO>YND;F@iVAj*h|&*^X*61Si-d?s zkGMOmy`||_sQa2ab=30rnA?FI@V?^2Lv@7sQzSj1wV^H2`Gpu2qhbC_tRB&PqP9pL z&y3?+Z2TR;zd^QJD1K#C%4#-F!)ttaqSb34;^YbQJC>(AY<@%016_E9*%65|v=?aE zK>O8NMRh9}9KOT(E3}@NFEiR6AaAhv1}{5G-h+FG+KHk)Ex)AYU(xcfnaev|-ILF+ zKr&(Dneq|K4d+Ls{XG@~EQZV%%CbevJsdom8(Pn>{mBX}-&K4%&>r5h$iyAkmN{To~X%DkH5s`3taXTwj@!8XRq+Ra-QCj!-YIOVv{hL2N&tno=$GD zYFPgPD17+kzvSlehEk5C@xs$GQr(83KM;1F$iz5iQmCjH&#9Cz7yrk3(xFbnsob1V(vAWjy#4A!J`YwRm(3bbO!w!)iyu+t}vlEE~9PsIa z&jDguMG;Q1T~BF|5G$>C+~8MZw>ftENW+kQBu=YHptykAhE^vuJ5)w=ex!tZO54)( z7F>@XdfX5QaplOhvT(lah*i-%VkES@Mo$aQEwt9-!$@flcG zBNiRf9WZs|*@0Ux5a!c~Hl7(h6f>$cdcS9o3>MHRu#AW-Wl$R4P0IsxdJ#_>)B$&R!FJG?Y?9>oe_DDh>+)s ziQs%#&AZKLD6J}KBb3>bqQj)%yDc#|#>>;Xk|&NX8sZ!h1ExJrAJOt21g@TMS>^?! zV}JFUWto`gJ47%5;a;^|=vEkTcdRmJR0(@o~L)s^I1Y z?J7(KO-e|S{if%BT<}|n3)t+4W-Q}^Ht=miP^uZ?_w09$R*o#i<9$c7%y?0>vThw} z#I!PWD<)5Uq~dYig4jy02!qiUkYWsSVv)d7)(ePYij>u0Y^DVJSFGrUEpYs(bm5bX z%H5EhBVX>R<3LrIP8WvlHQU!;k;;3{$3ja&V?Za*^!UW?`W3_eC3?3*%HI-0#Q7e& z0cU5D84E(L1uf9oOS*JLX_e(-{{yYc@|@&ms(yfag)V_a;3;C zJeheMNu5%!dty`;A~{5~KGMpJt3uSYGC}H&a(<7wGo9aH{VjwK%sPOcvEe197W|ag z4_)p^XlGowLA6oTF~ml_jF`)qfNc->gNL0Fr@~w-lJ?Za@I|S1L8pvx1Rn|E2DN_O zoU)nALnFwR5U&aOg!w%sMmG9DX){i@cnh>B1Xqdm0iR$xex%M5>8cRoo@%d1_CS{! z>H3z%-Xpc)>os-rf*N1Yg3@tM7q+-G6Y?1!J8Zup3|n#?iQ^r?K>9r~Y|z=^OlWmL zc*Of22`_Qw_xQ~V+OolFTmz{%&`y7kvq&h<3A;cTULfo+Gt_0G|2fGen*9j&M5hty zBHfjPw56(&r|(H^r1&>$O(_Uzw?O;nwEB~kPZvC}TLUo>oE&KKf>D2Du{djk6heE$ute1qu9PqOYC z%%0=K2y=m6(azy)LR4t2(Dgf-?I_a)uSQB+ygv}b8Ru{Dc7ykg+GcWjq>Ede+Y