@office-iss/react-native-win32 0.0.0-canary.296 → 0.0.0-canary.297

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/.flowconfig +3 -1
  2. package/CHANGELOG.json +22 -1
  3. package/CHANGELOG.md +13 -4
  4. package/Libraries/Animated/Animated.js +0 -1
  5. package/Libraries/Animated/Animated.js.flow +0 -1
  6. package/Libraries/Animated/AnimatedExports.js +0 -1
  7. package/Libraries/Animated/AnimatedExports.js.flow +1 -2
  8. package/Libraries/Animated/animations/Animation.js +5 -2
  9. package/Libraries/Animated/components/AnimatedScrollView.js +53 -52
  10. package/Libraries/Animated/createAnimatedComponent.js +37 -33
  11. package/Libraries/Animated/nodes/AnimatedObject.js +2 -3
  12. package/Libraries/Animated/nodes/AnimatedProps.js +1 -1
  13. package/Libraries/Animated/shouldUseTurboAnimatedModule.js +6 -1
  14. package/Libraries/AppState/AppState.js +6 -1
  15. package/Libraries/Components/ActivityIndicator/ActivityIndicator.js +19 -18
  16. package/Libraries/Components/Button.js +2 -2
  17. package/Libraries/Components/Button.win32.js +2 -2
  18. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +2 -3
  19. package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +2 -1
  20. package/Libraries/Components/LayoutConformance/LayoutConformance.js +0 -1
  21. package/Libraries/Components/Pressable/Pressable.js +9 -6
  22. package/Libraries/Components/Pressable/Pressable.win32.js +9 -6
  23. package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +14 -13
  24. package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js +13 -1
  25. package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidTypes.js +29 -20
  26. package/Libraries/Components/ScrollView/ScrollView.d.ts +9 -5
  27. package/Libraries/Components/ScrollView/ScrollView.js +18 -12
  28. package/Libraries/Components/ScrollView/ScrollViewContext.js +2 -1
  29. package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +1 -1
  30. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +19 -6
  31. package/Libraries/Components/Switch/Switch.js +8 -2
  32. package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +1 -5
  33. package/Libraries/Components/TextInput/TextInput.flow.js +1 -5
  34. package/Libraries/Components/TextInput/TextInput.flow.win32.js +1 -5
  35. package/Libraries/Components/TextInput/TextInput.js +26 -25
  36. package/Libraries/Components/TextInput/TextInput.win32.js +27 -25
  37. package/Libraries/Components/Touchable/TouchableBounce.js +9 -3
  38. package/Libraries/Components/Touchable/TouchableHighlight.js +9 -4
  39. package/Libraries/Components/Touchable/TouchableNativeFeedback.js +2 -1
  40. package/Libraries/Components/Touchable/TouchableNativeFeedback.win32.js +2 -0
  41. package/Libraries/Components/Touchable/TouchableOpacity.js +7 -3
  42. package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +2 -2
  43. package/Libraries/Components/View/View.js +111 -25
  44. package/Libraries/Core/Devtools/loadBundleFromServer.js +49 -7
  45. package/Libraries/Core/Devtools/loadBundleFromServer.win32.js +49 -7
  46. package/Libraries/Core/InitializeCore.js +1 -22
  47. package/Libraries/Core/ReactNativeVersion.js +3 -2
  48. package/Libraries/Debugging/DebuggingOverlay.js +6 -8
  49. package/Libraries/Debugging/DebuggingOverlayRegistry.js +0 -1
  50. package/Libraries/Debugging/useSubscribeToDebuggingOverlayRegistry.js +0 -1
  51. package/Libraries/EventEmitter/NativeEventEmitter.js +1 -1
  52. package/Libraries/Image/AssetRegistry.js +4 -10
  53. package/Libraries/Image/AssetSourceResolver.js +17 -4
  54. package/Libraries/Image/Image.android.js +112 -106
  55. package/Libraries/Image/Image.ios.js +10 -2
  56. package/Libraries/Image/Image.win32.js +11 -3
  57. package/Libraries/Image/ImageAnalyticsTagContext.js +2 -2
  58. package/Libraries/Image/RelativeImageStub.js +1 -0
  59. package/Libraries/Lists/FlatList.d.ts +9 -5
  60. package/Libraries/Lists/FlatList.js +1 -1
  61. package/Libraries/Lists/SectionListModern.js +9 -3
  62. package/Libraries/LogBox/UI/LogBoxButton.js +2 -1
  63. package/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js +2 -1
  64. package/Libraries/LogBox/UI/LogBoxInspectorReactFrames.win32.js +2 -1
  65. package/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js +3 -2
  66. package/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.win32.js +3 -2
  67. package/Libraries/LogBox/UI/LogBoxInspectorStackFrames.js +2 -1
  68. package/Libraries/ReactNative/AppContainer-dev.js +4 -4
  69. package/Libraries/ReactNative/AppContainer-prod.js +0 -1
  70. package/Libraries/ReactNative/RootTag.js +2 -2
  71. package/Libraries/ReactPrivate/ReactNativePrivateInterface.js +1 -0
  72. package/Libraries/Renderer/shims/ReactNativeTypes.js +21 -25
  73. package/Libraries/Renderer/shims/ReactNativeTypes.win32.js +270 -0
  74. package/Libraries/StyleSheet/StyleSheetExports.js.flow +3 -1
  75. package/Libraries/StyleSheet/StyleSheetTypes.js +4 -3
  76. package/Libraries/StyleSheet/private/_TransformStyle.js +49 -21
  77. package/Libraries/StyleSheet/processBoxShadow.js +0 -1
  78. package/Libraries/StyleSheet/processFilter.js +0 -1
  79. package/Libraries/Text/Text.d.ts +7 -0
  80. package/Libraries/Text/Text.js +255 -244
  81. package/Libraries/Text/Text.win32.js +293 -284
  82. package/Libraries/Text/TextAncestor.js +3 -2
  83. package/Libraries/Text/TextProps.js +2 -34
  84. package/Libraries/Text/TextProps.win32.js +2 -33
  85. package/Libraries/Types/ReactDevToolsTypes.js +0 -1
  86. package/Libraries/Utilities/PerformanceLoggerContext.js +2 -2
  87. package/Libraries/Utilities/PlatformTypes.js +1 -1
  88. package/Libraries/vendor/core/ErrorUtils.js +28 -4
  89. package/index.js +0 -1
  90. package/jest/mockNativeComponent.js +2 -1
  91. package/jest/renderer.js +0 -1
  92. package/jest/resolver.js +31 -0
  93. package/jest/setup.js +1 -1
  94. package/overrides.json +27 -20
  95. package/package.json +13 -13
  96. package/src/private/animated/NativeAnimatedHelper.js +6 -1
  97. package/src/private/animated/NativeAnimatedHelper.win32.js +6 -1
  98. package/src/private/animated/createAnimatedPropsHook.js +11 -4
  99. package/src/private/animated/createAnimatedPropsMemoHook.js +0 -1
  100. package/src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js +0 -1
  101. package/src/private/components/scrollview/HScrollViewNativeComponents.js +0 -1
  102. package/src/private/components/scrollview/VScrollViewNativeComponents.js +0 -1
  103. package/src/private/devsupport/rndevtools/FuseboxSessionObserver.js +0 -1
  104. package/src/private/devsupport/rndevtools/ReactDevToolsSettingsManager.android.js +8 -9
  105. package/src/private/devsupport/rndevtools/ReactDevToolsSettingsManager.ios.js +12 -15
  106. package/src/private/devsupport/rndevtools/ReactDevToolsSettingsManager.win32.js +8 -9
  107. package/src/private/devsupport/rndevtools/setUpFuseboxReactDevToolsDispatcher.js +0 -1
  108. package/src/private/devsupport/rndevtools/specs/NativeReactDevToolsRuntimeSettingsModule.js +0 -1
  109. package/src/private/featureflags/ReactNativeFeatureFlags.js +39 -4
  110. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +5 -2
  111. package/src/private/setup/setUpDefaultReactNativeEnvironment.js +44 -0
  112. package/src/private/styles/composeStyles.js +12 -5
  113. package/src/private/webapis/dom/events/Event.js +3 -0
  114. package/src/private/webapis/dom/events/EventTarget.js +3 -0
  115. package/src/private/webapis/dom/nodes/ReactNativeElement.js +6 -23
  116. package/src/private/webapis/dom/nodes/ReadOnlyNode.js +3 -1
  117. package/src/private/webapis/dom/nodes/specs/NativeDOM.js +38 -0
  118. package/src/private/webapis/dom/oldstylecollections/HTMLCollection.js +3 -0
  119. package/src/private/webapis/dom/oldstylecollections/NodeList.js +3 -0
  120. package/src/private/webapis/errors/DOMException.js +166 -0
  121. package/src/private/webapis/geometry/DOMRect.js +5 -0
  122. package/src/private/webapis/geometry/DOMRectList.js +3 -0
  123. package/src/private/webapis/geometry/DOMRectReadOnly.js +6 -0
  124. package/src/private/webapis/intersectionobserver/IntersectionObserver.js +15 -7
  125. package/src/private/webapis/intersectionobserver/IntersectionObserverEntry.js +3 -0
  126. package/src/private/webapis/intersectionobserver/internals/IntersectionObserverManager.js +80 -18
  127. package/src/private/webapis/intersectionobserver/specs/NativeIntersectionObserver.js +12 -0
  128. package/src/private/webapis/mutationobserver/MutationObserver.js +23 -33
  129. package/src/private/webapis/mutationobserver/MutationRecord.js +3 -0
  130. package/src/private/webapis/mutationobserver/internals/MutationObserverManager.js +56 -24
  131. package/src/private/webapis/mutationobserver/specs/NativeMutationObserver.js +4 -1
  132. package/src/private/webapis/performance/MemoryInfo.js +4 -1
  133. package/src/private/webapis/performance/Performance.js +19 -8
  134. package/src/private/webapis/performance/PerformanceEntry.js +4 -0
  135. package/src/private/webapis/performance/ReactNativeStartupTiming.js +4 -1
  136. package/src/private/webapis/performance/internals/RawPerformanceEntry.js +2 -0
  137. package/src/private/webapis/structuredClone/structuredClone.js +233 -0
  138. package/src/private/webapis/webidl/PlatformObjects.js +59 -0
  139. package/src/types/globals.d.ts +42 -0
  140. package/src-win/Libraries/Text/Text.d.ts +7 -0
  141. package/types/index.d.ts +1 -1
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ /**
12
+ * This module implements the `DOMException` interface from WebIDL.
13
+ * See https://webidl.spec.whatwg.org/#idl-DOMException.
14
+ */
15
+
16
+ // flowlint unsafe-getters-setters:off
17
+
18
+ import {setPlatformObject} from '../webidl/PlatformObjects';
19
+
20
+ const ERROR_NAME_TO_ERROR_CODE_MAP: {[string]: number} = {
21
+ IndexSizeError: 1,
22
+ HierarchyRequestError: 3,
23
+ WrongDocumentError: 4,
24
+ InvalidCharacterError: 5,
25
+ NoModificationAllowedError: 7,
26
+ NotFoundError: 8,
27
+ NotSupportedError: 9,
28
+ InUseAttributeError: 10,
29
+ InvalidStateError: 11,
30
+ SyntaxError: 12,
31
+ InvalidModificationError: 13,
32
+ NamespaceError: 14,
33
+ InvalidAccessError: 15,
34
+ TypeMismatchError: 17,
35
+ SecurityError: 18,
36
+ NetworkError: 19,
37
+ AbortError: 20,
38
+ URLMismatchError: 21,
39
+ QuotaExceededError: 22,
40
+ TimeoutError: 23,
41
+ InvalidNodeTypeError: 24,
42
+ DataCloneError: 25,
43
+ };
44
+
45
+ const ERROR_CODES: {[string]: number} = {
46
+ INDEX_SIZE_ERR: 1,
47
+ DOMSTRING_SIZE_ERR: 2,
48
+ HIERARCHY_REQUEST_ERR: 3,
49
+ WRONG_DOCUMENT_ERR: 4,
50
+ INVALID_CHARACTER_ERR: 5,
51
+ NO_DATA_ALLOWED_ERR: 6,
52
+ NO_MODIFICATION_ALLOWED_ERR: 7,
53
+ NOT_FOUND_ERR: 8,
54
+ NOT_SUPPORTED_ERR: 9,
55
+ INUSE_ATTRIBUTE_ERR: 10,
56
+ INVALID_STATE_ERR: 11,
57
+ SYNTAX_ERR: 12,
58
+ INVALID_MODIFICATION_ERR: 13,
59
+ NAMESPACE_ERR: 14,
60
+ INVALID_ACCESS_ERR: 15,
61
+ VALIDATION_ERR: 16,
62
+ TYPE_MISMATCH_ERR: 17,
63
+ SECURITY_ERR: 18,
64
+ NETWORK_ERR: 19,
65
+ ABORT_ERR: 20,
66
+ URL_MISMATCH_ERR: 21,
67
+ QUOTA_EXCEEDED_ERR: 22,
68
+ TIMEOUT_ERR: 23,
69
+ INVALID_NODE_TYPE_ERR: 24,
70
+ DATA_CLONE_ERR: 25,
71
+ };
72
+
73
+ /* eslint-disable lint/require-extends-error */
74
+ // $FlowExpectedError[incompatible-variance] name is writable in Error but not in DOMException, but this is how it works on Web.
75
+ export default class DOMException extends Error {
76
+ static +INDEX_SIZE_ERR: 1;
77
+ static +DOMSTRING_SIZE_ERR: 2;
78
+ static +HIERARCHY_REQUEST_ERR: 3;
79
+ static +WRONG_DOCUMENT_ERR: 4;
80
+ static +INVALID_CHARACTER_ERR: 5;
81
+ static +NO_DATA_ALLOWED_ERR: 6;
82
+ static +NO_MODIFICATION_ALLOWED_ERR: 7;
83
+ static +NOT_FOUND_ERR: 8;
84
+ static +NOT_SUPPORTED_ERR: 9;
85
+ static +INUSE_ATTRIBUTE_ERR: 10;
86
+ static +INVALID_STATE_ERR: 11;
87
+ static +SYNTAX_ERR: 12;
88
+ static +INVALID_MODIFICATION_ERR: 13;
89
+ static +NAMESPACE_ERR: 14;
90
+ static +INVALID_ACCESS_ERR: 15;
91
+ static +VALIDATION_ERR: 16;
92
+ static +TYPE_MISMATCH_ERR: 17;
93
+ static +SECURITY_ERR: 18;
94
+ static +NETWORK_ERR: 19;
95
+ static +ABORT_ERR: 20;
96
+ static +URL_MISMATCH_ERR: 21;
97
+ static +QUOTA_EXCEEDED_ERR: 22;
98
+ static +TIMEOUT_ERR: 23;
99
+ static +INVALID_NODE_TYPE_ERR: 24;
100
+ static +DATA_CLONE_ERR: 25;
101
+
102
+ +INDEX_SIZE_ERR: 1;
103
+ +DOMSTRING_SIZE_ERR: 2;
104
+ +HIERARCHY_REQUEST_ERR: 3;
105
+ +WRONG_DOCUMENT_ERR: 4;
106
+ +INVALID_CHARACTER_ERR: 5;
107
+ +NO_DATA_ALLOWED_ERR: 6;
108
+ +NO_MODIFICATION_ALLOWED_ERR: 7;
109
+ +NOT_FOUND_ERR: 8;
110
+ +NOT_SUPPORTED_ERR: 9;
111
+ +INUSE_ATTRIBUTE_ERR: 10;
112
+ +INVALID_STATE_ERR: 11;
113
+ +SYNTAX_ERR: 12;
114
+ +INVALID_MODIFICATION_ERR: 13;
115
+ +NAMESPACE_ERR: 14;
116
+ +INVALID_ACCESS_ERR: 15;
117
+ +VALIDATION_ERR: 16;
118
+ +TYPE_MISMATCH_ERR: 17;
119
+ +SECURITY_ERR: 18;
120
+ +NETWORK_ERR: 19;
121
+ +ABORT_ERR: 20;
122
+ +URL_MISMATCH_ERR: 21;
123
+ +QUOTA_EXCEEDED_ERR: 22;
124
+ +TIMEOUT_ERR: 23;
125
+ +INVALID_NODE_TYPE_ERR: 24;
126
+ +DATA_CLONE_ERR: 25;
127
+
128
+ #name: string;
129
+ #code: number;
130
+
131
+ constructor(message?: string, name?: string) {
132
+ super(message);
133
+
134
+ if (typeof name === 'undefined') {
135
+ this.#name = 'Error';
136
+ this.#code = 0;
137
+ } else {
138
+ this.#name = String(name);
139
+ this.#code = ERROR_NAME_TO_ERROR_CODE_MAP[this.name] ?? 0;
140
+ }
141
+ }
142
+
143
+ get name(): string {
144
+ return this.#name;
145
+ }
146
+
147
+ get code(): number {
148
+ return this.#code;
149
+ }
150
+ }
151
+
152
+ for (const code in ERROR_CODES) {
153
+ Object.defineProperty(DOMException, code, {
154
+ enumerable: true,
155
+ value: ERROR_CODES[code],
156
+ });
157
+
158
+ Object.defineProperty(DOMException.prototype, code, {
159
+ enumerable: true,
160
+ value: ERROR_CODES[code],
161
+ });
162
+ }
163
+
164
+ setPlatformObject(DOMException, {
165
+ clone: exception => new DOMException(exception.message, exception.name),
166
+ });
@@ -14,6 +14,7 @@
14
14
  * licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
15
15
  */
16
16
 
17
+ import {setPlatformObject} from '../webidl/PlatformObjects';
17
18
  import DOMRectReadOnly, {type DOMRectInit} from './DOMRectReadOnly';
18
19
 
19
20
  // flowlint unsafe-getters-setters:off
@@ -80,3 +81,7 @@ export default class DOMRect extends DOMRectReadOnly {
80
81
  return new DOMRect(rect.x, rect.y, rect.width, rect.height);
81
82
  }
82
83
  }
84
+
85
+ setPlatformObject(DOMRect, {
86
+ clone: rect => new DOMRect(rect.x, rect.y, rect.width, rect.height),
87
+ });
@@ -14,6 +14,7 @@ import type {ArrayLike} from '../utils/ArrayLikeUtils';
14
14
  import type DOMRectReadOnly from './DOMRectReadOnly';
15
15
 
16
16
  import {createValueIterator} from '../utils/ArrayLikeUtils';
17
+ import {setPlatformObject} from '../webidl/PlatformObjects';
17
18
 
18
19
  // IMPORTANT: The Flow type definition for this module is defined in `DOMRectList.js.flow`
19
20
  // because Flow only supports indexers in classes in declaration files.
@@ -63,6 +64,8 @@ export default class DOMRectList implements Iterable<DOMRectReadOnly> {
63
64
  }
64
65
  }
65
66
 
67
+ setPlatformObject(DOMRectList);
68
+
66
69
  /**
67
70
  * This is an internal method to create instances of `DOMRectList`,
68
71
  * which avoids leaking its constructor to end users.
@@ -14,6 +14,8 @@
14
14
  * licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
15
15
  */
16
16
 
17
+ import {setPlatformObject} from '../webidl/PlatformObjects';
18
+
17
19
  // flowlint sketchy-null:off, unsafe-getters-setters:off
18
20
 
19
21
  export interface DOMRectInit {
@@ -186,3 +188,7 @@ export default class DOMRectReadOnly {
186
188
  this.#height = castToNumber(height);
187
189
  }
188
190
  }
191
+
192
+ setPlatformObject(DOMRectReadOnly, {
193
+ clone: rect => new DOMRectReadOnly(rect.x, rect.y, rect.width, rect.height),
194
+ });
@@ -14,6 +14,7 @@ import type {IntersectionObserverId} from './internals/IntersectionObserverManag
14
14
  import type IntersectionObserverEntry from './IntersectionObserverEntry';
15
15
 
16
16
  import ReactNativeElement from '../dom/nodes/ReactNativeElement';
17
+ import {setPlatformObject} from '../webidl/PlatformObjects';
17
18
  import * as IntersectionObserverManager from './internals/IntersectionObserverManager';
18
19
 
19
20
  export type IntersectionObserverCallback = (
@@ -22,7 +23,7 @@ export type IntersectionObserverCallback = (
22
23
  ) => mixed;
23
24
 
24
25
  export interface IntersectionObserverInit {
25
- // root?: ReactNativeElement, // This option exists on the Web but it's not currently supported in React Native.
26
+ root?: ?ReactNativeElement;
26
27
  // rootMargin?: string, // This option exists on the Web but it's not currently supported in React Native.
27
28
  threshold?: number | $ReadOnlyArray<number>;
28
29
 
@@ -66,6 +67,7 @@ export default class IntersectionObserver {
66
67
  _observationTargets: Set<ReactNativeElement> = new Set();
67
68
  _intersectionObserverId: ?IntersectionObserverId;
68
69
  _rootThresholds: $ReadOnlyArray<number> | null;
70
+ _root: ReactNativeElement | null;
69
71
 
70
72
  constructor(
71
73
  callback: IntersectionObserverCallback,
@@ -84,16 +86,18 @@ export default class IntersectionObserver {
84
86
  }
85
87
 
86
88
  // $FlowExpectedError[prop-missing] it's not typed in React Native but exists on Web.
87
- if (options?.root != null) {
89
+ if (options?.rootMargin != null) {
88
90
  throw new TypeError(
89
- "Failed to construct 'IntersectionObserver': root is not supported",
91
+ "Failed to construct 'IntersectionObserver': rootMargin is not supported",
90
92
  );
91
93
  }
92
94
 
93
- // $FlowExpectedError[prop-missing] it's not typed in React Native but exists on Web.
94
- if (options?.rootMargin != null) {
95
+ if (
96
+ options?.root != null &&
97
+ !(options?.root instanceof ReactNativeElement)
98
+ ) {
95
99
  throw new TypeError(
96
- "Failed to construct 'IntersectionObserver': rootMargin is not supported",
100
+ "Failed to construct 'IntersectionObserver': Failed to read the 'root' property from 'IntersectionObserverInit': The provided value is not of type '(null or ReactNativeElement)",
97
101
  );
98
102
  }
99
103
 
@@ -104,6 +108,7 @@ export default class IntersectionObserver {
104
108
  options?.threshold,
105
109
  this._rootThresholds != null, // only provide default if no rootThreshold
106
110
  );
111
+ this._root = options?.root ?? null;
107
112
  }
108
113
 
109
114
  /**
@@ -115,7 +120,7 @@ export default class IntersectionObserver {
115
120
  * NOTE: This cannot currently be configured and `root` is always `null`.
116
121
  */
117
122
  get root(): ReactNativeElement | null {
118
- return null;
123
+ return this._root;
119
124
  }
120
125
 
121
126
  /**
@@ -182,6 +187,7 @@ export default class IntersectionObserver {
182
187
 
183
188
  const didStartObserving = IntersectionObserverManager.observe({
184
189
  intersectionObserverId: this._getOrCreateIntersectionObserverId(),
190
+ root: this._root,
185
191
  target,
186
192
  });
187
193
 
@@ -250,6 +256,8 @@ export default class IntersectionObserver {
250
256
  }
251
257
  }
252
258
 
259
+ setPlatformObject(IntersectionObserver);
260
+
253
261
  /**
254
262
  * Converts the user defined `threshold` value into an array of sorted valid
255
263
  * threshold options for `IntersectionObserver` (double ∈ [0, 1]).
@@ -14,6 +14,7 @@ import type ReactNativeElement from '../dom/nodes/ReactNativeElement';
14
14
  import type {NativeIntersectionObserverEntry} from './specs/NativeIntersectionObserver';
15
15
 
16
16
  import DOMRectReadOnly from '../geometry/DOMRectReadOnly';
17
+ import {setPlatformObject} from '../webidl/PlatformObjects';
17
18
 
18
19
  /**
19
20
  * The [`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)
@@ -159,6 +160,8 @@ export default class IntersectionObserverEntry {
159
160
  }
160
161
  }
161
162
 
163
+ setPlatformObject(IntersectionObserverEntry);
164
+
162
165
  export function createIntersectionObserverEntry(
163
166
  entry: NativeIntersectionObserverEntry,
164
167
  target: ReactNativeElement,
@@ -23,9 +23,11 @@ import type IntersectionObserver, {
23
23
  IntersectionObserverCallback,
24
24
  } from '../IntersectionObserver';
25
25
  import type IntersectionObserverEntry from '../IntersectionObserverEntry';
26
+ import type {NativeIntersectionObserverToken} from '../specs/NativeIntersectionObserver';
26
27
 
27
28
  import * as Systrace from '../../../../../Libraries/Performance/Systrace';
28
29
  import warnOnce from '../../../../../Libraries/Utilities/warnOnce';
30
+ import * as ReactNativeFeatureFlags from '../../../featureflags/ReactNativeFeatureFlags';
29
31
  import {
30
32
  getInstanceHandle,
31
33
  getNativeNodeReference,
@@ -74,6 +76,26 @@ const targetToShadowNodeMap: WeakMap<
74
76
  ReturnType<typeof getNativeNodeReference>,
75
77
  > = new WeakMap();
76
78
 
79
+ const targetToTokenMap: WeakMap<
80
+ ReactNativeElement,
81
+ NativeIntersectionObserverToken,
82
+ > = new WeakMap();
83
+
84
+ let modernNativeIntersectionObserver =
85
+ NativeIntersectionObserver == null
86
+ ? null
87
+ : NativeIntersectionObserver.observeV2 == null ||
88
+ NativeIntersectionObserver.unobserveV2 == null
89
+ ? null
90
+ : {
91
+ observe: NativeIntersectionObserver.observeV2,
92
+ unobserve: NativeIntersectionObserver.unobserveV2,
93
+ };
94
+
95
+ if (!ReactNativeFeatureFlags.utilizeTokensInIntersectionObserver()) {
96
+ modernNativeIntersectionObserver = null;
97
+ }
98
+
77
99
  /**
78
100
  * Registers the given intersection observer and returns a unique ID for it,
79
101
  * which is required to start observing targets.
@@ -115,9 +137,11 @@ export function unregisterObserver(
115
137
  */
116
138
  export function observe({
117
139
  intersectionObserverId,
140
+ root,
118
141
  target,
119
142
  }: {
120
143
  intersectionObserverId: IntersectionObserverId,
144
+ root: ?ReactNativeElement,
121
145
  target: ReactNativeElement,
122
146
  }): boolean {
123
147
  if (NativeIntersectionObserver == null) {
@@ -149,24 +173,47 @@ export function observe({
149
173
  return false;
150
174
  }
151
175
 
176
+ const rootNativeNodeReference =
177
+ root != null ? getNativeNodeReference(root) : null;
178
+ if (root != null && rootNativeNodeReference == null) {
179
+ console.error(
180
+ 'IntersectionObserverManager: could not find shadow node for observation root',
181
+ );
182
+ return false;
183
+ }
184
+
152
185
  // Store the mapping between the instance handle and the target so we can
153
186
  // access it even after the instance handle has been unmounted.
154
187
  setTargetForInstanceHandle(instanceHandle, target);
155
188
 
156
- // Same for the mapping between the target and its shadow node.
157
- targetToShadowNodeMap.set(target, targetNativeNodeReference);
189
+ if (modernNativeIntersectionObserver == null) {
190
+ // Same for the mapping between the target and its shadow node.
191
+ targetToShadowNodeMap.set(target, targetNativeNodeReference);
192
+ }
158
193
 
159
194
  if (!isConnected) {
160
195
  NativeIntersectionObserver.connect(notifyIntersectionObservers);
161
196
  isConnected = true;
162
197
  }
163
198
 
164
- NativeIntersectionObserver.observe({
165
- intersectionObserverId,
166
- targetShadowNode: targetNativeNodeReference,
167
- thresholds: registeredObserver.observer.thresholds,
168
- rootThresholds: registeredObserver.observer.rnRootThresholds,
169
- });
199
+ if (modernNativeIntersectionObserver == null) {
200
+ NativeIntersectionObserver.observe({
201
+ intersectionObserverId,
202
+ rootShadowNode: rootNativeNodeReference,
203
+ targetShadowNode: targetNativeNodeReference,
204
+ thresholds: registeredObserver.observer.thresholds,
205
+ rootThresholds: registeredObserver.observer.rnRootThresholds,
206
+ });
207
+ } else {
208
+ const token = modernNativeIntersectionObserver.observe({
209
+ intersectionObserverId,
210
+ rootShadowNode: rootNativeNodeReference,
211
+ targetShadowNode: targetNativeNodeReference,
212
+ thresholds: registeredObserver.observer.thresholds,
213
+ rootThresholds: registeredObserver.observer.rnRootThresholds,
214
+ });
215
+ targetToTokenMap.set(target, token);
216
+ }
170
217
 
171
218
  return true;
172
219
  }
@@ -190,18 +237,33 @@ export function unobserve(
190
237
  return;
191
238
  }
192
239
 
193
- const targetNativeNodeReference = targetToShadowNodeMap.get(target);
194
- if (targetNativeNodeReference == null) {
195
- console.error(
196
- 'IntersectionObserverManager: could not find registration data for target',
240
+ if (modernNativeIntersectionObserver == null) {
241
+ const targetNativeNodeReference = targetToShadowNodeMap.get(target);
242
+ if (targetNativeNodeReference == null) {
243
+ console.error(
244
+ 'IntersectionObserverManager: could not find registration data for target',
245
+ );
246
+ return;
247
+ }
248
+
249
+ NativeIntersectionObserver.unobserve(
250
+ intersectionObserverId,
251
+ targetNativeNodeReference,
197
252
  );
198
- return;
199
- }
253
+ } else {
254
+ const targetToken = targetToTokenMap.get(target);
255
+ if (targetToken == null) {
256
+ console.error(
257
+ 'IntersectionObserverManager: could not find registration data for target',
258
+ );
259
+ return;
260
+ }
200
261
 
201
- NativeIntersectionObserver.unobserve(
202
- intersectionObserverId,
203
- targetNativeNodeReference,
204
- );
262
+ modernNativeIntersectionObserver.unobserve(
263
+ intersectionObserverId,
264
+ targetToken,
265
+ );
266
+ }
205
267
  }
206
268
 
207
269
  /**
@@ -25,14 +25,26 @@ export type NativeIntersectionObserverEntry = {
25
25
 
26
26
  export type NativeIntersectionObserverObserveOptions = {
27
27
  intersectionObserverId: number,
28
+ rootShadowNode?: ?mixed,
28
29
  targetShadowNode: mixed,
29
30
  thresholds: $ReadOnlyArray<number>,
30
31
  rootThresholds?: ?$ReadOnlyArray<number>,
31
32
  };
32
33
 
34
+ export type NativeIntersectionObserverToken = mixed;
35
+
33
36
  export interface Spec extends TurboModule {
37
+ // TODO(T223605846): Remove legacy observe method
34
38
  +observe: (options: NativeIntersectionObserverObserveOptions) => void;
39
+ // TODO(T223605846): Remove legacy unobserve method
35
40
  +unobserve: (intersectionObserverId: number, targetShadowNode: mixed) => void;
41
+ +observeV2?: (
42
+ options: NativeIntersectionObserverObserveOptions,
43
+ ) => NativeIntersectionObserverToken;
44
+ +unobserveV2?: (
45
+ intersectionObserverId: number,
46
+ token: NativeIntersectionObserverToken,
47
+ ) => void;
36
48
  +connect: (notifyIntersectionObserversCallback: () => void) => void;
37
49
  +disconnect: () => void;
38
50
  +takeRecords: () => $ReadOnlyArray<NativeIntersectionObserverEntry>;
@@ -14,7 +14,9 @@ import type {MutationObserverId} from './internals/MutationObserverManager';
14
14
  import type MutationRecord from './MutationRecord';
15
15
 
16
16
  import ReactNativeElement from '../dom/nodes/ReactNativeElement';
17
+ import {setPlatformObject} from '../webidl/PlatformObjects';
17
18
  import * as MutationObserverManager from './internals/MutationObserverManager';
19
+ import nullthrows from 'nullthrows';
18
20
 
19
21
  export type MutationObserverCallback = (
20
22
  mutationRecords: $ReadOnlyArray<MutationRecord>,
@@ -42,6 +44,7 @@ export interface MutationObserverInit {
42
44
  */
43
45
  export default class MutationObserver {
44
46
  _callback: MutationObserverCallback;
47
+ // TODO: delete in the next version.
45
48
  _observationTargets: Set<ReactNativeElement> = new Set();
46
49
  _mutationObserverId: ?MutationObserverId;
47
50
 
@@ -115,56 +118,41 @@ export default class MutationObserver {
115
118
 
116
119
  const mutationObserverId = this._getOrCreateMutationObserverId();
117
120
 
118
- // As per the spec, if the target is already being observed, we "reset"
119
- // the observation and only use the last options used.
120
- if (this._observationTargets.has(target)) {
121
- MutationObserverManager.unobserve(mutationObserverId, target);
122
- }
123
-
124
121
  const didStartObserving = MutationObserverManager.observe({
125
122
  mutationObserverId,
126
123
  target,
127
124
  subtree: Boolean(options?.subtree),
128
125
  });
129
126
 
130
- if (didStartObserving) {
127
+ if (didStartObserving && !MutationObserverManager.unobserveAll) {
131
128
  this._observationTargets.add(target);
132
129
  }
133
130
  }
134
131
 
135
- _unobserve(target: ReactNativeElement): void {
136
- if (!(target instanceof ReactNativeElement)) {
137
- throw new TypeError(
138
- "Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'ReactNativeElement'.",
139
- );
140
- }
141
-
142
- if (!this._observationTargets.has(target)) {
143
- return;
144
- }
145
-
132
+ /**
133
+ * Tells the observer to stop watching for mutations.
134
+ * The observer can be reused by calling its `observe()` method again.
135
+ */
136
+ disconnect(): void {
146
137
  const mutationObserverId = this._mutationObserverId;
147
138
  if (mutationObserverId == null) {
148
139
  return;
149
140
  }
150
141
 
151
- MutationObserverManager.unobserve(mutationObserverId, target);
152
- this._observationTargets.delete(target);
153
-
154
- if (this._observationTargets.size === 0) {
155
- MutationObserverManager.unregisterObserver(mutationObserverId);
156
- this._mutationObserverId = null;
142
+ if (MutationObserverManager.unobserveAll) {
143
+ MutationObserverManager.unobserveAll(mutationObserverId);
144
+ } else if (MutationObserverManager.unobserve) {
145
+ for (const target of this._observationTargets.keys()) {
146
+ nullthrows(MutationObserverManager.unobserve)(
147
+ mutationObserverId,
148
+ target,
149
+ );
150
+ }
151
+ this._observationTargets.clear();
157
152
  }
158
- }
159
153
 
160
- /**
161
- * Tells the observer to stop watching for mutations.
162
- * The observer can be reused by calling its `observe()` method again.
163
- */
164
- disconnect(): void {
165
- for (const target of this._observationTargets.keys()) {
166
- this._unobserve(target);
167
- }
154
+ MutationObserverManager.unregisterObserver(mutationObserverId);
155
+ this._mutationObserverId = null;
168
156
  }
169
157
 
170
158
  _getOrCreateMutationObserverId(): MutationObserverId {
@@ -184,3 +172,5 @@ export default class MutationObserver {
184
172
  return this._mutationObserverId;
185
173
  }
186
174
  }
175
+
176
+ setPlatformObject(MutationObserver);
@@ -15,6 +15,7 @@ import type ReadOnlyNode from '../dom/nodes/ReadOnlyNode';
15
15
  import type {NativeMutationRecord} from './specs/NativeMutationObserver';
16
16
 
17
17
  import NodeList, {createNodeList} from '../dom/oldstylecollections/NodeList';
18
+ import {setPlatformObject} from '../webidl/PlatformObjects';
18
19
 
19
20
  export type MutationType = 'attributes' | 'characterData' | 'childList';
20
21
 
@@ -75,6 +76,8 @@ export default class MutationRecord {
75
76
  }
76
77
  }
77
78
 
79
+ setPlatformObject(MutationRecord);
80
+
78
81
  export function createMutationRecord(
79
82
  entry: NativeMutationRecord,
80
83
  ): MutationRecord {