@office-iss/react-native-win32 0.0.0-canary.266 → 0.0.0-canary.267

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 (54) hide show
  1. package/.flowconfig +1 -1
  2. package/CHANGELOG.json +16 -1
  3. package/CHANGELOG.md +12 -4
  4. package/Libraries/Animated/animations/Animation.js +4 -1
  5. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js +3 -1
  6. package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +17 -0
  7. package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +1 -0
  8. package/Libraries/Components/Touchable/BoundingDimensions.js +11 -3
  9. package/Libraries/Components/Touchable/Position.js +7 -2
  10. package/Libraries/Components/Touchable/Touchable.js +4 -0
  11. package/Libraries/Components/Touchable/Touchable.win32.js +4 -0
  12. package/Libraries/Components/View/ReactNativeStyleAttributes.js +1 -1
  13. package/Libraries/Core/ReactNativeVersion.js +1 -1
  14. package/Libraries/Core/setUpReactDevTools.js +33 -7
  15. package/Libraries/Inspector/NetworkOverlay.js +4 -0
  16. package/Libraries/Inspector/ReactDevToolsOverlay.js +8 -13
  17. package/Libraries/Interaction/TouchHistoryMath.js +22 -19
  18. package/Libraries/LogBox/Data/LogBoxData.js +2 -2
  19. package/Libraries/NativeComponent/BaseViewConfig.android.js +1 -1
  20. package/Libraries/NativeComponent/BaseViewConfig.ios.js +1 -1
  21. package/Libraries/NativeComponent/BaseViewConfig.win32.js +1 -1
  22. package/Libraries/Network/XHRInterceptor.js +63 -14
  23. package/Libraries/Renderer/shims/ReactNativeTypes.js +2 -1
  24. package/Libraries/StyleSheet/StyleSheetTypes.js +1 -1
  25. package/Libraries/WebSocket/WebSocketEvent.js +4 -1
  26. package/Libraries/WebSocket/WebSocketInterceptor.js +31 -13
  27. package/index.js +4 -0
  28. package/index.win32.js +4 -0
  29. package/overrides.json +12 -12
  30. package/package.json +11 -11
  31. package/src/private/devmenu/DevMenu.d.ts +20 -0
  32. package/src/private/devmenu/DevMenu.js +31 -0
  33. package/src/private/featureflags/ReactNativeFeatureFlags.js +22 -11
  34. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +4 -3
  35. package/src/private/reactdevtools/ReactDevToolsSettingsManager.android.js +20 -0
  36. package/src/private/reactdevtools/ReactDevToolsSettingsManager.ios.js +30 -0
  37. package/src/private/reactdevtools/ReactDevToolsSettingsManager.win32.js +20 -0
  38. package/src/private/specs/components/AndroidHorizontalScrollContentViewNativeComponent.js +1 -0
  39. package/src/private/specs/modules/{NativeDevToolsSettingsManager.js → NativeReactDevToolsSettingsManager.js} +3 -5
  40. package/src/private/webapis/performance/EventTiming.js +1 -1
  41. package/src/private/webapis/performance/Performance.js +3 -21
  42. package/src/private/webapis/performance/PerformanceObserver.js +68 -155
  43. package/src/private/webapis/performance/Utilities.js +25 -0
  44. package/src/private/webapis/performance/specs/NativePerformanceObserver.js +24 -16
  45. package/src/private/webapis/performance/specs/__mocks__/NativePerformance.js +11 -9
  46. package/src/private/webapis/performance/specs/__mocks__/NativePerformanceObserver.js +85 -58
  47. package/types/experimental.d.ts +1 -1
  48. package/types/index.d.ts +1 -1
  49. package/types/public/ReactNativeTypes.d.ts +0 -4
  50. package/Libraries/DevToolsSettings/DevToolsSettingsManager.android.js +0 -35
  51. package/Libraries/DevToolsSettings/DevToolsSettingsManager.d.ts +0 -20
  52. package/Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js +0 -49
  53. package/Libraries/DevToolsSettings/DevToolsSettingsManager.win32.js +0 -35
  54. package/Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js +0 -13
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<79bdedd5a09ba284cdaa2e4f40ffd2fd>>
7
+ * @generated SignedSource<<e161b67cb919ad7e2e67ddcb3c501adb>>
8
8
  * @flow strict
9
9
  */
10
10
 
@@ -36,6 +36,7 @@ export type ReactNativeFeatureFlagsJsOnly = {
36
36
  enableAnimatedPropsMemo: Getter<boolean>,
37
37
  enableOptimisedVirtualizedCells: Getter<boolean>,
38
38
  isLayoutAnimationEnabled: Getter<boolean>,
39
+ shouldSkipStateUpdatesForLoopingAnimations: Getter<boolean>,
39
40
  shouldUseAnimatedObjectForTransform: Getter<boolean>,
40
41
  shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter<boolean>,
41
42
  shouldUseSetNativePropsInFabric: Getter<boolean>,
@@ -55,13 +56,14 @@ export type ReactNativeFeatureFlags = {
55
56
  destroyFabricSurfacesInReactInstanceManager: Getter<boolean>,
56
57
  enableAlignItemsBaselineOnFabricIOS: Getter<boolean>,
57
58
  enableAndroidLineHeightCentering: Getter<boolean>,
58
- enableAndroidMixBlendModeProp: Getter<boolean>,
59
59
  enableBackgroundStyleApplicator: Getter<boolean>,
60
+ enableBridgelessArchitecture: Getter<boolean>,
60
61
  enableCleanTextInputYogaNode: Getter<boolean>,
61
62
  enableDeletionOfUnmountedViews: Getter<boolean>,
62
63
  enableEagerRootViewAttachment: Getter<boolean>,
63
64
  enableEventEmitterRetentionDuringGesturesOnAndroid: Getter<boolean>,
64
65
  enableFabricLogs: Getter<boolean>,
66
+ enableFabricRenderer: Getter<boolean>,
65
67
  enableFabricRendererExclusively: Getter<boolean>,
66
68
  enableGranularShadowTreeStateReconciliation: Getter<boolean>,
67
69
  enableIOSViewClipToPaddingBox: Getter<boolean>,
@@ -97,8 +99,8 @@ export type ReactNativeFeatureFlags = {
97
99
  useOptimizedEventBatchingOnAndroid: Getter<boolean>,
98
100
  useRuntimeShadowNodeReferenceUpdate: Getter<boolean>,
99
101
  useRuntimeShadowNodeReferenceUpdateOnLayout: Getter<boolean>,
100
- useStateAlignmentMechanism: Getter<boolean>,
101
102
  useTurboModuleInterop: Getter<boolean>,
103
+ useTurboModules: Getter<boolean>,
102
104
  }
103
105
 
104
106
  /**
@@ -146,6 +148,11 @@ export const enableOptimisedVirtualizedCells: Getter<boolean> = createJavaScript
146
148
  */
147
149
  export const isLayoutAnimationEnabled: Getter<boolean> = createJavaScriptFlagGetter('isLayoutAnimationEnabled', true);
148
150
 
151
+ /**
152
+ * If the animation is within Animated.loop, we do not send state updates to React.
153
+ */
154
+ export const shouldSkipStateUpdatesForLoopingAnimations: Getter<boolean> = createJavaScriptFlagGetter('shouldSkipStateUpdatesForLoopingAnimations', false);
155
+
149
156
  /**
150
157
  * Enables use of AnimatedObject for animating transform values.
151
158
  */
@@ -204,14 +211,14 @@ export const enableAlignItemsBaselineOnFabricIOS: Getter<boolean> = createNative
204
211
  * When enabled, custom line height calculation will be centered from top to bottom.
205
212
  */
206
213
  export const enableAndroidLineHeightCentering: Getter<boolean> = createNativeFlagGetter('enableAndroidLineHeightCentering', false);
207
- /**
208
- * Enables mix-blend-mode prop on Android.
209
- */
210
- export const enableAndroidMixBlendModeProp: Getter<boolean> = createNativeFlagGetter('enableAndroidMixBlendModeProp', false);
211
214
  /**
212
215
  * Use BackgroundStyleApplicator in place of other background/border drawing code
213
216
  */
214
217
  export const enableBackgroundStyleApplicator: Getter<boolean> = createNativeFlagGetter('enableBackgroundStyleApplicator', true);
218
+ /**
219
+ * Feature flag to enable the new bridgeless architecture. Note: Enabling this will force enable the following flags: `useTurboModules` & `enableFabricRenderer.
220
+ */
221
+ export const enableBridgelessArchitecture: Getter<boolean> = createNativeFlagGetter('enableBridgelessArchitecture', false);
215
222
  /**
216
223
  * Clean yoga node when <TextInput /> does not change.
217
224
  */
@@ -232,6 +239,10 @@ export const enableEventEmitterRetentionDuringGesturesOnAndroid: Getter<boolean>
232
239
  * This feature flag enables logs for Fabric.
233
240
  */
234
241
  export const enableFabricLogs: Getter<boolean> = createNativeFlagGetter('enableFabricLogs', false);
242
+ /**
243
+ * Enables the use of the Fabric renderer in the whole app.
244
+ */
245
+ export const enableFabricRenderer: Getter<boolean> = createNativeFlagGetter('enableFabricRenderer', false);
235
246
  /**
236
247
  * When the app is completely migrated to Fabric, set this flag to true to disable parts of Paper infrastructure that are not needed anymore but consume memory and CPU. Specifically, UIViewOperationQueue and EventDispatcherImpl will no longer work as they will not subscribe to ReactChoreographer for updates.
237
248
  */
@@ -372,14 +383,14 @@ export const useRuntimeShadowNodeReferenceUpdate: Getter<boolean> = createNative
372
383
  * When enabled, cloning shadow nodes during layout will update the reference held by the current JS fiber tree.
373
384
  */
374
385
  export const useRuntimeShadowNodeReferenceUpdateOnLayout: Getter<boolean> = createNativeFlagGetter('useRuntimeShadowNodeReferenceUpdateOnLayout', false);
375
- /**
376
- * When enabled, it uses optimised state reconciliation algorithm.
377
- */
378
- export const useStateAlignmentMechanism: Getter<boolean> = createNativeFlagGetter('useStateAlignmentMechanism', false);
379
386
  /**
380
387
  * In Bridgeless mode, should legacy NativeModules use the TurboModule system?
381
388
  */
382
389
  export const useTurboModuleInterop: Getter<boolean> = createNativeFlagGetter('useTurboModuleInterop', false);
390
+ /**
391
+ * When enabled, NativeModules will be executed by using the TurboModule system
392
+ */
393
+ export const useTurboModules: Getter<boolean> = createNativeFlagGetter('useTurboModules', false);
383
394
 
384
395
  /**
385
396
  * Overrides the feature flags with the provided methods.
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * @generated SignedSource<<ee3f60941427d4efa2f5b03bf0b78514>>
7
+ * @generated SignedSource<<cd4a2a047e3a6fdb4205efb518906462>>
8
8
  * @flow strict
9
9
  */
10
10
 
@@ -30,13 +30,14 @@ export interface Spec extends TurboModule {
30
30
  +destroyFabricSurfacesInReactInstanceManager?: () => boolean;
31
31
  +enableAlignItemsBaselineOnFabricIOS?: () => boolean;
32
32
  +enableAndroidLineHeightCentering?: () => boolean;
33
- +enableAndroidMixBlendModeProp?: () => boolean;
34
33
  +enableBackgroundStyleApplicator?: () => boolean;
34
+ +enableBridgelessArchitecture?: () => boolean;
35
35
  +enableCleanTextInputYogaNode?: () => boolean;
36
36
  +enableDeletionOfUnmountedViews?: () => boolean;
37
37
  +enableEagerRootViewAttachment?: () => boolean;
38
38
  +enableEventEmitterRetentionDuringGesturesOnAndroid?: () => boolean;
39
39
  +enableFabricLogs?: () => boolean;
40
+ +enableFabricRenderer?: () => boolean;
40
41
  +enableFabricRendererExclusively?: () => boolean;
41
42
  +enableGranularShadowTreeStateReconciliation?: () => boolean;
42
43
  +enableIOSViewClipToPaddingBox?: () => boolean;
@@ -72,8 +73,8 @@ export interface Spec extends TurboModule {
72
73
  +useOptimizedEventBatchingOnAndroid?: () => boolean;
73
74
  +useRuntimeShadowNodeReferenceUpdate?: () => boolean;
74
75
  +useRuntimeShadowNodeReferenceUpdateOnLayout?: () => boolean;
75
- +useStateAlignmentMechanism?: () => boolean;
76
76
  +useTurboModuleInterop?: () => boolean;
77
+ +useTurboModules?: () => boolean;
77
78
  }
78
79
 
79
80
  const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get<Spec>(
@@ -0,0 +1,20 @@
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-local
8
+ * @format
9
+ */
10
+
11
+ import NativeReactDevToolsSettingsManager from '../specs/modules/NativeReactDevToolsSettingsManager';
12
+
13
+ module.exports = {
14
+ setGlobalHookSettings(settings: string) {
15
+ NativeReactDevToolsSettingsManager?.setGlobalHookSettings(settings);
16
+ },
17
+ getGlobalHookSettings(): ?string {
18
+ return NativeReactDevToolsSettingsManager?.getGlobalHookSettings();
19
+ },
20
+ };
@@ -0,0 +1,30 @@
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-local
8
+ * @format
9
+ */
10
+
11
+ import Settings from '../../../Libraries/Settings/Settings';
12
+
13
+ const GLOBAL_HOOK_SETTINGS = 'ReactDevTools::HookSettings';
14
+
15
+ const ReactDevToolsSettingsManager = {
16
+ setGlobalHookSettings(settings: string): void {
17
+ Settings.set({
18
+ [GLOBAL_HOOK_SETTINGS]: settings,
19
+ });
20
+ },
21
+ getGlobalHookSettings(): ?string {
22
+ const value = Settings.get(GLOBAL_HOOK_SETTINGS);
23
+ if (typeof value === 'string') {
24
+ return value;
25
+ }
26
+ return null;
27
+ },
28
+ };
29
+
30
+ module.exports = ReactDevToolsSettingsManager;
@@ -0,0 +1,20 @@
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-local
8
+ * @format
9
+ */
10
+
11
+ import NativeReactDevToolsSettingsManager from '../specs/modules/NativeReactDevToolsSettingsManager';
12
+
13
+ module.exports = {
14
+ setGlobalHookSettings(settings: string) {
15
+ NativeReactDevToolsSettingsManager?.setGlobalHookSettings(settings);
16
+ },
17
+ getGlobalHookSettings(): ?string {
18
+ return NativeReactDevToolsSettingsManager?.getGlobalHookSettings();
19
+ },
20
+ };
@@ -23,4 +23,5 @@ type NativeType = HostComponent<NativeProps>;
23
23
 
24
24
  export default (codegenNativeComponent<NativeProps>(
25
25
  'AndroidHorizontalScrollContentView',
26
+ {interfaceOnly: true},
26
27
  ): NativeType);
@@ -13,12 +13,10 @@ import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport';
13
13
  import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry';
14
14
 
15
15
  export interface Spec extends TurboModule {
16
- +setConsolePatchSettings: (newConsolePatchSettings: string) => void;
17
- +getConsolePatchSettings: () => ?string;
18
- +setProfilingSettings?: (newProfilingSettings: string) => void;
19
- +getProfilingSettings?: () => ?string;
16
+ +setGlobalHookSettings: (settings: string) => void;
17
+ +getGlobalHookSettings: () => ?string;
20
18
  }
21
19
 
22
20
  export default (TurboModuleRegistry.get<Spec>(
23
- 'DevToolsSettingsManager',
21
+ 'ReactDevToolsSettingsManager',
24
22
  ): ?Spec);
@@ -16,7 +16,7 @@ import type {
16
16
  } from './PerformanceEntry';
17
17
 
18
18
  import {PerformanceEntry} from './PerformanceEntry';
19
- import {warnNoNativePerformanceObserver} from './PerformanceObserver';
19
+ import {warnNoNativePerformanceObserver} from './Utilities';
20
20
  import NativePerformanceObserver from './specs/NativePerformanceObserver';
21
21
 
22
22
  export type PerformanceEventTimingJSON = {
@@ -17,11 +17,10 @@ import type {
17
17
  import type {PerformanceEntryList} from './PerformanceObserver';
18
18
  import type {DetailType, PerformanceMarkOptions} from './UserTiming';
19
19
 
20
- import warnOnce from '../../../../Libraries/Utilities/warnOnce';
21
20
  import {EventCounts} from './EventTiming';
22
21
  import MemoryInfo from './MemoryInfo';
23
22
  import {ALWAYS_LOGGED_ENTRY_TYPES} from './PerformanceEntry';
24
- import {warnNoNativePerformanceObserver} from './PerformanceObserver';
23
+ import {warnNoNativePerformanceObserver} from './Utilities';
25
24
  import {
26
25
  performanceEntryTypeToRaw,
27
26
  rawToPerformanceEntry,
@@ -31,6 +30,7 @@ import ReactNativeStartupTiming from './ReactNativeStartupTiming';
31
30
  import NativePerformance from './specs/NativePerformance';
32
31
  import NativePerformanceObserver from './specs/NativePerformanceObserver';
33
32
  import {PerformanceMark, PerformanceMeasure} from './UserTiming';
33
+ import {warnNoNativePerformance} from './Utilities';
34
34
 
35
35
  declare var global: {
36
36
  // This value is defined directly via JSI, if available.
@@ -40,24 +40,6 @@ declare var global: {
40
40
  const getCurrentTimeStamp: () => DOMHighResTimeStamp =
41
41
  NativePerformance?.now ?? global.nativePerformanceNow ?? (() => Date.now());
42
42
 
43
- // We want some of the performance entry types to be always logged,
44
- // even if they are not currently observed - this is either to be able to
45
- // retrieve them at any time via Performance.getEntries* or to refer by other entries
46
- // (such as when measures may refer to marks, even if the latter are not observed)
47
- if (NativePerformanceObserver?.setIsBuffered) {
48
- NativePerformanceObserver?.setIsBuffered(
49
- ALWAYS_LOGGED_ENTRY_TYPES.map(performanceEntryTypeToRaw),
50
- true,
51
- );
52
- }
53
-
54
- function warnNoNativePerformance() {
55
- warnOnce(
56
- 'missing-native-performance',
57
- 'Missing native implementation of Performance',
58
- );
59
- }
60
-
61
43
  export type PerformanceMeasureOptions = {
62
44
  detail?: DetailType,
63
45
  start?: DOMHighResTimeStamp,
@@ -145,7 +127,7 @@ export default class Performance {
145
127
  return;
146
128
  }
147
129
 
148
- NativePerformanceObserver?.clearEntries(
130
+ NativePerformanceObserver.clearEntries(
149
131
  RawPerformanceEntryTypeValues.MARK,
150
132
  markName,
151
133
  );
@@ -13,7 +13,6 @@ import type {
13
13
  PerformanceEntryType,
14
14
  } from './PerformanceEntry';
15
15
 
16
- import warnOnce from '../../../../Libraries/Utilities/warnOnce';
17
16
  import {PerformanceEventTiming} from './EventTiming';
18
17
  import {PerformanceEntry} from './PerformanceEntry';
19
18
  import {
@@ -22,6 +21,8 @@ import {
22
21
  rawToPerformanceEntryType,
23
22
  } from './RawPerformanceEntry';
24
23
  import NativePerformanceObserver from './specs/NativePerformanceObserver';
24
+ import type {OpaqueNativeObserverHandle} from './specs/NativePerformanceObserver';
25
+ import {warnNoNativePerformanceObserver} from './Utilities';
25
26
 
26
27
  export type PerformanceEntryList = $ReadOnlyArray<PerformanceEntry>;
27
28
 
@@ -56,89 +57,24 @@ export class PerformanceObserverEntryList {
56
57
  }
57
58
  }
58
59
 
60
+ export type PerformanceObserverCallbackOptions = {
61
+ droppedEntriesCount: number,
62
+ };
63
+
59
64
  export type PerformanceObserverCallback = (
60
65
  list: PerformanceObserverEntryList,
61
66
  observer: PerformanceObserver,
62
67
  // The number of buffered entries which got dropped from the buffer due to the buffer being full:
63
- droppedEntryCount?: number,
68
+ options?: PerformanceObserverCallbackOptions,
64
69
  ) => void;
65
70
 
66
- export type PerformanceObserverInit =
67
- | {
68
- entryTypes: Array<PerformanceEntryType>,
69
- }
70
- | {
71
- type: PerformanceEntryType,
72
- durationThreshold?: DOMHighResTimeStamp,
73
- };
74
-
75
- type PerformanceObserverConfig = {|
76
- callback: PerformanceObserverCallback,
77
- entryTypes: $ReadOnlySet<PerformanceEntryType>,
78
- durationThreshold: ?number,
79
- |};
80
-
81
- const observerCountPerEntryType: Map<PerformanceEntryType, number> = new Map();
82
- const registeredObservers: Map<PerformanceObserver, PerformanceObserverConfig> =
83
- new Map();
84
- let isOnPerformanceEntryCallbackSet: boolean = false;
85
-
86
- // This is a callback that gets scheduled and periodically called from the native side
87
- const onPerformanceEntry = () => {
88
- if (!NativePerformanceObserver) {
89
- return;
90
- }
91
- const entryResult = NativePerformanceObserver.popPendingEntries();
92
- const rawEntries = entryResult?.entries ?? [];
93
- const droppedEntriesCount = entryResult?.droppedEntriesCount;
94
- if (rawEntries.length === 0) {
95
- return;
96
- }
97
- const entries = rawEntries.map(rawToPerformanceEntry);
98
- for (const [observer, observerConfig] of registeredObservers.entries()) {
99
- const entriesForObserver: PerformanceEntryList = entries.filter(entry => {
100
- if (!observerConfig.entryTypes.has(entry.entryType)) {
101
- return false;
102
- }
103
-
104
- if (
105
- entry.entryType === 'event' &&
106
- observerConfig.durationThreshold != null
107
- ) {
108
- return entry.duration >= observerConfig.durationThreshold;
109
- }
110
-
111
- return true;
112
- });
113
- if (entriesForObserver.length !== 0) {
114
- try {
115
- observerConfig.callback(
116
- new PerformanceObserverEntryList(entriesForObserver),
117
- observer,
118
- droppedEntriesCount,
119
- );
120
- } catch (error) {
121
- console.error(error);
122
- }
123
- }
124
- }
71
+ export type PerformanceObserverInit = {
72
+ entryTypes?: Array<PerformanceEntryType>,
73
+ type?: PerformanceEntryType,
74
+ buffered?: boolean,
75
+ durationThreshold?: DOMHighResTimeStamp,
125
76
  };
126
77
 
127
- export function warnNoNativePerformanceObserver() {
128
- warnOnce(
129
- 'missing-native-performance-observer',
130
- 'Missing native implementation of PerformanceObserver',
131
- );
132
- }
133
-
134
- function applyDurationThresholds() {
135
- const durationThresholds = Array.from(registeredObservers.values())
136
- .map(observerConfig => observerConfig.durationThreshold)
137
- .filter(Boolean);
138
-
139
- return Math.min(...durationThresholds);
140
- }
141
-
142
78
  function getSupportedPerformanceEntryTypes(): $ReadOnlyArray<PerformanceEntryType> {
143
79
  if (!NativePerformanceObserver) {
144
80
  return Object.freeze([]);
@@ -175,111 +111,96 @@ function getSupportedPerformanceEntryTypes(): $ReadOnlyArray<PerformanceEntryTyp
175
111
  * observer.observe({ type: "event" });
176
112
  */
177
113
  export class PerformanceObserver {
114
+ #nativeObserverHandle: OpaqueNativeObserverHandle | null = null;
178
115
  #callback: PerformanceObserverCallback;
179
116
  #type: 'single' | 'multiple' | void;
117
+ #calledAtLeastOnce = false;
180
118
 
181
119
  constructor(callback: PerformanceObserverCallback) {
182
120
  this.#callback = callback;
183
121
  }
184
122
 
185
123
  observe(options: PerformanceObserverInit): void {
186
- if (!NativePerformanceObserver) {
124
+ if (
125
+ !NativePerformanceObserver ||
126
+ NativePerformanceObserver.observe == null
127
+ ) {
187
128
  warnNoNativePerformanceObserver();
188
129
  return;
189
130
  }
190
131
 
191
132
  this.#validateObserveOptions(options);
192
133
 
193
- let requestedEntryTypes;
134
+ if (this.#nativeObserverHandle == null) {
135
+ this.#nativeObserverHandle = this.#createNativeObserver();
136
+ }
194
137
 
195
138
  if (options.entryTypes) {
196
139
  this.#type = 'multiple';
197
- requestedEntryTypes = new Set(options.entryTypes);
198
- } else {
140
+ NativePerformanceObserver.observe?.(this.#nativeObserverHandle, {
141
+ entryTypes: options.entryTypes.map(performanceEntryTypeToRaw),
142
+ });
143
+ } else if (options.type) {
199
144
  this.#type = 'single';
200
- requestedEntryTypes = new Set([options.type]);
145
+ NativePerformanceObserver.observe?.(this.#nativeObserverHandle, {
146
+ type: performanceEntryTypeToRaw(options.type),
147
+ buffered: options.buffered,
148
+ durationThreshold: options.durationThreshold,
149
+ });
201
150
  }
151
+ }
202
152
 
203
- // The same observer may receive multiple calls to "observe", so we need
204
- // to check what is new on this call vs. previous ones.
205
- const currentEntryTypes = registeredObservers.get(this)?.entryTypes;
206
- const nextEntryTypes = currentEntryTypes
207
- ? union(requestedEntryTypes, currentEntryTypes)
208
- : requestedEntryTypes;
209
-
210
- // This `observe` call is a no-op because there are no new things to observe.
211
- if (currentEntryTypes && currentEntryTypes.size === nextEntryTypes.size) {
153
+ disconnect(): void {
154
+ if (!NativePerformanceObserver) {
155
+ warnNoNativePerformanceObserver();
212
156
  return;
213
157
  }
214
158
 
215
- registeredObservers.set(this, {
216
- callback: this.#callback,
217
- durationThreshold:
218
- options.type === 'event' ? options.durationThreshold : undefined,
219
- entryTypes: nextEntryTypes,
220
- });
221
-
222
- if (!isOnPerformanceEntryCallbackSet) {
223
- NativePerformanceObserver.setOnPerformanceEntryCallback(
224
- onPerformanceEntry,
225
- );
226
- isOnPerformanceEntryCallbackSet = true;
159
+ if (
160
+ this.#nativeObserverHandle == null ||
161
+ !NativePerformanceObserver.disconnect
162
+ ) {
163
+ return;
227
164
  }
228
165
 
229
- // We only need to start listenening to new entry types being observed in
230
- // this observer.
231
- const newEntryTypes = currentEntryTypes
232
- ? difference(
233
- new Set(requestedEntryTypes.keys()),
234
- new Set(currentEntryTypes.keys()),
235
- )
236
- : new Set(requestedEntryTypes.keys());
237
- for (const type of newEntryTypes) {
238
- if (!observerCountPerEntryType.has(type)) {
239
- const rawType = performanceEntryTypeToRaw(type);
240
- NativePerformanceObserver.startReporting(rawType);
241
- }
242
- observerCountPerEntryType.set(
243
- type,
244
- (observerCountPerEntryType.get(type) ?? 0) + 1,
245
- );
246
- }
247
- applyDurationThresholds();
166
+ NativePerformanceObserver.disconnect(this.#nativeObserverHandle);
248
167
  }
249
168
 
250
- disconnect(): void {
251
- if (!NativePerformanceObserver) {
169
+ #createNativeObserver(): OpaqueNativeObserverHandle {
170
+ if (
171
+ !NativePerformanceObserver ||
172
+ !NativePerformanceObserver.createObserver
173
+ ) {
252
174
  warnNoNativePerformanceObserver();
253
175
  return;
254
176
  }
255
177
 
256
- const observerConfig = registeredObservers.get(this);
257
- if (!observerConfig) {
258
- return;
259
- }
178
+ this.#calledAtLeastOnce = false;
260
179
 
261
- // Disconnect this observer
262
- for (const type of observerConfig.entryTypes.keys()) {
263
- const numberOfObserversForThisType =
264
- observerCountPerEntryType.get(type) ?? 0;
265
- if (numberOfObserversForThisType === 1) {
266
- observerCountPerEntryType.delete(type);
267
- NativePerformanceObserver.stopReporting(
268
- performanceEntryTypeToRaw(type),
269
- );
270
- } else if (numberOfObserversForThisType !== 0) {
271
- observerCountPerEntryType.set(type, numberOfObserversForThisType - 1);
180
+ return NativePerformanceObserver.createObserver(() => {
181
+ // $FlowNotNull
182
+ const rawEntries = NativePerformanceObserver.takeRecords?.(
183
+ this.#nativeObserverHandle,
184
+ true, // sort records
185
+ );
186
+ if (!rawEntries) {
187
+ return;
272
188
  }
273
- }
274
189
 
275
- // Disconnect all observers if this was the last one
276
- registeredObservers.delete(this);
277
- if (registeredObservers.size === 0) {
278
- NativePerformanceObserver.setOnPerformanceEntryCallback(undefined);
279
- isOnPerformanceEntryCallbackSet = false;
280
- }
190
+ const entries = rawEntries.map(rawToPerformanceEntry);
191
+ const entryList = new PerformanceObserverEntryList(entries);
192
+
193
+ let droppedEntriesCount = 0;
194
+ if (!this.#calledAtLeastOnce) {
195
+ droppedEntriesCount =
196
+ NativePerformanceObserver.getDroppedEntriesCount?.(
197
+ this.#nativeObserverHandle,
198
+ ) ?? 0;
199
+ this.#calledAtLeastOnce = true;
200
+ }
281
201
 
282
- applyDurationThresholds();
202
+ this.#callback(entryList, this, {droppedEntriesCount});
203
+ });
283
204
  }
284
205
 
285
206
  #validateObserveOptions(options: PerformanceObserverInit): void {
@@ -309,7 +230,7 @@ export class PerformanceObserver {
309
230
  );
310
231
  }
311
232
 
312
- if (entryTypes && durationThreshold !== undefined) {
233
+ if (entryTypes && durationThreshold != null) {
313
234
  throw new TypeError(
314
235
  "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and durationThreshold arguments.",
315
236
  );
@@ -320,12 +241,4 @@ export class PerformanceObserver {
320
241
  getSupportedPerformanceEntryTypes();
321
242
  }
322
243
 
323
- function union<T>(a: $ReadOnlySet<T>, b: $ReadOnlySet<T>): Set<T> {
324
- return new Set([...a, ...b]);
325
- }
326
-
327
- function difference<T>(a: $ReadOnlySet<T>, b: $ReadOnlySet<T>): Set<T> {
328
- return new Set([...a].filter(x => !b.has(x)));
329
- }
330
-
331
244
  export {PerformanceEventTiming};
@@ -0,0 +1,25 @@
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
+ * @format
8
+ * @flow strict
9
+ */
10
+
11
+ import warnOnce from '../../../../Libraries/Utilities/warnOnce';
12
+
13
+ export function warnNoNativePerformance() {
14
+ warnOnce(
15
+ 'missing-native-performance',
16
+ 'Missing native implementation of Performance',
17
+ );
18
+ }
19
+
20
+ export function warnNoNativePerformanceObserver() {
21
+ warnOnce(
22
+ 'missing-native-performance-observer',
23
+ 'Missing native implementation of PerformanceObserver',
24
+ );
25
+ }