@office-iss/react-native-win32 0.69.0 → 0.70.0-preview.1

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 (154) hide show
  1. package/.eslintrc.js +0 -1
  2. package/.flowconfig +5 -1
  3. package/CHANGELOG.json +194 -32
  4. package/CHANGELOG.md +79 -19
  5. package/IntegrationTests/AsyncStorageTest.js +20 -4
  6. package/IntegrationTests/BUCK +2 -2
  7. package/IntegrationTests/LayoutEventsTest.js +4 -1
  8. package/IntegrationTests/{launchWebSocketServer.command → launchWebSocketServer.sh} +3 -9
  9. package/Libraries/Alert/Alert.js +18 -4
  10. package/Libraries/Alert/Alert.win32.js +2 -0
  11. package/Libraries/Alert/NativeAlertManager.js +1 -0
  12. package/Libraries/Animated/Animated.js +2 -2
  13. package/Libraries/Animated/AnimatedEvent.js +7 -4
  14. package/Libraries/Animated/AnimatedImplementation.js +17 -3
  15. package/Libraries/Animated/AnimatedMock.js +7 -2
  16. package/Libraries/Animated/NativeAnimatedHelper.js +220 -95
  17. package/Libraries/Animated/NativeAnimatedModule.js +3 -0
  18. package/Libraries/Animated/NativeAnimatedTurboModule.js +3 -0
  19. package/Libraries/Animated/animations/SpringAnimation.js +3 -3
  20. package/Libraries/Animated/animations/TimingAnimation.js +3 -3
  21. package/Libraries/Animated/createAnimatedComponent.js +8 -1
  22. package/Libraries/Animated/nodes/AnimatedAddition.js +3 -1
  23. package/Libraries/Animated/nodes/AnimatedColor.js +50 -29
  24. package/Libraries/Animated/nodes/AnimatedDiffClamp.js +3 -1
  25. package/Libraries/Animated/nodes/AnimatedDivision.js +3 -1
  26. package/Libraries/Animated/nodes/AnimatedInterpolation.js +22 -21
  27. package/Libraries/Animated/nodes/AnimatedModulo.js +3 -1
  28. package/Libraries/Animated/nodes/AnimatedMultiplication.js +3 -2
  29. package/Libraries/Animated/nodes/AnimatedProps.js +20 -12
  30. package/Libraries/Animated/nodes/AnimatedStyle.js +19 -16
  31. package/Libraries/Animated/nodes/AnimatedSubtraction.js +3 -1
  32. package/Libraries/Animated/nodes/AnimatedTransform.js +5 -5
  33. package/Libraries/Animated/nodes/AnimatedValue.js +14 -5
  34. package/Libraries/Animated/nodes/AnimatedValueXY.js +28 -1
  35. package/Libraries/Animated/useAnimatedProps.js +1 -0
  36. package/Libraries/AppState/AppState.js +0 -32
  37. package/Libraries/BatchedBridge/MessageQueue.js +21 -15
  38. package/Libraries/BatchedBridge/NativeModules.js +3 -4
  39. package/Libraries/Blob/FileReader.js +0 -6
  40. package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +0 -20
  41. package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.win32.js +0 -20
  42. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +4 -0
  43. package/Libraries/Components/Keyboard/Keyboard.js +0 -11
  44. package/Libraries/Components/Pressable/Pressable.js +2 -0
  45. package/Libraries/Components/Pressable/Pressable.win32.js +2 -0
  46. package/Libraries/Components/SafeAreaView/RCTSafeAreaViewNativeComponent.js +1 -3
  47. package/Libraries/Components/SafeAreaView/SafeAreaView.js +3 -30
  48. package/Libraries/Components/SafeAreaView/SafeAreaView.win32.js +4 -32
  49. package/Libraries/Components/ScrollView/ScrollView.js +13 -11
  50. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +5 -3
  51. package/Libraries/Components/StatusBar/StatusBar.js +10 -7
  52. package/Libraries/Components/TextInput/InputAccessoryView.js +14 -13
  53. package/Libraries/Components/TextInput/TextInput.js +12 -2
  54. package/Libraries/Components/Touchable/PooledClass.js +16 -4
  55. package/Libraries/Components/Touchable/Touchable.js +50 -1
  56. package/Libraries/Components/Touchable/Touchable.win32.js +972 -0
  57. package/Libraries/Components/Touchable/TouchableNativeFeedback.js +6 -2
  58. package/Libraries/Components/View/ReactNativeStyleAttributes.js +0 -7
  59. package/Libraries/Components/View/ViewPropTypes.js +3 -8
  60. package/Libraries/Components/View/ViewPropTypes.win32.js +3 -8
  61. package/Libraries/Core/ExceptionsManager.js +2 -0
  62. package/Libraries/Core/ReactNativeVersion.js +2 -2
  63. package/Libraries/Core/Timers/JSTimers.js +2 -2
  64. package/Libraries/Core/polyfillPromise.js +0 -32
  65. package/Libraries/Core/setUpBatchedBridge.js +5 -1
  66. package/Libraries/Core/setUpPerformance.js +1 -1
  67. package/Libraries/EventEmitter/NativeEventEmitter.js +0 -13
  68. package/Libraries/Image/AssetSourceResolver.js +2 -2
  69. package/Libraries/Image/Image.android.js +5 -3
  70. package/Libraries/Image/Image.ios.js +6 -3
  71. package/Libraries/Image/Image.win32.js +6 -3
  72. package/Libraries/Image/ImageSource.js +7 -5
  73. package/Libraries/Inspector/ElementBox.js +2 -2
  74. package/Libraries/Inspector/NetworkOverlay.js +13 -8
  75. package/Libraries/Interaction/PanResponder.js +16 -14
  76. package/Libraries/Linking/Linking.js +0 -11
  77. package/Libraries/Lists/FlatList.js +3 -2
  78. package/Libraries/Lists/SectionList.js +2 -0
  79. package/Libraries/Lists/ViewabilityHelper.js +7 -3
  80. package/Libraries/Lists/VirtualizeUtils.js +33 -20
  81. package/Libraries/Lists/VirtualizedList.js +93 -47
  82. package/Libraries/Lists/VirtualizedListContext.js +1 -0
  83. package/Libraries/Lists/VirtualizedSectionList.js +14 -9
  84. package/Libraries/Lists/__tests__/VirtualizeUtils-test.js +19 -18
  85. package/Libraries/Lists/__tests__/VirtualizedList-test.js +10 -6
  86. package/Libraries/LogBox/Data/LogBoxData.js +1 -1
  87. package/Libraries/LogBox/Data/parseLogBoxLog.js +1 -1
  88. package/Libraries/LogBox/LogBox.js +3 -1
  89. package/Libraries/LogBox/UI/AnsiHighlight.js +2 -0
  90. package/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.js +3 -0
  91. package/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js +0 -3
  92. package/Libraries/LogBox/UI/LogBoxInspectorStackFrames.js +8 -3
  93. package/Libraries/NativeComponent/BaseViewConfig.android.js +9 -18
  94. package/Libraries/NativeComponent/BaseViewConfig.ios.js +26 -12
  95. package/Libraries/NativeComponent/BaseViewConfig.win32.js +26 -12
  96. package/Libraries/Network/XMLHttpRequest.js +9 -11
  97. package/Libraries/Performance/PureComponentDebug.js +1 -0
  98. package/Libraries/PermissionsAndroid/NativePermissionsAndroid.js +9 -1
  99. package/Libraries/PermissionsAndroid/PermissionsAndroid.js +16 -0
  100. package/Libraries/Pressability/Pressability.js +26 -16
  101. package/Libraries/Pressability/Pressability.win32.js +26 -16
  102. package/Libraries/Promise.js +0 -1
  103. package/Libraries/ReactNative/AppRegistry.js +16 -13
  104. package/Libraries/ReactNative/BridgelessUIManager.js +2 -0
  105. package/Libraries/ReactNative/PaperUIManager.js +9 -9
  106. package/Libraries/ReactNative/PaperUIManager.win32.js +7 -8
  107. package/Libraries/ReactNative/ReactNativeFeatureFlags.js +12 -0
  108. package/Libraries/ReactNative/ReactNativeRuntimeDiagnostics.js +68 -0
  109. package/Libraries/ReactNative/getNativeComponentAttributes.js +6 -7
  110. package/Libraries/ReactNative/renderApplication.js +1 -1
  111. package/Libraries/Renderer/implementations/ReactFabric-dev.js +4443 -3615
  112. package/Libraries/Renderer/implementations/ReactFabric-prod.js +1496 -1170
  113. package/Libraries/Renderer/implementations/ReactFabric-profiling.js +1694 -1356
  114. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +4439 -3588
  115. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +1583 -1249
  116. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +1719 -1372
  117. package/Libraries/Storage/AsyncStorage.js +7 -1
  118. package/Libraries/StyleSheet/PlatformColorValueTypes.ios.js +8 -0
  119. package/Libraries/StyleSheet/flattenStyle.js +1 -1
  120. package/Libraries/StyleSheet/processTransform.js +2 -0
  121. package/Libraries/StyleSheet/splitLayoutProps.js +2 -0
  122. package/Libraries/Text/Text.js +15 -7
  123. package/Libraries/Types/CoreEventTypes.js +137 -11
  124. package/Libraries/Types/CoreEventTypes.win32.js +147 -22
  125. package/Libraries/Utilities/Dimensions.js +0 -13
  126. package/Libraries/Utilities/Dimensions.win32.js +0 -9
  127. package/Libraries/Utilities/HMRClient.js +3 -3
  128. package/Libraries/Utilities/Platform.ios.js +0 -7
  129. package/Libraries/Utilities/ReactNativeTestTools.js +3 -1
  130. package/Libraries/Utilities/codegenNativeCommands.js +11 -2
  131. package/Libraries/Utilities/deepFreezeAndThrowOnMutationInDev.js +2 -0
  132. package/Libraries/Utilities/stringifySafe.js +3 -1
  133. package/Libraries/Utilities/truncate.js +1 -1
  134. package/Libraries/Utilities/verifyComponentAttributeEquivalence.js +2 -2
  135. package/Libraries/Vibration/Vibration.js +1 -1
  136. package/Libraries/WebSocket/WebSocket.js +1 -0
  137. package/Libraries/vendor/emitter/EventEmitter.js +105 -12
  138. package/Libraries/vendor/emitter/__flowtests__/EventEmitter-flowtest.js +73 -117
  139. package/flow/JSITimerInternalType.js +30 -0
  140. package/jest/assetFileTransformer.js +3 -2
  141. package/jest/setup.js +4 -0
  142. package/jest.config.js +0 -1
  143. package/overrides.json +23 -16
  144. package/package.json +23 -24
  145. package/rntypes/index.d.ts +0 -1
  146. package/src/rntypes/index.d.ts +0 -1
  147. package/Libraries/vendor/emitter/EventSubscription.js +0 -19
  148. package/Libraries/vendor/emitter/_EmitterSubscription.js +0 -62
  149. package/Libraries/vendor/emitter/_EventEmitter.js +0 -184
  150. package/Libraries/vendor/emitter/_EventSubscription.js +0 -45
  151. package/Libraries/vendor/emitter/_EventSubscriptionVendor.js +0 -108
  152. package/jest/preprocessor.js +0 -40
  153. package/jest/preprocessor_DO_NOT_USE.js +0 -122
  154. package/src/Libraries/Lists/__tests__/__snapshots__/VirtualizeUtils-test.js.snap +0 -3
@@ -20,6 +20,7 @@ export type Args = {|
20
20
  cancelButtonKey?: string,
21
21
  destructiveButtonKey?: string,
22
22
  keyboardType?: string,
23
+ userInterfaceStyle?: string,
23
24
  |};
24
25
 
25
26
  export interface Spec extends TurboModule {
@@ -16,8 +16,8 @@ import typeof AnimatedSectionList from './components/AnimatedSectionList';
16
16
  import typeof AnimatedText from './components/AnimatedText';
17
17
  import typeof AnimatedView from './components/AnimatedView';
18
18
 
19
- const AnimatedMock = require('./AnimatedMock');
20
- const AnimatedImplementation = require('./AnimatedImplementation');
19
+ import * as AnimatedMock from './AnimatedMock';
20
+ import * as AnimatedImplementation from './AnimatedImplementation';
21
21
 
22
22
  const Animated = ((Platform.isTesting
23
23
  ? AnimatedMock
@@ -41,7 +41,7 @@ function attachNativeEvent(
41
41
  // key path inside the `nativeEvent` object. Ex.: ['contentOffset', 'x'].
42
42
  const eventMappings = [];
43
43
 
44
- const traverse = (value, path) => {
44
+ const traverse = (value: mixed, path: Array<string>) => {
45
45
  if (value instanceof AnimatedValue) {
46
46
  value.__makeNative(platformConfig);
47
47
 
@@ -94,8 +94,8 @@ function attachNativeEvent(
94
94
  };
95
95
  }
96
96
 
97
- function validateMapping(argMapping, args) {
98
- const validate = (recMapping, recEvt, key) => {
97
+ function validateMapping(argMapping: $ReadOnlyArray<?Mapping>, args: any) {
98
+ const validate = (recMapping: ?Mapping, recEvt: any, key: string) => {
99
99
  if (recMapping instanceof AnimatedValue) {
100
100
  invariant(
101
101
  typeof recEvt === 'number',
@@ -223,7 +223,10 @@ class AnimatedEvent {
223
223
  validatedMapping = true;
224
224
  }
225
225
 
226
- const traverse = (recMapping, recEvt) => {
226
+ const traverse = (
227
+ recMapping: ?(Mapping | AnimatedValue),
228
+ recEvt: any,
229
+ ) => {
227
230
  if (recMapping instanceof AnimatedValue) {
228
231
  if (typeof recEvt === 'number') {
229
232
  recMapping.setValue(recEvt);
@@ -94,7 +94,7 @@ const _combineCallbacks = function (
94
94
  config: $ReadOnly<{...AnimationConfig, ...}>,
95
95
  ) {
96
96
  if (callback && config.onComplete) {
97
- return (...args) => {
97
+ return (...args: Array<EndResult>) => {
98
98
  config.onComplete && config.onComplete(...args);
99
99
  callback && callback(...args);
100
100
  };
@@ -308,7 +308,7 @@ const sequence = function (
308
308
  let current = 0;
309
309
  return {
310
310
  start: function (callback?: ?EndCallback) {
311
- const onComplete = function (result) {
311
+ const onComplete = function (result: EndResult) {
312
312
  if (!result.finished) {
313
313
  callback && callback(result);
314
314
  return;
@@ -380,7 +380,7 @@ const parallel = function (
380
380
  }
381
381
 
382
382
  animations.forEach((animation, idx) => {
383
- const cb = function (endResult) {
383
+ const cb = function (endResult: EndResult | {finished: boolean}) {
384
384
  hasEnded[idx] = true;
385
385
  doneCount++;
386
386
  if (doneCount === animations.length) {
@@ -460,6 +460,7 @@ type LoopAnimationConfig = {
460
460
 
461
461
  const loop = function (
462
462
  animation: CompositeAnimation,
463
+ // $FlowFixMe[prop-missing]
463
464
  {iterations = -1, resetBeforeIteration = true}: LoopAnimationConfig = {},
464
465
  ): CompositeAnimation {
465
466
  let isFinished = false;
@@ -551,6 +552,19 @@ const event = function (
551
552
  }
552
553
  };
553
554
 
555
+ // All types of animated nodes that represent scalar numbers and can be interpolated (etc)
556
+ type AnimatedNumeric =
557
+ | AnimatedAddition
558
+ | AnimatedDiffClamp
559
+ | AnimatedDivision
560
+ | AnimatedInterpolation<number>
561
+ | AnimatedModulo
562
+ | AnimatedMultiplication
563
+ | AnimatedSubtraction
564
+ | AnimatedValue;
565
+
566
+ export type {AnimatedNumeric as Numeric};
567
+
554
568
  /**
555
569
  * The `Animated` library is designed to make animations fluid, powerful, and
556
570
  * easy to build and maintain. `Animated` focuses on declarative relationships
@@ -10,6 +10,8 @@
10
10
 
11
11
  'use strict';
12
12
 
13
+ import type {EndResult} from './animations/Animation';
14
+
13
15
  const {AnimatedEvent, attachNativeEvent} = require('./AnimatedEvent');
14
16
  const AnimatedImplementation = require('./AnimatedImplementation');
15
17
  const AnimatedInterpolation = require('./nodes/AnimatedInterpolation');
@@ -23,7 +25,7 @@ import type {EndCallback} from './animations/Animation';
23
25
  import type {TimingAnimationConfig} from './animations/TimingAnimation';
24
26
  import type {DecayAnimationConfig} from './animations/DecayAnimation';
25
27
  import type {SpringAnimationConfig} from './animations/SpringAnimation';
26
-
28
+ import type {Numeric as AnimatedNumeric} from './AnimatedImplementation';
27
29
  import AnimatedColor from './nodes/AnimatedColor';
28
30
 
29
31
  /**
@@ -43,7 +45,7 @@ function mockAnimationStart(
43
45
  const guardedCallback =
44
46
  callback == null
45
47
  ? callback
46
- : (...args) => {
48
+ : (...args: Array<EndResult>) => {
47
49
  if (inAnimationCallback) {
48
50
  console.warn(
49
51
  'Ignoring recursive animation callback when running mock animations',
@@ -158,11 +160,14 @@ type LoopAnimationConfig = {
158
160
 
159
161
  const loop = function (
160
162
  animation: CompositeAnimation,
163
+ // $FlowFixMe[prop-missing]
161
164
  {iterations = -1}: LoopAnimationConfig = {},
162
165
  ): CompositeAnimation {
163
166
  return emptyAnimation;
164
167
  };
165
168
 
169
+ export type {AnimatedNumeric as Numeric};
170
+
166
171
  module.exports = {
167
172
  Value: AnimatedValue,
168
173
  ValueXY: AnimatedValueXY,
@@ -20,7 +20,10 @@ import type {
20
20
  } from './NativeAnimatedModule';
21
21
  import type {AnimationConfig, EndCallback} from './animations/Animation';
22
22
  import type {InterpolationConfigType} from './nodes/AnimatedInterpolation';
23
+ import ReactNativeFeatureFlags from '../ReactNative/ReactNativeFeatureFlags';
23
24
  import invariant from 'invariant';
25
+ import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
26
+ import type {EventSubscription} from '../vendor/emitter/EventEmitter';
24
27
 
25
28
  // TODO T69437152 @petetheheat - Delete this fork when Fabric ships to 100%.
26
29
  const NativeAnimatedModule =
@@ -36,24 +39,83 @@ let nativeEventEmitter;
36
39
  let waitingForQueuedOperations = new Set();
37
40
  let queueOperations = false;
38
41
  let queue: Array<() => void> = [];
42
+ // $FlowFixMe
43
+ let singleOpQueue: Array<any> = [];
44
+
45
+ const useSingleOpBatching =
46
+ Platform.OS === 'android' &&
47
+ !!NativeAnimatedModule?.queueAndExecuteBatchedOperations &&
48
+ ReactNativeFeatureFlags.animatedShouldUseSingleOp();
49
+ let flushQueueTimeout = null;
50
+
51
+ const eventListenerGetValueCallbacks = {};
52
+ const eventListenerAnimationFinishedCallbacks = {};
53
+ let globalEventEmitterGetValueListener: ?EventSubscription = null;
54
+ let globalEventEmitterAnimationFinishedListener: ?EventSubscription = null;
55
+
56
+ const nativeOps: ?typeof NativeAnimatedModule = useSingleOpBatching
57
+ ? ((function () {
58
+ const apis = [
59
+ 'createAnimatedNode', // 1
60
+ 'updateAnimatedNodeConfig', // 2
61
+ 'getValue', // 3
62
+ 'startListeningToAnimatedNodeValue', // 4
63
+ 'stopListeningToAnimatedNodeValue', // 5
64
+ 'connectAnimatedNodes', // 6
65
+ 'disconnectAnimatedNodes', // 7
66
+ 'startAnimatingNode', // 8
67
+ 'stopAnimation', // 9
68
+ 'setAnimatedNodeValue', // 10
69
+ 'setAnimatedNodeOffset', // 11
70
+ 'flattenAnimatedNodeOffset', // 12
71
+ 'extractAnimatedNodeOffset', // 13
72
+ 'connectAnimatedNodeToView', // 14
73
+ 'disconnectAnimatedNodeFromView', // 15
74
+ 'restoreDefaultValues', // 16
75
+ 'dropAnimatedNode', // 17
76
+ 'addAnimatedEventToView', // 18
77
+ 'removeAnimatedEventFromView', // 19
78
+ 'addListener', // 20
79
+ 'removeListener', // 21
80
+ ];
81
+ return apis.reduce((acc, functionName, i) => {
82
+ // These indices need to be kept in sync with the indices in native (see NativeAnimatedModule in Java, or the equivalent for any other native platform).
83
+ // $FlowFixMe[prop-missing]
84
+ acc[functionName] = i + 1;
85
+ return acc;
86
+ }, {});
87
+ })(): $FlowFixMe)
88
+ : NativeAnimatedModule;
39
89
 
40
90
  /**
41
- * Simple wrappers around NativeAnimatedModule to provide flow and autocomplete support for
42
- * the native module methods
91
+ * Wrappers around NativeAnimatedModule to provide flow and autocomplete support for
92
+ * the native module methods, and automatic queue management on Android
43
93
  */
44
94
  const API = {
45
95
  getValue: function (
46
96
  tag: number,
47
97
  saveValueCallback: (value: number) => void,
48
98
  ): void {
49
- invariant(NativeAnimatedModule, 'Native animated module is not available');
50
- API.queueOperation(() => {
51
- NativeAnimatedModule.getValue(tag, saveValueCallback);
52
- });
99
+ invariant(nativeOps, 'Native animated module is not available');
100
+ if (useSingleOpBatching) {
101
+ if (saveValueCallback) {
102
+ eventListenerGetValueCallbacks[tag] = saveValueCallback;
103
+ }
104
+ // $FlowFixMe
105
+ API.queueOperation(nativeOps.getValue, tag);
106
+ } else {
107
+ API.queueOperation(nativeOps.getValue, tag, saveValueCallback);
108
+ }
53
109
  },
54
110
  setWaitingForIdentifier: function (id: string): void {
55
111
  waitingForQueuedOperations.add(id);
56
112
  queueOperations = true;
113
+ if (
114
+ ReactNativeFeatureFlags.animatedShouldDebounceQueueFlush() &&
115
+ flushQueueTimeout
116
+ ) {
117
+ clearTimeout(flushQueueTimeout);
118
+ }
57
119
  },
58
120
  unsetWaitingForIdentifier: function (id: string): void {
59
121
  waitingForQueuedOperations.delete(id);
@@ -64,70 +126,103 @@ const API = {
64
126
  }
65
127
  },
66
128
  disableQueue: function (): void {
129
+ invariant(nativeOps, 'Native animated module is not available');
130
+
131
+ if (ReactNativeFeatureFlags.animatedShouldDebounceQueueFlush()) {
132
+ const prevTimeout = flushQueueTimeout;
133
+ clearImmediate(prevTimeout);
134
+ flushQueueTimeout = setImmediate(API.flushQueue);
135
+ } else {
136
+ API.flushQueue();
137
+ }
138
+ },
139
+ flushQueue: function (): void {
67
140
  invariant(NativeAnimatedModule, 'Native animated module is not available');
141
+ flushQueueTimeout = null;
68
142
 
69
- if (Platform.OS === 'android') {
70
- NativeAnimatedModule.startOperationBatch();
143
+ // Early returns before calling any APIs
144
+ if (useSingleOpBatching && singleOpQueue.length === 0) {
145
+ return;
71
146
  }
72
- for (let q = 0, l = queue.length; q < l; q++) {
73
- queue[q]();
147
+ if (!useSingleOpBatching && queue.length === 0) {
148
+ return;
74
149
  }
75
- queue.length = 0;
76
- if (Platform.OS === 'android') {
77
- NativeAnimatedModule.finishOperationBatch();
150
+
151
+ if (useSingleOpBatching) {
152
+ // Set up event listener for callbacks if it's not set up
153
+ if (
154
+ !globalEventEmitterGetValueListener ||
155
+ !globalEventEmitterAnimationFinishedListener
156
+ ) {
157
+ setupGlobalEventEmitterListeners();
158
+ }
159
+ // Single op batching doesn't use callback functions, instead we
160
+ // use RCTDeviceEventEmitter. This reduces overhead of sending lots of
161
+ // JSI functions across to native code; but also, TM infrastructure currently
162
+ // does not support packing a function into native arrays.
163
+ NativeAnimatedModule.queueAndExecuteBatchedOperations?.(singleOpQueue);
164
+ singleOpQueue.length = 0;
165
+ } else {
166
+ Platform.OS === 'android' && NativeAnimatedModule.startOperationBatch?.();
167
+ for (let q = 0, l = queue.length; q < l; q++) {
168
+ queue[q]();
169
+ }
170
+ queue.length = 0;
171
+ Platform.OS === 'android' &&
172
+ NativeAnimatedModule.finishOperationBatch?.();
78
173
  }
79
174
  },
80
- queueOperation: (fn: () => void): void => {
81
- if (queueOperations) {
82
- queue.push(fn);
175
+ queueOperation: <Args: $ReadOnlyArray<mixed>, Fn: (...Args) => void>(
176
+ fn: Fn,
177
+ ...args: Args
178
+ ): void => {
179
+ if (useSingleOpBatching) {
180
+ // Get the command ID from the queued function, and push that ID and any arguments needed to execute the operation
181
+ // $FlowFixMe: surprise, fn is actually a number
182
+ singleOpQueue.push(fn, ...args);
183
+ return;
184
+ }
185
+
186
+ // If queueing is explicitly on, *or* the queue has not yet
187
+ // been flushed, use the queue. This is to prevent operations
188
+ // from being executed out of order.
189
+ if (queueOperations || queue.length !== 0) {
190
+ queue.push(() => fn(...args));
83
191
  } else {
84
- fn();
192
+ fn(...args);
85
193
  }
86
194
  },
87
195
  createAnimatedNode: function (tag: number, config: AnimatedNodeConfig): void {
88
- invariant(NativeAnimatedModule, 'Native animated module is not available');
89
- API.queueOperation(() =>
90
- NativeAnimatedModule.createAnimatedNode(tag, config),
91
- );
196
+ invariant(nativeOps, 'Native animated module is not available');
197
+ API.queueOperation(nativeOps.createAnimatedNode, tag, config);
92
198
  },
93
199
  updateAnimatedNodeConfig: function (
94
200
  tag: number,
95
201
  config: AnimatedNodeConfig,
96
202
  ): void {
97
- invariant(NativeAnimatedModule, 'Native animated module is not available');
98
- if (typeof NativeAnimatedModule.updateAnimatedNodeConfig === 'function') {
99
- API.queueOperation(() =>
100
- // $FlowIgnore[not-a-function] - checked above
101
- NativeAnimatedModule.updateAnimatedNodeConfig(tag, config),
102
- );
203
+ invariant(nativeOps, 'Native animated module is not available');
204
+ if (nativeOps.updateAnimatedNodeConfig) {
205
+ API.queueOperation(nativeOps.updateAnimatedNodeConfig, tag, config);
103
206
  }
104
207
  },
105
208
  startListeningToAnimatedNodeValue: function (tag: number) {
106
- invariant(NativeAnimatedModule, 'Native animated module is not available');
107
- API.queueOperation(() =>
108
- NativeAnimatedModule.startListeningToAnimatedNodeValue(tag),
109
- );
209
+ invariant(nativeOps, 'Native animated module is not available');
210
+ API.queueOperation(nativeOps.startListeningToAnimatedNodeValue, tag);
110
211
  },
111
212
  stopListeningToAnimatedNodeValue: function (tag: number) {
112
- invariant(NativeAnimatedModule, 'Native animated module is not available');
113
- API.queueOperation(() =>
114
- NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag),
115
- );
213
+ invariant(nativeOps, 'Native animated module is not available');
214
+ API.queueOperation(nativeOps.stopListeningToAnimatedNodeValue, tag);
116
215
  },
117
216
  connectAnimatedNodes: function (parentTag: number, childTag: number): void {
118
- invariant(NativeAnimatedModule, 'Native animated module is not available');
119
- API.queueOperation(() =>
120
- NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag),
121
- );
217
+ invariant(nativeOps, 'Native animated module is not available');
218
+ API.queueOperation(nativeOps.connectAnimatedNodes, parentTag, childTag);
122
219
  },
123
220
  disconnectAnimatedNodes: function (
124
221
  parentTag: number,
125
222
  childTag: number,
126
223
  ): void {
127
- invariant(NativeAnimatedModule, 'Native animated module is not available');
128
- API.queueOperation(() =>
129
- NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag),
130
- );
224
+ invariant(nativeOps, 'Native animated module is not available');
225
+ API.queueOperation(nativeOps.disconnectAnimatedNodes, parentTag, childTag);
131
226
  },
132
227
  startAnimatingNode: function (
133
228
  animationId: number,
@@ -135,84 +230,85 @@ const API = {
135
230
  config: AnimatingNodeConfig,
136
231
  endCallback: EndCallback,
137
232
  ): void {
138
- invariant(NativeAnimatedModule, 'Native animated module is not available');
139
- API.queueOperation(() =>
140
- NativeAnimatedModule.startAnimatingNode(
233
+ invariant(nativeOps, 'Native animated module is not available');
234
+ if (useSingleOpBatching) {
235
+ if (endCallback) {
236
+ eventListenerAnimationFinishedCallbacks[animationId] = endCallback;
237
+ }
238
+ // $FlowFixMe
239
+ API.queueOperation(
240
+ nativeOps.startAnimatingNode,
241
+ animationId,
242
+ nodeTag,
243
+ config,
244
+ );
245
+ } else {
246
+ API.queueOperation(
247
+ nativeOps.startAnimatingNode,
141
248
  animationId,
142
249
  nodeTag,
143
250
  config,
144
251
  endCallback,
145
- ),
146
- );
252
+ );
253
+ }
147
254
  },
148
255
  stopAnimation: function (animationId: number) {
149
- invariant(NativeAnimatedModule, 'Native animated module is not available');
150
- API.queueOperation(() => NativeAnimatedModule.stopAnimation(animationId));
256
+ invariant(nativeOps, 'Native animated module is not available');
257
+ API.queueOperation(nativeOps.stopAnimation, animationId);
151
258
  },
152
259
  setAnimatedNodeValue: function (nodeTag: number, value: number): void {
153
- invariant(NativeAnimatedModule, 'Native animated module is not available');
154
- API.queueOperation(() =>
155
- NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value),
156
- );
260
+ invariant(nativeOps, 'Native animated module is not available');
261
+ API.queueOperation(nativeOps.setAnimatedNodeValue, nodeTag, value);
157
262
  },
158
263
  setAnimatedNodeOffset: function (nodeTag: number, offset: number): void {
159
- invariant(NativeAnimatedModule, 'Native animated module is not available');
160
- API.queueOperation(() =>
161
- NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset),
162
- );
264
+ invariant(nativeOps, 'Native animated module is not available');
265
+ API.queueOperation(nativeOps.setAnimatedNodeOffset, nodeTag, offset);
163
266
  },
164
267
  flattenAnimatedNodeOffset: function (nodeTag: number): void {
165
- invariant(NativeAnimatedModule, 'Native animated module is not available');
166
- API.queueOperation(() =>
167
- NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag),
168
- );
268
+ invariant(nativeOps, 'Native animated module is not available');
269
+ API.queueOperation(nativeOps.flattenAnimatedNodeOffset, nodeTag);
169
270
  },
170
271
  extractAnimatedNodeOffset: function (nodeTag: number): void {
171
- invariant(NativeAnimatedModule, 'Native animated module is not available');
172
- API.queueOperation(() =>
173
- NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag),
174
- );
272
+ invariant(nativeOps, 'Native animated module is not available');
273
+ API.queueOperation(nativeOps.extractAnimatedNodeOffset, nodeTag);
175
274
  },
176
275
  connectAnimatedNodeToView: function (nodeTag: number, viewTag: number): void {
177
- invariant(NativeAnimatedModule, 'Native animated module is not available');
178
- API.queueOperation(() =>
179
- NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag),
180
- );
276
+ invariant(nativeOps, 'Native animated module is not available');
277
+ API.queueOperation(nativeOps.connectAnimatedNodeToView, nodeTag, viewTag);
181
278
  },
182
279
  disconnectAnimatedNodeFromView: function (
183
280
  nodeTag: number,
184
281
  viewTag: number,
185
282
  ): void {
186
- invariant(NativeAnimatedModule, 'Native animated module is not available');
187
- API.queueOperation(() =>
188
- NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag),
283
+ invariant(nativeOps, 'Native animated module is not available');
284
+ API.queueOperation(
285
+ nativeOps.disconnectAnimatedNodeFromView,
286
+ nodeTag,
287
+ viewTag,
189
288
  );
190
289
  },
191
290
  restoreDefaultValues: function (nodeTag: number): void {
192
- invariant(NativeAnimatedModule, 'Native animated module is not available');
291
+ invariant(nativeOps, 'Native animated module is not available');
193
292
  // Backwards compat with older native runtimes, can be removed later.
194
- if (NativeAnimatedModule.restoreDefaultValues != null) {
195
- API.queueOperation(() =>
196
- NativeAnimatedModule.restoreDefaultValues(nodeTag),
197
- );
293
+ if (nativeOps.restoreDefaultValues != null) {
294
+ API.queueOperation(nativeOps.restoreDefaultValues, nodeTag);
198
295
  }
199
296
  },
200
297
  dropAnimatedNode: function (tag: number): void {
201
- invariant(NativeAnimatedModule, 'Native animated module is not available');
202
- API.queueOperation(() => NativeAnimatedModule.dropAnimatedNode(tag));
298
+ invariant(nativeOps, 'Native animated module is not available');
299
+ API.queueOperation(nativeOps.dropAnimatedNode, tag);
203
300
  },
204
301
  addAnimatedEventToView: function (
205
302
  viewTag: number,
206
303
  eventName: string,
207
304
  eventMapping: EventMapping,
208
305
  ) {
209
- invariant(NativeAnimatedModule, 'Native animated module is not available');
210
- API.queueOperation(() =>
211
- NativeAnimatedModule.addAnimatedEventToView(
212
- viewTag,
213
- eventName,
214
- eventMapping,
215
- ),
306
+ invariant(nativeOps, 'Native animated module is not available');
307
+ API.queueOperation(
308
+ nativeOps.addAnimatedEventToView,
309
+ viewTag,
310
+ eventName,
311
+ eventMapping,
216
312
  );
217
313
  },
218
314
  removeAnimatedEventFromView(
@@ -220,17 +316,44 @@ const API = {
220
316
  eventName: string,
221
317
  animatedNodeTag: number,
222
318
  ) {
223
- invariant(NativeAnimatedModule, 'Native animated module is not available');
224
- API.queueOperation(() =>
225
- NativeAnimatedModule.removeAnimatedEventFromView(
226
- viewTag,
227
- eventName,
228
- animatedNodeTag,
229
- ),
319
+ invariant(nativeOps, 'Native animated module is not available');
320
+ API.queueOperation(
321
+ nativeOps.removeAnimatedEventFromView,
322
+ viewTag,
323
+ eventName,
324
+ animatedNodeTag,
230
325
  );
231
326
  },
232
327
  };
233
328
 
329
+ function setupGlobalEventEmitterListeners() {
330
+ globalEventEmitterGetValueListener = RCTDeviceEventEmitter.addListener(
331
+ 'onNativeAnimatedModuleGetValue',
332
+ function (params) {
333
+ const {tag} = params;
334
+ const callback = eventListenerGetValueCallbacks[tag];
335
+ if (!callback) {
336
+ return;
337
+ }
338
+ callback(params.value);
339
+ delete eventListenerGetValueCallbacks[tag];
340
+ },
341
+ );
342
+ globalEventEmitterAnimationFinishedListener =
343
+ RCTDeviceEventEmitter.addListener(
344
+ 'onNativeAnimatedModuleAnimationFinished',
345
+ function (params) {
346
+ const {animationId} = params;
347
+ const callback = eventListenerAnimationFinishedCallbacks[animationId];
348
+ if (!callback) {
349
+ return;
350
+ }
351
+ callback(params);
352
+ delete eventListenerAnimationFinishedCallbacks[animationId];
353
+ },
354
+ );
355
+ }
356
+
234
357
  /**
235
358
  * Styles allowed by the native animated implementation.
236
359
  *
@@ -359,7 +482,9 @@ function validateStyles(styles: {[key: string]: ?number, ...}): void {
359
482
  }
360
483
  }
361
484
 
362
- function validateInterpolation(config: InterpolationConfigType): void {
485
+ function validateInterpolation<OutputT: number | string>(
486
+ config: InterpolationConfigType<OutputT>,
487
+ ): void {
363
488
  for (const key in config) {
364
489
  if (!isSupportedInterpolationParam(key)) {
365
490
  throw new Error(
@@ -64,6 +64,9 @@ export interface Spec extends TurboModule {
64
64
  // Events
65
65
  +addListener: (eventName: string) => void;
66
66
  +removeListeners: (count: number) => void;
67
+
68
+ // All of the above in a batched mode
69
+ +queueAndExecuteBatchedOperations?: (operationsAndArgs: Array<any>) => void;
67
70
  }
68
71
 
69
72
  export default (TurboModuleRegistry.get<Spec>('NativeAnimatedModule'): ?Spec);
@@ -64,6 +64,9 @@ export interface Spec extends TurboModule {
64
64
  // Events
65
65
  +addListener: (eventName: string) => void;
66
66
  +removeListeners: (count: number) => void;
67
+
68
+ // All of the above in a batched mode
69
+ +queueAndExecuteBatchedOperations?: (operationsAndArgs: Array<any>) => void;
67
70
  }
68
71
 
69
72
  export default (TurboModuleRegistry.get<Spec>(
@@ -44,7 +44,7 @@ export type SpringAnimationConfig = {
44
44
  ...
45
45
  }
46
46
  | AnimatedColor
47
- | AnimatedInterpolation,
47
+ | AnimatedInterpolation<number>,
48
48
  overshootClamping?: boolean,
49
49
  restDisplacementThreshold?: number,
50
50
  restSpeedThreshold?: number,
@@ -67,7 +67,7 @@ export type SpringAnimationConfig = {
67
67
 
68
68
  export type SpringAnimationConfigSingle = {
69
69
  ...AnimationConfig,
70
- toValue: number | AnimatedValue | AnimatedInterpolation,
70
+ toValue: number,
71
71
  overshootClamping?: boolean,
72
72
  restDisplacementThreshold?: number,
73
73
  restSpeedThreshold?: number,
@@ -90,7 +90,7 @@ class SpringAnimation extends Animation {
90
90
  _startPosition: number;
91
91
  _lastPosition: number;
92
92
  _fromValue: number;
93
- _toValue: any;
93
+ _toValue: number;
94
94
  _stiffness: number;
95
95
  _damping: number;
96
96
  _mass: number;
@@ -36,7 +36,7 @@ export type TimingAnimationConfig = $ReadOnly<{
36
36
  | AnimatedValueXY
37
37
  | RgbaValue
38
38
  | AnimatedColor
39
- | AnimatedInterpolation,
39
+ | AnimatedInterpolation<number>,
40
40
  easing?: (value: number) => number,
41
41
  duration?: number,
42
42
  delay?: number,
@@ -44,7 +44,7 @@ export type TimingAnimationConfig = $ReadOnly<{
44
44
 
45
45
  export type TimingAnimationConfigSingle = $ReadOnly<{
46
46
  ...AnimationConfig,
47
- toValue: number | AnimatedValue | AnimatedInterpolation,
47
+ toValue: number,
48
48
  easing?: (value: number) => number,
49
49
  duration?: number,
50
50
  delay?: number,
@@ -62,7 +62,7 @@ function easeInOut() {
62
62
  class TimingAnimation extends Animation {
63
63
  _startTime: number;
64
64
  _fromValue: number;
65
- _toValue: any;
65
+ _toValue: number;
66
66
  _duration: number;
67
67
  _delay: number;
68
68
  _easing: (value: number) => number;