diff --git a/.ado/image/rnw-img-vs2022-node18.json b/.ado/image/rnw-img-vs2022-node18.json index 8901268d8f0..20d23fbc959 100644 --- a/.ado/image/rnw-img-vs2022-node18.json +++ b/.ado/image/rnw-img-vs2022-node18.json @@ -34,7 +34,7 @@ { "name": "Windows-NodeJS", "parameters": { - "Version": "18.16.1" + "Version": "18.18.0" } }, { diff --git a/change/@office-iss-react-native-win32-ab9bf9be-8971-414b-9a32-7e4c75caff97.json b/change/@office-iss-react-native-win32-ab9bf9be-8971-414b-9a32-7e4c75caff97.json new file mode 100644 index 00000000000..4d821079389 --- /dev/null +++ b/change/@office-iss-react-native-win32-ab9bf9be-8971-414b-9a32-7e4c75caff97.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "integrate react-native-3-21", + "packageName": "@office-iss/react-native-win32", + "email": "tatianakapos@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@react-native-windows-automation-channel-e03e525c-abcb-485c-bf7f-cdb161ca836a.json b/change/@react-native-windows-automation-channel-e03e525c-abcb-485c-bf7f-cdb161ca836a.json new file mode 100644 index 00000000000..aa86357ece5 --- /dev/null +++ b/change/@react-native-windows-automation-channel-e03e525c-abcb-485c-bf7f-cdb161ca836a.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "integrate react-native-3-21", + "packageName": "@react-native-windows/automation-channel", + "email": "tatianakapos@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@react-native-windows-cli-a1ce68a8-2e76-4625-bc76-7c5bb8d1c69d.json b/change/@react-native-windows-cli-a1ce68a8-2e76-4625-bc76-7c5bb8d1c69d.json new file mode 100644 index 00000000000..574204bb270 --- /dev/null +++ b/change/@react-native-windows-cli-a1ce68a8-2e76-4625-bc76-7c5bb8d1c69d.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "integrate react-native-3-21", + "packageName": "@react-native-windows/cli", + "email": "tatianakapos@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@rnw-scripts-eslint-config-6c54f16d-6659-4e2d-a99d-6a4ce5dbb9f2.json b/change/@rnw-scripts-eslint-config-6c54f16d-6659-4e2d-a99d-6a4ce5dbb9f2.json new file mode 100644 index 00000000000..04d5334b681 --- /dev/null +++ b/change/@rnw-scripts-eslint-config-6c54f16d-6659-4e2d-a99d-6a4ce5dbb9f2.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "integrate react-native-3-21", + "packageName": "@rnw-scripts/eslint-config", + "email": "tatianakapos@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/react-native-windows-fb4b6aba-56ea-4d8a-a329-d0f0e682a095.json b/change/react-native-windows-fb4b6aba-56ea-4d8a-a329-d0f0e682a095.json new file mode 100644 index 00000000000..652e63cc0e2 --- /dev/null +++ b/change/react-native-windows-fb4b6aba-56ea-4d8a-a329-d0f0e682a095.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "integrate react-native-3-21", + "packageName": "react-native-windows", + "email": "tatianakapos@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/@office-iss/react-native-win32-tester/overrides.json b/packages/@office-iss/react-native-win32-tester/overrides.json index 8249415c27c..0763aad1e34 100644 --- a/packages/@office-iss/react-native-win32-tester/overrides.json +++ b/packages/@office-iss/react-native-win32-tester/overrides.json @@ -5,7 +5,7 @@ "excludePatterns": [ "src/js/examples-win32/**" ], - "baseVersion": "0.75.0-nightly-20240307-ff03b149e", + "baseVersion": "0.75.0-nightly-20240321-7d180d712", "overrides": [ { "type": "patch", diff --git a/packages/@office-iss/react-native-win32-tester/package.json b/packages/@office-iss/react-native-win32-tester/package.json index 3d433a9fd07..fff218d2232 100644 --- a/packages/@office-iss/react-native-win32-tester/package.json +++ b/packages/@office-iss/react-native-win32-tester/package.json @@ -19,7 +19,7 @@ "peerDependencies": { "@office-iss/react-native-win32": "^0.0.0-canary.243", "react": "18.0.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e" + "react-native": "0.75.0-nightly-20240321-7d180d712" }, "devDependencies": { "@office-iss/react-native-win32": "^0.0.0-canary.243", @@ -30,7 +30,7 @@ "@types/node": "^18.0.0", "eslint": "^8.19.0", "just-scripts": "^1.3.3", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-platform-override": "^1.9.30", "typescript": "5.0.4" }, diff --git a/packages/@office-iss/react-native-win32/.flowconfig b/packages/@office-iss/react-native-win32/.flowconfig index e9e6b47eb15..62e68951ec3 100644 --- a/packages/@office-iss/react-native-win32/.flowconfig +++ b/packages/@office-iss/react-native-win32/.flowconfig @@ -154,4 +154,4 @@ untyped-import untyped-type-import [version] -^0.229.2 +^0.231.0 diff --git a/packages/@office-iss/react-native-win32/overrides.json b/packages/@office-iss/react-native-win32/overrides.json index dfb16ad2217..d658e33d546 100644 --- a/packages/@office-iss/react-native-win32/overrides.json +++ b/packages/@office-iss/react-native-win32/overrides.json @@ -7,13 +7,13 @@ "**/__snapshots__/**", "src-win/rntypes/**" ], - "baseVersion": "0.75.0-nightly-20240307-ff03b149e", + "baseVersion": "0.75.0-nightly-20240321-7d180d712", "overrides": [ { "type": "derived", "file": ".flowconfig", "baseFile": ".flowconfig", - "baseHash": "bdebcba51a5c13fbe5acab9e07720acff0825bc9" + "baseHash": "a57066be1285dc8bc5d9702d0227d04c1c6447ce" }, { "type": "derived", @@ -122,7 +122,7 @@ "type": "derived", "file": "src-win/Libraries/Components/TextInput/TextInput.win32.js", "baseFile": "packages/react-native/Libraries/Components/TextInput/TextInput.js", - "baseHash": "f05b36551197bfa87f2342bd6d1c9b134c1731b2" + "baseHash": "b1ef5981a6abbb0548fc5fd835ad711c10712d61" }, { "type": "patch", @@ -323,7 +323,7 @@ "type": "derived", "file": "src-win/Libraries/LogBox/UI/LogBoxInspectorReactFrames.win32.js", "baseFile": "packages/react-native/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js", - "baseHash": "04c1210d0198315af8358b22a81dc74dc76ef752" + "baseHash": "3a765d2180cca25ed35172ebce8294fc569486aa" }, { "type": "derived", @@ -528,20 +528,6 @@ "file": "src-win/src/private/specs/modules/NativePlatformConstantsWin.js", "baseFile": "packages/react-native/src/private/specs/modules/NativePlatformConstantsAndroid.js", "baseHash": "b4a125d9134f33aeaba9e06988e18cbb0b4e9e9c" - }, - { - "type": "patch", - "file": "src-win/src/private/webapis/dom/nodes/ReadOnlyElement.js", - "baseFile": "packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js", - "baseHash": "e049a95c6fab9e5d3f7e13edbeb7b12440f71259", - "issue": 12951 - }, - { - "type": "patch", - "file": "src-win/src/private/webapis/dom/nodes/ReadOnlyNode.js", - "baseFile": "packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js", - "baseHash": "bbb8d136ec9b0f56a3843ea9da0bd1e17a50a7a3", - "issue": 12951 } ] } \ No newline at end of file diff --git a/packages/@office-iss/react-native-win32/package.json b/packages/@office-iss/react-native-win32/package.json index 566bc97823f..66c45af166a 100644 --- a/packages/@office-iss/react-native-win32/package.json +++ b/packages/@office-iss/react-native-win32/package.json @@ -26,17 +26,17 @@ "dependencies": { "@babel/runtime": "^7.0.0", "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "13.6.1", - "@react-native-community/cli-platform-android": "13.6.1", - "@react-native-community/cli-platform-ios": "13.6.1", + "@react-native-community/cli": "14.0.0-alpha.0", + "@react-native-community/cli-platform-android": "14.0.0-alpha.0", + "@react-native-community/cli-platform-ios": "14.0.0-alpha.0", "@react-native/assets": "1.0.0", - "@react-native/assets-registry": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/codegen": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/community-cli-plugin": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/gradle-plugin": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/js-polyfills": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/normalize-colors": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/virtualized-lists": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/assets-registry": "0.75.0-nightly-20240321-7d180d712", + "@react-native/codegen": "0.75.0-nightly-20240321-7d180d712", + "@react-native/community-cli-plugin": "0.75.0-nightly-20240321-7d180d712", + "@react-native/gradle-plugin": "0.75.0-nightly-20240321-7d180d712", + "@react-native/js-polyfills": "0.75.0-nightly-20240321-7d180d712", + "@react-native/normalize-colors": "0.75.0-nightly-20240321-7d180d712", + "@react-native/virtualized-lists": "0.75.0-nightly-20240321-7d180d712", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", @@ -56,7 +56,7 @@ "pretty-format": "^26.5.2", "promise": "^8.3.0", "react-clone-referenced-element": "^1.0.1", - "react-devtools-core": "^5.0.0", + "react-devtools-core": "^5.0.2", "react-refresh": "^0.14.0", "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", @@ -69,7 +69,7 @@ "devDependencies": { "@babel/core": "^7.20.0", "@babel/eslint-parser": "^7.20.0", - "@react-native/metro-config": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/metro-config": "0.75.0-nightly-20240321-7d180d712", "@rnw-scripts/babel-react-native-config": "0.0.0", "@rnw-scripts/eslint-config": "1.2.13", "@rnw-scripts/jest-out-of-tree-snapshot-resolver": "^1.1.17", @@ -85,13 +85,13 @@ "just-scripts": "^1.3.3", "prettier": "2.8.8", "react": "18.2.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-platform-override": "^1.9.30", "typescript": "5.0.4" }, "peerDependencies": { "react": "18.2.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e" + "react-native": "0.75.0-nightly-20240321-7d180d712" }, "beachball": { "defaultNpmTag": "canary", diff --git a/packages/@office-iss/react-native-win32/src-win/Libraries/Components/TextInput/TextInput.win32.js b/packages/@office-iss/react-native-win32/src-win/Libraries/Components/TextInput/TextInput.win32.js index 11e709f4a2e..d30e6b398ac 100644 --- a/packages/@office-iss/react-native-win32/src-win/Libraries/Components/TextInput/TextInput.win32.js +++ b/packages/@office-iss/react-native-win32/src-win/Libraries/Components/TextInput/TextInput.win32.js @@ -784,33 +784,12 @@ export type Props = $ReadOnly<{| */ onChange?: ?(e: ChangeEvent) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * Callback that is called when the text input's text changes. - * - * @platform ios - */ - unstable_onChangeSync?: ?(e: ChangeEvent) => mixed, - /** * Callback that is called when the text input's text changes. * Changed text is passed as an argument to the callback handler. */ onChangeText?: ?(text: string) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * Callback that is called when the text input's text changes. - * Changed text is passed as an argument to the callback handler. - * - * @platform ios - */ - unstable_onChangeTextSync?: ?(text: string) => mixed, - /** * Callback that is called when the text input's content size changes. * This will be called with @@ -839,21 +818,6 @@ export type Props = $ReadOnly<{| */ onKeyPress?: ?(e: KeyPressEvent) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * - * Callback that is called when a key is pressed. - * This will be called with `{ nativeEvent: { key: keyValue } }` - * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and - * the typed-in character otherwise including `' '` for space. - * Fires before `onChange` callbacks. - * - * @platform ios - */ - unstable_onKeyPressSync?: ?(e: KeyPressEvent) => mixed, - /** * Called when a single tap gesture is detected. */ @@ -1359,26 +1323,6 @@ function InternalTextInput(props: Props): React.Node { setMostRecentEventCount(event.nativeEvent.eventCount); }; - const _onChangeSync = (event: ChangeEvent) => { - const currentText = event.nativeEvent.text; - props.unstable_onChangeSync && props.unstable_onChangeSync(event); - props.unstable_onChangeTextSync && - props.unstable_onChangeTextSync(currentText); - - if (inputRef.current == null) { - // calling `props.onChange` or `props.onChangeText` - // may clean up the input itself. Exits here. - return; - } - - setLastNativeText(currentText); - // This must happen last, after we call setLastNativeText. - // Different ordering can cause bugs when editing AndroidTextInputs - // with multiple Fragments. - // We must update this so that controlled input updates work. - setMostRecentEventCount(event.nativeEvent.eventCount); - }; - const _onSelectionChange = (event: SelectionChangeEvent) => { props.onSelectionChange && props.onSelectionChange(event); @@ -1583,10 +1527,6 @@ function InternalTextInput(props: Props): React.Node { style.paddingVertical == null && style.paddingTop == null)); - const useOnChangeSync = - (props.unstable_onChangeSync || props.unstable_onChangeTextSync) && - !(props.onChange || props.onChangeText); - textInput = ( { - return createHTMLCollection(getChildElements(this)); - } - - get clientHeight(): number { - const node = getShadowNode(this); - - if (node != null) { - const innerSize = nullthrows(getFabricUIManager()).getInnerSize(node); - if (innerSize != null) { - return innerSize[1]; - } - } - - return 0; - } - - get clientLeft(): number { - const node = getShadowNode(this); - - if (node != null) { - const borderSize = nullthrows(getFabricUIManager()).getBorderSize(node); - if (borderSize != null) { - return borderSize[3]; - } - } - - return 0; - } - - get clientTop(): number { - const node = getShadowNode(this); - - if (node != null) { - const borderSize = nullthrows(getFabricUIManager()).getBorderSize(node); - if (borderSize != null) { - return borderSize[0]; - } - } - - return 0; - } - - get clientWidth(): number { - const node = getShadowNode(this); - - if (node != null) { - const innerSize = nullthrows(getFabricUIManager()).getInnerSize(node); - if (innerSize != null) { - return innerSize[0]; - } - } - - return 0; - } - - get firstElementChild(): ReadOnlyElement | null { - const childElements = getChildElements(this); - - if (childElements.length === 0) { - return null; - } - - return childElements[0]; - } - - get id(): string { - const instanceHandle = getInstanceHandle(this); - // TODO: migrate off this private React API - // $FlowExpectedError[incompatible-use] - const props = instanceHandle?.stateNode?.canonical?.currentProps; - return props?.id ?? props?.nativeID ?? ''; - } - - get lastElementChild(): ReadOnlyElement | null { - const childElements = getChildElements(this); - - if (childElements.length === 0) { - return null; - } - - return childElements[childElements.length - 1]; - } - - get nextElementSibling(): ReadOnlyElement | null { - return getElementSibling(this, 'next'); - } - - get nodeName(): string { - return this.tagName; - } - - get nodeType(): number { - return ReadOnlyNode.ELEMENT_NODE; - } - - get nodeValue(): string | null { - return null; - } - - set nodeValue(value: string): void {} - - get previousElementSibling(): ReadOnlyElement | null { - return getElementSibling(this, 'previous'); - } - - get scrollHeight(): number { - const node = getShadowNode(this); - - if (node != null) { - const scrollSize = nullthrows(getFabricUIManager()).getScrollSize(node); - if (scrollSize != null) { - return scrollSize[1]; - } - } - - return 0; - } - - get scrollLeft(): number { - const node = getShadowNode(this); - - if (node != null) { - // Override for #12951 - const scrollPosition = nullthrows(getFabricUIManager()).getScrollPosition( - node, - ); - if (scrollPosition != null) { - return scrollPosition[0]; - } - } - - return 0; - } - - get scrollTop(): number { - const node = getShadowNode(this); - - if (node != null) { - // Override for #12951 - const scrollPosition = nullthrows(getFabricUIManager()).getScrollPosition( - node, - ); - if (scrollPosition != null) { - return scrollPosition[1]; - } - } - - return 0; - } - - get scrollWidth(): number { - const node = getShadowNode(this); - - if (node != null) { - const scrollSize = nullthrows(getFabricUIManager()).getScrollSize(node); - if (scrollSize != null) { - return scrollSize[0]; - } - } - - return 0; - } - - get tagName(): string { - const node = getShadowNode(this); - - if (node != null) { - return nullthrows(getFabricUIManager()).getTagName(node); - } - - return ''; - } - - get textContent(): string | null { - const shadowNode = getShadowNode(this); - - if (shadowNode != null) { - return nullthrows(getFabricUIManager()).getTextContent(shadowNode); - } - - return ''; - } - - getBoundingClientRect(): DOMRect { - return getBoundingClientRect(this, {includeTransform: true}); - } - - /** - * Pointer Capture APIs - */ - hasPointerCapture(pointerId: number): boolean { - const node = getShadowNode(this); - if (node != null) { - return nullthrows(getFabricUIManager()).hasPointerCapture( - node, - pointerId, - ); - } - return false; - } - - setPointerCapture(pointerId: number): void { - const node = getShadowNode(this); - if (node != null) { - nullthrows(getFabricUIManager()).setPointerCapture(node, pointerId); - } - } - - releasePointerCapture(pointerId: number): void { - const node = getShadowNode(this); - if (node != null) { - nullthrows(getFabricUIManager()).releasePointerCapture(node, pointerId); - } - } -} - -function getChildElements(node: ReadOnlyNode): $ReadOnlyArray { - // $FlowIssue[incompatible-call] - return getChildNodes(node).filter( - childNode => childNode instanceof ReadOnlyElement, - ); -} - -/** - * The public API for `getBoundingClientRect` always includes transform, - * so we use this internal version to get the data without transform to - * implement methods like `offsetWidth` and `offsetHeight`. - */ -export function getBoundingClientRect( - node: ReadOnlyElement, - {includeTransform}: {includeTransform: boolean}, -): DOMRect { - const shadowNode = getShadowNode(node); - - if (shadowNode != null) { - const rect = nullthrows(getFabricUIManager()).getBoundingClientRect( - shadowNode, - includeTransform, - ); - - 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); -} diff --git a/packages/@office-iss/react-native-win32/src-win/src/private/webapis/dom/nodes/ReadOnlyNode.js b/packages/@office-iss/react-native-win32/src-win/src/private/webapis/dom/nodes/ReadOnlyNode.js deleted file mode 100644 index 1563615ccf1..00000000000 --- a/packages/@office-iss/react-native-win32/src-win/src/private/webapis/dom/nodes/ReadOnlyNode.js +++ /dev/null @@ -1,367 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow strict-local - */ - -// flowlint unsafe-getters-setters:off - -import type { - InternalInstanceHandle, - Node as ShadowNode, -} from '../../../../../Libraries/Renderer/shims/ReactNativeTypes'; -import type NodeList from '../oldstylecollections/NodeList'; -import type ReadOnlyElement from './ReadOnlyElement'; - -import {getFabricUIManager} from '../../../../../Libraries/ReactNative/FabricUIManager'; -import {createNodeList} from '../oldstylecollections/NodeList'; -import nullthrows from 'nullthrows'; - -// We initialize this lazily to avoid a require cycle -// (`ReadOnlyElement` also depends on `ReadOnlyNode`). -let ReadOnlyElementClass: Class; - -export default class ReadOnlyNode { - constructor(internalInstanceHandle: InternalInstanceHandle) { - setInstanceHandle(this, internalInstanceHandle); - } - - get childNodes(): NodeList { - const childNodes = getChildNodes(this); - return createNodeList(childNodes); - } - - get firstChild(): ReadOnlyNode | null { - const childNodes = getChildNodes(this); - - if (childNodes.length === 0) { - return null; - } - - return childNodes[0]; - } - - get isConnected(): boolean { - const shadowNode = getShadowNode(this); - - if (shadowNode == null) { - return false; - } - - return nullthrows(getFabricUIManager()).isConnected(shadowNode); - } - - get lastChild(): ReadOnlyNode | null { - const childNodes = getChildNodes(this); - - if (childNodes.length === 0) { - return null; - } - - return childNodes[childNodes.length - 1]; - } - - get nextSibling(): ReadOnlyNode | null { - const [siblings, position] = getNodeSiblingsAndPosition(this); - - if (position === siblings.length - 1) { - // this node is the last child of its parent, so there is no next sibling. - return null; - } - - return siblings[position + 1]; - } - - /** - * @abstract - */ - get nodeName(): string { - throw new TypeError( - '`nodeName` is abstract and must be implemented in a subclass of `ReadOnlyNode`', - ); - } - - /** - * @abstract - */ - get nodeType(): number { - throw new TypeError( - '`nodeType` is abstract and must be implemented in a subclass of `ReadOnlyNode`', - ); - } - - /** - * @abstract - */ - get nodeValue(): string | null { - throw new TypeError( - '`nodeValue` is abstract and must be implemented in a subclass of `ReadOnlyNode`', - ); - } - - get parentElement(): ReadOnlyElement | null { - const parentNode = this.parentNode; - - if (ReadOnlyElementClass == null) { - // We initialize this lazily to avoid a require cycle. - ReadOnlyElementClass = require('./ReadOnlyElement').default; - } - - if (parentNode instanceof ReadOnlyElementClass) { - return parentNode; - } - - return null; - } - - get parentNode(): ReadOnlyNode | null { - const shadowNode = getShadowNode(this); - - if (shadowNode == null) { - return null; - } - - // Override for #12951 - const parentInstanceHandle = nullthrows(getFabricUIManager()).getParentNode( - shadowNode, - ); - - if (parentInstanceHandle == null) { - return null; - } - - return ( - getPublicInstanceFromInternalInstanceHandle(parentInstanceHandle) ?? null - ); - } - - get previousSibling(): ReadOnlyNode | null { - const [siblings, position] = getNodeSiblingsAndPosition(this); - - if (position === 0) { - // this node is the first child of its parent, so there is no previous sibling. - return null; - } - - return siblings[position - 1]; - } - - /** - * @abstract - */ - get textContent(): string | null { - throw new TypeError( - '`textContent` is abstract and must be implemented in a subclass of `ReadOnlyNode`', - ); - } - - compareDocumentPosition(otherNode: ReadOnlyNode): number { - // Quick check to avoid having to call into Fabric if the nodes are the same. - if (otherNode === this) { - return 0; - } - - const shadowNode = getShadowNode(this); - const otherShadowNode = getShadowNode(otherNode); - - if (shadowNode == null || otherShadowNode == null) { - return ReadOnlyNode.DOCUMENT_POSITION_DISCONNECTED; - } - - return nullthrows(getFabricUIManager()).compareDocumentPosition( - shadowNode, - otherShadowNode, - ); - } - - contains(otherNode: ReadOnlyNode): boolean { - if (otherNode === this) { - return true; - } - - const position = this.compareDocumentPosition(otherNode); - // eslint-disable-next-line no-bitwise - return (position & ReadOnlyNode.DOCUMENT_POSITION_CONTAINED_BY) !== 0; - } - - getRootNode(): ReadOnlyNode { - // eslint-disable-next-line consistent-this - let lastKnownParent: ReadOnlyNode = this; - let nextPossibleParent: ?ReadOnlyNode = this.parentNode; - - while (nextPossibleParent != null) { - lastKnownParent = nextPossibleParent; - nextPossibleParent = nextPossibleParent.parentNode; - } - - return lastKnownParent; - } - - hasChildNodes(): boolean { - return getChildNodes(this).length > 0; - } - - /* - * Node types, as returned by the `nodeType` property. - */ - - /** - * Type of Element, HTMLElement and ReactNativeElement instances. - */ - static ELEMENT_NODE: number = 1; - /** - * Currently Unused in React Native. - */ - static ATTRIBUTE_NODE: number = 2; - /** - * Text nodes. - */ - static TEXT_NODE: number = 3; - /** - * @deprecated Unused in React Native. - */ - static CDATA_SECTION_NODE: number = 4; - /** - * @deprecated - */ - static ENTITY_REFERENCE_NODE: number = 5; - /** - * @deprecated - */ - static ENTITY_NODE: number = 6; - /** - * @deprecated Unused in React Native. - */ - static PROCESSING_INSTRUCTION_NODE: number = 7; - /** - * @deprecated Unused in React Native. - */ - static COMMENT_NODE: number = 8; - /** - * @deprecated Unused in React Native. - */ - static DOCUMENT_NODE: number = 9; - /** - * @deprecated Unused in React Native. - */ - static DOCUMENT_TYPE_NODE: number = 10; - /** - * @deprecated Unused in React Native. - */ - static DOCUMENT_FRAGMENT_NODE: number = 11; - /** - * @deprecated - */ - static NOTATION_NODE: number = 12; - - /* - * Document position flags. Used to check the return value of - * `compareDocumentPosition()`. - */ - - /** - * Both nodes are in different documents. - */ - static DOCUMENT_POSITION_DISCONNECTED: number = 1; - /** - * `otherNode` precedes the node in either a pre-order depth-first traversal of a tree containing both - * (e.g., as an ancestor or previous sibling or a descendant of a previous sibling or previous sibling of an ancestor) - * or (if they are disconnected) in an arbitrary but consistent ordering. - */ - static DOCUMENT_POSITION_PRECEDING: number = 2; - /** - * `otherNode` follows the node in either a pre-order depth-first traversal of a tree containing both - * (e.g., as a descendant or following sibling or a descendant of a following sibling or following sibling of an ancestor) - * or (if they are disconnected) in an arbitrary but consistent ordering. - */ - static DOCUMENT_POSITION_FOLLOWING: number = 4; - /** - * `otherNode` is an ancestor of the node. - */ - static DOCUMENT_POSITION_CONTAINS: number = 8; - /** - * `otherNode` is a descendant of the node. - */ - static DOCUMENT_POSITION_CONTAINED_BY: number = 16; - /** - * @deprecated Unused in React Native. - */ - static DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number = 32; -} - -const INSTANCE_HANDLE_KEY = Symbol('internalInstanceHandle'); - -export function getInstanceHandle(node: ReadOnlyNode): InternalInstanceHandle { - // $FlowExpectedError[prop-missing] - return node[INSTANCE_HANDLE_KEY]; -} - -function setInstanceHandle( - node: ReadOnlyNode, - instanceHandle: InternalInstanceHandle, -): void { - // $FlowExpectedError[prop-missing] - node[INSTANCE_HANDLE_KEY] = instanceHandle; -} - -export function getShadowNode(node: ReadOnlyNode): ?ShadowNode { - // Lazy import Fabric here to avoid DOM Node APIs classes from having side-effects. - // With a static import we can't use these classes for Paper-only variants. - const ReactFabric = require('../../../../../Libraries/Renderer/shims/ReactFabric'); - return ReactFabric.getNodeFromInternalInstanceHandle(getInstanceHandle(node)); -} - -export function getChildNodes( - node: ReadOnlyNode, -): $ReadOnlyArray { - const shadowNode = getShadowNode(node); - - if (shadowNode == null) { - return []; - } - - // Override for #12951 - const childNodeInstanceHandles = nullthrows( - getFabricUIManager(), - ).getChildNodes(shadowNode); - return childNodeInstanceHandles - .map(instanceHandle => - getPublicInstanceFromInternalInstanceHandle(instanceHandle), - ) - .filter(Boolean); -} - -function getNodeSiblingsAndPosition( - node: ReadOnlyNode, -): [$ReadOnlyArray, number] { - const parent = node.parentNode; - if (parent == null) { - // This node is the root or it's disconnected. - return [[node], 0]; - } - - const siblings = getChildNodes(parent); - const position = siblings.indexOf(node); - - if (position === -1) { - throw new TypeError("Missing node in parent's child node list"); - } - - return [siblings, position]; -} - -export function getPublicInstanceFromInternalInstanceHandle( - instanceHandle: InternalInstanceHandle, -): ?ReadOnlyNode { - // Lazy import Fabric here to avoid DOM Node APIs classes from having side-effects. - // With a static import we can't use these classes for Paper-only variants. - const ReactFabric = require('../../../../../Libraries/Renderer/shims/ReactFabric'); - const mixedPublicInstance = - ReactFabric.getPublicInstanceFromInternalInstanceHandle(instanceHandle); - // $FlowExpectedError[incompatible-return] React defines public instances as "mixed" because it can't access the definition from React Native. - return mixedPublicInstance; -} diff --git a/packages/@react-native-windows/automation-channel/package.json b/packages/@react-native-windows/automation-channel/package.json index 8b47051f405..bf508086266 100644 --- a/packages/@react-native-windows/automation-channel/package.json +++ b/packages/@react-native-windows/automation-channel/package.json @@ -31,7 +31,7 @@ "just-scripts": "^1.3.2", "prettier": "2.8.8", "react": "18.2.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-windows": "^0.0.0-canary.811", "typescript": "5.0.4" }, diff --git a/packages/@react-native-windows/cli/package.json b/packages/@react-native-windows/cli/package.json index c3ee2134765..c76bfc073d6 100644 --- a/packages/@react-native-windows/cli/package.json +++ b/packages/@react-native-windows/cli/package.json @@ -40,8 +40,8 @@ "xpath": "^0.0.27" }, "devDependencies": { - "@react-native-community/cli-doctor": "13.6.1", - "@react-native-community/cli-types": "13.6.1", + "@react-native-community/cli-doctor": "14.0.0-alpha.0", + "@react-native-community/cli-types": "14.0.0-alpha.0", "@rnw-scripts/eslint-config": "1.2.13", "@rnw-scripts/jest-unittest-config": "1.5.8", "@rnw-scripts/just-task": "2.3.29", diff --git a/packages/@react-native-windows/tester/overrides.json b/packages/@react-native-windows/tester/overrides.json index e6ea98fc268..c8ef822f239 100644 --- a/packages/@react-native-windows/tester/overrides.json +++ b/packages/@react-native-windows/tester/overrides.json @@ -5,7 +5,7 @@ "excludePatterns": [ "src/js/examples-win/**" ], - "baseVersion": "0.75.0-nightly-20240307-ff03b149e", + "baseVersion": "0.75.0-nightly-20240321-7d180d712", "overrides": [ { "type": "derived", diff --git a/packages/@react-native-windows/tester/package.json b/packages/@react-native-windows/tester/package.json index 98729f26ffd..a553e7b532d 100644 --- a/packages/@react-native-windows/tester/package.json +++ b/packages/@react-native-windows/tester/package.json @@ -18,7 +18,7 @@ "peerDependencies": { "@react-native-picker/picker": "2.4.10", "react": "18.0.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-windows": "^0.0.0-canary.811", "react-native-xaml": "^0.0.78" }, @@ -31,7 +31,7 @@ "@types/node": "^18.0.0", "eslint": "^8.19.0", "just-scripts": "^1.3.3", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-platform-override": "^1.9.30", "react-native-windows": "^0.0.0-canary.811", "typescript": "5.0.4" diff --git a/packages/@react-native/monorepo/overrides.json b/packages/@react-native/monorepo/overrides.json index 75dab1205a7..719ebd9dee0 100644 --- a/packages/@react-native/monorepo/overrides.json +++ b/packages/@react-native/monorepo/overrides.json @@ -1,11 +1,11 @@ { - "baseVersion": "0.75.0-nightly-20240307-ff03b149e", + "baseVersion": "0.75.0-nightly-20240321-7d180d712", "overrides": [ { "type": "patch", "file": "package.json", "baseFile": "package.json", - "baseHash": "6e31f38001f7dd4716c303fa8b3265bbfbc4328f" + "baseHash": "3ca43895e5f26cebeae65ad2a7fd8678781bc49e" } ] } \ No newline at end of file diff --git a/packages/@react-native/monorepo/package.json b/packages/@react-native/monorepo/package.json index 27784d48947..5dfd7295c3c 100644 --- a/packages/@react-native/monorepo/package.json +++ b/packages/@react-native/monorepo/package.json @@ -13,7 +13,6 @@ "scripts": { "android": "cd packages/rn-tester && npm run android", "build-android": "./gradlew :packages:react-native:ReactAndroid:build", - "bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages", "clang-format": "clang-format -i --glob=*/**/*.{h,cpp,m,mm}", "clean": "node ./scripts/build/clean.js", "flow-check": "flow check", @@ -56,13 +55,12 @@ "@definitelytyped/dtslint": "^0.0.127", "@jest/create-cache-key-function": "^29.6.3", "@pkgjs/parseargs": "^0.11.0", - "@react-native/metro-babel-transformer": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/metro-config": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/metro-babel-transformer": "0.75.0-nightly-20240321-7d180d712", + "@react-native/metro-config": "0.75.0-nightly-20240321-7d180d712", "@tsconfig/node18": "1.0.1", "@types/react": "^18.2.6", "@typescript-eslint/parser": "^6.7.4", "ansi-styles": "^4.2.1", - "async": "^3.2.2", "babel-plugin-minify-dead-code-elimination": "^0.5.2", "babel-plugin-transform-define": "^2.1.2", "babel-plugin-transform-flow-enums": "^0.0.2", @@ -70,12 +68,12 @@ "chalk": "^4.0.0", "clang-format": "^1.8.0", "connect": "^3.6.5", - "eslint": "^8.23.1", + "eslint": "^8.57.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-babel": "^5.3.1", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-ft-flow": "^2.0.1", - "eslint-plugin-jest": "^26.5.3", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsx-a11y": "^6.6.0", "eslint-plugin-lint": "^1.0.0", "eslint-plugin-prettier": "^4.2.1", @@ -84,8 +82,8 @@ "eslint-plugin-react-native": "^4.0.0", "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", - "flow-api-translator": "0.20.0", - "flow-bin": "^0.229.2", + "flow-api-translator": "0.20.1", + "flow-bin": "^0.231.0", "glob": "^7.1.1", "hermes-eslint": "0.20.0", "hermes-transform": "0.20.0", @@ -97,7 +95,6 @@ "metro-memory-fs": "^0.80.0", "micromatch": "^4.0.4", "mkdirp": "^0.5.1", - "mock-fs": "^5.1.4", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "prettier": "2.8.8", diff --git a/packages/@react-native/tester/js/assets/bottom-nav-apis-icon-active.png b/packages/@react-native/tester/js/assets/bottom-nav-apis-icon-dark.png similarity index 100% rename from packages/@react-native/tester/js/assets/bottom-nav-apis-icon-active.png rename to packages/@react-native/tester/js/assets/bottom-nav-apis-icon-dark.png diff --git a/packages/@react-native/tester/js/assets/bottom-nav-apis-icon-inactive.png b/packages/@react-native/tester/js/assets/bottom-nav-apis-icon-light.png similarity index 100% rename from packages/@react-native/tester/js/assets/bottom-nav-apis-icon-inactive.png rename to packages/@react-native/tester/js/assets/bottom-nav-apis-icon-light.png diff --git a/packages/@react-native/tester/js/assets/bottom-nav-components-icon-active.png b/packages/@react-native/tester/js/assets/bottom-nav-components-icon-dark.png similarity index 100% rename from packages/@react-native/tester/js/assets/bottom-nav-components-icon-active.png rename to packages/@react-native/tester/js/assets/bottom-nav-components-icon-dark.png diff --git a/packages/@react-native/tester/js/assets/bottom-nav-components-icon-inactive.png b/packages/@react-native/tester/js/assets/bottom-nav-components-icon-light.png similarity index 100% rename from packages/@react-native/tester/js/assets/bottom-nav-components-icon-inactive.png rename to packages/@react-native/tester/js/assets/bottom-nav-components-icon-light.png diff --git a/packages/@react-native/tester/js/components/RNTesterNavbar.js b/packages/@react-native/tester/js/components/RNTesterNavbar.js index 8b49ab157c4..a0817d8d62e 100644 --- a/packages/@react-native/tester/js/components/RNTesterNavbar.js +++ b/packages/@react-native/tester/js/components/RNTesterNavbar.js @@ -37,7 +37,12 @@ const NavbarButton = ({ style={iconStyle} source={isActive ? activeImage : inactiveImage} /> - + {label} @@ -57,8 +62,8 @@ const ComponentTab = ({ testID="components-tab" label="Components" handlePress={() => handleNavBarPress({screen: 'components'})} - activeImage={require('./../assets/bottom-nav-components-icon-active.png')} - inactiveImage={require('./../assets/bottom-nav-components-icon-inactive.png')} + activeImage={theme.NavBarComponentsActiveIcon} + inactiveImage={theme.NavBarComponentsInactiveIcon} isActive={isComponentActive} theme={theme} iconStyle={styles.componentIcon} @@ -78,8 +83,8 @@ const APITab = ({ testID="apis-tab" label="APIs" handlePress={() => handleNavBarPress({screen: 'apis'})} - activeImage={require('./../assets/bottom-nav-apis-icon-active.png')} - inactiveImage={require('./../assets/bottom-nav-apis-icon-inactive.png')} + activeImage={theme.NavBarAPIsActiveIcon} + inactiveImage={theme.NavBarAPIsInactiveIcon} isActive={isAPIActive} theme={theme} iconStyle={styles.apiIcon} @@ -157,12 +162,6 @@ const styles = StyleSheet.create({ height: 20, alignSelf: 'center', }, - activeText: { - color: '#5E5F62', - }, - inactiveText: { - color: '#B1B4BA', - }, activeBar: { borderTopWidth: 2, borderColor: '#005DFF', diff --git a/packages/@react-native/tester/js/components/RNTesterTheme.js b/packages/@react-native/tester/js/components/RNTesterTheme.js index a94c7c54787..6c7858e17c5 100644 --- a/packages/@react-native/tester/js/components/RNTesterTheme.js +++ b/packages/@react-native/tester/js/components/RNTesterTheme.js @@ -8,6 +8,7 @@ * @format */ +import type {ImageSource} from 'react-native/Libraries/Image/ImageSource'; import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; import * as React from 'react'; @@ -42,6 +43,13 @@ export type RNTesterTheme = { ToolbarColor: ColorValue, BackgroundColor: ColorValue, BorderColor: ColorValue, + + NavBarLabelActiveColor: ColorValue, + NavBarLabelInactiveColor: ColorValue, + NavBarComponentsActiveIcon: ImageSource, + NavBarComponentsInactiveIcon: ImageSource, + NavBarAPIsActiveIcon: ImageSource, + NavBarAPIsInactiveIcon: ImageSource, ... }; @@ -75,6 +83,13 @@ export const RNTesterLightTheme = { ToolbarColor: '#e9eaedff', BackgroundColor: '#f3f8ffff', BorderColor: '#005dffff', + + NavBarLabelActiveColor: '#5e5f62ff', + NavBarLabelInactiveColor: '#b1b4baff', + NavBarComponentsActiveIcon: require('./../assets/bottom-nav-components-icon-dark.png'), + NavBarComponentsInactiveIcon: require('./../assets/bottom-nav-components-icon-light.png'), + NavBarAPIsActiveIcon: require('./../assets/bottom-nav-apis-icon-dark.png'), + NavBarAPIsInactiveIcon: require('./../assets/bottom-nav-apis-icon-light.png'), }; export const RNTesterDarkTheme = { @@ -107,6 +122,13 @@ export const RNTesterDarkTheme = { ToolbarColor: '#3c3c43ff', BackgroundColor: '#0c0700ff', BorderColor: '#005dffff', + + NavBarLabelActiveColor: '#b1b4baff', + NavBarLabelInactiveColor: '#5e5f62ff', + NavBarComponentsActiveIcon: require('./../assets/bottom-nav-components-icon-light.png'), + NavBarComponentsInactiveIcon: require('./../assets/bottom-nav-components-icon-dark.png'), + NavBarAPIsActiveIcon: require('./../assets/bottom-nav-apis-icon-light.png'), + NavBarAPIsInactiveIcon: require('./../assets/bottom-nav-apis-icon-dark.png'), }; export const themes = {light: RNTesterLightTheme, dark: RNTesterDarkTheme}; diff --git a/packages/@react-native/tester/js/examples/Appearance/AppearanceExample.js b/packages/@react-native/tester/js/examples/Appearance/AppearanceExample.js index 8d7c3472465..d688e29e03f 100644 --- a/packages/@react-native/tester/js/examples/Appearance/AppearanceExample.js +++ b/packages/@react-native/tester/js/examples/Appearance/AppearanceExample.js @@ -96,40 +96,41 @@ const ColorShowcase = (props: {themeName: string}) => ( {props.themeName} - {Object.keys(theme).map(key => ( - - - - - {key} - - - {typeof theme[key] === 'string' - ? theme[key] - : JSON.stringify(theme[key])} - - - - ))} + {Object.keys(theme).map( + key => + typeof theme[key] === 'string' && ( + + + + + {key} + + + {theme[key]} + + + + ), + )} ); }} diff --git a/packages/@react-native/tester/overrides.json b/packages/@react-native/tester/overrides.json index 5e36dad77e9..6d559a076bb 100644 --- a/packages/@react-native/tester/overrides.json +++ b/packages/@react-native/tester/overrides.json @@ -1,18 +1,18 @@ { - "baseVersion": "0.75.0-nightly-20240307-ff03b149e", + "baseVersion": "0.75.0-nightly-20240321-7d180d712", "overrides": [ { "type": "copy", "directory": "js/assets", "baseDirectory": "packages/rn-tester/js/assets", - "baseHash": "abb5cf85647531d0c8f89c7281c3b6808eec12e8", + "baseHash": "414d1c3b1d436448a773bb772f0ec93cf2402055", "issue": 4054 }, { "type": "copy", "directory": "js/components", "baseDirectory": "packages/rn-tester/js/components", - "baseHash": "1eda76bc2c7d63409b04b40a47dbe02488e08e45", + "baseHash": "4e779d653a3fb4c692026045a003a1716127d4b7", "issue": 4054 }, { @@ -61,7 +61,7 @@ "type": "copy", "directory": "js/examples/Appearance", "baseDirectory": "packages/rn-tester/js/examples/Appearance", - "baseHash": "dc660f8ee6a129b7ed8f4ec7f299ca6c73ac781e", + "baseHash": "6e1c89669e9495d50d06e27c6c203012a6c480da", "issue": 4054 }, { @@ -523,7 +523,7 @@ "type": "copy", "file": "package.json", "baseFile": "packages/rn-tester/package.json", - "baseHash": "e21499711af0cee6e00c28af01d3b87c501fa0b7", + "baseHash": "2df1789eee76067765485f86d45809d93a65fc92", "issue": 4054 } ] diff --git a/packages/@react-native/tester/package.json b/packages/@react-native/tester/package.json index f66b9f6eecf..b9141d86c34 100644 --- a/packages/@react-native/tester/package.json +++ b/packages/@react-native/tester/package.json @@ -6,7 +6,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/facebook/react-native.git", + "url": "git+https://github.com/facebook/react-native.git", "directory": "packages/rn-tester" }, "engines": { diff --git a/packages/@rnw-scripts/babel-react-native-config/package.json b/packages/@rnw-scripts/babel-react-native-config/package.json index c3d04128e6c..21b6dd88e8a 100644 --- a/packages/@rnw-scripts/babel-react-native-config/package.json +++ b/packages/@rnw-scripts/babel-react-native-config/package.json @@ -11,12 +11,12 @@ }, "dependencies": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/babel-preset": "0.75.0-nightly-20240321-7d180d712", "babel-plugin-transform-flow-enums": "^0.0.2" }, "devDependencies": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/babel-preset": "0.75.0-nightly-20240321-7d180d712", "eslint": "^8.19.0", "prettier": "2.8.8" }, diff --git a/packages/@rnw-scripts/eslint-config/package.json b/packages/@rnw-scripts/eslint-config/package.json index 763fd814405..7066d59753f 100644 --- a/packages/@rnw-scripts/eslint-config/package.json +++ b/packages/@rnw-scripts/eslint-config/package.json @@ -12,7 +12,7 @@ "@babel/core": "^7.20.0", "@babel/eslint-parser": "^7.20.0", "@microsoft/eslint-plugin-sdl": "^0.2.0", - "@react-native/eslint-config": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/eslint-config": "0.75.0-nightly-20240321-7d180d712", "eslint-config-prettier": "^8.5.0", "eslint-plugin-ft-flow": "^2.0.1" }, diff --git a/packages/@rnw-scripts/metro-dev-config/package.json b/packages/@rnw-scripts/metro-dev-config/package.json index 2504645e90e..5a9d10d3d9e 100644 --- a/packages/@rnw-scripts/metro-dev-config/package.json +++ b/packages/@rnw-scripts/metro-dev-config/package.json @@ -17,7 +17,7 @@ "lint:fix": "rnw-scripts lint:fix" }, "dependencies": { - "@react-native/metro-config": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/metro-config": "0.75.0-nightly-20240321-7d180d712", "@rnx-kit/metro-config": "^1.3.5", "@rnx-kit/metro-plugin-duplicates-checker": "^2.1.0", "@rnx-kit/metro-serializer": "^1.0.11", @@ -31,6 +31,6 @@ "prettier": "2.8.8" }, "engines": { - "node": ">= 16.0.0" + "node": ">= 18" } } diff --git a/packages/e2e-test-app-fabric/package.json b/packages/e2e-test-app-fabric/package.json index 13a53c4d978..79e2a05ca63 100644 --- a/packages/e2e-test-app-fabric/package.json +++ b/packages/e2e-test-app-fabric/package.json @@ -19,7 +19,7 @@ "@typescript-eslint/eslint-plugin": "^5.21.0", "@typescript-eslint/parser": "^5.21.0", "react": "18.2.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-windows": "^0.0.0-canary.811" }, "devDependencies": { @@ -30,7 +30,7 @@ "@babel/runtime": "^7.20.0", "@react-native-windows/automation": "^0.3.233", "@react-native-windows/automation-commands": "^0.1.253", - "@react-native/metro-config": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/metro-config": "0.75.0-nightly-20240321-7d180d712", "@rnw-scripts/babel-node-config": "2.3.2", "@rnw-scripts/babel-react-native-config": "0.0.0", "@rnw-scripts/eslint-config": "1.2.13", diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap index a9b1efa8420..e7e5fa62802 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/snapshotPages.test.js.snap @@ -11129,7 +11129,6 @@ exports[`snapshotAllPages FlatList 1`] = ` renderItem={[Function]} scrollEventThrottle={0.0001} stickyHeaderIndices={[]} - style={{}} viewabilityConfig={ { "minimumViewTime": 3000, @@ -47617,7 +47616,6 @@ exports[`snapshotAllPages ScrollViewAnimated 1`] = ` horizontal={true} onScroll={[Function]} scrollEventThrottle={16} - style={{}} > const &longLivedObjectCollection, facebook::jsi::Runtime &runtime) - : longLivedObjectCollection_(longLivedObjectCollection), runtime_(runtime) {} + : LongLivedObject(runtime), runtime_(runtime), longLivedObjectCollection_(longLivedObjectCollection) {} LongLivedJsiRuntime(LongLivedJsiRuntime const &) = delete; diff --git a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp index 383f09ad44b..bc57f6711ff 100644 --- a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp +++ b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp @@ -8,25 +8,33 @@ namespace winrt::Microsoft::ReactNative { // CallInvoker implementation based on JSDispatcher. struct AbiCallInvoker final : facebook::react::CallInvoker { - AbiCallInvoker(IReactDispatcher const &jsDispatcher) : m_jsDispatcher(jsDispatcher) {} + AbiCallInvoker(IReactContext const &context) : m_context(context) {} void invokeAsync(std::function &&func) noexcept override { - m_jsDispatcher.Post([func = std::move(func)]() { func(); }); + m_context.JSDispatcher().Post([func = std::move(func)]() { func(); }); } - void invokeSync(std::function && /*func*/) override { + void invokeAsync(facebook::react::CallFunc &&func) noexcept override { + // If async is allowed to run sync if already on the JS thread, this could be replaced with just the ExecuteJsi call + m_context.JSDispatcher().Post([context = m_context, func = std::move(func)]() { + winrt::Microsoft::ReactNative::ExecuteJsi(context, std::move(func)); + }); + } + + virtual void invokeSync(facebook::react::CallFunc &&func) override { // Throwing an exception in this method matches the behavior of // Instance::JSCallInvoker::invokeSync in react-native\ReactCommon\cxxreact\Instance.cpp + UNREFERENCED_PARAMETER(func); throw std::runtime_error("Synchronous native -> JS calls are currently not supported."); } private: - IReactDispatcher m_jsDispatcher{nullptr}; + IReactContext m_context{nullptr}; }; // Creates CallInvoker based on JSDispatcher. -std::shared_ptr MakeAbiCallInvoker(IReactDispatcher const &jsDispatcher) noexcept { - return std::make_shared(jsDispatcher); +std::shared_ptr MakeAbiCallInvoker(IReactContext const &context) noexcept { + return std::make_shared(context); } } // namespace winrt::Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h index 6df9293c1ea..3308662a74c 100644 --- a/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h +++ b/vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.h @@ -11,7 +11,7 @@ namespace winrt::Microsoft::ReactNative { // Creates CallInvoker based on JSDispatcher. -std::shared_ptr MakeAbiCallInvoker(IReactDispatcher const &jsDispatcher) noexcept; +std::shared_ptr MakeAbiCallInvoker(IReactContext const &context) noexcept; template < typename TTurboModule, @@ -23,7 +23,7 @@ void AddTurboModuleProvider(IReactPackageBuilder const &packageBuilder, std::wst // We expect the initializer to be called immediately for TurboModules moduleBuilder.AddInitializer([&abiTurboModule](IReactContext const &context) mutable { TryGetOrCreateContextRuntime(ReactContext{context}); // Ensure the JSI runtime is created. - auto callInvoker = MakeAbiCallInvoker(context.JSDispatcher()); + auto callInvoker = MakeAbiCallInvoker(context); auto turboModule = std::make_shared(callInvoker); abiTurboModule = winrt::make(std::move(turboModule)); }); diff --git a/vnext/Microsoft.ReactNative/ComponentView.idl b/vnext/Microsoft.ReactNative/ComponentView.idl index af64f860ec2..527d08c033b 100644 --- a/vnext/Microsoft.ReactNative/ComponentView.idl +++ b/vnext/Microsoft.ReactNative/ComponentView.idl @@ -20,21 +20,6 @@ namespace Microsoft.ReactNative [experimental] delegate Object StateUpdateMutation(Object props); - [webhosthidden] - [experimental] - enum EventPriority - { - SynchronousUnbatched, - SynchronousBatched, - AsynchronousUnbatched, - AsynchronousBatched, - - Sync = SynchronousUnbatched, - Work = SynchronousBatched, - Interactive = AsynchronousUnbatched, - Deferred = AsynchronousBatched - }; - [flags] [webhosthidden] [experimental] @@ -55,9 +40,7 @@ namespace Microsoft.ReactNative { Object Data { get; }; void UpdateState(Object data); - void UpdateStateWithPriority(Object data, EventPriority priority); void UpdateStateWithMutation(StateUpdateMutation mutation); - void UpdateStateWithMutationAndPriority(StateUpdateMutation mutation, EventPriority priority); }; [experimental] diff --git a/vnext/Microsoft.ReactNative/Fabric/AbiState.cpp b/vnext/Microsoft.ReactNative/Fabric/AbiState.cpp index 95fe2c6335e..b2f6ea81f94 100644 --- a/vnext/Microsoft.ReactNative/Fabric/AbiState.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/AbiState.cpp @@ -19,53 +19,11 @@ void AbiComponentState::UpdateState(const winrt::Windows::Foundation::IInspectab m_state->updateState(std::move(state)); } -// Verify winrt::Microsoft::ReactNative::EventPriority and facebook::react::EventPriority are in sync -static_assert( - winrt::Microsoft::ReactNative::EventPriority::SynchronousUnbatched == - static_cast(facebook::react::EventPriority::SynchronousUnbatched)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::SynchronousBatched == - static_cast(facebook::react::EventPriority::SynchronousBatched)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::AsynchronousUnbatched == - static_cast(facebook::react::EventPriority::AsynchronousUnbatched)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::AsynchronousBatched == - static_cast(facebook::react::EventPriority::AsynchronousBatched)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::Sync == - static_cast(facebook::react::EventPriority::Sync)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::Work == - static_cast(facebook::react::EventPriority::Work)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::Interactive == - static_cast(facebook::react::EventPriority::Interactive)); -static_assert( - winrt::Microsoft::ReactNative::EventPriority::Deferred == - static_cast(facebook::react::EventPriority::Deferred)); - -void AbiComponentState::UpdateStateWithPriority( - const winrt::Windows::Foundation::IInspectable &data, - winrt::Microsoft::ReactNative::EventPriority priority) noexcept { - AbiStateData state; - state.userdata = data; - m_state->updateState(std::move(state), static_cast(priority)); -} - void AbiComponentState::UpdateStateWithMutation( const winrt::Microsoft::ReactNative::StateUpdateMutation &mutation) noexcept { - UpdateStateWithMutationAndPriority(mutation, winrt::Microsoft::ReactNative::EventPriority::AsynchronousUnbatched); -} - -void AbiComponentState::UpdateStateWithMutationAndPriority( - const winrt::Microsoft::ReactNative::StateUpdateMutation &mutation, - winrt::Microsoft::ReactNative::EventPriority priority) noexcept { - m_state->updateState( - [mutation](const AbiStateData &oldData) { - return std::make_shared(mutation(oldData.userdata)); - }, - static_cast(priority)); + m_state->updateState([mutation](const AbiStateData &oldData) { + return std::make_shared(mutation(oldData.userdata)); + }); } } // namespace Microsoft::ReactNative diff --git a/vnext/Microsoft.ReactNative/Fabric/AbiState.h b/vnext/Microsoft.ReactNative/Fabric/AbiState.h index 939f4fb2baa..485e8296451 100644 --- a/vnext/Microsoft.ReactNative/Fabric/AbiState.h +++ b/vnext/Microsoft.ReactNative/Fabric/AbiState.h @@ -23,13 +23,7 @@ struct AbiComponentState : winrt::implements const> m_state; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp index 84089f1892c..2f8715a6a6c 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp @@ -1148,7 +1148,7 @@ void ScrollViewComponentView::ensureVisual() noexcept { updateStateWithContentOffset(); auto eventEmitter = GetEventEmitter(); if (eventEmitter) { - facebook::react::ScrollViewMetrics scrollMetrics; + facebook::react::ScrollViewEventEmitter::Metrics scrollMetrics; scrollMetrics.containerSize.height = m_layoutMetrics.frame.size.height; scrollMetrics.containerSize.width = m_layoutMetrics.frame.size.width; scrollMetrics.contentOffset.x = args.Position().x / m_layoutMetrics.pointScaleFactor; diff --git a/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp b/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp index 43ddbeb26b9..28ac70ba967 100644 --- a/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp @@ -80,20 +80,8 @@ void FabricUIManager::installFabricUIManager() noexcept { runtimeExecutor = [runtimeScheduler](std::function &&callback) { runtimeScheduler->scheduleWork(std::move(callback)); }; - facebook::react::EventBeat::Factory synchronousBeatFactory = - [runtimeExecutor, context = m_context, runtimeScheduler]( - facebook::react::EventBeat::SharedOwnerBox const &ownerBox) { - return std::make_unique(ownerBox, context, runtimeExecutor, runtimeScheduler); - }; - toolbox.synchronousEventBeatFactory = synchronousBeatFactory; } else { runtimeExecutor = SchedulerSettings::GetRuntimeExecutor(m_context.Properties()); - - facebook::react::EventBeat::Factory synchronousBeatFactory = - [runtimeExecutor, context = m_context](facebook::react::EventBeat::SharedOwnerBox const &ownerBox) { - return std::make_unique(ownerBox, context, runtimeExecutor); - }; - toolbox.synchronousEventBeatFactory = synchronousBeatFactory; } facebook::react::EventBeat::Factory asynchronousBeatFactory = diff --git a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp index 091e0c52f48..f082e94f59e 100644 --- a/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp @@ -39,19 +39,11 @@ void HostPlatformViewEventEmitter::onBlur() const { #pragma mark - Mouse Events void HostPlatformViewEventEmitter::onMouseEnter(PointerEvent const &pointerEvent) const { - dispatchEvent( - "mouseEnter", - std::make_shared(pointerEvent), - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + dispatchEvent("mouseEnter", std::make_shared(pointerEvent), RawEvent::Category::ContinuousStart); } void HostPlatformViewEventEmitter::onMouseLeave(PointerEvent const &pointerEvent) const { - dispatchEvent( - "mouseLeave", - std::make_shared(pointerEvent), - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + dispatchEvent("mouseLeave", std::make_shared(pointerEvent), RawEvent::Category::ContinuousStart); } } // namespace facebook::react diff --git a/vnext/Microsoft.ReactNative/packages.lock.json b/vnext/Microsoft.ReactNative/packages.lock.json index 423d84bb0ba..ab4537703ef 100644 --- a/vnext/Microsoft.ReactNative/packages.lock.json +++ b/vnext/Microsoft.ReactNative/packages.lock.json @@ -24,21 +24,21 @@ "Microsoft.SourceLink.Common": "1.1.1" } }, + "Microsoft.UI.Xaml": { + "type": "Direct", + "requested": "[2.8.0, )", + "resolved": "2.8.0", + "contentHash": "vxdHxTr63s5KVtNddMFpgvjBjUH50z7seq/5jLWmmSuf8poxg+sXrywkofUdE8ZstbpO9y3FL/IXXUcPYbeesA==", + "dependencies": { + "Microsoft.Web.WebView2": "1.0.1264.42" + } + }, "Microsoft.Windows.CppWinRT": { "type": "Direct", "requested": "[2.0.230706.1, )", "resolved": "2.0.230706.1", "contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ==" }, - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } - }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", "resolved": "1.1.1", @@ -49,10 +49,10 @@ "resolved": "1.1.1", "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==" }, - "Microsoft.Windows.SDK.BuildTools": { + "Microsoft.Web.WebView2": { "type": "Transitive", - "resolved": "10.0.22621.756", - "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA==" + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" }, "common": { "type": "Project", @@ -79,80 +79,52 @@ } }, "native,Version=v0.0/win10-arm": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-arm-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-arm64-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x64": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x64-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x86": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } }, "native,Version=v0.0/win10-x86-aot": { - "Microsoft.WindowsAppSDK": { - "type": "Direct", - "requested": "[1.5.240227000, )", - "resolved": "1.5.240227000", - "contentHash": "6rESOsREi8534J7IDpNfFYPvxQaSleXKt4A7ZYPeQyckNMQ0o1W0jZ420bJbEMz9Cw/S/8IbpPftLLZ9w/GTCQ==", - "dependencies": { - "Microsoft.Windows.SDK.BuildTools": "10.0.22621.756" - } + "Microsoft.Web.WebView2": { + "type": "Transitive", + "resolved": "1.0.1264.42", + "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA==" } } } diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp new file mode 100644 index 00000000000..5607cf18f6d --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp @@ -0,0 +1,61 @@ +/* + * 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 "JSExecutor.h" + +#include "RAMBundleRegistry.h" + +#include +#include +#include + +#include + +namespace facebook::react { + +std::string JSExecutor::getSyntheticBundlePath( + uint32_t bundleId, + const std::string& bundlePath) { + if (bundleId == RAMBundleRegistry::MAIN_BUNDLE_ID) { + return bundlePath; + } + return folly::to("seg-", bundleId, ".js"); +} + +double JSExecutor::performanceNow() { + auto time = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast( + time.time_since_epoch()) + .count(); + + constexpr double NANOSECONDS_IN_MILLISECOND = 1000000.0; + return duration / NANOSECONDS_IN_MILLISECOND; +} + +void JSExecutor::addConsoleMessage(jsi::Runtime& runtime, jsinspector_modern::ConsoleMessage message){ + return; +} + +bool JSExecutor::supportsConsole() const { + return false; +} + +std::unique_ptr +JSExecutor::createAgentDelegate( + jsinspector_modern::FrontendChannel frontendChannel, + jsinspector_modern::SessionState& sessionState, + std::unique_ptr, + const jsinspector_modern::ExecutionContextDescription& + executionContextDescription, + RuntimeExecutor runtimeExecutor) { + (void)executionContextDescription; + (void)runtimeExecutor; + return std::make_unique( + std::move(frontendChannel), sessionState, getDescription()); +} + +} // namespace facebook::react \ No newline at end of file diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.h b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.h new file mode 100644 index 00000000000..20b0c21a965 --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef RN_EXPORT +#define RN_EXPORT __attribute__((visibility("default"))) +#endif + +namespace facebook::react { + +class JSBigString; +class JSExecutor; +class JSModulesUnbundle; +class MessageQueueThread; +class ModuleRegistry; +class RAMBundleRegistry; + +// This interface describes the delegate interface required by +// Executor implementations to call from JS into native code. +class ExecutorDelegate { + public: + virtual ~ExecutorDelegate() {} + + virtual std::shared_ptr getModuleRegistry() = 0; + + virtual void callNativeModules( + JSExecutor& executor, + folly::dynamic&& calls, + bool isEndOfBatch) = 0; + virtual MethodCallResult callSerializableNativeHook( + JSExecutor& executor, + unsigned int moduleId, + unsigned int methodId, + folly::dynamic&& args) = 0; +}; + +class JSExecutorFactory { + public: + virtual std::unique_ptr createJSExecutor( + std::shared_ptr delegate, + std::shared_ptr jsQueue) = 0; + virtual ~JSExecutorFactory() {} +}; + +class RN_EXPORT JSExecutor : public jsinspector_modern::RuntimeTargetDelegate { + public: + /** + * Prepares the JS runtime for React Native by installing global variables. + * Called once before any JS is evaluated. + */ + virtual void initializeRuntime() = 0; + /** + * Execute an application script bundle in the JS context. + */ + virtual void loadBundle( + std::unique_ptr script, + std::string sourceURL) = 0; + + /** + * Add an application "RAM" bundle registry + */ + virtual void setBundleRegistry( + std::unique_ptr bundleRegistry) = 0; + + /** + * Register a file path for an additional "RAM" bundle + */ + virtual void registerBundle( + uint32_t bundleId, + const std::string& bundlePath) = 0; + + /** + * Executes BatchedBridge.callFunctionReturnFlushedQueue with the module ID, + * method ID and optional additional arguments in JS. The executor is + * responsible for using Bridge->callNativeModules to invoke any necessary + * native modules methods. + */ + virtual void callFunction( + const std::string& moduleId, + const std::string& methodId, + const folly::dynamic& arguments) = 0; + + /** + * Executes BatchedBridge.invokeCallbackAndReturnFlushedQueue with the cbID, + * and optional additional arguments in JS and returns the next queue. The + * executor is responsible for using Bridge->callNativeModules to invoke any + * necessary native modules methods. + */ + virtual void invokeCallback( + const double callbackId, + const folly::dynamic& arguments) = 0; + + virtual void setGlobalVariable( + std::string propName, + std::unique_ptr jsonValue) = 0; + + virtual void* getJavaScriptContext() { + return nullptr; + } + + /** + * Returns whether or not the underlying executor supports debugging via the + * Chrome remote debugging protocol. If true, the executor should also + * override the \c createAgentDelegate method. + */ + virtual bool isInspectable() { + return false; + } + + /** + * The description is displayed in the dev menu, if there is one in + * this build. There is a default, but if this method returns a + * non-empty string, it will be used instead. + */ + virtual std::string getDescription() = 0; + + virtual void handleMemoryPressure([[maybe_unused]] int pressureLevel) {} + + virtual void destroy() {} + virtual ~JSExecutor() override {} + + virtual void flush() {} + + static std::string getSyntheticBundlePath( + uint32_t bundleId, + const std::string& bundlePath); + + static double performanceNow(); + + virtual void addConsoleMessage(jsi::Runtime& runtime, jsinspector_modern::ConsoleMessage message); + + virtual bool supportsConsole() const; + + /** + * Create a RuntimeAgentDelegate that can be used to debug the JS VM instance. + */ + virtual std::unique_ptr + createAgentDelegate( + jsinspector_modern::FrontendChannel frontendChannel, + jsinspector_modern::SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const jsinspector_modern::ExecutionContextDescription& + executionContextDescription, + RuntimeExecutor runtimeExecutor) override; +}; + +} // namespace facebook::react \ No newline at end of file diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp new file mode 100644 index 00000000000..494dfd927da --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp @@ -0,0 +1,351 @@ +/* + * 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 "NativeToJsBridge.h" + +#include +#include +#include +#include +#include + +#include "ErrorUtils.h" +#include "Instance.h" +#include "JSBigString.h" +#include "MessageQueueThread.h" +#include "MethodCall.h" +#include "ModuleRegistry.h" +#include "MoveWrapper.h" +#include "RAMBundleRegistry.h" +#include "SystraceSection.h" + +#include + +#ifdef WITH_FBSYSTRACE +#include + +using fbsystrace::FbSystraceAsyncFlow; +#endif + +namespace facebook::react { + +// This class manages calls from JS to native code. +class JsToNativeBridge : public react::ExecutorDelegate { + public: + JsToNativeBridge( + std::shared_ptr registry, + std::shared_ptr callback) + : m_registry(registry), m_callback(callback) {} + + std::shared_ptr getModuleRegistry() override { + return m_registry; + } + + bool isBatchActive() { + return m_batchHadNativeModuleOrTurboModuleCalls; + } + + void callNativeModules( + [[maybe_unused]] JSExecutor& executor, + folly::dynamic&& calls, + bool isEndOfBatch) override { + CHECK(m_registry || calls.empty()) + << "native module calls cannot be completed with no native modules"; + m_batchHadNativeModuleOrTurboModuleCalls = + m_batchHadNativeModuleOrTurboModuleCalls || !calls.empty(); + + std::vector methodCalls = parseMethodCalls(std::move(calls)); + BridgeNativeModulePerfLogger::asyncMethodCallBatchPreprocessEnd( + (int)methodCalls.size()); + + // An exception anywhere in here stops processing of the batch. This + // was the behavior of the Android bridge, and since exception handling + // terminates the whole bridge, there's not much point in continuing. + for (auto& call : methodCalls) { + m_registry->callNativeMethod( + call.moduleId, call.methodId, std::move(call.arguments), call.callId); + } + if (isEndOfBatch) { + // onBatchComplete will be called on the native (module) queue, but + // decrementPendingJSCalls will be called sync. Be aware that the bridge + // may still be processing native calls when the bridge idle signaler + // fires. + if (m_batchHadNativeModuleOrTurboModuleCalls) { + m_callback->onBatchComplete(); + m_batchHadNativeModuleOrTurboModuleCalls = false; + } + m_callback->decrementPendingJSCalls(); + } + } + + MethodCallResult callSerializableNativeHook( + [[maybe_unused]] JSExecutor& executor, + unsigned int moduleId, + unsigned int methodId, + folly::dynamic&& args) override { + return m_registry->callSerializableNativeHook( + moduleId, methodId, std::move(args)); + } + + void recordTurboModuleAsyncMethodCall() noexcept { + m_batchHadNativeModuleOrTurboModuleCalls = true; + } + + private: + // These methods are always invoked from an Executor. The NativeToJsBridge + // keeps a reference to the executor, and when destroy() is called, the + // executor is destroyed synchronously on its queue. + std::shared_ptr m_registry; + std::shared_ptr m_callback; + bool m_batchHadNativeModuleOrTurboModuleCalls = false; +}; + +NativeToJsBridge::NativeToJsBridge( + JSExecutorFactory* jsExecutorFactory, + std::shared_ptr registry, + std::shared_ptr jsQueue, + std::shared_ptr callback) + : m_destroyed(std::make_shared(false)), + m_delegate(std::make_shared(registry, callback)), + m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue)), + m_executorMessageQueueThread(std::move(jsQueue)), + m_inspectable(m_executor->isInspectable()) {} + +// This must be called on the same thread on which the constructor was called. +NativeToJsBridge::~NativeToJsBridge() { + CHECK(*m_destroyed) + << "NativeToJsBridge::destroy() must be called before deallocating the NativeToJsBridge!"; +} + +void NativeToJsBridge::initializeRuntime() { + runOnExecutorQueue( + [](JSExecutor* executor) mutable { executor->initializeRuntime(); }); +} + +void NativeToJsBridge::loadBundle( + std::unique_ptr bundleRegistry, + std::unique_ptr startupScript, + std::string startupScriptSourceURL) { + runOnExecutorQueue( + [this, + bundleRegistryWrap = makeMoveWrapper(std::move(bundleRegistry)), + startupScript = makeMoveWrapper(std::move(startupScript)), + startupScriptSourceURL = + std::move(startupScriptSourceURL)](JSExecutor* executor) mutable { + auto bundleRegistry = bundleRegistryWrap.move(); + if (bundleRegistry) { + executor->setBundleRegistry(std::move(bundleRegistry)); + } + try { + executor->loadBundle( + std::move(*startupScript), std::move(startupScriptSourceURL)); + } catch (...) { + m_applicationScriptHasFailure = true; + throw; + } + }); +} + +void NativeToJsBridge::loadBundleSync( + std::unique_ptr bundleRegistry, + std::unique_ptr startupScript, + std::string startupScriptSourceURL) { + if (bundleRegistry) { + m_executor->setBundleRegistry(std::move(bundleRegistry)); + } + try { + m_executor->loadBundle( + std::move(startupScript), std::move(startupScriptSourceURL)); + } catch (...) { + m_applicationScriptHasFailure = true; + throw; + } +} + +void NativeToJsBridge::callFunction( + std::string&& module, + std::string&& method, + folly::dynamic&& arguments) { + int systraceCookie = -1; +#ifdef WITH_FBSYSTRACE + systraceCookie = m_systraceCookie++; + FbSystraceAsyncFlow::begin( + TRACE_TAG_REACT_CXX_BRIDGE, "JSCall", systraceCookie); +#endif + + runOnExecutorQueue([this, + module = std::move(module), + method = std::move(method), + arguments = std::move(arguments), + systraceCookie](JSExecutor* executor) { + if (m_applicationScriptHasFailure) { + LOG(ERROR) + << "Attempting to call JS function on a bad application bundle: " + << module.c_str() << "." << method.c_str() << "()"; + throw std::runtime_error( + "Attempting to call JS function on a bad application bundle: " + + module + "." + method + "()"); + } + +#ifdef WITH_FBSYSTRACE + FbSystraceAsyncFlow::end( + TRACE_TAG_REACT_CXX_BRIDGE, "JSCall", systraceCookie); + SystraceSection s( + "NativeToJsBridge::callFunction", "module", module, "method", method); +#else + (void)(systraceCookie); +#endif + // This is safe because we are running on the executor's thread: it won't + // destruct until after it's been unregistered (which we check above) and + // that will happen on this thread + executor->callFunction(module, method, arguments); + }); +} + +void NativeToJsBridge::invokeCallback( + double callbackId, + folly::dynamic&& arguments) { + int systraceCookie = -1; +#ifdef WITH_FBSYSTRACE + systraceCookie = m_systraceCookie++; + FbSystraceAsyncFlow::begin( + TRACE_TAG_REACT_CXX_BRIDGE, "", systraceCookie); +#endif + + runOnExecutorQueue( + [this, callbackId, arguments = std::move(arguments), systraceCookie]( + JSExecutor* executor) { + if (m_applicationScriptHasFailure) { + LOG(ERROR) + << "Attempting to call JS callback on a bad application bundle: " + << callbackId; + throw std::runtime_error( + "Attempting to invoke JS callback on a bad application bundle."); + } +#ifdef WITH_FBSYSTRACE + FbSystraceAsyncFlow::end( + TRACE_TAG_REACT_CXX_BRIDGE, "", systraceCookie); + SystraceSection s("NativeToJsBridge::invokeCallback"); +#else + (void)(systraceCookie); +#endif + executor->invokeCallback(callbackId, arguments); + }); +} + +void NativeToJsBridge::registerBundle( + uint32_t bundleId, + const std::string& bundlePath) { + runOnExecutorQueue([bundleId, bundlePath](JSExecutor* executor) { + executor->registerBundle(bundleId, bundlePath); + }); +} + +void NativeToJsBridge::setGlobalVariable( + std::string propName, + std::unique_ptr jsonValue) { + runOnExecutorQueue([propName = std::move(propName), + jsonValue = makeMoveWrapper(std::move(jsonValue))]( + JSExecutor* executor) mutable { + executor->setGlobalVariable(propName, jsonValue.move()); + }); +} + +void* NativeToJsBridge::getJavaScriptContext() { + // TODO(cjhopman): this seems unsafe unless we require that it is only called + // on the main js queue. + return m_executor->getJavaScriptContext(); +} + +bool NativeToJsBridge::isInspectable() { + return m_inspectable; +} + +bool NativeToJsBridge::isBatchActive() { + return m_delegate->isBatchActive(); +} + +void NativeToJsBridge::handleMemoryPressure(int pressureLevel) { + runOnExecutorQueue([=](JSExecutor* executor) { + executor->handleMemoryPressure(pressureLevel); + }); +} + +void NativeToJsBridge::destroy() { + // All calls made through runOnExecutorQueue have an early exit if + // m_destroyed is true. Setting this before the runOnQueueSync will cause + // pending work to be cancelled and we won't have to wait for it. + *m_destroyed = true; + m_executorMessageQueueThread->runOnQueueSync([this] { + m_executor->destroy(); + m_executorMessageQueueThread->quitSynchronous(); + m_executor = nullptr; + }); +} + +void NativeToJsBridge::runOnExecutorQueue( + std::function&& task) noexcept { + if (*m_destroyed) { + return; + } + + std::shared_ptr isDestroyed = m_destroyed; + m_executorMessageQueueThread->runOnQueue( + [this, isDestroyed, task = std::move(task)] { + if (*isDestroyed) { + return; + } + + // The executor is guaranteed to be valid for the duration of the task + // because: + // 1. the executor is only destroyed after it is unregistered + // 2. the executor is unregistered on this queue + // 3. we just confirmed that the executor hasn't been unregistered above + task(m_executor.get()); + }); +} + +std::shared_ptr +NativeToJsBridge::getDecoratedNativeMethodCallInvoker( + std::shared_ptr nativeMethodCallInvoker) const { + class NativeMethodCallInvokerImpl : public NativeMethodCallInvoker { + private: + std::weak_ptr m_jsToNativeBridge; + std::shared_ptr m_nativeInvoker; + + public: + NativeMethodCallInvokerImpl( + std::weak_ptr jsToNativeBridge, + std::shared_ptr nativeInvoker) + : m_jsToNativeBridge(std::move(jsToNativeBridge)), + m_nativeInvoker(std::move(nativeInvoker)) {} + + void invokeAsync( + const std::string& methodName, + NativeMethodCallFunc&& func) noexcept override { + if (auto strongJsToNativeBridge = m_jsToNativeBridge.lock()) { + strongJsToNativeBridge->recordTurboModuleAsyncMethodCall(); + } + m_nativeInvoker->invokeAsync(methodName, std::move(func)); + } + + void invokeSync(const std::string& methodName, NativeMethodCallFunc&& func) + override { + m_nativeInvoker->invokeSync(methodName, std::move(func)); + } + }; + + return std::make_shared( + m_delegate, std::move(nativeMethodCallInvoker)); +} + +jsinspector_modern::RuntimeTargetDelegate& +NativeToJsBridge::getInspectorTargetDelegate() { + return *m_executor; +} + +} // namespace facebook::react \ No newline at end of file diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h index af9f8d1a2a8..6c90bda14a8 100644 --- a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h @@ -19,12 +19,11 @@ namespace react { class CallbackWrapper : public LongLivedObject { private: CallbackWrapper( - jsi::Function &&callback, - jsi::Runtime &runtime, + jsi::Function&& callback, + jsi::Runtime& runtime, std::shared_ptr jsInvoker) - : longLivedObjectCollection_(), + : LongLivedObject(runtime), callback_(std::move(callback)), - runtime_(runtime), jsInvoker_(std::move(jsInvoker)) {} CallbackWrapper( @@ -32,9 +31,8 @@ class CallbackWrapper : public LongLivedObject { jsi::Function &&callback, jsi::Runtime &runtime, std::shared_ptr jsInvoker) - : longLivedObjectCollection_(longLivedObjectCollection), + : LongLivedObject(runtime), callback_(std::move(callback)), - runtime_(runtime), jsInvoker_(std::move(jsInvoker)) {} // Use a weak_ptr to avoid a retain cycle: LongLivedObjectCollection owns all @@ -42,7 +40,6 @@ class CallbackWrapper : public LongLivedObject { // LongLivedObjectCollection. std::weak_ptr longLivedObjectCollection_; jsi::Function callback_; - jsi::Runtime &runtime_; std::shared_ptr jsInvoker_; public: @@ -50,9 +47,9 @@ class CallbackWrapper : public LongLivedObject { jsi::Function &&callback, jsi::Runtime &runtime, std::shared_ptr jsInvoker) { - auto wrapper = std::shared_ptr( - new CallbackWrapper(std::move(callback), runtime, jsInvoker)); - LongLivedObjectCollection::get().add(wrapper); + auto wrapper = std::shared_ptr(new CallbackWrapper( + std::move(callback), runtime, std::move(jsInvoker))); + LongLivedObjectCollection::get(runtime).add(wrapper); return wrapper; } diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.cpp index 60d4ed847eb..b8609dcc892 100644 --- a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.cpp +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.cpp @@ -40,25 +40,22 @@ TurboModule::TurboModule( : name_(std::move(name)), jsInvoker_(std::move(jsInvoker)) {} void TurboModule::emitDeviceEvent( - jsi::Runtime& runtime, const std::string& eventName, ArgFactory argFactory) { - jsInvoker_->invokeAsync([&runtime, eventName, argFactory]() { - jsi::Value emitter = - runtime.global().getProperty(runtime, "__rctDeviceEventEmitter"); + jsInvoker_->invokeAsync([eventName, argFactory](jsi::Runtime& rt) { + jsi::Value emitter = rt.global().getProperty(rt, "__rctDeviceEventEmitter"); if (!emitter.isUndefined()) { - jsi::Object emitterObject = emitter.asObject(runtime); + jsi::Object emitterObject = emitter.asObject(rt); // TODO: consider caching these jsi::Function emitFunction = - emitterObject.getPropertyAsFunction(runtime, "emit"); + emitterObject.getPropertyAsFunction(rt, "emit"); std::vector args; - args.emplace_back( - jsi::String::createFromAscii(runtime, eventName.c_str())); + args.emplace_back(jsi::String::createFromAscii(rt, eventName.c_str())); if (argFactory) { - argFactory(runtime, args); + argFactory(rt, args); } emitFunction.callWithThis( - runtime, emitterObject, (const jsi::Value*)args.data(), args.size()); + rt, emitterObject, (const jsi::Value*)args.data(), args.size()); } }); } diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h index 68b32b60f0f..3ccee71f8f4 100644 --- a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h @@ -26,7 +26,6 @@ struct Promise : public LongLivedObject { void resolve(const jsi::Value& result); void reject(const std::string& error); - jsi::Runtime& runtime_; jsi::Function resolve_; jsi::Function reject_; }; @@ -56,4 +55,4 @@ class RAIICallbackWrapperDestroyer { std::weak_ptr callbackWrapper_; }; -} // namespace facebook::react \ No newline at end of file +} // namespace facebook::react diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/scrollview/ScrollViewProps.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/scrollview/ScrollViewProps.cpp index c312384a422..e3e16599e67 100644 --- a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/scrollview/ScrollViewProps.cpp +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/scrollview/ScrollViewProps.cpp @@ -111,17 +111,6 @@ ScrollViewProps::ScrollViewProps( // [Windows fix (Float)1)), // Windows] - endDraggingSensitivityVelocityMultiplier( - CoreFeatures::enablePropIteratorSetter - ? sourceProps.endDraggingSensitivityVelocityMultiplier - : convertRawProp( - context, - rawProps, - "endDraggingSensitivityVelocityMultiplier", - sourceProps.endDraggingSensitivityVelocityMultiplier, - // [Windows fix - (Float)0)), - // Windows] directionalLockEnabled( CoreFeatures::enablePropIteratorSetter ? sourceProps.directionalLockEnabled @@ -532,4 +521,5 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const { } #endif -} // namespace facebook::react \ No newline at end of file +} // namespace facebook::react + \ No newline at end of file diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.cpp new file mode 100644 index 00000000000..c75d6d10787 --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.cpp @@ -0,0 +1,45 @@ +/* + * 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 "JSRuntimeFactory.h" +#include +#include + +namespace facebook::react { + +jsi::Runtime& JSIRuntimeHolder::getRuntime() noexcept { + return *runtime_; +} + +JSIRuntimeHolder::JSIRuntimeHolder(std::unique_ptr runtime) + : runtime_(std::move(runtime)) { + assert(runtime_ != nullptr); +} + +void JSIRuntimeHolder::addConsoleMessage(jsi::Runtime& runtime, jsinspector_modern::ConsoleMessage message) { + return; +} + +bool JSIRuntimeHolder::supportsConsole() const{ + return false; +} + +std::unique_ptr +JSIRuntimeHolder::createAgentDelegate( + jsinspector_modern::FrontendChannel frontendChannel, + jsinspector_modern::SessionState& sessionState, + std::unique_ptr, + const jsinspector_modern::ExecutionContextDescription& + executionContextDescription, + RuntimeExecutor runtimeExecutor) { + (void)executionContextDescription; + (void)runtimeExecutor; + return std::make_unique( + std::move(frontendChannel), sessionState, runtime_->description()); +} + +} // namespace facebook::react \ No newline at end of file diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.h b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.h new file mode 100644 index 00000000000..236a33b6901 --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include +#include + + +namespace facebook::react { + +/** + * An interface that represents an instance of a JS VM + */ +class JSRuntime : public jsinspector_modern::RuntimeTargetDelegate { + public: + virtual jsi::Runtime& getRuntime() noexcept = 0; + + virtual ~JSRuntime() = default; + + virtual void addConsoleMessage(jsi::Runtime& runtime, jsinspector_modern::ConsoleMessage message) = 0; + virtual bool supportsConsole() const = 0; +}; + +/** + * Interface for a class that creates instances of a JS VM + */ +class JSRuntimeFactory { + public: + virtual std::unique_ptr createJSRuntime( + std::shared_ptr msgQueueThread) noexcept = 0; + + virtual ~JSRuntimeFactory() = default; +}; + +/** + * Utility class for creating a JSRuntime from a uniquely owned jsi::Runtime. + */ +class JSIRuntimeHolder : public JSRuntime { + public: + jsi::Runtime& getRuntime() noexcept override; + void addConsoleMessage(jsi::Runtime& runtime, jsinspector_modern::ConsoleMessage message) override; + bool supportsConsole() const override; + + std::unique_ptr createAgentDelegate( + jsinspector_modern::FrontendChannel frontendChannel, + jsinspector_modern::SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const jsinspector_modern::ExecutionContextDescription& + executionContextDescription, + RuntimeExecutor runtimeExecutor) override; + + explicit JSIRuntimeHolder(std::unique_ptr runtime); + + private: + std::unique_ptr runtime_; +}; + +} // namespace facebook::react diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp new file mode 100644 index 00000000000..392ab7513d0 --- /dev/null +++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp @@ -0,0 +1,464 @@ +/* + * 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 "ReactInstance.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace facebook::react { + +ReactInstance::ReactInstance( + std::unique_ptr runtime, + std::shared_ptr jsMessageQueueThread, + std::shared_ptr timerManager, + JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc, + jsinspector_modern::HostTarget* parentInspectorTarget) + : runtime_(std::move(runtime)), + jsMessageQueueThread_(jsMessageQueueThread), + timerManager_(std::move(timerManager)), + jsErrorHandler_(jsErrorHandlingFunc), + hasFatalJsError_(std::make_shared(false)), + parentInspectorTarget_(parentInspectorTarget) { + RuntimeExecutor runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_), + weakTimerManager = + std::weak_ptr(timerManager_), + weakJsMessageQueueThread = + std::weak_ptr(jsMessageQueueThread_), + weakHasFatalJsError = std::weak_ptr( + hasFatalJsError_)](auto callback) { + if (std::shared_ptr sharedHasFatalJsError = + weakHasFatalJsError.lock()) { + if (*sharedHasFatalJsError) { + LOG(INFO) + << "Calling into JS using runtimeExecutor but hasFatalJsError_ is true"; + return; + } + } + if (weakRuntime.expired()) { + return; + } + + if (std::shared_ptr sharedJsMessageQueueThread = + weakJsMessageQueueThread.lock()) { + sharedJsMessageQueueThread->runOnQueue( + [weakRuntime, weakTimerManager, callback = std::move(callback)]() { + if (auto strongRuntime = weakRuntime.lock()) { + jsi::Runtime& jsiRuntime = strongRuntime->getRuntime(); + SystraceSection s("ReactInstance::_runtimeExecutor[Callback]"); + try { + callback(jsiRuntime); + + // If we have first-class support for microtasks, + // they would've been called as part of the previous callback. + if (!ReactNativeFeatureFlags::enableMicrotasks()) { + if (auto strongTimerManager = weakTimerManager.lock()) { + strongTimerManager->callReactNativeMicrotasks(jsiRuntime); + } + } + } catch (jsi::JSError& originalError) { + handleJSError(jsiRuntime, originalError, true); + } + } + }); + } + }; + + if (parentInspectorTarget_) { + auto executor = parentInspectorTarget_->executorFromThis(); + + auto runtimeExecutorThatWaitsForInspectorSetup = + std::make_shared(runtimeExecutor); + + // This code can execute from any thread, so we need to make sure we set up + // the inspector logic in the right one. The callback executes immediately + // if we are already in the right thread. + executor([this, runtimeExecutor, runtimeExecutorThatWaitsForInspectorSetup]( + jsinspector_modern::HostTarget& hostTarget) { + // Callbacks scheduled through the page target executor are generally + // not guaranteed to run (e.g.: if the page target is destroyed) + // but in this case it is because the page target cannot be destroyed + // before the instance finishes its setup: + // * On iOS it's because we do the setup synchronously. + // * On Android it's because we explicitly wait for the instance + // creation task to finish before starting the destruction. + inspectorTarget_ = &hostTarget.registerInstance(*this); + runtimeInspectorTarget_ = + &inspectorTarget_->registerRuntime(*runtime_, runtimeExecutor); + runtimeExecutorThatWaitsForInspectorSetup->flush(); + }); + + // We decorate the runtime executor used everywhere else to wait for the + // inspector to finish its setup. + runtimeExecutor = + [runtimeExecutorThatWaitsForInspectorSetup]( + std::function&& callback) { + runtimeExecutorThatWaitsForInspectorSetup->execute( + std::move(callback)); + }; + } + + runtimeScheduler_ = std::make_shared(runtimeExecutor); + + auto pipedRuntimeExecutor = + [runtimeScheduler = runtimeScheduler_.get()]( + std::function&& callback) { + runtimeScheduler->scheduleWork(std::move(callback)); + }; + + bufferedRuntimeExecutor_ = + std::make_shared(pipedRuntimeExecutor); +} + +void ReactInstance::unregisterFromInspector() { + if (inspectorTarget_) { + assert(runtimeInspectorTarget_); + inspectorTarget_->unregisterRuntime(*runtimeInspectorTarget_); + + assert(parentInspectorTarget_); + parentInspectorTarget_->unregisterInstance(*inspectorTarget_); + + inspectorTarget_ = nullptr; + } +} + +RuntimeExecutor ReactInstance::getUnbufferedRuntimeExecutor() noexcept { + return [runtimeScheduler = runtimeScheduler_.get()]( + std::function&& callback) { + runtimeScheduler->scheduleWork(std::move(callback)); + }; +} + +// This BufferedRuntimeExecutor ensures that the main JS bundle finished +// execution before any JS queued into it from C++ are executed. Use +// getBufferedRuntimeExecutor() instead if you do not need the main JS bundle to +// have finished. e.g. setting global variables into JS runtime. +RuntimeExecutor ReactInstance::getBufferedRuntimeExecutor() noexcept { + return [weakBufferedRuntimeExecutor_ = + std::weak_ptr(bufferedRuntimeExecutor_)]( + std::function&& callback) { + if (auto strongBufferedRuntimeExecutor_ = + weakBufferedRuntimeExecutor_.lock()) { + strongBufferedRuntimeExecutor_->execute(std::move(callback)); + } + }; +} + +std::shared_ptr +ReactInstance::getRuntimeScheduler() noexcept { + return runtimeScheduler_; +} + +namespace { + +// Copied from JSIExecutor.cpp +// basename_r isn't in all iOS SDKs, so use this simple version instead. +std::string simpleBasename(const std::string& path) { + size_t pos = path.rfind("/"); + return (pos != std::string::npos) ? path.substr(pos) : path; +} + +} // namespace + +/** + * Load the JS bundle and flush buffered JS calls, future JS calls won't be + * buffered after calling this. + * Note that this method is asynchronous. However, a completion callback + * isn't needed because all calls into JS should be dispatched to the JSThread, + * preferably via the runtimeExecutor_. + */ +void ReactInstance::loadScript( + std::unique_ptr script, + const std::string& sourceURL) { + auto buffer = std::make_shared(std::move(script)); + std::string scriptName = simpleBasename(sourceURL); + + runtimeScheduler_->scheduleWork( + [this, + scriptName, + sourceURL, + buffer = std::move(buffer), + weakBufferedRuntimeExecuter = std::weak_ptr( + bufferedRuntimeExecutor_)](jsi::Runtime& runtime) { + try { + SystraceSection s("ReactInstance::loadScript"); + bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl); + if (hasLogger) { + ReactMarker::logTaggedMarkerBridgeless( + ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str()); + } + + runtime.evaluateJavaScript(buffer, sourceURL); + if (hasLogger) { + ReactMarker::logTaggedMarkerBridgeless( + ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str()); + ReactMarker::logMarkerBridgeless( + ReactMarker::INIT_REACT_RUNTIME_STOP); + ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP); + } + if (auto strongBufferedRuntimeExecuter = + weakBufferedRuntimeExecuter.lock()) { + strongBufferedRuntimeExecuter->flush(); + } + } catch (jsi::JSError& error) { + // Handle uncaught JS errors during loading JS bundle + *hasFatalJsError_ = true; + this->jsErrorHandler_.handleJsError(error, true); + } + }); +} + +/* + * Calls a method on a JS module that has been registered with + * `registerCallableModule`. Used to invoke a JS function from platform code. + */ +void ReactInstance::callFunctionOnModule( + const std::string& moduleName, + const std::string& methodName, + const folly::dynamic& args) { + // TODO (C++ 20): This code previously implicitly captured `this` in a [=] + // capture group. Was it meaning to pass modules_ by value? + bufferedRuntimeExecutor_->execute([=, this](jsi::Runtime& runtime) { + SystraceSection s( + "ReactInstance::callFunctionOnModule", + "moduleName", + moduleName, + "methodName", + methodName); + if (modules_.find(moduleName) == modules_.end()) { + std::ostringstream knownModules; + int i = 0; + for (auto it = modules_.begin(); it != modules_.end(); it++, i++) { + const char* space = (i > 0 ? ", " : " "); + knownModules << space << it->first; + } + throw jsi::JSError( + runtime, + "Failed to call into JavaScript module method " + moduleName + "." + + methodName + + "(). Module has not been registered as callable. Registered callable JavaScript modules (n = " + + std::to_string(modules_.size()) + "):" + knownModules.str() + + ". Did you forget to call `RN$registerCallableModule`?"); + } + + auto module = modules_[moduleName]->factory.call(runtime).asObject(runtime); + auto method = module.getProperty(runtime, methodName.c_str()); + if (method.isUndefined()) { + throw jsi::JSError( + runtime, + "Failed to call into JavaScript module method " + moduleName + "." + + methodName + ". Module exists, but the method is undefined."); + } + + std::vector jsArgs; + for (auto& arg : args) { + jsArgs.push_back(jsi::valueFromDynamic(runtime, arg)); + } + method.asObject(runtime).asFunction(runtime).callWithThis( + runtime, module, (const jsi::Value*)jsArgs.data(), jsArgs.size()); + }); +} + +void ReactInstance::registerSegment( + uint32_t segmentId, + const std::string& segmentPath) { + LOG(WARNING) << "Starting to run ReactInstance::registerSegment with segment " + << segmentId; + runtimeScheduler_->scheduleWork([=](jsi::Runtime& runtime) { + SystraceSection s("ReactInstance::registerSegment"); + const auto tag = folly::to(segmentId); + auto script = JSBigFileString::fromPath(segmentPath); + if (script->size() == 0) { + throw std::invalid_argument( + "Empty segment registered with ID " + tag + " from " + segmentPath); + } + auto buffer = std::make_shared(std::move(script)); + + bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl); + if (hasLogger) { + ReactMarker::logTaggedMarkerBridgeless( + ReactMarker::REGISTER_JS_SEGMENT_START, tag.c_str()); + } + LOG(WARNING) << "Starting to evaluate segment " << segmentId + << " in ReactInstance::registerSegment"; + runtime.evaluateJavaScript( + buffer, JSExecutor::getSyntheticBundlePath(segmentId, segmentPath)); + LOG(WARNING) << "Finished evaluating segment " << segmentId + << " in ReactInstance::registerSegment"; + if (hasLogger) { + ReactMarker::logTaggedMarkerBridgeless( + ReactMarker::REGISTER_JS_SEGMENT_STOP, tag.c_str()); + } + }); +} + +namespace { +void defineReactInstanceFlags( + jsi::Runtime& runtime, + ReactInstance::JSRuntimeFlags options) noexcept { + defineReadOnlyGlobal(runtime, "RN$Bridgeless", jsi::Value(true)); + + if (options.isProfiling) { + defineReadOnlyGlobal(runtime, "__RCTProfileIsProfiling", jsi::Value(true)); + } + + if (options.runtimeDiagnosticFlags.length() > 0) { + defineReadOnlyGlobal( + runtime, + "RN$DiagnosticFlags", + jsi::String::createFromUtf8(runtime, options.runtimeDiagnosticFlags)); + } +} + +} // namespace + +void ReactInstance::initializeRuntime( + JSRuntimeFlags options, + BindingsInstallFunc bindingsInstallFunc) noexcept { + runtimeScheduler_->scheduleWork([this, options, bindingsInstallFunc]( + jsi::Runtime& runtime) { + SystraceSection s("ReactInstance::initializeRuntime"); + + bindNativePerformanceNow(runtime); + + RuntimeSchedulerBinding::createAndInstallIfNeeded( + runtime, runtimeScheduler_); + + defineReactInstanceFlags(runtime, options); + + defineReadOnlyGlobal( + runtime, + "RN$registerCallableModule", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "registerCallableModule"), + 2, + [this]( + jsi::Runtime& runtime, + const jsi::Value& /*unused*/, + const jsi::Value* args, + size_t count) { + if (count != 2) { + throw jsi::JSError( + runtime, + "registerCallableModule requires exactly 2 arguments"); + } + if (!args[0].isString()) { + throw jsi::JSError( + runtime, + "The first argument to registerCallableModule must be a string (the name of the JS module)."); + } + auto name = args[0].asString(runtime).utf8(runtime); + if (!args[1].isObject() || + !args[1].asObject(runtime).isFunction(runtime)) { + throw jsi::JSError( + runtime, + "The second argument to registerCallableModule must be a function that returns the JS module."); + } + modules_[name] = std::make_shared( + args[1].getObject(runtime).asFunction(runtime)); + return jsi::Value::undefined(); + })); + + timerManager_->attachGlobals(runtime); + + bindingsInstallFunc(runtime); + }); +} + +void ReactInstance::handleMemoryPressureJs(int pressureLevel) { + // The level is an enum value passed by the Android OS to an onTrimMemory + // event callback. Defined in ComponentCallbacks2. + enum AndroidMemoryPressure { + TRIM_MEMORY_BACKGROUND = 40, + TRIM_MEMORY_COMPLETE = 80, + TRIM_MEMORY_MODERATE = 60, + TRIM_MEMORY_RUNNING_CRITICAL = 15, + TRIM_MEMORY_RUNNING_LOW = 10, + TRIM_MEMORY_RUNNING_MODERATE = 5, + TRIM_MEMORY_UI_HIDDEN = 20, + }; + const char* levelName; + switch (pressureLevel) { + case TRIM_MEMORY_BACKGROUND: + levelName = "TRIM_MEMORY_BACKGROUND"; + break; + case TRIM_MEMORY_COMPLETE: + levelName = "TRIM_MEMORY_COMPLETE"; + break; + case TRIM_MEMORY_MODERATE: + levelName = "TRIM_MEMORY_MODERATE"; + break; + case TRIM_MEMORY_RUNNING_CRITICAL: + levelName = "TRIM_MEMORY_RUNNING_CRITICAL"; + break; + case TRIM_MEMORY_RUNNING_LOW: + levelName = "TRIM_MEMORY_RUNNING_LOW"; + break; + case TRIM_MEMORY_RUNNING_MODERATE: + levelName = "TRIM_MEMORY_RUNNING_MODERATE"; + break; + case TRIM_MEMORY_UI_HIDDEN: + levelName = "TRIM_MEMORY_UI_HIDDEN"; + break; + default: + levelName = "UNKNOWN"; + break; + } + + switch (pressureLevel) { + case TRIM_MEMORY_RUNNING_LOW: + case TRIM_MEMORY_RUNNING_MODERATE: + case TRIM_MEMORY_UI_HIDDEN: + // For non-severe memory trims, do nothing. + LOG(INFO) << "Memory warning (pressure level: " << levelName + << ") received by JS VM, ignoring because it's non-severe"; + break; + case TRIM_MEMORY_BACKGROUND: + case TRIM_MEMORY_COMPLETE: + case TRIM_MEMORY_MODERATE: + case TRIM_MEMORY_RUNNING_CRITICAL: + // For now, pressureLevel is unused by collectGarbage. + // This may change in the future if the JS GC has different styles of + // collections. + LOG(INFO) << "Memory warning (pressure level: " << levelName + << ") received by JS VM, running a GC"; + runtimeScheduler_->scheduleWork([=](jsi::Runtime& runtime) { + SystraceSection s("ReactInstance::handleMemoryPressure"); + runtime.instrumentation().collectGarbage(levelName); + }); + break; + default: + // Use the raw number instead of the name here since the name is + // meaningless. + LOG(WARNING) << "Memory warning (pressure level: " << pressureLevel + << ") received by JS VM, unrecognized pressure level"; + break; + } +} + +void* ReactInstance::getJavaScriptContext() { + return &runtime_->getRuntime(); +} + +} // namespace facebook::react diff --git a/vnext/Scripts/rnw-dependencies.ps1 b/vnext/Scripts/rnw-dependencies.ps1 index c6711417ca3..92fa37b3dea 100644 --- a/vnext/Scripts/rnw-dependencies.ps1 +++ b/vnext/Scripts/rnw-dependencies.ps1 @@ -440,7 +440,7 @@ $requirements = @( Name = 'Node.js (LTS, >= 18.0)'; Tags = @('appDev'); Valid = { CheckNode; } - Install = { WinGetInstall OpenJS.NodeJS.LTS "18.16.1" }; + Install = { WinGetInstall OpenJS.NodeJS.LTS "18.18.0" }; HasVerboseOutput = $true; }, @{ diff --git a/vnext/Shared/HermesRuntimeHolder.cpp b/vnext/Shared/HermesRuntimeHolder.cpp index 200753898ed..10252bcc44f 100644 --- a/vnext/Shared/HermesRuntimeHolder.cpp +++ b/vnext/Shared/HermesRuntimeHolder.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include "SafeLoadLibrary.h" @@ -400,6 +401,16 @@ facebook::jsi::Runtime &HermesJSRuntime::getRuntime() noexcept { return *m_holder->getRuntime(); } +void HermesJSRuntime::addConsoleMessage( + facebook::jsi::Runtime &runtime, + facebook::react::jsinspector_modern::ConsoleMessage message) { + return; +} + +bool HermesJSRuntime::supportsConsole() const { + return false; +} + std::unique_ptr HermesJSRuntime::createAgentDelegate( facebook::react::jsinspector_modern::FrontendChannel frontendChannel, facebook::react::jsinspector_modern::SessionState &sessionState, diff --git a/vnext/Shared/HermesRuntimeHolder.h b/vnext/Shared/HermesRuntimeHolder.h index b7f5087d2fa..20aaaadbf13 100644 --- a/vnext/Shared/HermesRuntimeHolder.h +++ b/vnext/Shared/HermesRuntimeHolder.h @@ -58,6 +58,9 @@ class HermesJSRuntime : public facebook::react::JSRuntime { HermesJSRuntime(std::shared_ptr hermesRuntimeHolder); facebook::jsi::Runtime &getRuntime() noexcept override; + void addConsoleMessage(facebook::jsi::Runtime &runtime, facebook::react::jsinspector_modern::ConsoleMessage message) + override; + bool supportsConsole() const override; std::unique_ptr createAgentDelegate( facebook::react::jsinspector_modern::FrontendChannel frontendChannel, diff --git a/vnext/Shared/Shared.vcxitems b/vnext/Shared/Shared.vcxitems index 7a8b26602ad..93cb4196a9c 100644 --- a/vnext/Shared/Shared.vcxitems +++ b/vnext/Shared/Shared.vcxitems @@ -480,6 +480,7 @@ + @@ -490,17 +491,20 @@ - - + + + + + - + + - - - + + @@ -547,7 +551,6 @@ - @@ -574,7 +577,6 @@ - @@ -608,6 +610,7 @@ + diff --git a/vnext/Shared/Shared.vcxitems.filters b/vnext/Shared/Shared.vcxitems.filters index b985a1b02b2..c052ed02989 100644 --- a/vnext/Shared/Shared.vcxitems.filters +++ b/vnext/Shared/Shared.vcxitems.filters @@ -316,13 +316,17 @@ + + + + diff --git a/vnext/Shared/Threading/BatchingQueueThread.cpp b/vnext/Shared/Threading/BatchingQueueThread.cpp index f056b0e85c9..53de6cf1a8e 100644 --- a/vnext/Shared/Threading/BatchingQueueThread.cpp +++ b/vnext/Shared/Threading/BatchingQueueThread.cpp @@ -16,7 +16,9 @@ BatchingQueueCallInvoker::BatchingQueueCallInvoker( std::shared_ptr const &queueThread) : m_queueThread(queueThread) {} -void BatchingQueueCallInvoker::invokeAsync(const std::string &methodName, std::function &&func) noexcept { +void BatchingQueueCallInvoker::invokeAsync( + const std::string &methodName, + facebook::react::NativeMethodCallFunc &&func) noexcept { EnsureQueue(); m_taskQueue->emplace_back(std::move(func)); @@ -58,7 +60,9 @@ void BatchingQueueCallInvoker::quitSynchronous() noexcept { m_queueThread->quitSynchronous(); } -void BatchingQueueCallInvoker::invokeSync(const std::string &methodName, std::function &&func) noexcept { +void BatchingQueueCallInvoker::invokeSync( + const std::string &methodName, + facebook::react::NativeMethodCallFunc &&func) noexcept { assert(false && "Not supported"); std::terminate(); } diff --git a/vnext/Shared/Threading/BatchingQueueThread.h b/vnext/Shared/Threading/BatchingQueueThread.h index af086145c00..bacf5442561 100644 --- a/vnext/Shared/Threading/BatchingQueueThread.h +++ b/vnext/Shared/Threading/BatchingQueueThread.h @@ -16,12 +16,12 @@ namespace Microsoft::ReactNative { struct BatchingQueueCallInvoker : facebook::react::NativeMethodCallInvoker { BatchingQueueCallInvoker(std::shared_ptr const &queueThread); - void invokeAsync(const std::string &methodName, std::function &&func) noexcept override; + void invokeAsync(const std::string &methodName, facebook::react::NativeMethodCallFunc &&func) noexcept override; void EnsureQueue() noexcept; void onBatchComplete() noexcept; void quitSynchronous() noexcept; void PostBatch() noexcept; - void invokeSync(const std::string &methodName, std::function &&func) noexcept override; + void invokeSync(const std::string &methodName, facebook::react::NativeMethodCallFunc &&func) noexcept override; private: std::shared_ptr m_queueThread; diff --git a/vnext/codegen/NativeDOMSpec.g.h b/vnext/codegen/NativeDOMSpec.g.h new file mode 100644 index 00000000000..64f3eca9667 --- /dev/null +++ b/vnext/codegen/NativeDOMSpec.g.h @@ -0,0 +1,118 @@ + +/* + * This file is auto-generated from a NativeModule spec file in js. + * + * This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules + * in a way that also verifies at compile time that the native module matches the interface required + * by the TurboModule JS spec. + */ +#pragma once + +#include +#include + +namespace Microsoft::ReactNativeSpecs { + + +struct DOMSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { + static constexpr auto methods = std::tuple{ + SyncMethod() noexcept>{0, L"getParentNode"}, + SyncMethod>() noexcept>{1, L"getChildNodes"}, + SyncMethod{2, L"isConnected"}, + SyncMethod{3, L"compareDocumentPosition"}, + SyncMethod{4, L"getTextContent"}, + SyncMethod>(, bool) noexcept>{5, L"getBoundingClientRect"}, + SyncMethod>() noexcept>{6, L"getOffset"}, + SyncMethod>() noexcept>{7, L"getScrollPosition"}, + SyncMethod>() noexcept>{8, L"getScrollSize"}, + SyncMethod>() noexcept>{9, L"getInnerSize"}, + SyncMethod>() noexcept>{10, L"getBorderSize"}, + SyncMethod{11, L"getTagName"}, + SyncMethod{12, L"hasPointerCapture"}, + Method{13, L"setPointerCapture"}, + Method{14, L"releasePointerCapture"}, + }; + + template + static constexpr void ValidateModule() noexcept { + constexpr auto methodCheckResults = CheckMethods(); + + REACT_SHOW_METHOD_SPEC_ERRORS( + 0, + "getParentNode", + " REACT_SYNC_METHOD(getParentNode) std::optional<> getParentNode( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getParentNode) static std::optional<> getParentNode( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 1, + "getChildNodes", + " REACT_SYNC_METHOD(getChildNodes) std::optional> getChildNodes( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getChildNodes) static std::optional> getChildNodes( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 2, + "isConnected", + " REACT_SYNC_METHOD(isConnected) bool isConnected( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(isConnected) static bool isConnected( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 3, + "compareDocumentPosition", + " REACT_SYNC_METHOD(compareDocumentPosition) double compareDocumentPosition( shadowNode, otherShadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(compareDocumentPosition) static double compareDocumentPosition( shadowNode, otherShadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 4, + "getTextContent", + " REACT_SYNC_METHOD(getTextContent) std::string getTextContent( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getTextContent) static std::string getTextContent( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 5, + "getBoundingClientRect", + " REACT_SYNC_METHOD(getBoundingClientRect) std::optional> getBoundingClientRect( shadowNode, bool includeTransform) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getBoundingClientRect) static std::optional> getBoundingClientRect( shadowNode, bool includeTransform) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 6, + "getOffset", + " REACT_SYNC_METHOD(getOffset) std::optional> getOffset( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getOffset) static std::optional> getOffset( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 7, + "getScrollPosition", + " REACT_SYNC_METHOD(getScrollPosition) std::optional> getScrollPosition( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getScrollPosition) static std::optional> getScrollPosition( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 8, + "getScrollSize", + " REACT_SYNC_METHOD(getScrollSize) std::optional> getScrollSize( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getScrollSize) static std::optional> getScrollSize( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 9, + "getInnerSize", + " REACT_SYNC_METHOD(getInnerSize) std::optional> getInnerSize( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getInnerSize) static std::optional> getInnerSize( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 10, + "getBorderSize", + " REACT_SYNC_METHOD(getBorderSize) std::optional> getBorderSize( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getBorderSize) static std::optional> getBorderSize( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 11, + "getTagName", + " REACT_SYNC_METHOD(getTagName) std::string getTagName( shadowNode) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(getTagName) static std::string getTagName( shadowNode) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 12, + "hasPointerCapture", + " REACT_SYNC_METHOD(hasPointerCapture) bool hasPointerCapture( shadowNode, double pointerId) noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(hasPointerCapture) static bool hasPointerCapture( shadowNode, double pointerId) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 13, + "setPointerCapture", + " REACT_METHOD(setPointerCapture) void setPointerCapture( shadowNode, double pointerId) noexcept { /* implementation */ }\n" + " REACT_METHOD(setPointerCapture) static void setPointerCapture( shadowNode, double pointerId) noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 14, + "releasePointerCapture", + " REACT_METHOD(releasePointerCapture) void releasePointerCapture( shadowNode, double pointerId) noexcept { /* implementation */ }\n" + " REACT_METHOD(releasePointerCapture) static void releasePointerCapture( shadowNode, double pointerId) noexcept { /* implementation */ }\n"); + } +}; + +} // namespace Microsoft::ReactNativeSpecs diff --git a/vnext/codegen/NativeMicrotasksSpec.g.h b/vnext/codegen/NativeMicrotasksSpec.g.h new file mode 100644 index 00000000000..9d6f6308cb5 --- /dev/null +++ b/vnext/codegen/NativeMicrotasksSpec.g.h @@ -0,0 +1,34 @@ + +/* + * This file is auto-generated from a NativeModule spec file in js. + * + * This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules + * in a way that also verifies at compile time that the native module matches the interface required + * by the TurboModule JS spec. + */ +#pragma once + +#include +#include + +namespace Microsoft::ReactNativeSpecs { + + +struct MicrotasksSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { + static constexpr auto methods = std::tuple{ + Method) noexcept>{0, L"queueMicrotask"}, + }; + + template + static constexpr void ValidateModule() noexcept { + constexpr auto methodCheckResults = CheckMethods(); + + REACT_SHOW_METHOD_SPEC_ERRORS( + 0, + "queueMicrotask", + " REACT_METHOD(queueMicrotask) void queueMicrotask(std::function const & callback) noexcept { /* implementation */ }\n" + " REACT_METHOD(queueMicrotask) static void queueMicrotask(std::function const & callback) noexcept { /* implementation */ }\n"); + } +}; + +} // namespace Microsoft::ReactNativeSpecs diff --git a/vnext/codegen/NativePerformanceSpec.g.h b/vnext/codegen/NativePerformanceSpec.g.h index 0e5ec8129cc..7c962708837 100644 --- a/vnext/codegen/NativePerformanceSpec.g.h +++ b/vnext/codegen/NativePerformanceSpec.g.h @@ -16,10 +16,11 @@ namespace Microsoft::ReactNativeSpecs { struct PerformanceSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { static constexpr auto methods = std::tuple{ - Method{0, L"mark"}, - Method{1, L"measure"}, - SyncMethod<::React::JSValue() noexcept>{2, L"getSimpleMemoryInfo"}, - SyncMethod<::React::JSValue() noexcept>{3, L"getReactNativeStartupTiming"}, + SyncMethod{0, L"now"}, + Method{1, L"mark"}, + Method{2, L"measure"}, + SyncMethod<::React::JSValue() noexcept>{3, L"getSimpleMemoryInfo"}, + SyncMethod<::React::JSValue() noexcept>{4, L"getReactNativeStartupTiming"}, }; template @@ -28,21 +29,26 @@ struct PerformanceSpec : winrt::Microsoft::ReactNative::TurboModuleSpec { REACT_SHOW_METHOD_SPEC_ERRORS( 0, + "now", + " REACT_SYNC_METHOD(now) double now() noexcept { /* implementation */ }\n" + " REACT_SYNC_METHOD(now) static double now() noexcept { /* implementation */ }\n"); + REACT_SHOW_METHOD_SPEC_ERRORS( + 1, "mark", " REACT_METHOD(mark) void mark(std::string name, double startTime) noexcept { /* implementation */ }\n" " REACT_METHOD(mark) static void mark(std::string name, double startTime) noexcept { /* implementation */ }\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 1, + 2, "measure", " REACT_METHOD(measure) void measure(std::string name, double startTime, double endTime, double duration, std::string startMark, std::string endMark) noexcept { /* implementation */ }\n" " REACT_METHOD(measure) static void measure(std::string name, double startTime, double endTime, double duration, std::string startMark, std::string endMark) noexcept { /* implementation */ }\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 2, + 3, "getSimpleMemoryInfo", " REACT_SYNC_METHOD(getSimpleMemoryInfo) ::React::JSValue getSimpleMemoryInfo() noexcept { /* implementation */ }\n" " REACT_SYNC_METHOD(getSimpleMemoryInfo) static ::React::JSValue getSimpleMemoryInfo() noexcept { /* implementation */ }\n"); REACT_SHOW_METHOD_SPEC_ERRORS( - 3, + 4, "getReactNativeStartupTiming", " REACT_SYNC_METHOD(getReactNativeStartupTiming) ::React::JSValue getReactNativeStartupTiming() noexcept { /* implementation */ }\n" " REACT_SYNC_METHOD(getReactNativeStartupTiming) static ::React::JSValue getReactNativeStartupTiming() noexcept { /* implementation */ }\n"); diff --git a/vnext/codegen/NativeReactNativeFeatureFlagsSpec.g.h b/vnext/codegen/NativeReactNativeFeatureFlagsSpec.g.h index 58d7dee6a64..c3b68cb7aa4 100644 --- a/vnext/codegen/NativeReactNativeFeatureFlagsSpec.g.h +++ b/vnext/codegen/NativeReactNativeFeatureFlagsSpec.g.h @@ -26,8 +26,7 @@ struct ReactNativeFeatureFlagsSpec : winrt::Microsoft::ReactNative::TurboModuleS SyncMethod{7, L"enableSpannableBuildingUnification"}, SyncMethod{8, L"inspectorEnableCxxInspectorPackagerConnection"}, SyncMethod{9, L"inspectorEnableModernCDPRegistry"}, - SyncMethod{10, L"skipMountHookNotifications"}, - SyncMethod{11, L"useModernRuntimeScheduler"}, + SyncMethod{10, L"useModernRuntimeScheduler"}, }; template @@ -86,11 +85,6 @@ struct ReactNativeFeatureFlagsSpec : winrt::Microsoft::ReactNative::TurboModuleS " REACT_SYNC_METHOD(inspectorEnableModernCDPRegistry) static bool inspectorEnableModernCDPRegistry() noexcept { /* implementation */ }\n"); REACT_SHOW_METHOD_SPEC_ERRORS( 10, - "skipMountHookNotifications", - " REACT_SYNC_METHOD(skipMountHookNotifications) bool skipMountHookNotifications() noexcept { /* implementation */ }\n" - " REACT_SYNC_METHOD(skipMountHookNotifications) static bool skipMountHookNotifications() noexcept { /* implementation */ }\n"); - REACT_SHOW_METHOD_SPEC_ERRORS( - 11, "useModernRuntimeScheduler", " REACT_SYNC_METHOD(useModernRuntimeScheduler) bool useModernRuntimeScheduler() noexcept { /* implementation */ }\n" " REACT_SYNC_METHOD(useModernRuntimeScheduler) static bool useModernRuntimeScheduler() noexcept { /* implementation */ }\n"); diff --git a/vnext/codegen/rnwcoreJSI-generated.cpp b/vnext/codegen/rnwcoreJSI-generated.cpp index 949d50ae8ae..35069ec9901 100644 --- a/vnext/codegen/rnwcoreJSI-generated.cpp +++ b/vnext/codegen/rnwcoreJSI-generated.cpp @@ -61,11 +61,6 @@ static jsi::Value __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_inspect rt ); } -static jsi::Value __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_skipMountHookNotifications(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { - return static_cast(&turboModule)->skipMountHookNotifications( - rt - ); -} static jsi::Value __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_useModernRuntimeScheduler(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->useModernRuntimeScheduler( rt @@ -84,7 +79,6 @@ NativeReactNativeFeatureFlagsCxxSpecJSI::NativeReactNativeFeatureFlagsCxxSpecJSI methodMap_["enableSpannableBuildingUnification"] = MethodMetadata {0, __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_enableSpannableBuildingUnification}; methodMap_["inspectorEnableCxxInspectorPackagerConnection"] = MethodMetadata {0, __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_inspectorEnableCxxInspectorPackagerConnection}; methodMap_["inspectorEnableModernCDPRegistry"] = MethodMetadata {0, __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_inspectorEnableModernCDPRegistry}; - methodMap_["skipMountHookNotifications"] = MethodMetadata {0, __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_skipMountHookNotifications}; methodMap_["useModernRuntimeScheduler"] = MethodMetadata {0, __hostFunction_NativeReactNativeFeatureFlagsCxxSpecJSI_useModernRuntimeScheduler}; } static jsi::Value __hostFunction_NativeAccessibilityInfoCxxSpecJSI_isReduceMotionEnabled(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -2807,6 +2801,23 @@ NativeWebSocketModuleCxxSpecJSI::NativeWebSocketModuleCxxSpecJSI(std::shared_ptr methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleCxxSpecJSI_addListener}; methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeWebSocketModuleCxxSpecJSI_removeListeners}; } +static jsi::Value __hostFunction_NativeMicrotasksCxxSpecJSI_queueMicrotask(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->queueMicrotask( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt).asFunction(rt) + ); + return jsi::Value::undefined(); +} + +NativeMicrotasksCxxSpecJSI::NativeMicrotasksCxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("NativeMicrotasksCxx", jsInvoker) { + methodMap_["queueMicrotask"] = MethodMetadata {1, __hostFunction_NativeMicrotasksCxxSpecJSI_queueMicrotask}; +} +static jsi::Value __hostFunction_NativePerformanceCxxSpecJSI_now(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->now( + rt + ); +} static jsi::Value __hostFunction_NativePerformanceCxxSpecJSI_mark(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->mark( rt, @@ -2840,6 +2851,7 @@ static jsi::Value __hostFunction_NativePerformanceCxxSpecJSI_getReactNativeStart NativePerformanceCxxSpecJSI::NativePerformanceCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule("NativePerformanceCxx", jsInvoker) { + methodMap_["now"] = MethodMetadata {0, __hostFunction_NativePerformanceCxxSpecJSI_now}; methodMap_["mark"] = MethodMetadata {2, __hostFunction_NativePerformanceCxxSpecJSI_mark}; methodMap_["measure"] = MethodMetadata {6, __hostFunction_NativePerformanceCxxSpecJSI_measure}; methodMap_["getSimpleMemoryInfo"] = MethodMetadata {0, __hostFunction_NativePerformanceCxxSpecJSI_getSimpleMemoryInfo}; @@ -2934,6 +2946,130 @@ NativePerformanceObserverCxxSpecJSI::NativePerformanceObserverCxxSpecJSI(std::sh methodMap_["getEntries"] = MethodMetadata {2, __hostFunction_NativePerformanceObserverCxxSpecJSI_getEntries}; methodMap_["getSupportedPerformanceEntryTypes"] = MethodMetadata {0, __hostFunction_NativePerformanceObserverCxxSpecJSI_getSupportedPerformanceEntryTypes}; } +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getParentNode(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getParentNode( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getChildNodes(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getChildNodes( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_isConnected(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->isConnected( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_compareDocumentPosition(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->compareDocumentPosition( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]), + count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : jsi::Value(rt, args[1]) + ); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getTextContent(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getTextContent( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getBoundingClientRect(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getBoundingClientRect( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]), + count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asBool() + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getOffset(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getOffset( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getScrollPosition(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getScrollPosition( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getScrollSize(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getScrollSize( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getInnerSize(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getInnerSize( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getBorderSize(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + auto result = static_cast(&turboModule)->getBorderSize( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); + return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_getTagName(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getTagName( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]) + ); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_hasPointerCapture(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->hasPointerCapture( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]), + count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asNumber() + ); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_setPointerCapture(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->setPointerCapture( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]), + count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asNumber() + ); + return jsi::Value::undefined(); +} +static jsi::Value __hostFunction_NativeDOMCxxSpecJSI_releasePointerCapture(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + static_cast(&turboModule)->releasePointerCapture( + rt, + count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : jsi::Value(rt, args[0]), + count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asNumber() + ); + return jsi::Value::undefined(); +} + +NativeDOMCxxSpecJSI::NativeDOMCxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule("NativeDOMCxx", jsInvoker) { + methodMap_["getParentNode"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getParentNode}; + methodMap_["getChildNodes"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getChildNodes}; + methodMap_["isConnected"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_isConnected}; + methodMap_["compareDocumentPosition"] = MethodMetadata {2, __hostFunction_NativeDOMCxxSpecJSI_compareDocumentPosition}; + methodMap_["getTextContent"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getTextContent}; + methodMap_["getBoundingClientRect"] = MethodMetadata {2, __hostFunction_NativeDOMCxxSpecJSI_getBoundingClientRect}; + methodMap_["getOffset"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getOffset}; + methodMap_["getScrollPosition"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getScrollPosition}; + methodMap_["getScrollSize"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getScrollSize}; + methodMap_["getInnerSize"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getInnerSize}; + methodMap_["getBorderSize"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getBorderSize}; + methodMap_["getTagName"] = MethodMetadata {1, __hostFunction_NativeDOMCxxSpecJSI_getTagName}; + methodMap_["hasPointerCapture"] = MethodMetadata {2, __hostFunction_NativeDOMCxxSpecJSI_hasPointerCapture}; + methodMap_["setPointerCapture"] = MethodMetadata {2, __hostFunction_NativeDOMCxxSpecJSI_setPointerCapture}; + methodMap_["releasePointerCapture"] = MethodMetadata {2, __hostFunction_NativeDOMCxxSpecJSI_releasePointerCapture}; +} } // namespace facebook::react diff --git a/vnext/codegen/rnwcoreJSI.h b/vnext/codegen/rnwcoreJSI.h index 2e63264ad77..2ab131cda5c 100644 --- a/vnext/codegen/rnwcoreJSI.h +++ b/vnext/codegen/rnwcoreJSI.h @@ -30,7 +30,6 @@ namespace facebook::react { virtual bool enableSpannableBuildingUnification(jsi::Runtime &rt) = 0; virtual bool inspectorEnableCxxInspectorPackagerConnection(jsi::Runtime &rt) = 0; virtual bool inspectorEnableModernCDPRegistry(jsi::Runtime &rt) = 0; - virtual bool skipMountHookNotifications(jsi::Runtime &rt) = 0; virtual bool useModernRuntimeScheduler(jsi::Runtime &rt) = 0; }; @@ -135,14 +134,6 @@ class JSI_EXPORT NativeReactNativeFeatureFlagsCxxSpec : public TurboModule { return bridging::callFromJs( rt, &T::inspectorEnableModernCDPRegistry, jsInvoker_, instance_); } - bool skipMountHookNotifications(jsi::Runtime &rt) override { - static_assert( - bridging::getParameterCount(&T::skipMountHookNotifications) == 1, - "Expected skipMountHookNotifications(...) to have 1 parameters"); - - return bridging::callFromJs( - rt, &T::skipMountHookNotifications, jsInvoker_, instance_); - } bool useModernRuntimeScheduler(jsi::Runtime &rt) override { static_assert( bridging::getParameterCount(&T::useModernRuntimeScheduler) == 1, @@ -9539,11 +9530,58 @@ class JSI_EXPORT NativeWebSocketModuleCxxSpec : public TurboModule { }; + class JSI_EXPORT NativeMicrotasksCxxSpecJSI : public TurboModule { +protected: + NativeMicrotasksCxxSpecJSI(std::shared_ptr jsInvoker); + +public: + virtual void queueMicrotask(jsi::Runtime &rt, jsi::Function callback) = 0; + +}; + +template +class JSI_EXPORT NativeMicrotasksCxxSpec : public TurboModule { +public: + jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override { + return delegate_.get(rt, propName); + } + + static constexpr std::string_view kModuleName = "NativeMicrotasksCxx"; + +protected: + NativeMicrotasksCxxSpec(std::shared_ptr jsInvoker) + : TurboModule(std::string{NativeMicrotasksCxxSpec::kModuleName}, jsInvoker), + delegate_(reinterpret_cast(this), jsInvoker) {} + +private: + class Delegate : public NativeMicrotasksCxxSpecJSI { + public: + Delegate(T *instance, std::shared_ptr jsInvoker) : + NativeMicrotasksCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + + void queueMicrotask(jsi::Runtime &rt, jsi::Function callback) override { + static_assert( + bridging::getParameterCount(&T::queueMicrotask) == 2, + "Expected queueMicrotask(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::queueMicrotask, jsInvoker_, instance_, std::move(callback)); + } + + private: + T *instance_; + }; + + Delegate delegate_; +}; + + class JSI_EXPORT NativePerformanceCxxSpecJSI : public TurboModule { protected: NativePerformanceCxxSpecJSI(std::shared_ptr jsInvoker); public: + virtual double now(jsi::Runtime &rt) = 0; virtual void mark(jsi::Runtime &rt, jsi::String name, double startTime) = 0; virtual void measure(jsi::Runtime &rt, jsi::String name, double startTime, double endTime, std::optional duration, std::optional startMark, std::optional endMark) = 0; virtual jsi::Object getSimpleMemoryInfo(jsi::Runtime &rt) = 0; @@ -9571,6 +9609,14 @@ class JSI_EXPORT NativePerformanceCxxSpec : public TurboModule { Delegate(T *instance, std::shared_ptr jsInvoker) : NativePerformanceCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + double now(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::now) == 1, + "Expected now(...) to have 1 parameters"); + + return bridging::callFromJs( + rt, &T::now, jsInvoker_, instance_); + } void mark(jsi::Runtime &rt, jsi::String name, double startTime) override { static_assert( bridging::getParameterCount(&T::mark) == 3, @@ -10015,4 +10061,176 @@ class JSI_EXPORT NativePerformanceObserverCxxSpec : public TurboModule { Delegate delegate_; }; + + class JSI_EXPORT NativeDOMCxxSpecJSI : public TurboModule { +protected: + NativeDOMCxxSpecJSI(std::shared_ptr jsInvoker); + +public: + virtual std::optional getParentNode(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual std::optional getChildNodes(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual bool isConnected(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual double compareDocumentPosition(jsi::Runtime &rt, jsi::Value shadowNode, jsi::Value otherShadowNode) = 0; + virtual jsi::String getTextContent(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual std::optional getBoundingClientRect(jsi::Runtime &rt, jsi::Value shadowNode, bool includeTransform) = 0; + virtual std::optional getOffset(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual std::optional getScrollPosition(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual std::optional getScrollSize(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual std::optional getInnerSize(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual std::optional getBorderSize(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual jsi::String getTagName(jsi::Runtime &rt, jsi::Value shadowNode) = 0; + virtual bool hasPointerCapture(jsi::Runtime &rt, jsi::Value shadowNode, double pointerId) = 0; + virtual void setPointerCapture(jsi::Runtime &rt, jsi::Value shadowNode, double pointerId) = 0; + virtual void releasePointerCapture(jsi::Runtime &rt, jsi::Value shadowNode, double pointerId) = 0; + +}; + +template +class JSI_EXPORT NativeDOMCxxSpec : public TurboModule { +public: + jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override { + return delegate_.get(rt, propName); + } + + static constexpr std::string_view kModuleName = "NativeDOMCxx"; + +protected: + NativeDOMCxxSpec(std::shared_ptr jsInvoker) + : TurboModule(std::string{NativeDOMCxxSpec::kModuleName}, jsInvoker), + delegate_(reinterpret_cast(this), jsInvoker) {} + +private: + class Delegate : public NativeDOMCxxSpecJSI { + public: + Delegate(T *instance, std::shared_ptr jsInvoker) : + NativeDOMCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {} + + std::optional getParentNode(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getParentNode) == 2, + "Expected getParentNode(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getParentNode, jsInvoker_, instance_, std::move(shadowNode)); + } + std::optional getChildNodes(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getChildNodes) == 2, + "Expected getChildNodes(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getChildNodes, jsInvoker_, instance_, std::move(shadowNode)); + } + bool isConnected(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::isConnected) == 2, + "Expected isConnected(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::isConnected, jsInvoker_, instance_, std::move(shadowNode)); + } + double compareDocumentPosition(jsi::Runtime &rt, jsi::Value shadowNode, jsi::Value otherShadowNode) override { + static_assert( + bridging::getParameterCount(&T::compareDocumentPosition) == 3, + "Expected compareDocumentPosition(...) to have 3 parameters"); + + return bridging::callFromJs( + rt, &T::compareDocumentPosition, jsInvoker_, instance_, std::move(shadowNode), std::move(otherShadowNode)); + } + jsi::String getTextContent(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getTextContent) == 2, + "Expected getTextContent(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::getTextContent, jsInvoker_, instance_, std::move(shadowNode)); + } + std::optional getBoundingClientRect(jsi::Runtime &rt, jsi::Value shadowNode, bool includeTransform) override { + static_assert( + bridging::getParameterCount(&T::getBoundingClientRect) == 3, + "Expected getBoundingClientRect(...) to have 3 parameters"); + + return bridging::callFromJs>( + rt, &T::getBoundingClientRect, jsInvoker_, instance_, std::move(shadowNode), std::move(includeTransform)); + } + std::optional getOffset(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getOffset) == 2, + "Expected getOffset(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getOffset, jsInvoker_, instance_, std::move(shadowNode)); + } + std::optional getScrollPosition(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getScrollPosition) == 2, + "Expected getScrollPosition(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getScrollPosition, jsInvoker_, instance_, std::move(shadowNode)); + } + std::optional getScrollSize(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getScrollSize) == 2, + "Expected getScrollSize(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getScrollSize, jsInvoker_, instance_, std::move(shadowNode)); + } + std::optional getInnerSize(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getInnerSize) == 2, + "Expected getInnerSize(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getInnerSize, jsInvoker_, instance_, std::move(shadowNode)); + } + std::optional getBorderSize(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getBorderSize) == 2, + "Expected getBorderSize(...) to have 2 parameters"); + + return bridging::callFromJs>( + rt, &T::getBorderSize, jsInvoker_, instance_, std::move(shadowNode)); + } + jsi::String getTagName(jsi::Runtime &rt, jsi::Value shadowNode) override { + static_assert( + bridging::getParameterCount(&T::getTagName) == 2, + "Expected getTagName(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::getTagName, jsInvoker_, instance_, std::move(shadowNode)); + } + bool hasPointerCapture(jsi::Runtime &rt, jsi::Value shadowNode, double pointerId) override { + static_assert( + bridging::getParameterCount(&T::hasPointerCapture) == 3, + "Expected hasPointerCapture(...) to have 3 parameters"); + + return bridging::callFromJs( + rt, &T::hasPointerCapture, jsInvoker_, instance_, std::move(shadowNode), std::move(pointerId)); + } + void setPointerCapture(jsi::Runtime &rt, jsi::Value shadowNode, double pointerId) override { + static_assert( + bridging::getParameterCount(&T::setPointerCapture) == 3, + "Expected setPointerCapture(...) to have 3 parameters"); + + return bridging::callFromJs( + rt, &T::setPointerCapture, jsInvoker_, instance_, std::move(shadowNode), std::move(pointerId)); + } + void releasePointerCapture(jsi::Runtime &rt, jsi::Value shadowNode, double pointerId) override { + static_assert( + bridging::getParameterCount(&T::releasePointerCapture) == 3, + "Expected releasePointerCapture(...) to have 3 parameters"); + + return bridging::callFromJs( + rt, &T::releasePointerCapture, jsInvoker_, instance_, std::move(shadowNode), std::move(pointerId)); + } + + private: + T *instance_; + }; + + Delegate delegate_; +}; + } // namespace facebook::react diff --git a/vnext/overrides.json b/vnext/overrides.json index 47b782eb444..a4e2f7681e0 100644 --- a/vnext/overrides.json +++ b/vnext/overrides.json @@ -8,13 +8,13 @@ "**/__snapshots__/**", "src-win/rntypes/**" ], - "baseVersion": "0.75.0-nightly-20240307-ff03b149e", + "baseVersion": "0.75.0-nightly-20240321-7d180d712", "overrides": [ { "type": "derived", "file": ".flowconfig", "baseFile": ".flowconfig", - "baseHash": "bdebcba51a5c13fbe5acab9e07720acff0825bc9" + "baseHash": "a57066be1285dc8bc5d9702d0227d04c1c6447ce" }, { "type": "derived", @@ -77,6 +77,27 @@ "baseHash": "4a707c9cab0c6534094cd303e000265b664f05b4", "issue": 7821 }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp", + "baseFile": "packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp", + "baseHash": "0308ba988c534f4a94fb3f1a2006a5fb8a8b2bc5", + "issue": 13172 + }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.h", + "baseFile": "packages/react-native/ReactCommon/cxxreact/JSExecutor.h", + "baseHash": "459d79bc399760546afaf3209c7ec96caeebc449", + "issue": 13172 + }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp", + "baseFile": "packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp", + "baseHash": "f2bb85b79b6e8add5e4604418f953651973011ce", + "issue": 13172 + }, { "type": "patch", "file": "ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp", @@ -95,23 +116,44 @@ "type": "patch", "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/bridging/CallbackWrapper.h", "baseFile": "packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h", - "baseHash": "fe1adea3ede6ed141bc6db212be72091722ffa02", + "baseHash": "fe297f56ac277e5ff3ebcb284eea1f511b5e2d8e", "issue": 12195 }, { "type": "patch", "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleUtils.h", "baseFile": "packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h", - "baseHash": "11de652e153bff8c42cc0e2bbf209c762ed3b314", + "baseHash": "ba5efe9ba0db80a3f38c94deb8983420fd82beff", "issue": 12195 }, { "type": "patch", "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/scrollview/ScrollViewProps.cpp", "baseFile": "packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp", - "baseHash": "8f39e994dcc9dd871d502637f01fbcd6bfd2cccc", + "baseHash": "9ac8a49eedc2f175f2aac3c67a3f3667842e4ca4", "issue": 12879 }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.cpp", + "baseFile": "packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp", + "baseHash": "c77f0b0829b850f8e2f115bfc3440ce94feb207d", + "issue": 13172 + }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/JSRuntimeFactory.h", + "baseFile": "packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h", + "baseHash": "a3cf8c924d0bd3419943f0e46d603f84eb5b52ab", + "issue": 13172 + }, + { + "type": "patch", + "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp", + "baseFile": "packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp", + "baseHash": "779898014c0487575738e29afce2596eea34b19e", + "issue": 13172 + }, { "type": "copy", "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/utils/jsi-utils.cpp", @@ -295,7 +337,7 @@ "type": "patch", "file": "src-win/Libraries/Components/TextInput/TextInput.windows.js", "baseFile": "packages/react-native/Libraries/Components/TextInput/TextInput.js", - "baseHash": "f05b36551197bfa87f2342bd6d1c9b134c1731b2" + "baseHash": "b1ef5981a6abbb0548fc5fd835ad711c10712d61" }, { "type": "patch", @@ -424,7 +466,7 @@ "type": "derived", "file": "src-win/Libraries/LogBox/UI/LogBoxInspectorReactFrames.windows.js", "baseFile": "packages/react-native/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js", - "baseHash": "04c1210d0198315af8358b22a81dc74dc76ef752" + "baseHash": "3a765d2180cca25ed35172ebce8294fc569486aa" }, { "type": "derived", diff --git a/vnext/package.json b/vnext/package.json index 830ca94b834..09e997c1715 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -23,18 +23,18 @@ "dependencies": { "@babel/runtime": "^7.0.0", "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "13.6.1", - "@react-native-community/cli-platform-android": "13.6.1", - "@react-native-community/cli-platform-ios": "13.6.1", + "@react-native-community/cli": "14.0.0-alpha.0", + "@react-native-community/cli-platform-android": "14.0.0-alpha.0", + "@react-native-community/cli-platform-ios": "14.0.0-alpha.0", "@react-native-windows/cli": "0.0.0-canary.210", "@react-native/assets": "1.0.0", - "@react-native/assets-registry": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/codegen": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/community-cli-plugin": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/gradle-plugin": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/js-polyfills": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/normalize-colors": "0.75.0-nightly-20240307-ff03b149e", - "@react-native/virtualized-lists": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/assets-registry": "0.75.0-nightly-20240321-7d180d712", + "@react-native/codegen": "0.75.0-nightly-20240321-7d180d712", + "@react-native/community-cli-plugin": "0.75.0-nightly-20240321-7d180d712", + "@react-native/gradle-plugin": "0.75.0-nightly-20240321-7d180d712", + "@react-native/js-polyfills": "0.75.0-nightly-20240321-7d180d712", + "@react-native/normalize-colors": "0.75.0-nightly-20240321-7d180d712", + "@react-native/virtualized-lists": "0.75.0-nightly-20240321-7d180d712", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", @@ -52,7 +52,7 @@ "nullthrows": "^1.1.1", "pretty-format": "^26.5.2", "promise": "^8.3.0", - "react-devtools-core": "^5.0.0", + "react-devtools-core": "^5.0.2", "react-refresh": "^0.14.0", "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", @@ -65,7 +65,7 @@ }, "devDependencies": { "@react-native-windows/codegen": "0.0.0-canary.84", - "@react-native/metro-config": "0.75.0-nightly-20240307-ff03b149e", + "@react-native/metro-config": "0.75.0-nightly-20240321-7d180d712", "@rnw-scripts/babel-react-native-config": "0.0.0", "@rnw-scripts/eslint-config": "1.2.13", "@rnw-scripts/jest-out-of-tree-snapshot-resolver": "^1.1.17", @@ -81,14 +81,14 @@ "just-scripts": "^1.3.3", "prettier": "2.8.8", "react": "18.2.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e", + "react-native": "0.75.0-nightly-20240321-7d180d712", "react-native-platform-override": "^1.9.30", "react-refresh": "^0.14.0", "typescript": "5.0.4" }, "peerDependencies": { "react": "18.2.0", - "react-native": "0.75.0-nightly-20240307-ff03b149e" + "react-native": "0.75.0-nightly-20240321-7d180d712" }, "beachball": { "defaultNpmTag": "canary", diff --git a/vnext/src-win/Libraries/Components/TextInput/TextInput.windows.js b/vnext/src-win/Libraries/Components/TextInput/TextInput.windows.js index fcbf4a6d191..d078c0d5e20 100644 --- a/vnext/src-win/Libraries/Components/TextInput/TextInput.windows.js +++ b/vnext/src-win/Libraries/Components/TextInput/TextInput.windows.js @@ -818,33 +818,12 @@ export type Props = $ReadOnly<{| */ onChange?: ?(e: ChangeEvent) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * Callback that is called when the text input's text changes. - * - * @platform ios - */ - unstable_onChangeSync?: ?(e: ChangeEvent) => mixed, - /** * Callback that is called when the text input's text changes. * Changed text is passed as an argument to the callback handler. */ onChangeText?: ?(text: string) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * Callback that is called when the text input's text changes. - * Changed text is passed as an argument to the callback handler. - * - * @platform ios - */ - unstable_onChangeTextSync?: ?(text: string) => mixed, - /** * Callback that is called when the text input's content size changes. * This will be called with @@ -873,21 +852,6 @@ export type Props = $ReadOnly<{| */ onKeyPress?: ?(e: KeyPressEvent) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * - * Callback that is called when a key is pressed. - * This will be called with `{ nativeEvent: { key: keyValue } }` - * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and - * the typed-in character otherwise including `' '` for space. - * Fires before `onChange` callbacks. - * - * @platform ios - */ - unstable_onKeyPressSync?: ?(e: KeyPressEvent) => mixed, - /** * Called when a single tap gesture is detected. */ @@ -1391,26 +1355,6 @@ function InternalTextInput(props: Props): React.Node { setMostRecentEventCount(event.nativeEvent.eventCount); }; - const _onChangeSync = (event: ChangeEvent) => { - const currentText = event.nativeEvent.text; - props.unstable_onChangeSync && props.unstable_onChangeSync(event); - props.unstable_onChangeTextSync && - props.unstable_onChangeTextSync(currentText); - - if (inputRef.current == null) { - // calling `props.onChange` or `props.onChangeText` - // may clean up the input itself. Exits here. - return; - } - - setLastNativeText(currentText); - // This must happen last, after we call setLastNativeText. - // Different ordering can cause bugs when editing AndroidTextInputs - // with multiple Fragments. - // We must update this so that controlled input updates work. - setMostRecentEventCount(event.nativeEvent.eventCount); - }; - const _onSelectionChange = (event: SelectionChangeEvent) => { props.onSelectionChange && props.onSelectionChange(event); @@ -1616,10 +1560,6 @@ function InternalTextInput(props: Props): React.Node { style.paddingVertical == null && style.paddingTop == null)); - const useOnChangeSync = - (props.unstable_onChangeSync || props.unstable_onChangeTextSync) && - !(props.onChange || props.onChangeText); - textInput = (