mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
41
Commits
@@ -179,8 +179,9 @@ jobs:
|
||||
- name: Compress and Rename dSYM
|
||||
if: steps.restore-xcframework.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
tar -cz -f packages/react-native/third-party/Symbols/ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz \
|
||||
packages/react-native/third-party/Symbols/ReactNativeDependencies.framework.dSYM
|
||||
cd packages/react-native/third-party/Symbols/
|
||||
tar -cz -f ../ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz .
|
||||
mv ../ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz ./ReactNativeDependencies${{ matrix.flavor }}.framework.dSYM.tar.gz
|
||||
- name: Upload XCFramework Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
@@ -81,10 +81,147 @@ export {Commands};
|
||||
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_COVERAGE_INVALID = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
// Coverage instrumentation of invalid Commands export - should still fail
|
||||
export const Commands = (cov_1234567890().s[0]++, {
|
||||
hotspotUpdate: () => {},
|
||||
scrollTo: () => {},
|
||||
});
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_COVERAGE_WRONG_FUNCTION = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
// Coverage instrumentation of wrong function call - should fail
|
||||
export const Commands = (cov_abcdef123().s[0]++, someOtherFunction({
|
||||
supportedCommands: ['pause', 'play'],
|
||||
}));
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_COMPLEX_COVERAGE_INVALID = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
// Complex coverage instrumentation with invalid nested structure - should fail
|
||||
export const Commands = (
|
||||
cov_xyz789().f[1]++,
|
||||
cov_xyz789().s[2]++,
|
||||
{
|
||||
pause: (ref) => {},
|
||||
play: (ref) => {},
|
||||
}
|
||||
);
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_COVERAGE_WRONG_NAME = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+pause: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
+play: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
}
|
||||
|
||||
// Coverage instrumentation with correct function but wrong export name - should fail
|
||||
export const WrongName = (cov_wrong123().s[0]++, codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['pause', 'play'],
|
||||
}));
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_COVERAGE_TYPE_CAST_INVALID = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+pause: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
+play: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
}
|
||||
|
||||
// Coverage instrumentation with type cast but wrong function - should fail
|
||||
export const Commands: NativeCommands = (cov_cast123().s[0]++, invalidFunction({
|
||||
supportedCommands: ['pause', 'play'],
|
||||
}));
|
||||
|
||||
export default (codegenNativeComponent<ModuleProps>('Module'): NativeType);
|
||||
`;
|
||||
|
||||
module.exports = {
|
||||
'CommandsExportedWithDifferentNameNativeComponent.js':
|
||||
COMMANDS_EXPORTED_WITH_DIFFERENT_NAME,
|
||||
'CommandsExportedWithShorthandNativeComponent.js':
|
||||
COMMANDS_EXPORTED_WITH_SHORTHAND,
|
||||
'OtherCommandsExportNativeComponent.js': OTHER_COMMANDS_EXPORT,
|
||||
'CommandsWithCoverageInvalidNativeComponent.js':
|
||||
COMMANDS_WITH_COVERAGE_INVALID,
|
||||
'CommandsWithCoverageWrongFunctionNativeComponent.js':
|
||||
COMMANDS_WITH_COVERAGE_WRONG_FUNCTION,
|
||||
'CommandsWithComplexCoverageInvalidNativeComponent.js':
|
||||
COMMANDS_WITH_COMPLEX_COVERAGE_INVALID,
|
||||
'CommandsWithCoverageWrongNameNativeComponent.js':
|
||||
COMMANDS_WITH_COVERAGE_WRONG_NAME,
|
||||
'CommandsWithCoverageTypeCastInvalidNativeComponent.js':
|
||||
COMMANDS_WITH_COVERAGE_TYPE_CAST_INVALID,
|
||||
};
|
||||
|
||||
@@ -59,6 +59,92 @@ export default codegenNativeComponent<ModuleProps>('Module', {
|
||||
});
|
||||
`;
|
||||
|
||||
// Coverage instrumentation test cases - should be recognized as valid
|
||||
const COMMANDS_WITH_SIMPLE_COVERAGE = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+pause: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
+play: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
}
|
||||
|
||||
export const Commands = (cov_1234567890.s[0]++, codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['pause', 'play'],
|
||||
}));
|
||||
|
||||
export default codegenNativeComponent<ModuleProps>('Module');
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_COMPLEX_COVERAGE = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+seek: (viewRef: React.ElementRef<NativeType>, position: number) => void;
|
||||
+stop: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
}
|
||||
|
||||
export const Commands = (
|
||||
cov_abcdef123().f[2]++,
|
||||
cov_abcdef123().s[5]++,
|
||||
codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['seek', 'stop'],
|
||||
})
|
||||
);
|
||||
|
||||
export default codegenNativeComponent<ModuleProps>('Module');
|
||||
`;
|
||||
|
||||
const COMMANDS_WITH_TYPE_CAST_COVERAGE = `
|
||||
// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {NativeComponentType} from 'codegenNativeComponent';
|
||||
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
|}>;
|
||||
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+mute: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
+unmute: (viewRef: React.ElementRef<NativeType>) => void;
|
||||
}
|
||||
|
||||
export const Commands: NativeCommands = (cov_xyz789().s[1]++, codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['mute', 'unmute'],
|
||||
}));
|
||||
|
||||
export default codegenNativeComponent<ModuleProps>('Module');
|
||||
`;
|
||||
|
||||
const FULL_NATIVE_COMPONENT_WITH_TYPE_EXPORT = `
|
||||
// @flow
|
||||
|
||||
@@ -107,4 +193,9 @@ module.exports = {
|
||||
'NotANativeComponent.js': NOT_A_NATIVE_COMPONENT,
|
||||
'FullNativeComponent.js': FULL_NATIVE_COMPONENT,
|
||||
'FullTypedNativeComponent.js': FULL_NATIVE_COMPONENT_WITH_TYPE_EXPORT,
|
||||
'CommandsWithSimpleCoverageNativeComponent.js': COMMANDS_WITH_SIMPLE_COVERAGE,
|
||||
'CommandsWithComplexCoverageNativeComponent.js':
|
||||
COMMANDS_WITH_COMPLEX_COVERAGE,
|
||||
'CommandsWithTypeCastCoverageNativeComponent.js':
|
||||
COMMANDS_WITH_TYPE_CAST_COVERAGE,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,77 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Babel plugin inline view configs can inline config for CommandsWithComplexCoverageNativeComponent.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type { ViewProps } from 'ViewPropTypes';
|
||||
import type { NativeComponentType } from 'codegenNativeComponent';
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps
|
||||
|}>;
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
interface NativeCommands {
|
||||
+seek: (viewRef: React.ElementRef<NativeType>, position: number) => void,
|
||||
+stop: (viewRef: React.ElementRef<NativeType>) => void,
|
||||
}
|
||||
const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
|
||||
let nativeComponentName = 'Module';
|
||||
export const __INTERNAL_VIEW_CONFIG = {
|
||||
uiViewClassName: \\"Module\\",
|
||||
validAttributes: {}
|
||||
};
|
||||
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs can inline config for CommandsWithSimpleCoverageNativeComponent.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type { ViewProps } from 'ViewPropTypes';
|
||||
import type { NativeComponentType } from 'codegenNativeComponent';
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps
|
||||
|}>;
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
interface NativeCommands {
|
||||
+pause: (viewRef: React.ElementRef<NativeType>) => void,
|
||||
+play: (viewRef: React.ElementRef<NativeType>) => void,
|
||||
}
|
||||
const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
|
||||
let nativeComponentName = 'Module';
|
||||
export const __INTERNAL_VIEW_CONFIG = {
|
||||
uiViewClassName: \\"Module\\",
|
||||
validAttributes: {}
|
||||
};
|
||||
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs can inline config for CommandsWithTypeCastCoverageNativeComponent.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
const codegenNativeCommands = require('codegenNativeCommands');
|
||||
const codegenNativeComponent = require('codegenNativeComponent');
|
||||
import type { ViewProps } from 'ViewPropTypes';
|
||||
import type { NativeComponentType } from 'codegenNativeComponent';
|
||||
type ModuleProps = $ReadOnly<{|
|
||||
...ViewProps
|
||||
|}>;
|
||||
type NativeType = NativeComponentType<ModuleProps>;
|
||||
interface NativeCommands {
|
||||
+mute: (viewRef: React.ElementRef<NativeType>) => void,
|
||||
+unmute: (viewRef: React.ElementRef<NativeType>) => void,
|
||||
}
|
||||
const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');
|
||||
let nativeComponentName = 'Module';
|
||||
export const __INTERNAL_VIEW_CONFIG = {
|
||||
uiViewClassName: \\"Module\\",
|
||||
validAttributes: {}
|
||||
};
|
||||
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs can inline config for FullNativeComponent.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
@@ -153,6 +225,61 @@ exports[`Babel plugin inline view configs fails on inline config for CommandsExp
|
||||
24 |"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs fails on inline config for CommandsWithComplexCoverageInvalidNativeComponent.js 1`] = `
|
||||
"/CommandsWithComplexCoverageInvalidNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
|
||||
14 |
|
||||
15 | // Complex coverage instrumentation with invalid nested structure - should fail
|
||||
> 16 | export const Commands = (
|
||||
| ^
|
||||
17 | cov_xyz789().f[1]++,
|
||||
18 | cov_xyz789().s[2]++,
|
||||
19 | {"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageInvalidNativeComponent.js 1`] = `
|
||||
"/CommandsWithCoverageInvalidNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
|
||||
14 |
|
||||
15 | // Coverage instrumentation of invalid Commands export - should still fail
|
||||
> 16 | export const Commands = (cov_1234567890().s[0]++, {
|
||||
| ^
|
||||
17 | hotspotUpdate: () => {},
|
||||
18 | scrollTo: () => {},
|
||||
19 | });"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageTypeCastInvalidNativeComponent.js 1`] = `
|
||||
"/CommandsWithCoverageTypeCastInvalidNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
|
||||
19 |
|
||||
20 | // Coverage instrumentation with type cast but wrong function - should fail
|
||||
> 21 | export const Commands: NativeCommands = (cov_cast123().s[0]++, invalidFunction({
|
||||
| ^
|
||||
22 | supportedCommands: ['pause', 'play'],
|
||||
23 | }));
|
||||
24 |"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageWrongFunctionNativeComponent.js 1`] = `
|
||||
"/CommandsWithCoverageWrongFunctionNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
|
||||
14 |
|
||||
15 | // Coverage instrumentation of wrong function call - should fail
|
||||
> 16 | export const Commands = (cov_abcdef123().s[0]++, someOtherFunction({
|
||||
| ^
|
||||
17 | supportedCommands: ['pause', 'play'],
|
||||
18 | }));
|
||||
19 |"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs fails on inline config for CommandsWithCoverageWrongNameNativeComponent.js 1`] = `
|
||||
"/CommandsWithCoverageWrongNameNativeComponent.js: Native commands must be exported with the name 'Commands'
|
||||
20 |
|
||||
21 | // Coverage instrumentation with correct function but wrong export name - should fail
|
||||
> 22 | export const WrongName = (cov_wrong123().s[0]++, codegenNativeCommands<NativeCommands>({
|
||||
| ^
|
||||
23 | supportedCommands: ['pause', 'play'],
|
||||
24 | }));
|
||||
25 |"
|
||||
`;
|
||||
|
||||
exports[`Babel plugin inline view configs fails on inline config for OtherCommandsExportNativeComponent.js 1`] = `
|
||||
"/OtherCommandsExportNativeComponent.js: 'Commands' is a reserved export and may only be used to export the result of codegenNativeCommands.
|
||||
17 | }
|
||||
|
||||
@@ -102,6 +102,58 @@ function isCodegenDeclaration(declaration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isCodegenNativeCommandsDeclaration(declaration) {
|
||||
if (!declaration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle direct calls: codegenNativeCommands()
|
||||
if (
|
||||
declaration.type === 'CallExpression' &&
|
||||
declaration.callee &&
|
||||
declaration.callee.type === 'Identifier' &&
|
||||
declaration.callee.name === 'codegenNativeCommands'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle coverage instrumentation: (cov_xxx().s[0]++, codegenNativeCommands())
|
||||
if (declaration.type === 'SequenceExpression' && declaration.expressions) {
|
||||
// Get the last expression in the sequence (the actual function call)
|
||||
const lastExpression =
|
||||
declaration.expressions[declaration.expressions.length - 1];
|
||||
// Recursively check if the last expression is a valid codegenNativeCommands call
|
||||
return isCodegenNativeCommandsDeclaration(lastExpression);
|
||||
}
|
||||
|
||||
// Handle Flow type casts: (codegenNativeCommands(): NativeCommands)
|
||||
if (
|
||||
(declaration.type === 'TypeCastExpression' ||
|
||||
declaration.type === 'AsExpression') &&
|
||||
declaration.expression &&
|
||||
declaration.expression.type === 'CallExpression' &&
|
||||
declaration.expression.callee &&
|
||||
declaration.expression.callee.type === 'Identifier' &&
|
||||
declaration.expression.callee.name === 'codegenNativeCommands'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle TypeScript assertions: codegenNativeCommands() as NativeCommands
|
||||
if (
|
||||
declaration.type === 'TSAsExpression' &&
|
||||
declaration.expression &&
|
||||
declaration.expression.type === 'CallExpression' &&
|
||||
declaration.expression.callee &&
|
||||
declaration.expression.callee.type === 'Identifier' &&
|
||||
declaration.expression.callee.name === 'codegenNativeCommands'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = function ({parse, types: t}) {
|
||||
return {
|
||||
pre(state) {
|
||||
@@ -125,12 +177,12 @@ module.exports = function ({parse, types: t}) {
|
||||
const firstDeclaration = path.node.declaration.declarations[0];
|
||||
|
||||
if (firstDeclaration.type === 'VariableDeclarator') {
|
||||
if (
|
||||
firstDeclaration.init &&
|
||||
firstDeclaration.init.type === 'CallExpression' &&
|
||||
firstDeclaration.init.callee.type === 'Identifier' &&
|
||||
firstDeclaration.init.callee.name === 'codegenNativeCommands'
|
||||
) {
|
||||
// Check if this is a valid codegenNativeCommands call, handling type annotations
|
||||
const isValidCommandsExport = isCodegenNativeCommandsDeclaration(
|
||||
firstDeclaration.init,
|
||||
);
|
||||
|
||||
if (isValidCommandsExport) {
|
||||
if (
|
||||
firstDeclaration.id.type === 'Identifier' &&
|
||||
firstDeclaration.id.name !== 'Commands'
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
"peerDependenciesMeta": {
|
||||
"@react-native-community/cli": {
|
||||
"optional": true
|
||||
},
|
||||
"@react-native/metro-config": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -31,9 +31,9 @@ type MiddlewareReturn = {
|
||||
...
|
||||
};
|
||||
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[incompatible-type]
|
||||
const unusedStubWSServer: ws$WebSocketServer = {};
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[incompatible-type]
|
||||
const unusedMiddlewareStub: Server = {};
|
||||
|
||||
const communityMiddlewareFallback = {
|
||||
|
||||
@@ -36,7 +36,7 @@ function handleLaunchArgs(argv: string[]) {
|
||||
});
|
||||
|
||||
// Find an existing window for this app and launch configuration.
|
||||
const existingWindow = BrowserWindow.getAllWindows().find(window => {
|
||||
let frontendWindow = BrowserWindow.getAllWindows().find(window => {
|
||||
const metadata = windowMetadata.get(window);
|
||||
if (!metadata) {
|
||||
return false;
|
||||
@@ -44,41 +44,37 @@ function handleLaunchArgs(argv: string[]) {
|
||||
return metadata.windowKey === windowKey;
|
||||
});
|
||||
|
||||
if (existingWindow) {
|
||||
if (frontendWindow) {
|
||||
// If the window is already visible, flash it.
|
||||
if (existingWindow.isVisible()) {
|
||||
existingWindow.flashFrame(true);
|
||||
if (frontendWindow.isVisible()) {
|
||||
frontendWindow.flashFrame(true);
|
||||
setTimeout(() => {
|
||||
existingWindow.flashFrame(false);
|
||||
frontendWindow.flashFrame(false);
|
||||
}, 1000);
|
||||
}
|
||||
if (process.platform === 'darwin') {
|
||||
app.focus({
|
||||
steal: true,
|
||||
});
|
||||
}
|
||||
existingWindow.focus();
|
||||
return;
|
||||
} else {
|
||||
// Create the browser window.
|
||||
frontendWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
partition: 'persist:react-native-devtools',
|
||||
preload: require.resolve('./preload.js'),
|
||||
},
|
||||
// Icon for Linux
|
||||
icon: path.join(__dirname, 'resources', 'icon.png'),
|
||||
});
|
||||
}
|
||||
|
||||
// Create the browser window.
|
||||
const frontendWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
partition: 'persist:react-native-devtools',
|
||||
preload: require.resolve('./preload.js'),
|
||||
},
|
||||
// Icon for Linux
|
||||
icon: path.join(__dirname, 'resources', 'icon.png'),
|
||||
});
|
||||
|
||||
// Open links in the default browser instead of in new Electron windows.
|
||||
frontendWindow.webContents.setWindowOpenHandler(({url}) => {
|
||||
shell.openExternal(url);
|
||||
return {action: 'deny'};
|
||||
});
|
||||
|
||||
// TODO: If the window contains a live, working frontend instance with a valid connection to the backend,
|
||||
// we should avoid this reload and instead send the frontend a message to handle the launch arguments
|
||||
// dynamically (e.g. update the launch ID for telemetry purposes, handle deeplinking to a specific CDT panel, etc).
|
||||
frontendWindow.loadURL(frontendUrl);
|
||||
|
||||
windowMetadata.set(frontendWindow, {
|
||||
@@ -90,6 +86,7 @@ function handleLaunchArgs(argv: string[]) {
|
||||
steal: true,
|
||||
});
|
||||
}
|
||||
frontendWindow.focus();
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
||||
+15
-15
@@ -58,11 +58,11 @@ class PrepareBoostTaskTest {
|
||||
val boostThirdPartyJniPath = tempFolder.newFolder("boostpath/jni")
|
||||
val output = tempFolder.newFolder("output")
|
||||
val task =
|
||||
createTestTask<PrepareBoostTask> {
|
||||
it.boostPath.setFrom(boostpath)
|
||||
it.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
|
||||
it.boostVersion.set("1.0.0")
|
||||
it.outputDir.set(output)
|
||||
createTestTask<PrepareBoostTask> { task ->
|
||||
task.boostPath.setFrom(boostpath)
|
||||
task.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
|
||||
task.boostVersion.set("1.0.0")
|
||||
task.outputDir.set(output)
|
||||
}
|
||||
File(boostpath, "asm/asm.S").apply {
|
||||
parentFile.mkdirs()
|
||||
@@ -79,11 +79,11 @@ class PrepareBoostTaskTest {
|
||||
val boostThirdPartyJniPath = tempFolder.newFolder("boostpath/jni")
|
||||
val output = tempFolder.newFolder("output")
|
||||
val task =
|
||||
createTestTask<PrepareBoostTask> {
|
||||
it.boostPath.setFrom(boostpath)
|
||||
it.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
|
||||
it.boostVersion.set("1.0.0")
|
||||
it.outputDir.set(output)
|
||||
createTestTask<PrepareBoostTask> { task ->
|
||||
task.boostPath.setFrom(boostpath)
|
||||
task.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
|
||||
task.boostVersion.set("1.0.0")
|
||||
task.outputDir.set(output)
|
||||
}
|
||||
File(boostpath, "boost_1.0.0/boost/config.hpp").apply {
|
||||
parentFile.mkdirs()
|
||||
@@ -100,11 +100,11 @@ class PrepareBoostTaskTest {
|
||||
val boostThirdPartyJniPath = tempFolder.newFolder("boostpath/jni")
|
||||
val output = tempFolder.newFolder("output")
|
||||
val task =
|
||||
createTestTask<PrepareBoostTask> {
|
||||
it.boostPath.setFrom(boostpath)
|
||||
it.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
|
||||
it.boostVersion.set("1.0.0")
|
||||
it.outputDir.set(output)
|
||||
createTestTask<PrepareBoostTask> { task ->
|
||||
task.boostPath.setFrom(boostpath)
|
||||
task.boostThirdPartyJniPath.set(boostThirdPartyJniPath)
|
||||
task.boostVersion.set("1.0.0")
|
||||
task.outputDir.set(output)
|
||||
}
|
||||
File(boostpath, "boost/boost/config.hpp").apply {
|
||||
parentFile.mkdirs()
|
||||
|
||||
+3
-3
@@ -186,9 +186,9 @@ class PreparePrefabHeadersTaskTest {
|
||||
|
||||
val project = createProject(projectDir = tempFolder.root)
|
||||
val task =
|
||||
createTestTask<PreparePrefabHeadersTask>(project = project) {
|
||||
it.outputDir.set(outputDir)
|
||||
it.input.set(listOf(PrefabPreprocessingEntry("sample_library", "boost/" to "")))
|
||||
createTestTask<PreparePrefabHeadersTask>(project = project) { task ->
|
||||
task.outputDir.set(outputDir)
|
||||
task.input.set(listOf(PrefabPreprocessingEntry("sample_library", "boost/" to "")))
|
||||
}
|
||||
|
||||
task.taskAction()
|
||||
|
||||
+2
-2
@@ -59,8 +59,8 @@ internal fun createZip(dest: File, paths: List<String>) {
|
||||
val uri = URI.create("jar:file:$dest")
|
||||
|
||||
FileSystems.newFileSystem(uri, env).use { zipfs ->
|
||||
paths.forEach {
|
||||
val zipEntryPath = zipfs.getPath(it)
|
||||
paths.forEach { path ->
|
||||
val zipEntryPath = zipfs.getPath(path)
|
||||
val zipEntryFolder = zipEntryPath.subpath(0, zipEntryPath.nameCount - 1)
|
||||
Files.createDirectories(zipEntryFolder)
|
||||
Files.createFile(zipEntryPath)
|
||||
|
||||
@@ -47,7 +47,7 @@ it('refuses non-spec compliant colors', () => {
|
||||
expect(normalizeColor('rgb (0, 1, 2)')).toBe(null);
|
||||
expect(normalizeColor('rgba(0 0 0 0.0)')).toBe(null);
|
||||
expect(normalizeColor('hsv(0, 1, 2)')).toBe(null);
|
||||
// $FlowExpectedError - Intentionally malformed argument.
|
||||
// $FlowExpectedError[incompatible-type] - Intentionally malformed argument.
|
||||
expect(normalizeColor({r: 10, g: 10, b: 10})).toBe(null);
|
||||
expect(normalizeColor('hsl(1%, 2, 3)')).toBe(null);
|
||||
expect(normalizeColor('rgb(1%, 2%, 3%)')).toBe(null);
|
||||
|
||||
+1
-1
@@ -218,7 +218,7 @@ const transform /*: BabelTransformer['transform'] */ = ({
|
||||
|
||||
// The result from `transformFromAstSync` can be null (if the file is ignored)
|
||||
if (!result) {
|
||||
/* $FlowFixMe BabelTransformer specifies that the `ast` can never be null but
|
||||
/* $FlowFixMe[incompatible-type] BabelTransformer specifies that the `ast` can never be null but
|
||||
* the function returns here. Discovered when typing `BabelNode`. */
|
||||
return {ast: null};
|
||||
}
|
||||
|
||||
+4
@@ -350,6 +350,8 @@ function setDefaultValue(
|
||||
common.default = ((defaultValue ? defaultValue : 0): number);
|
||||
break;
|
||||
case 'FloatTypeAnnotation':
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
common.default = ((defaultValue === null
|
||||
? null
|
||||
: defaultValue
|
||||
@@ -357,6 +359,8 @@ function setDefaultValue(
|
||||
: 0): number | null);
|
||||
break;
|
||||
case 'BooleanTypeAnnotation':
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
common.default = defaultValue === null ? null : !!defaultValue;
|
||||
break;
|
||||
case 'StringTypeAnnotation':
|
||||
|
||||
@@ -275,7 +275,7 @@ export function formatNativeSpecErrorStore(
|
||||
export function formatDiffSet(summary: DiffSummary): FormattedDiffSummary {
|
||||
const summaryStatus = summary.status;
|
||||
if (summaryStatus === 'ok' || summaryStatus === 'patchable') {
|
||||
// $FlowFixMe I don't think we can ever get in this branch
|
||||
// $FlowFixMe[incompatible-type] I don't think we can ever get in this branch
|
||||
return summary;
|
||||
}
|
||||
const hasteModules = Object.keys(summary.incompatibilityReport);
|
||||
|
||||
@@ -77,6 +77,8 @@ const ActionSheetIOS = {
|
||||
callback: (buttonIndex: number) => void,
|
||||
) {
|
||||
invariant(
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
typeof options === 'object' && options !== null,
|
||||
'Options must be a valid object',
|
||||
);
|
||||
@@ -162,6 +164,8 @@ const ActionSheetIOS = {
|
||||
successCallback: Function | ((success: boolean, method: ?string) => void),
|
||||
) {
|
||||
invariant(
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
typeof options === 'object' && options !== null,
|
||||
'Options must be a valid object',
|
||||
);
|
||||
|
||||
@@ -54,7 +54,8 @@ const AnimatedScrollView: AnimatedComponentType<
|
||||
props.style != null
|
||||
) {
|
||||
return (
|
||||
// $FlowFixMe - It should return an Animated ScrollView but it returns a ScrollView with Animated props applied.
|
||||
// $FlowFixMe[incompatible-type] - It should return an Animated ScrollView but it returns a ScrollView with Animated props applied.
|
||||
// $FlowFixMe[incompatible-variance]
|
||||
<AnimatedScrollViewWithInvertedRefreshControl
|
||||
scrollEventThrottle={0.0001}
|
||||
{...props}
|
||||
|
||||
@@ -14,7 +14,7 @@ import SectionList, {type SectionListProps} from '../../Lists/SectionList';
|
||||
import createAnimatedComponent from '../createAnimatedComponent';
|
||||
import * as React from 'react';
|
||||
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[incompatible-type]
|
||||
export default (createAnimatedComponent(SectionList): component<
|
||||
// $FlowExpectedError[unclear-type]
|
||||
ItemT = any,
|
||||
|
||||
@@ -18,6 +18,8 @@ export class URLSearchParams {
|
||||
}
|
||||
|
||||
constructor(params?: Record<string, string> | string | [string, string][]) {
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
if (params === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1503,7 +1503,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
|
||||
keyboardNeverPersistTaps &&
|
||||
this._keyboardIsDismissible() &&
|
||||
e.target != null &&
|
||||
// $FlowFixMe Error supressed during the migration of HostInstance to ReactNativeElement
|
||||
// $FlowFixMe[incompatible-type] Error supressed during the migration of HostInstance to ReactNativeElement
|
||||
!TextInputState.isTextInput(e.target)
|
||||
) {
|
||||
return true;
|
||||
|
||||
@@ -88,7 +88,7 @@ function focusTextInput(textField: ?HostInstance) {
|
||||
if (textField != null) {
|
||||
const fieldCanBeFocused =
|
||||
currentlyFocusedInputRef !== textField &&
|
||||
// $FlowFixMe - `currentProps` is missing in `NativeMethods`
|
||||
// $FlowFixMe[prop-missing] - `currentProps` is missing in `NativeMethods`
|
||||
textField.currentProps?.editable !== false;
|
||||
|
||||
if (!fieldCanBeFocused) {
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ jest.unmock('../TextInput');
|
||||
throw new Error('Expected `textInputElement` to be non-null');
|
||||
}
|
||||
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[prop-missing]
|
||||
textInputElement.currentProps = textInputElement.props;
|
||||
expect(textInputElement.isFocused()).toBe(false);
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ if (ReactNativeFeatureFlags.reduceDefaultPropsInImage()) {
|
||||
// in order to have a better alignment between platforms in the future.
|
||||
src: sources,
|
||||
source: sources,
|
||||
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
|
||||
/* $FlowFixMe[prop-missing](>=0.78.0 site=react_native_android_fb) This issue was found
|
||||
* when making Flow check .android.js files. */
|
||||
headers: (source?.[0]?.headers || source?.headers: ?{[string]: string}),
|
||||
defaultSource: defaultSource ? defaultSource.uri : null,
|
||||
|
||||
@@ -36,7 +36,7 @@ export function testBadDataWithTypicalItem(): React.Node {
|
||||
key: 1,
|
||||
},
|
||||
];
|
||||
// $FlowExpectedError - bad title type 6, should be string
|
||||
// $FlowExpectedError[incompatible-type] - bad title type 6, should be string
|
||||
return <FlatList renderItem={renderMyListItem} data={data} />;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export function testMissingFieldWithTypicalItem(): React.Node {
|
||||
key: 1,
|
||||
},
|
||||
];
|
||||
// $FlowExpectedError - missing title
|
||||
// $FlowExpectedError[incompatible-type] - missing title
|
||||
return <FlatList renderItem={renderMyListItem} data={data} />;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export function testGoodDataWithBadCustomRenderItemFunction(): React.Node {
|
||||
renderItem={info => (
|
||||
<span>
|
||||
{
|
||||
// $FlowExpectedError - bad widgetCount type 6, should be Object
|
||||
// $FlowExpectedError[prop-missing] - bad widgetCount type 6, should be Object
|
||||
info.item.widget.missingProp
|
||||
}
|
||||
</span>
|
||||
@@ -80,22 +80,26 @@ export function testBadRenderItemFunction(): $ReadOnlyArray<React.Node> {
|
||||
},
|
||||
];
|
||||
return [
|
||||
// $FlowExpectedError - title should be inside `item`
|
||||
// $FlowExpectedError[incompatible-type] - title should be inside `item`
|
||||
// $FlowExpectedError[incompatible-exact]
|
||||
<FlatList renderItem={(info: {title: string}) => <span />} data={data} />,
|
||||
<FlatList
|
||||
// $FlowExpectedError - bad index type string, should be number
|
||||
// $FlowExpectedError[incompatible-type] - bad index type string, should be number
|
||||
// $FlowExpectedError[incompatible-exact]
|
||||
// $FlowExpectedError[unclear-type]
|
||||
renderItem={(info: {item: any, index: string}) => <span />}
|
||||
data={data}
|
||||
/>,
|
||||
<FlatList
|
||||
// $FlowExpectedError - bad title type number, should be string
|
||||
// $FlowExpectedError[incompatible-type] - bad index type string, should be number
|
||||
// $FlowExpectedError[incompatible-exact]
|
||||
renderItem={(info: {item: {title: number}}) => <span />}
|
||||
// $FlowExpectedError - bad title type number, should be string
|
||||
// $FlowExpectedError[incompatible-type] - bad title type number, should be string
|
||||
data={data}
|
||||
/>,
|
||||
// EverythingIsFine
|
||||
<FlatList
|
||||
// $FlowExpectedError - bad title type number, should be string
|
||||
// $FlowExpectedError[incompatible-type] - bad title type number, should be string
|
||||
renderItem={(info: {item: {title: string, ...}, ...}) => <span />}
|
||||
data={data}
|
||||
/>,
|
||||
@@ -104,11 +108,11 @@ export function testBadRenderItemFunction(): $ReadOnlyArray<React.Node> {
|
||||
|
||||
export function testOtherBadProps(): $ReadOnlyArray<React.Node> {
|
||||
return [
|
||||
// $FlowExpectedError - bad numColumns type "lots"
|
||||
// $FlowExpectedError[incompatible-type] - bad numColumns type "lots"
|
||||
<FlatList renderItem={renderMyListItem} data={[]} numColumns="lots" />,
|
||||
// $FlowExpectedError - bad windowSize type "big"
|
||||
// $FlowExpectedError[incompatible-type] - bad windowSize type "big"
|
||||
<FlatList renderItem={renderMyListItem} data={[]} windowSize="big" />,
|
||||
// $FlowExpectedError - missing `data` prop
|
||||
// $FlowExpectedError[incompatible-type] - missing `data` prop
|
||||
<FlatList renderItem={renderMyListItem} />,
|
||||
];
|
||||
}
|
||||
|
||||
+6
-5
@@ -55,12 +55,13 @@ export function testBadRenderItemFunction(): $ReadOnlyArray<React.Node> {
|
||||
];
|
||||
return [
|
||||
<SectionList
|
||||
// $FlowExpectedError - title should be inside `item`
|
||||
// $FlowExpectedError[incompatible-type] - title should be inside `item`
|
||||
renderItem={(info: {title: string, ...}) => <span />}
|
||||
sections={sections}
|
||||
/>,
|
||||
<SectionList
|
||||
// $FlowExpectedError - bad index type string, should be number
|
||||
// $FlowExpectedError[incompatible-type] - bad index type string, should be number
|
||||
// $FlowExpectedError[incompatible-exact]
|
||||
renderItem={(info: {index: string}) => <span />}
|
||||
sections={sections}
|
||||
/>,
|
||||
@@ -78,14 +79,14 @@ export function testBadInheritedDefaultProp(): React.MixedElement {
|
||||
<SectionList
|
||||
renderItem={renderMyListItem}
|
||||
sections={sections}
|
||||
// $FlowExpectedError - bad windowSize type "big"
|
||||
// $FlowExpectedError[incompatible-type] - bad windowSize type "big"
|
||||
windowSize="big"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function testMissingData(): React.MixedElement {
|
||||
// $FlowExpectedError - missing `sections` prop
|
||||
// $FlowExpectedError[incompatible-type] - missing `sections` prop
|
||||
return <SectionList renderItem={renderMyListItem} />;
|
||||
}
|
||||
|
||||
@@ -122,7 +123,7 @@ export function testBadSectionsMetadata(): React.MixedElement {
|
||||
<SectionList
|
||||
renderSectionHeader={renderMyHeader}
|
||||
renderItem={renderMyListItem}
|
||||
/* $FlowExpectedError - section has bad meta data `fooNumber` field of
|
||||
/* $FlowExpectedError[incompatible-type] - section has bad meta data `fooNumber` field of
|
||||
* type string */
|
||||
sections={sections}
|
||||
/>
|
||||
|
||||
Vendored
+2
-2
@@ -58,12 +58,12 @@ export default class ReactFabricHostComponent implements NativeMethods {
|
||||
}
|
||||
|
||||
blur() {
|
||||
// $FlowFixMe - Error supressed during the migration of HostInstance to ReactNativeElement
|
||||
// $FlowFixMe[incompatible-type] - Error supressed during the migration of HostInstance to ReactNativeElement
|
||||
TextInputState.blurTextInput(this);
|
||||
}
|
||||
|
||||
focus() {
|
||||
// $FlowFixMe - Error supressed during the migration of HostInstance to ReactNativeElement
|
||||
// $FlowFixMe[incompatible-type] - Error supressed during the migration of HostInstance to ReactNativeElement
|
||||
TextInputState.focusTextInput(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@ const getMethod: (<MethodName: $Keys<ReactFabricType>>(
|
||||
) => ReactNativeType[MethodName]) = (getRenderer, methodName) => {
|
||||
let cachedImpl;
|
||||
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
return function (arg1, arg2, arg3, arg4, arg5, arg6) {
|
||||
if (cachedImpl == null) {
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[prop-missing]
|
||||
cachedImpl = getRenderer()[methodName];
|
||||
}
|
||||
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[extra-arg]
|
||||
return cachedImpl(arg1, arg2, arg3, arg4, arg5);
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -7,7 +7,7 @@
|
||||
* @noformat
|
||||
* @nolint
|
||||
* @flow strict-local
|
||||
* @generated SignedSource<<83073425aa3f71ced2c8c51f25a25938>>
|
||||
* @generated SignedSource<<1f7876c0dc0b05685a730513dc410236>>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -82,6 +82,8 @@ export function register(name: string, callback: () => ViewConfig): string {
|
||||
typeof callback === 'function',
|
||||
'View config getter callback for component `%s` must be a function (received `%s`)',
|
||||
name,
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
callback === null ? 'null' : typeof callback,
|
||||
);
|
||||
viewConfigCallbacks.set(name, callback);
|
||||
|
||||
@@ -83,6 +83,8 @@ class Share {
|
||||
options?: ShareOptions = {},
|
||||
): Promise<{action: string, activityType: ?string}> {
|
||||
invariant(
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
typeof content === 'object' && content !== null,
|
||||
'Content to share must be a valid object',
|
||||
);
|
||||
@@ -91,6 +93,8 @@ class Share {
|
||||
'At least one of URL or message is required',
|
||||
);
|
||||
invariant(
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
typeof options === 'object' && options !== null,
|
||||
'Options must be a valid object',
|
||||
);
|
||||
|
||||
+3
-3
@@ -37,17 +37,17 @@ export function testGoodCompose() {
|
||||
}
|
||||
|
||||
export function testBadCompose() {
|
||||
// $FlowExpectedError - Incompatible type.
|
||||
// $FlowExpectedError[incompatible-type] - Incompatible type.
|
||||
(StyleSheet.compose(textStyle, textStyle): ImageStyleProp);
|
||||
|
||||
// $FlowExpectedError - Incompatible type.
|
||||
// $FlowExpectedError[incompatible-type] - Incompatible type.
|
||||
(StyleSheet.compose(
|
||||
// $FlowExpectedError - Incompatible type.
|
||||
[textStyle],
|
||||
null,
|
||||
): ImageStyleProp);
|
||||
|
||||
// $FlowExpectedError - Incompatible type.
|
||||
// $FlowExpectedError[incompatible-type] - Incompatible type.
|
||||
(StyleSheet.compose(
|
||||
Math.random() < 0.5 ? textStyle : null,
|
||||
null,
|
||||
|
||||
@@ -69,9 +69,9 @@ export default function processFilter(
|
||||
|
||||
if (amount != null) {
|
||||
const filterFunction = {};
|
||||
// $FlowFixMe The key will be the correct one but flow can't see that.
|
||||
// $FlowFixMe[prop-missing] The key will be the correct one but flow can't see that.
|
||||
filterFunction[camelizedName] = amount;
|
||||
// $FlowFixMe The key will be the correct one but flow can't see that.
|
||||
// $FlowFixMe[incompatible-type] The key will be the correct one but flow can't see that.
|
||||
result.push(filterFunction);
|
||||
} else {
|
||||
// If any primitive is invalid then apply none of the filters. This is how
|
||||
@@ -85,7 +85,7 @@ export default function processFilter(
|
||||
for (const filterFunction of filter) {
|
||||
const [filterName, filterValue] = Object.entries(filterFunction)[0];
|
||||
if (filterName === 'dropShadow') {
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[incompatible-type]
|
||||
const dropShadow = parseDropShadow(filterValue);
|
||||
if (dropShadow == null) {
|
||||
return [];
|
||||
@@ -96,9 +96,9 @@ export default function processFilter(
|
||||
|
||||
if (amount != null) {
|
||||
const resultObject = {};
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[prop-missing]
|
||||
resultObject[filterName] = amount;
|
||||
// $FlowFixMe
|
||||
// $FlowFixMe[incompatible-type]
|
||||
result.push(resultObject);
|
||||
} else {
|
||||
// If any primitive is invalid then apply none of the filters. This is how
|
||||
|
||||
@@ -165,6 +165,8 @@ const HMRClient: HMRClientNativeInterface = {
|
||||
// Moving to top gives errors due to NativeModules not being initialized
|
||||
const DevLoadingView = require('./DevLoadingView').default;
|
||||
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
const serverHost = port !== null && port !== '' ? `${host}:${port}` : host;
|
||||
|
||||
const serverScheme = scheme;
|
||||
|
||||
+2
@@ -33,6 +33,8 @@ function deepFreezeAndThrowOnMutationInDev<T: {...} | Array<mixed>>(
|
||||
if (__DEV__) {
|
||||
if (
|
||||
typeof object !== 'object' ||
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
object === null ||
|
||||
Object.isFrozen(object) ||
|
||||
Object.isSealed(object)
|
||||
|
||||
@@ -232,6 +232,8 @@ const WebSocketInterceptor = {
|
||||
|
||||
_arrayBufferToString(data: string): ArrayBuffer | string {
|
||||
const value = base64.toByteArray(data).buffer;
|
||||
/* $FlowFixMe[invalid-compare] Error discovered during Constant Condition
|
||||
* roll out. See https://fburl.com/workplace/5whu3i34. */
|
||||
if (value === undefined || value === null) {
|
||||
return '(no value)';
|
||||
}
|
||||
|
||||
+5
-5
@@ -106,27 +106,27 @@ describe('listeners', () => {
|
||||
}).not.toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
emitter.addListener('A', null);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
emitter.addListener('A', undefined);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
emitter.addListener('A', 'abc');
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
emitter.addListener('A', 123);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError
|
||||
// $FlowExpectedError[incompatible-type]
|
||||
emitter.addListener('A', 123);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
@@ -415,7 +415,9 @@ CGSize RCTSwitchSize(void)
|
||||
static CGSize rctSwitchSize;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
rctSwitchSize = [UISwitch new].intrinsicContentSize;
|
||||
RCTUnsafeExecuteOnMainQueueSync(^{
|
||||
rctSwitchSize = [UISwitch new].intrinsicContentSize;
|
||||
});
|
||||
});
|
||||
return rctSwitchSize;
|
||||
}
|
||||
|
||||
+17
-4
@@ -230,21 +230,34 @@ static BOOL sIsAccessibilityUsed = NO;
|
||||
scrollView.contentOffset.y,
|
||||
scrollView.frame.size.width,
|
||||
scrollView.frame.size.height);
|
||||
const CGFloat visibleWidth = thresholdRect.size.width;
|
||||
const CGFloat visibleHeight = thresholdRect.size.height;
|
||||
|
||||
if (CGRectOverlaps(targetRect, thresholdRect)) {
|
||||
newMode = RCTVirtualViewModeVisible;
|
||||
} else {
|
||||
auto prerender = false;
|
||||
const CGFloat prerenderRatio = ReactNativeFeatureFlags::virtualViewPrerenderRatio();
|
||||
if (prerenderRatio > 0) {
|
||||
thresholdRect = CGRectInset(
|
||||
thresholdRect, -thresholdRect.size.width * prerenderRatio, -thresholdRect.size.height * prerenderRatio);
|
||||
thresholdRect = CGRectInset(thresholdRect, -visibleWidth * prerenderRatio, -visibleHeight * prerenderRatio);
|
||||
prerender = CGRectOverlaps(targetRect, thresholdRect);
|
||||
}
|
||||
if (prerender) {
|
||||
newMode = RCTVirtualViewModePrerender;
|
||||
} else {
|
||||
newMode = RCTVirtualViewModeHidden;
|
||||
thresholdRect = CGRectZero;
|
||||
const CGFloat hysteresisRatio = ReactNativeFeatureFlags::virtualViewHysteresisRatio();
|
||||
if (_mode.has_value() && hysteresisRatio > 0) {
|
||||
thresholdRect = CGRectInset(thresholdRect, -visibleWidth * hysteresisRatio, -visibleHeight * hysteresisRatio);
|
||||
if (CGRectOverlaps(targetRect, thresholdRect)) {
|
||||
newMode = _mode.value();
|
||||
} else {
|
||||
newMode = RCTVirtualViewModeHidden;
|
||||
thresholdRect = CGRectZero;
|
||||
}
|
||||
} else {
|
||||
newMode = RCTVirtualViewModeHidden;
|
||||
thresholdRect = CGRectZero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -744,34 +744,6 @@ public abstract class com/facebook/react/bridge/GuardedRunnable : java/lang/Runn
|
||||
public abstract fun runGuarded ()V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/bridge/Inspector {
|
||||
public static final field Companion Lcom/facebook/react/bridge/Inspector$Companion;
|
||||
public static final fun connect (ILcom/facebook/react/bridge/Inspector$RemoteConnection;)Lcom/facebook/react/bridge/Inspector$LocalConnection;
|
||||
public static final fun getPages ()Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/bridge/Inspector$Companion {
|
||||
public final fun connect (ILcom/facebook/react/bridge/Inspector$RemoteConnection;)Lcom/facebook/react/bridge/Inspector$LocalConnection;
|
||||
public final fun getPages ()Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/bridge/Inspector$LocalConnection {
|
||||
public final fun disconnect ()V
|
||||
public final fun sendMessage (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/bridge/Inspector$Page {
|
||||
public final fun getId ()I
|
||||
public final fun getTitle ()Ljava/lang/String;
|
||||
public final fun getVM ()Ljava/lang/String;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/bridge/Inspector$RemoteConnection {
|
||||
public abstract fun onDisconnect ()V
|
||||
public abstract fun onMessage (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public class com/facebook/react/bridge/JSApplicationCausedNativeException : java/lang/RuntimeException {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
@@ -1018,10 +990,6 @@ public abstract interface class com/facebook/react/bridge/NotThreadSafeBridgeIdl
|
||||
public abstract fun onTransitionToBridgeIdle ()V
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/bridge/OnBatchCompleteListener {
|
||||
public abstract fun onBatchComplete ()V
|
||||
}
|
||||
|
||||
public abstract interface class com/facebook/react/bridge/PerformanceCounter {
|
||||
public abstract fun getPerformanceCounters ()Ljava/util/Map;
|
||||
public abstract fun profileNextBatch ()V
|
||||
@@ -1863,15 +1831,9 @@ public class com/facebook/react/defaults/DefaultReactActivityDelegate : com/face
|
||||
public final class com/facebook/react/defaults/DefaultReactHost {
|
||||
public static final field INSTANCE Lcom/facebook/react/defaults/DefaultReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;Lcom/facebook/react/runtime/JSRuntimeFactory;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;)Lcom/facebook/react/ReactHost;
|
||||
public static final fun getDefaultReactHost (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Lcom/facebook/react/ReactNativeHost;Lcom/facebook/react/runtime/JSRuntimeFactory;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/runtime/JSRuntimeFactory;ZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
public static synthetic fun getDefaultReactHost$default (Landroid/content/Context;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/List;Lkotlin/jvm/functions/Function1;Lcom/facebook/react/runtime/BindingsInstaller;ILjava/lang/Object;)Lcom/facebook/react/ReactHost;
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/defaults/DefaultReactNativeHost : com/facebook/react/ReactNativeHost {
|
||||
@@ -4368,7 +4330,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b
|
||||
public fun addRootView (Landroid/view/View;Lcom/facebook/react/bridge/WritableMap;)I
|
||||
public fun addUIBlock (Lcom/facebook/react/uimanager/UIBlock;)V
|
||||
public fun addUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V
|
||||
public fun addUIManagerListener (Lcom/facebook/react/uimanager/UIManagerModuleListener;)V
|
||||
public fun clearJSResponder ()V
|
||||
public fun configureNextLayoutAnimation (Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V
|
||||
public static fun createConstants (Ljava/util/List;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map;
|
||||
@@ -4405,7 +4366,6 @@ public class com/facebook/react/uimanager/UIManagerModule : com/facebook/react/b
|
||||
public fun receiveEvent (ILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V
|
||||
public fun removeRootView (I)V
|
||||
public fun removeUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V
|
||||
public fun removeUIManagerListener (Lcom/facebook/react/uimanager/UIManagerModuleListener;)V
|
||||
public fun resolveCustomDirectEventName (Ljava/lang/String;)Ljava/lang/String;
|
||||
public fun resolveRootTagFromReactTag (I)I
|
||||
public fun resolveView (I)Landroid/view/View;
|
||||
@@ -5687,6 +5647,8 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollViewManager :
|
||||
public fun flashScrollIndicators (Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;)V
|
||||
public synthetic fun flashScrollIndicators (Ljava/lang/Object;)V
|
||||
public fun getName ()Ljava/lang/String;
|
||||
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
|
||||
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;)Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;
|
||||
public synthetic fun receiveCommand (Landroid/view/View;ILcom/facebook/react/bridge/ReadableArray;)V
|
||||
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public fun receiveCommand (Lcom/facebook/react/views/scroll/ReactHorizontalScrollView;ILcom/facebook/react/bridge/ReadableArray;)V
|
||||
@@ -5950,6 +5912,8 @@ public class com/facebook/react/views/scroll/ReactScrollViewManager : com/facebo
|
||||
public fun getCommandsMap ()Ljava/util/Map;
|
||||
public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
|
||||
public fun getName ()Ljava/lang/String;
|
||||
public synthetic fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)Landroid/view/View;
|
||||
protected fun prepareToRecycleView (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/scroll/ReactScrollView;)Lcom/facebook/react/views/scroll/ReactScrollView;
|
||||
public synthetic fun receiveCommand (Landroid/view/View;ILcom/facebook/react/bridge/ReadableArray;)V
|
||||
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public fun receiveCommand (Lcom/facebook/react/views/scroll/ReactScrollView;ILcom/facebook/react/bridge/ReadableArray;)V
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge
|
||||
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.jni.HybridData
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
import com.facebook.react.common.ReactConstants
|
||||
|
||||
@DoNotStrip
|
||||
public class Inspector
|
||||
private constructor(@Suppress("NoHungarianNotation") private val mHybridData: HybridData) {
|
||||
|
||||
private external fun getPagesNative(): Array<Page>
|
||||
|
||||
private external fun connectNative(pageId: Int, remote: RemoteConnection): LocalConnection?
|
||||
|
||||
@DoNotStrip
|
||||
public class Page
|
||||
private constructor(private val id: Int, private val title: String, private val vm: String) {
|
||||
public fun getId(): Int = id
|
||||
|
||||
public fun getTitle(): String = title
|
||||
|
||||
public fun getVM(): String = vm
|
||||
|
||||
override fun toString(): String = "Page{id=$id, title='$title'}"
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public interface RemoteConnection {
|
||||
@DoNotStrip public fun onMessage(message: String)
|
||||
|
||||
@DoNotStrip public fun onDisconnect()
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public class LocalConnection
|
||||
private constructor(@Suppress("NoHungarianNotation") private val mHybridData: HybridData) {
|
||||
public external fun sendMessage(message: String)
|
||||
|
||||
public external fun disconnect()
|
||||
}
|
||||
|
||||
public companion object {
|
||||
init {
|
||||
ReactNativeJNISoLoader.staticInit()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun getPages(): List<Page> {
|
||||
return try {
|
||||
instance().getPagesNative().toList()
|
||||
} catch (e: UnsatisfiedLinkError) {
|
||||
FLog.e(ReactConstants.TAG, "Inspector doesn't work in open source yet", e)
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public fun connect(pageId: Int, remote: RemoteConnection): LocalConnection {
|
||||
return try {
|
||||
instance().connectNative(pageId, remote)
|
||||
?: throw IllegalStateException("Can't open failed connection")
|
||||
} catch (e: UnsatisfiedLinkError) {
|
||||
FLog.e(ReactConstants.TAG, "Inspector doesn't work in open source yet", e)
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic private external fun instance(): Inspector
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -189,7 +189,7 @@ internal class JavaMethodWrapper(
|
||||
}
|
||||
|
||||
if (jsArgumentsNeeded != parameters.size()) {
|
||||
throw NativeArgumentsParseException(
|
||||
throw JSApplicationCausedNativeException(
|
||||
"$traceName got ${parameters.size()} arguments, expected $jsArgumentsNeeded"
|
||||
)
|
||||
}
|
||||
@@ -208,7 +208,7 @@ internal class JavaMethodWrapper(
|
||||
i++
|
||||
}
|
||||
} catch (e: UnexpectedNativeTypeException) {
|
||||
throw NativeArgumentsParseException(
|
||||
throw JSApplicationCausedNativeException(
|
||||
"${e.message} (constructing arguments for $traceName at argument index ${
|
||||
getAffectedRange(
|
||||
jsArgumentsConsumed,
|
||||
@@ -218,7 +218,7 @@ internal class JavaMethodWrapper(
|
||||
e,
|
||||
)
|
||||
} catch (e: NullPointerException) {
|
||||
throw NativeArgumentsParseException(
|
||||
throw JSApplicationCausedNativeException(
|
||||
"${e.message} (constructing arguments for $traceName at argument index ${
|
||||
getAffectedRange(
|
||||
jsArgumentsConsumed,
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.bridge
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger
|
||||
|
||||
/** Exception thrown when a native module method call receives unexpected arguments from JS. */
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
@Deprecated(
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING,
|
||||
)
|
||||
internal class NativeArgumentsParseException : JSApplicationCausedNativeException {
|
||||
|
||||
constructor(detailMessage: String) : super(detailMessage)
|
||||
|
||||
constructor(detailMessage: String, throwable: Throwable?) : super(detailMessage, throwable)
|
||||
|
||||
private companion object {
|
||||
init {
|
||||
LegacyArchitectureLogger.assertLegacyArchitecture(
|
||||
"NativeArgumentsParseException",
|
||||
logLevel = LegacyArchitectureLogLevel.ERROR,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,6 +16,6 @@ import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
message = "This class is part of Legacy Architecture and will be removed in a future release",
|
||||
level = DeprecationLevel.WARNING,
|
||||
)
|
||||
public fun interface OnBatchCompleteListener {
|
||||
public fun onBatchComplete()
|
||||
internal fun interface OnBatchCompleteListener {
|
||||
fun onBatchComplete()
|
||||
}
|
||||
|
||||
+2
@@ -7,8 +7,10 @@
|
||||
|
||||
package com.facebook.react.bridge
|
||||
|
||||
import com.facebook.react.common.annotations.internal.InteropLegacyArchitecture
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
@InteropLegacyArchitecture
|
||||
internal object ReactNativeJNISoLoader {
|
||||
|
||||
@JvmStatic
|
||||
|
||||
-167
@@ -35,50 +35,6 @@ import java.lang.Exception
|
||||
public object DefaultReactHost {
|
||||
private var reactHost: ReactHost? = null
|
||||
|
||||
/**
|
||||
* Util function to create a default [ReactHost] to be used in your application. This method is
|
||||
* used by the New App template.
|
||||
*
|
||||
* @param context the Android [Context] to use for creating the [ReactHost]
|
||||
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
|
||||
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
|
||||
* `index.<platform>`
|
||||
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
|
||||
* composed in a `asset://...` URL
|
||||
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
|
||||
* `file://...` URL
|
||||
* @param jsRuntimeFactory the JS engine to use for executing [ReactHost], default to Hermes.
|
||||
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
|
||||
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
|
||||
* modules)
|
||||
*
|
||||
* TODO(T186951312): Should this be @UnstableReactNativeAPI?
|
||||
*/
|
||||
@OptIn(UnstableReactNativeAPI::class)
|
||||
@JvmStatic
|
||||
public fun getDefaultReactHost(
|
||||
context: Context,
|
||||
packageList: List<ReactPackage>,
|
||||
jsMainModulePath: String = "index",
|
||||
jsBundleAssetPath: String = "index",
|
||||
jsBundleFilePath: String? = null,
|
||||
jsRuntimeFactory: JSRuntimeFactory? = null,
|
||||
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
|
||||
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
|
||||
): ReactHost =
|
||||
getDefaultReactHost(
|
||||
context,
|
||||
packageList,
|
||||
jsMainModulePath,
|
||||
jsBundleAssetPath,
|
||||
jsBundleFilePath,
|
||||
jsRuntimeFactory,
|
||||
useDevSupport,
|
||||
cxxReactPackageProviders,
|
||||
{ throw it },
|
||||
null,
|
||||
)
|
||||
|
||||
/**
|
||||
* Util function to create a default [ReactHost] to be used in your application. This method is
|
||||
* used by the New App template.
|
||||
@@ -154,129 +110,6 @@ public object DefaultReactHost {
|
||||
return reactHost as ReactHost
|
||||
}
|
||||
|
||||
/**
|
||||
* Util function to create a default [ReactHost] to be used in your application. This method is
|
||||
* used by the New App template.
|
||||
*
|
||||
* @param context the Android [Context] to use for creating the [ReactHost]
|
||||
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
|
||||
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
|
||||
* `index.<platform>`
|
||||
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
|
||||
* composed in a `asset://...` URL
|
||||
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
|
||||
* `file://...` URL
|
||||
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
|
||||
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
|
||||
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
|
||||
* modules)
|
||||
* @param exceptionHandler Callback that can be used by React Native host applications to react to
|
||||
* exceptions thrown by the internals of React Native.
|
||||
* @param bindingsInstaller that can be used for installing bindings.
|
||||
*/
|
||||
@Deprecated(
|
||||
message = "Use `getDefaultReactHost` with `jsRuntimeFactory` instead",
|
||||
replaceWith =
|
||||
ReplaceWith(
|
||||
"""
|
||||
fun getDefaultReactHost(
|
||||
context: Context,
|
||||
packageList: List<ReactPackage>,
|
||||
jsMainModulePath: String,
|
||||
jsBundleAssetPath: String,
|
||||
jsBundleFilePath: String?,
|
||||
jsRuntimeFactory: JSRuntimeFactory?,
|
||||
useDevSupport: Boolean,
|
||||
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage>,
|
||||
exceptionHandler: (Exception) -> Unit,
|
||||
bindingsInstaller: BindingsInstaller?,
|
||||
): ReactHost
|
||||
"""
|
||||
),
|
||||
)
|
||||
@JvmStatic
|
||||
public fun getDefaultReactHost(
|
||||
context: Context,
|
||||
packageList: List<ReactPackage>,
|
||||
jsMainModulePath: String = "index",
|
||||
jsBundleAssetPath: String = "index",
|
||||
jsBundleFilePath: String? = null,
|
||||
isHermesEnabled: Boolean = true,
|
||||
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
|
||||
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
|
||||
exceptionHandler: (Exception) -> Unit = { throw it },
|
||||
bindingsInstaller: BindingsInstaller? = null,
|
||||
): ReactHost =
|
||||
getDefaultReactHost(
|
||||
context,
|
||||
packageList,
|
||||
jsMainModulePath,
|
||||
jsBundleAssetPath,
|
||||
jsBundleFilePath,
|
||||
HermesInstance(),
|
||||
useDevSupport,
|
||||
cxxReactPackageProviders,
|
||||
exceptionHandler,
|
||||
bindingsInstaller,
|
||||
)
|
||||
|
||||
/**
|
||||
* Util function to create a default [ReactHost] to be used in your application. This method is
|
||||
* used by the New App template.
|
||||
*
|
||||
* @param context the Android [Context] to use for creating the [ReactHost]
|
||||
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
|
||||
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
|
||||
* `index.<platform>`
|
||||
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
|
||||
* composed in a `asset://...` URL
|
||||
* @param jsBundleFilePath the path to the JS bundle on the filesystem. Will be composed in a
|
||||
* `file://...` URL
|
||||
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
|
||||
* @param useDevSupport whether to enable dev support, default to ReactBuildConfig.DEBUG.
|
||||
* @param cxxReactPackageProviders a list of cxxreactpackage providers (to register c++ turbo
|
||||
* modules)
|
||||
*/
|
||||
@Deprecated(
|
||||
message = "Use `getDefaultReactHost` with `jsRuntimeFactory` instead",
|
||||
replaceWith =
|
||||
ReplaceWith(
|
||||
"""
|
||||
fun getDefaultReactHost(
|
||||
context: Context,
|
||||
packageList: List<ReactPackage>,
|
||||
jsMainModulePath: String,
|
||||
jsBundleAssetPath: String,
|
||||
jsBundleFilePath: String?,
|
||||
jsRuntimeFactory: JSRuntimeFactory?,
|
||||
useDevSupport: Boolean,
|
||||
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage>,
|
||||
): ReactHost
|
||||
"""
|
||||
),
|
||||
)
|
||||
@JvmStatic
|
||||
public fun getDefaultReactHost(
|
||||
context: Context,
|
||||
packageList: List<ReactPackage>,
|
||||
jsMainModulePath: String = "index",
|
||||
jsBundleAssetPath: String = "index",
|
||||
jsBundleFilePath: String? = null,
|
||||
isHermesEnabled: Boolean = true,
|
||||
useDevSupport: Boolean = ReactBuildConfig.DEBUG,
|
||||
cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
|
||||
): ReactHost =
|
||||
getDefaultReactHost(
|
||||
context,
|
||||
packageList,
|
||||
jsMainModulePath,
|
||||
jsBundleAssetPath,
|
||||
jsBundleFilePath,
|
||||
HermesInstance(),
|
||||
useDevSupport,
|
||||
cxxReactPackageProviders,
|
||||
)
|
||||
|
||||
/**
|
||||
* Util function to create a default [ReactHost] to be used in your application. This method is
|
||||
* used by the New App template.
|
||||
|
||||
+1
-1
@@ -927,7 +927,7 @@ public abstract class DevSupportManagerBase(
|
||||
devServerHelper.openDebugger(
|
||||
currentReactContext,
|
||||
applicationContext.getString(R.string.catalyst_open_debugger_error),
|
||||
ChromeDevToolsViewKeys.Performance.value,
|
||||
null,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<f162c19a6742ecadd171500ccb918f4b>>
|
||||
* @generated SignedSource<<34c12f5a31aab5bfb874953f1beefef1>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -258,6 +258,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun enableViewRecycling(): Boolean = accessor.enableViewRecycling()
|
||||
|
||||
/**
|
||||
* Enables View Recycling for <ScrollView> via ReactViewGroup/ReactViewManager.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun enableViewRecyclingForScrollView(): Boolean = accessor.enableViewRecyclingForScrollView()
|
||||
|
||||
/**
|
||||
* Enables View Recycling for <Text> via ReactTextView/ReactTextViewManager.
|
||||
*/
|
||||
@@ -426,6 +432,12 @@ public object ReactNativeFeatureFlags {
|
||||
@JvmStatic
|
||||
public fun useTurboModules(): Boolean = accessor.useTurboModules()
|
||||
|
||||
/**
|
||||
* Sets a hysteresis window for transition between prerender and hidden modes.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun virtualViewHysteresisRatio(): Double = accessor.virtualViewHysteresisRatio()
|
||||
|
||||
/**
|
||||
* Initial prerender ratio for VirtualView.
|
||||
*/
|
||||
|
||||
+21
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<51bb91fd70ba266c01bf46b3ca237ad5>>
|
||||
* @generated SignedSource<<392da016e0bf4193b72c44a508811e10>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -58,6 +58,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var enableResourceTimingAPICache: Boolean? = null
|
||||
private var enableViewCullingCache: Boolean? = null
|
||||
private var enableViewRecyclingCache: Boolean? = null
|
||||
private var enableViewRecyclingForScrollViewCache: Boolean? = null
|
||||
private var enableViewRecyclingForTextCache: Boolean? = null
|
||||
private var enableViewRecyclingForViewCache: Boolean? = null
|
||||
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
|
||||
@@ -86,6 +87,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
private var useShadowNodeStateOnCloneCache: Boolean? = null
|
||||
private var useTurboModuleInteropCache: Boolean? = null
|
||||
private var useTurboModulesCache: Boolean? = null
|
||||
private var virtualViewHysteresisRatioCache: Double? = null
|
||||
private var virtualViewPrerenderRatioCache: Double? = null
|
||||
|
||||
override fun commonTestFlag(): Boolean {
|
||||
@@ -430,6 +432,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableViewRecyclingForScrollView(): Boolean {
|
||||
var cached = enableViewRecyclingForScrollViewCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.enableViewRecyclingForScrollView()
|
||||
enableViewRecyclingForScrollViewCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableViewRecyclingForText(): Boolean {
|
||||
var cached = enableViewRecyclingForTextCache
|
||||
if (cached == null) {
|
||||
@@ -682,6 +693,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun virtualViewHysteresisRatio(): Double {
|
||||
var cached = virtualViewHysteresisRatioCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.virtualViewHysteresisRatio()
|
||||
virtualViewHysteresisRatioCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun virtualViewPrerenderRatio(): Double {
|
||||
var cached = virtualViewPrerenderRatioCache
|
||||
if (cached == null) {
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<d4a1d4510264580e2f1436b05f1c2f0e>>
|
||||
* @generated SignedSource<<a0453230524ebca2bfb8fad656a6f54a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -104,6 +104,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForScrollView(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForText(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun enableViewRecyclingForView(): Boolean
|
||||
@@ -160,6 +162,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun useTurboModules(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun virtualViewHysteresisRatio(): Double
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun virtualViewPrerenderRatio(): Double
|
||||
|
||||
@DoNotStrip @JvmStatic public external fun override(provider: Any)
|
||||
|
||||
+8
-4
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<4cc61b5f71805589fa91abbdefb5eade>>
|
||||
* @generated SignedSource<<719706a983a073b6c286c49d993f7f80>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -99,6 +99,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun enableViewRecycling(): Boolean = false
|
||||
|
||||
override fun enableViewRecyclingForScrollView(): Boolean = false
|
||||
|
||||
override fun enableViewRecyclingForText(): Boolean = true
|
||||
|
||||
override fun enableViewRecyclingForView(): Boolean = true
|
||||
@@ -139,15 +141,15 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun useFabricInterop(): Boolean = true
|
||||
|
||||
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = false
|
||||
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = true
|
||||
|
||||
override fun useNativeTransformHelperAndroid(): Boolean = false
|
||||
override fun useNativeTransformHelperAndroid(): Boolean = true
|
||||
|
||||
override fun useNativeViewConfigsInBridgelessMode(): Boolean = false
|
||||
|
||||
override fun useOptimizedEventBatchingOnAndroid(): Boolean = false
|
||||
|
||||
override fun useRawPropsJsiValue(): Boolean = false
|
||||
override fun useRawPropsJsiValue(): Boolean = true
|
||||
|
||||
override fun useShadowNodeStateOnClone(): Boolean = false
|
||||
|
||||
@@ -155,5 +157,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
|
||||
|
||||
override fun useTurboModules(): Boolean = false
|
||||
|
||||
override fun virtualViewHysteresisRatio(): Double = 0.0
|
||||
|
||||
override fun virtualViewPrerenderRatio(): Double = 5.0
|
||||
}
|
||||
|
||||
+23
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<78c9ee8f53273560de6b75719e317273>>
|
||||
* @generated SignedSource<<594815ba6a984c460ab8bddd91c5cae2>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -62,6 +62,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var enableResourceTimingAPICache: Boolean? = null
|
||||
private var enableViewCullingCache: Boolean? = null
|
||||
private var enableViewRecyclingCache: Boolean? = null
|
||||
private var enableViewRecyclingForScrollViewCache: Boolean? = null
|
||||
private var enableViewRecyclingForTextCache: Boolean? = null
|
||||
private var enableViewRecyclingForViewCache: Boolean? = null
|
||||
private var enableVirtualViewDebugFeaturesCache: Boolean? = null
|
||||
@@ -90,6 +91,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
private var useShadowNodeStateOnCloneCache: Boolean? = null
|
||||
private var useTurboModuleInteropCache: Boolean? = null
|
||||
private var useTurboModulesCache: Boolean? = null
|
||||
private var virtualViewHysteresisRatioCache: Double? = null
|
||||
private var virtualViewPrerenderRatioCache: Double? = null
|
||||
|
||||
override fun commonTestFlag(): Boolean {
|
||||
@@ -472,6 +474,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableViewRecyclingForScrollView(): Boolean {
|
||||
var cached = enableViewRecyclingForScrollViewCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.enableViewRecyclingForScrollView()
|
||||
accessedFeatureFlags.add("enableViewRecyclingForScrollView")
|
||||
enableViewRecyclingForScrollViewCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun enableViewRecyclingForText(): Boolean {
|
||||
var cached = enableViewRecyclingForTextCache
|
||||
if (cached == null) {
|
||||
@@ -752,6 +764,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun virtualViewHysteresisRatio(): Double {
|
||||
var cached = virtualViewHysteresisRatioCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.virtualViewHysteresisRatio()
|
||||
accessedFeatureFlags.add("virtualViewHysteresisRatio")
|
||||
virtualViewHysteresisRatioCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun virtualViewPrerenderRatio(): Double {
|
||||
var cached = virtualViewPrerenderRatioCache
|
||||
if (cached == null) {
|
||||
|
||||
+1
-5
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<1f89971ab4d5b2ee27ace3a3c8da78cf>>
|
||||
* @generated SignedSource<<4feeb3c1789d8169dd93bee7ae1ff1ac>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -26,8 +26,4 @@ public open class ReactNativeFeatureFlagsOverrides_RNOSS_Experimental_Android :
|
||||
override fun enableAccessibilityOrder(): Boolean = true
|
||||
|
||||
override fun preventShadowTreeCommitExhaustion(): Boolean = true
|
||||
|
||||
override fun useNativeEqualsInNativeReadableArrayAndroid(): Boolean = true
|
||||
|
||||
override fun useNativeTransformHelperAndroid(): Boolean = true
|
||||
}
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<3db9f160e7221eb9c7660a3e93da0f40>>
|
||||
* @generated SignedSource<<dfbd5e84392f1fda0e68324582c328b2>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -99,6 +99,8 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun enableViewRecycling(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableViewRecyclingForScrollView(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableViewRecyclingForText(): Boolean
|
||||
|
||||
@DoNotStrip public fun enableViewRecyclingForView(): Boolean
|
||||
@@ -155,5 +157,7 @@ public interface ReactNativeFeatureFlagsProvider {
|
||||
|
||||
@DoNotStrip public fun useTurboModules(): Boolean
|
||||
|
||||
@DoNotStrip public fun virtualViewHysteresisRatio(): Double
|
||||
|
||||
@DoNotStrip public fun virtualViewPrerenderRatio(): Double
|
||||
}
|
||||
|
||||
+6
@@ -34,6 +34,12 @@ internal class ReactHostInspectorTarget(reactHostImpl: ReactHostImpl) :
|
||||
|
||||
external fun sendDebuggerResumeCommand()
|
||||
|
||||
external fun startBackgroundTrace(): Boolean
|
||||
|
||||
external fun stopAndStashBackgroundTrace()
|
||||
|
||||
external fun stopAndDiscardBackgroundTrace()
|
||||
|
||||
override fun addPerfMonitorListener(listener: PerfMonitorUpdateListener) {
|
||||
perfMonitorListeners.add(listener)
|
||||
}
|
||||
|
||||
-15
@@ -52,7 +52,6 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.facebook.react.uimanager.internal.LegacyArchitectureShadowNodeLogger;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@@ -117,7 +116,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
private final ViewManagerRegistry mViewManagerRegistry;
|
||||
private final UIImplementation mUIImplementation;
|
||||
private final MemoryTrimCallback mMemoryTrimCallback = new MemoryTrimCallback();
|
||||
private final List<UIManagerModuleListener> mListeners = new ArrayList<>();
|
||||
private final CopyOnWriteArrayList<UIManagerListener> mUIManagerListeners =
|
||||
new CopyOnWriteArrayList<>();
|
||||
|
||||
@@ -687,9 +685,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT, "onBatchCompleteUI")
|
||||
.arg("BatchId", batchId)
|
||||
.flush();
|
||||
for (UIManagerModuleListener listener : mListeners) {
|
||||
listener.willDispatchViewUpdates(this);
|
||||
}
|
||||
for (UIManagerListener listener : mUIManagerListeners) {
|
||||
listener.willDispatchViewUpdates(this);
|
||||
}
|
||||
@@ -757,16 +752,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
mUIImplementation.prependUIBlock(block);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void addUIManagerListener(UIManagerModuleListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void removeUIManagerListener(UIManagerModuleListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void addUIManagerEventListener(UIManagerListener listener) {
|
||||
mUIManagerListeners.add(listener);
|
||||
}
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.facebook.react.uimanager
|
||||
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitecture
|
||||
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel
|
||||
|
||||
/** Listener used to hook into the UIManager update process. */
|
||||
@Deprecated("Use UIManagerListener instead. This will be deleted in some future release.")
|
||||
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
||||
internal interface UIManagerModuleListener {
|
||||
/**
|
||||
* Called right before view updates are dispatched at the end of a batch. This is useful if a
|
||||
* module needs to add UIBlocks to the queue before it is flushed.
|
||||
*/
|
||||
fun willDispatchViewUpdates(uiManager: UIManagerModule)
|
||||
}
|
||||
+1
-1
@@ -54,7 +54,7 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
|
||||
* null signals that View Recycling is disabled. `enableViewRecycling` must be explicitly called
|
||||
* in a concrete constructor to enable View Recycling per ViewManager.
|
||||
*/
|
||||
@Nullable private HashMap<Integer, Stack<T>> mRecyclableViews = null;
|
||||
@Nullable private Map<Integer, Stack<T>> mRecyclableViews = null;
|
||||
|
||||
public ViewManager() {
|
||||
super(null);
|
||||
|
||||
+68
-14
@@ -96,8 +96,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper();
|
||||
private final @Nullable OverScroller mScroller;
|
||||
private final VelocityHelper mVelocityHelper = new VelocityHelper();
|
||||
private final Rect mOverflowInset = new Rect();
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollX", 0, 0);
|
||||
|
||||
private Rect mOverflowInset = new Rect();
|
||||
private boolean mActivelyScrolling;
|
||||
private @Nullable Rect mClippingRect;
|
||||
private Overflow mOverflow = Overflow.SCROLL;
|
||||
@@ -118,11 +120,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private boolean mSnapToEnd = true;
|
||||
private int mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
|
||||
private boolean mPagedArrowScrolling = false;
|
||||
private int pendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
private int pendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
private int mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
private int mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
private @Nullable StateWrapper mStateWrapper = null;
|
||||
private final ReactScrollViewScrollState mReactScrollViewScrollState;
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollX", 0, 0);
|
||||
private ReactScrollViewScrollState mReactScrollViewScrollState;
|
||||
private PointerEvents mPointerEvents = PointerEvents.AUTO;
|
||||
private long mLastScrollDispatchTime = 0;
|
||||
private int mScrollEventThrottle = 0;
|
||||
@@ -131,8 +132,6 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private int mFadingEdgeLengthStart = 0;
|
||||
private int mFadingEdgeLengthEnd = 0;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
public ReactHorizontalScrollView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -144,12 +143,67 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate());
|
||||
|
||||
mScroller = getOverScrollerFromParent();
|
||||
mReactScrollViewScrollState = new ReactScrollViewScrollState();
|
||||
|
||||
setOnHierarchyChangeListener(this);
|
||||
setClipChildren(false);
|
||||
initView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all default values here as opposed to in the constructor or field defaults. It is important
|
||||
* that these properties are set during the constructor, but also on-demand whenever an existing
|
||||
* ReactTextView is recycled.
|
||||
*/
|
||||
private void initView() {
|
||||
mOverflowInset = new Rect();
|
||||
mActivelyScrolling = false;
|
||||
mClippingRect = null;
|
||||
mOverflow = Overflow.SCROLL;
|
||||
mDragging = false;
|
||||
mPagingEnabled = false;
|
||||
mPostTouchRunnable = null;
|
||||
mRemoveClippedSubviews = false;
|
||||
mScrollEnabled = true;
|
||||
mSendMomentumEvents = false;
|
||||
mFpsListener = null;
|
||||
mScrollPerfTag = null;
|
||||
mEndBackground = null;
|
||||
mEndFillColor = Color.TRANSPARENT;
|
||||
mDisableIntervalMomentum = false;
|
||||
mSnapInterval = 0;
|
||||
mSnapOffsets = null;
|
||||
mSnapToStart = true;
|
||||
mSnapToEnd = true;
|
||||
mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
|
||||
mPagedArrowScrolling = false;
|
||||
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
mStateWrapper = null;
|
||||
mReactScrollViewScrollState = new ReactScrollViewScrollState();
|
||||
|
||||
mPointerEvents = PointerEvents.AUTO;
|
||||
mLastScrollDispatchTime = 0;
|
||||
mScrollEventThrottle = 0;
|
||||
mContentView = null;
|
||||
mMaintainVisibleContentPositionHelper = null;
|
||||
mFadingEdgeLengthStart = 0;
|
||||
mFadingEdgeLengthEnd = 0;
|
||||
}
|
||||
|
||||
/* package */ void recycleView() {
|
||||
// Set default field values
|
||||
initView();
|
||||
|
||||
// If the view is still attached to a parent, we need to remove it from the parent
|
||||
// before we can recycle it.
|
||||
if (getParent() != null) {
|
||||
((ViewGroup) getParent()).removeView(this);
|
||||
}
|
||||
updateView();
|
||||
}
|
||||
|
||||
private void updateView() {}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
@@ -441,9 +495,9 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
// If a "pending" content offset value has been set, we restore that value.
|
||||
// Upon call to scrollTo, the "pending" values will be re-set.
|
||||
int scrollToX =
|
||||
pendingContentOffsetX != UNSET_CONTENT_OFFSET ? pendingContentOffsetX : getScrollX();
|
||||
mPendingContentOffsetX != UNSET_CONTENT_OFFSET ? mPendingContentOffsetX : getScrollX();
|
||||
int scrollToY =
|
||||
pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY();
|
||||
mPendingContentOffsetY != UNSET_CONTENT_OFFSET ? mPendingContentOffsetY : getScrollY();
|
||||
scrollTo(scrollToX, scrollToY);
|
||||
}
|
||||
|
||||
@@ -1459,11 +1513,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
}
|
||||
|
||||
if (isContentReady()) {
|
||||
pendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
pendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
} else {
|
||||
pendingContentOffsetX = x;
|
||||
pendingContentOffsetY = y;
|
||||
mPendingContentOffsetX = x;
|
||||
mPendingContentOffsetY = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -14,6 +14,7 @@ import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.bridge.ReadableType
|
||||
import com.facebook.react.bridge.RetryableMountingLayerException
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.module.annotations.ReactModule
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderColor
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderRadius
|
||||
@@ -55,6 +56,23 @@ public open class ReactHorizontalScrollViewManager
|
||||
@JvmOverloads
|
||||
constructor(private val fpsListener: FpsListener? = null) :
|
||||
ViewGroupManager<ReactHorizontalScrollView>(), ScrollCommandHandler<ReactHorizontalScrollView> {
|
||||
init {
|
||||
if (ReactNativeFeatureFlags.enableViewRecyclingForScrollView()) {
|
||||
setupViewRecycling()
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareToRecycleView(
|
||||
reactContext: ThemedReactContext,
|
||||
view: ReactHorizontalScrollView,
|
||||
): ReactHorizontalScrollView? {
|
||||
// BaseViewManager
|
||||
val preparedView = super.prepareToRecycleView(reactContext, view)
|
||||
if (preparedView != null) {
|
||||
preparedView.recycleView()
|
||||
}
|
||||
return preparedView
|
||||
}
|
||||
|
||||
override fun getName(): String = REACT_CLASS
|
||||
|
||||
|
||||
+85
-31
@@ -96,43 +96,41 @@ public class ReactScrollView extends ScrollView
|
||||
private final @Nullable OverScroller mScroller;
|
||||
private final VelocityHelper mVelocityHelper = new VelocityHelper();
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final Rect mOverflowInset = new Rect();
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
|
||||
|
||||
private Rect mOverflowInset;
|
||||
private @Nullable VirtualViewContainerState mVirtualViewContainerState;
|
||||
private boolean mActivelyScrolling;
|
||||
private @Nullable Rect mClippingRect;
|
||||
private Overflow mOverflow = Overflow.SCROLL;
|
||||
private Overflow mOverflow;
|
||||
private boolean mDragging;
|
||||
private boolean mPagingEnabled = false;
|
||||
private boolean mPagingEnabled;
|
||||
private @Nullable Runnable mPostTouchRunnable;
|
||||
private boolean mRemoveClippedSubviews;
|
||||
private boolean mScrollEnabled = true;
|
||||
private boolean mScrollEnabled;
|
||||
private boolean mSendMomentumEvents;
|
||||
private @Nullable FpsListener mFpsListener = null;
|
||||
private @Nullable FpsListener mFpsListener;
|
||||
private @Nullable String mScrollPerfTag;
|
||||
private @Nullable Drawable mEndBackground;
|
||||
private int mEndFillColor = Color.TRANSPARENT;
|
||||
private boolean mDisableIntervalMomentum = false;
|
||||
private int mSnapInterval = 0;
|
||||
private int mEndFillColor;
|
||||
private boolean mDisableIntervalMomentum;
|
||||
private int mSnapInterval;
|
||||
private @Nullable List<Integer> mSnapOffsets;
|
||||
private boolean mSnapToStart = true;
|
||||
private boolean mSnapToEnd = true;
|
||||
private int mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
|
||||
private boolean mSnapToStart;
|
||||
private boolean mSnapToEnd;
|
||||
private int mSnapToAlignment;
|
||||
private @Nullable View mContentView;
|
||||
private @Nullable ReadableMap mCurrentContentOffset = null;
|
||||
private int pendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
private int pendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
private @Nullable StateWrapper mStateWrapper = null;
|
||||
private final ReactScrollViewScrollState mReactScrollViewScrollState =
|
||||
new ReactScrollViewScrollState();
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
|
||||
private PointerEvents mPointerEvents = PointerEvents.AUTO;
|
||||
private long mLastScrollDispatchTime = 0;
|
||||
private int mScrollEventThrottle = 0;
|
||||
private @Nullable MaintainVisibleScrollPositionHelper mMaintainVisibleContentPositionHelper =
|
||||
null;
|
||||
private int mFadingEdgeLengthStart = 0;
|
||||
private int mFadingEdgeLengthEnd = 0;
|
||||
private @Nullable ReadableMap mCurrentContentOffset;
|
||||
private int mPendingContentOffsetX;
|
||||
private int mPendingContentOffsetY;
|
||||
private @Nullable StateWrapper mStateWrapper;
|
||||
private ReactScrollViewScrollState mReactScrollViewScrollState;
|
||||
private PointerEvents mPointerEvents;
|
||||
private long mLastScrollDispatchTime;
|
||||
private int mScrollEventThrottle;
|
||||
private @Nullable MaintainVisibleScrollPositionHelper mMaintainVisibleContentPositionHelper;
|
||||
private int mFadingEdgeLengthStart;
|
||||
private int mFadingEdgeLengthEnd;
|
||||
|
||||
public ReactScrollView(Context context) {
|
||||
this(context, null);
|
||||
@@ -148,8 +146,64 @@ public class ReactScrollView extends ScrollView
|
||||
setClipChildren(false);
|
||||
|
||||
ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate());
|
||||
initView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all default values here as opposed to in the constructor or field defaults. It is important
|
||||
* that these properties are set during the constructor, but also on-demand whenever an existing
|
||||
* ReactTextView is recycled.
|
||||
*/
|
||||
private void initView() {
|
||||
mOverflowInset = new Rect();
|
||||
mVirtualViewContainerState = null;
|
||||
mActivelyScrolling = false;
|
||||
mClippingRect = null;
|
||||
mOverflow = Overflow.SCROLL;
|
||||
mDragging = false;
|
||||
mPagingEnabled = false;
|
||||
mPostTouchRunnable = null;
|
||||
mRemoveClippedSubviews = false;
|
||||
mScrollEnabled = true;
|
||||
mSendMomentumEvents = false;
|
||||
mFpsListener = null;
|
||||
mScrollPerfTag = null;
|
||||
mEndBackground = null;
|
||||
mEndFillColor = Color.TRANSPARENT;
|
||||
mDisableIntervalMomentum = false;
|
||||
mSnapInterval = 0;
|
||||
mSnapOffsets = null;
|
||||
mSnapToStart = true;
|
||||
mSnapToEnd = true;
|
||||
mSnapToAlignment = SNAP_ALIGNMENT_DISABLED;
|
||||
mContentView = null;
|
||||
mCurrentContentOffset = null;
|
||||
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
mStateWrapper = null;
|
||||
mReactScrollViewScrollState = new ReactScrollViewScrollState();
|
||||
mPointerEvents = PointerEvents.AUTO;
|
||||
mLastScrollDispatchTime = 0;
|
||||
mScrollEventThrottle = 0;
|
||||
mMaintainVisibleContentPositionHelper = null;
|
||||
mFadingEdgeLengthStart = 0;
|
||||
mFadingEdgeLengthEnd = 0;
|
||||
}
|
||||
|
||||
/* package */ void recycleView() {
|
||||
// Set default field values
|
||||
initView();
|
||||
|
||||
// If the view is still attached to a parent, we need to remove it from the parent
|
||||
// before we can recycle it.
|
||||
if (getParent() != null) {
|
||||
((ViewGroup) getParent()).removeView(this);
|
||||
}
|
||||
updateView();
|
||||
}
|
||||
|
||||
private void updateView() {}
|
||||
|
||||
@Override
|
||||
public VirtualViewContainerState getVirtualViewContainerState() {
|
||||
if (mVirtualViewContainerState == null) {
|
||||
@@ -368,9 +422,9 @@ public class ReactScrollView extends ScrollView
|
||||
// If a "pending" content offset value has been set, we restore that value.
|
||||
// Upon call to scrollTo, the "pending" values will be re-set.
|
||||
int scrollToX =
|
||||
pendingContentOffsetX != UNSET_CONTENT_OFFSET ? pendingContentOffsetX : getScrollX();
|
||||
mPendingContentOffsetX != UNSET_CONTENT_OFFSET ? mPendingContentOffsetX : getScrollX();
|
||||
int scrollToY =
|
||||
pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY();
|
||||
mPendingContentOffsetY != UNSET_CONTENT_OFFSET ? mPendingContentOffsetY : getScrollY();
|
||||
scrollTo(scrollToX, scrollToY);
|
||||
}
|
||||
|
||||
@@ -1269,11 +1323,11 @@ public class ReactScrollView extends ScrollView
|
||||
*/
|
||||
private void setPendingContentOffsets(int x, int y) {
|
||||
if (isContentReady()) {
|
||||
pendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
pendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
mPendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
mPendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
} else {
|
||||
pendingContentOffsetX = x;
|
||||
pendingContentOffsetY = y;
|
||||
mPendingContentOffsetX = x;
|
||||
mPendingContentOffsetY = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -15,6 +15,7 @@ import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.bridge.ReadableType
|
||||
import com.facebook.react.bridge.RetryableMountingLayerException
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
import com.facebook.react.module.annotations.ReactModule
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderColor
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderRadius
|
||||
@@ -56,6 +57,24 @@ public open class ReactScrollViewManager
|
||||
constructor(private val fpsListener: FpsListener? = null) :
|
||||
ViewGroupManager<ReactScrollView>(), ScrollCommandHandler<ReactScrollView> {
|
||||
|
||||
init {
|
||||
if (ReactNativeFeatureFlags.enableViewRecyclingForScrollView()) {
|
||||
setupViewRecycling()
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareToRecycleView(
|
||||
reactContext: ThemedReactContext,
|
||||
view: ReactScrollView,
|
||||
): ReactScrollView? {
|
||||
// BaseViewManager
|
||||
val preparedView = super.prepareToRecycleView(reactContext, view)
|
||||
if (preparedView != null) {
|
||||
preparedView.recycleView()
|
||||
}
|
||||
return preparedView
|
||||
}
|
||||
|
||||
override fun getName(): String = REACT_CLASS
|
||||
|
||||
public override fun createViewInstance(context: ThemedReactContext): ReactScrollView =
|
||||
|
||||
+24
-5
@@ -41,6 +41,7 @@ public class ReactVirtualView(context: Context) :
|
||||
internal var modeChangeEmitter: VirtualViewModeChangeEmitter? = null
|
||||
internal var prerenderRatio: Double = ReactNativeFeatureFlags.virtualViewPrerenderRatio()
|
||||
internal val debugLogEnabled: Boolean = ReactNativeFeatureFlags.enableVirtualViewDebugFeatures()
|
||||
private val hysteresisRatio: Double = ReactNativeFeatureFlags.virtualViewHysteresisRatio()
|
||||
|
||||
private val onWindowFocusChangeListener =
|
||||
if (ReactNativeFeatureFlags.enableVirtualViewWindowFocusDetection()) {
|
||||
@@ -188,7 +189,7 @@ public class ReactVirtualView(context: Context) :
|
||||
// If no ScrollView, or ScrollView has disabled removeClippedSubviews, use default behavior
|
||||
if (
|
||||
parentScrollView == null ||
|
||||
!((parentScrollView as ReactClippingViewGroup)?.removeClippedSubviews ?: false)
|
||||
!((parentScrollView as ReactClippingViewGroup).removeClippedSubviews ?: false)
|
||||
) {
|
||||
super.updateClippingRect(excludedViews)
|
||||
return
|
||||
@@ -222,6 +223,8 @@ public class ReactVirtualView(context: Context) :
|
||||
bottom + offsetY,
|
||||
)
|
||||
scrollView.getDrawingRect(thresholdRect)
|
||||
val visibleHeight = thresholdRect.height()
|
||||
val visibleWidth = thresholdRect.width()
|
||||
|
||||
// TODO: Validate whether this is still the case and whether these checks are still needed.
|
||||
// updateRects will initially get called before the targetRect has any dimensions set, so if
|
||||
@@ -260,16 +263,32 @@ public class ReactVirtualView(context: Context) :
|
||||
var prerender = false
|
||||
if (prerenderRatio > 0.0) {
|
||||
thresholdRect.inset(
|
||||
(-thresholdRect.width() * prerenderRatio).toInt(),
|
||||
(-thresholdRect.height() * prerenderRatio).toInt(),
|
||||
(-visibleWidth * prerenderRatio).toInt(),
|
||||
(-visibleHeight * prerenderRatio).toInt(),
|
||||
)
|
||||
prerender = rectsOverlap(targetRect, thresholdRect)
|
||||
}
|
||||
if (prerender) {
|
||||
newMode = VirtualViewMode.Prerender
|
||||
} else {
|
||||
newMode = VirtualViewMode.Hidden
|
||||
thresholdRect.setEmpty()
|
||||
val _mode = mode // local variable so Kotlin knows its not nullable
|
||||
if (_mode != null && hysteresisRatio > 0.0) {
|
||||
thresholdRect.inset(
|
||||
(-visibleWidth * hysteresisRatio).toInt(),
|
||||
(-visibleHeight * hysteresisRatio).toInt(),
|
||||
)
|
||||
if (rectsOverlap(targetRect, thresholdRect)) {
|
||||
// In hysteresis window, no change to mode
|
||||
newMode = _mode
|
||||
debugLog("dispatchOnModeChangeIfNeeded") { "hysteresis, mode=$newMode" }
|
||||
} else {
|
||||
newMode = VirtualViewMode.Hidden
|
||||
thresholdRect.setEmpty()
|
||||
}
|
||||
} else {
|
||||
newMode = VirtualViewMode.Hidden
|
||||
thresholdRect.setEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
debugLog("dispatchOnModeChangeIfNeeded") {
|
||||
|
||||
+29
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<0dadaee3f6bd74cc13295b8683e8e470>>
|
||||
* @generated SignedSource<<16b12024bb363358ef09b9a42cb2fc97>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -267,6 +267,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableViewRecyclingForScrollView() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewRecyclingForScrollView");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
bool enableViewRecyclingForText() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableViewRecyclingForText");
|
||||
@@ -435,6 +441,12 @@ class ReactNativeFeatureFlagsJavaProvider
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
double virtualViewHysteresisRatio() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("virtualViewHysteresisRatio");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
double virtualViewPrerenderRatio() override {
|
||||
static const auto method =
|
||||
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("virtualViewPrerenderRatio");
|
||||
@@ -635,6 +647,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableViewRecycling(
|
||||
return ReactNativeFeatureFlags::enableViewRecycling();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForScrollView(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableViewRecyclingForScrollView();
|
||||
}
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForText(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::enableViewRecyclingForText();
|
||||
@@ -775,6 +792,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useTurboModules(
|
||||
return ReactNativeFeatureFlags::useTurboModules();
|
||||
}
|
||||
|
||||
double JReactNativeFeatureFlagsCxxInterop::virtualViewHysteresisRatio(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::virtualViewHysteresisRatio();
|
||||
}
|
||||
|
||||
double JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::virtualViewPrerenderRatio();
|
||||
@@ -925,6 +947,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"enableViewRecycling",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableViewRecycling),
|
||||
makeNativeMethod(
|
||||
"enableViewRecyclingForScrollView",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForScrollView),
|
||||
makeNativeMethod(
|
||||
"enableViewRecyclingForText",
|
||||
JReactNativeFeatureFlagsCxxInterop::enableViewRecyclingForText),
|
||||
@@ -1009,6 +1034,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
makeNativeMethod(
|
||||
"useTurboModules",
|
||||
JReactNativeFeatureFlagsCxxInterop::useTurboModules),
|
||||
makeNativeMethod(
|
||||
"virtualViewHysteresisRatio",
|
||||
JReactNativeFeatureFlagsCxxInterop::virtualViewHysteresisRatio),
|
||||
makeNativeMethod(
|
||||
"virtualViewPrerenderRatio",
|
||||
JReactNativeFeatureFlagsCxxInterop::virtualViewPrerenderRatio),
|
||||
|
||||
+7
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<74ac256afe63253ddb6576285858444c>>
|
||||
* @generated SignedSource<<54118ccd475a8bf1d7db83304b1f17d0>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -144,6 +144,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool enableViewRecycling(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableViewRecyclingForScrollView(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static bool enableViewRecyclingForText(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
@@ -228,6 +231,9 @@ class JReactNativeFeatureFlagsCxxInterop
|
||||
static bool useTurboModules(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static double virtualViewHysteresisRatio(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static double virtualViewPrerenderRatio(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ add_library(
|
||||
CatalystInstanceImpl.cpp
|
||||
InspectorNetworkRequestListener.cpp
|
||||
JExecutor.cpp
|
||||
JInspector.cpp
|
||||
JMessageQueueThread.cpp
|
||||
JReactCxxErrorHandler.cpp
|
||||
JReactSoftExceptionLogger.cpp
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "JInspector.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
namespace {
|
||||
|
||||
class RemoteConnection : public jsinspector_modern::IRemoteConnection {
|
||||
public:
|
||||
RemoteConnection(jni::alias_ref<JRemoteConnection::javaobject> connection)
|
||||
: connection_(jni::make_global(connection)) {}
|
||||
|
||||
void onMessage(std::string message) override {
|
||||
connection_->onMessage(message);
|
||||
}
|
||||
|
||||
void onDisconnect() override {
|
||||
connection_->onDisconnect();
|
||||
}
|
||||
|
||||
private:
|
||||
jni::global_ref<JRemoteConnection::javaobject> connection_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
jni::local_ref<JPage::javaobject>
|
||||
JPage::create(int id, const std::string& title, const std::string& vm) {
|
||||
static auto constructor = javaClassStatic()
|
||||
->getConstructor<JPage::javaobject(
|
||||
jint,
|
||||
jni::local_ref<jni::JString>,
|
||||
jni::local_ref<jni::JString>)>();
|
||||
return javaClassStatic()->newObject(
|
||||
constructor, id, jni::make_jstring(title), jni::make_jstring(vm));
|
||||
}
|
||||
|
||||
void JRemoteConnection::onMessage(const std::string& message) const {
|
||||
static auto method =
|
||||
javaClassStatic()->getMethod<void(jni::local_ref<jstring>)>("onMessage");
|
||||
method(self(), jni::make_jstring(message));
|
||||
}
|
||||
|
||||
void JRemoteConnection::onDisconnect() const {
|
||||
static auto method = javaClassStatic()->getMethod<void()>("onDisconnect");
|
||||
method(self());
|
||||
}
|
||||
|
||||
JLocalConnection::JLocalConnection(
|
||||
std::unique_ptr<jsinspector_modern::ILocalConnection> connection)
|
||||
: connection_(std::move(connection)) {}
|
||||
|
||||
void JLocalConnection::sendMessage(std::string message) {
|
||||
connection_->sendMessage(std::move(message));
|
||||
}
|
||||
|
||||
void JLocalConnection::disconnect() {
|
||||
connection_->disconnect();
|
||||
}
|
||||
|
||||
void JLocalConnection::registerNatives() {
|
||||
javaClassStatic()->registerNatives({
|
||||
makeNativeMethod("sendMessage", JLocalConnection::sendMessage),
|
||||
makeNativeMethod("disconnect", JLocalConnection::disconnect),
|
||||
});
|
||||
}
|
||||
|
||||
jni::global_ref<JInspector::javaobject> JInspector::instance(
|
||||
jni::alias_ref<jclass> /*unused*/) {
|
||||
static auto instance = jni::make_global(
|
||||
newObjectCxxArgs(&jsinspector_modern::getInspectorInstance()));
|
||||
return instance;
|
||||
}
|
||||
|
||||
jni::local_ref<jni::JArrayClass<JPage::javaobject>> JInspector::getPages() {
|
||||
std::vector<jsinspector_modern::InspectorPageDescription> pages =
|
||||
inspector_->getPages();
|
||||
auto array = jni::JArrayClass<JPage::javaobject>::newArray(pages.size());
|
||||
for (size_t i = 0; i < pages.size(); i++) {
|
||||
(*array)[i] = JPage::create(pages[i].id, pages[i].description, pages[i].vm);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
jni::local_ref<JLocalConnection::javaobject> JInspector::connect(
|
||||
int pageId,
|
||||
jni::alias_ref<JRemoteConnection::javaobject> remote) {
|
||||
auto localConnection = inspector_->connect(
|
||||
pageId, std::make_unique<RemoteConnection>(std::move(remote)));
|
||||
return localConnection
|
||||
? JLocalConnection::newObjectCxxArgs(std::move(localConnection))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void JInspector::registerNatives() {
|
||||
JLocalConnection::registerNatives();
|
||||
javaClassStatic()->registerNatives({
|
||||
makeNativeMethod("instance", JInspector::instance),
|
||||
makeNativeMethod("getPagesNative", JInspector::getPages),
|
||||
makeNativeMethod("connectNative", JInspector::connect),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jsinspector-modern/InspectorInterfaces.h>
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class JPage : public jni::JavaClass<JPage> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/bridge/Inspector$Page;";
|
||||
|
||||
static jni::local_ref<JPage::javaobject>
|
||||
create(int id, const std::string& title, const std::string& vm);
|
||||
};
|
||||
|
||||
class JRemoteConnection : public jni::JavaClass<JRemoteConnection> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/bridge/Inspector$RemoteConnection;";
|
||||
|
||||
void onMessage(const std::string& message) const;
|
||||
void onDisconnect() const;
|
||||
};
|
||||
|
||||
class JLocalConnection : public jni::HybridClass<JLocalConnection> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/bridge/Inspector$LocalConnection;";
|
||||
|
||||
JLocalConnection(
|
||||
std::unique_ptr<jsinspector_modern::ILocalConnection> connection);
|
||||
|
||||
void sendMessage(std::string message);
|
||||
void disconnect();
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
private:
|
||||
std::unique_ptr<jsinspector_modern::ILocalConnection> connection_;
|
||||
};
|
||||
|
||||
class JInspector : public jni::HybridClass<JInspector> {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/bridge/Inspector;";
|
||||
|
||||
static jni::global_ref<JInspector::javaobject> instance(
|
||||
jni::alias_ref<jclass>);
|
||||
|
||||
jni::local_ref<jni::JArrayClass<JPage::javaobject>> getPages();
|
||||
jni::local_ref<JLocalConnection::javaobject> connect(
|
||||
int pageId,
|
||||
jni::alias_ref<JRemoteConnection::javaobject> remote);
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
private:
|
||||
friend HybridBase;
|
||||
|
||||
JInspector(jsinspector_modern::IInspector* inspector)
|
||||
: inspector_(inspector) {}
|
||||
|
||||
jsinspector_modern::IInspector* inspector_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "CatalystInstanceImpl.h"
|
||||
#include "CxxModuleWrapperBase.h"
|
||||
#include "InspectorNetworkRequestListener.h"
|
||||
#include "JInspector.h"
|
||||
#include "JavaScriptExecutorHolder.h"
|
||||
#include "ReactInstanceManagerInspectorTarget.h"
|
||||
|
||||
@@ -41,7 +40,6 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
CatalystInstanceImpl::registerNatives();
|
||||
#endif
|
||||
CxxModuleWrapperBase::registerNatives();
|
||||
JInspector::registerNatives();
|
||||
ReactInstanceManagerInspectorTarget::registerNatives();
|
||||
InspectorNetworkRequestListener::registerNatives();
|
||||
});
|
||||
|
||||
+59
-9
@@ -80,15 +80,6 @@ void JReactHostInspectorTarget::sendDebuggerResumeCommand() {
|
||||
}
|
||||
}
|
||||
|
||||
void JReactHostInspectorTarget::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", JReactHostInspectorTarget::initHybrid),
|
||||
makeNativeMethod(
|
||||
"sendDebuggerResumeCommand",
|
||||
JReactHostInspectorTarget::sendDebuggerResumeCommand),
|
||||
});
|
||||
}
|
||||
|
||||
jsinspector_modern::HostTargetMetadata
|
||||
JReactHostInspectorTarget::getMetadata() {
|
||||
jsinspector_modern::HostTargetMetadata metadata = {
|
||||
@@ -157,4 +148,63 @@ HostTarget* JReactHostInspectorTarget::getInspectorTarget() {
|
||||
return inspectorTarget_ ? inspectorTarget_.get() : nullptr;
|
||||
}
|
||||
|
||||
bool JReactHostInspectorTarget::startBackgroundTrace() {
|
||||
if (inspectorTarget_) {
|
||||
return inspectorTarget_->startTracing(tracing::Mode::Background);
|
||||
} else {
|
||||
jni::throwNewJavaException(
|
||||
"java/lang/IllegalStateException",
|
||||
"Cannot start Tracing session while the Fusebox backend is not enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
tracing::TraceRecordingState JReactHostInspectorTarget::stopTracing() {
|
||||
if (inspectorTarget_) {
|
||||
return inspectorTarget_->stopTracing();
|
||||
} else {
|
||||
jni::throwNewJavaException(
|
||||
"java/lang/IllegalStateException",
|
||||
"Cannot stop Tracing session while the Fusebox backend is not enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
void JReactHostInspectorTarget::stopAndStashBackgroundTrace() {
|
||||
auto capturedTrace = inspectorTarget_->stopTracing();
|
||||
stashTraceRecordingState(std::move(capturedTrace));
|
||||
}
|
||||
|
||||
void JReactHostInspectorTarget::stopAndDiscardBackgroundTrace() {
|
||||
inspectorTarget_->stopTracing();
|
||||
}
|
||||
|
||||
void JReactHostInspectorTarget::stashTraceRecordingState(
|
||||
tracing::TraceRecordingState&& state) {
|
||||
stashedTraceRecordingState_ = std::move(state);
|
||||
}
|
||||
|
||||
std::optional<tracing::TraceRecordingState> JReactHostInspectorTarget::
|
||||
unstable_getTraceRecordingThatWillBeEmittedOnInitialization() {
|
||||
auto state = std::move(stashedTraceRecordingState_);
|
||||
stashedTraceRecordingState_.reset();
|
||||
return state;
|
||||
}
|
||||
|
||||
void JReactHostInspectorTarget::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", JReactHostInspectorTarget::initHybrid),
|
||||
makeNativeMethod(
|
||||
"sendDebuggerResumeCommand",
|
||||
JReactHostInspectorTarget::sendDebuggerResumeCommand),
|
||||
makeNativeMethod(
|
||||
"startBackgroundTrace",
|
||||
JReactHostInspectorTarget::startBackgroundTrace),
|
||||
makeNativeMethod(
|
||||
"stopAndStashBackgroundTrace",
|
||||
JReactHostInspectorTarget::stopAndStashBackgroundTrace),
|
||||
makeNativeMethod(
|
||||
"stopAndDiscardBackgroundTrace",
|
||||
JReactHostInspectorTarget::stopAndDiscardBackgroundTrace),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+36
@@ -77,6 +77,22 @@ class JReactHostInspectorTarget
|
||||
static void registerNatives();
|
||||
void sendDebuggerResumeCommand();
|
||||
|
||||
/**
|
||||
* Starts a background trace recording for this HostTarget.
|
||||
*
|
||||
* \return false if already tracing, true otherwise.
|
||||
*/
|
||||
bool startBackgroundTrace();
|
||||
/**
|
||||
* Stops previously started trace recording and stashes the captured trace,
|
||||
* which will be emitted the next time CDP session is created.
|
||||
*/
|
||||
void stopAndStashBackgroundTrace();
|
||||
/**
|
||||
* Stops previously started trace recording and discards the captured trace.
|
||||
*/
|
||||
void stopAndDiscardBackgroundTrace();
|
||||
|
||||
jsinspector_modern::HostTarget* getInspectorTarget();
|
||||
|
||||
// HostTargetDelegate methods
|
||||
@@ -90,6 +106,8 @@ class JReactHostInspectorTarget
|
||||
const jsinspector_modern::LoadNetworkResourceRequest& params,
|
||||
jsinspector_modern::ScopedExecutor<
|
||||
jsinspector_modern::NetworkRequestListener> executor) override;
|
||||
std::optional<jsinspector_modern::tracing::TraceRecordingState>
|
||||
unstable_getTraceRecordingThatWillBeEmittedOnInitialization() override;
|
||||
|
||||
private:
|
||||
JReactHostInspectorTarget(
|
||||
@@ -106,6 +124,24 @@ class JReactHostInspectorTarget
|
||||
std::shared_ptr<jsinspector_modern::HostTarget> inspectorTarget_;
|
||||
std::optional<int> inspectorPageId_;
|
||||
|
||||
/**
|
||||
* Stops previously started trace recording and returns the captured trace.
|
||||
*/
|
||||
jsinspector_modern::tracing::TraceRecordingState stopTracing();
|
||||
/**
|
||||
* Stashes previously recorded trace recording state that will be emitted when
|
||||
* CDP session is created. Once emitted, the value will be cleared from this
|
||||
* instance.
|
||||
*/
|
||||
void stashTraceRecordingState(
|
||||
jsinspector_modern::tracing::TraceRecordingState&& state);
|
||||
/**
|
||||
* Previously recorded trace recording state that will be emitted when
|
||||
* CDP session is created.
|
||||
*/
|
||||
std::optional<jsinspector_modern::tracing::TraceRecordingState>
|
||||
stashedTraceRecordingState_;
|
||||
|
||||
friend HybridBase;
|
||||
};
|
||||
} // namespace facebook::react
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ class BaseJavaModuleTest {
|
||||
private fun findMethod(mname: String, methods: List<JavaModuleWrapper.MethodDescriptor>): Int =
|
||||
methods.indexOfFirst({ it.name === mname })
|
||||
|
||||
@Test(expected = NativeArgumentsParseException::class)
|
||||
@Test(expected = JSApplicationCausedNativeException::class)
|
||||
fun testCallMethodWithoutEnoughArgs() {
|
||||
val methodId = findMethod("regularMethod", methods)
|
||||
whenever(arguments.size()).thenReturn(1)
|
||||
|
||||
@@ -328,6 +328,18 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
|
||||
plain_.setPropertyValue(o, name, value);
|
||||
};
|
||||
|
||||
void deleteProperty(const Object& object, const PropNameID& name) override {
|
||||
plain_.deleteProperty(object, name);
|
||||
}
|
||||
|
||||
void deleteProperty(const Object& object, const String& name) override {
|
||||
plain_.deleteProperty(object, name);
|
||||
}
|
||||
|
||||
void deleteProperty(const Object& object, const Value& name) override {
|
||||
plain_.deleteProperty(object, name);
|
||||
}
|
||||
|
||||
bool isArray(const Object& o) const override {
|
||||
return plain_.isArray(o);
|
||||
};
|
||||
@@ -852,6 +864,21 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
|
||||
RD::setPropertyValue(o, name, value);
|
||||
};
|
||||
|
||||
void deleteProperty(const Object& object, const PropNameID& name) override {
|
||||
Around around{with_};
|
||||
RD::deleteProperty(object, name);
|
||||
}
|
||||
|
||||
void deleteProperty(const Object& object, const String& name) override {
|
||||
Around around{with_};
|
||||
RD::deleteProperty(object, name);
|
||||
}
|
||||
|
||||
void deleteProperty(const Object& object, const Value& name) override {
|
||||
Around around{with_};
|
||||
RD::deleteProperty(object, name);
|
||||
}
|
||||
|
||||
bool isArray(const Object& o) const override {
|
||||
Around around{with_};
|
||||
return RD::isArray(o);
|
||||
|
||||
@@ -148,6 +148,23 @@ void Object::setProperty(Runtime& runtime, const PropNameID& name, T&& value)
|
||||
runtime, name, detail::toValue(runtime, std::forward<T>(value)));
|
||||
}
|
||||
|
||||
inline void Object::deleteProperty(Runtime& runtime, const char* name) const {
|
||||
deleteProperty(runtime, String::createFromAscii(runtime, name));
|
||||
}
|
||||
|
||||
inline void Object::deleteProperty(Runtime& runtime, const String& name) const {
|
||||
runtime.deleteProperty(*this, name);
|
||||
}
|
||||
|
||||
inline void Object::deleteProperty(Runtime& runtime, const PropNameID& name)
|
||||
const {
|
||||
runtime.deleteProperty(*this, name);
|
||||
}
|
||||
|
||||
inline void Object::deleteProperty(Runtime& runtime, const Value& name) const {
|
||||
runtime.deleteProperty(*this, name);
|
||||
}
|
||||
|
||||
inline Array Object::getArray(Runtime& runtime) const& {
|
||||
assert(runtime.isArray(*this));
|
||||
(void)runtime; // when assert is disabled we need to mark this as used
|
||||
|
||||
@@ -416,6 +416,37 @@ Object Runtime::createObjectWithPrototype(const Value& prototype) {
|
||||
return createFn.call(*this, prototype).asObject(*this);
|
||||
}
|
||||
|
||||
void Runtime::deleteProperty(const Object& object, const PropNameID& name) {
|
||||
auto nameStr = String::createFromUtf16(*this, name.utf16(*this));
|
||||
auto deleteFn = global()
|
||||
.getPropertyAsObject(*this, "Reflect")
|
||||
.getPropertyAsFunction(*this, "deleteProperty");
|
||||
auto res = deleteFn.call(*this, object, nameStr).getBool();
|
||||
if (!res) {
|
||||
throw JSError(*this, "Failed to delete property");
|
||||
}
|
||||
}
|
||||
|
||||
void Runtime::deleteProperty(const Object& object, const String& name) {
|
||||
auto deleteFn = global()
|
||||
.getPropertyAsObject(*this, "Reflect")
|
||||
.getPropertyAsFunction(*this, "deleteProperty");
|
||||
auto res = deleteFn.call(*this, object, name).getBool();
|
||||
if (!res) {
|
||||
throw JSError(*this, "Failed to delete property");
|
||||
}
|
||||
}
|
||||
|
||||
void Runtime::deleteProperty(const Object& object, const Value& name) {
|
||||
auto deleteFn = global()
|
||||
.getPropertyAsObject(*this, "Reflect")
|
||||
.getPropertyAsFunction(*this, "deleteProperty");
|
||||
auto res = deleteFn.call(*this, object, name).getBool();
|
||||
if (!res) {
|
||||
throw JSError(*this, "Failed to delete property");
|
||||
}
|
||||
}
|
||||
|
||||
void Runtime::setRuntimeDataImpl(
|
||||
const UUID& uuid,
|
||||
const void* data,
|
||||
|
||||
@@ -486,6 +486,10 @@ class JSI_EXPORT Runtime : public ICast {
|
||||
virtual void
|
||||
setPropertyValue(const Object&, const String& name, const Value& value) = 0;
|
||||
|
||||
virtual void deleteProperty(const Object&, const PropNameID& name);
|
||||
virtual void deleteProperty(const Object&, const String& name);
|
||||
virtual void deleteProperty(const Object&, const Value& name);
|
||||
|
||||
virtual bool isArray(const Object&) const = 0;
|
||||
virtual bool isArrayBuffer(const Object&) const = 0;
|
||||
virtual bool isFunction(const Object&) const = 0;
|
||||
@@ -984,6 +988,22 @@ class JSI_EXPORT Object : public Pointer {
|
||||
template <typename T>
|
||||
void setProperty(Runtime& runtime, const PropNameID& name, T&& value) const;
|
||||
|
||||
/// Delete the property with the given ascii name. Throws if the deletion
|
||||
/// failed.
|
||||
void deleteProperty(Runtime& runtime, const char* name) const;
|
||||
|
||||
/// Delete the property with the given String name. Throws if the deletion
|
||||
/// failed.
|
||||
void deleteProperty(Runtime& runtime, const String& name) const;
|
||||
|
||||
/// Delete the property with the given PropNameID name. Throws if the deletion
|
||||
/// failed.
|
||||
void deleteProperty(Runtime& runtime, const PropNameID& name) const;
|
||||
|
||||
/// Delete the property with the given Value name. Throws if the deletion
|
||||
/// failed.
|
||||
void deleteProperty(Runtime& runtime, const Value& name) const;
|
||||
|
||||
/// \return true iff JS \c Array.isArray() would return \c true. If
|
||||
/// so, then \c getArray() will succeed.
|
||||
bool isArray(Runtime& runtime) const {
|
||||
|
||||
@@ -1882,6 +1882,65 @@ TEST_P(JSITest, CastInterface) {
|
||||
EXPECT_TRUE(ptr == nullptr);
|
||||
}
|
||||
|
||||
TEST_P(JSITest, DeleteProperty) {
|
||||
// This Runtime Decorator is used to test the default implementation of
|
||||
// Runtime::deleteProperty
|
||||
class RD : public RuntimeDecorator<Runtime, Runtime> {
|
||||
public:
|
||||
explicit RD(Runtime& rt) : RuntimeDecorator(rt) {}
|
||||
|
||||
void deleteProperty(const Object& object, const PropNameID& name) override {
|
||||
Runtime::deleteProperty(object, name);
|
||||
}
|
||||
void deleteProperty(const Object& object, const String& name) override {
|
||||
Runtime::deleteProperty(object, name);
|
||||
}
|
||||
void deleteProperty(const Object& object, const Value& name) override {
|
||||
Runtime::deleteProperty(object, name);
|
||||
}
|
||||
};
|
||||
RD rd = RD(rt);
|
||||
auto obj = eval("obj = {1:2, foo: 'bar', 3: 4, salt:'pepper'}").getObject(rd);
|
||||
|
||||
auto prop = PropNameID::forAscii(rd, "1");
|
||||
auto hasRes = obj.hasProperty(rd, prop);
|
||||
EXPECT_TRUE(hasRes);
|
||||
obj.deleteProperty(rd, prop);
|
||||
hasRes = obj.hasProperty(rd, prop);
|
||||
EXPECT_FALSE(hasRes);
|
||||
|
||||
auto str = String::createFromAscii(rd, "foo");
|
||||
hasRes = obj.hasProperty(rd, str);
|
||||
EXPECT_TRUE(hasRes);
|
||||
obj.deleteProperty(rd, str);
|
||||
hasRes = obj.hasProperty(rd, str);
|
||||
EXPECT_FALSE(hasRes);
|
||||
|
||||
auto valProp = Value(3);
|
||||
hasRes = obj.hasProperty(rd, "3");
|
||||
EXPECT_TRUE(hasRes);
|
||||
obj.deleteProperty(rd, valProp);
|
||||
auto getRes = obj.getProperty(rd, "3");
|
||||
EXPECT_TRUE(getRes.isUndefined());
|
||||
|
||||
hasRes = obj.hasProperty(rd, "salt");
|
||||
EXPECT_TRUE(hasRes);
|
||||
obj.deleteProperty(rd, "salt");
|
||||
hasRes = obj.hasProperty(rd, "salt");
|
||||
EXPECT_FALSE(hasRes);
|
||||
|
||||
obj = eval(
|
||||
"const obj = {};"
|
||||
"Object.defineProperty(obj, 'prop', {"
|
||||
" value: 10,"
|
||||
" configurable: false,});"
|
||||
"obj;")
|
||||
.getObject(rd);
|
||||
EXPECT_THROW(obj.deleteProperty(rd, "prop"), JSError);
|
||||
hasRes = obj.hasProperty(rd, "prop");
|
||||
EXPECT_TRUE(hasRes);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
Runtimes,
|
||||
JSITest,
|
||||
|
||||
@@ -41,14 +41,18 @@ class HostAgent::Impl final {
|
||||
HostTargetController& targetController,
|
||||
HostTargetMetadata hostMetadata,
|
||||
SessionState& sessionState,
|
||||
VoidExecutor executor)
|
||||
VoidExecutor executor,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
|
||||
: frontendChannel_(frontendChannel),
|
||||
targetController_(targetController),
|
||||
hostMetadata_(std::move(hostMetadata)),
|
||||
sessionState_(sessionState),
|
||||
networkIOAgent_(NetworkIOAgent(frontendChannel, std::move(executor))),
|
||||
tracingAgent_(
|
||||
TracingAgent(frontendChannel, sessionState, targetController)) {}
|
||||
tracingAgent_(TracingAgent(
|
||||
frontendChannel,
|
||||
sessionState,
|
||||
targetController,
|
||||
std::move(traceRecordingToEmit))) {}
|
||||
|
||||
~Impl() {
|
||||
if (isPausedInDebuggerOverlayVisible_) {
|
||||
@@ -428,7 +432,8 @@ class HostAgent::Impl final {
|
||||
HostTargetController& targetController,
|
||||
HostTargetMetadata hostMetadata,
|
||||
SessionState& sessionState,
|
||||
VoidExecutor executor) {}
|
||||
VoidExecutor executor,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit) {}
|
||||
|
||||
void handleRequest(const cdp::PreparsedRequest& req) {}
|
||||
void setCurrentInstanceAgent(std::shared_ptr<InstanceAgent> agent) {}
|
||||
@@ -441,14 +446,16 @@ HostAgent::HostAgent(
|
||||
HostTargetController& targetController,
|
||||
HostTargetMetadata hostMetadata,
|
||||
SessionState& sessionState,
|
||||
VoidExecutor executor)
|
||||
VoidExecutor executor,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
|
||||
: impl_(std::make_unique<Impl>(
|
||||
*this,
|
||||
frontendChannel,
|
||||
targetController,
|
||||
std::move(hostMetadata),
|
||||
sessionState,
|
||||
std::move(executor))) {}
|
||||
std::move(executor),
|
||||
std::move(traceRecordingToEmit))) {}
|
||||
|
||||
HostAgent::~HostAgent() = default;
|
||||
|
||||
|
||||
@@ -36,13 +36,16 @@ class HostAgent final {
|
||||
* \param hostMetadata Metadata about the host that created this agent.
|
||||
* \param sessionState The state of the session that created this agent.
|
||||
* \param executor A void executor to be used by async-aware handlers.
|
||||
* \param traceRecordingToEmit If set, this is the trace that Host has
|
||||
* requested to display in the Frontend.
|
||||
*/
|
||||
HostAgent(
|
||||
const FrontendChannel& frontendChannel,
|
||||
HostTargetController& targetController,
|
||||
HostTargetMetadata hostMetadata,
|
||||
SessionState& sessionState,
|
||||
VoidExecutor executor);
|
||||
VoidExecutor executor,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit);
|
||||
|
||||
HostAgent(const HostAgent&) = delete;
|
||||
HostAgent(HostAgent&&) = delete;
|
||||
|
||||
@@ -34,7 +34,8 @@ class HostTargetSession {
|
||||
std::unique_ptr<IRemoteConnection> remote,
|
||||
HostTargetController& targetController,
|
||||
HostTargetMetadata hostMetadata,
|
||||
VoidExecutor executor)
|
||||
VoidExecutor executor,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
|
||||
: remote_(std::make_shared<RAIIRemoteConnection>(std::move(remote))),
|
||||
frontendChannel_(
|
||||
[remoteWeak = std::weak_ptr(remote_)](std::string_view message) {
|
||||
@@ -47,7 +48,8 @@ class HostTargetSession {
|
||||
targetController,
|
||||
std::move(hostMetadata),
|
||||
state_,
|
||||
std::move(executor)) {}
|
||||
std::move(executor),
|
||||
std::move(traceRecordingToEmit)) {}
|
||||
|
||||
/**
|
||||
* Called by CallbackLocalConnection to send a message to this Session's
|
||||
@@ -206,7 +208,8 @@ std::unique_ptr<ILocalConnection> HostTarget::connect(
|
||||
std::move(connectionToFrontend),
|
||||
controller_,
|
||||
delegate_.getMetadata(),
|
||||
makeVoidExecutor(executorFromThis()));
|
||||
makeVoidExecutor(executorFromThis()),
|
||||
delegate_.unstable_getTraceRecordingThatWillBeEmittedOnInitialization());
|
||||
session->setCurrentInstance(currentInstance_.get());
|
||||
sessions_.insert(std::weak_ptr(session));
|
||||
return std::make_unique<CallbackLocalConnection>(
|
||||
@@ -217,6 +220,11 @@ HostTarget::~HostTarget() {
|
||||
// HostCommandSender owns a session, so we must release it for the assertion
|
||||
// below to be valid.
|
||||
commandSender_.reset();
|
||||
|
||||
// HostRuntimeBinding owns a connection, so we must release it for the
|
||||
// assertion
|
||||
perfMetricsBinding_.reset();
|
||||
|
||||
// Sessions are owned by InspectorPackagerConnection, not by HostTarget, but
|
||||
// they hold a HostTarget& that we must guarantee is valid.
|
||||
assert(
|
||||
|
||||
@@ -146,6 +146,19 @@ class HostTargetDelegate : public LoadNetworkResourceDelegate {
|
||||
throw NotImplementedException(
|
||||
"LoadNetworkResourceDelegate.loadNetworkResource is not implemented by this host target delegate.");
|
||||
}
|
||||
|
||||
/**
|
||||
* [Experimental] Will be called at the CDP session initialization to get the
|
||||
* trace recording that may have been stashed by the Host from the previous
|
||||
* background session.
|
||||
*
|
||||
* \return the trace recording state if there is one that needs to be
|
||||
* displayed, otherwise std::nullopt.
|
||||
*/
|
||||
virtual std::optional<tracing::TraceRecordingState>
|
||||
unstable_getTraceRecordingThatWillBeEmittedOnInitialization() {
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,10 +38,17 @@ const uint16_t PROFILE_TRACE_EVENT_CHUNK_SIZE = 1;
|
||||
TracingAgent::TracingAgent(
|
||||
FrontendChannel frontendChannel,
|
||||
SessionState& sessionState,
|
||||
HostTargetController& hostTargetController)
|
||||
HostTargetController& hostTargetController,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit)
|
||||
: frontendChannel_(std::move(frontendChannel)),
|
||||
sessionState_(sessionState),
|
||||
hostTargetController_(hostTargetController) {}
|
||||
hostTargetController_(hostTargetController) {
|
||||
if (traceRecordingToEmit.has_value()) {
|
||||
frontendChannel_(
|
||||
cdp::jsonNotification("ReactNativeApplication.traceRequested"));
|
||||
emitTraceRecording(std::move(traceRecordingToEmit.value()));
|
||||
}
|
||||
}
|
||||
|
||||
TracingAgent::~TracingAgent() {
|
||||
// Agents are owned by the session. If the agent is destroyed, it means that
|
||||
@@ -86,25 +93,29 @@ bool TracingAgent::handleRequest(const cdp::PreparsedRequest& req) {
|
||||
// Send response to Tracing.end request.
|
||||
frontendChannel_(cdp::jsonResult(req.id));
|
||||
|
||||
auto dataCollectedCallback = [this](folly::dynamic&& eventsChunk) {
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Tracing.dataCollected",
|
||||
folly::dynamic::object("value", std::move(eventsChunk))));
|
||||
};
|
||||
tracing::TraceRecordingStateSerializer::emitAsDataCollectedChunks(
|
||||
std::move(state),
|
||||
dataCollectedCallback,
|
||||
TRACE_EVENT_CHUNK_SIZE,
|
||||
PROFILE_TRACE_EVENT_CHUNK_SIZE);
|
||||
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Tracing.tracingComplete",
|
||||
folly::dynamic::object("dataLossOccurred", false)));
|
||||
|
||||
emitTraceRecording(std::move(state));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TracingAgent::emitTraceRecording(
|
||||
tracing::TraceRecordingState state) const {
|
||||
auto dataCollectedCallback = [this](folly::dynamic&& eventsChunk) {
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Tracing.dataCollected",
|
||||
folly::dynamic::object("value", std::move(eventsChunk))));
|
||||
};
|
||||
tracing::TraceRecordingStateSerializer::emitAsDataCollectedChunks(
|
||||
std::move(state),
|
||||
dataCollectedCallback,
|
||||
TRACE_EVENT_CHUNK_SIZE,
|
||||
PROFILE_TRACE_EVENT_CHUNK_SIZE);
|
||||
|
||||
frontendChannel_(cdp::jsonNotification(
|
||||
"Tracing.tracingComplete",
|
||||
folly::dynamic::object("dataLossOccurred", false)));
|
||||
}
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
|
||||
@@ -24,11 +24,18 @@ class TracingAgent {
|
||||
/**
|
||||
* \param frontendChannel A channel used to send responses to the
|
||||
* frontend.
|
||||
* \param sessionState The state of the session that created this agent.
|
||||
* \param hostTargetController An interface to the HostTarget that this agent
|
||||
* is attached to. The caller is responsible for ensuring that the
|
||||
* HostTargetDelegate and underlying HostTarget both outlive the agent.
|
||||
* \param traceRecordingToEmit If set, this is the trace that Host has
|
||||
* requested to display in the Frontend.
|
||||
*/
|
||||
TracingAgent(
|
||||
FrontendChannel frontendChannel,
|
||||
SessionState& sessionState,
|
||||
HostTargetController& hostTargetController);
|
||||
HostTargetController& hostTargetController,
|
||||
std::optional<tracing::TraceRecordingState> traceRecordingToEmit);
|
||||
|
||||
~TracingAgent();
|
||||
|
||||
@@ -48,6 +55,12 @@ class TracingAgent {
|
||||
SessionState& sessionState_;
|
||||
|
||||
HostTargetController& hostTargetController_;
|
||||
|
||||
/**
|
||||
* Emits the captured Trace Recording state in a series of
|
||||
* Tracing.dataCollected events, followed by a Tracing.tracingComplete event.
|
||||
*/
|
||||
void emitTraceRecording(tracing::TraceRecordingState state) const;
|
||||
};
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
|
||||
@@ -190,6 +190,7 @@ void PerformanceTracer::reportTimeStamp(
|
||||
.trackName = std::move(trackName),
|
||||
.trackGroup = std::move(trackGroup),
|
||||
.color = std::move(color),
|
||||
.threadId = getCurrentThreadId(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -399,7 +400,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
|
||||
.ph = 'X',
|
||||
.ts = event.start,
|
||||
.pid = processId_,
|
||||
.tid = getCurrentThreadId(),
|
||||
.tid = event.threadId,
|
||||
.dur = event.end - event.start,
|
||||
});
|
||||
},
|
||||
@@ -410,7 +411,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
|
||||
.ph = 'X',
|
||||
.ts = event.start,
|
||||
.pid = processId_,
|
||||
.tid = getCurrentThreadId(),
|
||||
.tid = event.threadId,
|
||||
.dur = event.end - event.start,
|
||||
});
|
||||
},
|
||||
@@ -429,7 +430,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
|
||||
.ph = 'I',
|
||||
.ts = event.start,
|
||||
.pid = processId_,
|
||||
.tid = getCurrentThreadId(),
|
||||
.tid = event.threadId,
|
||||
.args = std::move(eventArgs),
|
||||
});
|
||||
},
|
||||
@@ -449,7 +450,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
|
||||
.ph = 'b',
|
||||
.ts = event.start,
|
||||
.pid = processId_,
|
||||
.tid = getCurrentThreadId(),
|
||||
.tid = event.threadId,
|
||||
.args = std::move(beginEventArgs),
|
||||
});
|
||||
events.emplace_back(TraceEvent{
|
||||
@@ -459,7 +460,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
|
||||
.ph = 'e',
|
||||
.ts = event.start + event.duration,
|
||||
.pid = processId_,
|
||||
.tid = getCurrentThreadId(),
|
||||
.tid = event.threadId,
|
||||
});
|
||||
},
|
||||
[&](PerformanceTracerEventTimeStamp&& event) {
|
||||
@@ -500,7 +501,7 @@ void PerformanceTracer::enqueueTraceEventsFromPerformanceTracerEvent(
|
||||
.ph = 'I',
|
||||
.ts = event.createdAt,
|
||||
.pid = processId_,
|
||||
.tid = getCurrentThreadId(),
|
||||
.tid = event.threadId,
|
||||
.args = folly::dynamic::object("data", std::move(data)),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<392fdd6e857b7c8ae99329b927be6ae0>>
|
||||
* @generated SignedSource<<12a06ea04fc09c34f1fbdcbdf6046d81>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -178,6 +178,10 @@ bool ReactNativeFeatureFlags::enableViewRecycling() {
|
||||
return getAccessor().enableViewRecycling();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enableViewRecyclingForScrollView() {
|
||||
return getAccessor().enableViewRecyclingForScrollView();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlags::enableViewRecyclingForText() {
|
||||
return getAccessor().enableViewRecyclingForText();
|
||||
}
|
||||
@@ -290,6 +294,10 @@ bool ReactNativeFeatureFlags::useTurboModules() {
|
||||
return getAccessor().useTurboModules();
|
||||
}
|
||||
|
||||
double ReactNativeFeatureFlags::virtualViewHysteresisRatio() {
|
||||
return getAccessor().virtualViewHysteresisRatio();
|
||||
}
|
||||
|
||||
double ReactNativeFeatureFlags::virtualViewPrerenderRatio() {
|
||||
return getAccessor().virtualViewPrerenderRatio();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<b601a3c92cd80549ca2391ab0a123214>>
|
||||
* @generated SignedSource<<eee81e4e9bb13ef5134d4e2d79876b38>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -229,6 +229,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool enableViewRecycling();
|
||||
|
||||
/**
|
||||
* Enables View Recycling for <ScrollView> via ReactViewGroup/ReactViewManager.
|
||||
*/
|
||||
RN_EXPORT static bool enableViewRecyclingForScrollView();
|
||||
|
||||
/**
|
||||
* Enables View Recycling for <Text> via ReactTextView/ReactTextViewManager.
|
||||
*/
|
||||
@@ -369,6 +374,11 @@ class ReactNativeFeatureFlags {
|
||||
*/
|
||||
RN_EXPORT static bool useTurboModules();
|
||||
|
||||
/**
|
||||
* Sets a hysteresis window for transition between prerender and hidden modes.
|
||||
*/
|
||||
RN_EXPORT static double virtualViewHysteresisRatio();
|
||||
|
||||
/**
|
||||
* Initial prerender ratio for VirtualView.
|
||||
*/
|
||||
|
||||
+66
-30
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<69518331e8b6225d4aa524e46951302d>>
|
||||
* @generated SignedSource<<3c5588a851e6cdefaba22236c5ebb828>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -713,6 +713,24 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() {
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() {
|
||||
auto flagValue = enableViewRecyclingForScrollView_.load();
|
||||
|
||||
if (!flagValue.has_value()) {
|
||||
// This block is not exclusive but it is not necessary.
|
||||
// If multiple threads try to initialize the feature flag, we would only
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(38, "enableViewRecyclingForScrollView");
|
||||
|
||||
flagValue = currentProvider_->enableViewRecyclingForScrollView();
|
||||
enableViewRecyclingForScrollView_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
|
||||
auto flagValue = enableViewRecyclingForText_.load();
|
||||
|
||||
@@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(38, "enableViewRecyclingForText");
|
||||
markFlagAsAccessed(39, "enableViewRecyclingForText");
|
||||
|
||||
flagValue = currentProvider_->enableViewRecyclingForText();
|
||||
enableViewRecyclingForText_ = flagValue;
|
||||
@@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(39, "enableViewRecyclingForView");
|
||||
markFlagAsAccessed(40, "enableViewRecyclingForView");
|
||||
|
||||
flagValue = currentProvider_->enableViewRecyclingForView();
|
||||
enableViewRecyclingForView_ = flagValue;
|
||||
@@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(40, "enableVirtualViewDebugFeatures");
|
||||
markFlagAsAccessed(41, "enableVirtualViewDebugFeatures");
|
||||
|
||||
flagValue = currentProvider_->enableVirtualViewDebugFeatures();
|
||||
enableVirtualViewDebugFeatures_ = flagValue;
|
||||
@@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewRenderState() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(41, "enableVirtualViewRenderState");
|
||||
markFlagAsAccessed(42, "enableVirtualViewRenderState");
|
||||
|
||||
flagValue = currentProvider_->enableVirtualViewRenderState();
|
||||
enableVirtualViewRenderState_ = flagValue;
|
||||
@@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(42, "enableVirtualViewWindowFocusDetection");
|
||||
markFlagAsAccessed(43, "enableVirtualViewWindowFocusDetection");
|
||||
|
||||
flagValue = currentProvider_->enableVirtualViewWindowFocusDetection();
|
||||
enableVirtualViewWindowFocusDetection_ = flagValue;
|
||||
@@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(43, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
markFlagAsAccessed(44, "fixMappingOfEventPrioritiesBetweenFabricAndReact");
|
||||
|
||||
flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact();
|
||||
fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue;
|
||||
@@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(44, "fuseboxEnabledRelease");
|
||||
markFlagAsAccessed(45, "fuseboxEnabledRelease");
|
||||
|
||||
flagValue = currentProvider_->fuseboxEnabledRelease();
|
||||
fuseboxEnabledRelease_ = flagValue;
|
||||
@@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(45, "fuseboxNetworkInspectionEnabled");
|
||||
markFlagAsAccessed(46, "fuseboxNetworkInspectionEnabled");
|
||||
|
||||
flagValue = currentProvider_->fuseboxNetworkInspectionEnabled();
|
||||
fuseboxNetworkInspectionEnabled_ = flagValue;
|
||||
@@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(46, "hideOffscreenVirtualViewsOnIOS");
|
||||
markFlagAsAccessed(47, "hideOffscreenVirtualViewsOnIOS");
|
||||
|
||||
flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS();
|
||||
hideOffscreenVirtualViewsOnIOS_ = flagValue;
|
||||
@@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(47, "perfMonitorV2Enabled");
|
||||
markFlagAsAccessed(48, "perfMonitorV2Enabled");
|
||||
|
||||
flagValue = currentProvider_->perfMonitorV2Enabled();
|
||||
perfMonitorV2Enabled_ = flagValue;
|
||||
@@ -902,7 +920,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(48, "preparedTextCacheSize");
|
||||
markFlagAsAccessed(49, "preparedTextCacheSize");
|
||||
|
||||
flagValue = currentProvider_->preparedTextCacheSize();
|
||||
preparedTextCacheSize_ = flagValue;
|
||||
@@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(49, "preventShadowTreeCommitExhaustion");
|
||||
markFlagAsAccessed(50, "preventShadowTreeCommitExhaustion");
|
||||
|
||||
flagValue = currentProvider_->preventShadowTreeCommitExhaustion();
|
||||
preventShadowTreeCommitExhaustion_ = flagValue;
|
||||
@@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::releaseImageDataWhenConsumed() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(50, "releaseImageDataWhenConsumed");
|
||||
markFlagAsAccessed(51, "releaseImageDataWhenConsumed");
|
||||
|
||||
flagValue = currentProvider_->releaseImageDataWhenConsumed();
|
||||
releaseImageDataWhenConsumed_ = flagValue;
|
||||
@@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(51, "shouldPressibilityUseW3CPointerEventsForHover");
|
||||
markFlagAsAccessed(52, "shouldPressibilityUseW3CPointerEventsForHover");
|
||||
|
||||
flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover();
|
||||
shouldPressibilityUseW3CPointerEventsForHover_ = flagValue;
|
||||
@@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause()
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(52, "skipActivityIdentityAssertionOnHostPause");
|
||||
markFlagAsAccessed(53, "skipActivityIdentityAssertionOnHostPause");
|
||||
|
||||
flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause();
|
||||
skipActivityIdentityAssertionOnHostPause_ = flagValue;
|
||||
@@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(53, "sweepActiveTouchOnChildNativeGesturesAndroid");
|
||||
markFlagAsAccessed(54, "sweepActiveTouchOnChildNativeGesturesAndroid");
|
||||
|
||||
flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid();
|
||||
sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue;
|
||||
@@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(54, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
markFlagAsAccessed(55, "traceTurboModulePromiseRejectionsOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid();
|
||||
traceTurboModulePromiseRejectionsOnAndroid_ = flagValue;
|
||||
@@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit(
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(55, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
markFlagAsAccessed(56, "updateRuntimeShadowNodeReferencesOnCommit");
|
||||
|
||||
flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit();
|
||||
updateRuntimeShadowNodeReferencesOnCommit_ = flagValue;
|
||||
@@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(56, "useAlwaysAvailableJSErrorHandling");
|
||||
markFlagAsAccessed(57, "useAlwaysAvailableJSErrorHandling");
|
||||
|
||||
flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling();
|
||||
useAlwaysAvailableJSErrorHandling_ = flagValue;
|
||||
@@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(57, "useFabricInterop");
|
||||
markFlagAsAccessed(58, "useFabricInterop");
|
||||
|
||||
flagValue = currentProvider_->useFabricInterop();
|
||||
useFabricInterop_ = flagValue;
|
||||
@@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(58, "useNativeEqualsInNativeReadableArrayAndroid");
|
||||
markFlagAsAccessed(59, "useNativeEqualsInNativeReadableArrayAndroid");
|
||||
|
||||
flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid();
|
||||
useNativeEqualsInNativeReadableArrayAndroid_ = flagValue;
|
||||
@@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(59, "useNativeTransformHelperAndroid");
|
||||
markFlagAsAccessed(60, "useNativeTransformHelperAndroid");
|
||||
|
||||
flagValue = currentProvider_->useNativeTransformHelperAndroid();
|
||||
useNativeTransformHelperAndroid_ = flagValue;
|
||||
@@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(60, "useNativeViewConfigsInBridgelessMode");
|
||||
markFlagAsAccessed(61, "useNativeViewConfigsInBridgelessMode");
|
||||
|
||||
flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
|
||||
useNativeViewConfigsInBridgelessMode_ = flagValue;
|
||||
@@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(61, "useOptimizedEventBatchingOnAndroid");
|
||||
markFlagAsAccessed(62, "useOptimizedEventBatchingOnAndroid");
|
||||
|
||||
flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid();
|
||||
useOptimizedEventBatchingOnAndroid_ = flagValue;
|
||||
@@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(62, "useRawPropsJsiValue");
|
||||
markFlagAsAccessed(63, "useRawPropsJsiValue");
|
||||
|
||||
flagValue = currentProvider_->useRawPropsJsiValue();
|
||||
useRawPropsJsiValue_ = flagValue;
|
||||
@@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(63, "useShadowNodeStateOnClone");
|
||||
markFlagAsAccessed(64, "useShadowNodeStateOnClone");
|
||||
|
||||
flagValue = currentProvider_->useShadowNodeStateOnClone();
|
||||
useShadowNodeStateOnClone_ = flagValue;
|
||||
@@ -1190,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(64, "useTurboModuleInterop");
|
||||
markFlagAsAccessed(65, "useTurboModuleInterop");
|
||||
|
||||
flagValue = currentProvider_->useTurboModuleInterop();
|
||||
useTurboModuleInterop_ = flagValue;
|
||||
@@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(65, "useTurboModules");
|
||||
markFlagAsAccessed(66, "useTurboModules");
|
||||
|
||||
flagValue = currentProvider_->useTurboModules();
|
||||
useTurboModules_ = flagValue;
|
||||
@@ -1217,6 +1235,24 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() {
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
double ReactNativeFeatureFlagsAccessor::virtualViewHysteresisRatio() {
|
||||
auto flagValue = virtualViewHysteresisRatio_.load();
|
||||
|
||||
if (!flagValue.has_value()) {
|
||||
// This block is not exclusive but it is not necessary.
|
||||
// If multiple threads try to initialize the feature flag, we would only
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(67, "virtualViewHysteresisRatio");
|
||||
|
||||
flagValue = currentProvider_->virtualViewHysteresisRatio();
|
||||
virtualViewHysteresisRatio_ = flagValue;
|
||||
}
|
||||
|
||||
return flagValue.value();
|
||||
}
|
||||
|
||||
double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
|
||||
auto flagValue = virtualViewPrerenderRatio_.load();
|
||||
|
||||
@@ -1226,7 +1262,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() {
|
||||
// be accessing the provider multiple times but the end state of this
|
||||
// instance and the returned flag value would be the same.
|
||||
|
||||
markFlagAsAccessed(66, "virtualViewPrerenderRatio");
|
||||
markFlagAsAccessed(68, "virtualViewPrerenderRatio");
|
||||
|
||||
flagValue = currentProvider_->virtualViewPrerenderRatio();
|
||||
virtualViewPrerenderRatio_ = flagValue;
|
||||
|
||||
+6
-2
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<e7ebd228905c959f5472fba72bc3f99c>>
|
||||
* @generated SignedSource<<f1eb31a7412bff743a5c581224d71e2a>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -70,6 +70,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
bool enableResourceTimingAPI();
|
||||
bool enableViewCulling();
|
||||
bool enableViewRecycling();
|
||||
bool enableViewRecyclingForScrollView();
|
||||
bool enableViewRecyclingForText();
|
||||
bool enableViewRecyclingForView();
|
||||
bool enableVirtualViewDebugFeatures();
|
||||
@@ -98,6 +99,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
bool useShadowNodeStateOnClone();
|
||||
bool useTurboModuleInterop();
|
||||
bool useTurboModules();
|
||||
double virtualViewHysteresisRatio();
|
||||
double virtualViewPrerenderRatio();
|
||||
|
||||
void override(std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
|
||||
@@ -110,7 +112,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
|
||||
bool wasOverridden_;
|
||||
|
||||
std::array<std::atomic<const char*>, 67> accessedFeatureFlags_;
|
||||
std::array<std::atomic<const char*>, 69> accessedFeatureFlags_;
|
||||
|
||||
std::atomic<std::optional<bool>> commonTestFlag_;
|
||||
std::atomic<std::optional<bool>> cdpInteractionMetricsEnabled_;
|
||||
@@ -150,6 +152,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::atomic<std::optional<bool>> enableResourceTimingAPI_;
|
||||
std::atomic<std::optional<bool>> enableViewCulling_;
|
||||
std::atomic<std::optional<bool>> enableViewRecycling_;
|
||||
std::atomic<std::optional<bool>> enableViewRecyclingForScrollView_;
|
||||
std::atomic<std::optional<bool>> enableViewRecyclingForText_;
|
||||
std::atomic<std::optional<bool>> enableViewRecyclingForView_;
|
||||
std::atomic<std::optional<bool>> enableVirtualViewDebugFeatures_;
|
||||
@@ -178,6 +181,7 @@ class ReactNativeFeatureFlagsAccessor {
|
||||
std::atomic<std::optional<bool>> useShadowNodeStateOnClone_;
|
||||
std::atomic<std::optional<bool>> useTurboModuleInterop_;
|
||||
std::atomic<std::optional<bool>> useTurboModules_;
|
||||
std::atomic<std::optional<double>> virtualViewHysteresisRatio_;
|
||||
std::atomic<std::optional<double>> virtualViewPrerenderRatio_;
|
||||
};
|
||||
|
||||
|
||||
+12
-4
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<a7f5d45347dee3c9c5b17731e1bf8993>>
|
||||
* @generated SignedSource<<a76f1a1e8ba0d65b689b4b87d33d7ced>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -179,6 +179,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enableViewRecyclingForScrollView() override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enableViewRecyclingForText() override {
|
||||
return true;
|
||||
}
|
||||
@@ -260,11 +264,11 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
}
|
||||
|
||||
bool useNativeEqualsInNativeReadableArrayAndroid() override {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool useNativeTransformHelperAndroid() override {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool useNativeViewConfigsInBridgelessMode() override {
|
||||
@@ -276,7 +280,7 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
}
|
||||
|
||||
bool useRawPropsJsiValue() override {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool useShadowNodeStateOnClone() override {
|
||||
@@ -291,6 +295,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
double virtualViewHysteresisRatio() override {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double virtualViewPrerenderRatio() override {
|
||||
return 5.0;
|
||||
}
|
||||
|
||||
+19
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<60b81844a9af1862b27ed6b4d9be5f59>>
|
||||
* @generated SignedSource<<e2a5086e5586caf4c90ef503416a0e83>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -387,6 +387,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::enableViewRecycling();
|
||||
}
|
||||
|
||||
bool enableViewRecyclingForScrollView() override {
|
||||
auto value = values_["enableViewRecyclingForScrollView"];
|
||||
if (!value.isNull()) {
|
||||
return value.getBool();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::enableViewRecyclingForScrollView();
|
||||
}
|
||||
|
||||
bool enableViewRecyclingForText() override {
|
||||
auto value = values_["enableViewRecyclingForText"];
|
||||
if (!value.isNull()) {
|
||||
@@ -639,6 +648,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef
|
||||
return ReactNativeFeatureFlagsDefaults::useTurboModules();
|
||||
}
|
||||
|
||||
double virtualViewHysteresisRatio() override {
|
||||
auto value = values_["virtualViewHysteresisRatio"];
|
||||
if (!value.isNull()) {
|
||||
return value.getDouble();
|
||||
}
|
||||
|
||||
return ReactNativeFeatureFlagsDefaults::virtualViewHysteresisRatio();
|
||||
}
|
||||
|
||||
double virtualViewPrerenderRatio() override {
|
||||
auto value = values_["virtualViewPrerenderRatio"];
|
||||
if (!value.isNull()) {
|
||||
|
||||
+1
-9
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<c9b7b95d3cc3fed879476f191a60d3f2>>
|
||||
* @generated SignedSource<<77870f0db494c7b6932950a1fa475fdc>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -34,14 +34,6 @@ class ReactNativeFeatureFlagsOverridesOSSExperimental : public ReactNativeFeatur
|
||||
bool preventShadowTreeCommitExhaustion() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool useNativeEqualsInNativeReadableArrayAndroid() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool useNativeTransformHelperAndroid() override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+3
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<56fe64198dddcba67062ef52a180128e>>
|
||||
* @generated SignedSource<<feb44bb7ec97d29787eac070103f9e1b>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -63,6 +63,7 @@ class ReactNativeFeatureFlagsProvider {
|
||||
virtual bool enableResourceTimingAPI() = 0;
|
||||
virtual bool enableViewCulling() = 0;
|
||||
virtual bool enableViewRecycling() = 0;
|
||||
virtual bool enableViewRecyclingForScrollView() = 0;
|
||||
virtual bool enableViewRecyclingForText() = 0;
|
||||
virtual bool enableViewRecyclingForView() = 0;
|
||||
virtual bool enableVirtualViewDebugFeatures() = 0;
|
||||
@@ -91,6 +92,7 @@ class ReactNativeFeatureFlagsProvider {
|
||||
virtual bool useShadowNodeStateOnClone() = 0;
|
||||
virtual bool useTurboModuleInterop() = 0;
|
||||
virtual bool useTurboModules() = 0;
|
||||
virtual double virtualViewHysteresisRatio() = 0;
|
||||
virtual double virtualViewPrerenderRatio() = 0;
|
||||
};
|
||||
|
||||
|
||||
+11
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<3c321b78f9d710e5f3dc3a73e56be298>>
|
||||
* @generated SignedSource<<c9c36c1dbece9e27f7b71da7611cb747>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -234,6 +234,11 @@ bool NativeReactNativeFeatureFlags::enableViewRecycling(
|
||||
return ReactNativeFeatureFlags::enableViewRecycling();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enableViewRecyclingForScrollView(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enableViewRecyclingForScrollView();
|
||||
}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::enableViewRecyclingForText(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::enableViewRecyclingForText();
|
||||
@@ -374,6 +379,11 @@ bool NativeReactNativeFeatureFlags::useTurboModules(
|
||||
return ReactNativeFeatureFlags::useTurboModules();
|
||||
}
|
||||
|
||||
double NativeReactNativeFeatureFlags::virtualViewHysteresisRatio(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::virtualViewHysteresisRatio();
|
||||
}
|
||||
|
||||
double NativeReactNativeFeatureFlags::virtualViewPrerenderRatio(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::virtualViewPrerenderRatio();
|
||||
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<15625838a3b9e9ecf3e77940a5f019a6>>
|
||||
* @generated SignedSource<<320e69fa54228a352fad210e3a43b947>>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -112,6 +112,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool enableViewRecycling(jsi::Runtime& runtime);
|
||||
|
||||
bool enableViewRecyclingForScrollView(jsi::Runtime& runtime);
|
||||
|
||||
bool enableViewRecyclingForText(jsi::Runtime& runtime);
|
||||
|
||||
bool enableViewRecyclingForView(jsi::Runtime& runtime);
|
||||
@@ -168,6 +170,8 @@ class NativeReactNativeFeatureFlags
|
||||
|
||||
bool useTurboModules(jsi::Runtime& runtime);
|
||||
|
||||
double virtualViewHysteresisRatio(jsi::Runtime& runtime);
|
||||
|
||||
double virtualViewPrerenderRatio(jsi::Runtime& runtime);
|
||||
};
|
||||
|
||||
|
||||
+3
-1
@@ -20,7 +20,9 @@ Size SwitchShadowNode::measureContent(
|
||||
const LayoutConstraints & /*layoutConstraints*/) const
|
||||
{
|
||||
CGSize uiSwitchSize = RCTSwitchSize();
|
||||
return {.width = uiSwitchSize.width, .height = uiSwitchSize.height};
|
||||
// Apple has some error when returning the width of the component and it doesn't
|
||||
// account for the borders.
|
||||
return {.width = uiSwitchSize.width + 2, .height = uiSwitchSize.height};
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+1
-1
@@ -184,7 +184,7 @@ static inline facebook::react::ColorComponents _ColorComponentsFromUIColor(UICol
|
||||
{
|
||||
CGFloat rgba[4];
|
||||
[color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
|
||||
return {(float)rgba[0], (float)rgba[1], (float)rgba[2], (float)rgba[3]};
|
||||
return {.red = (float)rgba[0], .green = (float)rgba[1], .blue = (float)rgba[2], .alpha = (float)rgba[3]};
|
||||
}
|
||||
|
||||
facebook::react::ColorComponents RCTPlatformColorComponentsFromSemanticItems(std::vector<std::string> &semanticItems)
|
||||
|
||||
@@ -126,6 +126,8 @@ static void calculateShadowViewMutations(
|
||||
const CullingContext& oldCullingContext = {},
|
||||
const CullingContext& newCullingContext = {});
|
||||
|
||||
namespace {
|
||||
|
||||
struct OrderedMutationInstructionContainer {
|
||||
ShadowViewMutation::List createMutations{};
|
||||
ShadowViewMutation::List deleteMutations{};
|
||||
@@ -136,6 +138,8 @@ struct OrderedMutationInstructionContainer {
|
||||
ShadowViewMutation::List destructiveDownwardMutations{};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static void updateMatchedPairSubtrees(
|
||||
ViewNodePairScope& scope,
|
||||
OrderedMutationInstructionContainer& mutationContainer,
|
||||
|
||||
+36
-33
@@ -187,34 +187,36 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
std::vector<LineMeasurement> paragraphLines{};
|
||||
auto blockParagraphLines = ¶graphLines;
|
||||
|
||||
[layoutManager enumerateLineFragmentsForGlyphRange:glyphRange
|
||||
usingBlock:^(
|
||||
CGRect overallRect,
|
||||
CGRect usedRect,
|
||||
NSTextContainer *_Nonnull usedTextContainer,
|
||||
NSRange lineGlyphRange,
|
||||
BOOL *_Nonnull stop) {
|
||||
NSRange range = [layoutManager characterRangeForGlyphRange:lineGlyphRange
|
||||
actualGlyphRange:nil];
|
||||
NSString *renderedString = [textStorage.string substringWithRange:range];
|
||||
UIFont *font = [[textStorage attributedSubstringFromRange:range]
|
||||
attribute:NSFontAttributeName
|
||||
atIndex:0
|
||||
effectiveRange:nil];
|
||||
auto rect = facebook::react::Rect{
|
||||
facebook::react::Point{usedRect.origin.x, usedRect.origin.y},
|
||||
facebook::react::Size{usedRect.size.width, usedRect.size.height}};
|
||||
[layoutManager
|
||||
enumerateLineFragmentsForGlyphRange:glyphRange
|
||||
usingBlock:^(
|
||||
CGRect overallRect,
|
||||
CGRect usedRect,
|
||||
NSTextContainer *_Nonnull usedTextContainer,
|
||||
NSRange lineGlyphRange,
|
||||
BOOL *_Nonnull stop) {
|
||||
NSRange range = [layoutManager characterRangeForGlyphRange:lineGlyphRange
|
||||
actualGlyphRange:nil];
|
||||
NSString *renderedString = [textStorage.string substringWithRange:range];
|
||||
UIFont *font =
|
||||
[[textStorage attributedSubstringFromRange:range] attribute:NSFontAttributeName
|
||||
atIndex:0
|
||||
effectiveRange:nil];
|
||||
auto rect = facebook::react::Rect{
|
||||
.origin = facebook::react::Point{.x = usedRect.origin.x, .y = usedRect.origin.y},
|
||||
.size = facebook::react::Size{
|
||||
.width = usedRect.size.width, .height = usedRect.size.height}};
|
||||
|
||||
CGFloat baseline = [layoutManager locationForGlyphAtIndex:range.location].y;
|
||||
auto line = LineMeasurement{
|
||||
std::string([renderedString UTF8String]),
|
||||
rect,
|
||||
overallRect.size.height - baseline,
|
||||
font.capHeight,
|
||||
baseline,
|
||||
font.xHeight};
|
||||
blockParagraphLines->push_back(line);
|
||||
}];
|
||||
CGFloat baseline = [layoutManager locationForGlyphAtIndex:range.location].y;
|
||||
auto line = LineMeasurement{
|
||||
std::string([renderedString UTF8String]),
|
||||
rect,
|
||||
overallRect.size.height - baseline,
|
||||
font.capHeight,
|
||||
baseline,
|
||||
font.xHeight};
|
||||
blockParagraphLines->push_back(line);
|
||||
}];
|
||||
return paragraphLines;
|
||||
}
|
||||
|
||||
@@ -416,19 +418,20 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
atIndex:0
|
||||
effectiveRange:nil];
|
||||
frame = {
|
||||
{glyphRect.origin.x,
|
||||
glyphRect.origin.y + glyphRect.size.height - attachmentSize.height + font.descender},
|
||||
attachmentSize};
|
||||
.origin =
|
||||
{glyphRect.origin.x,
|
||||
glyphRect.origin.y + glyphRect.size.height - attachmentSize.height + font.descender},
|
||||
.size = attachmentSize};
|
||||
|
||||
auto rect = facebook::react::Rect{
|
||||
facebook::react::Point{frame.origin.x, frame.origin.y},
|
||||
facebook::react::Size{frame.size.width, frame.size.height}};
|
||||
.origin = facebook::react::Point{.x = frame.origin.x, .y = frame.origin.y},
|
||||
.size = facebook::react::Size{.width = frame.size.width, .height = frame.size.height}};
|
||||
|
||||
attachments.push_back(TextMeasurement::Attachment{.frame = rect, .isClipped = false});
|
||||
}
|
||||
}];
|
||||
|
||||
return TextMeasurement{{size.width, size.height}, attachments};
|
||||
return TextMeasurement{.size = {.width = size.width, .height = size.height}, .attachments = attachments};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+25
-20
@@ -39,23 +39,27 @@ TextMeasurement TextLayoutManager::measure(
|
||||
case AttributedStringBox::Mode::Value: {
|
||||
auto attributedString = ensurePlaceholderIfEmpty_DO_NOT_USE(attributedStringBox.getValue());
|
||||
|
||||
measurement = textMeasureCache_.get({attributedString, paragraphAttributes, layoutConstraints}, [&]() {
|
||||
auto telemetry = TransactionTelemetry::threadLocalTelemetry();
|
||||
if (telemetry) {
|
||||
telemetry->willMeasureText();
|
||||
}
|
||||
measurement = textMeasureCache_.get(
|
||||
{.attributedString = attributedString,
|
||||
.paragraphAttributes = paragraphAttributes,
|
||||
.layoutConstraints = layoutConstraints},
|
||||
[&]() {
|
||||
auto telemetry = TransactionTelemetry::threadLocalTelemetry();
|
||||
if (telemetry) {
|
||||
telemetry->willMeasureText();
|
||||
}
|
||||
|
||||
auto measurement = [textLayoutManager measureAttributedString:attributedString
|
||||
paragraphAttributes:paragraphAttributes
|
||||
layoutContext:layoutContext
|
||||
layoutConstraints:layoutConstraints];
|
||||
auto measurement = [textLayoutManager measureAttributedString:attributedString
|
||||
paragraphAttributes:paragraphAttributes
|
||||
layoutContext:layoutContext
|
||||
layoutConstraints:layoutConstraints];
|
||||
|
||||
if (telemetry) {
|
||||
telemetry->didMeasureText();
|
||||
}
|
||||
if (telemetry) {
|
||||
telemetry->didMeasureText();
|
||||
}
|
||||
|
||||
return measurement;
|
||||
});
|
||||
return measurement;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -96,12 +100,13 @@ LinesMeasurements TextLayoutManager::measureLines(
|
||||
|
||||
RCTTextLayoutManager *textLayoutManager = (RCTTextLayoutManager *)unwrapManagedObject(nativeTextLayoutManager_);
|
||||
|
||||
auto measurement = lineMeasureCache_.get({attributedString, paragraphAttributes, size}, [&]() {
|
||||
auto measurement = [textLayoutManager getLinesForAttributedString:attributedString
|
||||
paragraphAttributes:paragraphAttributes
|
||||
size:{size.width, size.height}];
|
||||
return measurement;
|
||||
});
|
||||
auto measurement = lineMeasureCache_.get(
|
||||
{.attributedString = attributedString, .paragraphAttributes = paragraphAttributes, .size = size}, [&]() {
|
||||
auto measurement = [textLayoutManager getLinesForAttributedString:attributedString
|
||||
paragraphAttributes:paragraphAttributes
|
||||
size:{size.width, size.height}];
|
||||
return measurement;
|
||||
});
|
||||
|
||||
return measurement;
|
||||
}
|
||||
|
||||
-2
@@ -27,8 +27,6 @@ const std::string JS_SAMPLING_TRACK = "JS Sampling";
|
||||
|
||||
const int SAMPLING_HZ = 1000;
|
||||
|
||||
using perfetto::TrackEvent;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
std::string getApplicationId() {
|
||||
pid_t pid = getpid();
|
||||
|
||||
+1
-3
@@ -23,8 +23,6 @@ const int SAMPLING_HZ = 100;
|
||||
|
||||
int64_t hermesDeltaTime = 0;
|
||||
|
||||
using perfetto::TrackEvent;
|
||||
|
||||
uint64_t hermesToPerfettoTime(int64_t hermesTs) {
|
||||
if (hermesDeltaTime == 0) {
|
||||
hermesDeltaTime = TrackEvent::GetTraceTimeNs() -
|
||||
@@ -113,7 +111,7 @@ void HermesPerfettoDataSource::OnStart(const StartArgs&) {
|
||||
"react-native",
|
||||
perfetto::DynamicString{"Profiling Started"},
|
||||
getPerfettoWebPerfTrackSync("JS Sampling"),
|
||||
perfetto::TrackEvent::GetTraceTimeNs());
|
||||
TrackEvent::GetTraceTimeNs());
|
||||
}
|
||||
|
||||
void HermesPerfettoDataSource::OnFlush(const FlushArgs&) {
|
||||
|
||||
@@ -29,7 +29,7 @@ void initializePerfetto() {
|
||||
args.backends |= perfetto::kSystemBackend;
|
||||
args.use_monotonic_clock = true;
|
||||
perfetto::Tracing::Initialize(args);
|
||||
perfetto::TrackEvent::Register();
|
||||
TrackEvent::Register();
|
||||
});
|
||||
|
||||
HermesPerfettoDataSource::RegisterDataSource();
|
||||
@@ -42,7 +42,7 @@ static perfetto::Track createTrack(const std::string& trackName) {
|
||||
auto track = perfetto::Track(trackId++);
|
||||
auto desc = track.Serialize();
|
||||
desc.set_name(trackName);
|
||||
perfetto::TrackEvent::SetTrackDescriptor(track, desc);
|
||||
TrackEvent::SetTrackDescriptor(track, desc);
|
||||
return track;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user