Compare commits

..
Author SHA1 Message Date
Devmate Bot 32b5907271 xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java
Reviewed By: javache

Differential Revision: D85546696
2025-10-29 02:11:48 -07:00
109 changed files with 995 additions and 2249 deletions
@@ -121,7 +121,7 @@ describe('Create Draft Release', () => {
});
describe('#_computeBody', () => {
it('computes body for release when no hermes versions are passed', async () => {
it('computes body for release', async () => {
const version = '0.77.1';
const changelog = `## v${version}
### Breaking Changes
@@ -134,83 +134,20 @@ describe('Create Draft Release', () => {
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`;
const body = _computeBody(changelog, version);
const body = _computeBody(version, changelog);
expect(body).toEqual(`${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-release.tar.gz)
Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${version}/hermes-ios-${version}-hermes-framework-dSYM-release.tar.gz)
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
---
To help you upgrade to this version, you can use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) ⚛️.
---
View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/react-native/blob/main/CHANGELOG.md).`);
});
it('computes body for release when hermes versions are passed', async () => {
const version = '0.77.1';
const hermesVersion = '0.15.0';
const hermesV1Version = '250829098.0.2';
const changelog = `## v${version}
### Breaking Changes
- [PR #9012](https://github.com/facebook/react-native/pull/9012) - Some other change
#### Android
- [PR #3456](https://github.com/facebook/react-native/pull/3456) - Some other change
- [PR #3457](https://github.com/facebook/react-native/pull/3457) - Some other change
#### iOS
- [PR #3436](https://github.com/facebook/react-native/pull/3436) - Some other change
- [PR #3437](https://github.com/facebook/react-native/pull/3437) - Some other change`;
const body = _computeBody(
changelog,
version,
hermesVersion,
hermesV1Version,
);
expect(body).toEqual(`${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-release.tar.gz)
Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
+5 -21
View File
@@ -40,29 +40,19 @@ function _extractChangelog(version) {
return changelog.slice(changelogStarts, changelogEnds).join('\n').trim();
}
function _computeBody(changelog, version, hermesVersion, hermesV1Version) {
hermesVersion = hermesVersion ?? version;
hermesV1Version = hermesV1Version ?? version;
function _computeBody(version, changelog) {
return `${changelog}
---
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesVersion}/hermes-ios-${hermesVersion}-hermes-framework-dSYM-release.tar.gz)
Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/${hermesV1Version}/hermes-ios-${hermesV1Version}-hermes-framework-dSYM-release.tar.gz)
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-hermes-framework-dSYM-release.tar.gz)
ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-dependencies-dSYM-release.tar.gz)
ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/${version}/react-native-artifacts-${version}-reactnative-core-release.tar.gz)
---
You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).
@@ -123,13 +113,7 @@ function moveToChangelogBranch(version) {
run(`git checkout -b changelog/v${version}`);
}
async function createDraftRelease(
version,
latest,
token,
hermesVersion,
hermesV1Version,
) {
async function createDraftRelease(version, latest, token) {
if (version.startsWith('v')) {
version = version.substring(1);
}
@@ -137,7 +121,7 @@ async function createDraftRelease(
_verifyTagExists(version);
moveToChangelogBranch(version);
const changelog = _extractChangelog(version);
const body = _computeBody(changelog, version, hermesVersion, hermesV1Version);
const body = _computeBody(version, changelog);
const release = await _createDraftReleaseOnGitHub(
version,
body,
+1 -10
View File
@@ -2,15 +2,6 @@ name: Create Draft Release
on:
workflow_call:
inputs:
hermesVersion:
required: false
type: string
description: The version of Hermes to use for this release (eg. 0.15.0). If not specified, it will use React Native Version
hermesV1Version:
required: false
type: string
description: The version of Hermes V1 to use for this release (eg. 250829098.0.2). If not specified, it will use React Native Version
jobs:
create-draft-release:
@@ -36,7 +27,7 @@ jobs:
const {createDraftRelease} = require('./.github/workflow-scripts/createDraftRelease.js');
const version = '${{ github.ref_name }}';
const {isLatest} = require('./.github/workflow-scripts/publishTemplate.js');
return (await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}', ${{ inputs.hermesVersion }}, ${{ inputs.hermesV1Version }})).id;
return (await createDraftRelease(version, isLatest(), '${{secrets.REACT_NATIVE_BOT_GITHUB_TOKEN}}')).id;
result-encoding: string
- name: Upload release assets for DotSlash
uses: actions/github-script@v6
+1 -26
View File
@@ -19,28 +19,6 @@ jobs:
echo "Setting release type to release"
echo "RELEASE_TYPE=release" >> $GITHUB_OUTPUT
set_hermes_versions:
runs-on: ubuntu-latest
if: github.repository == 'facebook/react-native'
outputs:
HERMES_VERSION: ${{ steps.set_hermes_versions.outputs.HERMES_VERSION }}
HERMES_V1_VERSION: ${{ steps.set_hermes_versions.outputs.HERMES_V1_VERSION }}
steps:
- name: Checkout
uses: actions/checkout@v4
- id: set_hermes_versions
run: |
echo "Setting hermes versions to latest"
hermes_version=$(grep -oE 'HERMES_VERSION_NAME=([0-9]+\.[0-9]+\.[0-9]+)' packages/react-native/sdks/hermes-engine/version.properties | cut -d'=' -f2)
hermes_v1_version=$(grep -oE 'HERMES_V1_VERSION_NAME=([0-9]+\.[0-9]+\.[0-9]+)' packages/react-native/sdks/hermes-engine/version.properties | cut -d'=' -f2)
echo "HERMES_VERSION=$hermes_version" >> $GITHUB_OUTPUT
echo "HERMES_V1_VERSION=$hermes_v1_version" >> $GITHUB_OUTPUT
- name: Print hermes versions
run: |
echo "HERMES_VERSION=${{ steps.set_hermes_versions.outputs.HERMES_VERSION }}"
echo "HERMES_V1_VERSION=${{ steps.set_hermes_versions.outputs.HERMES_V1_VERSION }}"
prebuild_apple_dependencies:
if: github.repository == 'facebook/react-native'
uses: ./.github/workflows/prebuild-ios-dependencies.yml
@@ -139,9 +117,6 @@ jobs:
secrets: inherit
create_draft_release:
needs: [generate_changelog, set_hermes_versions]
needs: generate_changelog
uses: ./.github/workflows/create-draft-release.yml
secrets: inherit
with:
hermesVersion: ${{ needs.set_hermes_versions.outputs.HERMES_VERSION }}
hermesV1Version: ${{ needs.set_hermes_versions.outputs.HERMES_V1_VERSION }}
+2 -2
View File
@@ -1,5 +1,5 @@
@generated SignedSource<<4bb67766e15e25a481c4c38873260a7a>>
Git revision: 7aa57d13e50ce9d74a91c9315c9b0ded00fbc19f
@generated SignedSource<<dc58cf17e902cabe1ef88730ce9e056e>>
Git revision: 96e6bb8ecdff166816e2a469b7594f1276bda8c1
Built with --nohooks: false
Is local checkout: false
Remote URL: https://github.com/facebook/react-native-devtools-frontend
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import*as e from"../root/root.js";const t=e.Runtime.RNExperimentName,i={didInitializeExperiments:!1,isReactNativeEntryPoint:!1};class n{name;title;unstable;docLink;feedbackLink;enabledByDefault;constructor(e){this.name=e.name,this.title=e.title,this.unstable=e.unstable,this.docLink=e.docLink,this.feedbackLink=e.feedbackLink,this.enabledByDefault=function(e,t){if(null==e)return()=>t;if("boolean"==typeof e)return()=>e;return e}(e.enabledByDefault,!1)}}const r=new class{#e=new Map;#t=new Set;register(e){if(i.didInitializeExperiments)throw new Error("Experiments must be registered before constructing MainImpl");const{name:t}=e;if(this.#e.has(t))throw new Error(`React Native Experiment ${t} is already registered`);this.#e.set(t,new n(e))}enableExperimentsByDefault(e){if(i.didInitializeExperiments)throw new Error("Experiments must be configured before constructing MainImpl");for(const i of e)if(Object.prototype.hasOwnProperty.call(t,i)){const e=this.#e.get(i);if(!e)throw new Error(`React Native Experiment ${i} is not registered`);e.enabledByDefault=()=>!0}else this.#t.add(i)}copyInto(e,t=""){for(const[n,r]of this.#e)e.register(n,t+r.title,r.unstable,r.docLink,r.feedbackLink),r.enabledByDefault({isReactNativeEntryPoint:i.isReactNativeEntryPoint})&&e.enableExperimentsByDefault([n]);for(const t of this.#t)e.enableExperimentsByDefault([t]);i.didInitializeExperiments=!0}};r.register({name:t.JS_HEAP_PROFILER_ENABLE,title:"Enable Heap Profiler (Memory Panel)",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>!e}),r.register({name:t.REACT_NATIVE_SPECIFIC_UI,title:"Show React Native-specific UI",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>e}),r.register({name:t.ENABLE_NETWORK_PANEL,title:"Enable Network panel",unstable:!0,enabledByDefault:()=>!1});var a=Object.freeze({__proto__:null,Instance:r,RNExperimentName:t,setIsReactNativeEntryPoint:function(e){if(i.didInitializeExperiments)throw new Error("setIsReactNativeEntryPoint must be called before constructing MainImpl");i.isReactNativeEntryPoint=e}});export{a as RNExperimentsImpl};
import*as e from"../root/root.js";const t=e.Runtime.RNExperimentName,n={didInitializeExperiments:!1,isReactNativeEntryPoint:!1};class i{name;title;unstable;docLink;feedbackLink;enabledByDefault;constructor(e){this.name=e.name,this.title=e.title,this.unstable=e.unstable,this.docLink=e.docLink,this.feedbackLink=e.feedbackLink,this.enabledByDefault=function(e,t){if(null==e)return()=>t;if("boolean"==typeof e)return()=>e;return e}(e.enabledByDefault,!1)}}const r=new class{#e=new Map;#t=new Set;register(e){if(n.didInitializeExperiments)throw new Error("Experiments must be registered before constructing MainImpl");const{name:t}=e;if(this.#e.has(t))throw new Error(`React Native Experiment ${t} is already registered`);this.#e.set(t,new i(e))}enableExperimentsByDefault(e){if(n.didInitializeExperiments)throw new Error("Experiments must be configured before constructing MainImpl");for(const n of e)if(Object.prototype.hasOwnProperty.call(t,n)){const e=this.#e.get(n);if(!e)throw new Error(`React Native Experiment ${n} is not registered`);e.enabledByDefault=()=>!0}else this.#t.add(n)}copyInto(e,t=""){for(const[i,r]of this.#e)e.register(i,t+r.title,r.unstable,r.docLink,r.feedbackLink),r.enabledByDefault({isReactNativeEntryPoint:n.isReactNativeEntryPoint})&&e.enableExperimentsByDefault([i]);for(const t of this.#t)e.enableExperimentsByDefault([t]);n.didInitializeExperiments=!0}};r.register({name:t.JS_HEAP_PROFILER_ENABLE,title:"Enable Heap Profiler (Memory Panel)",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>!e}),r.register({name:t.REACT_NATIVE_SPECIFIC_UI,title:"Show React Native-specific UI",unstable:!1,enabledByDefault:({isReactNativeEntryPoint:e})=>e}),r.register({name:t.ENABLE_PERFORMANCE_PANEL,title:"Enable Performance panel",unstable:!0,enabledByDefault:({isReactNativeEntryPoint:e})=>!e}),r.register({name:t.ENABLE_NETWORK_PANEL,title:"Enable Network panel",unstable:!0,enabledByDefault:()=>!1});var a=Object.freeze({__proto__:null,Instance:r,RNExperimentName:t,setIsReactNativeEntryPoint:function(e){if(n.didInitializeExperiments)throw new Error("setIsReactNativeEntryPoint must be called before constructing MainImpl");n.isReactNativeEntryPoint=e}});export{a as RNExperimentsImpl};
@@ -1 +1 @@
import*as e from"../platform/platform.js";const t=new URLSearchParams(location.search);let n,r,s="";function a(){return window.location.pathname}function i(e){return["node_app","js_app"].some((t=>e.includes(t)))}class o{constructor(){}static instance(e={forceNew:null}){const{forceNew:t}=e;return n&&!t||(n=new o),n}static removeInstance(){n=void 0}static queryParam(e){return t.get(e)}static setQueryParamForTesting(e,n){t.set(e,n)}static isNode(){return void 0===r&&(r=i(a())),r}static setPlatform(e){s=e}static platform(){return s}static isDescriptorEnabled(e){const{experiment:t}=e;if("*"===t)return!0;if(t&&t.startsWith("!")&&h.isEnabled(t.substring(1)))return!1;if(t&&!t.startsWith("!")&&!h.isEnabled(t))return!1;const{condition:n}=e;return!n||n(_)}loadLegacyModule(e){console.log("Loading legacy module: "+e);return import(`../../${e}`).then((t=>(console.log("Loaded legacy module: "+e),t)))}}class l{#e=[];#t=new Set;#n=new Set;#r=new Set;#s=new Set;#a=new c;allConfigurableExperiments(){const e=[];for(const t of this.#e)this.#n.has(t.name)||e.push(t);return e}register(t,n,r,s,a){if(this.#t.has(t))throw new Error(`Duplicate registration of experiment '${t}'`);this.#t.add(t),this.#e.push(new m(this,t,n,Boolean(r),s??e.DevToolsPath.EmptyUrlString,a??e.DevToolsPath.EmptyUrlString))}isEnabled(e){return this.checkExperiment(e),!1!==this.#a.get(e)&&(!(!this.#n.has(e)&&!this.#r.has(e))||(!!this.#s.has(e)||Boolean(this.#a.get(e))))}setEnabled(e,t){this.checkExperiment(e),this.#a.set(e,t)}enableExperimentsTransiently(e){for(const t of e)this.checkExperiment(t),this.#n.add(t)}enableExperimentsByDefault(e){for(const t of e)this.checkExperiment(t),this.#r.add(t)}setServerEnabledExperiments(e){for(const t of e)this.checkExperiment(t),this.#s.add(t)}enableForTest(e){this.checkExperiment(e),this.#n.add(e)}disableForTest(e){this.checkExperiment(e),this.#n.delete(e)}clearForTest(){this.#e=[],this.#t.clear(),this.#n.clear(),this.#r.clear(),this.#s.clear()}cleanUpStaleExperiments(){this.#a.cleanUpStaleExperiments(this.#t)}checkExperiment(e){if(!this.#t.has(e))throw new Error(`Unknown experiment '${e}'`)}}class c{#e={};constructor(){try{const e=self.localStorage?.getItem("experiments");e&&(this.#e=JSON.parse(e))}catch{console.error("Failed to parse localStorage['experiments']")}}get(e){return this.#e[e]}set(e,t){this.#e[e]=t,this.#i()}cleanUpStaleExperiments(e){for(const[t]of Object.entries(this.#e))e.has(t)||delete this.#e[t];this.#i()}#i(){self.localStorage?.setItem("experiments",JSON.stringify(this.#e))}}class m{name;title;unstable;docLink;feedbackLink;#e;constructor(e,t,n,r,s,a){this.name=t,this.title=n,this.unstable=r,this.docLink=s,this.feedbackLink=a,this.#e=e}isEnabled(){return this.#e.isEnabled(this.name)}setEnabled(e){this.#e.setEnabled(this.name,e)}}const h=new l;var E,p,d,u;!function(e){e.REACT_NATIVE_SPECIFIC_UI="react-native-specific-ui",e.JS_HEAP_PROFILER_ENABLE="js-heap-profiler-enable",e.ENABLE_NETWORK_PANEL="enable-network-panel"}(E||(E={})),function(e){e.NOT_SOURCES_HIDE_ADD_FOLDER="!sources.hide_add_folder",e.REACT_NATIVE_UNSTABLE_NETWORK_PANEL="unstable_enableNetworkPanel"}(p||(p={})),function(e){e[e.ALLOW=0]="ALLOW",e[e.ALLOW_WITHOUT_LOGGING=1]="ALLOW_WITHOUT_LOGGING",e[e.DISABLE=2]="DISABLE"}(d||(d={})),function(e){e.ALL_SCRIPTS="ALL_SCRIPTS",e.SIDE_EFFECT_FREE_SCRIPTS_ONLY="SIDE_EFFECT_FREE_SCRIPTS_ONLY",e.NO_SCRIPTS="NO_SCRIPTS"}(u||(u={}));const _=Object.create(null),f={canDock:()=>Boolean(o.queryParam("can_dock")),notSourcesHideAddFolder:()=>Boolean(o.queryParam(p.NOT_SOURCES_HIDE_ADD_FOLDER)),reactNativeUnstableNetworkPanel:()=>Boolean(o.queryParam(p.REACT_NATIVE_UNSTABLE_NETWORK_PANEL))||h.isEnabled("enable-network-panel")};var x=Object.freeze({__proto__:null,get ConditionName(){return p},Experiment:m,ExperimentsSupport:l,get GenAiEnterprisePolicyValue(){return d},get HostConfigFreestylerExecutionMode(){return u},get RNExperimentName(){return E},Runtime:o,conditions:f,experiments:h,getChromeVersion:()=>{const e=navigator.userAgent.match(/(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/);return e&&e.length>1?e[1]:""},getPathName:a,getRemoteBase:function(e=self.location.toString()){const t=new URL(e).searchParams.get("remoteBase");if(!t)return null;const n=/\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(t);return n?{base:`devtools://devtools/remote/serve_file/${n[1]}/`,version:n[1]}:null},hostConfig:_,isNodeEntry:i});export{x as Runtime};
import*as e from"../platform/platform.js";const t=new URLSearchParams(location.search);let n,r,s="";function a(){return window.location.pathname}function i(e){return["node_app","js_app"].some((t=>e.includes(t)))}class o{constructor(){}static instance(e={forceNew:null}){const{forceNew:t}=e;return n&&!t||(n=new o),n}static removeInstance(){n=void 0}static queryParam(e){return t.get(e)}static setQueryParamForTesting(e,n){t.set(e,n)}static isNode(){return void 0===r&&(r=i(a())),r}static setPlatform(e){s=e}static platform(){return s}static isDescriptorEnabled(e){const{experiment:t}=e;if("*"===t)return!0;if(t&&t.startsWith("!")&&h.isEnabled(t.substring(1)))return!1;if(t&&!t.startsWith("!")&&!h.isEnabled(t))return!1;const{condition:n}=e;return!n||n(_)}loadLegacyModule(e){console.log("Loading legacy module: "+e);return import(`../../${e}`).then((t=>(console.log("Loaded legacy module: "+e),t)))}}class l{#e=[];#t=new Set;#n=new Set;#r=new Set;#s=new Set;#a=new c;allConfigurableExperiments(){const e=[];for(const t of this.#e)this.#n.has(t.name)||e.push(t);return e}register(t,n,r,s,a){if(this.#t.has(t))throw new Error(`Duplicate registration of experiment '${t}'`);this.#t.add(t),this.#e.push(new m(this,t,n,Boolean(r),s??e.DevToolsPath.EmptyUrlString,a??e.DevToolsPath.EmptyUrlString))}isEnabled(e){return this.checkExperiment(e),!1!==this.#a.get(e)&&(!(!this.#n.has(e)&&!this.#r.has(e))||(!!this.#s.has(e)||Boolean(this.#a.get(e))))}setEnabled(e,t){this.checkExperiment(e),this.#a.set(e,t)}enableExperimentsTransiently(e){for(const t of e)this.checkExperiment(t),this.#n.add(t)}enableExperimentsByDefault(e){for(const t of e)this.checkExperiment(t),this.#r.add(t)}setServerEnabledExperiments(e){for(const t of e)this.checkExperiment(t),this.#s.add(t)}enableForTest(e){this.checkExperiment(e),this.#n.add(e)}disableForTest(e){this.checkExperiment(e),this.#n.delete(e)}clearForTest(){this.#e=[],this.#t.clear(),this.#n.clear(),this.#r.clear(),this.#s.clear()}cleanUpStaleExperiments(){this.#a.cleanUpStaleExperiments(this.#t)}checkExperiment(e){if(!this.#t.has(e))throw new Error(`Unknown experiment '${e}'`)}}class c{#e={};constructor(){try{const e=self.localStorage?.getItem("experiments");e&&(this.#e=JSON.parse(e))}catch{console.error("Failed to parse localStorage['experiments']")}}get(e){return this.#e[e]}set(e,t){this.#e[e]=t,this.#i()}cleanUpStaleExperiments(e){for(const[t]of Object.entries(this.#e))e.has(t)||delete this.#e[t];this.#i()}#i(){self.localStorage?.setItem("experiments",JSON.stringify(this.#e))}}class m{name;title;unstable;docLink;feedbackLink;#e;constructor(e,t,n,r,s,a){this.name=t,this.title=n,this.unstable=r,this.docLink=s,this.feedbackLink=a,this.#e=e}isEnabled(){return this.#e.isEnabled(this.name)}setEnabled(e){this.#e.setEnabled(this.name,e)}}const h=new l;var E,p,d,u;!function(e){e.REACT_NATIVE_SPECIFIC_UI="react-native-specific-ui",e.JS_HEAP_PROFILER_ENABLE="js-heap-profiler-enable",e.ENABLE_PERFORMANCE_PANEL="enable-performance-panel",e.ENABLE_NETWORK_PANEL="enable-network-panel"}(E||(E={})),function(e){e.NOT_SOURCES_HIDE_ADD_FOLDER="!sources.hide_add_folder",e.REACT_NATIVE_UNSTABLE_NETWORK_PANEL="unstable_enableNetworkPanel"}(p||(p={})),function(e){e[e.ALLOW=0]="ALLOW",e[e.ALLOW_WITHOUT_LOGGING=1]="ALLOW_WITHOUT_LOGGING",e[e.DISABLE=2]="DISABLE"}(d||(d={})),function(e){e.ALL_SCRIPTS="ALL_SCRIPTS",e.SIDE_EFFECT_FREE_SCRIPTS_ONLY="SIDE_EFFECT_FREE_SCRIPTS_ONLY",e.NO_SCRIPTS="NO_SCRIPTS"}(u||(u={}));const _=Object.create(null),f={canDock:()=>Boolean(o.queryParam("can_dock")),notSourcesHideAddFolder:()=>Boolean(o.queryParam(p.NOT_SOURCES_HIDE_ADD_FOLDER)),reactNativeUnstableNetworkPanel:()=>Boolean(o.queryParam(p.REACT_NATIVE_UNSTABLE_NETWORK_PANEL))||h.isEnabled("enable-network-panel")};var x=Object.freeze({__proto__:null,get ConditionName(){return p},Experiment:m,ExperimentsSupport:l,get GenAiEnterprisePolicyValue(){return d},get HostConfigFreestylerExecutionMode(){return u},get RNExperimentName(){return E},Runtime:o,conditions:f,experiments:h,getChromeVersion:()=>{const e=navigator.userAgent.match(/(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/);return e&&e.length>1?e[1]:""},getPathName:a,getRemoteBase:function(e=self.location.toString()){const t=new URL(e).searchParams.get("remoteBase");if(!t)return null;const n=/\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(t);return n?{base:`devtools://devtools/remote/serve_file/${n[1]}/`,version:n[1]}:null},hostConfig:_,isNodeEntry:i});export{x as Runtime};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -26,9 +26,7 @@ describe('console.timeStamp()', () => {
it("doesn't throw when additional arguments are specified", () => {
expect(() =>
console.timeStamp('label', 100, 500, 'Track', 'Group', 'error', {
tooltipText: 'Image processing failed',
}),
console.timeStamp('label', 100, 500, 'Track', 'Group', 'error'),
).not.toThrow();
});
@@ -30,11 +30,8 @@ class RCTDeviceEventEmitterImpl extends EventEmitter<RCTDeviceEventDefinitions>
...args: RCTDeviceEventDefinitions[TEvent]
): void {
beginEvent(() => `RCTDeviceEventEmitter.emit#${eventType}`);
try {
super.emit(eventType, ...args);
} finally {
endEvent();
}
super.emit(eventType, ...args);
endEvent();
}
}
const RCTDeviceEventEmitter: IEventEmitter<RCTDeviceEventDefinitions> =
+1 -4
View File
@@ -87,7 +87,7 @@ export default function Ansi({
<View style={styles.container}>
{parsedLines.map((items, i) => (
<View style={styles.line} key={i}>
<Text style={styles.text}>
<Text>
{items.map((bundle, key) => {
const textStyle =
bundle.fg && COLORS[bundle.fg]
@@ -122,7 +122,4 @@ const styles = StyleSheet.create({
line: {
flexDirection: 'row',
},
text: {
flexGrow: 1,
},
});
+39 -1
View File
@@ -14,6 +14,7 @@ import type {
EventCallback,
EventListener,
} from '../../src/private/webapis/dom/events/EventTarget';
import type Performance from '../../src/private/webapis/performance/Performance';
import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger';
import Event from '../../src/private/webapis/dom/events/Event';
@@ -33,7 +34,13 @@ const RCTNetworking = require('./RCTNetworking').default;
const base64 = require('base64-js');
const invariant = require('invariant');
const PERFORMANCE_TRACK_NAME = 'Network (JS-initiated only)';
const PERFORMANCE_TRACK_GROUP = 'Chrome DevTools Temp Compat';
declare var performance: Performance;
const DEBUG_NETWORK_SEND_DELAY: false = false; // Set to a number of milliseconds when debugging
const LABEL_FOR_MISSING_URL_FOR_PROFILING = 'Unknown URL';
export type NativeResponseType = 'base64' | 'blob' | 'text';
export type ResponseType =
@@ -134,6 +141,7 @@ class XMLHttpRequest extends EventTarget {
static DONE: number = DONE;
static _interceptor: ?XHRInterceptor = null;
static _profiling: boolean = false;
UNSENT: number = UNSENT;
OPENED: number = OPENED;
@@ -174,6 +182,10 @@ class XMLHttpRequest extends EventTarget {
XMLHttpRequest._interceptor = interceptor;
}
static enableProfiling(enableProfiling: boolean): void {
XMLHttpRequest._profiling = enableProfiling;
}
constructor() {
super();
this._reset();
@@ -377,12 +389,23 @@ class XMLHttpRequest extends EventTarget {
return;
}
const start = XMLHttpRequest._profiling ? performance.now() : undefined;
if (!this._response) {
this._response = responseText;
} else {
this._response += responseText;
}
if (XMLHttpRequest._profiling) {
console.timeStamp(
'Incremental Data: ' + this._getMeasureURL(),
start,
undefined,
PERFORMANCE_TRACK_NAME,
PERFORMANCE_TRACK_GROUP,
);
}
XMLHttpRequest._interceptor &&
XMLHttpRequest._interceptor.dataReceived(requestId, responseText);
@@ -427,7 +450,16 @@ class XMLHttpRequest extends EventTarget {
this._clearSubscriptions();
this._requestId = null;
this.setReadyState(this.DONE);
if (XMLHttpRequest._profiling && this._startTime != null) {
const start = this._startTime;
console.timeStamp(
this._getMeasureURL(),
start,
undefined,
PERFORMANCE_TRACK_NAME,
PERFORMANCE_TRACK_GROUP,
);
}
if (error) {
XMLHttpRequest._interceptor &&
XMLHttpRequest._interceptor.loadingFailed(requestId, error);
@@ -697,6 +729,12 @@ class XMLHttpRequest extends EventTarget {
super.addEventListener(type, listener);
}
_getMeasureURL(): string {
return (
this._trackingName ?? this._url ?? LABEL_FOR_MISSING_URL_FOR_PROFILING
);
}
/*
* `on<event>` event handling (without JS prototype magic).
*/
@@ -0,0 +1,152 @@
/**
* 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 {
HostInstance,
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
NativeMethods,
} from '../../../src/private/types/HostInstance';
import type {
InternalInstanceHandle,
ViewConfig,
} from '../../Renderer/shims/ReactNativeTypes';
import TextInputState from '../../Components/TextInput/TextInputState';
import {getNodeFromInternalInstanceHandle} from '../../ReactNative/RendererProxy';
import {getFabricUIManager} from '../FabricUIManager';
import {create} from './ReactNativeAttributePayload';
import warnForStyleProps from './warnForStyleProps';
import nullthrows from 'nullthrows';
const {
measure: fabricMeasure,
measureInWindow: fabricMeasureInWindow,
measureLayout: fabricMeasureLayout,
getBoundingClientRect: fabricGetBoundingClientRect,
setNativeProps,
} = nullthrows(getFabricUIManager());
const noop = () => {};
/**
* This is used for refs on host components.
*/
export default class ReactFabricHostComponent implements NativeMethods {
// These need to be accessible from `ReactFabricPublicInstanceUtils`.
__nativeTag: number;
__internalInstanceHandle: InternalInstanceHandle;
_viewConfig: ViewConfig;
constructor(
tag: number,
viewConfig: ViewConfig,
internalInstanceHandle: InternalInstanceHandle,
) {
this.__nativeTag = tag;
this._viewConfig = viewConfig;
this.__internalInstanceHandle = internalInstanceHandle;
}
blur() {
// $FlowFixMe[incompatible-type] - Error supressed during the migration of HostInstance to ReactNativeElement
TextInputState.blurTextInput(this);
}
focus() {
// $FlowFixMe[incompatible-type] - Error supressed during the migration of HostInstance to ReactNativeElement
TextInputState.focusTextInput(this);
}
measure(callback: MeasureOnSuccessCallback) {
const node = getNodeFromInternalInstanceHandle(
this.__internalInstanceHandle,
);
if (node != null) {
fabricMeasure(node, callback);
}
}
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
const node = getNodeFromInternalInstanceHandle(
this.__internalInstanceHandle,
);
if (node != null) {
fabricMeasureInWindow(node, callback);
}
}
measureLayout(
relativeToNativeNode: number | HostInstance,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void /* currently unused */,
) {
if (
typeof relativeToNativeNode === 'number' ||
!(relativeToNativeNode instanceof ReactFabricHostComponent)
) {
if (__DEV__) {
console.error(
'Warning: ref.measureLayout must be called with a ref to a native component.',
);
}
return;
}
const toStateNode = getNodeFromInternalInstanceHandle(
this.__internalInstanceHandle,
);
const fromStateNode = getNodeFromInternalInstanceHandle(
relativeToNativeNode.__internalInstanceHandle,
);
if (toStateNode != null && fromStateNode != null) {
fabricMeasureLayout(
toStateNode,
fromStateNode,
onFail != null ? onFail : noop,
onSuccess != null ? onSuccess : noop,
);
}
}
unstable_getBoundingClientRect(): DOMRect {
const node = getNodeFromInternalInstanceHandle(
this.__internalInstanceHandle,
);
if (node != null) {
const rect = fabricGetBoundingClientRect(node, true);
if (rect) {
return new DOMRect(rect[0], rect[1], rect[2], rect[3]);
}
}
// Empty rect if any of the above failed
return new DOMRect(0, 0, 0, 0);
}
setNativeProps(nativeProps: {...}): void {
if (__DEV__) {
warnForStyleProps(nativeProps, this._viewConfig.validAttributes);
}
const updatePayload = create(nativeProps, this._viewConfig.validAttributes);
const node = getNodeFromInternalInstanceHandle(
this.__internalInstanceHandle,
);
if (node != null && updatePayload != null) {
setNativeProps(node, updatePayload);
}
}
}
@@ -13,62 +13,124 @@
* instances and get some data from them (like their instance handle / fiber).
*/
import type ReactNativeDocumentT from '../../../src/private/webapis/dom/nodes/ReactNativeDocument';
import typeof * as ReactNativeDocumentModuleT from '../../../src/private/webapis/dom/nodes/ReactNativeDocument';
import type ReactNativeElementT from '../../../src/private/webapis/dom/nodes/ReactNativeElement';
import type ReadOnlyTextT from '../../../src/private/webapis/dom/nodes/ReadOnlyText';
import typeof * as RendererProxyT from '../../ReactNative/RendererProxy';
import type {
InternalInstanceHandle,
Node,
ViewConfig,
} from '../../Renderer/shims/ReactNativeTypes';
import type {RootTag} from '../RootTag';
import type ReactFabricHostComponentT from './ReactFabricHostComponent';
import ReactNativeDocument, {
createReactNativeDocument,
} from '../../../src/private/webapis/dom/nodes/ReactNativeDocument';
import ReactNativeElement from '../../../src/private/webapis/dom/nodes/ReactNativeElement';
import ReadOnlyText from '../../../src/private/webapis/dom/nodes/ReadOnlyText';
import * as RendererProxy from '../../ReactNative/RendererProxy';
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
export opaque type PublicRootInstance = mixed;
// Lazy loaded to avoid evaluating the module when using the legacy renderer.
let ReactNativeDocumentModuleObject: ?ReactNativeDocumentModuleT;
let ReactFabricHostComponentClass: Class<ReactFabricHostComponentT>;
let ReactNativeElementClass: Class<ReactNativeElementT>;
let ReadOnlyTextClass: Class<ReadOnlyTextT>;
let RendererProxy: RendererProxyT;
function getReactNativeDocumentModule(): ReactNativeDocumentModuleT {
if (ReactNativeDocumentModuleObject == null) {
// We initialize this lazily to avoid a require cycle.
ReactNativeDocumentModuleObject = require('../../../src/private/webapis/dom/nodes/ReactNativeDocument');
}
return ReactNativeDocumentModuleObject;
}
function getReactNativeElementClass(): Class<ReactNativeElementT> {
if (ReactNativeElementClass == null) {
ReactNativeElementClass =
require('../../../src/private/webapis/dom/nodes/ReactNativeElement').default;
}
return ReactNativeElementClass;
}
function getReactFabricHostComponentClass(): Class<ReactFabricHostComponentT> {
if (ReactFabricHostComponentClass == null) {
ReactFabricHostComponentClass =
require('./ReactFabricHostComponent').default;
}
return ReactFabricHostComponentClass;
}
function getReadOnlyTextClass(): Class<ReadOnlyTextT> {
if (ReadOnlyTextClass == null) {
ReadOnlyTextClass =
require('../../../src/private/webapis/dom/nodes/ReadOnlyText').default;
}
return ReadOnlyTextClass;
}
export function createPublicRootInstance(rootTag: RootTag): PublicRootInstance {
if (ReactNativeFeatureFlags.enableAccessToHostTreeInFabric()) {
const ReactNativeDocumentModule = getReactNativeDocumentModule();
// $FlowExpectedError[incompatible-return]
return ReactNativeDocumentModule.createReactNativeDocument(rootTag);
}
// $FlowExpectedError[incompatible-return]
return createReactNativeDocument(rootTag);
return null;
}
export function createPublicInstance(
tag: number,
viewConfig: ViewConfig,
internalInstanceHandle: InternalInstanceHandle,
ownerDocument: ReactNativeDocument,
): ReactNativeElement {
return new ReactNativeElement(
tag,
viewConfig,
internalInstanceHandle,
ownerDocument,
);
ownerDocument: ReactNativeDocumentT,
): ReactFabricHostComponentT | ReactNativeElementT {
if (ReactNativeFeatureFlags.enableAccessToHostTreeInFabric()) {
const ReactNativeElement = getReactNativeElementClass();
return new ReactNativeElement(
tag,
viewConfig,
internalInstanceHandle,
ownerDocument,
);
} else {
const ReactFabricHostComponent = getReactFabricHostComponentClass();
return new ReactFabricHostComponent(
tag,
viewConfig,
internalInstanceHandle,
);
}
}
export function createPublicTextInstance(
internalInstanceHandle: InternalInstanceHandle,
ownerDocument: ReactNativeDocument,
): ReadOnlyText {
ownerDocument: ReactNativeDocumentT,
): ReadOnlyTextT {
const ReadOnlyText = getReadOnlyTextClass();
return new ReadOnlyText(internalInstanceHandle, ownerDocument);
}
export function getNativeTagFromPublicInstance(
publicInstance: ReactNativeElement,
publicInstance: ReactFabricHostComponentT | ReactNativeElementT,
): number {
return publicInstance.__nativeTag;
}
export function getNodeFromPublicInstance(
publicInstance: ReactNativeElement,
publicInstance: ReactFabricHostComponentT | ReactNativeElementT,
): ?Node {
// Avoid loading ReactFabric if using an instance from the legacy renderer.
if (publicInstance.__internalInstanceHandle == null) {
return null;
}
if (RendererProxy == null) {
RendererProxy = require('../../ReactNative/RendererProxy');
}
return RendererProxy.getNodeFromInternalInstanceHandle(
// $FlowExpectedError[incompatible-type] __internalInstanceHandle is always an InternalInstanceHandle from React when we get here.
publicInstance.__internalInstanceHandle,
@@ -76,7 +138,7 @@ export function getNodeFromPublicInstance(
}
export function getInternalInstanceHandleFromPublicInstance(
publicInstance: ReactNativeElement,
publicInstance: ReactFabricHostComponentT | ReactNativeElementT,
): InternalInstanceHandle {
// TODO(T174762768): Remove this once OSS versions of renderers will be synced.
// $FlowExpectedError[prop-missing] Keeping this for backwards-compatibility with the renderers versions in open source.
@@ -0,0 +1,75 @@
/**
* 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 '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {
InternalInstanceHandle,
ViewConfig,
} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
import type ReactNativeDocument from 'react-native/src/private/webapis/dom/nodes/ReactNativeDocument';
import * as Fantom from '@react-native/fantom';
import ReactFabricHostComponent from 'react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
// Create fake parameters for the class.
const tag = 11;
const viewConfig: ViewConfig = {
uiViewClassName: 'test',
validAttributes: {
style: {},
},
};
// $FlowExpectedError[incompatible-type]
const internalInstanceHandle: InternalInstanceHandle = {};
// $FlowExpectedError[incompatible-type]
const ownerDocument: ReactNativeDocument = {};
const ITERATIONS = 100;
const now = Fantom.unstable_benchmark.now;
/* eslint-disable no-new */
Fantom.unstable_benchmark
.suite('ReactNativeElement vs. ReactFabricHostComponent', {
minIterations: 50000,
})
.test('ReactNativeElement', () => {
// This logic is very fast and if we only run it once the cost of calling
// the benchmark function itself is significant. Calling it in a loop and
// computing the average is more accurate to account for that.
const start = now();
for (let i = 0; i < ITERATIONS; i++) {
new ReactNativeElement(
tag,
viewConfig,
internalInstanceHandle,
ownerDocument,
);
}
const end = now();
return {
overriddenDuration: (end - start) / ITERATIONS,
};
})
.test('ReactFabricHostComponent', () => {
// This logic is very fast and if we only run it once the cost of calling
// the benchmark function itself is significant. Calling it in a loop and
// computing the average is more accurate to account for that.
const start = now();
for (let i = 0; i < ITERATIONS; i++) {
new ReactFabricHostComponent(tag, viewConfig, internalInstanceHandle);
}
const end = now();
return {
overriddenDuration: (end - start) / ITERATIONS,
};
});
@@ -0,0 +1,353 @@
/**
* 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
* @fantom_flags enableAccessToHostTreeInFabric:*
*/
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
import type {HostInstance} from 'react-native';
import ReactNativeElement from '../../../../src/private/webapis/dom/nodes/ReactNativeElement';
import TextInput from '../../../Components/TextInput/TextInput';
import TextInputState from '../../../Components/TextInput/TextInputState';
import View from '../../../Components/View/View';
import ReactFabricHostComponent from '../ReactFabricHostComponent';
import * as Fantom from '@react-native/fantom';
import nullthrows from 'nullthrows';
import * as React from 'react';
import {createRef} from 'react';
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
// TODO: move these tests to the test file for `ReactNativeElement` when the legacy implementation is removed.
describe('ReactFabricPublicInstance', () => {
it('should provide instances of the right class as refs in host components', () => {
const nodeRef = createRef<HostInstance>();
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<View ref={nodeRef} />);
});
const node = nullthrows(nodeRef.current);
expect(node).toBeInstanceOf(
ReactNativeFeatureFlags.enableAccessToHostTreeInFabric()
? ReactNativeElement
: ReactFabricHostComponent,
);
});
describe('blur', () => {
test('blur() invokes TextInputState', () => {
const root = Fantom.createRoot();
const nodeRef = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(<TextInput ref={nodeRef} />);
});
const node = nullthrows(nodeRef.current);
const blurTextInput = jest.fn();
// We don't support view commands in Fantom yet, so we have to mock this.
TextInputState.blurTextInput = blurTextInput;
Fantom.runTask(() => {
node.blur();
});
expect(blurTextInput).toHaveBeenCalledTimes(1);
expect(blurTextInput.mock.calls).toEqual([[node]]);
});
});
describe('focus', () => {
test('focus() invokes TextInputState', () => {
const root = Fantom.createRoot();
const ref = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(<TextInput ref={ref} />);
});
const node = nullthrows(ref.current);
const focusTextInput = jest.fn();
// We don't support view commands in Fantom yet, so we have to mock this.
TextInputState.focusTextInput = focusTextInput;
Fantom.runTask(() => {
node.focus();
});
expect(focusTextInput).toHaveBeenCalledTimes(1);
expect(focusTextInput.mock.calls).toEqual([[node]]);
});
});
describe('measure', () => {
it('component.measure(...) invokes callback', () => {
const root = Fantom.createRoot();
const ref = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={ref}
/>,
);
});
const node = nullthrows(ref.current);
const callback = jest.fn();
node.measure(callback);
expect(callback).toHaveBeenCalledTimes(1);
expect(callback.mock.calls).toEqual([[10, 10, 100, 100, 10, 10]]);
});
it('unmounted.measure(...) does nothing', () => {
const root = Fantom.createRoot();
const ref = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={ref}
/>,
);
});
const node = nullthrows(ref.current);
Fantom.runTask(() => {
root.render(<></>);
});
const callback = jest.fn();
node.measure(callback);
expect(callback).not.toHaveBeenCalled();
});
});
describe('measureInWindow', () => {
it('component.measureInWindow(...) invokes callback', () => {
const root = Fantom.createRoot();
const ref = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={ref}
/>,
);
});
const node = nullthrows(ref.current);
const callback = jest.fn();
node.measureInWindow(callback);
expect(callback).toHaveBeenCalledTimes(1);
expect(callback.mock.calls).toEqual([[10, 10, 100, 100]]);
});
it('unmounted.measureInWindow(...) does nothing', () => {
const root = Fantom.createRoot();
const ref = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={ref}
/>,
);
});
const node = nullthrows(ref.current);
Fantom.runTask(() => {
root.render(<></>);
});
const callback = jest.fn();
node.measureInWindow(callback);
expect(callback).not.toHaveBeenCalled();
});
});
describe('measureLayout', () => {
it('component.measureLayout(component, ...) invokes callback', () => {
const root = Fantom.createRoot();
const parentRef = createRef<HostInstance>();
const childRef = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={parentRef}>
<View
style={{width: 10, height: 10, left: 20, top: 20}}
ref={childRef}
/>
</View>,
);
});
const parentNode = nullthrows(parentRef.current);
const childNode = nullthrows(childRef.current);
const callback = jest.fn();
childNode.measureLayout(parentNode, callback);
expect(callback).toHaveBeenCalledTimes(1);
expect(callback.mock.calls).toEqual([[20, 20, 10, 10]]);
});
it('unmounted.measureLayout(component, ...) does nothing', () => {
const root = Fantom.createRoot();
const parentRef = createRef<HostInstance>();
const childRef = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={parentRef}>
<View
style={{width: 10, height: 10, left: 20, top: 20}}
ref={childRef}
/>
</View>,
);
});
const parentNode = nullthrows(parentRef.current);
const childNode = nullthrows(childRef.current);
Fantom.runTask(() => {
root.render(
<View style={{width: 100, height: 100, left: 10, top: 10}} />,
);
});
const callback = jest.fn();
childNode.measureLayout(parentNode, callback);
expect(callback).not.toHaveBeenCalled();
});
it('component.measureLayout(unmounted, ...) does nothing', () => {
const root = Fantom.createRoot();
const parentRef = createRef<HostInstance>();
const childRef = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={parentRef}>
<View
style={{width: 10, height: 10, left: 20, top: 20}}
ref={childRef}
/>
</View>,
);
});
const parentNode = nullthrows(parentRef.current);
const childNode = nullthrows(childRef.current);
Fantom.runTask(() => {
root.render(
<View style={{width: 100, height: 100, left: 10, top: 10}} />,
);
});
const callback = jest.fn();
parentNode.measureLayout(childNode, callback);
expect(callback).not.toHaveBeenCalled();
});
it('unmounted.measureLayout(unmounted, ...) does nothing', () => {
const root = Fantom.createRoot();
const parentRef = createRef<HostInstance>();
const childRef = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(
<View
style={{width: 100, height: 100, left: 10, top: 10}}
ref={parentRef}>
<View
style={{width: 10, height: 10, left: 20, top: 20}}
ref={childRef}
/>
</View>,
);
});
const parentNode = nullthrows(parentRef.current);
const childNode = nullthrows(childRef.current);
Fantom.runTask(() => {
root.render(<></>);
});
const callback = jest.fn();
childNode.measureLayout(parentNode, callback);
expect(callback).not.toHaveBeenCalled();
});
});
describe('setNativeProps', () => {
it('should propagate changes to the host component', () => {
const root = Fantom.createRoot();
const nodeRef = createRef<HostInstance>();
Fantom.runTask(() => {
root.render(<View ref={nodeRef} testID="first test id" />);
});
expect(
root
.getRenderedOutput({
props: ['testID'],
})
.toJSX(),
).toEqual(<rn-view testID={'first test id'} />);
const element = nullthrows(nodeRef.current);
Fantom.runTask(() => {
element.setNativeProps({testID: 'second test id'});
});
expect(
root
.getRenderedOutput({
props: ['testID'],
})
.toJSX(),
).toEqual(<rn-view testID={'second test id'} />);
});
});
});
@@ -1088,16 +1088,6 @@ static RCTBorderStyle RCTBorderStyleFromOutlineStyle(OutlineStyle outlineStyle)
Float saturation = std::get<Float>(primitive.parameters);
[_swiftUIWrapper updateSaturation:@(saturation)];
}
} else if (primitive.type == FilterType::Contrast) {
if (_swiftUIWrapper != nullptr) {
Float contrast = std::get<Float>(primitive.parameters);
[_swiftUIWrapper updateContrast:@(contrast)];
}
} else if (primitive.type == FilterType::HueRotate) {
if (_swiftUIWrapper != nullptr) {
Float hueRotateDegrees = std::get<Float>(primitive.parameters);
[_swiftUIWrapper updateHueRotate:@(hueRotateDegrees)];
}
}
}
}
@@ -1555,8 +1545,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
if (!_props->filter.empty()) {
for (const auto &primitive : _props->filter) {
if (primitive.type == FilterType::Blur || primitive.type == FilterType::Grayscale ||
primitive.type == FilterType::DropShadow || primitive.type == FilterType::Saturate ||
primitive.type == FilterType::Contrast || primitive.type == FilterType::HueRotate) {
primitive.type == FilterType::DropShadow || primitive.type == FilterType::Saturate) {
return YES;
}
}
@@ -247,12 +247,8 @@ static UIImage *RCTGetSolidBorderImage(
const CGSize size = makeStretchable ? (CGSize){
// 1pt for the middle stretchable area along each axis
// we also need to round the edge insets to avoid border bleeding
// this is because if the size is decimal, when calculating the unit
// rectangle for CALayer.contentsCenter we encounter rounding errors
// which causes visual glitches
ceil(edgeInsets.left) + 1 + ceil(edgeInsets.right),
ceil(edgeInsets.top) + 1 + ceil(edgeInsets.bottom),
edgeInsets.left + 1 + edgeInsets.right,
edgeInsets.top + 1 + edgeInsets.bottom
} : viewSize;
UIGraphicsImageRenderer *const imageRenderer =
@@ -5651,7 +5651,6 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollView : android
public fun pageScroll (I)Z
public fun reactSmoothScrollTo (II)V
public fun requestChildFocus (Landroid/view/View;Landroid/view/View;)V
protected fun requestChildFocusWithoutScroll (Landroid/view/View;Landroid/view/View;)V
protected fun restoreScrollTo (II)V
public fun scrollTo (II)V
public fun scrollToPreservingMomentum (II)V
@@ -5792,7 +5791,6 @@ public class com/facebook/react/views/scroll/ReactScrollView : android/widget/Sc
public fun onTouchEvent (Landroid/view/MotionEvent;)Z
public fun reactSmoothScrollTo (II)V
public fun requestChildFocus (Landroid/view/View;Landroid/view/View;)V
protected fun requestChildFocusWithoutScroll (Landroid/view/View;Landroid/view/View;)V
public fun scrollTo (II)V
public fun scrollToPreservingMomentum (II)V
public fun setBackgroundColor (I)V
@@ -22,7 +22,6 @@ internal class PerfMonitorOverlayManager(
private var view: PerfMonitorOverlayView? = null
private var tracingState: TracingState = TracingState.ENABLEDINCDPMODE
private var perfIssueCount: Int = 0
/** Enable the Perf Monitor overlay. */
fun enable() {
@@ -73,19 +72,8 @@ internal class PerfMonitorOverlayManager(
override fun onRecordingStateChanged(state: TracingState) {
tracingState = state
if (state != TracingState.DISABLED) {
perfIssueCount = 0
}
UiThreadUtil.runOnUiThread {
view?.updateRecordingState(state)
view?.updatePerfIssueCount(perfIssueCount)
view?.show()
}
}
override fun onPerfIssueAdded(name: String) {
UiThreadUtil.runOnUiThread {
view?.updatePerfIssueCount(++perfIssueCount)
view?.show()
}
}
@@ -30,11 +30,9 @@ internal class PerfMonitorOverlayView(
private val onButtonPress: () -> Unit,
) {
private val dialog: Dialog
private lateinit var statusIndicator: TextView
private lateinit var statusLabel: TextView
private lateinit var tooltipLabel: TextView
private lateinit var issuesContainer: LinearLayout
private lateinit var issueCountLabel: TextView
private lateinit var statusIndicator: TextView
init {
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(context)
@@ -72,11 +70,6 @@ internal class PerfMonitorOverlayView(
dialog.show()
}
fun updatePerfIssueCount(count: Int) {
issueCountLabel.text = count.toString()
issuesContainer.visibility = if (count == 0) LinearLayout.GONE else LinearLayout.VISIBLE
}
private fun createToolbarDialog(): Dialog {
statusIndicator =
TextView(context).apply {
@@ -92,7 +85,11 @@ internal class PerfMonitorOverlayView(
val textContainer =
LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL
setPadding(dpToPx(2f).toInt(), 0, 0, 0)
layoutParams =
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
)
}
statusLabel =
TextView(context).apply {
@@ -109,35 +106,10 @@ internal class PerfMonitorOverlayView(
textContainer.addView(statusLabel)
textContainer.addView(tooltipLabel)
issuesContainer =
LinearLayout(context).apply {
setPadding(dpToPx(8f).toInt(), 0, 0, 0)
visibility = LinearLayout.GONE
}
issueCountLabel =
TextView(context).apply {
textSize = TEXT_SIZE_PRIMARY
setTextColor(Color.WHITE)
typeface = TYPEFACE_BOLD
val alertDrawable =
context.getDrawable(android.R.drawable.ic_dialog_alert)?.apply {
setBounds(
0,
1,
dpToPx(TEXT_SIZE_PRIMARY).toInt(),
dpToPx(TEXT_SIZE_PRIMARY).toInt() + 1,
)
}
setCompoundDrawables(alertDrawable, null, null, null)
compoundDrawablePadding = dpToPx(6f).toInt()
}
issuesContainer.addView(issueCountLabel)
val containerLayout = createInnerLayout()
containerLayout.setOnClickListener { onButtonPress() }
containerLayout.addView(statusIndicator)
containerLayout.addView(textContainer)
containerLayout.addView(issuesContainer)
val dialog =
createAnchoredDialog(dpToPx(12f), dpToPx(12f)).apply { setContentView(containerLayout) }
@@ -203,7 +175,7 @@ internal class PerfMonitorOverlayView(
showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
dividerDrawable =
object : ColorDrawable(Color.TRANSPARENT) {
override fun getIntrinsicWidth(): Int = dpToPx(10f).toInt()
override fun getIntrinsicWidth(): Int = dpToPx(8f).toInt()
}
}
}
@@ -4,7 +4,6 @@
* 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.devsupport.perfmonitor
import com.facebook.react.devsupport.interfaces.TracingState
@@ -13,7 +12,4 @@ import com.facebook.react.devsupport.interfaces.TracingState
internal interface PerfMonitorUpdateListener {
/** Called when the recording state of the background performance trace has changed. */
fun onRecordingStateChanged(state: TracingState)
/** Called when a new Performance Issue is added. */
fun onPerfIssueAdded(name: String)
}
@@ -80,7 +80,7 @@ public class SurfaceMountingManager {
// These are all non-null, until StopSurface is called
private ConcurrentHashMap<Integer, ViewState> mTagToViewState =
new ConcurrentHashMap<>(); // any thread
private final Queue<MountItem> mOnViewAttachMountItems = new ArrayDeque<>();
private Queue<MountItem> mOnViewAttachMountItems = new ArrayDeque<>();
private JSResponderHandler mJSResponderHandler;
private ViewManagerRegistry mViewManagerRegistry;
private RootViewManager mRootViewManager;
@@ -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<<d8dc8c3a2efe8b7e870546e5749ef5ad>>
* @generated SignedSource<<28000f9d4a36207875619060f2fa5713>>
*/
/**
@@ -210,12 +210,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean = accessor.enableInteropViewManagerClassLookUpOptimizationIOS()
/**
* Enables key up/down/press events to be sent to JS from components
*/
@JvmStatic
public fun enableKeyEvents(): Boolean = accessor.enableKeyEvents()
/**
* When enabled, LayoutAnimations API will animate state changes on Android.
*/
@@ -312,12 +306,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableViewRecyclingForView(): Boolean = accessor.enableViewRecyclingForView()
/**
* Set clipping to drawingRect of ScrollView.
*/
@JvmStatic
public fun enableVirtualViewClippingWithoutScrollViewClipping(): Boolean = accessor.enableVirtualViewClippingWithoutScrollViewClipping()
/**
* Enables the experimental version of `VirtualViewContainerState`.
*/
@@ -378,12 +366,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = accessor.overrideBySynchronousMountPropsAtMountingAndroid()
/**
* Enable reporting Performance Issues (`detail.rnPerfIssue`). Displayed in the V2 Performance Monitor and the "Performance Issues" sub-panel in DevTools.
*/
@JvmStatic
public fun perfIssuesEnabled(): Boolean = accessor.perfIssuesEnabled()
/**
* Enable the V2 in-app Performance Monitor. This flag is global and should not be changed across React Host lifetimes.
*/
@@ -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<<447ccc7271b71b0208a2297b7eba5995>>
* @generated SignedSource<<ba1a322a9c7069cf63fd759090f9025d>>
*/
/**
@@ -50,7 +50,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableImmediateUpdateModeForContentOffsetChangesCache: Boolean? = null
private var enableImperativeFocusCache: Boolean? = null
private var enableInteropViewManagerClassLookUpOptimizationIOSCache: Boolean? = null
private var enableKeyEventsCache: Boolean? = null
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
private var enableMainQueueCoordinatorOnIOSCache: Boolean? = null
@@ -67,7 +66,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var enableViewRecyclingForScrollViewCache: Boolean? = null
private var enableViewRecyclingForTextCache: Boolean? = null
private var enableViewRecyclingForViewCache: Boolean? = null
private var enableVirtualViewClippingWithoutScrollViewClippingCache: Boolean? = null
private var enableVirtualViewContainerStateExperimentalCache: Boolean? = null
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
private var enableVirtualViewRenderStateCache: Boolean? = null
@@ -78,7 +76,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
private var perfIssuesEnabledCache: Boolean? = null
private var perfMonitorV2EnabledCache: Boolean? = null
private var preparedTextCacheSizeCache: Double? = null
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
@@ -374,15 +371,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableKeyEvents(): Boolean {
var cached = enableKeyEventsCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableKeyEvents()
enableKeyEventsCache = cached
}
return cached
}
override fun enableLayoutAnimationsOnAndroid(): Boolean {
var cached = enableLayoutAnimationsOnAndroidCache
if (cached == null) {
@@ -527,15 +515,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun enableVirtualViewClippingWithoutScrollViewClipping(): Boolean {
var cached = enableVirtualViewClippingWithoutScrollViewClippingCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableVirtualViewClippingWithoutScrollViewClipping()
enableVirtualViewClippingWithoutScrollViewClippingCache = cached
}
return cached
}
override fun enableVirtualViewContainerStateExperimental(): Boolean {
var cached = enableVirtualViewContainerStateExperimentalCache
if (cached == null) {
@@ -626,15 +605,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}
override fun perfIssuesEnabled(): Boolean {
var cached = perfIssuesEnabledCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.perfIssuesEnabled()
perfIssuesEnabledCache = cached
}
return cached
}
override fun perfMonitorV2Enabled(): Boolean {
var cached = perfMonitorV2EnabledCache
if (cached == null) {
@@ -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<<d6403b67e269ad80ef3e2389ac923c8a>>
* @generated SignedSource<<412a865e975214a0d794985e48fbbe4b>>
*/
/**
@@ -88,8 +88,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean
@DoNotStrip @JvmStatic public external fun enableKeyEvents(): Boolean
@DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun enableLayoutAnimationsOnIOS(): Boolean
@@ -122,8 +120,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForView(): Boolean
@DoNotStrip @JvmStatic public external fun enableVirtualViewClippingWithoutScrollViewClipping(): Boolean
@DoNotStrip @JvmStatic public external fun enableVirtualViewContainerStateExperimental(): Boolean
@DoNotStrip @JvmStatic public external fun enableVirtualViewDebugFeatures(): Boolean
@@ -144,8 +140,6 @@ public object ReactNativeFeatureFlagsCxxInterop {
@DoNotStrip @JvmStatic public external fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@DoNotStrip @JvmStatic public external fun perfIssuesEnabled(): Boolean
@DoNotStrip @JvmStatic public external fun perfMonitorV2Enabled(): Boolean
@DoNotStrip @JvmStatic public external fun preparedTextCacheSize(): Double
@@ -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<<ab48ba86a7cf3cd35ec530a216aea774>>
* @generated SignedSource<<7987eba84c39c6e8cb6494092a94790e>>
*/
/**
@@ -83,8 +83,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean = false
override fun enableKeyEvents(): Boolean = false
override fun enableLayoutAnimationsOnAndroid(): Boolean = false
override fun enableLayoutAnimationsOnIOS(): Boolean = true
@@ -117,8 +115,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableViewRecyclingForView(): Boolean = true
override fun enableVirtualViewClippingWithoutScrollViewClipping(): Boolean = true
override fun enableVirtualViewContainerStateExperimental(): Boolean = false
override fun enableVirtualViewDebugFeatures(): Boolean = false
@@ -127,7 +123,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun enableVirtualViewWindowFocusDetection(): Boolean = false
override fun enableWebPerformanceAPIsByDefault(): Boolean = true
override fun enableWebPerformanceAPIsByDefault(): Boolean = false
override fun fixMappingOfEventPrioritiesBetweenFabricAndReact(): Boolean = false
@@ -139,8 +135,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean = false
override fun perfIssuesEnabled(): Boolean = false
override fun perfMonitorV2Enabled(): Boolean = false
override fun preparedTextCacheSize(): Double = 200.0
@@ -153,7 +147,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
override fun skipActivityIdentityAssertionOnHostPause(): Boolean = false
override fun sweepActiveTouchOnChildNativeGesturesAndroid(): Boolean = true
override fun sweepActiveTouchOnChildNativeGesturesAndroid(): Boolean = false
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = false
@@ -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<<6f6b5abe79764b88cf3ed62fe0230786>>
* @generated SignedSource<<7f43cde1ba2bef2300c077f35b168d31>>
*/
/**
@@ -54,7 +54,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableImmediateUpdateModeForContentOffsetChangesCache: Boolean? = null
private var enableImperativeFocusCache: Boolean? = null
private var enableInteropViewManagerClassLookUpOptimizationIOSCache: Boolean? = null
private var enableKeyEventsCache: Boolean? = null
private var enableLayoutAnimationsOnAndroidCache: Boolean? = null
private var enableLayoutAnimationsOnIOSCache: Boolean? = null
private var enableMainQueueCoordinatorOnIOSCache: Boolean? = null
@@ -71,7 +70,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var enableViewRecyclingForScrollViewCache: Boolean? = null
private var enableViewRecyclingForTextCache: Boolean? = null
private var enableViewRecyclingForViewCache: Boolean? = null
private var enableVirtualViewClippingWithoutScrollViewClippingCache: Boolean? = null
private var enableVirtualViewContainerStateExperimentalCache: Boolean? = null
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
private var enableVirtualViewRenderStateCache: Boolean? = null
@@ -82,7 +80,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
private var hideOffscreenVirtualViewsOnIOSCache: Boolean? = null
private var overrideBySynchronousMountPropsAtMountingAndroidCache: Boolean? = null
private var perfIssuesEnabledCache: Boolean? = null
private var perfMonitorV2EnabledCache: Boolean? = null
private var preparedTextCacheSizeCache: Double? = null
private var preventShadowTreeCommitExhaustionCache: Boolean? = null
@@ -408,16 +405,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableKeyEvents(): Boolean {
var cached = enableKeyEventsCache
if (cached == null) {
cached = currentProvider.enableKeyEvents()
accessedFeatureFlags.add("enableKeyEvents")
enableKeyEventsCache = cached
}
return cached
}
override fun enableLayoutAnimationsOnAndroid(): Boolean {
var cached = enableLayoutAnimationsOnAndroidCache
if (cached == null) {
@@ -578,16 +565,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun enableVirtualViewClippingWithoutScrollViewClipping(): Boolean {
var cached = enableVirtualViewClippingWithoutScrollViewClippingCache
if (cached == null) {
cached = currentProvider.enableVirtualViewClippingWithoutScrollViewClipping()
accessedFeatureFlags.add("enableVirtualViewClippingWithoutScrollViewClipping")
enableVirtualViewClippingWithoutScrollViewClippingCache = cached
}
return cached
}
override fun enableVirtualViewContainerStateExperimental(): Boolean {
var cached = enableVirtualViewContainerStateExperimentalCache
if (cached == null) {
@@ -688,16 +665,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}
override fun perfIssuesEnabled(): Boolean {
var cached = perfIssuesEnabledCache
if (cached == null) {
cached = currentProvider.perfIssuesEnabled()
accessedFeatureFlags.add("perfIssuesEnabled")
perfIssuesEnabledCache = cached
}
return cached
}
override fun perfMonitorV2Enabled(): Boolean {
var cached = perfMonitorV2EnabledCache
if (cached == null) {
@@ -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<<f82b5905d822f8009c054a9443f86e39>>
* @generated SignedSource<<4464982256b8ce543d9235fccbf67054>>
*/
/**
@@ -27,6 +27,8 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Canary_Android : ReactN
override fun enableFabricRenderer(): Boolean = true
override fun enableWebPerformanceAPIsByDefault(): Boolean = true
override fun useNativeViewConfigsInBridgelessMode(): Boolean = true
override fun useTurboModuleInterop(): Boolean = true
@@ -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<<6b61490a8d6b1df1d6264016455382f8>>
* @generated SignedSource<<692dcdb2af3c6af981e8f48686ca105e>>
*/
/**
@@ -83,8 +83,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableInteropViewManagerClassLookUpOptimizationIOS(): Boolean
@DoNotStrip public fun enableKeyEvents(): Boolean
@DoNotStrip public fun enableLayoutAnimationsOnAndroid(): Boolean
@DoNotStrip public fun enableLayoutAnimationsOnIOS(): Boolean
@@ -117,8 +115,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun enableViewRecyclingForView(): Boolean
@DoNotStrip public fun enableVirtualViewClippingWithoutScrollViewClipping(): Boolean
@DoNotStrip public fun enableVirtualViewContainerStateExperimental(): Boolean
@DoNotStrip public fun enableVirtualViewDebugFeatures(): Boolean
@@ -139,8 +135,6 @@ public interface ReactNativeFeatureFlagsProvider {
@DoNotStrip public fun overrideBySynchronousMountPropsAtMountingAndroid(): Boolean
@DoNotStrip public fun perfIssuesEnabled(): Boolean
@DoNotStrip public fun perfMonitorV2Enabled(): Boolean
@DoNotStrip public fun preparedTextCacheSize(): Double
@@ -1,109 +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.internal.tracing
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.bridge.ReadableNativeMap
import com.facebook.soloader.SoLoader
/**
* JNI interface to access PerformanceTracer methods from React Native Inspector Modern.
*
* This provides access to reportMark and reportMeasure methods which are used for performance
* tracing in the React Native DevTools.
*/
@DoNotStrip
public object PerformanceTracer {
init {
SoLoader.loadLibrary("react_performancetracerjni")
}
/** Callback interface for tracing state changes. */
@DoNotStrip
public interface TracingStateCallback {
/**
* Called when tracing state changes.
*
* @param isTracing true if tracing has started, false if tracing has stopped
*/
@DoNotStrip public fun onTracingStateChanged(isTracing: Boolean)
}
/**
* Report a Performance.mark() event - a labelled timestamp.
*
* @param name The name/label of the mark
* @param timestampNanos The timestamp in nanoseconds (monotonic time)
* @param detail Optional map with additional detail (pass null if not needed)
*/
@DoNotStrip
@JvmStatic
public external fun reportMark(name: String, timestampNanos: Long, detail: ReadableNativeMap?)
/**
* Report a Performance.measure() event - a labelled duration.
*
* @param name The name/label of the measure
* @param startTimestampNanos The start timestamp in nanoseconds (monotonic time)
* @param durationNanos The duration in nanoseconds
* @param detail Optional map with additional detail (pass null if not needed)
*/
@DoNotStrip
@JvmStatic
public external fun reportMeasure(
name: String,
startTimestampNanos: Long,
durationNanos: Long,
detail: ReadableNativeMap?,
)
/**
* Report a TimeStamp Trace Event - a labelled entry on Performance timeline.
*
* @param name The name/label of the timestamp
* @param startTimeNanos Start timestamp in nanoseconds (monotonic time)
* @param endTimeNanos End timestamp in nanoseconds (monotonic time)
* @param trackName Optional track name for organizing the timestamp
* @param trackGroup Optional track group for organizing the timestamp
* @param color Optional color name (e.g., "primary", "secondary", "error", "warning")
*/
@DoNotStrip
@JvmStatic
public external fun reportTimeStamp(
name: String,
startTimeNanos: Long,
endTimeNanos: Long,
trackName: String?,
trackGroup: String?,
color: String?,
)
/**
* Check if the tracer is currently tracing.
*
* @return true if tracing is active, false otherwise
*/
@DoNotStrip @JvmStatic public external fun isTracing(): Boolean
/**
* Subscribe to tracing state changes (start/stop events).
*
* @param callback The callback to invoke when tracing starts or stops
* @return A subscription ID that can be used to unsubscribe
*/
@DoNotStrip
@JvmStatic
public external fun subscribeToTracingStateChanges(callback: TracingStateCallback): Int
/**
* Unsubscribe from tracing state changes.
*
* @param subscriptionId The subscription ID returned from subscribeToTracingStateChanges
*/
@DoNotStrip @JvmStatic public external fun unsubscribeFromTracingStateChanges(subscriptionId: Int)
}
@@ -74,12 +74,6 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
}
}
fun handleNativePerfIssueAdded(
name: String,
) {
perfMonitorListeners.forEach { listener -> listener.onPerfIssueAdded(name) }
}
override fun close() {
mHybridData.resetNative()
}
@@ -45,22 +45,12 @@ import com.facebook.react.uimanager.style.LogicalEdge
import com.facebook.react.uimanager.style.OutlineStyle
/**
* Utility object responsible for applying backgrounds, borders, and related visual effects to
* Android views.
*
* This object provides methods to manage background colors, images, borders, outlines, and box
* shadows for React Native views. It handles the complex layering and composition of these visual
* properties by managing [CompositeBackgroundDrawable] instances.
* BackgroundStyleApplicator is responsible for applying backgrounds, borders, and related effects,
* to an Android view
*/
@OptIn(UnstableReactNativeAPI::class)
public object BackgroundStyleApplicator {
/**
* Sets the background color of the view.
*
* @param view The view to apply the background color to
* @param color The color to set, or null to remove the background color
*/
@JvmStatic
public fun setBackgroundColor(view: View, @ColorInt color: Int?): Unit {
// No color to set, and no color already set
@@ -74,12 +64,6 @@ public object BackgroundStyleApplicator {
ensureBackgroundDrawable(view).backgroundColor = color ?: Color.TRANSPARENT
}
/**
* Sets the background image layers for the view.
*
* @param view The view to apply the background images to
* @param backgroundImageLayers The list of background image layers to apply, or null to remove
*/
@JvmStatic
public fun setBackgroundImage(
view: View,
@@ -106,25 +90,12 @@ public object BackgroundStyleApplicator {
ensureBackgroundImageDrawable(view).backgroundRepeat = backgroundRepeats
}
/**
* Gets the background color of the view.
*
* @param view The view to get the background color from
* @return The background color, or null if no background color is set
*/
@JvmStatic
@ColorInt
public fun getBackgroundColor(view: View): Int? {
return getBackground(view)?.backgroundColor
}
/**
* Sets the border width for a specific edge of the view.
*
* @param view The view to apply the border width to
* @param edge The logical edge (start, end, top, bottom, etc.) to set the width for
* @param width The border width in DIPs, or null to remove
*/
@JvmStatic
public fun setBorderWidth(view: View, edge: LogicalEdge, width: Float?): Unit {
val composite = ensureCompositeBackgroundDrawable(view)
@@ -150,13 +121,6 @@ public object BackgroundStyleApplicator {
}
}
/**
* Gets the border width for a specific edge of the view.
*
* @param view The view to get the border width from
* @param edge The logical edge to get the width for
* @return The border width in DIPs, or null if not set
*/
@JvmStatic
public fun getBorderWidth(view: View, edge: LogicalEdge): Float? {
val width = getBorder(view)?.borderWidth?.getRaw(edge.toSpacingType())
@@ -167,38 +131,17 @@ public object BackgroundStyleApplicator {
}
}
/**
* Sets the border color for a specific edge of the view.
*
* @param view The view to apply the border color to
* @param edge The logical edge to set the color for
* @param color The border color, or null to remove
*/
@JvmStatic
public fun setBorderColor(view: View, edge: LogicalEdge, @ColorInt color: Int?): Unit {
ensureBorderDrawable(view).setBorderColor(edge, color)
}
/**
* Gets the border color for a specific edge of the view.
*
* @param view The view to get the border color from
* @param edge The logical edge to get the color for
* @return The border color, or null if not set
*/
@JvmStatic
@ColorInt
public fun getBorderColor(view: View, edge: LogicalEdge): Int? {
return getBorder(view)?.getBorderColor(edge)
}
/**
* Sets the border radius for a specific corner of the view.
*
* @param view The view to apply the border radius to
* @param corner The corner property to set the radius for
* @param radius The border radius value (length or percentage), or null to remove
*/
@JvmStatic
public fun setBorderRadius(
view: View,
@@ -240,47 +183,22 @@ public object BackgroundStyleApplicator {
compositeBackgroundDrawable.invalidateSelf()
}
/**
* Gets the border radius for a specific corner of the view.
*
* @param view The view to get the border radius from
* @param corner The corner property to get the radius for
* @return The border radius value, or null if not set
*/
@JvmStatic
public fun getBorderRadius(view: View, corner: BorderRadiusProp): LengthPercentage? {
return getCompositeBackgroundDrawable(view)?.borderRadius?.get(corner)
}
/**
* Sets the border style for the view.
*
* @param view The view to apply the border style to
* @param borderStyle The border style (solid, dashed, dotted), or null to remove
*/
@JvmStatic
public fun setBorderStyle(view: View, borderStyle: BorderStyle?) {
ensureBorderDrawable(view).borderStyle = borderStyle
}
/**
* Gets the border style of the view.
*
* @param view The view to get the border style from
* @return The border style, or null if not set
*/
@JvmStatic
public fun getBorderStyle(view: View): BorderStyle? {
return getBorder(view)?.borderStyle
}
/**
* Sets the outline color for the view (Fabric only).
*
* @param view The view to apply the outline color to
* @param outlineColor The outline color, or null to remove
*/
@JvmStatic
public fun setOutlineColor(view: View, @ColorInt outlineColor: Int?) {
if (ViewUtil.getUIManagerType(view) != UIManagerType.FABRIC) {
@@ -293,20 +211,8 @@ public object BackgroundStyleApplicator {
}
}
/**
* Gets the outline color of the view.
*
* @param view The view to get the outline color from
* @return The outline color, or null if not set
*/
@JvmStatic public fun getOutlineColor(view: View): Int? = getOutlineDrawable(view)?.outlineColor
/**
* Sets the outline offset for the view (Fabric only).
*
* @param view The view to apply the outline offset to
* @param outlineOffset The outline offset in DIPs
*/
@JvmStatic
public fun setOutlineOffset(view: View, outlineOffset: Float): Unit {
if (ViewUtil.getUIManagerType(view) != UIManagerType.FABRIC) {
@@ -317,20 +223,8 @@ public object BackgroundStyleApplicator {
outline.outlineOffset = outlineOffset.dpToPx()
}
/**
* Gets the outline offset of the view.
*
* @param view The view to get the outline offset from
* @return The outline offset in pixels, or null if not set
*/
public fun getOutlineOffset(view: View): Float? = getOutlineDrawable(view)?.outlineOffset
/**
* Sets the outline style for the view (Fabric only).
*
* @param view The view to apply the outline style to
* @param outlineStyle The outline style (solid, dashed, dotted), or null to remove
*/
@JvmStatic
public fun setOutlineStyle(view: View, outlineStyle: OutlineStyle?): Unit {
if (ViewUtil.getUIManagerType(view) != UIManagerType.FABRIC) {
@@ -343,20 +237,8 @@ public object BackgroundStyleApplicator {
}
}
/**
* Gets the outline style of the view.
*
* @param view The view to get the outline style from
* @return The outline style, or null if not set
*/
public fun getOutlineStyle(view: View): OutlineStyle? = getOutlineDrawable(view)?.outlineStyle
/**
* Sets the outline width for the view (Fabric only).
*
* @param view The view to apply the outline width to
* @param width The outline width in DIPs
*/
@JvmStatic
public fun setOutlineWidth(view: View, width: Float) {
if (ViewUtil.getUIManagerType(view) != UIManagerType.FABRIC) {
@@ -367,20 +249,8 @@ public object BackgroundStyleApplicator {
outline.outlineWidth = width.dpToPx()
}
/**
* Gets the outline width of the view.
*
* @param view The view to get the outline width from
* @return The outline width in pixels, or null if not set
*/
public fun getOutlineWidth(view: View): Float? = getOutlineDrawable(view)?.outlineOffset
/**
* Sets box shadows for the view (Fabric only).
*
* @param view The view to apply box shadows to
* @param shadows The list of box shadow styles to apply
*/
@JvmStatic
public fun setBoxShadow(view: View, shadows: List<BoxShadow>) {
if (ViewUtil.getUIManagerType(view) != UIManagerType.FABRIC) {
@@ -439,12 +309,6 @@ public object BackgroundStyleApplicator {
.withNewShadows(outerShadows = outerShadows, innerShadows = innerShadows)
}
/**
* Sets box shadows for the view from a ReadableArray (Fabric only).
*
* @param view The view to apply box shadows to
* @param shadows The array of box shadow definitions, or null to remove all shadows
*/
@JvmStatic
public fun setBoxShadow(view: View, shadows: ReadableArray?) {
if (shadows == null) {
@@ -459,26 +323,11 @@ public object BackgroundStyleApplicator {
BackgroundStyleApplicator.setBoxShadow(view, shadowStyles)
}
/**
* Sets a feedback underlay drawable for the view.
*
* @param view The view to apply the feedback underlay to
* @param drawable The drawable to use as feedback underlay, or null to remove
*/
@JvmStatic
public fun setFeedbackUnderlay(view: View, drawable: Drawable?) {
ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
}
/**
* Clips the canvas to the padding box of the view.
*
* The padding box is the area within the borders of the view, accounting for border radius if
* present.
*
* @param view The view whose padding box defines the clipping region
* @param canvas The canvas to clip
*/
@JvmStatic
public fun clipToPaddingBox(view: View, canvas: Canvas) {
val drawingRect = Rect()
@@ -517,13 +366,6 @@ public object BackgroundStyleApplicator {
}
}
/**
* Resets the background styling of the view to its original state.
*
* This removes any CompositeBackgroundDrawable and restores the original background.
*
* @param view The view to reset
*/
@JvmStatic
public fun reset(view: View) {
if (view.background is CompositeBackgroundDrawable) {
@@ -14,23 +14,10 @@ import android.view.ViewGroup
import androidx.core.view.children
import com.facebook.react.R
/**
* Helper object for parsing and handling CSS mix-blend-mode properties on Android Q+ (API 29+).
*
* This object provides utilities to convert CSS mix-blend-mode string values into Android's
* [BlendMode] enumeration and to determine when views need isolated layers for proper blending.
*/
@TargetApi(29)
internal object BlendModeHelper {
/**
* Parses a CSS mix-blend-mode string value into an Android BlendMode.
*
* @param mixBlendMode The CSS mix-blend-mode value (e.g., "multiply", "screen", "overlay")
* @return The corresponding [BlendMode], or null if "normal" or on unsupported Android versions
* @throws IllegalArgumentException if the mix-blend-mode name is invalid
* @see <a href="https://www.w3.org/TR/compositing-1/#mix-blend-mode">mix-blend-mode</a>
*/
/** @see <a href="https://www.w3.org/TR/compositing-1/#mix-blend-mode">mix-blend-mode</a> */
@JvmStatic
fun parseMixBlendMode(mixBlendMode: String?): BlendMode? {
if (mixBlendMode == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
@@ -9,18 +9,8 @@ package com.facebook.react.uimanager
import com.facebook.proguard.annotations.DoNotStripAny
/**
* Interface for resolving component names registered in React Native.
*
* This interface provides access to all registered component names in the React Native runtime,
* which is useful for debugging and inspection purposes.
*/
@DoNotStripAny
internal interface ComponentNameResolver {
/**
* Gets the list of all component names registered in React Native.
*
* @return An array of all registered component names
*/
/* returns a list of all the component names that are registered in React Native. */
val componentNames: Array<String>
}
@@ -12,23 +12,11 @@ import com.facebook.react.bridge.RuntimeExecutor
import com.facebook.soloader.SoLoader
import kotlin.jvm.JvmStatic
/**
* JNI binding for installing a ComponentNameResolver into the JavaScript runtime.
*
* This object provides a native binding to install a [ComponentNameResolver] into the React Native
* JavaScript runtime, making component name information available to the native side.
*/
@DoNotStripAny
internal object ComponentNameResolverBinding {
init {
SoLoader.loadLibrary("uimanagerjni")
}
/**
* Installs a ComponentNameResolver into the JavaScript runtime.
*
* @param runtimeExecutor The runtime executor for the JavaScript runtime
* @param componentNameResolver The component name resolver to install
*/
@JvmStatic external fun install(runtimeExecutor: RuntimeExecutor, componentNameResolver: Any)
}
@@ -21,25 +21,9 @@ import com.facebook.react.uimanager.PixelUtil.dpToPx
import kotlin.math.cos
import kotlin.math.sin
/**
* Helper object for parsing and applying CSS filter effects on Android S+ (API 31+).
*
* This object provides utilities to convert CSS filter arrays into Android [RenderEffect] chains
* and [ColorMatrixColorFilter] objects. Supports filters like blur, brightness, contrast,
* grayscale, sepia, saturate, hue-rotate, invert, opacity, and drop-shadow.
*
* @see <a href="https://www.w3.org/TR/filter-effects-1/">CSS Filter Effects Module Level 1</a>
*/
@TargetApi(31)
internal object FilterHelper {
/**
* Parses a ReadableArray of CSS filter definitions into a chained [RenderEffect].
*
* @param filters The array of filter definitions, or null
* @return A chained RenderEffect representing all filters, or null if no filters provided
* @throws IllegalArgumentException if an invalid filter name is encountered
*/
@JvmStatic
fun parseFilters(filters: ReadableArray?): RenderEffect? {
filters ?: return null
@@ -9,30 +9,9 @@ package com.facebook.react.uimanager
import kotlin.math.abs
/**
* Utility class for comparing floating-point numbers with epsilon-based equality.
*
* This class provides methods to compare float values while accounting for floating-point precision
* issues. Direct equality comparison of floats can be unreliable due to rounding errors in
* floating-point arithmetic. This utility uses an epsilon threshold to determine if two float
* values are "close enough" to be considered equal.
*/
public object FloatUtil {
private const val EPSILON = .00001f
/**
* Compares two float values for equality using an epsilon threshold.
*
* This method handles special cases:
* - If both values are NaN, they are considered equal
* - If only one value is NaN, they are not equal
* - Otherwise, values are equal if their absolute difference is less than [EPSILON]
*
* @param f1 the first float value to compare
* @param f2 the second float value to compare
* @return `true` if the values are equal within the epsilon threshold, `false` otherwise
*/
@JvmStatic
public fun floatsEqual(f1: Float, f2: Float): Boolean {
return if (f1.isNaN() || f2.isNaN()) {
@@ -40,18 +19,6 @@ public object FloatUtil {
} else abs(f2 - f1) < EPSILON
}
/**
* Compares two nullable float values for equality using an epsilon threshold.
*
* This method handles null values:
* - If both values are null, they are considered equal
* - If only one value is null, they are not equal
* - If both values are non-null, delegates to [floatsEqual] with non-null parameters
*
* @param f1 the first nullable float value to compare
* @param f2 the second nullable float value to compare
* @return `true` if the values are equal (both null or equal within epsilon), `false` otherwise
*/
@JvmStatic
public fun floatsEqual(f1: Float?, f2: Float?): Boolean {
if (f1 == null) {
@@ -14,15 +14,15 @@ import androidx.annotation.ColorInt
import com.facebook.react.modules.i18nmanager.I18nUtil
internal data class ColorEdges(
@param:ColorInt val left: Int = Color.BLACK,
@param:ColorInt val top: Int = Color.BLACK,
@param:ColorInt val right: Int = Color.BLACK,
@param:ColorInt val bottom: Int = Color.BLACK,
@ColorInt val left: Int = Color.BLACK,
@ColorInt val top: Int = Color.BLACK,
@ColorInt val right: Int = Color.BLACK,
@ColorInt val bottom: Int = Color.BLACK,
)
@JvmInline
internal value class BorderColors(
@param:ColorInt val edgeColors: Array<Int?> = arrayOfNulls<Int?>(LogicalEdge.values().size)
@ColorInt val edgeColors: Array<Int?> = arrayOfNulls<Int?>(LogicalEdge.values().size)
) {
fun resolve(layoutDirection: Int, context: Context): ColorEdges {
@@ -18,7 +18,7 @@ import com.facebook.react.bridge.ReadableType
public data class BoxShadow(
val offsetX: Float,
val offsetY: Float,
@param:ColorInt val color: Int? = null,
@ColorInt val color: Int? = null,
val blurRadius: Float? = null,
val spreadDistance: Float? = null,
val inset: Boolean? = null,
@@ -83,10 +83,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
HasSmoothScroll,
VirtualViewContainer {
private static final boolean DEBUG_MODE = false && ReactBuildConfig.DEBUG;
private static final String TAG = ReactHorizontalScrollView.class.getSimpleName();
private static boolean DEBUG_MODE = false && ReactBuildConfig.DEBUG;
private static String TAG = ReactHorizontalScrollView.class.getSimpleName();
private static final int NO_SCROLL_POSITION = Integer.MIN_VALUE;
private static int NO_SCROLL_POSITION = Integer.MIN_VALUE;
private static @Nullable Field sScrollerField;
private static boolean sTriedToGetScrollerField = false;
@@ -542,15 +542,6 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
if (focused != null && !mPagingEnabled) {
scrollToChild(focused);
}
requestChildFocusWithoutScroll(child, focused);
}
/**
* In rare cases where an app overrides the built-in ReactScrollView by overriding it, and also
* needs to customize scroll into view on focus behaviors, this protected method can be used to
* unblocks such customization.
*/
protected void requestChildFocusWithoutScroll(View child, View focused) {
super.requestChildFocus(child, focused);
}
@@ -511,15 +511,6 @@ public class ReactScrollView extends ScrollView
if (focused != null) {
scrollToChild(focused);
}
requestChildFocusWithoutScroll(child, focused);
}
/**
* In rare cases where an app overrides the built-in ReactScrollView by overriding it, and also
* needs to customize scroll into view on focus behaviors, this protected method can be used to
* unblocks such customization.
*/
protected void requestChildFocusWithoutScroll(View child, View focused) {
super.requestChildFocus(child, focused);
}
@@ -153,7 +153,6 @@ public open class ReactViewGroup public constructor(context: Context?) :
private var accessibilityStateChangeListener:
AccessibilityManager.AccessibilityStateChangeListener? =
null
private var focusOnAttach = false
init {
initView()
@@ -213,9 +212,6 @@ public open class ReactViewGroup public constructor(context: Context?) :
updateBackgroundDrawable(null)
resetPointerEvents()
// In case a focus was attempted but the view never attached, reset to false
focusOnAttach = false
}
private var _drawingOrderHelper: ViewGroupDrawingOrderHelper? = null
@@ -421,15 +417,10 @@ public open class ReactViewGroup public constructor(context: Context?) :
}
internal fun requestFocusFromJS() {
if (isAttachedToWindow) {
super.requestFocus(FOCUS_DOWN, null)
} else {
focusOnAttach = true
}
super.requestFocus(FOCUS_DOWN, null)
}
internal fun clearFocusFromJS() {
focusOnAttach = false
super.clearFocus()
}
@@ -581,11 +572,6 @@ public open class ReactViewGroup public constructor(context: Context?) :
if (_removeClippedSubviews) {
updateClippingRect()
}
if (focusOnAttach) {
requestFocusFromJS()
focusOnAttach = false
}
}
private fun customDrawOrderDisabled(): Boolean {
@@ -187,28 +187,17 @@ public class ReactVirtualView(context: Context) :
}
// If no ScrollView, or ScrollView has disabled removeClippedSubviews, use default behavior
if (parentScrollView == null) {
if (
parentScrollView == null ||
!((parentScrollView as ReactClippingViewGroup).removeClippedSubviews ?: false)
) {
super.updateClippingRect(excludedViews)
return
}
val clippingRect = checkNotNull(clippingRect)
val parentScrollView = checkNotNull(parentScrollView) as ReactClippingViewGroup
if (ReactNativeFeatureFlags.enableVirtualViewClippingWithoutScrollViewClipping()) {
if (parentScrollView.removeClippedSubviews) {
parentScrollView.getClippingRect(clippingRect)
} else {
(parentScrollView as View).getDrawingRect(clippingRect)
}
} else {
if (!(parentScrollView.removeClippedSubviews ?: false)) {
super.updateClippingRect(excludedViews)
return
}
parentScrollView.getClippingRect(clippingRect)
}
(parentScrollView as ReactClippingViewGroup).getClippingRect(clippingRect)
clippingRect.intersect(targetRect)
clippingRect.offset(-targetRect.left, -targetRect.top)
@@ -208,29 +208,17 @@ public class ReactVirtualViewExperimental(context: Context) :
}
// If no ScrollView, or ScrollView has disabled removeClippedSubviews, use default behavior
if (scrollView == null) {
if (
scrollView == null ||
!((scrollView as ReactClippingViewGroup).removeClippedSubviews ?: false)
) {
super.updateClippingRect(excludedViews)
return
}
val clippingRect = checkNotNull(clippingRect)
val scrollView = checkNotNull(scrollView) as ReactClippingViewGroup
if (ReactNativeFeatureFlags.enableVirtualViewClippingWithoutScrollViewClipping()) {
if (scrollView.removeClippedSubviews) {
scrollView.getClippingRect(clippingRect)
} else {
(scrollView as View).getDrawingRect(clippingRect)
}
} else {
if (!(scrollView.removeClippedSubviews ?: false)) {
super.updateClippingRect(excludedViews)
return
}
scrollView.getClippingRect(clippingRect)
}
(scrollView as ReactClippingViewGroup).getClippingRect(clippingRect)
clippingRect.intersect(containerRelativeRect)
clippingRect.offset(-containerRelativeRect.left, -containerRelativeRect.top)
@@ -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<<13ed11b5c260fae79048ea80745d22fe>>
* @generated SignedSource<<48a05f5360c927150021af873e6d52b8>>
*/
/**
@@ -219,12 +219,6 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableKeyEvents() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableKeyEvents");
return method(javaProvider_);
}
bool enableLayoutAnimationsOnAndroid() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableLayoutAnimationsOnAndroid");
@@ -321,12 +315,6 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool enableVirtualViewClippingWithoutScrollViewClipping() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableVirtualViewClippingWithoutScrollViewClipping");
return method(javaProvider_);
}
bool enableVirtualViewContainerStateExperimental() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableVirtualViewContainerStateExperimental");
@@ -387,12 +375,6 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}
bool perfIssuesEnabled() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("perfIssuesEnabled");
return method(javaProvider_);
}
bool perfMonitorV2Enabled() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("perfMonitorV2Enabled");
@@ -691,11 +673,6 @@ bool JReactNativeFeatureFlagsCxxInterop::enableInteropViewManagerClassLookUpOpti
return ReactNativeFeatureFlags::enableInteropViewManagerClassLookUpOptimizationIOS();
}
bool JReactNativeFeatureFlagsCxxInterop::enableKeyEvents(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableKeyEvents();
}
bool JReactNativeFeatureFlagsCxxInterop::enableLayoutAnimationsOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid();
@@ -776,11 +753,6 @@ bool JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForView(
return ReactNativeFeatureFlags::enableViewRecyclingForView();
}
bool JReactNativeFeatureFlagsCxxInterop::enableVirtualViewClippingWithoutScrollViewClipping(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableVirtualViewClippingWithoutScrollViewClipping();
}
bool JReactNativeFeatureFlagsCxxInterop::enableVirtualViewContainerStateExperimental(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableVirtualViewContainerStateExperimental();
@@ -831,11 +803,6 @@ bool JReactNativeFeatureFlagsCxxInterop::overrideBySynchronousMountPropsAtMounti
return ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid();
}
bool JReactNativeFeatureFlagsCxxInterop::perfIssuesEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::perfIssuesEnabled();
}
bool JReactNativeFeatureFlagsCxxInterop::perfMonitorV2Enabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::perfMonitorV2Enabled();
@@ -1077,9 +1044,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableInteropViewManagerClassLookUpOptimizationIOS",
JReactNativeFeatureFlagsCxxInterop::enableInteropViewManagerClassLookUpOptimizationIOS),
makeNativeMethod(
"enableKeyEvents",
JReactNativeFeatureFlagsCxxInterop::enableKeyEvents),
makeNativeMethod(
"enableLayoutAnimationsOnAndroid",
JReactNativeFeatureFlagsCxxInterop::enableLayoutAnimationsOnAndroid),
@@ -1128,9 +1092,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableViewRecyclingForView",
JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForView),
makeNativeMethod(
"enableVirtualViewClippingWithoutScrollViewClipping",
JReactNativeFeatureFlagsCxxInterop::enableVirtualViewClippingWithoutScrollViewClipping),
makeNativeMethod(
"enableVirtualViewContainerStateExperimental",
JReactNativeFeatureFlagsCxxInterop::enableVirtualViewContainerStateExperimental),
@@ -1161,9 +1122,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"overrideBySynchronousMountPropsAtMountingAndroid",
JReactNativeFeatureFlagsCxxInterop::overrideBySynchronousMountPropsAtMountingAndroid),
makeNativeMethod(
"perfIssuesEnabled",
JReactNativeFeatureFlagsCxxInterop::perfIssuesEnabled),
makeNativeMethod(
"perfMonitorV2Enabled",
JReactNativeFeatureFlagsCxxInterop::perfMonitorV2Enabled),
@@ -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<<1e57bf8252c16fc10bbfcae08710af85>>
* @generated SignedSource<<e8bbe1de8eccb3ecea6b9f001de07fd2>>
*/
/**
@@ -120,9 +120,6 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableInteropViewManagerClassLookUpOptimizationIOS(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableKeyEvents(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableLayoutAnimationsOnAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -171,9 +168,6 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableViewRecyclingForView(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableVirtualViewClippingWithoutScrollViewClipping(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool enableVirtualViewContainerStateExperimental(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -204,9 +198,6 @@ class JReactNativeFeatureFlagsCxxInterop
static bool overrideBySynchronousMountPropsAtMountingAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool perfIssuesEnabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
static bool perfMonitorV2Enabled(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
@@ -120,13 +120,6 @@ void JReactHostInspectorTarget::onSetPausedInDebuggerMessage(
}
}
void JReactHostInspectorTarget::unstable_onPerfIssueAdded(
const PerfIssuePayload& issue) {
static auto method = javaClassStatic()->getMethod<void(local_ref<jstring>)>(
"handleNativePerfIssueAdded");
method(jobj_, make_jstring(issue.name));
}
void JReactHostInspectorTarget::loadNetworkResource(
const jsinspector_modern::LoadNetworkResourceRequest& params,
jsinspector_modern::ScopedExecutor<
@@ -103,7 +103,6 @@ class JReactHostInspectorTarget : public jni::HybridClass<JReactHostInspectorTar
jsinspector_modern::HostTargetMetadata getMetadata() override;
void onReload(const PageReloadRequest &request) override;
void onSetPausedInDebuggerMessage(const OverlaySetPausedInDebuggerMessageRequest &request) override;
void unstable_onPerfIssueAdded(const jsinspector_modern::PerfIssuePayload &issue) override;
void loadNetworkResource(
const jsinspector_modern::LoadNetworkResourceRequest &params,
jsinspector_modern::ScopedExecutor<jsinspector_modern::NetworkRequestListener> executor) override;
@@ -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.
*/
#include "PerformanceTracerCxxInterop.h"
#include <fbjni/fbjni.h>
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* /*unused*/) {
return facebook::jni::initialize(vm, [] {
facebook::react::PerformanceTracerCxxInterop::registerNatives();
});
}
@@ -1,241 +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 "PerformanceTracerCxxInterop.h"
#include <folly/dynamic.h>
#include <jsinspector-modern/tracing/PerformanceTracer.h>
#include <react/jni/NativeMap.h>
#include <react/jni/ReadableNativeMap.h>
#include <react/timing/primitives.h>
#include <map>
#include <memory>
#include <mutex>
namespace facebook::react {
void TracingStateCallback::onTracingStateChanged(bool isTracing) const {
static const auto method =
javaClassStatic()->getMethod<void(jboolean)>("onTracingStateChanged");
method(self(), static_cast<jboolean>(isTracing));
}
namespace {
class TracingCallbackRegistry {
public:
static TracingCallbackRegistry& getInstance() {
static TracingCallbackRegistry instance;
return instance;
}
void registerCallback(
uint32_t subscriptionId,
jni::global_ref<jobject> callback) {
std::lock_guard<std::mutex> lock(mutex_);
callbacks_[subscriptionId] = std::move(callback);
}
void unregisterCallback(uint32_t subscriptionId) {
std::lock_guard<std::mutex> lock(mutex_);
callbacks_.erase(subscriptionId);
}
jni::global_ref<jobject> getCallback(uint32_t subscriptionId) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = callbacks_.find(subscriptionId);
if (it != callbacks_.end()) {
return it->second;
}
return nullptr;
}
private:
std::mutex mutex_;
std::map<uint32_t, jni::global_ref<jobject>> callbacks_;
};
} // namespace
void PerformanceTracerCxxInterop::reportMark(
jni::alias_ref<PerformanceTracerCxxInterop> /*jthis*/,
jni::alias_ref<jstring> name,
jlong timestampNanos,
jni::alias_ref<ReadableNativeMap::javaobject> detail) {
auto& tracer = jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (!tracer.isTracing()) {
return;
}
std::string nameStr = name->toStdString();
HighResTimeStamp timestamp = HighResTimeStamp::fromChronoSteadyClockTimePoint(
std::chrono::steady_clock::time_point(
std::chrono::nanoseconds(timestampNanos)));
folly::dynamic detailDynamic = nullptr;
if (detail) {
detailDynamic = detail->cthis()->consume();
}
tracer.reportMark(nameStr, timestamp, std::move(detailDynamic));
}
void PerformanceTracerCxxInterop::reportMeasure(
jni::alias_ref<PerformanceTracerCxxInterop> /*jthis*/,
jni::alias_ref<jstring> name,
jlong startTimestampNanos,
jlong durationNanos,
jni::alias_ref<ReadableNativeMap::javaobject> detail) {
auto& tracer = jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (!tracer.isTracing()) {
return;
}
std::string nameStr = name->toStdString();
HighResTimeStamp startTimestamp =
HighResTimeStamp::fromChronoSteadyClockTimePoint(
std::chrono::steady_clock::time_point(
std::chrono::nanoseconds(startTimestampNanos)));
HighResDuration duration = HighResDuration::fromNanoseconds(durationNanos);
folly::dynamic detailDynamic = nullptr;
if (detail) {
detailDynamic = detail->cthis()->consume();
}
tracer.reportMeasure(
nameStr, startTimestamp, duration, std::move(detailDynamic));
}
void PerformanceTracerCxxInterop::reportTimeStamp(
jni::alias_ref<PerformanceTracerCxxInterop> /*jthis*/,
jni::alias_ref<jstring> name,
jlong startTimeNanos,
jlong endTimeNanos,
jni::alias_ref<jstring> trackName,
jni::alias_ref<jstring> trackGroup,
jni::alias_ref<jstring> color) {
auto& tracer = jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (!tracer.isTracing()) {
return;
}
std::string nameStr = name->toStdString();
// Convert start timestamp
HighResTimeStamp startTimestamp =
HighResTimeStamp::fromChronoSteadyClockTimePoint(
std::chrono::steady_clock::time_point(
std::chrono::nanoseconds(startTimeNanos)));
// Convert end timestamp
HighResTimeStamp endTimestamp =
HighResTimeStamp::fromChronoSteadyClockTimePoint(
std::chrono::steady_clock::time_point(
std::chrono::nanoseconds(endTimeNanos)));
// Handle optional string parameters
std::optional<std::string> trackNameOpt = std::nullopt;
if (trackName) {
trackNameOpt = trackName->toStdString();
}
std::optional<std::string> trackGroupOpt = std::nullopt;
if (trackGroup) {
trackGroupOpt = trackGroup->toStdString();
}
// Handle optional color parameter
std::optional<jsinspector_modern::tracing::ConsoleTimeStampColor> colorOpt =
std::nullopt;
if (color) {
colorOpt = jsinspector_modern::tracing::getConsoleTimeStampColorFromString(
color->toStdString());
}
tracer.reportTimeStamp(
nameStr,
startTimestamp,
endTimestamp,
trackNameOpt,
trackGroupOpt,
colorOpt);
}
jboolean PerformanceTracerCxxInterop::isTracing(
jni::alias_ref<PerformanceTracerCxxInterop> /*jthis*/) {
return static_cast<jboolean>(
jsinspector_modern::tracing::PerformanceTracer::getInstance()
.isTracing());
}
jint PerformanceTracerCxxInterop::subscribeToTracingStateChanges(
jni::alias_ref<PerformanceTracerCxxInterop> /*jthis*/,
jni::alias_ref<TracingStateCallback::javaobject> callback) {
auto globalCallback = jni::make_global(callback);
auto& tracer = jsinspector_modern::tracing::PerformanceTracer::getInstance();
auto callbackWrapper = std::make_shared<uint32_t>(0);
uint32_t subscriptionId =
tracer.subscribeToTracingStateChanges([callbackWrapper](bool isTracing) {
auto callback = TracingCallbackRegistry::getInstance().getCallback(
*callbackWrapper);
if (callback) {
try {
jni::ThreadScope::WithClassLoader([&] {
auto callbackClass = callback->getClass();
auto onTracingStateChangedMethod =
callbackClass->getMethod<void(jboolean)>(
"onTracingStateChanged");
onTracingStateChangedMethod(
callback, static_cast<jboolean>(isTracing));
});
} catch (const std::exception& e) {
}
}
});
*callbackWrapper = subscriptionId;
TracingCallbackRegistry::getInstance().registerCallback(
subscriptionId, globalCallback);
return static_cast<jint>(subscriptionId);
}
void PerformanceTracerCxxInterop::unsubscribeFromTracingStateChanges(
jni::alias_ref<PerformanceTracerCxxInterop> /*jthis*/,
jint subscriptionId) {
auto& tracer = jsinspector_modern::tracing::PerformanceTracer::getInstance();
tracer.unsubscribeFromTracingStateChanges(
static_cast<uint32_t>(subscriptionId));
TracingCallbackRegistry::getInstance().unregisterCallback(
static_cast<uint32_t>(subscriptionId));
}
void PerformanceTracerCxxInterop::registerNatives() {
javaClassLocal()->registerNatives(
{makeNativeMethod("reportMark", PerformanceTracerCxxInterop::reportMark),
makeNativeMethod(
"reportMeasure", PerformanceTracerCxxInterop::reportMeasure),
makeNativeMethod(
"reportTimeStamp", PerformanceTracerCxxInterop::reportTimeStamp),
makeNativeMethod("isTracing", PerformanceTracerCxxInterop::isTracing),
makeNativeMethod(
"subscribeToTracingStateChanges",
PerformanceTracerCxxInterop::subscribeToTracingStateChanges),
makeNativeMethod(
"unsubscribeFromTracingStateChanges",
PerformanceTracerCxxInterop::unsubscribeFromTracingStateChanges)});
}
} // namespace facebook::react
@@ -1,63 +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.
*/
#pragma once
#include <fbjni/fbjni.h>
#include <jni.h>
#include <react/jni/ReadableNativeMap.h>
namespace facebook::react {
class TracingStateCallback : public facebook::jni::JavaClass<TracingStateCallback> {
public:
static constexpr auto kJavaDescriptor =
"Lcom/facebook/react/internal/tracing/PerformanceTracer$TracingStateCallback;";
void onTracingStateChanged(bool isTracing) const;
};
class PerformanceTracerCxxInterop : public facebook::jni::JavaClass<PerformanceTracerCxxInterop> {
public:
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/internal/tracing/PerformanceTracer;";
static void reportMark(
facebook::jni::alias_ref<PerformanceTracerCxxInterop> jthis,
facebook::jni::alias_ref<jstring> name,
jlong timestampNanos,
facebook::jni::alias_ref<ReadableNativeMap::javaobject> detail);
static void reportMeasure(
facebook::jni::alias_ref<PerformanceTracerCxxInterop> jthis,
facebook::jni::alias_ref<jstring> name,
jlong startTimestampNanos,
jlong durationNanos,
facebook::jni::alias_ref<ReadableNativeMap::javaobject> detail);
static void reportTimeStamp(
facebook::jni::alias_ref<PerformanceTracerCxxInterop> jthis,
facebook::jni::alias_ref<jstring> name,
jlong startTimeNanos,
jlong endTimeNanos,
facebook::jni::alias_ref<jstring> trackName,
facebook::jni::alias_ref<jstring> trackGroup,
facebook::jni::alias_ref<jstring> color);
static jboolean isTracing(facebook::jni::alias_ref<PerformanceTracerCxxInterop> jthis);
static jint subscribeToTracingStateChanges(
facebook::jni::alias_ref<PerformanceTracerCxxInterop> jthis,
facebook::jni::alias_ref<TracingStateCallback::javaobject> callback);
static void unsubscribeFromTracingStateChanges(
facebook::jni::alias_ref<PerformanceTracerCxxInterop> jthis,
jint subscriptionId);
static void registerNatives();
};
} // namespace facebook::react
@@ -53,14 +53,6 @@ import UIKit
containerViewModel.saturationAmount = CGFloat(saturation.floatValue)
}
@objc public func updateContrast(_ contrast: NSNumber) {
containerViewModel.contrastAmount = CGFloat(contrast.floatValue)
}
@objc public func updateHueRotate(_ degrees: NSNumber) {
containerViewModel.hueRotationDegrees = CGFloat(degrees.floatValue)
}
@objc public func updateLayout(withBounds bounds: CGRect) {
hostingController?.view.frame = bounds
containerViewModel.contentView?.frame = bounds
@@ -74,8 +66,6 @@ import UIKit
containerViewModel.shadowY = 0
containerViewModel.shadowColor = Color.clear
containerViewModel.saturationAmount = 1
containerViewModel.contrastAmount = 1
containerViewModel.hueRotationDegrees = 0
}
}
@@ -95,12 +85,6 @@ class ContainerViewModel: ObservableObject {
// saturation filter properties
@Published var saturationAmount: CGFloat = 1
// contrast filter properties
@Published var contrastAmount: CGFloat = 1
// hue-rotate filter properties
@Published var hueRotationDegrees: CGFloat = 0
@Published var contentView: UIView?
}
@@ -114,8 +98,6 @@ struct SwiftUIContainerView: View {
.grayscale(viewModel.grayscale)
.shadow(color: viewModel.shadowColor, radius: viewModel.shadowRadius, x: viewModel.shadowX, y: viewModel.shadowY)
.saturation(viewModel.saturationAmount)
.contrast(viewModel.contrastAmount)
.hueRotation(.degrees(viewModel.hueRotationDegrees))
}
}
}
@@ -17,8 +17,6 @@ NS_ASSUME_NONNULL_BEGIN
- (void)updateGrayscale:(NSNumber *)grayscale;
- (void)updateDropShadow:(NSNumber *)standardDeviation x:(NSNumber *)x y:(NSNumber *)y color:(UIColor *)color;
- (void)updateSaturation:(NSNumber *)saturation;
- (void)updateContrast:(NSNumber *)contrast;
- (void)updateHueRotate:(NSNumber *)degrees;
- (void)updateContentView:(UIView *)view;
- (UIView *_Nullable)hostingView;
- (void)resetStyles;
@@ -58,16 +58,6 @@
[self.swiftContainerView updateSaturation:saturation];
}
- (void)updateContrast:(NSNumber *)contrast
{
[self.swiftContainerView updateContrast:contrast];
}
- (void)updateHueRotate:(NSNumber *)degrees
{
[self.swiftContainerView updateHueRotate:degrees];
}
- (void)updateDropShadow:(NSNumber *)standardDeviation x:(NSNumber *)x y:(NSNumber *)y color:(UIColor *)color
{
[self.swiftContainerView updateDropShadowWithStandardDeviation:standardDeviation x:x y:y color:color];
@@ -1523,7 +1523,6 @@ jsi::Value JSCRuntime::createValue(JSValueRef value) const {
}
case kJSTypeSymbol:
return jsi::Value(createSymbol(value));
case kJSTypeBigInt:
default:
// WHAT ARE YOU
abort();
@@ -206,9 +206,6 @@ std::shared_ptr<HostTarget> HostTarget::create(
VoidExecutor executor) {
std::shared_ptr<HostTarget> hostTarget{new HostTarget(delegate)};
hostTarget->setExecutor(std::move(executor));
if (InspectorFlags::getInstance().getPerfIssuesEnabled()) {
hostTarget->installPerfIssuesBinding();
}
return hostTarget;
}
@@ -292,17 +289,6 @@ void HostTarget::sendCommand(HostCommand command) {
});
}
void HostTarget::installPerfIssuesBinding() {
perfMonitorUpdateHandler_ =
std::make_unique<PerfMonitorUpdateHandler>(delegate_);
perfMetricsBinding_ = std::make_unique<HostRuntimeBinding>(
*this, // Used immediately
"__react_native_perf_issues_reporter",
[this](const std::string& message) {
perfMonitorUpdateHandler_->handlePerfIssueAdded(message);
});
}
HostTargetController::HostTargetController(HostTarget& target)
: target_(target) {}
@@ -12,7 +12,6 @@
#include "InspectorInterfaces.h"
#include "InstanceTarget.h"
#include "NetworkIOAgent.h"
#include "PerfMonitorV2.h"
#include "ScopedExecutor.h"
#include "WeakList.h"
@@ -127,12 +126,6 @@ class HostTargetDelegate : public LoadNetworkResourceDelegate {
*/
virtual void onSetPausedInDebuggerMessage(const OverlaySetPausedInDebuggerMessageRequest &request) = 0;
/**
* [Experimental] Called when the runtime has new data for the V2 Perf
* Monitor overlay. This is called on the inspector thread.
*/
virtual void unstable_onPerfIssueAdded(const PerfIssuePayload & /*issue*/) {}
/**
* Called by NetworkIOAgent on handling a `Network.loadNetworkResource` CDP
* request. Platform implementations should override this to perform a
@@ -173,13 +166,6 @@ class HostTargetController final {
bool hasInstance() const;
/**
* [Experimental] Install a runtime binding subscribing to new Performance
* Issues, which we broadcast to the V2 Perf Monitor overlay via
* \ref HostTargetDelegate::unstable_onPerfIssueAdded.
*/
void installPerfIssuesBinding();
/**
* Increments the target's pause overlay counter. The counter represents the
* exact number of Agents that have (concurrently) requested the pause
@@ -339,7 +325,6 @@ class JSINSPECTOR_EXPORT HostTarget : public EnableExecutorFromThis<HostTarget>
std::shared_ptr<ExecutionContextManager> executionContextManager_;
std::shared_ptr<InstanceTarget> currentInstance_{nullptr};
std::unique_ptr<HostCommandSender> commandSender_;
std::unique_ptr<PerfMonitorUpdateHandler> perfMonitorUpdateHandler_;
std::unique_ptr<HostRuntimeBinding> perfMetricsBinding_;
/**
@@ -360,13 +345,6 @@ class JSINSPECTOR_EXPORT HostTarget : public EnableExecutorFromThis<HostTarget>
return currentInstance_ != nullptr;
}
/**
* [Experimental] Install a runtime binding subscribing to new Peformance
* Issues, which we broadcast to the V2 Perf Monitor overlay via
* \ref HostTargetDelegate::unstable_onPerfMonitorUpdate.
*/
void installPerfIssuesBinding();
// Necessary to allow HostAgent to access HostTarget's internals in a
// controlled way (i.e. only HostTargetController gets friend access, while
// HostAgent itself doesn't).
@@ -33,10 +33,6 @@ bool InspectorFlags::getNetworkInspectionEnabled() const {
return loadFlagsAndAssertUnchanged().networkInspectionEnabled;
}
bool InspectorFlags::getPerfIssuesEnabled() const {
return loadFlagsAndAssertUnchanged().perfIssuesEnabled;
}
void InspectorFlags::dangerouslyResetFlags() {
*this = InspectorFlags{};
}
@@ -63,7 +59,6 @@ const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged()
.networkInspectionEnabled =
ReactNativeFeatureFlags::enableBridgelessArchitecture() &&
ReactNativeFeatureFlags::fuseboxNetworkInspectionEnabled(),
.perfIssuesEnabled = ReactNativeFeatureFlags::perfIssuesEnabled(),
};
if (cachedValues_.has_value() && !inconsistentFlagsStateLogged_) {
@@ -35,11 +35,6 @@ class InspectorFlags {
*/
bool getNetworkInspectionEnabled() const;
/**
* Flag determining if the V2 in-app Performance Monitor is enabled.
*/
bool getPerfIssuesEnabled() const;
/**
* Forcibly disable the main `getFuseboxEnabled()` flag. This should ONLY be
* used by `ReactInstanceIntegrationTest`.
@@ -57,7 +52,6 @@ class InspectorFlags {
bool fuseboxEnabled;
bool isProfilingBuild;
bool networkInspectionEnabled;
bool perfIssuesEnabled;
bool operator==(const Values &) const = default;
};
@@ -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.
*/
#include "PerfMonitorV2.h"
#include "HostTarget.h"
#include <folly/json.h>
#include <react/timing/primitives.h>
namespace facebook::react::jsinspector_modern {
void PerfMonitorUpdateHandler::handlePerfIssueAdded(
const std::string& message) {
auto payload = folly::parseJson(message);
if (payload.isObject()) {
delegate_.unstable_onPerfIssueAdded(
PerfIssuePayload{
.name = payload["name"].asString(),
.severity = payload["severity"].asString(),
});
}
}
} // namespace facebook::react::jsinspector_modern
@@ -1,38 +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.
*/
#pragma once
#include <string>
namespace facebook::react::jsinspector_modern {
class HostTargetDelegate;
struct PerfIssuePayload {
std::string name;
std::string severity;
};
/**
* [Experimental] Utility to handle performance metrics updates received from
* the runtime and forward update events to the V2 Perf Monitor UI.
*/
class PerfMonitorUpdateHandler {
public:
explicit PerfMonitorUpdateHandler(HostTargetDelegate &delegate) : delegate_(delegate) {}
/**
* Handle a new "__react_native_perf_issues_reporter" message.
*/
void handlePerfIssueAdded(const std::string &message);
private:
HostTargetDelegate &delegate_;
};
} // namespace facebook::react::jsinspector_modern
@@ -342,7 +342,10 @@ class JSINSPECTOR_EXPORT RuntimeTarget : public EnableExecutorFromThis<RuntimeTa
* sessions, or when the only Agent that had this domain enabled has
* disconnected.
*/
std::pair<bool, bool> processDomainChange(Domain domain, bool enabled, const RuntimeAgent &notifyingAgent);
std::pair<bool, bool> processDomainChange(
Domain domain,
bool enabled,
const RuntimeAgent& notifyingAgent);
/**
* Checks whether the given domain is enabled in at least one session
@@ -467,18 +467,9 @@ void consoleTimeStamp(
}
}
std::optional<folly::dynamic> detail;
if (performanceTracer.isTracing() && argumentsCount >= 7) {
const jsi::Value& detailArgument = arguments[6];
if (detailArgument.isObject()) {
detail =
tracing::getConsoleTimeStampDetailFromObject(runtime, detailArgument);
}
}
if (performanceTracer.isTracing()) {
performanceTracer.reportTimeStamp(
label, start, end, trackName, trackGroup, color, std::move(detail));
label, start, end, trackName, trackGroup, color);
}
if (ReactPerfettoLogger::isTracing()) {
@@ -18,7 +18,6 @@ target_include_directories(jsinspector_tracing PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(jsinspector_tracing
folly_runtime
jsi
jsinspector_network
oscompat
react_timing
@@ -1,22 +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 "ConsoleTimeStamp.h"
namespace facebook::react::jsinspector_modern::tracing {
std::optional<folly::dynamic> getConsoleTimeStampDetailFromObject(
jsi::Runtime& runtime,
const jsi::Value& detailValue) {
try {
return jsi::dynamicFromValue(runtime, detailValue);
} catch (jsi::JSIException&) {
return std::nullopt;
}
}
} // namespace facebook::react::jsinspector_modern::tracing
@@ -7,8 +7,6 @@
#pragma once
#include <jsi/JSIDynamic.h>
#include <jsi/jsi.h>
#include <react/timing/primitives.h>
#include <cassert>
@@ -98,6 +96,4 @@ inline std::optional<ConsoleTimeStampColor> getConsoleTimeStampColorFromString(c
}
};
std::optional<folly::dynamic> getConsoleTimeStampDetailFromObject(jsi::Runtime &runtime, const jsi::Value &detailValue);
}; // namespace facebook::react::jsinspector_modern::tracing
@@ -57,39 +57,26 @@ bool PerformanceTracer::startTracing(HighResDuration maxDuration) {
bool PerformanceTracer::startTracingImpl(
std::optional<HighResDuration> maxDuration) {
std::vector<TracingStateCallback> callbacksToNotify;
std::lock_guard lock(mutex_);
{
std::lock_guard lock(mutex_);
if (tracingAtomic_) {
return false;
}
tracingAtomic_ = true;
if (maxDuration && *maxDuration < MIN_VALUE_FOR_MAX_TRACE_DURATION_OPTION) {
throw std::invalid_argument("maxDuration should be at least 1 second");
}
currentTraceStartTime_ = HighResTimeStamp::now();
currentTraceMaxDuration_ = maxDuration;
for (const auto& [id, callback] : tracingStateCallbacks_) {
callbacksToNotify.push_back(callback);
}
if (tracingAtomic_) {
return false;
}
for (const auto& callback : callbacksToNotify) {
callback(true);
tracingAtomic_ = true;
if (maxDuration && *maxDuration < MIN_VALUE_FOR_MAX_TRACE_DURATION_OPTION) {
throw std::invalid_argument("maxDuration should be at least 1 second");
}
currentTraceStartTime_ = HighResTimeStamp::now();
currentTraceMaxDuration_ = maxDuration;
return true;
}
std::optional<std::vector<TraceEvent>> PerformanceTracer::stopTracing() {
std::vector<TraceEvent> events;
std::vector<TracingStateCallback> callbacksToNotify;
auto currentTraceEndTime = HighResTimeStamp::now();
@@ -100,21 +87,6 @@ std::optional<std::vector<TraceEvent>> PerformanceTracer::stopTracing() {
return std::nullopt;
}
// Collect callbacks before disabling tracing
for (const auto& [id, callback] : tracingStateCallbacks_) {
callbacksToNotify.push_back(callback);
}
}
// Notify callbacks while tracing is still enabled, so they can send final
// events
for (const auto& callback : callbacksToNotify) {
callback(false);
}
{
std::lock_guard lock(mutex_);
tracingAtomic_ = false;
performanceMeasureCount_ = 0;
@@ -157,7 +129,6 @@ std::optional<std::vector<TraceEvent>> PerformanceTracer::stopTracing() {
});
currentTraceMaxDuration_ = std::nullopt;
return events;
}
@@ -213,8 +184,7 @@ void PerformanceTracer::reportTimeStamp(
std::optional<ConsoleTimeStampEntry> end,
std::optional<std::string> trackName,
std::optional<std::string> trackGroup,
std::optional<ConsoleTimeStampColor> color,
std::optional<folly::dynamic> detail) {
std::optional<ConsoleTimeStampColor> color) {
if (!tracingAtomic_) {
return;
}
@@ -232,7 +202,6 @@ void PerformanceTracer::reportTimeStamp(
.trackName = std::move(trackName),
.trackGroup = std::move(trackGroup),
.color = std::move(color),
.detail = std::move(detail),
.threadId = getCurrentThreadId(),
});
}
@@ -653,13 +622,6 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
if (event.color) {
data["color"] = consoleTimeStampColorToString(*event.color);
}
if (event.detail) {
folly::dynamic devtoolsDetail = folly::dynamic::object();
for (const auto& [key, value] : event.detail->items()) {
devtoolsDetail[key] = value;
}
data["devtools"] = folly::toJson(devtoolsDetail);
}
events.emplace_back(
TraceEvent{
@@ -741,18 +703,4 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
std::move(event));
}
uint32_t PerformanceTracer::subscribeToTracingStateChanges(
TracingStateCallback callback) {
std::lock_guard lock(mutex_);
uint32_t subscriptionId = nextCallbackId_++;
tracingStateCallbacks_[subscriptionId] = std::move(callback);
return subscriptionId;
}
void PerformanceTracer::unsubscribeFromTracingStateChanges(
uint32_t subscriptionId) {
std::lock_guard lock(mutex_);
tracingStateCallbacks_.erase(subscriptionId);
}
} // namespace facebook::react::jsinspector_modern::tracing
@@ -15,7 +15,6 @@
#include <folly/dynamic.h>
#include <atomic>
#include <functional>
#include <map>
#include <mutex>
#include <optional>
@@ -96,8 +95,7 @@ class PerformanceTracer {
std::optional<ConsoleTimeStampEntry> end = std::nullopt,
std::optional<std::string> trackName = std::nullopt,
std::optional<std::string> trackGroup = std::nullopt,
std::optional<ConsoleTimeStampColor> color = std::nullopt,
std::optional<folly::dynamic> detail = std::nullopt);
std::optional<ConsoleTimeStampColor> color = std::nullopt);
/**
* Record an Event Loop tick, which will be represented as an Event Loop task
@@ -184,29 +182,6 @@ class PerformanceTracer {
HighResTimeStamp chunkTimestamp,
TraceEventProfileChunk &&traceEventProfileChunk);
/**
* Callback function type for tracing state changes.
* @param isTracing true if tracing has started, false if tracing has stopped
*/
using TracingStateCallback = std::function<void(bool isTracing)>;
/**
* Subscribe to tracing state changes (start/stop events).
* Tracing start state is reported after tracing has started, so callbacks can
* report events immediately.
* Tracing stop state is reported before tracing has stopped, so callbacks
* can report final events.
* @param callback Function to call when tracing starts or stops
* @return A unique identifier for the subscription that can be used to unsubscribe
*/
uint32_t subscribeToTracingStateChanges(TracingStateCallback callback);
/**
* Unsubscribe from tracing state changes.
* @param subscriptionId The identifier returned from subscribeToTracingStateChanges
*/
void unsubscribeFromTracingStateChanges(uint32_t subscriptionId);
private:
PerformanceTracer();
PerformanceTracer(const PerformanceTracer &) = delete;
@@ -253,7 +228,6 @@ class PerformanceTracer {
std::optional<std::string> trackName;
std::optional<std::string> trackGroup;
std::optional<ConsoleTimeStampColor> color;
std::optional<folly::dynamic> detail;
ThreadId threadId;
HighResTimeStamp createdAt = HighResTimeStamp::now();
};
@@ -342,10 +316,6 @@ class PerformanceTracer {
*/
std::mutex mutex_;
// Callback management
std::map<uint32_t, TracingStateCallback> tracingStateCallbacks_;
uint32_t nextCallbackId_{0};
bool startTracingImpl(std::optional<HighResDuration> maxDuration = std::nullopt);
std::vector<TraceEvent> collectEventsAndClearBuffers(HighResTimeStamp currentTraceEndTime);
@@ -44,7 +44,6 @@ Pod::Spec.new do |s|
resolve_use_frameworks(s, header_mappings_dir: "../..", module_name: module_name)
add_dependency(s, "React-jsinspectornetwork", :framework_name => 'jsinspector_modernnetwork')
s.dependency "React-jsi"
s.dependency "React-oscompat"
s.dependency "React-timing"
@@ -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<<5d596cc470e66861d7c1b2ffbb15b268>>
* @generated SignedSource<<0554340092d31b5431e201f570599ab5>>
*/
/**
@@ -146,10 +146,6 @@ bool ReactNativeFeatureFlags::enableInteropViewManagerClassLookUpOptimizationIOS
return getAccessor().enableInteropViewManagerClassLookUpOptimizationIOS();
}
bool ReactNativeFeatureFlags::enableKeyEvents() {
return getAccessor().enableKeyEvents();
}
bool ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid() {
return getAccessor().enableLayoutAnimationsOnAndroid();
}
@@ -214,10 +210,6 @@ bool ReactNativeFeatureFlags::enableViewRecyclingForView() {
return getAccessor().enableViewRecyclingForView();
}
bool ReactNativeFeatureFlags::enableVirtualViewClippingWithoutScrollViewClipping() {
return getAccessor().enableVirtualViewClippingWithoutScrollViewClipping();
}
bool ReactNativeFeatureFlags::enableVirtualViewContainerStateExperimental() {
return getAccessor().enableVirtualViewContainerStateExperimental();
}
@@ -258,10 +250,6 @@ bool ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid()
return getAccessor().overrideBySynchronousMountPropsAtMountingAndroid();
}
bool ReactNativeFeatureFlags::perfIssuesEnabled() {
return getAccessor().perfIssuesEnabled();
}
bool ReactNativeFeatureFlags::perfMonitorV2Enabled() {
return getAccessor().perfMonitorV2Enabled();
}
@@ -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<<41492e85e1feeb20d2e3e60b6cc6cbe7>>
* @generated SignedSource<<98a77cdecfd3e6d42f03b2b4ba3d8c88>>
*/
/**
@@ -189,11 +189,6 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableInteropViewManagerClassLookUpOptimizationIOS();
/**
* Enables key up/down/press events to be sent to JS from components
*/
RN_EXPORT static bool enableKeyEvents();
/**
* When enabled, LayoutAnimations API will animate state changes on Android.
*/
@@ -274,11 +269,6 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableViewRecyclingForView();
/**
* Set clipping to drawingRect of ScrollView.
*/
RN_EXPORT static bool enableVirtualViewClippingWithoutScrollViewClipping();
/**
* Enables the experimental version of `VirtualViewContainerState`.
*/
@@ -329,11 +319,6 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool overrideBySynchronousMountPropsAtMountingAndroid();
/**
* Enable reporting Performance Issues (`detail.rnPerfIssue`). Displayed in the V2 Performance Monitor and the "Performance Issues" sub-panel in DevTools.
*/
RN_EXPORT static bool perfIssuesEnabled();
/**
* Enable the V2 in-app Performance Monitor. This flag is global and should not be changed across React Host lifetimes.
*/
@@ -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<<cf152ea3a4e9635a71d2794a3139dadb>>
* @generated SignedSource<<4eba223705b2d24f0360c6da1239b9a0>>
*/
/**
@@ -569,24 +569,6 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableKeyEvents() {
auto flagValue = enableKeyEvents_.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(30, "enableKeyEvents");
flagValue = currentProvider_->enableKeyEvents();
enableKeyEvents_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() {
auto flagValue = enableLayoutAnimationsOnAndroid_.load();
@@ -596,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(31, "enableLayoutAnimationsOnAndroid");
markFlagAsAccessed(30, "enableLayoutAnimationsOnAndroid");
flagValue = currentProvider_->enableLayoutAnimationsOnAndroid();
enableLayoutAnimationsOnAndroid_ = flagValue;
@@ -614,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(32, "enableLayoutAnimationsOnIOS");
markFlagAsAccessed(31, "enableLayoutAnimationsOnIOS");
flagValue = currentProvider_->enableLayoutAnimationsOnIOS();
enableLayoutAnimationsOnIOS_ = flagValue;
@@ -632,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueCoordinatorOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(33, "enableMainQueueCoordinatorOnIOS");
markFlagAsAccessed(32, "enableMainQueueCoordinatorOnIOS");
flagValue = currentProvider_->enableMainQueueCoordinatorOnIOS();
enableMainQueueCoordinatorOnIOS_ = flagValue;
@@ -650,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS()
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(34, "enableModuleArgumentNSNullConversionIOS");
markFlagAsAccessed(33, "enableModuleArgumentNSNullConversionIOS");
flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS();
enableModuleArgumentNSNullConversionIOS_ = flagValue;
@@ -668,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(35, "enableNativeCSSParsing");
markFlagAsAccessed(34, "enableNativeCSSParsing");
flagValue = currentProvider_->enableNativeCSSParsing();
enableNativeCSSParsing_ = flagValue;
@@ -686,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(36, "enableNetworkEventReporting");
markFlagAsAccessed(35, "enableNetworkEventReporting");
flagValue = currentProvider_->enableNetworkEventReporting();
enableNetworkEventReporting_ = flagValue;
@@ -704,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(37, "enablePreparedTextLayout");
markFlagAsAccessed(36, "enablePreparedTextLayout");
flagValue = currentProvider_->enablePreparedTextLayout();
enablePreparedTextLayout_ = flagValue;
@@ -722,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(38, "enablePropsUpdateReconciliationAndroid");
markFlagAsAccessed(37, "enablePropsUpdateReconciliationAndroid");
flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid();
enablePropsUpdateReconciliationAndroid_ = flagValue;
@@ -740,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResourceTimingAPI() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(39, "enableResourceTimingAPI");
markFlagAsAccessed(38, "enableResourceTimingAPI");
flagValue = currentProvider_->enableResourceTimingAPI();
enableResourceTimingAPI_ = flagValue;
@@ -758,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSwiftUIBasedFilters() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(40, "enableSwiftUIBasedFilters");
markFlagAsAccessed(39, "enableSwiftUIBasedFilters");
flagValue = currentProvider_->enableSwiftUIBasedFilters();
enableSwiftUIBasedFilters_ = flagValue;
@@ -776,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(41, "enableViewCulling");
markFlagAsAccessed(40, "enableViewCulling");
flagValue = currentProvider_->enableViewCulling();
enableViewCulling_ = flagValue;
@@ -794,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(42, "enableViewRecycling");
markFlagAsAccessed(41, "enableViewRecycling");
flagValue = currentProvider_->enableViewRecycling();
enableViewRecycling_ = flagValue;
@@ -812,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForImage() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(43, "enableViewRecyclingForImage");
markFlagAsAccessed(42, "enableViewRecyclingForImage");
flagValue = currentProvider_->enableViewRecyclingForImage();
enableViewRecyclingForImage_ = flagValue;
@@ -830,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(44, "enableViewRecyclingForScrollView");
markFlagAsAccessed(43, "enableViewRecyclingForScrollView");
flagValue = currentProvider_->enableViewRecyclingForScrollView();
enableViewRecyclingForScrollView_ = flagValue;
@@ -848,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(45, "enableViewRecyclingForText");
markFlagAsAccessed(44, "enableViewRecyclingForText");
flagValue = currentProvider_->enableViewRecyclingForText();
enableViewRecyclingForText_ = flagValue;
@@ -866,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(46, "enableViewRecyclingForView");
markFlagAsAccessed(45, "enableViewRecyclingForView");
flagValue = currentProvider_->enableViewRecyclingForView();
enableViewRecyclingForView_ = flagValue;
@@ -875,24 +857,6 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() {
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableVirtualViewClippingWithoutScrollViewClipping() {
auto flagValue = enableVirtualViewClippingWithoutScrollViewClipping_.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(47, "enableVirtualViewClippingWithoutScrollViewClipping");
flagValue = currentProvider_->enableVirtualViewClippingWithoutScrollViewClipping();
enableVirtualViewClippingWithoutScrollViewClipping_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::enableVirtualViewContainerStateExperimental() {
auto flagValue = enableVirtualViewContainerStateExperimental_.load();
@@ -902,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewContainerStateExperimenta
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(48, "enableVirtualViewContainerStateExperimental");
markFlagAsAccessed(46, "enableVirtualViewContainerStateExperimental");
flagValue = currentProvider_->enableVirtualViewContainerStateExperimental();
enableVirtualViewContainerStateExperimental_ = flagValue;
@@ -920,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(49, "enableVirtualViewDebugFeatures");
markFlagAsAccessed(47, "enableVirtualViewDebugFeatures");
flagValue = currentProvider_->enableVirtualViewDebugFeatures();
enableVirtualViewDebugFeatures_ = flagValue;
@@ -938,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewRenderState() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(50, "enableVirtualViewRenderState");
markFlagAsAccessed(48, "enableVirtualViewRenderState");
flagValue = currentProvider_->enableVirtualViewRenderState();
enableVirtualViewRenderState_ = flagValue;
@@ -956,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(51, "enableVirtualViewWindowFocusDetection");
markFlagAsAccessed(49, "enableVirtualViewWindowFocusDetection");
flagValue = currentProvider_->enableVirtualViewWindowFocusDetection();
enableVirtualViewWindowFocusDetection_ = flagValue;
@@ -974,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::enableWebPerformanceAPIsByDefault() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(52, "enableWebPerformanceAPIsByDefault");
markFlagAsAccessed(50, "enableWebPerformanceAPIsByDefault");
flagValue = currentProvider_->enableWebPerformanceAPIsByDefault();
enableWebPerformanceAPIsByDefault_ = flagValue;
@@ -992,7 +956,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(53, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
markFlagAsAccessed(51, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
@@ -1010,7 +974,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(54, "fuseboxEnabledRelease");
markFlagAsAccessed(52, "fuseboxEnabledRelease");
flagValue = currentProvider_->fuseboxEnabledRelease();
fuseboxEnabledRelease_ = flagValue;
@@ -1028,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(55, "fuseboxNetworkInspectionEnabled");
markFlagAsAccessed(53, "fuseboxNetworkInspectionEnabled");
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
fuseboxNetworkInspectionEnabled_ = flagValue;
@@ -1046,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(56, "hideOffscreenVirtualViewsOnIOS");
markFlagAsAccessed(54, "hideOffscreenVirtualViewsOnIOS");
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
hideOffscreenVirtualViewsOnIOS_ = flagValue;
@@ -1064,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(57, "overrideBySynchronousMountPropsAtMountingAndroid");
markFlagAsAccessed(55, "overrideBySynchronousMountPropsAtMountingAndroid");
flagValue = currentProvider_->overrideBySynchronousMountPropsAtMountingAndroid();
overrideBySynchronousMountPropsAtMountingAndroid_ = flagValue;
@@ -1073,24 +1037,6 @@ bool ReactNativeFeatureFlagsAccessor::overrideBySynchronousMountPropsAtMountingA
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::perfIssuesEnabled() {
auto flagValue = perfIssuesEnabled_.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(58, "perfIssuesEnabled");
flagValue = currentProvider_->perfIssuesEnabled();
perfIssuesEnabled_ = flagValue;
}
return flagValue.value();
}
bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
auto flagValue = perfMonitorV2Enabled_.load();
@@ -1100,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(59, "perfMonitorV2Enabled");
markFlagAsAccessed(56, "perfMonitorV2Enabled");
flagValue = currentProvider_->perfMonitorV2Enabled();
perfMonitorV2Enabled_ = flagValue;
@@ -1118,7 +1064,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(60, "preparedTextCacheSize");
markFlagAsAccessed(57, "preparedTextCacheSize");
flagValue = currentProvider_->preparedTextCacheSize();
preparedTextCacheSize_ = flagValue;
@@ -1136,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(61, "preventShadowTreeCommitExhaustion");
markFlagAsAccessed(58, "preventShadowTreeCommitExhaustion");
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
preventShadowTreeCommitExhaustion_ = flagValue;
@@ -1154,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(62, "shouldPressibilityUseW3CPointerEventsForHover");
markFlagAsAccessed(59, "shouldPressibilityUseW3CPointerEventsForHover");
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
@@ -1172,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldTriggerResponderTransferOnScrollAndr
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(63, "shouldTriggerResponderTransferOnScrollAndroid");
markFlagAsAccessed(60, "shouldTriggerResponderTransferOnScrollAndroid");
flagValue = currentProvider_->shouldTriggerResponderTransferOnScrollAndroid();
shouldTriggerResponderTransferOnScrollAndroid_ = flagValue;
@@ -1190,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause()
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(64, "skipActivityIdentityAssertionOnHostPause");
markFlagAsAccessed(61, "skipActivityIdentityAssertionOnHostPause");
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
skipActivityIdentityAssertionOnHostPause_ = flagValue;
@@ -1208,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(65, "sweepActiveTouchOnChildNativeGesturesAndroid");
markFlagAsAccessed(62, "sweepActiveTouchOnChildNativeGesturesAndroid");
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
@@ -1226,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(66, "traceTurboModulePromiseRejectionsOnAndroid");
markFlagAsAccessed(63, "traceTurboModulePromiseRejectionsOnAndroid");
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
@@ -1244,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(67, "updateRuntimeShadowNodeReferencesOnCommit");
markFlagAsAccessed(64, "updateRuntimeShadowNodeReferencesOnCommit");
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
@@ -1262,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(68, "useAlwaysAvailableJSErrorHandling");
markFlagAsAccessed(65, "useAlwaysAvailableJSErrorHandling");
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
useAlwaysAvailableJSErrorHandling_ = flagValue;
@@ -1280,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(69, "useFabricInterop");
markFlagAsAccessed(66, "useFabricInterop");
flagValue = currentProvider_->useFabricInterop();
useFabricInterop_ = flagValue;
@@ -1298,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(70, "useNativeEqualsInNativeReadableArrayAndroid");
markFlagAsAccessed(67, "useNativeEqualsInNativeReadableArrayAndroid");
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
@@ -1316,7 +1262,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(71, "useNativeTransformHelperAndroid");
markFlagAsAccessed(68, "useNativeTransformHelperAndroid");
flagValue = currentProvider_->useNativeTransformHelperAndroid();
useNativeTransformHelperAndroid_ = flagValue;
@@ -1334,7 +1280,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(72, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(69, "useNativeViewConfigsInBridgelessMode");
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
@@ -1352,7 +1298,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(73, "useOptimizedEventBatchingOnAndroid");
markFlagAsAccessed(70, "useOptimizedEventBatchingOnAndroid");
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
useOptimizedEventBatchingOnAndroid_ = flagValue;
@@ -1370,7 +1316,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(74, "useRawPropsJsiValue");
markFlagAsAccessed(71, "useRawPropsJsiValue");
flagValue = currentProvider_->useRawPropsJsiValue();
useRawPropsJsiValue_ = flagValue;
@@ -1388,7 +1334,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(75, "useShadowNodeStateOnClone");
markFlagAsAccessed(72, "useShadowNodeStateOnClone");
flagValue = currentProvider_->useShadowNodeStateOnClone();
useShadowNodeStateOnClone_ = flagValue;
@@ -1406,7 +1352,7 @@ bool ReactNativeFeatureFlagsAccessor::useSharedAnimatedBackend() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(76, "useSharedAnimatedBackend");
markFlagAsAccessed(73, "useSharedAnimatedBackend");
flagValue = currentProvider_->useSharedAnimatedBackend();
useSharedAnimatedBackend_ = flagValue;
@@ -1424,7 +1370,7 @@ bool ReactNativeFeatureFlagsAccessor::useTraitHiddenOnAndroid() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(77, "useTraitHiddenOnAndroid");
markFlagAsAccessed(74, "useTraitHiddenOnAndroid");
flagValue = currentProvider_->useTraitHiddenOnAndroid();
useTraitHiddenOnAndroid_ = flagValue;
@@ -1442,7 +1388,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(78, "useTurboModuleInterop");
markFlagAsAccessed(75, "useTurboModuleInterop");
flagValue = currentProvider_->useTurboModuleInterop();
useTurboModuleInterop_ = flagValue;
@@ -1460,7 +1406,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(79, "useTurboModules");
markFlagAsAccessed(76, "useTurboModules");
flagValue = currentProvider_->useTurboModules();
useTurboModules_ = flagValue;
@@ -1478,7 +1424,7 @@ double ReactNativeFeatureFlagsAccessor::viewCullingOutsetRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(80, "viewCullingOutsetRatio");
markFlagAsAccessed(77, "viewCullingOutsetRatio");
flagValue = currentProvider_->viewCullingOutsetRatio();
viewCullingOutsetRatio_ = flagValue;
@@ -1496,7 +1442,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(81, "virtualViewHysteresisRatio");
markFlagAsAccessed(78, "virtualViewHysteresisRatio");
flagValue = currentProvider_->virtualViewHysteresisRatio();
virtualViewHysteresisRatio_ = flagValue;
@@ -1514,7 +1460,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.
markFlagAsAccessed(82, "virtualViewPrerenderRatio");
markFlagAsAccessed(79, "virtualViewPrerenderRatio");
flagValue = currentProvider_->virtualViewPrerenderRatio();
virtualViewPrerenderRatio_ = flagValue;
@@ -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<<e7e8d311c0d1cca4e28bee7ddcf5065c>>
* @generated SignedSource<<de758de45c903f7bf895bf03e049a20a>>
*/
/**
@@ -62,7 +62,6 @@ class ReactNativeFeatureFlagsAccessor {
bool enableImmediateUpdateModeForContentOffsetChanges();
bool enableImperativeFocus();
bool enableInteropViewManagerClassLookUpOptimizationIOS();
bool enableKeyEvents();
bool enableLayoutAnimationsOnAndroid();
bool enableLayoutAnimationsOnIOS();
bool enableMainQueueCoordinatorOnIOS();
@@ -79,7 +78,6 @@ class ReactNativeFeatureFlagsAccessor {
bool enableViewRecyclingForScrollView();
bool enableViewRecyclingForText();
bool enableViewRecyclingForView();
bool enableVirtualViewClippingWithoutScrollViewClipping();
bool enableVirtualViewContainerStateExperimental();
bool enableVirtualViewDebugFeatures();
bool enableVirtualViewRenderState();
@@ -90,7 +88,6 @@ class ReactNativeFeatureFlagsAccessor {
bool fuseboxNetworkInspectionEnabled();
bool hideOffscreenVirtualViewsOnIOS();
bool overrideBySynchronousMountPropsAtMountingAndroid();
bool perfIssuesEnabled();
bool perfMonitorV2Enabled();
double preparedTextCacheSize();
bool preventShadowTreeCommitExhaustion();
@@ -126,7 +123,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;
std::array<std::atomic<const char*>, 83> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 80> accessedFeatureFlags_;
std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
@@ -158,7 +155,6 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableImmediateUpdateModeForContentOffsetChanges_;
std::atomic<std::optional<bool>> enableImperativeFocus_;
std::atomic<std::optional<bool>> enableInteropViewManagerClassLookUpOptimizationIOS_;
std::atomic<std::optional<bool>> enableKeyEvents_;
std::atomic<std::optional<bool>> enableLayoutAnimationsOnAndroid_;
std::atomic<std::optional<bool>> enableLayoutAnimationsOnIOS_;
std::atomic<std::optional<bool>> enableMainQueueCoordinatorOnIOS_;
@@ -175,7 +171,6 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> enableViewRecyclingForScrollView_;
std::atomic<std::optional<bool>> enableViewRecyclingForText_;
std::atomic<std::optional<bool>> enableViewRecyclingForView_;
std::atomic<std::optional<bool>> enableVirtualViewClippingWithoutScrollViewClipping_;
std::atomic<std::optional<bool>> enableVirtualViewContainerStateExperimental_;
std::atomic<std::optional<bool>> enableVirtualViewDebugFeatures_;
std::atomic<std::optional<bool>> enableVirtualViewRenderState_;
@@ -186,7 +181,6 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> fuseboxNetworkInspectionEnabled_;
std::atomic<std::optional<bool>> hideOffscreenVirtualViewsOnIOS_;
std::atomic<std::optional<bool>> overrideBySynchronousMountPropsAtMountingAndroid_;
std::atomic<std::optional<bool>> perfIssuesEnabled_;
std::atomic<std::optional<bool>> perfMonitorV2Enabled_;
std::atomic<std::optional<double>> preparedTextCacheSize_;
std::atomic<std::optional<bool>> preventShadowTreeCommitExhaustion_;
@@ -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<<a0a1898f3a4c14179bd03d5dbe97adfa>>
* @generated SignedSource<<21049b33fc72200390c6dd6d0ca27c19>>
*/
/**
@@ -147,10 +147,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool enableKeyEvents() override {
return false;
}
bool enableLayoutAnimationsOnAndroid() override {
return false;
}
@@ -215,10 +211,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return true;
}
bool enableVirtualViewClippingWithoutScrollViewClipping() override {
return true;
}
bool enableVirtualViewContainerStateExperimental() override {
return false;
}
@@ -236,7 +228,7 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
}
bool enableWebPerformanceAPIsByDefault() override {
return true;
return false;
}
bool fixMappingOfEventPrioritiesBetweenFabricAndReact() override {
@@ -259,10 +251,6 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
return false;
}
bool perfIssuesEnabled() override {
return false;
}
bool perfMonitorV2Enabled() override {
return false;
}
@@ -288,7 +276,7 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
}
bool sweepActiveTouchOnChildNativeGesturesAndroid() override {
return true;
return false;
}
bool traceTurboModulePromiseRejectionsOnAndroid() override {
@@ -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<<fc8f8541827a039fa5bc4a113e75fdf6>>
* @generated SignedSource<<cc71bfa62258ec91b00c4646441fa7fc>>
*/
/**
@@ -315,15 +315,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableInteropViewManagerClassLookUpOptimizationIOS();
}
bool enableKeyEvents() override {
auto value = values_["enableKeyEvents"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableKeyEvents();
}
bool enableLayoutAnimationsOnAndroid() override {
auto value = values_["enableLayoutAnimationsOnAndroid"];
if (!value.isNull()) {
@@ -468,15 +459,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::enableViewRecyclingForView();
}
bool enableVirtualViewClippingWithoutScrollViewClipping() override {
auto value = values_["enableVirtualViewClippingWithoutScrollViewClipping"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::enableVirtualViewClippingWithoutScrollViewClipping();
}
bool enableVirtualViewContainerStateExperimental() override {
auto value = values_["enableVirtualViewContainerStateExperimental"];
if (!value.isNull()) {
@@ -567,15 +549,6 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
return ReactNativeFeatureFlagsDefaults::overrideBySynchronousMountPropsAtMountingAndroid();
}
bool perfIssuesEnabled() override {
auto value = values_["perfIssuesEnabled"];
if (!value.isNull()) {
return value.getBool();
}
return ReactNativeFeatureFlagsDefaults::perfIssuesEnabled();
}
bool perfMonitorV2Enabled() override {
auto value = values_["perfMonitorV2Enabled"];
if (!value.isNull()) {
@@ -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<<db8626cf78a3ed226bbbe6bf20cc03a2>>
* @generated SignedSource<<32a03e199994c91c022013d7929bfea5>>
*/
/**
@@ -35,6 +35,10 @@ class ReactNativeFeatureFlagsOverridesOSSCanary : public ReactNativeFeatureFlags
return true;
}
bool enableWebPerformanceAPIsByDefault() override {
return true;
}
bool useNativeViewConfigsInBridgelessMode() override {
return true;
}
@@ -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<<5dcaab263795b1605da54dbbb617264f>>
* @generated SignedSource<<4b639e1b0211b16826bcfd1a19dd6658>>
*/
/**
@@ -55,7 +55,6 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enableImmediateUpdateModeForContentOffsetChanges() = 0;
virtual bool enableImperativeFocus() = 0;
virtual bool enableInteropViewManagerClassLookUpOptimizationIOS() = 0;
virtual bool enableKeyEvents() = 0;
virtual bool enableLayoutAnimationsOnAndroid() = 0;
virtual bool enableLayoutAnimationsOnIOS() = 0;
virtual bool enableMainQueueCoordinatorOnIOS() = 0;
@@ -72,7 +71,6 @@ class ReactNativeFeatureFlagsProvider {
virtual bool enableViewRecyclingForScrollView() = 0;
virtual bool enableViewRecyclingForText() = 0;
virtual bool enableViewRecyclingForView() = 0;
virtual bool enableVirtualViewClippingWithoutScrollViewClipping() = 0;
virtual bool enableVirtualViewContainerStateExperimental() = 0;
virtual bool enableVirtualViewDebugFeatures() = 0;
virtual bool enableVirtualViewRenderState() = 0;
@@ -83,7 +81,6 @@ class ReactNativeFeatureFlagsProvider {
virtual bool fuseboxNetworkInspectionEnabled() = 0;
virtual bool hideOffscreenVirtualViewsOnIOS() = 0;
virtual bool overrideBySynchronousMountPropsAtMountingAndroid() = 0;
virtual bool perfIssuesEnabled() = 0;
virtual bool perfMonitorV2Enabled() = 0;
virtual double preparedTextCacheSize() = 0;
virtual bool preventShadowTreeCommitExhaustion() = 0;
@@ -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<<6bd64914d0e2f0c727490a420496fbb0>>
* @generated SignedSource<<81b1cc08f5f6aa5f44c002eb7992811f>>
*/
/**
@@ -194,11 +194,6 @@ bool NativeReactNativeFeatureFlags::enableInteropViewManagerClassLookUpOptimizat
return ReactNativeFeatureFlags::enableInteropViewManagerClassLookUpOptimizationIOS();
}
bool NativeReactNativeFeatureFlags::enableKeyEvents(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableKeyEvents();
}
bool NativeReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableLayoutAnimationsOnAndroid();
@@ -279,11 +274,6 @@ bool NativeReactNativeFeatureFlags::enableViewRecyclingForView(
return ReactNativeFeatureFlags::enableViewRecyclingForView();
}
bool NativeReactNativeFeatureFlags::enableVirtualViewClippingWithoutScrollViewClipping(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableVirtualViewClippingWithoutScrollViewClipping();
}
bool NativeReactNativeFeatureFlags::enableVirtualViewContainerStateExperimental(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::enableVirtualViewContainerStateExperimental();
@@ -334,11 +324,6 @@ bool NativeReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAnd
return ReactNativeFeatureFlags::overrideBySynchronousMountPropsAtMountingAndroid();
}
bool NativeReactNativeFeatureFlags::perfIssuesEnabled(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::perfIssuesEnabled();
}
bool NativeReactNativeFeatureFlags::perfMonitorV2Enabled(
jsi::Runtime& /*runtime*/) {
return ReactNativeFeatureFlags::perfMonitorV2Enabled();
@@ -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<<99624bd7682ad34476ac395e8acc43c7>>
* @generated SignedSource<<2ac15ead28cac3a969854f339d625dca>>
*/
/**
@@ -96,8 +96,6 @@ class NativeReactNativeFeatureFlags
bool enableInteropViewManagerClassLookUpOptimizationIOS(jsi::Runtime& runtime);
bool enableKeyEvents(jsi::Runtime& runtime);
bool enableLayoutAnimationsOnAndroid(jsi::Runtime& runtime);
bool enableLayoutAnimationsOnIOS(jsi::Runtime& runtime);
@@ -130,8 +128,6 @@ class NativeReactNativeFeatureFlags
bool enableViewRecyclingForView(jsi::Runtime& runtime);
bool enableVirtualViewClippingWithoutScrollViewClipping(jsi::Runtime& runtime);
bool enableVirtualViewContainerStateExperimental(jsi::Runtime& runtime);
bool enableVirtualViewDebugFeatures(jsi::Runtime& runtime);
@@ -152,8 +148,6 @@ class NativeReactNativeFeatureFlags
bool overrideBySynchronousMountPropsAtMountingAndroid(jsi::Runtime& runtime);
bool perfIssuesEnabled(jsi::Runtime& runtime);
bool perfMonitorV2Enabled(jsi::Runtime& runtime);
double preparedTextCacheSize(jsi::Runtime& runtime);
@@ -19,11 +19,11 @@ namespace facebook::react {
* [Experimental] Reports CDP interaction events via the
* "__chromium_devtools_metrics_reporter" runtime binding.
*
* This populates the Interaction to Next Paint (INP) live metric in React
* Native DevTools. Events are reported immediately and do not require an
* active CDP Tracing session.
* This populates the Interaction to Next Paint (INP) live metric in Chrome
* DevTools and the V2 Perf Monitor. Events are reported immediately and do
* not require an active CDP Tracing session.
*/
class CdpMetricsReporter : public PerformanceEntryReporterEventListener {
class CdpMetricsReporter : public PerformanceEntryReporterEventTimingListener {
public:
explicit CdpMetricsReporter(RuntimeExecutor runtimeExecutor);
@@ -1,60 +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 "CdpPerfIssuesReporter.h"
#include <folly/dynamic.h>
#include <folly/json.h>
#include <string_view>
namespace facebook::react {
namespace {
constexpr std::string_view issuesReporterName =
"__react_native_perf_issues_reporter";
} // namespace
CdpPerfIssuesReporter::CdpPerfIssuesReporter(RuntimeExecutor runtimeExecutor)
: runtimeExecutor_(std::move(runtimeExecutor)) {}
void CdpPerfIssuesReporter::onMeasureEntry(
const PerformanceMeasure& entry,
const std::optional<UserTimingDetailProvider>& detailProvider) {
std::optional<folly::dynamic> maybeDetail = nullptr;
if (detailProvider.has_value()) {
maybeDetail = (*detailProvider)();
}
if (!maybeDetail.has_value() || !maybeDetail->isObject()) {
return;
}
runtimeExecutor_([entry,
detail = std::move(*maybeDetail)](jsi::Runtime& runtime) {
auto global = runtime.global();
if (!global.hasProperty(runtime, issuesReporterName.data())) {
return;
}
if (detail.count("rnPerfIssue") != 0 && detail["rnPerfIssue"].isObject()) {
auto& perfIssue = detail["rnPerfIssue"];
if (perfIssue.count("name") != 0 && perfIssue.count("severity") != 0 &&
perfIssue.count("description") != 0) {
auto jsonString = folly::toJson(perfIssue);
auto jsiString = jsi::String::createFromUtf8(runtime, jsonString);
auto issuesReporter =
global.getPropertyAsFunction(runtime, issuesReporterName.data());
issuesReporter.call(runtime, jsiString);
}
}
});
}
} // namespace facebook::react
@@ -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.
*/
#pragma once
#include <ReactCommon/RuntimeExecutor.h>
#include <folly/dynamic.h>
#include <jsi/jsi.h>
#include <react/performance/timeline/PerformanceEntry.h>
#include <react/performance/timeline/PerformanceEntryReporterListeners.h>
#include <react/timing/primitives.h>
namespace facebook::react {
/**
* [Experimental] Reports new Performance Issues via the
* "__react_native_perf_issues_reporter" runtime binding.
*
* This populates the Perf Issues indicator in the V2 Perf Monitor. Events are
* reported immediately and do not require an active CDP Tracing session.
*/
class CdpPerfIssuesReporter : public PerformanceEntryReporterEventListener {
public:
explicit CdpPerfIssuesReporter(RuntimeExecutor runtimeExecutor);
void onMeasureEntry(const PerformanceMeasure &entry, const std::optional<UserTimingDetailProvider> &detailProvider)
override;
private:
const RuntimeExecutor runtimeExecutor_{};
};
} // namespace facebook::react
@@ -88,18 +88,19 @@ PerformanceEntryReporter::PerformanceEntryReporter()
#endif
}
void PerformanceEntryReporter::addEventListener(
PerformanceEntryReporterEventListener* listener) {
void PerformanceEntryReporter::addEventTimingListener(
PerformanceEntryReporterEventTimingListener* listener) {
std::unique_lock lock(listenersMutex_);
eventListeners_.push_back(listener);
eventTimingListeners_.push_back(listener);
}
void PerformanceEntryReporter::removeEventListener(
PerformanceEntryReporterEventListener* listener) {
void PerformanceEntryReporter::removeEventTimingListener(
PerformanceEntryReporterEventTimingListener* listener) {
std::unique_lock lock(listenersMutex_);
auto it = std::find(eventListeners_.begin(), eventListeners_.end(), listener);
if (it != eventListeners_.end()) {
eventListeners_.erase(it);
auto it = std::find(
eventTimingListeners_.begin(), eventTimingListeners_.end(), listener);
if (it != eventTimingListeners_.end()) {
eventTimingListeners_.erase(it);
}
}
@@ -207,13 +208,13 @@ void PerformanceEntryReporter::reportMeasure(
const std::string& name,
HighResTimeStamp startTime,
HighResDuration duration,
const std::optional<UserTimingDetailProvider>& detailProvider) {
UserTimingDetailProvider&& detailProvider) {
const auto entry = PerformanceMeasure{
{.name = std::string(name),
.startTime = startTime,
.duration = duration}};
traceMeasure(entry, detailProvider);
traceMeasure(entry, std::move(detailProvider));
// Add to buffers & notify observers
{
@@ -222,16 +223,6 @@ void PerformanceEntryReporter::reportMeasure(
}
observerRegistry_->queuePerformanceEntry(entry);
std::vector<PerformanceEntryReporterEventListener*> listenersCopy;
{
std::shared_lock lock(listenersMutex_);
listenersCopy = eventListeners_;
}
for (auto* listener : listenersCopy) {
listener->onMeasureEntry(entry, detailProvider);
}
}
void PerformanceEntryReporter::clearEventCounts() {
@@ -281,10 +272,10 @@ void PerformanceEntryReporter::reportEvent(
// TODO(T198982346): Log interaction events to jsinspector_modern
observerRegistry_->queuePerformanceEntry(entry);
std::vector<PerformanceEntryReporterEventListener*> listenersCopy;
std::vector<PerformanceEntryReporterEventTimingListener*> listenersCopy;
{
std::shared_lock lock(listenersMutex_);
listenersCopy = eventListeners_;
listenersCopy = eventTimingListeners_;
}
for (auto* listener : listenersCopy) {
@@ -363,13 +354,11 @@ void PerformanceEntryReporter::traceMark(
void PerformanceEntryReporter::traceMeasure(
const PerformanceMeasure& entry,
const std::optional<UserTimingDetailProvider>& detailProvider) const {
UserTimingDetailProvider&& detailProvider) const {
auto& performanceTracer =
jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (performanceTracer.isTracing() || ReactPerfettoLogger::isTracing()) {
auto detail = detailProvider && detailProvider.has_value()
? (*detailProvider)()
: nullptr;
auto detail = detailProvider != nullptr ? detailProvider() : nullptr;
if (ReactPerfettoLogger::isTracing()) {
ReactPerfettoLogger::measure(
@@ -59,8 +59,8 @@ class PerformanceEntryReporter {
void clearEntries(PerformanceEntryType entryType);
void clearEntries(PerformanceEntryType entryType, const std::string &entryName);
void addEventListener(PerformanceEntryReporterEventListener *listener);
void removeEventListener(PerformanceEntryReporterEventListener *listener);
void addEventTimingListener(PerformanceEntryReporterEventTimingListener *listener);
void removeEventTimingListener(PerformanceEntryReporterEventTimingListener *listener);
static std::vector<PerformanceEntryType> getSupportedEntryTypes();
@@ -84,7 +84,7 @@ class PerformanceEntryReporter {
const std::string &name,
HighResTimeStamp startTime,
HighResDuration duration,
const std::optional<UserTimingDetailProvider> &detailProvider = std::nullopt);
UserTimingDetailProvider &&detailProvider = nullptr);
void reportEvent(
const std::string &name,
@@ -123,7 +123,7 @@ class PerformanceEntryReporter {
std::unordered_map<std::string, uint32_t> eventCounts_;
mutable std::shared_mutex listenersMutex_;
std::vector<PerformanceEntryReporterEventListener *> eventListeners_{};
std::vector<PerformanceEntryReporterEventTimingListener *> eventTimingListeners_{};
const inline PerformanceEntryBuffer &getBuffer(PerformanceEntryType entryType) const
{
@@ -166,8 +166,7 @@ class PerformanceEntryReporter {
}
void traceMark(const PerformanceMark &entry, UserTimingDetailProvider &&detailProvider) const;
void traceMeasure(const PerformanceMeasure &entry, const std::optional<UserTimingDetailProvider> &detailProvider)
const;
void traceMeasure(const PerformanceMeasure &entry, UserTimingDetailProvider &&detailProvider) const;
void traceResourceTiming(
const PerformanceResourceTiming &entry,
const std::optional<std::string> &devtoolsRequestId,
@@ -14,17 +14,9 @@
namespace facebook::react {
using UserTimingDetailProvider = std::function<folly::dynamic()>;
class PerformanceEntryReporterEventListener {
class PerformanceEntryReporterEventTimingListener {
public:
virtual ~PerformanceEntryReporterEventListener() = default;
virtual void onMeasureEntry(
const PerformanceMeasure & /*entry*/,
const std::optional<UserTimingDetailProvider> & /*detailProvider*/)
{
}
virtual ~PerformanceEntryReporterEventTimingListener() = default;
virtual void onEventTimingEntry(const PerformanceEventTiming & /*entry*/) {}
};
@@ -196,8 +196,7 @@ TEST(PerformanceObserver, PerformanceObserverTestObserveTakeRecords) {
reporter->reportMeasure(
"off",
timeOrigin + HighResDuration::fromMilliseconds(10),
HighResDuration::fromMilliseconds(20),
std::nullopt);
HighResDuration::fromMilliseconds(20));
reporter->reportMark(
"test2", timeOrigin + HighResDuration::fromMilliseconds(20));
reporter->reportMark(
@@ -392,10 +391,7 @@ TEST(PerformanceObserver, PerformanceObserverTestMultiple) {
{.durationThreshold = HighResDuration::fromMilliseconds(80)});
reporter->reportMeasure(
"measure",
timeOrigin,
HighResDuration::fromMilliseconds(50),
std::nullopt);
"measure", timeOrigin, HighResDuration::fromMilliseconds(50));
reporter->reportEvent(
"event1",
timeOrigin,
@@ -74,13 +74,11 @@ NativeAnimatedNodesManager::NativeAnimatedNodesManager(
DirectManipulationCallback&& directManipulationCallback,
FabricCommitCallback&& fabricCommitCallback,
StartOnRenderCallback&& startOnRenderCallback,
StopOnRenderCallback&& stopOnRenderCallback,
FrameRateListenerCallback&& frameRateListenerCallback) noexcept
StopOnRenderCallback&& stopOnRenderCallback) noexcept
: directManipulationCallback_(std::move(directManipulationCallback)),
fabricCommitCallback_(std::move(fabricCommitCallback)),
startOnRenderCallback_(std::move(startOnRenderCallback)),
stopOnRenderCallback_(std::move(stopOnRenderCallback)),
frameRateListenerCallback_(std::move(frameRateListenerCallback)) {
stopOnRenderCallback_(std::move(stopOnRenderCallback)) {
if (!fabricCommitCallback_) {
LOG(WARNING)
<< "C++ Animated was setup without commit callback. This may lead to issue where buttons are not tappable when animation is driven by onScroll event.";
@@ -543,7 +541,7 @@ void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {
}
if (startOnRenderCallback_) {
startOnRenderCallback_([this]() { onRender(); }, isAsync);
startOnRenderCallback_(isAsync);
}
}
@@ -565,10 +563,6 @@ void NativeAnimatedNodesManager::stopRenderCallbackIfNeeded(
if (stopOnRenderCallback_) {
stopOnRenderCallback_(isAsync);
}
if (frameRateListenerCallback_) {
frameRateListenerCallback_(false);
}
}
}
@@ -1036,10 +1030,6 @@ void NativeAnimatedNodesManager::onRender() {
"numActiveAnimations",
activeAnimations_.size());
if (frameRateListenerCallback_) {
frameRateListenerCallback_(true);
}
isOnRenderThread_ = true;
{
@@ -55,16 +55,14 @@ class NativeAnimatedNodesManager {
public:
using DirectManipulationCallback = std::function<void(Tag, const folly::dynamic &)>;
using FabricCommitCallback = std::function<void(std::unordered_map<Tag, folly::dynamic> &)>;
using StartOnRenderCallback = std::function<void(std::function<void()> &&, bool isAsync)>;
using StartOnRenderCallback = std::function<void(bool isAsync)>;
using StopOnRenderCallback = std::function<void(bool isAsync)>;
using FrameRateListenerCallback = std::function<void(bool /* shouldEnableListener */)>;
explicit NativeAnimatedNodesManager(
DirectManipulationCallback &&directManipulationCallback,
FabricCommitCallback &&fabricCommitCallback,
StartOnRenderCallback &&startOnRenderCallback = nullptr,
StopOnRenderCallback &&stopOnRenderCallback = nullptr,
FrameRateListenerCallback &&frameRateListenerCallback = nullptr) noexcept;
StopOnRenderCallback &&stopOnRenderCallback = nullptr) noexcept;
explicit NativeAnimatedNodesManager(std::shared_ptr<UIManagerAnimationBackend> animationBackend) noexcept;
@@ -239,7 +237,6 @@ class NativeAnimatedNodesManager {
std::atomic_bool isRenderCallbackStarted_{false};
const StartOnRenderCallback startOnRenderCallback_;
const StopOnRenderCallback stopOnRenderCallback_;
const FrameRateListenerCallback frameRateListenerCallback_;
std::shared_ptr<EventEmitterListener> eventEmitterListener_{nullptr};
@@ -19,26 +19,41 @@
namespace facebook::react {
UIManagerNativeAnimatedDelegateImpl::UIManagerNativeAnimatedDelegateImpl(
std::weak_ptr<NativeAnimatedNodesManager> manager)
: nativeAnimatedNodesManager_(manager) {}
NativeAnimatedNodesManagerProvider::FrameRateListenerCallback
frameRateListenerCallback)
: frameRateListenerCallback_(std::move(frameRateListenerCallback)) {}
void UIManagerNativeAnimatedDelegateImpl::runAnimationFrame() {
if (auto nativeAnimatedNodesManagerStrong =
nativeAnimatedNodesManager_.lock()) {
if (frameRateListenerCallback_) {
frameRateListenerCallback_(true);
}
nativeAnimatedNodesManagerStrong->onRender();
}
}
NativeAnimatedNodesManagerProvider::NativeAnimatedNodesManagerProvider(
NativeAnimatedNodesManager::StartOnRenderCallback startOnRenderCallback,
NativeAnimatedNodesManager::StopOnRenderCallback stopOnRenderCallback,
NativeAnimatedNodesManager::FrameRateListenerCallback
frameRateListenerCallback)
StartOnRenderCallback startOnRenderCallback,
StopOnRenderCallback stopOnRenderCallback,
FrameRateListenerCallback frameRateListenerCallback)
: eventEmitterListenerContainer_(
std::make_shared<EventEmitterListenerContainer>()),
startOnRenderCallback_(std::move(startOnRenderCallback)),
stopOnRenderCallback_(std::move(stopOnRenderCallback)),
frameRateListenerCallback_(std::move(frameRateListenerCallback)) {}
frameRateListenerCallback_(std::move(frameRateListenerCallback)),
startOnRenderCallback_(std::move(startOnRenderCallback)) {
if (frameRateListenerCallback_) {
stopOnRenderCallback_ = [this, stopOnRenderCallback](bool isAsync) {
if (stopOnRenderCallback) {
stopOnRenderCallback(isAsync);
}
if (frameRateListenerCallback_) {
frameRateListenerCallback_(false);
}
};
} else {
stopOnRenderCallback_ = std::move(stopOnRenderCallback);
}
}
std::shared_ptr<NativeAnimatedNodesManager>
NativeAnimatedNodesManagerProvider::getOrCreate(
@@ -70,6 +85,10 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
uiManager->synchronouslyUpdateViewOnUIThread(viewTag, props);
};
nativeAnimatedDelegate_ =
std::make_shared<UIManagerNativeAnimatedDelegateImpl>(
frameRateListenerCallback_);
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
#ifdef RN_USE_ANIMATION_BACKEND
// TODO: this should be initialized outside of animated, but for now it
@@ -87,14 +106,31 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
uiManager->unstable_setAnimationBackend(animationBackend_);
} else {
auto startOnRenderCallback =
[this, startOnRenderCallbackFn = std::move(startOnRenderCallback_)](
bool isAsync) {
if (startOnRenderCallbackFn) {
startOnRenderCallbackFn(
[this]() {
if (nativeAnimatedDelegate_) {
nativeAnimatedDelegate_->runAnimationFrame();
}
},
isAsync);
}
};
nativeAnimatedNodesManager_ =
std::make_shared<NativeAnimatedNodesManager>(
std::move(directManipulationCallback),
std::move(fabricCommitCallback),
std::move(startOnRenderCallback_),
std::move(startOnRenderCallback),
std::move(stopOnRenderCallback_));
}
std::static_pointer_cast<UIManagerNativeAnimatedDelegateImpl>(
nativeAnimatedDelegate_)
->setNativeAnimatedNodesManager(nativeAnimatedNodesManager_);
addEventEmitterListener(
nativeAnimatedNodesManager_->getEventEmitterListener());
@@ -117,10 +153,6 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
return false;
}));
nativeAnimatedDelegate_ =
std::make_shared<UIManagerNativeAnimatedDelegateImpl>(
nativeAnimatedNodesManager_);
uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_);
// TODO: remove force casting.
@@ -17,10 +17,16 @@ class AnimatedMountingOverrideDelegate;
class NativeAnimatedNodesManagerProvider {
public:
using FrameRateListenerCallback = std::function<void(bool /* shouldEnableListener */)>;
// when isAsync is true, it means StartOnRenderCallback is invoked from js
// thread, otherwise from main thread
using StartOnRenderCallback = std::function<void(std::function<void()> &&, bool /* isAsync */)>;
using StopOnRenderCallback = NativeAnimatedNodesManager::StopOnRenderCallback;
NativeAnimatedNodesManagerProvider(
NativeAnimatedNodesManager::StartOnRenderCallback startOnRenderCallback = nullptr,
NativeAnimatedNodesManager::StopOnRenderCallback stopOnRenderCallback = nullptr,
NativeAnimatedNodesManager::FrameRateListenerCallback frameRateListenerCallback = nullptr);
StartOnRenderCallback startOnRenderCallback = nullptr,
StopOnRenderCallback stopOnRenderCallback = nullptr,
FrameRateListenerCallback frameRateListenerCallback = nullptr);
std::shared_ptr<NativeAnimatedNodesManager> getOrCreate(
jsi::Runtime &runtime,
@@ -41,21 +47,29 @@ class NativeAnimatedNodesManagerProvider {
std::shared_ptr<UIManagerNativeAnimatedDelegate> nativeAnimatedDelegate_;
std::shared_ptr<AnimatedMountingOverrideDelegate> animatedMountingOverrideDelegate_;
NativeAnimatedNodesManager::StartOnRenderCallback startOnRenderCallback_;
NativeAnimatedNodesManager::StopOnRenderCallback stopOnRenderCallback_;
NativeAnimatedNodesManager::FrameRateListenerCallback frameRateListenerCallback_;
FrameRateListenerCallback frameRateListenerCallback_;
StartOnRenderCallback startOnRenderCallback_;
StopOnRenderCallback stopOnRenderCallback_;
std::unique_ptr<MergedValueDispatcher> mergedValueDispatcher_;
};
class UIManagerNativeAnimatedDelegateImpl : public UIManagerNativeAnimatedDelegate {
public:
explicit UIManagerNativeAnimatedDelegateImpl(std::weak_ptr<NativeAnimatedNodesManager> manager);
explicit UIManagerNativeAnimatedDelegateImpl(
NativeAnimatedNodesManagerProvider::FrameRateListenerCallback frameRateListenerCallback);
void runAnimationFrame() override;
void setNativeAnimatedNodesManager(std::weak_ptr<NativeAnimatedNodesManager> manager)
{
nativeAnimatedNodesManager_ = manager;
}
private:
std::weak_ptr<NativeAnimatedNodesManager> nativeAnimatedNodesManager_;
NativeAnimatedNodesManagerProvider::FrameRateListenerCallback frameRateListenerCallback_;
};
} // namespace facebook::react
@@ -74,24 +74,6 @@ void ImageShadowNode::updateStateIfNeeded() {
return;
}
#ifdef ANDROID
// Check if we should skip prefetching based on shouldResize logic
if (ReactNativeFeatureFlags::enableImagePrefetchingAndroid()) {
const auto& resizeMethod = imageProps.resizeMethod;
const auto& uri = newImageSource.uri;
bool shouldResize = (resizeMethod == "resize") ||
// Only resize for local content/file URIs
(resizeMethod == "auto" &&
(uri.starts_with("content://") || uri.starts_with("file://")));
// If we would resize but have no dimensions, skip creating the request
if (shouldResize &&
(newImageSource.size.width == 0 || newImageSource.size.height == 0)) {
// Keep the old state - don't create a new image request
return;
}
}
#endif
ImageState state{
newImageSource,
imageManager_->requestImage(
@@ -421,7 +421,7 @@ std::shared_ptr<ShadowNode> cloneMultipleRecursive(
std::shared_ptr<std::vector<std::shared_ptr<const ShadowNode>>> newChildren;
auto count = childrenCount.at(family);
for (size_t i = 0; count > 0 && i < children.size(); i++) {
for (int i = 0; count > 0 && i < children.size(); i++) {
const auto childFamily = &children[i]->getFamily();
if (childrenCount.contains(childFamily)) {
count--;
@@ -41,12 +41,7 @@ Scheduler::Scheduler(
if (ReactNativeFeatureFlags::enableBridgelessArchitecture() &&
ReactNativeFeatureFlags::cdpInteractionMetricsEnabled()) {
cdpMetricsReporter_.emplace(CdpMetricsReporter{runtimeExecutor_});
performanceEntryReporter_->addEventListener(&*cdpMetricsReporter_);
}
if (ReactNativeFeatureFlags::perfIssuesEnabled()) {
cdpPerfIssuesReporter_.emplace(CdpPerfIssuesReporter{runtimeExecutor_});
performanceEntryReporter_->addEventListener(&*cdpPerfIssuesReporter_);
performanceEntryReporter_->addEventTimingListener(&*cdpMetricsReporter_);
}
eventPerformanceLogger_ =
@@ -177,10 +172,7 @@ Scheduler::~Scheduler() {
uiManager_->setAnimationDelegate(nullptr);
if (cdpMetricsReporter_) {
performanceEntryReporter_->removeEventListener(&*cdpMetricsReporter_);
}
if (cdpPerfIssuesReporter_) {
performanceEntryReporter_->removeEventListener(&*cdpPerfIssuesReporter_);
performanceEntryReporter_->removeEventTimingListener(&*cdpMetricsReporter_);
}
// Then, let's verify that the requirement was satisfied.
@@ -291,8 +283,8 @@ void Scheduler::uiManagerDidDispatchCommand(
const std::shared_ptr<const ShadowNode>& shadowNode,
const std::string& commandName,
const folly::dynamic& args) {
TraceSection s(
"Scheduler::uiManagerDispatchCommand", "commandName", commandName);
TraceSection s("Scheduler::uiManagerDispatchCommand");
if (delegate_ != nullptr) {
auto shadowView = ShadowView(*shadowNode);
runtimeScheduler_->scheduleRenderingUpdate(
@@ -11,7 +11,6 @@
#include <ReactCommon/RuntimeExecutor.h>
#include <react/performance/cdpmetrics/CdpMetricsReporter.h>
#include <react/performance/cdpmetrics/CdpPerfIssuesReporter.h>
#include <react/performance/timeline/PerformanceEntryReporter.h>
#include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
#include <react/renderer/core/ComponentDescriptor.h>
@@ -135,7 +134,6 @@ class Scheduler final : public UIManagerDelegate {
std::shared_ptr<PerformanceEntryReporter> performanceEntryReporter_;
std::optional<CdpMetricsReporter> cdpMetricsReporter_;
std::optional<CdpPerfIssuesReporter> cdpPerfIssuesReporter_;
std::shared_ptr<EventPerformanceLogger> eventPerformanceLogger_;
/**

Some files were not shown because too many files have changed in this diff Show More