Merge commit '7b82df287d36e39073d29e3ae3adbe82cf424055' into amgleitman/0.64-merge-head
This commit is contained in:
Коммит
3e0ced8068
|
@ -224,7 +224,8 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
|
|||
style={mergedStyle}
|
||||
ref={this._setComponentRef}
|
||||
nativeID={
|
||||
this._isFabric() ? 'animatedComponent' : undefined
|
||||
props.nativeID ??
|
||||
(this._isFabric() ? 'animatedComponent' : undefined)
|
||||
} /* TODO: T68258846. */
|
||||
// The native driver updates views directly through the UI thread so we
|
||||
// have to make sure the view doesn't get optimized away because it cannot
|
||||
|
|
|
@ -20,6 +20,6 @@ fb_apple_library(
|
|||
deps = [
|
||||
"//xplat/js/react-native-github:RCTTypeSafety",
|
||||
"//xplat/js/react-native-github/Libraries/RCTRequired:RCTRequired",
|
||||
react_native_xplat_target_apple("turbomodule/core:core"),
|
||||
react_native_xplat_target_apple("react/nativemodule/core:core"),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -14,8 +15,6 @@ import createPerformanceLogger from '../createPerformanceLogger';
|
|||
import type {IPerformanceLogger} from '../createPerformanceLogger';
|
||||
|
||||
const TIMESPAN_1 = '<timespan_1>';
|
||||
const TIMESPAN_2 = '<timespan_2>';
|
||||
const TIMESPAN_2_DURATION = 123;
|
||||
const EXTRA_KEY = '<extra_key>';
|
||||
const EXTRA_VALUE = '<extra_value>';
|
||||
const EXTRA_VALUE_2 = '<extra_value_2>';
|
||||
|
@ -28,16 +27,16 @@ describe('PerformanceLogger', () => {
|
|||
GlobalPerformanceLogger.clear();
|
||||
});
|
||||
|
||||
it('starts & stops and adds a timespan', () => {
|
||||
it('starts & stops a timespan', () => {
|
||||
let perfLogger = createPerformanceLogger();
|
||||
perfLogger.startTimespan(TIMESPAN_1);
|
||||
perfLogger.stopTimespan(TIMESPAN_1);
|
||||
perfLogger.addTimeAnnotation(TIMESPAN_2, TIMESPAN_2_DURATION);
|
||||
expect(perfLogger.hasTimespan(TIMESPAN_1)).toBe(true);
|
||||
expect(perfLogger.hasTimespan(TIMESPAN_2)).toBe(true);
|
||||
expect(perfLogger.getTimespans()[TIMESPAN_2].totalTime).toBe(
|
||||
TIMESPAN_2_DURATION,
|
||||
);
|
||||
expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual({
|
||||
startTime: expect.any(Number),
|
||||
endTime: expect.any(Number),
|
||||
totalTime: expect.any(Number),
|
||||
});
|
||||
});
|
||||
|
||||
it('does not override a timespan', () => {
|
||||
|
@ -46,18 +45,14 @@ describe('PerformanceLogger', () => {
|
|||
let old = perfLogger.getTimespans()[TIMESPAN_1];
|
||||
perfLogger.startTimespan(TIMESPAN_1);
|
||||
expect(perfLogger.getTimespans()[TIMESPAN_1]).toBe(old);
|
||||
perfLogger.addTimeAnnotation(TIMESPAN_1, 1);
|
||||
expect(perfLogger.getTimespans()[TIMESPAN_1]).toBe(old);
|
||||
});
|
||||
|
||||
it('adds a timespan with start and end timestamps', () => {
|
||||
let perfLogger = createPerformanceLogger();
|
||||
const startTime = 0;
|
||||
const endTime = 100;
|
||||
const description = 'description';
|
||||
perfLogger.addTimespan(TIMESPAN_1, startTime, endTime, description);
|
||||
perfLogger.addTimespan(TIMESPAN_1, startTime, endTime);
|
||||
expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual({
|
||||
description,
|
||||
startTime,
|
||||
endTime,
|
||||
totalTime: endTime - startTime,
|
||||
|
@ -69,7 +64,7 @@ describe('PerformanceLogger', () => {
|
|||
perfLogger.startTimespan(TIMESPAN_1);
|
||||
perfLogger.stopTimespan(TIMESPAN_1);
|
||||
const existing = perfLogger.getTimespans()[TIMESPAN_1];
|
||||
perfLogger.addTimespan(TIMESPAN_1, 0, 100, 'overriding');
|
||||
perfLogger.addTimespan(TIMESPAN_1, 0, 100);
|
||||
expect(perfLogger.getTimespans()[TIMESPAN_1]).toEqual(existing);
|
||||
});
|
||||
|
||||
|
|
|
@ -13,39 +13,30 @@
|
|||
const Systrace = require('../Performance/Systrace');
|
||||
|
||||
const infoLog = require('./infoLog');
|
||||
const performanceNow =
|
||||
const performanceNow: () => number =
|
||||
global.nativeQPLTimestamp ?? global.performance.now.bind(global.performance);
|
||||
|
||||
type Timespan = {
|
||||
description?: string,
|
||||
totalTime?: number,
|
||||
startTime?: number,
|
||||
startTime: number,
|
||||
endTime?: number,
|
||||
...
|
||||
totalTime?: number,
|
||||
};
|
||||
|
||||
// Extra values should be serializable primitives
|
||||
type ExtraValue = number | string | boolean;
|
||||
|
||||
export interface IPerformanceLogger {
|
||||
addTimeAnnotation(
|
||||
key: string,
|
||||
durationInMs: number,
|
||||
description?: string,
|
||||
): void;
|
||||
addTimespan(
|
||||
key: string,
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
description?: string,
|
||||
): void;
|
||||
startTimespan(key: string, description?: string): void;
|
||||
stopTimespan(key: string, options?: {update?: boolean}): void;
|
||||
addTimespan(key: string, startTime: number, endTime: number): void;
|
||||
startTimespan(key: string): void;
|
||||
stopTimespan(key: string): void;
|
||||
clear(): void;
|
||||
clearCompleted(): void;
|
||||
currentTimestamp(): number;
|
||||
getTimespans(): {[key: string]: Timespan, ...};
|
||||
hasTimespan(key: string): boolean;
|
||||
setExtra(key: string, value: mixed): void;
|
||||
getExtras(): {[key: string]: mixed, ...};
|
||||
removeExtra(key: string): ?mixed;
|
||||
setExtra(key: string, value: ExtraValue): void;
|
||||
getExtras(): {[key: string]: ExtraValue, ...};
|
||||
removeExtra(key: string): ExtraValue | void;
|
||||
markPoint(key: string, timestamp?: number): void;
|
||||
getPoints(): {[key: string]: number, ...};
|
||||
logEverything(): void;
|
||||
|
@ -55,211 +46,183 @@ const _cookies: {[key: string]: number, ...} = {};
|
|||
|
||||
const PRINT_TO_CONSOLE: false = false; // Type as false to prevent accidentally committing `true`;
|
||||
|
||||
class PerformanceLogger implements IPerformanceLogger {
|
||||
_timespans: {[key: string]: Timespan} = {};
|
||||
_extras: {[key: string]: ExtraValue} = {};
|
||||
_points: {[key: string]: number} = {};
|
||||
|
||||
addTimespan(key: string, startTime: number, endTime: number) {
|
||||
if (this._timespans[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to add a timespan that already exists ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._timespans[key] = {
|
||||
startTime,
|
||||
endTime,
|
||||
totalTime: endTime - (startTime || 0),
|
||||
};
|
||||
}
|
||||
|
||||
startTimespan(key: string) {
|
||||
if (this._timespans[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to start a timespan that already exists ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._timespans[key] = {
|
||||
startTime: performanceNow(),
|
||||
};
|
||||
_cookies[key] = Systrace.beginAsyncEvent(key);
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'start: ' + key);
|
||||
}
|
||||
}
|
||||
|
||||
stopTimespan(key: string) {
|
||||
const timespan = this._timespans[key];
|
||||
if (!timespan || timespan.startTime == null) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to end a timespan that has not started ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (timespan.endTime != null) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to end a timespan that has already ended ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
timespan.endTime = performanceNow();
|
||||
timespan.totalTime = timespan.endTime - (timespan.startTime || 0);
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'end: ' + key);
|
||||
}
|
||||
|
||||
if (_cookies[key] != null) {
|
||||
Systrace.endAsyncEvent(key, _cookies[key]);
|
||||
delete _cookies[key];
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._timespans = {};
|
||||
this._extras = {};
|
||||
this._points = {};
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'clear');
|
||||
}
|
||||
}
|
||||
|
||||
clearCompleted() {
|
||||
for (const key in this._timespans) {
|
||||
if (this._timespans[key].totalTime != null) {
|
||||
delete this._timespans[key];
|
||||
}
|
||||
}
|
||||
this._extras = {};
|
||||
this._points = {};
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'clearCompleted');
|
||||
}
|
||||
}
|
||||
|
||||
currentTimestamp() {
|
||||
return performanceNow();
|
||||
}
|
||||
|
||||
getTimespans() {
|
||||
return this._timespans;
|
||||
}
|
||||
|
||||
hasTimespan(key: string) {
|
||||
return !!this._timespans[key];
|
||||
}
|
||||
|
||||
setExtra(key: string, value: ExtraValue) {
|
||||
if (this._extras.hasOwnProperty(key)) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to set an extra that already exists ',
|
||||
{key, currentValue: this._extras[key], attemptedValue: value},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._extras[key] = value;
|
||||
}
|
||||
|
||||
getExtras() {
|
||||
return this._extras;
|
||||
}
|
||||
|
||||
removeExtra(key: string): ExtraValue | void {
|
||||
const value = this._extras[key];
|
||||
delete this._extras[key];
|
||||
return value;
|
||||
}
|
||||
|
||||
markPoint(key: string, timestamp?: number) {
|
||||
if (this._points[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to mark a point that has been already logged ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._points[key] = timestamp ?? performanceNow();
|
||||
}
|
||||
|
||||
getPoints() {
|
||||
return this._points;
|
||||
}
|
||||
|
||||
logEverything() {
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
// log timespans
|
||||
for (const key in this._timespans) {
|
||||
if (this._timespans[key].totalTime != null) {
|
||||
infoLog(key + ': ' + this._timespans[key].totalTime + 'ms');
|
||||
}
|
||||
}
|
||||
|
||||
// log extras
|
||||
infoLog(this._extras);
|
||||
|
||||
// log points
|
||||
for (const key in this._points) {
|
||||
infoLog(key + ': ' + this._points[key] + 'ms');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function creates performance loggers that can be used to collect and log
|
||||
* various performance data such as timespans, points and extras.
|
||||
* The loggers need to have minimal overhead since they're used in production.
|
||||
*/
|
||||
function createPerformanceLogger(): IPerformanceLogger {
|
||||
const result: IPerformanceLogger & {
|
||||
_timespans: {[key: string]: Timespan, ...},
|
||||
_extras: {[key: string]: mixed, ...},
|
||||
_points: {[key: string]: number, ...},
|
||||
...
|
||||
} = {
|
||||
_timespans: {},
|
||||
_extras: {},
|
||||
_points: {},
|
||||
|
||||
addTimeAnnotation(key: string, durationInMs: number, description?: string) {
|
||||
if (this._timespans[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to add a timespan that already exists ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._timespans[key] = {
|
||||
description: description,
|
||||
totalTime: durationInMs,
|
||||
};
|
||||
},
|
||||
|
||||
addTimespan(
|
||||
key: string,
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
description?: string,
|
||||
) {
|
||||
if (this._timespans[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to add a timespan that already exists ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._timespans[key] = {
|
||||
description,
|
||||
startTime,
|
||||
endTime,
|
||||
totalTime: endTime - (startTime || 0),
|
||||
};
|
||||
},
|
||||
|
||||
startTimespan(key: string, description?: string) {
|
||||
if (this._timespans[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to start a timespan that already exists ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._timespans[key] = {
|
||||
description: description,
|
||||
startTime: performanceNow(),
|
||||
};
|
||||
_cookies[key] = Systrace.beginAsyncEvent(key);
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'start: ' + key);
|
||||
}
|
||||
},
|
||||
|
||||
stopTimespan(key: string, options?: {update?: boolean}) {
|
||||
const timespan = this._timespans[key];
|
||||
if (!timespan || !timespan.startTime) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to end a timespan that has not started ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (timespan.endTime && !options?.update) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to end a timespan that has already ended ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
timespan.endTime = performanceNow();
|
||||
timespan.totalTime = timespan.endTime - (timespan.startTime || 0);
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'end: ' + key);
|
||||
}
|
||||
|
||||
if (_cookies[key] != null) {
|
||||
Systrace.endAsyncEvent(key, _cookies[key]);
|
||||
delete _cookies[key];
|
||||
}
|
||||
},
|
||||
|
||||
clear() {
|
||||
this._timespans = {};
|
||||
this._extras = {};
|
||||
this._points = {};
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'clear');
|
||||
}
|
||||
},
|
||||
|
||||
clearCompleted() {
|
||||
for (const key in this._timespans) {
|
||||
if (this._timespans[key].totalTime) {
|
||||
delete this._timespans[key];
|
||||
}
|
||||
}
|
||||
this._extras = {};
|
||||
this._points = {};
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
infoLog('PerformanceLogger.js', 'clearCompleted');
|
||||
}
|
||||
},
|
||||
|
||||
currentTimestamp() {
|
||||
return performanceNow();
|
||||
},
|
||||
|
||||
getTimespans() {
|
||||
return this._timespans;
|
||||
},
|
||||
|
||||
hasTimespan(key: string) {
|
||||
return !!this._timespans[key];
|
||||
},
|
||||
|
||||
setExtra(key: string, value: mixed) {
|
||||
if (this._extras[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to set an extra that already exists ',
|
||||
{key, currentValue: this._extras[key], attemptedValue: value},
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._extras[key] = value;
|
||||
},
|
||||
|
||||
getExtras() {
|
||||
return this._extras;
|
||||
},
|
||||
|
||||
removeExtra(key: string): ?mixed {
|
||||
const value = this._extras[key];
|
||||
delete this._extras[key];
|
||||
return value;
|
||||
},
|
||||
|
||||
markPoint(key: string, timestamp?: number) {
|
||||
if (this._points[key]) {
|
||||
if (PRINT_TO_CONSOLE && __DEV__) {
|
||||
infoLog(
|
||||
'PerformanceLogger: Attempting to mark a point that has been already logged ',
|
||||
key,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this._points[key] = timestamp ?? performanceNow();
|
||||
},
|
||||
|
||||
getPoints() {
|
||||
return this._points;
|
||||
},
|
||||
|
||||
logEverything() {
|
||||
if (PRINT_TO_CONSOLE) {
|
||||
// log timespans
|
||||
for (const key in this._timespans) {
|
||||
if (this._timespans[key].totalTime) {
|
||||
infoLog(key + ': ' + this._timespans[key].totalTime + 'ms');
|
||||
}
|
||||
}
|
||||
|
||||
// log extras
|
||||
infoLog(this._extras);
|
||||
|
||||
// log points
|
||||
for (const key in this._points) {
|
||||
infoLog(key + ': ' + this._points[key] + 'ms');
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
return result;
|
||||
return new PerformanceLogger();
|
||||
}
|
||||
|
||||
module.exports = createPerformanceLogger;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#import "RCTActivityIndicatorViewComponentView.h"
|
||||
|
||||
#import <React/RCTConversions.h>
|
||||
|
||||
#import <react/renderer/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/renderer/components/rncore/EventEmitters.h>
|
||||
#import <react/renderer/components/rncore/Props.h>
|
||||
|
@ -50,7 +52,7 @@ static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const Acti
|
|||
} else {
|
||||
[_activityIndicatorView stopAnimating];
|
||||
}
|
||||
_activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps->color.get()];
|
||||
_activityIndicatorView.color = RCTUIColorFromSharedColor(defaultProps->color);
|
||||
_activityIndicatorView.hidesWhenStopped = defaultProps->hidesWhenStopped;
|
||||
_activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps->size);
|
||||
|
||||
|
@ -73,8 +75,8 @@ static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const Acti
|
|||
}
|
||||
}
|
||||
|
||||
if (oldViewProps.color.get() != newViewProps.color.get()) {
|
||||
_activityIndicatorView.color = [UIColor colorWithCGColor:newViewProps.color.get()];
|
||||
if (oldViewProps.color != newViewProps.color) {
|
||||
_activityIndicatorView.color = RCTUIColorFromSharedColor(newViewProps.color);
|
||||
}
|
||||
|
||||
// TODO: This prop should be deprecated.
|
||||
|
|
|
@ -74,7 +74,7 @@ using namespace facebook::react;
|
|||
|
||||
// `tintColor`
|
||||
if (oldImageProps.tintColor != newImageProps.tintColor) {
|
||||
_imageView.tintColor = [UIColor colorWithCGColor:newImageProps.tintColor.get()];
|
||||
_imageView.tintColor = RCTUIColorFromSharedColor(newImageProps.tintColor);
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
|
||||
#import "RCTSliderComponentView.h"
|
||||
|
||||
#import <React/RCTConversions.h>
|
||||
#import <React/RCTImageResponseDelegate.h>
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
|
||||
#import <react/renderer/components/rncore/EventEmitters.h>
|
||||
#import <react/renderer/components/rncore/Props.h>
|
||||
#import <react/renderer/components/slider/SliderComponentDescriptor.h>
|
||||
|
@ -131,17 +133,17 @@ using namespace facebook::react;
|
|||
|
||||
// `thumbTintColor`
|
||||
if (oldSliderProps.thumbTintColor != newSliderProps.thumbTintColor) {
|
||||
_sliderView.thumbTintColor = [UIColor colorWithCGColor:newSliderProps.thumbTintColor.get()];
|
||||
_sliderView.thumbTintColor = RCTUIColorFromSharedColor(newSliderProps.thumbTintColor);
|
||||
}
|
||||
|
||||
// `minimumTrackTintColor`
|
||||
if (oldSliderProps.minimumTrackTintColor != newSliderProps.minimumTrackTintColor) {
|
||||
_sliderView.minimumTrackTintColor = [UIColor colorWithCGColor:newSliderProps.minimumTrackTintColor.get()];
|
||||
_sliderView.minimumTrackTintColor = RCTUIColorFromSharedColor(newSliderProps.minimumTrackTintColor);
|
||||
}
|
||||
|
||||
// `maximumTrackTintColor`
|
||||
if (oldSliderProps.maximumTrackTintColor != newSliderProps.maximumTrackTintColor) {
|
||||
_sliderView.maximumTrackTintColor = [UIColor colorWithCGColor:newSliderProps.maximumTrackTintColor.get()];
|
||||
_sliderView.maximumTrackTintColor = RCTUIColorFromSharedColor(newSliderProps.maximumTrackTintColor);
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#import "RCTSwitchComponentView.h"
|
||||
|
||||
#import <React/RCTConversions.h>
|
||||
|
||||
#import <react/renderer/components/rncore/ComponentDescriptors.h>
|
||||
#import <react/renderer/components/rncore/EventEmitters.h>
|
||||
#import <react/renderer/components/rncore/Props.h>
|
||||
|
@ -75,17 +77,17 @@ using namespace facebook::react;
|
|||
|
||||
// `tintColor`
|
||||
if (oldSwitchProps.tintColor != newSwitchProps.tintColor) {
|
||||
_switchView.tintColor = [UIColor colorWithCGColor:newSwitchProps.tintColor.get()];
|
||||
_switchView.tintColor = RCTUIColorFromSharedColor(newSwitchProps.tintColor);
|
||||
}
|
||||
|
||||
// `onTintColor
|
||||
if (oldSwitchProps.onTintColor != newSwitchProps.onTintColor) {
|
||||
_switchView.onTintColor = [UIColor colorWithCGColor:newSwitchProps.onTintColor.get()];
|
||||
_switchView.onTintColor = RCTUIColorFromSharedColor(newSwitchProps.onTintColor);
|
||||
}
|
||||
|
||||
// `thumbTintColor`
|
||||
if (oldSwitchProps.thumbTintColor != newSwitchProps.thumbTintColor) {
|
||||
_switchView.thumbTintColor = [UIColor colorWithCGColor:newSwitchProps.thumbTintColor.get()];
|
||||
_switchView.thumbTintColor = RCTUIColorFromSharedColor(newSwitchProps.thumbTintColor);
|
||||
}
|
||||
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
|
||||
#import "RCTViewComponentView.h"
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <React/RCTAssert.h>
|
||||
#import <React/RCTBorderDrawing.h>
|
||||
#import <React/RCTConversions.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <react/renderer/components/view/ViewComponentDescriptor.h>
|
||||
#import <react/renderer/components/view/ViewEventEmitter.h>
|
||||
#import <react/renderer/components/view/ViewProps.h>
|
||||
|
@ -118,7 +120,7 @@ using namespace facebook::react;
|
|||
|
||||
// `shadowColor`
|
||||
if (oldViewProps.shadowColor != newViewProps.shadowColor) {
|
||||
CGColorRef shadowColor = RCTCGColorRefFromSharedColor(newViewProps.shadowColor);
|
||||
CGColorRef shadowColor = RCTCreateCGColorRefFromSharedColor(newViewProps.shadowColor);
|
||||
self.layer.shadowColor = shadowColor;
|
||||
CGColorRelease(shadowColor);
|
||||
needsInvalidateLayer = YES;
|
||||
|
@ -344,12 +346,20 @@ static RCTCornerRadii RCTCornerRadiiFromBorderRadii(BorderRadii borderRadii)
|
|||
.bottomRight = (CGFloat)borderRadii.bottomRight};
|
||||
}
|
||||
|
||||
static RCTBorderColors RCTBorderColorsFromBorderColors(BorderColors borderColors)
|
||||
static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors(BorderColors borderColors)
|
||||
{
|
||||
return RCTBorderColors{.top = RCTCGColorRefUnretainedFromSharedColor(borderColors.top),
|
||||
.left = RCTCGColorRefUnretainedFromSharedColor(borderColors.left),
|
||||
.bottom = RCTCGColorRefUnretainedFromSharedColor(borderColors.bottom),
|
||||
.right = RCTCGColorRefUnretainedFromSharedColor(borderColors.right)};
|
||||
return RCTBorderColors{.top = RCTCreateCGColorRefFromSharedColor(borderColors.top),
|
||||
.left = RCTCreateCGColorRefFromSharedColor(borderColors.left),
|
||||
.bottom = RCTCreateCGColorRefFromSharedColor(borderColors.bottom),
|
||||
.right = RCTCreateCGColorRefFromSharedColor(borderColors.right)};
|
||||
}
|
||||
|
||||
static void RCTReleaseRCTBorderColors(RCTBorderColors borderColors)
|
||||
{
|
||||
CGColorRelease(borderColors.top);
|
||||
CGColorRelease(borderColors.left);
|
||||
CGColorRelease(borderColors.bottom);
|
||||
CGColorRelease(borderColors.right);
|
||||
}
|
||||
|
||||
static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
|
||||
|
@ -412,7 +422,7 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
|
|||
}
|
||||
|
||||
layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left;
|
||||
CGColorRef borderColor = RCTCGColorRefFromSharedColor(borderMetrics.borderColors.left);
|
||||
CGColorRef borderColor = RCTCreateCGColorRefFromSharedColor(borderMetrics.borderColors.left);
|
||||
layer.borderColor = borderColor;
|
||||
CGColorRelease(borderColor);
|
||||
layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft;
|
||||
|
@ -431,15 +441,19 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
|
|||
layer.borderColor = nil;
|
||||
layer.cornerRadius = 0;
|
||||
|
||||
RCTBorderColors borderColors = RCTCreateRCTBorderColorsFromBorderColors(borderMetrics.borderColors);
|
||||
|
||||
UIImage *image = RCTGetBorderImage(
|
||||
RCTBorderStyleFromBorderStyle(borderMetrics.borderStyles.left),
|
||||
layer.bounds.size,
|
||||
RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii),
|
||||
RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths),
|
||||
RCTBorderColorsFromBorderColors(borderMetrics.borderColors),
|
||||
borderColors,
|
||||
_backgroundColor.CGColor,
|
||||
self.clipsToBounds);
|
||||
|
||||
RCTReleaseRCTBorderColors(borderColors);
|
||||
|
||||
if (image == nil) {
|
||||
_borderLayer.contents = nil;
|
||||
} else {
|
||||
|
|
|
@ -35,20 +35,32 @@ inline std::string RCTStringFromNSString(NSString *string)
|
|||
return std::string{string.UTF8String ?: ""};
|
||||
}
|
||||
|
||||
inline UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::SharedColor &sharedColor)
|
||||
inline UIColor *_Nullable RCTUIColorFromSharedColor(facebook::react::SharedColor const &sharedColor)
|
||||
{
|
||||
return sharedColor ? [UIColor colorWithCGColor:sharedColor.get()] : nil;
|
||||
if (!sharedColor) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (*facebook::react::clearColor() == *sharedColor) {
|
||||
return [UIColor clearColor];
|
||||
}
|
||||
|
||||
if (*facebook::react::blackColor() == *sharedColor) {
|
||||
return [UIColor blackColor];
|
||||
}
|
||||
|
||||
if (*facebook::react::whiteColor() == *sharedColor) {
|
||||
return [UIColor whiteColor];
|
||||
}
|
||||
|
||||
auto components = facebook::react::colorComponentsFromColor(sharedColor);
|
||||
return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
|
||||
}
|
||||
|
||||
inline CF_RETURNS_NOT_RETAINED CGColorRef
|
||||
RCTCGColorRefUnretainedFromSharedColor(const facebook::react::SharedColor &sharedColor)
|
||||
inline CF_RETURNS_RETAINED CGColorRef
|
||||
RCTCreateCGColorRefFromSharedColor(const facebook::react::SharedColor &sharedColor)
|
||||
{
|
||||
return sharedColor ? sharedColor.get() : nil;
|
||||
}
|
||||
|
||||
inline CF_RETURNS_RETAINED CGColorRef RCTCGColorRefFromSharedColor(const facebook::react::SharedColor &sharedColor)
|
||||
{
|
||||
return sharedColor ? CGColorCreateCopy(sharedColor.get()) : nil;
|
||||
return CGColorRetain(RCTUIColorFromSharedColor(sharedColor).CGColor);
|
||||
}
|
||||
|
||||
inline CGPoint RCTCGPointFromPoint(const facebook::react::Point &point)
|
||||
|
|
|
@ -48,7 +48,7 @@ static RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
|
|||
auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
|
||||
|
||||
RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
|
||||
std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
|
||||
std::function<void(facebook::jsi::Runtime &runtime)> &&callback) {
|
||||
RCTBridge *bridge = unwrapManagedObjectWeakly(bridgeWeakWrapper);
|
||||
|
||||
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of scheduling a call.");
|
||||
|
|
|
@ -51,7 +51,7 @@ rn_xplat_cxx_library(
|
|||
react_native_xplat_target("cxxreact:bridge"),
|
||||
],
|
||||
exported_deps = ([
|
||||
react_native_xplat_target("turbomodule/core:core"),
|
||||
react_native_xplat_target("react/nativemodule/core:core"),
|
||||
]) + ([
|
||||
"//xplat/jsi:jsi",
|
||||
]) if not IS_OSS_BUILD else [],
|
||||
|
|
|
@ -428,11 +428,12 @@ local_ref<JMountItem::javaobject> createUpdatePaddingMountItem(
|
|||
auto newChildShadowView = mutation.newChildShadowView;
|
||||
|
||||
if (oldChildShadowView.layoutMetrics.contentInsets ==
|
||||
newChildShadowView.layoutMetrics.contentInsets) {
|
||||
newChildShadowView.layoutMetrics.contentInsets &&
|
||||
mutation.type != ShadowViewMutation::Type::Insert) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static auto updateLayoutInstruction =
|
||||
static auto updatePaddingInstruction =
|
||||
jni::findClassStatic(Binding::UIManagerJavaDescriptor)
|
||||
->getMethod<alias_ref<JMountItem>(jint, jint, jint, jint, jint)>(
|
||||
"updatePaddingMountItem");
|
||||
|
@ -446,7 +447,7 @@ local_ref<JMountItem::javaobject> createUpdatePaddingMountItem(
|
|||
int right = round(contentInsets.right * pointScaleFactor);
|
||||
int bottom = round(contentInsets.bottom * pointScaleFactor);
|
||||
|
||||
return updateLayoutInstruction(
|
||||
return updatePaddingInstruction(
|
||||
javaUIManager, newChildShadowView.tag, left, top, right, bottom);
|
||||
}
|
||||
|
||||
|
|
|
@ -399,7 +399,7 @@ public class MountingManager {
|
|||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
"Tried to delete view ["
|
||||
"Tried to remove view ["
|
||||
+ tag
|
||||
+ "] of parent ["
|
||||
+ parentTag
|
||||
|
@ -577,12 +577,20 @@ public class MountingManager {
|
|||
return;
|
||||
}
|
||||
|
||||
View view = viewState.mView;
|
||||
// To delete we simply remove the tag from the registry.
|
||||
// In the past we called dropView here, but we want to rely on either
|
||||
// (1) the correct set of MountInstructions being sent to the platform
|
||||
// and/or (2) dropView being called by stopSurface.
|
||||
// If Views are orphaned at this stage and leaked, it's a problem in
|
||||
// the differ or LayoutAnimations, not MountingManager.
|
||||
// Additionally, as documented in `dropView`, we cannot always trust a
|
||||
// view's children to be up-to-date.
|
||||
mTagToViewState.remove(reactTag);
|
||||
|
||||
if (view != null) {
|
||||
dropView(view, false);
|
||||
} else {
|
||||
mTagToViewState.remove(reactTag);
|
||||
// For non-root views we notify viewmanager with {@link ViewManager#onDropInstance}
|
||||
ViewManager viewManager = viewState.mViewManager;
|
||||
if (!viewState.mIsRoot && viewManager != null) {
|
||||
viewManager.onDropViewInstance(viewState.mView);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
package com.facebook.react.fabric.mounting.mountitems;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.bridge.ReactMarkerConstants;
|
||||
|
@ -70,8 +71,20 @@ public class BatchMountItem implements MountItem {
|
|||
public void execute(@NonNull MountingManager mountingManager) {
|
||||
beginMarkers("mountViews");
|
||||
|
||||
for (int mountItemIndex = 0; mountItemIndex < mSize; mountItemIndex++) {
|
||||
mMountItems[mountItemIndex].execute(mountingManager);
|
||||
int mountItemIndex = 0;
|
||||
try {
|
||||
for (; mountItemIndex < mSize; mountItemIndex++) {
|
||||
mMountItems[mountItemIndex].execute(mountingManager);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
FLog.e(
|
||||
TAG,
|
||||
"Caught exception executing mountItem @"
|
||||
+ mountItemIndex
|
||||
+ ": "
|
||||
+ mMountItems[mountItemIndex].toString(),
|
||||
e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
endMarkers();
|
||||
|
|
|
@ -34,7 +34,7 @@ rn_xplat_cxx_library(
|
|||
exported_deps = [
|
||||
":callinvokerholder",
|
||||
"//xplat/jsi:jsi",
|
||||
react_native_xplat_target("turbomodule/core:core"),
|
||||
react_native_xplat_target("react/nativemodule/core:core"),
|
||||
react_native_target("java/com/facebook/react/reactperflogger/jni:jni"),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -92,12 +92,6 @@ CatalystInstanceImpl::initHybrid(jni::alias_ref<jclass>) {
|
|||
CatalystInstanceImpl::CatalystInstanceImpl()
|
||||
: instance_(std::make_unique<Instance>()) {}
|
||||
|
||||
CatalystInstanceImpl::~CatalystInstanceImpl() {
|
||||
if (moduleMessageQueue_ != NULL) {
|
||||
moduleMessageQueue_->quitSynchronous();
|
||||
}
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid),
|
||||
|
|
|
@ -37,7 +37,6 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
|
|||
"Lcom/facebook/react/bridge/CatalystInstanceImpl;";
|
||||
|
||||
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>);
|
||||
~CatalystInstanceImpl() override;
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ Pod::Spec.new do |s|
|
|||
"USE_HEADERMAP" => "YES",
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++14" }
|
||||
|
||||
# TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..."
|
||||
# Note: Update this only when ready to minimize breaking changes.
|
||||
s.subspec "turbomodule" do |ss|
|
||||
ss.dependency "React-callinvoker", version
|
||||
ss.dependency "React-perflogger", version
|
||||
|
@ -47,13 +49,13 @@ Pod::Spec.new do |s|
|
|||
ss.dependency "glog"
|
||||
|
||||
ss.subspec "core" do |sss|
|
||||
sss.source_files = "turbomodule/core/*.{cpp,h}",
|
||||
"turbomodule/core/platform/ios/*.{mm,cpp,h}"
|
||||
sss.source_files = "react/nativemodule/core/*.{cpp,h}",
|
||||
"react/nativemodule/core/platform/ios/*.{mm,cpp,h}"
|
||||
end
|
||||
|
||||
ss.subspec "samples" do |sss|
|
||||
sss.source_files = "turbomodule/samples/*.{cpp,h}",
|
||||
"turbomodule/samples/platform/ios/*.{mm,cpp,h}"
|
||||
sss.source_files = "react/nativemodule/samples/*.{cpp,h}",
|
||||
"react/nativemodule/samples/platform/ios/*.{mm,cpp,h}"
|
||||
sss.dependency "ReactCommon/turbomodule/core", version
|
||||
end
|
||||
end
|
||||
|
|
|
@ -331,8 +331,8 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
|
|||
return plain().instrumentation().getHeapInfo(includeExpensive);
|
||||
}
|
||||
|
||||
void collectGarbage() override {
|
||||
plain().instrumentation().collectGarbage();
|
||||
void collectGarbage(std::string cause) override {
|
||||
plain().instrumentation().collectGarbage(std::move(cause));
|
||||
}
|
||||
|
||||
void startTrackingHeapObjectStackTraces() override {
|
||||
|
|
|
@ -49,8 +49,10 @@ class JSI_EXPORT Instrumentation {
|
|||
virtual std::unordered_map<std::string, int64_t> getHeapInfo(
|
||||
bool includeExpensive) = 0;
|
||||
|
||||
/// perform a full garbage collection
|
||||
virtual void collectGarbage() = 0;
|
||||
/// Perform a full garbage collection.
|
||||
/// \param cause The cause of this collection, as it should be reported in
|
||||
/// logs.
|
||||
virtual void collectGarbage(std::string cause) = 0;
|
||||
|
||||
/// Start capturing JS stack-traces for all JS heap allocated objects. These
|
||||
/// can be accessed via \c ::createSnapshotToFile().
|
||||
|
|
|
@ -97,7 +97,7 @@ Instrumentation& Runtime::instrumentation() {
|
|||
return std::unordered_map<std::string, int64_t>{};
|
||||
}
|
||||
|
||||
void collectGarbage() override {}
|
||||
void collectGarbage(std::string) override {}
|
||||
|
||||
void startTrackingHeapObjectStackTraces() override {}
|
||||
void stopTrackingHeapObjectStackTraces() override {}
|
||||
|
|
|
@ -344,7 +344,7 @@ void JSIExecutor::handleMemoryPressure(int pressureLevel) {
|
|||
// collections.
|
||||
LOG(INFO) << "Memory warning (pressure level: " << levelName
|
||||
<< ") received by JS VM, running a GC";
|
||||
runtime_->instrumentation().collectGarbage();
|
||||
runtime_->instrumentation().collectGarbage("memory warning");
|
||||
break;
|
||||
default:
|
||||
// Use the raw number instead of the name here since the name is
|
||||
|
|
|
@ -31,6 +31,26 @@ JavaTurboModule::JavaTurboModule(const InitParams ¶ms)
|
|||
instance_(jni::make_global(params.instance)),
|
||||
nativeInvoker_(params.nativeInvoker) {}
|
||||
|
||||
JavaTurboModule::~JavaTurboModule() {
|
||||
/**
|
||||
* TODO(T75896241): In E2E tests, instance_ is null. Investigate why. Can we
|
||||
* get rid of this null check?
|
||||
*/
|
||||
if (!instance_) {
|
||||
return;
|
||||
}
|
||||
|
||||
nativeInvoker_->invokeAsync([instance = std::move(instance_)]() mutable {
|
||||
/**
|
||||
* Reset the global NativeModule ref on the NativeModules thread. Why:
|
||||
* - ~JavaTurboModule() can be called on a non-JVM thread. If we reset the
|
||||
* global ref in ~JavaTurboModule(), we might access the JVM from a
|
||||
* non-JVM thread, which will crash the app.
|
||||
*/
|
||||
instance.reset();
|
||||
});
|
||||
}
|
||||
|
||||
bool JavaTurboModule::isPromiseAsyncDispatchEnabled_ = false;
|
||||
void JavaTurboModule::enablePromiseAsyncDispatch(bool enable) {
|
||||
isPromiseAsyncDispatchEnabled_ = enable;
|
|
@ -41,6 +41,7 @@ class JSI_EXPORT JavaTurboModule : public TurboModule {
|
|||
};
|
||||
|
||||
JavaTurboModule(const InitParams ¶ms);
|
||||
virtual ~JavaTurboModule();
|
||||
jsi::Value invokeJavaMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
|
@ -171,7 +171,7 @@ convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value,
|
|||
{
|
||||
auto weakWrapper = CallbackWrapper::createWeak(value.getFunction(runtime), runtime, jsInvoker);
|
||||
BOOL __block wrapperWasCalled = NO;
|
||||
return ^(NSArray *responses) {
|
||||
RCTResponseSenderBlock callback = ^(NSArray *responses) {
|
||||
if (wrapperWasCalled) {
|
||||
throw std::runtime_error("callback arg cannot be called more than once");
|
||||
}
|
||||
|
@ -194,6 +194,8 @@ convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value,
|
|||
|
||||
wrapperWasCalled = YES;
|
||||
};
|
||||
|
||||
return [callback copy];
|
||||
}
|
||||
|
||||
namespace facebook {
|
||||
|
@ -331,12 +333,11 @@ jsi::Value ObjCTurboModule::performMethodInvocation(
|
|||
bool wasMethodSync = isMethodSync(returnType);
|
||||
|
||||
void (^block)() = ^{
|
||||
if (!weakModule) {
|
||||
id<RCTTurboModule> strongModule = weakModule;
|
||||
if (!strongModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<RCTTurboModule> strongModule = weakModule;
|
||||
|
||||
if (wasMethodSync) {
|
||||
TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str());
|
||||
} else {
|
||||
|
@ -635,10 +636,13 @@ jsi::Value ObjCTurboModule::invokeObjCMethod(
|
|||
runtime,
|
||||
jsInvoker_,
|
||||
^(RCTPromiseResolveBlock resolveBlock, RCTPromiseRejectBlock rejectBlock) {
|
||||
[inv setArgument:(void *)&resolveBlock atIndex:count + 2];
|
||||
[inv setArgument:(void *)&rejectBlock atIndex:count + 3];
|
||||
[retainedObjectsForInvocation addObject:resolveBlock];
|
||||
[retainedObjectsForInvocation addObject:rejectBlock];
|
||||
RCTPromiseResolveBlock resolveCopy = [resolveBlock copy];
|
||||
RCTPromiseRejectBlock rejectCopy = [rejectBlock copy];
|
||||
|
||||
[inv setArgument:(void *)&resolveCopy atIndex:count + 2];
|
||||
[inv setArgument:(void *)&rejectCopy atIndex:count + 3];
|
||||
[retainedObjectsForInvocation addObject:resolveCopy];
|
||||
[retainedObjectsForInvocation addObject:rejectCopy];
|
||||
// The return type becomes void in the ObjC side.
|
||||
performMethodInvocation(runtime, VoidKind, methodName, inv, retainedObjectsForInvocation);
|
||||
})
|
|
@ -75,6 +75,6 @@ rn_xplat_cxx_library(
|
|||
],
|
||||
exported_deps = [
|
||||
"//xplat/jsi:jsi",
|
||||
react_native_xplat_target("turbomodule/core:core"),
|
||||
react_native_xplat_target("react/nativemodule/core:core"),
|
||||
],
|
||||
)
|
|
@ -191,8 +191,10 @@ void LayoutAnimationDriver::animationMutationsForFrame(
|
|||
|
||||
// Queue up "final" mutations for all keyframes in the completed animation
|
||||
for (auto const &keyframe : animation.keyFrames) {
|
||||
if (!keyframe.invalidated &&
|
||||
keyframe.finalMutationForKeyFrame.hasValue()) {
|
||||
if (keyframe.invalidated) {
|
||||
continue;
|
||||
}
|
||||
if (keyframe.finalMutationForKeyFrame.hasValue()) {
|
||||
auto const &finalMutationForKeyFrame =
|
||||
*keyframe.finalMutationForKeyFrame;
|
||||
PrintMutationInstruction(
|
||||
|
@ -207,6 +209,17 @@ void LayoutAnimationDriver::animationMutationsForFrame(
|
|||
finalMutationForKeyFrame.oldChildShadowView,
|
||||
finalMutationForKeyFrame.newChildShadowView,
|
||||
finalMutationForKeyFrame.index});
|
||||
} else {
|
||||
// Issue a final UPDATE so that the final props object sent to the
|
||||
// mounting layer is the same as the one on the ShadowTree. This is
|
||||
// mostly to make the MountingCoordinator StubViewTree assertions
|
||||
// pass.
|
||||
mutationsList.push_back(
|
||||
ShadowViewMutation{ShadowViewMutation::Type::Update,
|
||||
keyframe.parentView,
|
||||
keyframe.viewStart,
|
||||
keyframe.viewEnd,
|
||||
-1});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace facebook {
|
|||
namespace react {
|
||||
|
||||
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
||||
std::string GetMutationInstructionString(ShadowViewMutation const &mutation) {
|
||||
static std::string GetMutationInstructionString(
|
||||
ShadowViewMutation const &mutation) {
|
||||
bool mutationIsRemove = mutation.type == ShadowViewMutation::Type::Remove;
|
||||
bool mutationIsInsert = mutation.type == ShadowViewMutation::Type::Insert;
|
||||
bool mutationIsDelete = mutation.type == ShadowViewMutation::Type::Delete;
|
||||
|
@ -1253,7 +1254,10 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|||
<< "Adjust delayed mutations based on finalConflictingMutations";
|
||||
#endif
|
||||
for (auto &mutation : finalConflictingMutations) {
|
||||
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
||||
if (mutation.type == ShadowViewMutation::Remove ||
|
||||
mutation.type == ShadowViewMutation::Insert) {
|
||||
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust keyframes based on already-delayed, existing animations, before
|
||||
|
|
|
@ -68,7 +68,9 @@ void TouchEventEmitter::onTouchStart(TouchEvent const &event) const {
|
|||
}
|
||||
|
||||
void TouchEventEmitter::onTouchMove(TouchEvent const &event) const {
|
||||
dispatchTouchEvent("touchMove", event, EventPriority::AsynchronousBatched);
|
||||
dispatchUniqueEvent("touchMove", [event](jsi::Runtime &runtime) {
|
||||
return touchEventPayload(runtime, event);
|
||||
});
|
||||
}
|
||||
|
||||
void TouchEventEmitter::onTouchEnd(TouchEvent const &event) const {
|
||||
|
|
|
@ -46,16 +46,31 @@ void ViewEventEmitter::onLayout(const LayoutMetrics &layoutMetrics) const {
|
|||
lastLayoutMetrics_ = layoutMetrics;
|
||||
}
|
||||
|
||||
dispatchEvent("layout", [frame = layoutMetrics.frame](jsi::Runtime &runtime) {
|
||||
auto layout = jsi::Object(runtime);
|
||||
layout.setProperty(runtime, "x", frame.origin.x);
|
||||
layout.setProperty(runtime, "y", frame.origin.y);
|
||||
layout.setProperty(runtime, "width", frame.size.width);
|
||||
layout.setProperty(runtime, "height", frame.size.height);
|
||||
auto payload = jsi::Object(runtime);
|
||||
payload.setProperty(runtime, "layout", std::move(layout));
|
||||
return payload;
|
||||
});
|
||||
std::atomic_uint_fast8_t *eventCounter = &eventCounter_;
|
||||
uint_fast8_t expectedEventCount = ++*eventCounter;
|
||||
|
||||
// dispatchUniqueEvent only drops consecutive onLayout events to the same
|
||||
// node. We want to drop *any* unprocessed onLayout events when there's a
|
||||
// newer one.
|
||||
dispatchEvent(
|
||||
"layout",
|
||||
[frame = layoutMetrics.frame, expectedEventCount, eventCounter](
|
||||
jsi::Runtime &runtime) {
|
||||
uint_fast8_t actualEventCount = eventCounter->load();
|
||||
if (expectedEventCount != actualEventCount) {
|
||||
// Drop stale events
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
auto layout = jsi::Object(runtime);
|
||||
layout.setProperty(runtime, "x", frame.origin.x);
|
||||
layout.setProperty(runtime, "y", frame.origin.y);
|
||||
layout.setProperty(runtime, "width", frame.size.width);
|
||||
layout.setProperty(runtime, "height", frame.size.height);
|
||||
auto payload = jsi::Object(runtime);
|
||||
payload.setProperty(runtime, "layout", std::move(layout));
|
||||
return jsi::Value(std::move(payload));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -40,6 +40,7 @@ class ViewEventEmitter : public TouchEventEmitter {
|
|||
private:
|
||||
mutable std::mutex layoutMetricsMutex_;
|
||||
mutable LayoutMetrics lastLayoutMetrics_;
|
||||
mutable std::atomic_uint_fast8_t eventCounter_{0};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -14,7 +14,7 @@ using Tag = EventTarget::Tag;
|
|||
|
||||
EventTarget::EventTarget(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &instanceHandle,
|
||||
jsi::Value const &instanceHandle,
|
||||
Tag tag)
|
||||
: weakInstanceHandle_(
|
||||
jsi::WeakObject(runtime, instanceHandle.asObject(runtime))),
|
||||
|
|
|
@ -35,7 +35,7 @@ class EventTarget {
|
|||
/*
|
||||
* Constructs an EventTarget from a weak instance handler and a tag.
|
||||
*/
|
||||
EventTarget(jsi::Runtime &runtime, const jsi::Value &instanceHandle, Tag tag);
|
||||
EventTarget(jsi::Runtime &runtime, jsi::Value const &instanceHandle, Tag tag);
|
||||
|
||||
/*
|
||||
* Sets the `enabled` flag that allows creating a strong instance handle from
|
||||
|
|
|
@ -7,6 +7,7 @@ load(
|
|||
"fb_xplat_cxx_test",
|
||||
"get_apple_compiler_flags",
|
||||
"get_apple_inspector_flags",
|
||||
"react_native_xplat_target",
|
||||
"rn_xplat_cxx_library",
|
||||
"subdir_glob",
|
||||
)
|
||||
|
@ -95,6 +96,7 @@ rn_xplat_cxx_library(
|
|||
tests = [":tests"],
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
react_native_xplat_target("better:better"),
|
||||
"//third-party/glog:glog",
|
||||
"//xplat/fbsystrace:fbsystrace",
|
||||
"//xplat/folly:headers_only",
|
||||
|
|
|
@ -12,28 +12,21 @@ namespace facebook {
|
|||
namespace react {
|
||||
|
||||
SharedColor colorFromComponents(ColorComponents components) {
|
||||
const CGFloat componentsArray[] = {
|
||||
components.red, components.green, components.blue, components.alpha};
|
||||
|
||||
auto color = CGColorCreate(CGColorSpaceCreateDeviceRGB(), componentsArray);
|
||||
|
||||
return SharedColor(color, CGColorRelease);
|
||||
float ratio = 255.9999;
|
||||
return SharedColor(
|
||||
((int)(components.alpha * ratio) & 0xff) << 24 |
|
||||
((int)(components.red * ratio) & 0xff) << 16 |
|
||||
((int)(components.green * ratio) & 0xff) << 8 |
|
||||
((int)(components.blue * ratio) & 0xff));
|
||||
}
|
||||
|
||||
ColorComponents colorComponentsFromColor(SharedColor color) {
|
||||
if (!color) {
|
||||
// Empty color object can be considered as `clear` (black, fully
|
||||
// transparent) color.
|
||||
return ColorComponents{0, 0, 0, 0};
|
||||
}
|
||||
|
||||
auto numberOfComponents __unused = CGColorGetNumberOfComponents(color.get());
|
||||
assert(numberOfComponents == 4);
|
||||
const CGFloat *components = CGColorGetComponents(color.get());
|
||||
return ColorComponents{(float)components[0],
|
||||
(float)components[1],
|
||||
(float)components[2],
|
||||
(float)components[3]};
|
||||
ColorComponents colorComponentsFromColor(SharedColor sharedColor) {
|
||||
float ratio = 256;
|
||||
Color color = *sharedColor;
|
||||
return ColorComponents{(float)((color >> 16) & 0xff) / ratio,
|
||||
(float)((color >> 8) & 0xff) / ratio,
|
||||
(float)((color >> 0) & 0xff) / ratio,
|
||||
(float)((color >> 24) & 0xff) / ratio};
|
||||
}
|
||||
|
||||
SharedColor clearColor() {
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <better/optional.h>
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <react/renderer/graphics/ColorComponents.h>
|
||||
#include <react/renderer/graphics/Float.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using Color = CGColor;
|
||||
using SharedColor = std::shared_ptr<Color>;
|
||||
using Color = int32_t;
|
||||
|
||||
using SharedColor = better::optional<Color>;
|
||||
|
||||
SharedColor colorFromComponents(ColorComponents components);
|
||||
ColorComponents colorComponentsFromColor(SharedColor color);
|
||||
|
|
|
@ -23,13 +23,13 @@ MountingCoordinator::MountingCoordinator(
|
|||
ShadowTreeRevision baseRevision,
|
||||
std::weak_ptr<MountingOverrideDelegate const> delegate,
|
||||
bool enableReparentingDetection)
|
||||
: surfaceId_(baseRevision.getRootShadowNode().getSurfaceId()),
|
||||
: surfaceId_(baseRevision.rootShadowNode->getSurfaceId()),
|
||||
baseRevision_(baseRevision),
|
||||
mountingOverrideDelegate_(delegate),
|
||||
telemetryController_(*this),
|
||||
enableReparentingDetection_(enableReparentingDetection) {
|
||||
#ifdef RN_SHADOW_TREE_INTROSPECTION
|
||||
stubViewTree_ = stubViewTreeFromShadowNode(baseRevision_.getRootShadowNode());
|
||||
stubViewTree_ = stubViewTreeFromShadowNode(*baseRevision_.rootShadowNode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -37,17 +37,15 @@ SurfaceId MountingCoordinator::getSurfaceId() const {
|
|||
return surfaceId_;
|
||||
}
|
||||
|
||||
void MountingCoordinator::push(ShadowTreeRevision &&revision) const {
|
||||
void MountingCoordinator::push(ShadowTreeRevision const &revision) const {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
assert(
|
||||
!lastRevision_.has_value() ||
|
||||
revision.getNumber() != lastRevision_->getNumber());
|
||||
!lastRevision_.has_value() || revision.number != lastRevision_->number);
|
||||
|
||||
if (!lastRevision_.has_value() ||
|
||||
lastRevision_->getNumber() < revision.getNumber()) {
|
||||
lastRevision_ = std::move(revision);
|
||||
if (!lastRevision_.has_value() || lastRevision_->number < revision.number) {
|
||||
lastRevision_ = revision;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +58,7 @@ void MountingCoordinator::revoke() const {
|
|||
// 1. We need to stop retaining `ShadowNode`s to not prolong their lifetime
|
||||
// to prevent them from overliving `ComponentDescriptor`s.
|
||||
// 2. A possible call to `pullTransaction()` should return empty optional.
|
||||
baseRevision_.rootShadowNode_.reset();
|
||||
baseRevision_.rootShadowNode.reset();
|
||||
lastRevision_.reset();
|
||||
}
|
||||
|
||||
|
@ -90,18 +88,17 @@ better::optional<MountingTransaction> MountingCoordinator::pullTransaction()
|
|||
if (lastRevision_.has_value()) {
|
||||
number_++;
|
||||
|
||||
auto telemetry = lastRevision_->getTelemetry();
|
||||
auto telemetry = lastRevision_->telemetry;
|
||||
|
||||
telemetry.willDiff();
|
||||
|
||||
auto mutations = calculateShadowViewMutations(
|
||||
baseRevision_.getRootShadowNode(), lastRevision_->getRootShadowNode());
|
||||
*baseRevision_.rootShadowNode,
|
||||
*lastRevision_->rootShadowNode,
|
||||
enableReparentingDetection_);
|
||||
|
||||
telemetry.didDiff();
|
||||
|
||||
baseRevision_ = std::move(*lastRevision_);
|
||||
lastRevision_.reset();
|
||||
|
||||
transaction = MountingTransaction{
|
||||
surfaceId_, number_, std::move(mutations), telemetry};
|
||||
}
|
||||
|
@ -119,10 +116,13 @@ better::optional<MountingTransaction> MountingCoordinator::pullTransaction()
|
|||
mutations = transaction->getMutations();
|
||||
telemetry = transaction->getTelemetry();
|
||||
} else {
|
||||
number_++;
|
||||
telemetry.willLayout();
|
||||
telemetry.didLayout();
|
||||
telemetry.willCommit();
|
||||
telemetry.didCommit();
|
||||
telemetry.willDiff();
|
||||
telemetry.didDiff();
|
||||
}
|
||||
|
||||
transaction = mountingOverrideDelegate->pullTransaction(
|
||||
|
@ -141,15 +141,17 @@ better::optional<MountingTransaction> MountingCoordinator::pullTransaction()
|
|||
// If the transaction was overridden, we don't have a model of the shadow
|
||||
// tree therefore we cannot validate the validity of the mutation
|
||||
// instructions.
|
||||
if (!shouldOverridePullTransaction) {
|
||||
auto line = std::string{};
|
||||
|
||||
if (!shouldOverridePullTransaction && lastRevision_.has_value()) {
|
||||
auto stubViewTree =
|
||||
stubViewTreeFromShadowNode(baseRevision_.getRootShadowNode());
|
||||
stubViewTreeFromShadowNode(*lastRevision_->rootShadowNode);
|
||||
|
||||
if (stubViewTree_ != stubViewTree) {
|
||||
bool treesEqual = stubViewTree_ == stubViewTree;
|
||||
|
||||
if (!treesEqual) {
|
||||
// Display debug info
|
||||
auto line = std::string{};
|
||||
std::stringstream ssOldTree(
|
||||
baseRevision_.getRootShadowNode().getDebugDescription());
|
||||
baseRevision_.rootShadowNode->getDebugDescription());
|
||||
while (std::getline(ssOldTree, line, '\n')) {
|
||||
LOG(ERROR) << "Old tree:" << line;
|
||||
}
|
||||
|
@ -160,19 +162,21 @@ better::optional<MountingTransaction> MountingCoordinator::pullTransaction()
|
|||
}
|
||||
|
||||
std::stringstream ssNewTree(
|
||||
lastRevision_->getRootShadowNode().getDebugDescription());
|
||||
lastRevision_->rootShadowNode->getDebugDescription());
|
||||
while (std::getline(ssNewTree, line, '\n')) {
|
||||
LOG(ERROR) << "New tree:" << line;
|
||||
}
|
||||
}
|
||||
|
||||
assert(
|
||||
(stubViewTree_ == stubViewTree) &&
|
||||
"Incorrect set of mutations detected.");
|
||||
assert((treesEqual) && "Incorrect set of mutations detected.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lastRevision_.has_value()) {
|
||||
baseRevision_ = std::move(*lastRevision_);
|
||||
lastRevision_.reset();
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ class MountingCoordinator final {
|
|||
private:
|
||||
friend class ShadowTree;
|
||||
|
||||
void push(ShadowTreeRevision &&revision) const;
|
||||
void push(ShadowTreeRevision const &revision) const;
|
||||
|
||||
/*
|
||||
* Revokes the last pushed `ShadowTreeRevision`.
|
||||
|
|
|
@ -237,17 +237,19 @@ ShadowTree::ShadowTree(
|
|||
auto family = rootComponentDescriptor.createFamily(
|
||||
ShadowNodeFamilyFragment{surfaceId, surfaceId, noopEventEmitter},
|
||||
nullptr);
|
||||
rootShadowNode_ = std::static_pointer_cast<const RootShadowNode>(
|
||||
|
||||
auto rootShadowNode = std::static_pointer_cast<const RootShadowNode>(
|
||||
rootComponentDescriptor.createShadowNode(
|
||||
ShadowNodeFragment{
|
||||
/* .props = */ props,
|
||||
},
|
||||
family));
|
||||
|
||||
currentRevision_ = ShadowTreeRevision{
|
||||
rootShadowNode, ShadowTreeRevision::Number{0}, TransactionTelemetry{}};
|
||||
|
||||
mountingCoordinator_ = std::make_shared<MountingCoordinator const>(
|
||||
ShadowTreeRevision{rootShadowNode_, 0, {}},
|
||||
mountingOverrideDelegate,
|
||||
enableReparentingDetection);
|
||||
currentRevision_, mountingOverrideDelegate, enableReparentingDetection);
|
||||
}
|
||||
|
||||
ShadowTree::~ShadowTree() {
|
||||
|
@ -291,15 +293,16 @@ CommitStatus ShadowTree::tryCommit(
|
|||
auto telemetry = TransactionTelemetry{};
|
||||
telemetry.willCommit();
|
||||
|
||||
RootShadowNode::Shared oldRootShadowNode;
|
||||
auto oldRevision = ShadowTreeRevision{};
|
||||
auto newRevision = ShadowTreeRevision{};
|
||||
|
||||
{
|
||||
// Reading `rootShadowNode_` in shared manner.
|
||||
// Reading `currentRevision_` in shared manner.
|
||||
std::shared_lock<better::shared_mutex> lock(commitMutex_);
|
||||
oldRootShadowNode = rootShadowNode_;
|
||||
oldRevision = currentRevision_;
|
||||
}
|
||||
|
||||
RootShadowNode::Unshared newRootShadowNode = transaction(oldRootShadowNode);
|
||||
auto newRootShadowNode = transaction(*oldRevision.rootShadowNode);
|
||||
|
||||
if (!newRootShadowNode) {
|
||||
return CommitStatus::Cancelled;
|
||||
|
@ -307,14 +310,14 @@ CommitStatus ShadowTree::tryCommit(
|
|||
|
||||
if (enableStateReconciliation) {
|
||||
auto updatedNewRootShadowNode =
|
||||
progressState(*newRootShadowNode, *oldRootShadowNode);
|
||||
progressState(*newRootShadowNode, *oldRevision.rootShadowNode);
|
||||
if (updatedNewRootShadowNode) {
|
||||
newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(updatedNewRootShadowNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Layout nodes
|
||||
// Layout nodes.
|
||||
std::vector<LayoutableShadowNode const *> affectedLayoutableNodes{};
|
||||
affectedLayoutableNodes.reserve(1024);
|
||||
|
||||
|
@ -327,48 +330,52 @@ CommitStatus ShadowTree::tryCommit(
|
|||
// Seal the shadow node so it can no longer be mutated
|
||||
newRootShadowNode->sealRecursive();
|
||||
|
||||
auto revisionNumber = ShadowTreeRevision::Number{};
|
||||
|
||||
{
|
||||
// Updating `rootShadowNode_` in unique manner if it hasn't changed.
|
||||
// Updating `currentRevision_` in unique manner if it hasn't changed.
|
||||
std::unique_lock<better::shared_mutex> lock(commitMutex_);
|
||||
|
||||
if (rootShadowNode_ != oldRootShadowNode) {
|
||||
if (currentRevision_.number != oldRevision.number) {
|
||||
return CommitStatus::Failed;
|
||||
}
|
||||
|
||||
rootShadowNode_ = newRootShadowNode;
|
||||
auto newRevisionNumber = oldRevision.number + 1;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> dispatchLock(EventEmitter::DispatchMutex());
|
||||
|
||||
updateMountedFlag(
|
||||
oldRootShadowNode->getChildren(), newRootShadowNode->getChildren());
|
||||
currentRevision_.rootShadowNode->getChildren(),
|
||||
newRootShadowNode->getChildren());
|
||||
}
|
||||
|
||||
revisionNumber_++;
|
||||
revisionNumber = revisionNumber_;
|
||||
telemetry.didCommit();
|
||||
telemetry.setRevisionNumber(newRevisionNumber);
|
||||
|
||||
newRevision =
|
||||
ShadowTreeRevision{newRootShadowNode, newRevisionNumber, telemetry};
|
||||
|
||||
currentRevision_ = newRevision;
|
||||
}
|
||||
|
||||
emitLayoutEvents(affectedLayoutableNodes);
|
||||
|
||||
telemetry.didCommit();
|
||||
telemetry.setRevisionNumber(revisionNumber);
|
||||
|
||||
mountingCoordinator_->push(
|
||||
ShadowTreeRevision{newRootShadowNode, revisionNumber, telemetry});
|
||||
mountingCoordinator_->push(newRevision);
|
||||
|
||||
notifyDelegatesOfUpdates();
|
||||
|
||||
return CommitStatus::Succeeded;
|
||||
}
|
||||
|
||||
ShadowTreeRevision ShadowTree::getCurrentRevision() const {
|
||||
std::shared_lock<better::shared_mutex> lock(commitMutex_);
|
||||
return currentRevision_;
|
||||
}
|
||||
|
||||
void ShadowTree::commitEmptyTree() const {
|
||||
commit(
|
||||
[](RootShadowNode::Shared const &oldRootShadowNode)
|
||||
-> RootShadowNode::Unshared {
|
||||
[](RootShadowNode const &oldRootShadowNode) -> RootShadowNode::Unshared {
|
||||
return std::make_shared<RootShadowNode>(
|
||||
*oldRootShadowNode,
|
||||
oldRootShadowNode,
|
||||
ShadowNodeFragment{
|
||||
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */ ShadowNode::emptySharedShadowNodeSharedList(),
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace facebook {
|
|||
namespace react {
|
||||
|
||||
using ShadowTreeCommitTransaction = std::function<RootShadowNode::Unshared(
|
||||
RootShadowNode::Shared const &oldRootShadowNode)>;
|
||||
RootShadowNode const &oldRootShadowNode)>;
|
||||
|
||||
/*
|
||||
* Represents the shadow tree and its lifecycle.
|
||||
|
@ -72,6 +72,12 @@ class ShadowTree final {
|
|||
ShadowTreeCommitTransaction transaction,
|
||||
bool enableStateReconciliation = false) const;
|
||||
|
||||
/*
|
||||
* Returns a `ShadowTreeRevision` representing the momentary state of
|
||||
* the `ShadowTree`.
|
||||
*/
|
||||
ShadowTreeRevision getCurrentRevision() const;
|
||||
|
||||
/*
|
||||
* Commit an empty tree (a new `RootShadowNode` with no children).
|
||||
*/
|
||||
|
@ -101,10 +107,7 @@ class ShadowTree final {
|
|||
SurfaceId const surfaceId_;
|
||||
ShadowTreeDelegate const &delegate_;
|
||||
mutable better::shared_mutex commitMutex_;
|
||||
mutable RootShadowNode::Shared
|
||||
rootShadowNode_; // Protected by `commitMutex_`.
|
||||
mutable ShadowTreeRevision::Number revisionNumber_{
|
||||
0}; // Protected by `commitMutex_`.
|
||||
mutable ShadowTreeRevision currentRevision_; // Protected by `commitMutex_`.
|
||||
MountingCoordinator::Shared mountingCoordinator_;
|
||||
bool enableReparentingDetection_{false};
|
||||
};
|
||||
|
|
|
@ -6,29 +6,3 @@
|
|||
*/
|
||||
|
||||
#include "ShadowTreeRevision.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using Number = ShadowTreeRevision::Number;
|
||||
|
||||
ShadowTreeRevision::ShadowTreeRevision(
|
||||
RootShadowNode::Shared const &rootShadowNode,
|
||||
Number number,
|
||||
TransactionTelemetry telemetry)
|
||||
: rootShadowNode_(rootShadowNode), number_(number), telemetry_(telemetry) {}
|
||||
|
||||
TransactionTelemetry const &ShadowTreeRevision::getTelemetry() const {
|
||||
return telemetry_;
|
||||
}
|
||||
|
||||
RootShadowNode const &ShadowTreeRevision::getRootShadowNode() {
|
||||
return *rootShadowNode_;
|
||||
}
|
||||
|
||||
Number ShadowTreeRevision::getNumber() const {
|
||||
return number_;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -30,40 +30,12 @@ class ShadowTreeRevision final {
|
|||
*/
|
||||
using Number = int64_t;
|
||||
|
||||
/*
|
||||
* Creates the object with given root shadow node, revision number and
|
||||
* telemetry.
|
||||
*/
|
||||
ShadowTreeRevision(
|
||||
RootShadowNode::Shared const &rootShadowNode,
|
||||
Number number,
|
||||
TransactionTelemetry telemetry);
|
||||
|
||||
/*
|
||||
* Returns telemetry associated with this revision.
|
||||
*/
|
||||
TransactionTelemetry const &getTelemetry() const;
|
||||
|
||||
/*
|
||||
* Methods from this section are meant to be used by
|
||||
* `MountingOverrideDelegate` only.
|
||||
*/
|
||||
public:
|
||||
RootShadowNode const &getRootShadowNode();
|
||||
|
||||
/*
|
||||
* Methods from this section are meant to be used by `MountingCoordinator`
|
||||
* only.
|
||||
*/
|
||||
private:
|
||||
friend class ShadowTree;
|
||||
friend class MountingCoordinator;
|
||||
|
||||
Number getNumber() const;
|
||||
|
||||
private:
|
||||
RootShadowNode::Shared rootShadowNode_;
|
||||
Number number_;
|
||||
TransactionTelemetry telemetry_;
|
||||
RootShadowNode::Shared rootShadowNode;
|
||||
Number number;
|
||||
TransactionTelemetry telemetry;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -12,18 +12,18 @@
|
|||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using ThreadLocalTransactionTelemetry = ThreadStorage<TransactionTelemetry *>;
|
||||
thread_local TransactionTelemetry *threadLocalTransactionTelemetry = nullptr;
|
||||
|
||||
TransactionTelemetry *TransactionTelemetry::threadLocalTelemetry() {
|
||||
return ThreadLocalTransactionTelemetry::getInstance().get().value_or(nullptr);
|
||||
return threadLocalTransactionTelemetry;
|
||||
}
|
||||
|
||||
void TransactionTelemetry::setAsThreadLocal() {
|
||||
ThreadLocalTransactionTelemetry::getInstance().set(this);
|
||||
threadLocalTransactionTelemetry = this;
|
||||
}
|
||||
|
||||
void TransactionTelemetry::unsetAsThreadLocal() {
|
||||
ThreadLocalTransactionTelemetry::getInstance().set(nullptr);
|
||||
threadLocalTransactionTelemetry = nullptr;
|
||||
}
|
||||
|
||||
void TransactionTelemetry::willCommit() {
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include <react/utils/Telemetry.h>
|
||||
#include <react/utils/ThreadStorage.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <react/renderer/components/root/RootComponentDescriptor.h>
|
||||
#include <react/renderer/components/view/ViewComponentDescriptor.h>
|
||||
#include <react/renderer/mounting/ShadowViewMutation.h>
|
||||
#include <react/renderer/mounting/Differentiator.h>
|
||||
#include <react/renderer/mounting/stubs.h>
|
||||
|
||||
|
@ -102,6 +105,25 @@ static void testShadowNodeTreeLifeCycle(
|
|||
auto mutations = calculateShadowViewMutations(
|
||||
*currentRootNode, *nextRootNode, useFlattener);
|
||||
|
||||
// If using flattener: make sure that in a single frame, a DELETE for a view is not
|
||||
// followed by a CREATE for the same view.
|
||||
if (useFlattener) {
|
||||
std::vector<int> deletedTags{};
|
||||
for (auto const& mutation : mutations) {
|
||||
if (mutation.type == ShadowViewMutation::Type::Delete) {
|
||||
deletedTags.push_back(mutation.oldChildShadowView.tag);
|
||||
}
|
||||
}
|
||||
for (auto const& mutation : mutations) {
|
||||
if (mutation.type == ShadowViewMutation::Type::Create) {
|
||||
if (std::find(deletedTags.begin(), deletedTags.end(), mutation.newChildShadowView.tag) != deletedTags.end()) {
|
||||
LOG(ERROR) << "Deleted tag was recreated in mutations list: [" << mutation.newChildShadowView.tag << "]";
|
||||
FAIL();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mutating the view tree.
|
||||
viewTree.mutate(mutations);
|
||||
|
||||
|
|
|
@ -43,16 +43,8 @@ inline ShadowNode const *findDescendantNode(
|
|||
inline ShadowNode const *findDescendantNode(
|
||||
ShadowTree const &shadowTree,
|
||||
ShadowNodeFamily const &family) {
|
||||
ShadowNode const *result = nullptr;
|
||||
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
result = findDescendantNode(*oldRootShadowNode, family);
|
||||
return nullptr;
|
||||
},
|
||||
false);
|
||||
|
||||
return result;
|
||||
return findDescendantNode(
|
||||
*shadowTree.getCurrentRevision().rootShadowNode, family);
|
||||
}
|
||||
|
||||
TEST(StateReconciliationTest, testStateReconciliation) {
|
||||
|
@ -107,7 +99,7 @@ TEST(StateReconciliationTest, testStateReconciliation) {
|
|||
{}};
|
||||
|
||||
shadowTree.commit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(rootShadowNodeState1);
|
||||
},
|
||||
true);
|
||||
|
@ -131,7 +123,7 @@ TEST(StateReconciliationTest, testStateReconciliation) {
|
|||
findDescendantNode(*rootShadowNodeState2, family)->getState(), state2);
|
||||
|
||||
shadowTree.commit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(rootShadowNodeState2);
|
||||
},
|
||||
true);
|
||||
|
@ -153,7 +145,7 @@ TEST(StateReconciliationTest, testStateReconciliation) {
|
|||
findDescendantNode(*rootShadowNodeState3, family)->getState(), state3);
|
||||
|
||||
shadowTree.commit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(rootShadowNodeState3);
|
||||
},
|
||||
true);
|
||||
|
@ -168,7 +160,7 @@ TEST(StateReconciliationTest, testStateReconciliation) {
|
|||
// Here we commit the old tree but we expect that the state associated with
|
||||
// the node will stay the same (newer that the old tree has).
|
||||
shadowTree.commit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(rootShadowNodeState2);
|
||||
},
|
||||
true);
|
||||
|
|
|
@ -110,11 +110,17 @@ Scheduler::Scheduler(
|
|||
"react_fabric:enable_reparenting_detection_android");
|
||||
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
|
||||
"react_fabric:remove_outstanding_surfaces_on_destruction_android");
|
||||
uiManager_->experimentEnableStateUpdateWithAutorepeat =
|
||||
reactNativeConfig_->getBool(
|
||||
"react_fabric:enable_state_update_with_autorepeat_android");
|
||||
#else
|
||||
enableReparentingDetection_ = reactNativeConfig_->getBool(
|
||||
"react_fabric:enable_reparenting_detection_ios");
|
||||
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
|
||||
"react_fabric:remove_outstanding_surfaces_on_destruction_ios");
|
||||
uiManager_->experimentEnableStateUpdateWithAutorepeat =
|
||||
reactNativeConfig_->getBool(
|
||||
"react_fabric:enable_state_update_with_autorepeat_ios");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -220,9 +226,9 @@ void Scheduler::renderTemplateToSurface(
|
|||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [=](const ShadowTree &shadowTree) {
|
||||
return shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::make_shared<RootShadowNode>(
|
||||
*oldRootShadowNode,
|
||||
oldRootShadowNode,
|
||||
ShadowNodeFragment{
|
||||
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */
|
||||
|
@ -272,19 +278,16 @@ Size Scheduler::measureSurface(
|
|||
const LayoutContext &layoutContext) const {
|
||||
SystraceSection s("Scheduler::measureSurface");
|
||||
|
||||
Size size;
|
||||
auto currentRootShadowNode = RootShadowNode::Shared{};
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [&](const ShadowTree &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
auto rootShadowNode =
|
||||
oldRootShadowNode->clone(layoutConstraints, layoutContext);
|
||||
rootShadowNode->layoutIfNeeded();
|
||||
size = rootShadowNode->getLayoutMetrics().frame.size;
|
||||
return nullptr;
|
||||
});
|
||||
currentRootShadowNode = shadowTree.getCurrentRevision().rootShadowNode;
|
||||
});
|
||||
return size;
|
||||
|
||||
auto rootShadowNode =
|
||||
currentRootShadowNode->clone(layoutConstraints, layoutContext);
|
||||
rootShadowNode->layoutIfNeeded();
|
||||
return rootShadowNode->getLayoutMetrics().frame.size;
|
||||
}
|
||||
|
||||
MountingCoordinator::Shared Scheduler::findMountingCoordinator(
|
||||
|
@ -305,8 +308,8 @@ void Scheduler::constraintSurfaceLayout(
|
|||
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.commit([&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
return oldRootShadowNode->clone(layoutConstraints, layoutContext);
|
||||
shadowTree.commit([&](RootShadowNode const &oldRootShadowNode) {
|
||||
return oldRootShadowNode.clone(layoutConstraints, layoutContext);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -96,7 +96,24 @@ inline static NSUnderlineStyle RCTNSUnderlineStyleFromStyleAndPattern(
|
|||
return style;
|
||||
}
|
||||
|
||||
inline static UIColor *RCTUIColorFromSharedColor(const SharedColor &color)
|
||||
inline static UIColor *RCTUIColorFromSharedColor(const SharedColor &sharedColor)
|
||||
{
|
||||
return color ? [UIColor colorWithCGColor:color.get()] : nil;
|
||||
if (!sharedColor) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (*facebook::react::clearColor() == *sharedColor) {
|
||||
return [UIColor clearColor];
|
||||
}
|
||||
|
||||
if (*facebook::react::blackColor() == *sharedColor) {
|
||||
return [UIColor blackColor];
|
||||
}
|
||||
|
||||
if (*facebook::react::whiteColor() == *sharedColor) {
|
||||
return [UIColor whiteColor];
|
||||
}
|
||||
|
||||
auto components = facebook::react::colorComponentsFromColor(sharedColor);
|
||||
return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
|
||||
}
|
||||
|
|
|
@ -97,9 +97,9 @@ void UIManager::completeSurface(
|
|||
|
||||
shadowTreeRegistry_.visit(surfaceId, [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.commit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::make_shared<RootShadowNode>(
|
||||
*oldRootShadowNode,
|
||||
oldRootShadowNode,
|
||||
ShadowNodeFragment{
|
||||
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */ rootChildren,
|
||||
|
@ -139,12 +139,7 @@ ShadowNode::Shared UIManager::getNewestCloneOfShadowNode(
|
|||
auto ancestorShadowNode = ShadowNode::Shared{};
|
||||
shadowTreeRegistry_.visit(
|
||||
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
ancestorShadowNode = oldRootShadowNode;
|
||||
return nullptr;
|
||||
},
|
||||
true);
|
||||
ancestorShadowNode = shadowTree.getCurrentRevision().rootShadowNode;
|
||||
});
|
||||
|
||||
if (!ancestorShadowNode) {
|
||||
|
@ -178,9 +173,9 @@ void UIManager::setNativeProps(
|
|||
shadowTreeRegistry_.visit(
|
||||
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
[&](RootShadowNode const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(
|
||||
oldRootShadowNode->cloneTree(
|
||||
oldRootShadowNode.cloneTree(
|
||||
shadowNode.getFamily(),
|
||||
[&](ShadowNode const &oldShadowNode) {
|
||||
return oldShadowNode.clone({
|
||||
|
@ -205,13 +200,9 @@ LayoutMetrics UIManager::getRelativeLayoutMetrics(
|
|||
if (!ancestorShadowNode) {
|
||||
shadowTreeRegistry_.visit(
|
||||
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
owningAncestorShadowNode = oldRootShadowNode;
|
||||
ancestorShadowNode = oldRootShadowNode.get();
|
||||
return nullptr;
|
||||
},
|
||||
true);
|
||||
owningAncestorShadowNode =
|
||||
shadowTree.getCurrentRevision().rootShadowNode;
|
||||
ancestorShadowNode = owningAncestorShadowNode.get();
|
||||
});
|
||||
} else {
|
||||
// It is possible for JavaScript (or other callers) to have a reference
|
||||
|
@ -240,10 +231,10 @@ void UIManager::updateStateWithAutorepeat(
|
|||
|
||||
shadowTreeRegistry_.visit(
|
||||
family->getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.commit([&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
shadowTree.commit([&](RootShadowNode const &oldRootShadowNode) {
|
||||
auto isValid = true;
|
||||
|
||||
auto rootNode = oldRootShadowNode->cloneTree(
|
||||
auto rootNode = oldRootShadowNode.cloneTree(
|
||||
*family, [&](ShadowNode const &oldShadowNode) {
|
||||
auto newData =
|
||||
callback(oldShadowNode.getState()->getDataPointer());
|
||||
|
@ -272,7 +263,7 @@ void UIManager::updateStateWithAutorepeat(
|
|||
}
|
||||
|
||||
void UIManager::updateState(StateUpdate const &stateUpdate) const {
|
||||
if (stateUpdate.autorepeat) {
|
||||
if (stateUpdate.autorepeat || experimentEnableStateUpdateWithAutorepeat) {
|
||||
updateStateWithAutorepeat(stateUpdate);
|
||||
return;
|
||||
}
|
||||
|
@ -283,10 +274,10 @@ void UIManager::updateState(StateUpdate const &stateUpdate) const {
|
|||
|
||||
shadowTreeRegistry_.visit(
|
||||
family->getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
auto status = shadowTree.tryCommit([&](RootShadowNode::Shared const
|
||||
auto status = shadowTree.tryCommit([&](RootShadowNode const
|
||||
&oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(
|
||||
oldRootShadowNode->cloneTree(
|
||||
oldRootShadowNode.cloneTree(
|
||||
*family, [&](ShadowNode const &oldShadowNode) {
|
||||
auto newData =
|
||||
callback(oldShadowNode.getState()->getDataPointer());
|
||||
|
@ -320,8 +311,8 @@ void UIManager::dispatchCommand(
|
|||
void UIManager::configureNextLayoutAnimation(
|
||||
jsi::Runtime &runtime,
|
||||
RawValue const &config,
|
||||
const jsi::Value &successCallback,
|
||||
const jsi::Value &failureCallback) const {
|
||||
jsi::Value const &successCallback,
|
||||
jsi::Value const &failureCallback) const {
|
||||
if (animationDelegate_) {
|
||||
animationDelegate_->uiManagerDidConfigureNextLayoutAnimation(
|
||||
runtime,
|
||||
|
|
|
@ -73,6 +73,11 @@ class UIManager final : public ShadowTreeDelegate {
|
|||
ShadowTree const &shadowTree,
|
||||
MountingCoordinator::Shared const &mountingCoordinator) const override;
|
||||
|
||||
/*
|
||||
* Temporary flags.
|
||||
*/
|
||||
bool experimentEnableStateUpdateWithAutorepeat{false};
|
||||
|
||||
private:
|
||||
friend class UIManagerBinding;
|
||||
friend class Scheduler;
|
||||
|
@ -142,8 +147,8 @@ class UIManager final : public ShadowTreeDelegate {
|
|||
void configureNextLayoutAnimation(
|
||||
jsi::Runtime &runtime,
|
||||
RawValue const &config,
|
||||
const jsi::Value &successCallback,
|
||||
const jsi::Value &failureCallback) const;
|
||||
jsi::Value const &successCallback,
|
||||
jsi::Value const &failureCallback) const;
|
||||
|
||||
ShadowTreeRegistry const &getShadowTreeRegistry() const;
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ class UIManagerAnimationDelegate {
|
|||
virtual void uiManagerDidConfigureNextLayoutAnimation(
|
||||
jsi::Runtime &runtime,
|
||||
RawValue const &config,
|
||||
const jsi::Value &successCallback,
|
||||
const jsi::Value &failureCallback) const = 0;
|
||||
jsi::Value const &successCallback,
|
||||
jsi::Value const &failureCallback) const = 0;
|
||||
|
||||
/**
|
||||
* Set ComponentDescriptor registry.
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace react {
|
|||
|
||||
static jsi::Object getModule(
|
||||
jsi::Runtime &runtime,
|
||||
const std::string &moduleName) {
|
||||
std::string const &moduleName) {
|
||||
auto batchedBridge =
|
||||
runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge");
|
||||
auto getCallableModule =
|
||||
|
@ -82,8 +82,8 @@ void UIManagerBinding::attach(std::shared_ptr<UIManager> const &uiManager) {
|
|||
void UIManagerBinding::startSurface(
|
||||
jsi::Runtime &runtime,
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initalProps) const {
|
||||
std::string const &moduleName,
|
||||
folly::dynamic const &initalProps) const {
|
||||
folly::dynamic parameters = folly::dynamic::object();
|
||||
parameters["rootTag"] = surfaceId;
|
||||
parameters["initialProps"] = initalProps;
|
||||
|
@ -128,13 +128,18 @@ void UIManagerBinding::stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId)
|
|||
|
||||
void UIManagerBinding::dispatchEvent(
|
||||
jsi::Runtime &runtime,
|
||||
const EventTarget *eventTarget,
|
||||
const std::string &type,
|
||||
const ValueFactory &payloadFactory) const {
|
||||
EventTarget const *eventTarget,
|
||||
std::string const &type,
|
||||
ValueFactory const &payloadFactory) const {
|
||||
SystraceSection s("UIManagerBinding::dispatchEvent");
|
||||
|
||||
auto payload = payloadFactory(runtime);
|
||||
|
||||
// If a payload is null, the factory has decided to cancel the event
|
||||
if (payload.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto instanceHandle = eventTarget
|
||||
? [&]() {
|
||||
auto instanceHandle = eventTarget->getInstanceHandle(runtime);
|
||||
|
@ -153,7 +158,7 @@ void UIManagerBinding::dispatchEvent(
|
|||
: jsi::Value::null();
|
||||
|
||||
auto &eventHandlerWrapper =
|
||||
static_cast<const EventHandlerWrapper &>(*eventHandler_);
|
||||
static_cast<EventHandlerWrapper const &>(*eventHandler_);
|
||||
|
||||
eventHandlerWrapper.callback.call(
|
||||
runtime,
|
||||
|
@ -168,7 +173,7 @@ void UIManagerBinding::invalidate() const {
|
|||
|
||||
jsi::Value UIManagerBinding::get(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::PropNameID &name) {
|
||||
jsi::PropNameID const &name) {
|
||||
auto methodName = name.utf8(runtime);
|
||||
|
||||
// Convert shared_ptr<UIManager> to a raw ptr
|
||||
|
@ -208,9 +213,9 @@ jsi::Value UIManagerBinding::get(
|
|||
5,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->createNode(
|
||||
|
@ -230,9 +235,9 @@ jsi::Value UIManagerBinding::get(
|
|||
1,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(shadowNodeFromValue(runtime, arguments[0])));
|
||||
|
@ -246,9 +251,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->setJSResponder(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
arguments[1].getBool());
|
||||
|
@ -264,9 +269,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto node = shadowNodeFromValue(runtime, arguments[0]);
|
||||
auto locationX = (Float)arguments[1].getNumber();
|
||||
auto locationY = (Float)arguments[2].getNumber();
|
||||
|
@ -294,9 +299,9 @@ jsi::Value UIManagerBinding::get(
|
|||
0,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->clearJSResponder();
|
||||
|
||||
return jsi::Value::undefined();
|
||||
|
@ -311,9 +316,9 @@ jsi::Value UIManagerBinding::get(
|
|||
1,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(
|
||||
|
@ -330,10 +335,10 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
const auto &rawProps = RawProps(runtime, arguments[1]);
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto const &rawProps = RawProps(runtime, arguments[1]);
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(
|
||||
|
@ -351,10 +356,10 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
const auto &rawProps = RawProps(runtime, arguments[1]);
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto const &rawProps = RawProps(runtime, arguments[1]);
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(
|
||||
|
@ -371,9 +376,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->appendChild(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
shadowNodeFromValue(runtime, arguments[1]));
|
||||
|
@ -387,9 +392,9 @@ jsi::Value UIManagerBinding::get(
|
|||
name,
|
||||
1,
|
||||
[](jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto shadowNodeList =
|
||||
std::make_shared<SharedShadowNodeList>(SharedShadowNodeList({}));
|
||||
return valueFromShadowNodeList(runtime, shadowNodeList);
|
||||
|
@ -402,9 +407,9 @@ jsi::Value UIManagerBinding::get(
|
|||
name,
|
||||
2,
|
||||
[](jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto shadowNodeList = shadowNodeListFromValue(runtime, arguments[0]);
|
||||
auto shadowNode = shadowNodeFromValue(runtime, arguments[1]);
|
||||
shadowNodeList->push_back(shadowNode);
|
||||
|
@ -424,29 +429,18 @@ jsi::Value UIManagerBinding::get(
|
|||
jsi::Runtime &runtime,
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
try {
|
||||
auto surfaceId = surfaceIdFromValue(runtime, arguments[0]);
|
||||
auto shadowNodeList =
|
||||
shadowNodeListFromValue(runtime, arguments[1]);
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto surfaceId = surfaceIdFromValue(runtime, arguments[0]);
|
||||
auto shadowNodeList =
|
||||
shadowNodeListFromValue(runtime, arguments[1]);
|
||||
|
||||
if (sharedUIManager->backgroundExecutor_) {
|
||||
sharedUIManager->backgroundExecutor_(
|
||||
[sharedUIManager, surfaceId, shadowNodeList] {
|
||||
sharedUIManager->completeSurface(
|
||||
surfaceId, shadowNodeList);
|
||||
});
|
||||
} else {
|
||||
uiManager->completeSurface(surfaceId, shadowNodeList);
|
||||
}
|
||||
} catch (std::exception const &e) {
|
||||
LOG(ERROR) << "Exception in UIManagerBinding::completeRoot(): "
|
||||
<< e.what();
|
||||
abort();
|
||||
} catch (...) {
|
||||
LOG(ERROR)
|
||||
<< "Exception in UIManagerBinding::completeRoot(): Unknown.";
|
||||
abort();
|
||||
if (sharedUIManager->backgroundExecutor_) {
|
||||
sharedUIManager->backgroundExecutor_(
|
||||
[sharedUIManager, surfaceId, shadowNodeList] {
|
||||
sharedUIManager->completeSurface(surfaceId, shadowNodeList);
|
||||
});
|
||||
} else {
|
||||
uiManager->completeSurface(surfaceId, shadowNodeList);
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
|
@ -462,20 +456,10 @@ jsi::Value UIManagerBinding::get(
|
|||
jsi::Runtime &runtime,
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
try {
|
||||
uiManager->completeSurface(
|
||||
surfaceIdFromValue(runtime, arguments[0]),
|
||||
shadowNodeListFromValue(runtime, arguments[1]));
|
||||
} catch (std::exception const &e) {
|
||||
LOG(ERROR) << "Exception in UIManagerBinding::completeRoot(): "
|
||||
<< e.what();
|
||||
abort();
|
||||
} catch (...) {
|
||||
LOG(ERROR)
|
||||
<< "Exception in UIManagerBinding::completeRoot(): Unknown.";
|
||||
abort();
|
||||
}
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->completeSurface(
|
||||
surfaceIdFromValue(runtime, arguments[0]),
|
||||
shadowNodeListFromValue(runtime, arguments[1]));
|
||||
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
|
@ -489,9 +473,9 @@ jsi::Value UIManagerBinding::get(
|
|||
1,
|
||||
[this](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto eventHandler =
|
||||
arguments[0].getObject(runtime).getFunction(runtime);
|
||||
eventHandler_ =
|
||||
|
@ -507,9 +491,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
shadowNodeFromValue(runtime, arguments[1]).get(),
|
||||
|
@ -531,9 +515,9 @@ jsi::Value UIManagerBinding::get(
|
|||
3,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->dispatchCommand(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
stringFromValue(runtime, arguments[1]),
|
||||
|
@ -551,9 +535,9 @@ jsi::Value UIManagerBinding::get(
|
|||
4,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
shadowNodeFromValue(runtime, arguments[1]).get(),
|
||||
|
@ -587,9 +571,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
nullptr,
|
||||
|
@ -622,9 +606,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
nullptr,
|
||||
|
@ -657,9 +641,9 @@ jsi::Value UIManagerBinding::get(
|
|||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->setNativeProps(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
RawProps(runtime, arguments[1]));
|
||||
|
@ -675,9 +659,9 @@ jsi::Value UIManagerBinding::get(
|
|||
3,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
jsi::Value const &thisValue,
|
||||
jsi::Value const *arguments,
|
||||
size_t count) noexcept -> jsi::Value {
|
||||
uiManager->configureNextLayoutAnimation(
|
||||
runtime,
|
||||
// TODO: pass in JSI value instead of folly::dynamic to RawValue
|
||||
|
|
|
@ -47,8 +47,8 @@ class UIManagerBinding : public jsi::HostObject {
|
|||
void startSurface(
|
||||
jsi::Runtime &runtime,
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initalProps) const;
|
||||
std::string const &moduleName,
|
||||
folly::dynamic const &initalProps) const;
|
||||
|
||||
/*
|
||||
* Stops React Native Surface with given id.
|
||||
|
@ -62,9 +62,9 @@ class UIManagerBinding : public jsi::HostObject {
|
|||
*/
|
||||
void dispatchEvent(
|
||||
jsi::Runtime &runtime,
|
||||
const EventTarget *eventTarget,
|
||||
const std::string &type,
|
||||
const ValueFactory &payloadFactory) const;
|
||||
EventTarget const *eventTarget,
|
||||
std::string const &type,
|
||||
ValueFactory const &payloadFactory) const;
|
||||
|
||||
/*
|
||||
* Invalidates the binding and underlying UIManager.
|
||||
|
@ -78,11 +78,11 @@ class UIManagerBinding : public jsi::HostObject {
|
|||
/*
|
||||
* `jsi::HostObject` specific overloads.
|
||||
*/
|
||||
jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
|
||||
jsi::Value get(jsi::Runtime &runtime, jsi::PropNameID const &name) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<UIManager> uiManager_;
|
||||
std::unique_ptr<const EventHandler> eventHandler_;
|
||||
std::unique_ptr<EventHandler const> eventHandler_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -42,7 +42,7 @@ struct ShadowNodeListWrapper : public jsi::HostObject {
|
|||
|
||||
inline static ShadowNode::Shared shadowNodeFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
jsi::Value const &value) {
|
||||
return value.getObject(runtime)
|
||||
.getHostObject<ShadowNodeWrapper>(runtime)
|
||||
->shadowNode;
|
||||
|
@ -57,7 +57,7 @@ inline static jsi::Value valueFromShadowNode(
|
|||
|
||||
inline static SharedShadowNodeUnsharedList shadowNodeListFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
jsi::Value const &value) {
|
||||
return value.getObject(runtime)
|
||||
.getHostObject<ShadowNodeListWrapper>(runtime)
|
||||
->shadowNodeList;
|
||||
|
@ -72,31 +72,31 @@ inline static jsi::Value valueFromShadowNodeList(
|
|||
|
||||
inline static SharedEventTarget eventTargetFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &eventTargetValue,
|
||||
const jsi::Value &tagValue) {
|
||||
jsi::Value const &eventTargetValue,
|
||||
jsi::Value const &tagValue) {
|
||||
return std::make_shared<EventTarget>(
|
||||
runtime, eventTargetValue, tagValue.getNumber());
|
||||
}
|
||||
|
||||
inline static Tag tagFromValue(jsi::Runtime &runtime, const jsi::Value &value) {
|
||||
inline static Tag tagFromValue(jsi::Runtime &runtime, jsi::Value const &value) {
|
||||
return (Tag)value.getNumber();
|
||||
}
|
||||
|
||||
inline static SurfaceId surfaceIdFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
jsi::Value const &value) {
|
||||
return (SurfaceId)value.getNumber();
|
||||
}
|
||||
|
||||
inline static std::string stringFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
jsi::Value const &value) {
|
||||
return value.getString(runtime).utf8(runtime);
|
||||
}
|
||||
|
||||
inline static folly::dynamic commandArgsFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
jsi::Value const &value) {
|
||||
return jsi::dynamicFromValue(runtime, value);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
"base64-js": "^1.1.2",
|
||||
"event-target-shim": "^5.0.1",
|
||||
"fbjs-scripts": "^1.1.0",
|
||||
"hermes-engine": "~0.6.0",
|
||||
"hermes-engine": "~0.7.0",
|
||||
"invariant": "^2.2.4",
|
||||
"jsc-android": "^245459.0.0",
|
||||
"metro-babel-register": "0.63.0",
|
||||
|
|
|
@ -383,7 +383,7 @@ def rn_codegen_cxx_modules(
|
|||
],
|
||||
visibility = ["PUBLIC"],
|
||||
exported_deps = [
|
||||
react_native_xplat_target("turbomodule/core:core"),
|
||||
react_native_xplat_target("react/nativemodule/core:core"),
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -510,8 +510,8 @@ SPEC CHECKSUMS:
|
|||
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
|
||||
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
|
||||
DoubleConversion: 2b45d0f8e156a5b02354c8a4062de64d41ccb4e0
|
||||
FBLazyVector: b1685f3e7e72b3e0e03eb9cafa76f44f205986e7
|
||||
FBReactNativeSpec: ac2a4d9bd03d8af7fb4813174428ad6a014e77c0
|
||||
FBLazyVector: 6840df244b2930eadc86dfddd63dd586de8fbf4b
|
||||
FBReactNativeSpec: 6a5b272a87d8fba0a0267169a9c69104a33f4104
|
||||
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
|
||||
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
|
||||
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
|
||||
|
@ -522,33 +522,33 @@ SPEC CHECKSUMS:
|
|||
glog: 789873d01e4b200777d0a09bc23d548446758699
|
||||
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
|
||||
RCT-Folly: 55d0039b24e192081ec0b2257f7bd9f42e382fb7
|
||||
RCTRequired: 205b323c68d5dfd5ce7914ffcbdeae97e24373ea
|
||||
RCTTypeSafety: 6fd50970af7c4e1f684f3e73c61c755747cbcdd3
|
||||
React: b2352d001abc0a4778f0c61687b4cf6d4ae5da41
|
||||
React-callinvoker: 8d01a1ae67805a6dcbf1993897646e18c58f182e
|
||||
React-Core: 588a1f9ff5b745676f75b3ae85423158956b5790
|
||||
React-CoreModules: 51089db7201fd36061945ea3e0950b6cc0d3d46a
|
||||
React-cxxreact: e9af0dd6b2f57a5383c662b18ce7047161a81af0
|
||||
React-jsi: 705b31c0c4ee6c85ec4eab8c34643120e9ed0e94
|
||||
React-jsiexecutor: c09397b4f5ffd8146d26a0df68223e04ee373ca6
|
||||
React-jsinspector: cfa811504e00c2e8e1655ee01eef5b6609a3d841
|
||||
React-perflogger: 0213f3cdfbfb0424ff459b8ecff59946f94b1470
|
||||
React-RCTActionSheet: 06a968c4debb85b326da51c9ef51ad7ab2d8a2ca
|
||||
React-RCTAnimation: 577d84c30d06078a09bfa98bf58d10b6dc921f74
|
||||
React-RCTBlob: 9552ef5af043628d1ab1c90034a33b9fa05dbe68
|
||||
React-RCTImage: 1a85a75849d8d3d624bf2c98585bd578c5c6e368
|
||||
React-RCTLinking: 03d175b4ab363b66e7c043bb8099ff5a13289dba
|
||||
React-RCTNetwork: 297ea48bf5b0306ed575c976d45ddf4b4a6330c6
|
||||
React-RCTPushNotification: 5c92e178eb91bdcdad13c8eb14f7f7939e79c964
|
||||
React-RCTSettings: a95c74817566c5eaec37865d2b22126912c256b2
|
||||
React-RCTTest: cf8c5562b4713ebe315b52e9fa80194e9d4c2d30
|
||||
React-RCTText: 2b28538ca0ce986efa4ec58b830b29f6e9b15149
|
||||
React-RCTVibration: 9a0ea019f241a96817185b7312db86374a016791
|
||||
React-runtimeexecutor: 636c0d7528206f59fbcd5d757341f3a3193257f1
|
||||
RCTRequired: 8aab7fd83973da16ad4a7c320ab60d95daaf3a49
|
||||
RCTTypeSafety: 1b9fcfa91c95a819c8ee11b2d78792a1a0c9f008
|
||||
React: 0d0bbc598d4e4a42c2d8f501e2d85bf68f4b4c58
|
||||
React-callinvoker: 7171dcdb2310bc9843acfd9e9d1ad4432f069343
|
||||
React-Core: f9261d49de3292529f426b0337589cf85cbd2be5
|
||||
React-CoreModules: 6cd34c4feb240e2243a2b766ac42b4922a43f272
|
||||
React-cxxreact: 1d94eae472a7d96512c9616b79755f17b7d9e60d
|
||||
React-jsi: 738aad53cef29cda532eb60393636882b048aa63
|
||||
React-jsiexecutor: 4f307d9cf526c904c6a29a492ee0d0a56a3955ac
|
||||
React-jsinspector: 9a11ad30cee910a8f9af0f93863b3583512ea3ca
|
||||
React-perflogger: 869de521c7b7dbdbb1b0ef973a3c00f7c8046ff8
|
||||
React-RCTActionSheet: a0bd6037f343183655817e8ccfb517d227ce89c6
|
||||
React-RCTAnimation: b89077f33ada3bc4d37b4b431810a90bce548395
|
||||
React-RCTBlob: ee093fdd17bea7fccea6b7798112d70f32e14590
|
||||
React-RCTImage: 6260a130d38065a6b6a0053b066b693b88bfcfb1
|
||||
React-RCTLinking: 455be7c2c9b567d1e8225d28cefbf0d6c3364f85
|
||||
React-RCTNetwork: a1d28da57b4d322b4dfd7c036da4e3fddc220ef1
|
||||
React-RCTPushNotification: 843cd5fdc428814ad09eef327f5e069e2962e5bc
|
||||
React-RCTSettings: 2fd29ce8818a57f6016243ca3857a36dfda3f73a
|
||||
React-RCTTest: f5e9ca6222f647dde3ca536ce5d983da1028cbb8
|
||||
React-RCTText: ae07257137eb22d788947b76d7176418c18d7f8b
|
||||
React-RCTVibration: 96e1d2916264a8787a2a409e9a3dd1ded5f2a404
|
||||
React-runtimeexecutor: 165044764bc0b6176e07f654f57d3c84567107b8
|
||||
React-TurboModuleCxx-RNW: 18bb71af41fe34c8b12a56bef60aae7ee32b0817
|
||||
React-TurboModuleCxx-WinRTPort: 1573ded4b5b79b532ec047684e45824bb7819802
|
||||
ReactCommon: 9eaa82ed36085dedf050938c1caf7ad87c9763ac
|
||||
Yoga: 465347bf1eea8844d3ce34a1564cab46567ae9db
|
||||
React-TurboModuleCxx-WinRTPort: 8a81b72f4adac4e05a468c73e399c32a65bfcee9
|
||||
ReactCommon: f4ea3975534282e48263f282d0d6deb8a7e546a1
|
||||
Yoga: a55415d3b511bbb13a9689678be7e18a6cac73d2
|
||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||
|
||||
PODFILE CHECKSUM: cb260f8f7765c910b68f8267cbd74709f6ae6e54
|
||||
|
|
|
@ -13,7 +13,7 @@ Before running the app, make sure you ran:
|
|||
### Running on iOS
|
||||
|
||||
Both macOS and Xcode are required.
|
||||
|
||||
- `cd packages/rn-tester`
|
||||
- Install [Bundler](https://bundler.io/): `gem install bundler`. We use bundler to install the right version of [CocoaPods](https://cocoapods.org/) locally.
|
||||
- Install Bundler and CocoaPods dependencies: `bundle install && bundle exec pod install`
|
||||
- Open the generated `RNTesterPods.xcworkspace`. This is not checked in, as it is generated by CocoaPods. Do not open `RNTesterPods.xcodeproj` directly.
|
||||
|
|
|
@ -121,6 +121,8 @@ def jscFlavor = 'org.webkit:android-jsc:+'
|
|||
def enableHermes = project.ext.react.get("enableHermes", false);
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
compileOptions {
|
||||
|
|
|
@ -6,6 +6,7 @@ buildscript {
|
|||
minSdkVersion = 19
|
||||
compileSdkVersion = 29
|
||||
targetSdkVersion = 29
|
||||
ndkVersion = "20.1.5948944"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
|
|
|
@ -4680,10 +4680,10 @@ hermes-engine-darwin@~0.5.0:
|
|||
resolved "https://registry.yarnpkg.com/hermes-engine-darwin/-/hermes-engine-darwin-0.5.1.tgz#697ac45c3aa2ea17a18494c9f8898d984c34c060"
|
||||
integrity sha512-+IHmncqIrZfOhUYgmInujJVnTQ5qxjijdKC5ohlHalVj088/H6hnAIGr4nX84HAs1JjLCGLA0xujRfd0WY50wA==
|
||||
|
||||
hermes-engine@~0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.6.0.tgz#82c0738b89afb3253dcc4b322888a8bf0f52930b"
|
||||
integrity sha512-WrKfVJ8zsaTz31GHuoX2rJl7AV85Y9bFQkWhqalbObwPusanSsvU+viByDXccUU3khs9CjLBTm0O6DAH3Yls8g==
|
||||
hermes-engine@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.7.0.tgz#c4a13e09811d7bc975a0662bd2ca7120003d6ef8"
|
||||
integrity sha512-lU9OenFWXXOzYldqn15QvbiD0kDc+uw2arhCOkR+9D+PhrLFcbEqnaXFESgchN77JYEf77KkqXncTZA8aoXw2A==
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.8"
|
||||
|
|
Загрузка…
Ссылка в новой задаче