Merge commit 'e1fa53af2eabc483be2f196ca96bbcd4a8226809' into amgleitman/0.64-merge-head

This commit is contained in:
Adam Gleitman 2021-09-01 18:12:47 -07:00
Родитель b756416539 e1fa53af2e
Коммит 7acf9edcf5
20 изменённых файлов: 582 добавлений и 271 удалений

Просмотреть файл

@ -35,8 +35,10 @@ let __nativeAnimationIdCount = 1; /* used for started animations */
let nativeEventEmitter;
let waitingForQueuedOperations = new Set();
let queueOperations = false;
let queueConnections = false;
let queue = [];
let queue: Array<() => void> = [];
/**
* Simple wrappers around NativeAnimatedModule to provide flow and autocomplete support for
@ -55,38 +57,74 @@ const API = {
NativeAnimatedModule.getValue(tag, saveValueCallback);
}
},
setWaitingForIdentifier: function(id: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
waitingForQueuedOperations.add(id);
queueOperations = true;
queueConnections = true;
},
unsetWaitingForIdentifier: function(id: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
waitingForQueuedOperations.delete(id);
if (waitingForQueuedOperations.size === 0) {
queueOperations = false;
API.disableQueue();
}
},
disableQueue: function(): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
queueConnections = false;
for (let q = 0, l = queue.length; q < l; q++) {
const args = queue[q];
NativeAnimatedModule.connectAnimatedNodes(args[0], args[1]);
if (!queueOperations) {
for (let q = 0, l = queue.length; q < l; q++) {
queue[q]();
}
queue.length = 0;
}
},
queueConnection: (fn: () => void): void => {
if (queueConnections) {
queue.push(fn);
} else {
fn();
}
},
queueOperation: (fn: () => void): void => {
if (queueOperations) {
queue.push(fn);
} else {
fn();
}
queue.length = 0;
},
createAnimatedNode: function(tag: number, config: AnimatedNodeConfig): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.createAnimatedNode(tag, config);
API.queueOperation(() =>
NativeAnimatedModule.createAnimatedNode(tag, config),
);
},
startListeningToAnimatedNodeValue: function(tag: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.startListeningToAnimatedNodeValue(tag);
API.queueOperation(() =>
NativeAnimatedModule.startListeningToAnimatedNodeValue(tag),
);
},
stopListeningToAnimatedNodeValue: function(tag: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag);
API.queueOperation(() =>
NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag),
);
},
connectAnimatedNodes: function(parentTag: number, childTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
if (queueConnections) {
queue.push([parentTag, childTag]);
return;
}
NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag);
API.queueConnection(() =>
NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag),
);
},
disconnectAnimatedNodes: function(parentTag: number, childTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag);
API.queueOperation(() =>
NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag),
);
},
startAnimatingNode: function(
animationId: number,
@ -95,54 +133,70 @@ const API = {
endCallback: EndCallback,
): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.startAnimatingNode(
animationId,
nodeTag,
config,
endCallback,
API.queueOperation(() =>
NativeAnimatedModule.startAnimatingNode(
animationId,
nodeTag,
config,
endCallback,
),
);
},
stopAnimation: function(animationId: number) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.stopAnimation(animationId);
API.queueOperation(() => NativeAnimatedModule.stopAnimation(animationId));
},
setAnimatedNodeValue: function(nodeTag: number, value: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value);
API.queueOperation(() =>
NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value),
);
},
setAnimatedNodeOffset: function(nodeTag: number, offset: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset);
API.queueOperation(() =>
NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset),
);
},
flattenAnimatedNodeOffset: function(nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag);
API.queueOperation(() =>
NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag),
);
},
extractAnimatedNodeOffset: function(nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag);
API.queueOperation(() =>
NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag),
);
},
connectAnimatedNodeToView: function(nodeTag: number, viewTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag);
API.queueOperation(() =>
NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag),
);
},
disconnectAnimatedNodeFromView: function(
nodeTag: number,
viewTag: number,
): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag);
API.queueOperation(() =>
NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag),
);
},
restoreDefaultValues: function(nodeTag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
// Backwards compat with older native runtimes, can be removed later.
if (NativeAnimatedModule.restoreDefaultValues != null) {
NativeAnimatedModule.restoreDefaultValues(nodeTag);
API.queueOperation(() =>
NativeAnimatedModule.restoreDefaultValues(nodeTag),
);
}
},
dropAnimatedNode: function(tag: number): void {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.dropAnimatedNode(tag);
API.queueOperation(() => NativeAnimatedModule.dropAnimatedNode(tag));
},
addAnimatedEventToView: function(
viewTag: number,
@ -150,10 +204,12 @@ const API = {
eventMapping: EventMapping,
) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.addAnimatedEventToView(
viewTag,
eventName,
eventMapping,
API.queueOperation(() =>
NativeAnimatedModule.addAnimatedEventToView(
viewTag,
eventName,
eventMapping,
),
);
},
removeAnimatedEventFromView(
@ -162,10 +218,12 @@ const API = {
animatedNodeTag: number,
) {
invariant(NativeAnimatedModule, 'Native animated module is not available');
NativeAnimatedModule.removeAnimatedEventFromView(
viewTag,
eventName,
animatedNodeTag,
API.queueOperation(() =>
NativeAnimatedModule.removeAnimatedEventFromView(
viewTag,
eventName,
animatedNodeTag,
),
);
},
};

Просмотреть файл

@ -11,13 +11,17 @@
'use strict';
const View = require('../../Components/View/View');
const Platform = require('../../Utilities/Platform');
const {AnimatedEvent} = require('./AnimatedEvent');
const AnimatedProps = require('./nodes/AnimatedProps');
const React = require('react');
const NativeAnimatedHelper = require('./NativeAnimatedHelper');
const invariant = require('invariant');
const setAndForwardRef = require('../../Utilities/setAndForwardRef');
let animatedComponentNextId = 1;
export type AnimatedComponentType<
Props: {+[string]: mixed, ...},
Instance,
@ -51,6 +55,9 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
_propsAnimated: AnimatedProps;
_eventDetachers: Array<Function> = [];
// Only to be used in this file, and only in Fabric.
_animatedComponentId: number = -1;
_attachNativeEvents() {
// Make sure to get the scrollable node for components that implement
// `ScrollResponder.Mixin`.
@ -72,25 +79,11 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
this._eventDetachers = [];
}
// The system is best designed when setNativeProps is implemented. It is
// able to avoid re-rendering and directly set the attributes that changed.
// However, setNativeProps can only be implemented on leaf native
// components. If you want to animate a composite component, you need to
// re-render it. In this case, we have a fallback that uses forceUpdate.
// This fallback is also called in Fabric.
_animatedPropsCallback = () => {
_isFabric = (): boolean => {
if (this._component == null) {
// AnimatedProps is created in will-mount because it's used in render.
// But this callback may be invoked before mount in async mode,
// In which case we should defer the setNativeProps() call.
// React may throw away uncommitted work in async mode,
// So a deferred call won't always be invoked.
this._invokeAnimatedPropsCallbackOnMount = true;
} else if (
process.env.NODE_ENV === 'test' ||
// For animating properties of non-leaf/non-native components
typeof this._component.setNativeProps !== 'function' ||
// In Fabric, force animations to go through forceUpdate and skip setNativeProps
return false;
}
return (
// eslint-disable-next-line dot-notation
this._component['_internalInstanceHandle']?.stateNode?.canonical !=
null ||
@ -114,6 +107,54 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
// eslint-disable-next-line dot-notation
'_internalInstanceHandle'
]?.stateNode?.canonical != null)
);
};
_waitForUpdate = (): void => {
// If this works well on iOS, we should remove this check
if (Platform.OS === 'android') {
if (this._isFabric()) {
if (this._animatedComponentId === -1) {
this._animatedComponentId = animatedComponentNextId++;
}
NativeAnimatedHelper.API.setWaitingForIdentifier(
this._animatedComponentId,
);
}
}
};
_markUpdateComplete = (): void => {
// If this works well on iOS, we should remove this check
if (Platform.OS === 'android') {
if (this._isFabric()) {
NativeAnimatedHelper.API.unsetWaitingForIdentifier(
this._animatedComponentId,
);
}
}
};
// The system is best designed when setNativeProps is implemented. It is
// able to avoid re-rendering and directly set the attributes that changed.
// However, setNativeProps can only be implemented on leaf native
// components. If you want to animate a composite component, you need to
// re-render it. In this case, we have a fallback that uses forceUpdate.
// This fallback is also called in Fabric.
_animatedPropsCallback = () => {
if (this._component == null) {
// AnimatedProps is created in will-mount because it's used in render.
// But this callback may be invoked before mount in async mode,
// In which case we should defer the setNativeProps() call.
// React may throw away uncommitted work in async mode,
// So a deferred call won't always be invoked.
this._invokeAnimatedPropsCallbackOnMount = true;
} else if (
process.env.NODE_ENV === 'test' ||
// For animating properties of non-leaf/non-native components
typeof this._component.setNativeProps !== 'function' ||
// In Fabric, force animations to go through forceUpdate and skip setNativeProps
this._isFabric()
) {
this.forceUpdate();
} else if (!this._propsAnimated.__isNative) {
@ -199,6 +240,7 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
}
UNSAFE_componentWillMount() {
this._waitForUpdate();
this._attachProps(this.props);
}
@ -210,9 +252,11 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
this._propsAnimated.setNativeView(this._component);
this._attachNativeEvents();
this._markUpdateComplete();
}
UNSAFE_componentWillReceiveProps(newProps) {
this._waitForUpdate();
this._attachProps(newProps);
}
@ -224,11 +268,13 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
this._detachNativeEvents();
this._attachNativeEvents();
}
this._markUpdateComplete();
}
componentWillUnmount() {
this._propsAnimated && this._propsAnimated.__detach();
this._detachNativeEvents();
this._markUpdateComplete();
}
}

Просмотреть файл

@ -510,8 +510,8 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: 2b45d0f8e156a5b02354c8a4062de64d41ccb4e0
FBLazyVector: 4b23de6e6b7e7d5d026b09c25d36d97b67bb40de
FBReactNativeSpec: 2d2a213b4c164af442698ea6af7bcb080ea5ee02
FBLazyVector: 732869c0b909e8bf216314da06e817522d65cc1b
FBReactNativeSpec: f179c5379aa50218c6d52b5327b3225bc8e86f08
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
@ -522,33 +522,33 @@ SPEC CHECKSUMS:
glog: 789873d01e4b200777d0a09bc23d548446758699
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
RCT-Folly: 55d0039b24e192081ec0b2257f7bd9f42e382fb7
RCTRequired: de797b1acb93dcd075319a38597b11cce2a4cd5c
RCTTypeSafety: de700bd81b3504c1aa247caa96f1b01750ec4f52
React: d557fabc871c1588c2031ff3ffc96490aaef7b71
React-callinvoker: a783f0ebf49dac341c433c97fb7bca87078aaa25
React-Core: bfb26c530d4596a5b6273c74a7067442b1415c27
React-CoreModules: afbf75c2fae3b05d9c6009d380deee06f156e5e8
React-cxxreact: 288c6b6b9348d3a4082a2ab1da9d1d15f0c12ece
React-jsi: 75157aabfeaf837ddf7a07bc740d2e2c85301ebb
React-jsiexecutor: 9e2055f1447d920ad59d3b7fee510fa8b472c298
React-jsinspector: acd6b8cf323b3c93dcb550d8040361cb00117101
React-perflogger: 18ee540a8500d2000fa88990df5d8eaa74cd9475
React-RCTActionSheet: be55a83ef4643278266c646d7d814367ec7f9563
React-RCTAnimation: 29742b09e5867180a5a1fa6e1e71633c7483ea85
React-RCTBlob: 483018994f6e2b6d015ba89f86435fbcea3d4210
React-RCTImage: d49d1af581a65f205f73eaa56b106e3f11c70435
React-RCTLinking: d4318ff788dd65c2149ce5ac919f4a27913b760d
React-RCTNetwork: 5525944a8d7e70263d6895fac8490c0d731dd1c4
React-RCTPushNotification: dc897506a895c979644b2127bb1bcab03ce88a59
React-RCTSettings: fb77ce3170f9b83d6f4b76e33eef729e712fd28d
React-RCTTest: 4a6f82fec5b33fd14d0ccb3dc91c0a9d585f1736
React-RCTText: e0b62bb2c46a2250a663da6a9cbfd4bbef790e61
React-RCTVibration: 04622c45021de9eb94873ca0a2d28b1b08d85c70
React-runtimeexecutor: 4b592cc4b6d41a06a25ebffad55a0a5b4a752c73
RCTRequired: e57c96e9043b32eb039c3be36b0323c9c0cc78b3
RCTTypeSafety: d89d63062f5f3880bc142a8115a9d7488f96f6e6
React: ffa956ca111517bdbac4adbda38f392ff1b24655
React-callinvoker: f8688c196a51ed024f2f2e5ed964f48fb0ccc104
React-Core: 23f3d8f877a3d838ba407ff8c4122d5ae5f2675b
React-CoreModules: c584baf382fa2fdd751c272fd8169b478ee9d16a
React-cxxreact: 8182b61c40331f2bab4861a01a148b75ce6d6a25
React-jsi: b40a0b755266eef1ccd36be376598e6b8deeeb65
React-jsiexecutor: 9082a6492e0786ee05b7c896b8d013dd14d6a7f5
React-jsinspector: ace5eb00f739058c1639de2cfa34d4723090c1d6
React-perflogger: ecc9e8fa74a3fed810ca23be9677dc488a7aa293
React-RCTActionSheet: f39b0fb0af5750509f1aa86b2ed56955ab9071d7
React-RCTAnimation: 83c410e9886788e0bad11c15552274bacce10296
React-RCTBlob: d0391ea7685afe50564c3221445c8b1c911fc1dc
React-RCTImage: 5490eb14709285403f30bb55aa53bb64e1d4183b
React-RCTLinking: 55ec860467d76a01f28284aaaf7bfd406524da93
React-RCTNetwork: f18683923b0396a68f028cf5a9810777cac4010c
React-RCTPushNotification: 33a883d3e6f10a1842b6b3f7fb592854a6f69676
React-RCTSettings: 7f8ec2893fa4129a7c7dc3db7fac421fb0a96c5a
React-RCTTest: 18046d93f0b48a7eacf50afb54ff7c7ac75e85e8
React-RCTText: 1f3470878a4ce51821a83640d6b4e310c8f7e1fc
React-RCTVibration: 0b7cef95d0b04c778c6751ff638c47e190cee7c5
React-runtimeexecutor: 14a8a45de8e02b8895afae7f38cc5aaf5ea90b5a
React-TurboModuleCxx-RNW: 18bb71af41fe34c8b12a56bef60aae7ee32b0817
React-TurboModuleCxx-WinRTPort: 7c3bbced514dbd1d0a43e226606987e2bce7ada6
ReactCommon: df708ad127837db8167616488e556ff3c90b365e
Yoga: f5c8b1a2347133d81ac2d765c26c62300f7581f0
React-TurboModuleCxx-WinRTPort: c4538e76df5bdf83edd892a8919c7202ac790ed1
ReactCommon: 6d574adf7fdd5d0e7e2e892b95c75ea167d3a725
Yoga: af7ff9d5087d827aa8dd130c1e2b1c3062494887
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: d3ddf54cbfd92c34f45d8fb0c9166fe4730df5c0

Просмотреть файл

@ -88,16 +88,6 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
private abstract class UIThreadOperation {
abstract void execute(NativeAnimatedNodesManager animatedNodesManager);
long mFrameNumber = -1;
public void setFrameNumber(long frameNumber) {
mFrameNumber = frameNumber;
}
public long getFrameNumber() {
return mFrameNumber;
}
}
@NonNull private final GuardedFrameCallback mAnimatedFrameCallback;
@ -113,8 +103,6 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
private @Nullable NativeAnimatedNodesManager mNodesManager;
private volatile long mFrameNumber = 0;
private long mDispatchedFrameNumber = 0;
private boolean mInitializedForFabric = false;
private boolean mInitializedForNonFabric = false;
private @UIManagerType int mUIManagerType = UIManagerType.DEFAULT;
@ -169,25 +157,13 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
}
private void addOperation(UIThreadOperation operation) {
operation.setFrameNumber(mFrameNumber);
mOperations.add(operation);
}
private void addPreOperation(UIThreadOperation operation) {
operation.setFrameNumber(mFrameNumber);
mPreOperations.add(operation);
}
// For FabricUIManager only
@Override
public void didScheduleMountItems(UIManager uiManager) {
if (mUIManagerType != UIManagerType.FABRIC) {
return;
}
mFrameNumber++;
}
// For FabricUIManager only
@Override
@UiThread
@ -196,22 +172,6 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
return;
}
// The problem we're trying to solve here: we could be in the middle of queueing
// a batch of related animation operations when Fabric flushes a batch of MountItems.
// It's visually bad if we execute half of the animation ops and then wait another frame
// (or more) to execute the rest.
// See mFrameNumber. If the dispatchedFrameNumber drifts too far - that
// is, if no MountItems are scheduled for a while, which can happen if a tree
// is committed but there are no changes - bring these counts back in sync and
// execute any queued operations. This number is arbitrary, but we want it low
// enough that the user shouldn't be able to see this delay in most cases.
mDispatchedFrameNumber++;
long currentFrameNo = mFrameNumber - 1;
if ((mDispatchedFrameNumber - mFrameNumber) > 2) {
mFrameNumber = mDispatchedFrameNumber;
currentFrameNo = mFrameNumber;
}
// This will execute all operations and preOperations queued
// since the last time this was run, and will race with anything
// being queued from the JS thread. That is, if the JS thread
@ -222,35 +182,13 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
// is that `scheduleMountItems` happens as close to the JS commit as
// possible, whereas execution of those same items might happen sometime
// later on the UI thread while the JS thread keeps plugging along.
executeAllOperations(mPreOperations, currentFrameNo);
executeAllOperations(mOperations, currentFrameNo);
executeAllOperations(mPreOperations);
executeAllOperations(mOperations);
}
private void executeAllOperations(Queue<UIThreadOperation> operationQueue, long maxFrameNumber) {
private void executeAllOperations(Queue<UIThreadOperation> operationQueue) {
NativeAnimatedNodesManager nodesManager = getNodesManager();
while (true) {
// There is a race condition where `peek` may return a non-null value and isEmpty() is false,
// but `poll` returns a null value - it's not clear why since we only peek and poll on the UI
// thread, but it might be something that happens during teardown or a crash. Regardless, the
// root cause is not currently known so we're extra cautious here.
// It happens equally in Fabric and non-Fabric.
UIThreadOperation peekedOperation = operationQueue.peek();
// This is the same as operationQueue.isEmpty()
if (peekedOperation == null) {
return;
}
// The rest of the operations are for the next frame.
if (peekedOperation.getFrameNumber() > maxFrameNumber) {
return;
}
// Since we apparently can't guarantee that there is still an operation on the queue,
// much less the same operation, we do a poll and another null check. If this isn't
// the same operation as the peeked operation, we can't do anything about it - we still
// need to execute it, we have no mechanism to put it at the front of the queue, and it
// won't cause any errors to execute it earlier than expected (just a bit of UI jank at worst)
// so we just continue happily along.
UIThreadOperation polledOperation = operationQueue.poll();
if (polledOperation == null) {
return;
@ -270,13 +208,11 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
return;
}
final long frameNo = mFrameNumber++;
UIBlock preOperationsUIBlock =
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
executeAllOperations(mPreOperations, frameNo);
executeAllOperations(mPreOperations);
}
};
@ -284,7 +220,7 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
executeAllOperations(mOperations, frameNo);
executeAllOperations(mOperations);
}
};
@ -734,10 +670,7 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
if (ANIMATED_MODULE_DEBUG) {
FLog.d(
NAME,
"queue connectAnimatedNodeToView: disconnectAnimatedNodeFromView: "
+ animatedNodeTag
+ " viewTag: "
+ viewTag);
"queue: disconnectAnimatedNodeFromView: " + animatedNodeTag + " viewTag: " + viewTag);
}
decrementInFlightAnimationsForViewTag(viewTag);
@ -749,7 +682,7 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
if (ANIMATED_MODULE_DEBUG) {
FLog.d(
NAME,
"execute connectAnimatedNodeToView: disconnectAnimatedNodeFromView: "
"execute: disconnectAnimatedNodeFromView: "
+ animatedNodeTag
+ " viewTag: "
+ viewTag);
@ -826,7 +759,7 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
if (ANIMATED_MODULE_DEBUG) {
FLog.d(
NAME,
"queue addAnimatedEventToView: removeAnimatedEventFromView: "
"queue removeAnimatedEventFromView: viewTag: "
+ viewTag
+ " eventName: "
+ eventName
@ -843,7 +776,7 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
if (ANIMATED_MODULE_DEBUG) {
FLog.d(
NAME,
"execute addAnimatedEventToView: removeAnimatedEventFromView: "
"execute removeAnimatedEventFromView: viewTag: "
+ viewTag
+ " eventName: "
+ eventName

Просмотреть файл

@ -0,0 +1,46 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.bridge;
import com.facebook.proguard.annotations.DoNotStrip;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@DoNotStrip
public class BackgroundExecutor {
private static final String TAG = "FabricBackgroundExecutor";
private final ExecutorService mExecutorService;
@DoNotStrip
private BackgroundExecutor() {
mExecutorService = Executors.newFixedThreadPool(1);
}
@DoNotStrip
private void queueRunnable(Runnable runnable) {
// Very rarely, an NPE is hit here - probably has to do with deallocation
// race conditions and the JNI.
// It's not clear yet which of these is most prevalent, or if either is a concern.
// If we don't find these logs in production then we can probably safely remove the logging,
// but it's also cheap to leave it here.
if (runnable == null) {
ReactSoftException.logSoftException(TAG, new ReactNoCrashSoftException("runnable is null"));
return;
}
final ExecutorService executorService = mExecutorService;
if (executorService == null) {
ReactSoftException.logSoftException(
TAG, new ReactNoCrashSoftException("executorService is null"));
return;
}
executorService.execute(runnable);
}
}

Просмотреть файл

@ -16,6 +16,4 @@ public interface UIManagerListener {
void willDispatchViewUpdates(UIManager uiManager);
/* Called right after view updates are dispatched for a frame. */
void didDispatchMountItems(UIManager uiManager);
/* Called right after scheduleMountItems is called in Fabric, after a new tree is committed. */
void didScheduleMountItems(UIManager uiManager);
}

Просмотреть файл

@ -587,12 +587,6 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
boolean isBatchMountItem = mountItem instanceof BatchMountItem;
boolean shouldSchedule = !(isBatchMountItem && ((BatchMountItem) mountItem).getSize() == 0);
// In case of sync rendering, this could be called on the UI thread. Otherwise,
// it should ~always be called on the JS thread.
for (UIManagerListener listener : mListeners) {
listener.didScheduleMountItems(this);
}
if (isBatchMountItem) {
mCommitStartTime = commitStartTime;
mLayoutTime = layoutEndTime - layoutStartTime;

Просмотреть файл

@ -278,6 +278,12 @@ void Binding::installFabricUIManager(
toolbox.synchronousEventBeatFactory = synchronousBeatFactory;
toolbox.asynchronousEventBeatFactory = asynchronousBeatFactory;
if (reactNativeConfig_->getBool(
"react_fabric:enable_background_executor_android")) {
backgroundExecutor_ = std::make_unique<JBackgroundExecutor>();
toolbox.backgroundExecutor = backgroundExecutor_->get();
}
if (enableLayoutAnimations) {
animationDriver_ = std::make_shared<LayoutAnimationDriver>(this);
}

Просмотреть файл

@ -19,6 +19,7 @@
#include <mutex>
#include "ComponentFactoryDelegate.h"
#include "EventBeatManager.h"
#include "JBackgroundExecutor.h"
namespace facebook {
namespace react {
@ -115,6 +116,7 @@ class Binding : public jni::HybridClass<Binding>,
virtual void onAllAnimationsComplete() override;
LayoutAnimationDriver *getAnimationDriver();
std::shared_ptr<LayoutAnimationDriver> animationDriver_;
std::unique_ptr<JBackgroundExecutor> backgroundExecutor_;
std::shared_ptr<Scheduler> scheduler_;
std::mutex schedulerMutex_;

Просмотреть файл

@ -0,0 +1,35 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <fbjni/fbjni.h>
#include <react/jni/JNativeRunnable.h>
#include "JBackgroundExecutor.h"
namespace facebook {
namespace react {
using namespace facebook::jni;
using facebook::react::JNativeRunnable;
using facebook::react::Runnable;
BackgroundExecutor JBackgroundExecutor::get() {
auto self = JBackgroundExecutor::create();
return [self](std::function<void()> &&runnable) {
static auto method =
findClassStatic(JBackgroundExecutor::JBackgroundExecutorJavaDescriptor)
->getMethod<void(Runnable::javaobject)>("queueRunnable");
auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(runnable));
method(self, static_ref_cast<Runnable>(jrunnable).get());
};
}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -0,0 +1,34 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fbjni/fbjni.h>
#include <react/uimanager/primitives.h>
namespace facebook {
namespace react {
using namespace facebook::jni;
class JBackgroundExecutor : public JavaClass<JBackgroundExecutor> {
public:
static auto constexpr kJavaDescriptor =
"Lcom/facebook/react/bridge/BackgroundExecutor;";
constexpr static auto JBackgroundExecutorJavaDescriptor =
"com/facebook/react/bridge/BackgroundExecutor";
static global_ref<javaobject> create() {
return make_global(newInstance());
}
BackgroundExecutor get();
};
} // namespace react
} // namespace facebook

Просмотреть файл

@ -351,6 +351,9 @@ folly::Future<debugger::BreakpointInfo> Inspector::setBreakpoint(
debugger::SourceLocation loc,
folly::Optional<std::string> condition) {
auto promise = std::make_shared<folly::Promise<debugger::BreakpointInfo>>();
// Automatically re-enable breakpoints since the user presumably wants this
// to start triggering.
breakpointsActive_ = true;
executor_->add([this, loc, condition, promise] {
setBreakpointOnExecutor(loc, condition, promise);
@ -453,6 +456,14 @@ folly::Future<folly::Unit> Inspector::setPauseOnLoads(
return promise->getFuture();
};
folly::Future<folly::Unit> Inspector::setBreakpointsActive(bool active) {
// Same logic as setPauseOnLoads.
auto promise = std::make_shared<folly::Promise<Unit>>();
breakpointsActive_ = active;
promise->setValue();
return promise->getFuture();
};
bool Inspector::shouldPauseOnThisScriptLoad() {
switch (pauseOnLoadMode_) {
case None:

Просмотреть файл

@ -208,6 +208,12 @@ class Inspector : public facebook::hermes::debugger::EventObserver,
*/
folly::Future<folly::Unit> setPauseOnLoads(const PauseOnLoadMode mode);
/**
* Set whether breakpoints are active (pause when hit). This does not require
* runtime modifications, but returns a future for consistency.
*/
folly::Future<folly::Unit> setBreakpointsActive(bool active);
/**
* If called during a script load event, return true if we should pause.
* Assumed to be called from a script load event where we already hold
@ -326,6 +332,9 @@ class Inspector : public facebook::hermes::debugger::EventObserver,
// Whether we should enter a paused state when a script loads.
PauseOnLoadMode pauseOnLoadMode_ = PauseOnLoadMode::None;
// Whether or not we should pause on breakpoints.
bool breakpointsActive_ = true;
// All scripts loaded in to the VM, along with whether we've notified the
// client about the script yet.
struct LoadedScriptInfo {

Просмотреть файл

@ -254,6 +254,12 @@ std::pair<NextStatePtr, CommandPtr> InspectorState::Running::didPause(
pendingEvalPromise_->setValue(
inspector_.debugger_.getProgramState().getEvalResult());
pendingEvalPromise_.reset();
} else if (
reason == debugger::PauseReason::Breakpoint &&
!inspector_.breakpointsActive_) {
// We hit a user defined breakpoint, but breakpoints have been deactivated.
return std::make_pair<NextStatePtr, CommandPtr>(
nullptr, makeContinueCommand());
} else /* other cases imply a transition to Pause */ {
return std::make_pair<NextStatePtr, CommandPtr>(
InspectorState::Paused::make(inspector_), nullptr);

Просмотреть файл

@ -81,6 +81,7 @@ class Connection::Impl : public inspector::InspectorObserver,
void handle(const m::debugger::ResumeRequest &req) override;
void handle(const m::debugger::SetBreakpointRequest &req) override;
void handle(const m::debugger::SetBreakpointByUrlRequest &req) override;
void handle(const m::debugger::SetBreakpointsActiveRequest &req) override;
void handle(
const m::debugger::SetInstrumentationBreakpointRequest &req) override;
void handle(const m::debugger::SetPauseOnExceptionsRequest &req) override;
@ -659,6 +660,16 @@ void Connection::Impl::handle(
.thenError<std::exception>(sendErrorToClient(req.id));
}
void Connection::Impl::handle(
const m::debugger::SetBreakpointsActiveRequest &req) {
inspector_->setBreakpointsActive(req.active)
.via(executor_.get())
.thenValue([this, id = req.id](const Unit &unit) {
sendResponseToClient(m::makeOkResponse(id));
})
.thenError<std::exception>(sendErrorToClient(req.id));
}
bool Connection::Impl::isVirtualBreakpointId(const std::string &id) {
return id.rfind(kVirtualBreakpointPrefix, 0) == 0;
}

Просмотреть файл

@ -1,5 +1,5 @@
// Copyright 2004-present Facebook. All Rights Reserved.
// @generated SignedSource<<f251363b69dd291d2c70e893c3fed04d>>
// @generated SignedSource<<addf39d6b92b8dc857e6e5ffe2a441d4>>
#include "MessageTypes.h"
@ -35,6 +35,8 @@ std::unique_ptr<Request> Request::fromJsonThrowOnError(const std::string &str) {
{"Debugger.setBreakpoint", makeUnique<debugger::SetBreakpointRequest>},
{"Debugger.setBreakpointByUrl",
makeUnique<debugger::SetBreakpointByUrlRequest>},
{"Debugger.setBreakpointsActive",
makeUnique<debugger::SetBreakpointsActiveRequest>},
{"Debugger.setInstrumentationBreakpoint",
makeUnique<debugger::SetInstrumentationBreakpointRequest>},
{"Debugger.setPauseOnExceptions",
@ -509,6 +511,35 @@ void debugger::SetBreakpointByUrlRequest::accept(
handler.handle(*this);
}
debugger::SetBreakpointsActiveRequest::SetBreakpointsActiveRequest()
: Request("Debugger.setBreakpointsActive") {}
debugger::SetBreakpointsActiveRequest::SetBreakpointsActiveRequest(
const dynamic &obj)
: Request("Debugger.setBreakpointsActive") {
assign(id, obj, "id");
assign(method, obj, "method");
dynamic params = obj.at("params");
assign(active, params, "active");
}
dynamic debugger::SetBreakpointsActiveRequest::toDynamic() const {
dynamic params = dynamic::object;
put(params, "active", active);
dynamic obj = dynamic::object;
put(obj, "id", id);
put(obj, "method", method);
put(obj, "params", std::move(params));
return obj;
}
void debugger::SetBreakpointsActiveRequest::accept(
RequestHandler &handler) const {
handler.handle(*this);
}
debugger::SetInstrumentationBreakpointRequest::
SetInstrumentationBreakpointRequest()
: Request("Debugger.setInstrumentationBreakpoint") {}

Просмотреть файл

@ -1,5 +1,5 @@
// Copyright 2004-present Facebook. All Rights Reserved.
// @generated SignedSource<<356df52df2a053b5254f0e039cc36a7b>>
// @generated SignedSource<<0563169b47d73a70d7540528f28d1d13>>
#pragma once
@ -38,6 +38,7 @@ struct SetBreakpointByUrlRequest;
struct SetBreakpointByUrlResponse;
struct SetBreakpointRequest;
struct SetBreakpointResponse;
struct SetBreakpointsActiveRequest;
struct SetInstrumentationBreakpointRequest;
struct SetInstrumentationBreakpointResponse;
struct SetPauseOnExceptionsRequest;
@ -89,6 +90,7 @@ struct RequestHandler {
virtual void handle(const debugger::ResumeRequest &req) = 0;
virtual void handle(const debugger::SetBreakpointRequest &req) = 0;
virtual void handle(const debugger::SetBreakpointByUrlRequest &req) = 0;
virtual void handle(const debugger::SetBreakpointsActiveRequest &req) = 0;
virtual void handle(
const debugger::SetInstrumentationBreakpointRequest &req) = 0;
virtual void handle(const debugger::SetPauseOnExceptionsRequest &req) = 0;
@ -116,6 +118,7 @@ struct NoopRequestHandler : public RequestHandler {
void handle(const debugger::ResumeRequest &req) override {}
void handle(const debugger::SetBreakpointRequest &req) override {}
void handle(const debugger::SetBreakpointByUrlRequest &req) override {}
void handle(const debugger::SetBreakpointsActiveRequest &req) override {}
void handle(
const debugger::SetInstrumentationBreakpointRequest &req) override {}
void handle(const debugger::SetPauseOnExceptionsRequest &req) override {}
@ -354,6 +357,16 @@ struct debugger::SetBreakpointByUrlRequest : public Request {
folly::Optional<std::string> condition;
};
struct debugger::SetBreakpointsActiveRequest : public Request {
SetBreakpointsActiveRequest();
explicit SetBreakpointsActiveRequest(const folly::dynamic &obj);
folly::dynamic toDynamic() const override;
void accept(RequestHandler &handler) const override;
bool active{};
};
struct debugger::SetInstrumentationBreakpointRequest : public Request {
SetInstrumentationBreakpointRequest();
explicit SetInstrumentationBreakpointRequest(const folly::dynamic &obj);

Просмотреть файл

@ -750,6 +750,70 @@ TEST(ConnectionTests, testSetBreakpointById) {
expectNotification<m::debugger::ResumedNotification>(conn);
}
TEST(ConnectionTests, testActivateBreakpoints) {
TestContext context;
AsyncHermesRuntime &asyncRuntime = context.runtime();
SyncConnection &conn = context.conn();
int msgId = 1;
asyncRuntime.executeScriptAsync(R"(
debugger; // line 1
x=100 // 2
debugger; // 3
x=101; // 4
)");
send<m::debugger::EnableRequest>(conn, ++msgId);
expectExecutionContextCreated(conn);
auto script = expectNotification<m::debugger::ScriptParsedNotification>(conn);
expectPaused(conn, "other", {{"global", 1, 1}});
// Set breakpoint #1
m::debugger::SetBreakpointRequest req;
req.id = ++msgId;
req.location.scriptId = script.scriptId;
req.location.lineNumber = 2;
conn.send(req.toJson());
expectResponse<m::debugger::SetBreakpointResponse>(conn, req.id);
// Set breakpoint #2
req.id = ++msgId;
req.location.scriptId = script.scriptId;
req.location.lineNumber = 4;
conn.send(req.toJson());
expectResponse<m::debugger::SetBreakpointResponse>(conn, req.id);
// Disable breakpoints
m::debugger::SetBreakpointsActiveRequest activeReq;
activeReq.id = ++msgId;
activeReq.active = false;
conn.send(activeReq.toJson());
expectResponse<m::OkResponse>(conn, activeReq.id);
// Resume
send<m::debugger::ResumeRequest>(conn, ++msgId);
expectNotification<m::debugger::ResumedNotification>(conn);
// Expect first breakpoint to be skipped, now hitting line #3
expectPaused(conn, "other", {{"global", 3, 1}});
// Re-enable breakpoints
activeReq.id = ++msgId;
activeReq.active = true;
conn.send(activeReq.toJson());
expectResponse<m::OkResponse>(conn, activeReq.id);
// Resume and expect breakpoints to trigger again
send<m::debugger::ResumeRequest>(conn, ++msgId);
expectNotification<m::debugger::ResumedNotification>(conn);
expectPaused(conn, "other", {{"global", 4, 1}});
// Continue and exit
send<m::debugger::ResumeRequest>(conn, ++msgId);
expectNotification<m::debugger::ResumedNotification>(conn);
}
TEST(ConnectionTests, testSetBreakpointByIdWithColumnInIndenting) {
TestContext context;
AsyncHermesRuntime &asyncRuntime = context.runtime();

Просмотреть файл

@ -10,6 +10,7 @@ Debugger.resumed
Debugger.scriptParsed
Debugger.setBreakpoint
Debugger.setBreakpointByUrl
Debugger.setBreakpointsActive
Debugger.setInstrumentationBreakpoint
Debugger.setPauseOnExceptions
Debugger.stepInto

Просмотреть файл

@ -1,3 +1,4 @@
load("@fbsource//tools/build_defs:buckconfig.bzl", "read_bool")
load("@fbsource//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
load("@fbsource//tools/build_defs:platform_defs.bzl", "IOS", "MACOSX")
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_preprocessor_flags_for_build_mode")
@ -184,78 +185,84 @@ def rn_codegen_components(
)
# libs
rn_xplat_cxx_library(
name = "generated_components-{}".format(name),
srcs = [
":{}".format(generate_event_emitter_cpp_name),
":{}".format(generate_props_cpp_name),
":{}".format(generate_shadow_node_cpp_name),
],
headers = [
":{}".format(generate_component_descriptor_h_name),
":{}".format(generate_event_emitter_h_name),
":{}".format(generate_props_h_name),
":{}".format(generate_shadow_node_h_name),
],
header_namespace = "react/components/{}".format(name),
exported_headers = {
"ComponentDescriptors.h": ":{}".format(generate_component_descriptor_h_name),
"EventEmitters.h": ":{}".format(generate_event_emitter_h_name),
"Props.h": ":{}".format(generate_props_h_name),
"RCTComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name),
"ShadowNodes.h": ":{}".format(generate_shadow_node_h_name),
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
fbobjc_compiler_flags = get_apple_compiler_flags(),
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
ios_exported_headers = {
"ComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name),
},
ios_headers = [
":{}".format(generate_component_hobjcpp_name),
],
labels = ["codegen_rule"],
platforms = (ANDROID, APPLE, CXX),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
tests = [":generated_tests-{}".format(name)],
visibility = ["PUBLIC"],
deps = [
"//third-party/glog:glog",
"//xplat/fbsystrace:fbsystrace",
"//xplat/folly:headers_only",
"//xplat/folly:memory",
"//xplat/folly:molly",
YOGA_CXX_TARGET,
react_native_xplat_target("fabric/debug:debug"),
react_native_xplat_target("fabric/core:core"),
react_native_xplat_target("fabric/graphics:graphics"),
react_native_xplat_target("fabric/components/image:image"),
react_native_xplat_target("fabric/imagemanager:imagemanager"),
react_native_xplat_target("fabric/components/view:view"),
],
)
if is_running_buck_project():
rn_xplat_cxx_library(name = "generated_components-{}".format(name), visibility = ["PUBLIC"])
else:
rn_xplat_cxx_library(
name = "generated_components-{}".format(name),
srcs = [
":{}".format(generate_event_emitter_cpp_name),
":{}".format(generate_props_cpp_name),
":{}".format(generate_shadow_node_cpp_name),
],
headers = [
":{}".format(generate_component_descriptor_h_name),
":{}".format(generate_event_emitter_h_name),
":{}".format(generate_props_h_name),
":{}".format(generate_shadow_node_h_name),
],
header_namespace = "react/components/{}".format(name),
exported_headers = {
"ComponentDescriptors.h": ":{}".format(generate_component_descriptor_h_name),
"EventEmitters.h": ":{}".format(generate_event_emitter_h_name),
"Props.h": ":{}".format(generate_props_h_name),
"RCTComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name),
"ShadowNodes.h": ":{}".format(generate_shadow_node_h_name),
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
fbobjc_compiler_flags = get_apple_compiler_flags(),
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
ios_exported_headers = {
"ComponentViewHelpers.h": ":{}".format(generate_component_hobjcpp_name),
},
ios_headers = [
":{}".format(generate_component_hobjcpp_name),
],
labels = ["codegen_rule"],
platforms = (ANDROID, APPLE, CXX),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
tests = [":generated_tests-{}".format(name)],
visibility = ["PUBLIC"],
deps = [
"//third-party/glog:glog",
"//xplat/fbsystrace:fbsystrace",
"//xplat/folly:headers_only",
"//xplat/folly:memory",
"//xplat/folly:molly",
YOGA_CXX_TARGET,
react_native_xplat_target("fabric/debug:debug"),
react_native_xplat_target("fabric/core:core"),
react_native_xplat_target("fabric/graphics:graphics"),
react_native_xplat_target("fabric/components/image:image"),
react_native_xplat_target("fabric/imagemanager:imagemanager"),
react_native_xplat_target("fabric/components/view:view"),
],
)
rn_android_library(
name = "generated_components_java-{}".format(name),
srcs = [
":{}".format(zip_generated_java_files),
],
labels = ["codegen_rule"],
visibility = ["PUBLIC"],
deps = [
react_native_dep("third-party/android/androidx:annotation"),
react_native_target("java/com/facebook/react/bridge:bridge"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
],
)
if is_running_buck_project():
rn_android_library(name = "generated_components_java-{}".format(name))
else:
rn_android_library(
name = "generated_components_java-{}".format(name),
srcs = [
":{}".format(zip_generated_java_files),
],
labels = ["codegen_rule"],
visibility = ["PUBLIC"],
deps = [
react_native_dep("third-party/android/androidx:annotation"),
react_native_target("java/com/facebook/react/bridge:bridge"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
],
)
# Tests
fb_xplat_cxx_test(
@ -308,35 +315,41 @@ def rn_codegen_cxx_modules(
labels = ["codegen_rule"],
)
rn_xplat_cxx_library(
name = "generated_cxx_modules-{}".format(name),
srcs = [
":{}".format(generate_module_cpp_name),
],
headers = [
":{}".format(generate_module_h_name),
],
header_namespace = "react/modules/{}".format(name),
exported_headers = {
"NativeModules.cpp": ":{}".format(generate_module_cpp_name),
"NativeModules.h": ":{}".format(generate_module_h_name),
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
fbobjc_compiler_flags = get_apple_compiler_flags(),
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
labels = ["codegen_rule"],
platforms = (ANDROID, APPLE),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
visibility = ["PUBLIC"],
exported_deps = [
react_native_xplat_target("turbomodule/core:core"),
],
)
if is_running_buck_project():
rn_xplat_cxx_library(name = "generated_cxx_modules-{}".format(name))
else:
rn_xplat_cxx_library(
name = "generated_cxx_modules-{}".format(name),
srcs = [
":{}".format(generate_module_cpp_name),
],
headers = [
":{}".format(generate_module_h_name),
],
header_namespace = "react/modules/{}".format(name),
exported_headers = {
"NativeModules.cpp": ":{}".format(generate_module_cpp_name),
"NativeModules.h": ":{}".format(generate_module_h_name),
},
compiler_flags = [
"-fexceptions",
"-frtti",
"-std=c++14",
"-Wall",
],
fbobjc_compiler_flags = get_apple_compiler_flags(),
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
labels = ["codegen_rule"],
platforms = (ANDROID, APPLE),
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
visibility = ["PUBLIC"],
exported_deps = [
react_native_xplat_target("turbomodule/core:core"),
],
)
def is_running_buck_project():
return read_bool("fbandroid", "is_running_buck_project", False)