Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
*/

import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
import {isBridgeless} from '../../src/private/runtime/ReactNativeRuntimeGlobals';
import Platform from '../Utilities/Platform';

function shouldUseTurboAnimatedModule(): boolean {
if (ReactNativeFeatureFlags.cxxNativeAnimatedEnabled()) {
return false;
} else {
return Platform.OS === 'ios' && global.RN$Bridgeless === true;
return Platform.OS === 'ios' && isBridgeless;
}
}

Expand Down
24 changes: 12 additions & 12 deletions packages/react-native/Libraries/BatchedBridge/MessageQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@

'use strict';

const {
isBridgeless,
nativeCallSyncHook,
nativeFlushQueueImmediate,
nativeTraceBeginAsyncFlow,
} = require('../../src/private/runtime/ReactNativeRuntimeGlobals');
const Systrace = require('../Performance/Systrace');
const deepFreezeAndThrowOnMutationInDev =
require('../Utilities/deepFreezeAndThrowOnMutationInDev').default;
Expand Down Expand Up @@ -179,15 +185,15 @@ class MessageQueue {
): unknown {
if (__DEV__) {
invariant(
global.nativeCallSyncHook,
nativeCallSyncHook,
'Calling synchronous methods on native ' +
'modules is not supported in Chrome.\n\n Consider providing alternative ' +
'methods to expose this method in debug mode, e.g. by exposing constants ' +
'ahead-of-time.',
);
}
this.processCallbacks(moduleID, methodID, params, onFail, onSucc);
return global.nativeCallSyncHook(moduleID, methodID, params);
return nativeCallSyncHook?.(moduleID, methodID, params);
}

processCallbacks(
Expand Down Expand Up @@ -231,12 +237,7 @@ class MessageQueue {
this._failureCallbacks.set(this._callID, onFail);
}
if (__DEV__) {
global.nativeTraceBeginAsyncFlow &&
global.nativeTraceBeginAsyncFlow(
TRACE_TAG_REACT,
'native',
this._callID,
);
nativeTraceBeginAsyncFlow?.(TRACE_TAG_REACT, 'native', this._callID);
}
this._callID++;
}
Expand Down Expand Up @@ -317,13 +318,13 @@ class MessageQueue {

const now = Date.now();
if (
global.nativeFlushQueueImmediate &&
nativeFlushQueueImmediate != null &&
now - this._lastFlush >= MIN_TIME_BETWEEN_FLUSHES_MS
) {
const queue = this._queue;
this._queue = [[], [], [], this._callID];
this._lastFlush = now;
global.nativeFlushQueueImmediate(queue);
nativeFlushQueueImmediate(queue);
}
Systrace.counterEvent('pending_js_to_native_queue', this._queue[0].length);
if (__DEV__ && this.__spy && isFinite(moduleID)) {
Expand Down Expand Up @@ -422,8 +423,7 @@ class MessageQueue {
const callableModuleNameList = callableModuleNames.join(', ');

// TODO(T122225939): Remove after investigation: Why are we getting to this line in bridgeless mode?
const isBridgelessMode =
global.RN$Bridgeless === true ? 'true' : 'false';
const isBridgelessMode = isBridgeless ? 'true' : 'false';
invariant(
false,
`Failed to call into JavaScript module method ${module}.${method}(). Module has not been registered as callable. Bridgeless Mode: ${isBridgelessMode}. Registered callable JavaScript modules (n = ${n}): ${callableModuleNameList}.
Expand Down
27 changes: 13 additions & 14 deletions packages/react-native/Libraries/BatchedBridge/NativeModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@

'use strict';

import type {ModuleConfig} from '../../src/private/runtime/ReactNativeRuntimeGlobals';
import type {ExtendedError} from '../Core/ExtendedError';

const {
batchedBridgeConfig,
nativeModuleProxy,
nativeRequireModuleConfig,
} = require('../../src/private/runtime/ReactNativeRuntimeGlobals');
const BatchedBridge = require('./BatchedBridge').default;
const invariant = require('invariant');

export type ModuleConfig = [
string /* name */,
?{...} /* constants */,
?ReadonlyArray<string> /* functions */,
?ReadonlyArray<number> /* promise method IDs */,
?ReadonlyArray<number> /* sync method IDs */,
];
export type {ModuleConfig} from '../../src/private/runtime/ReactNativeRuntimeGlobals';

export type MethodType = 'async' | 'promise' | 'sync';

Expand Down Expand Up @@ -88,10 +88,10 @@ global.__fbGenNativeModule = genModule;

function loadModule(name: string, moduleID: number): ?{...} {
invariant(
global.nativeRequireModuleConfig,
nativeRequireModuleConfig,
"Can't lazily create module without nativeRequireModuleConfig",
);
const config = global.nativeRequireModuleConfig(name);
const config = nativeRequireModuleConfig(name);
const info = genModule(config, moduleID);
return info && info.module;
}
Expand Down Expand Up @@ -182,18 +182,17 @@ function updateErrorWithErrorData(

/* $FlowFixMe[unclear-type] unclear type of NativeModules */
let NativeModules: {[moduleName: string]: any, ...} = {};
if (global.nativeModuleProxy) {
NativeModules = global.nativeModuleProxy;
if (nativeModuleProxy) {
NativeModules = nativeModuleProxy;
} else {
const bridgeConfig = global.__fbBatchedBridgeConfig;
invariant(
bridgeConfig,
batchedBridgeConfig,
'__fbBatchedBridgeConfig is not set, cannot invoke native modules',
);

const defineLazyObjectProperty =
require('../Utilities/defineLazyObjectProperty').default;
(bridgeConfig.remoteModuleConfig || []).forEach(
(batchedBridgeConfig.remoteModuleConfig || []).forEach(
(config: ModuleConfig, moduleID: number) => {
// Initially this config will only contain the module name when running in JSC. The actual
// configuration of the module will be lazily loaded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,24 +205,32 @@ describe('MessageQueue', function () {
});

describe('sync methods', () => {
afterEach(function () {
delete global.nativeCallSyncHook;
});

it('throwing an exception', function () {
global.nativeCallSyncHook = jest.fn(() => {
const mockNativeCallSyncHook = jest.fn(() => {
throw new Error('firstFailure');
});

jest.resetModules();
jest.doMock(
'../../../src/private/runtime/ReactNativeRuntimeGlobals',
() => ({
...jest.requireActual(
'../../../src/private/runtime/ReactNativeRuntimeGlobals',
),
nativeCallSyncHook: mockNativeCallSyncHook,
}),
);
NativeModules = require('../NativeModules').default;

let error;
try {
NativeModules.RemoteModule1.syncMethod('paloAlto', 'menloPark');
} catch (e) {
} catch (e: mixed) {
error = e;
}

expect(global.nativeCallSyncHook).toBeCalledTimes(1);
expect(global.nativeCallSyncHook).toBeCalledWith(
expect(mockNativeCallSyncHook).toHaveBeenCalledTimes(1);
expect(mockNativeCallSyncHook).toHaveBeenCalledWith(
0, // `RemoteModule1`
3, // `syncMethod`
['paloAlto', 'menloPark'],
Expand All @@ -234,14 +242,26 @@ describe('MessageQueue', function () {
});

it('returning a value', function () {
global.nativeCallSyncHook = jest.fn(() => {
const mockNativeCallSyncHook = jest.fn(() => {
return 'secondSucc';
});

jest.resetModules();
jest.doMock(
'../../../src/private/runtime/ReactNativeRuntimeGlobals',
() => ({
...jest.requireActual(
'../../../src/private/runtime/ReactNativeRuntimeGlobals',
),
nativeCallSyncHook: mockNativeCallSyncHook,
}),
);
NativeModules = require('../NativeModules').default;

const result = NativeModules.RemoteModule2.syncMethod('mac', 'windows');

expect(global.nativeCallSyncHook).toBeCalledTimes(1);
expect(global.nativeCallSyncHook).toBeCalledWith(
expect(mockNativeCallSyncHook).toHaveBeenCalledTimes(1);
expect(mockNativeCallSyncHook).toHaveBeenCalledWith(
1, // `RemoteModule2`
3, // `syncMethod`
['mac', 'windows'],
Expand Down
5 changes: 3 additions & 2 deletions packages/react-native/Libraries/Blob/BlobManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import typeof BlobT from './Blob';
import type {BlobCollector, BlobData, BlobOptions} from './BlobTypes';

import {blobCollectorProvider} from '../../src/private/runtime/ReactNativeRuntimeGlobals';
import NativeBlobModule from './NativeBlobModule';
import invariant from 'invariant';

Expand Down Expand Up @@ -40,10 +41,10 @@ function uuidv4(): string {
// that the current bridge infra doesn't allow to track js objects
// deallocation. Ideally the whole Blob object should be a jsi::HostObject.
function createBlobCollector(blobId: string): BlobCollector | null {
if (global.__blobCollectorProvider == null) {
if (blobCollectorProvider == null) {
return null;
} else {
return global.__blobCollectorProvider(blobId);
return blobCollectorProvider(blobId) ?? null;
}
}

Expand Down
21 changes: 14 additions & 7 deletions packages/react-native/Libraries/Core/ExceptionsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
import type {ExtendedError} from './ExtendedError';
import type {ExceptionData} from './NativeExceptionsManager';

import {
handleException as nativeHandleException,
hasHandledFatalException as nativeHasHandledFatalException,
inExceptionHandler as nativeInExceptionHandler,
notifyOfFatalException as nativeNotifyOfFatalException,
} from '../../src/private/runtime/ReactNativeRuntimeGlobals';

export class SyntheticError extends Error {
name: string = '';
}
Expand Down Expand Up @@ -124,10 +131,10 @@ function reportException(
require('./NativeExceptionsManager').default;
if (NativeExceptionsManager) {
if (isFatal) {
if (global.RN$hasHandledFatalException?.()) {
if (nativeHasHandledFatalException?.()) {
return;
}
global.RN$notifyOfFatalException?.();
nativeNotifyOfFatalException?.();
}
NativeExceptionsManager.reportException(data);
}
Expand All @@ -152,8 +159,8 @@ function handleException(e: unknown, isFatal: boolean) {
// TODO(T196834299): We should really use a c++ turbomodule for this
const reportToConsole = true;
if (
!global.RN$handleException ||
!global.RN$handleException(e, isFatal, reportToConsole)
!nativeHandleException ||
!nativeHandleException(e, isFatal, reportToConsole)
) {
let error: Error;
if (e instanceof Error) {
Expand Down Expand Up @@ -185,7 +192,7 @@ function reactConsoleErrorHandler(...args) {
if (!console.reportErrorsAsExceptions) {
return;
}
if (inExceptionHandler || global.RN$inExceptionHandler?.()) {
if (inExceptionHandler || nativeInExceptionHandler?.()) {
// The fundamental trick here is that are multiple entry point to logging errors:
// (see D19743075 for more background)
//
Expand Down Expand Up @@ -236,8 +243,8 @@ function reactConsoleErrorHandler(...args) {
const isFatal = false;
const reportToConsole = false;
if (
!global.RN$handleException ||
!global.RN$handleException(error, isFatal, reportToConsole)
!nativeHandleException ||
!nativeHandleException(error, isFatal, reportToConsole)
) {
if (__DEV__) {
// If we're not reporting to the console in reportException,
Expand Down
11 changes: 8 additions & 3 deletions packages/react-native/Libraries/Core/registerCallableModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,26 @@

'use strict';

import {
isBridgeless,
registerCallableModule as nativeRegisterCallableModule,
} from '../../src/private/runtime/ReactNativeRuntimeGlobals';

type Module = {...};
type RegisterCallableModule = (
name: string,
moduleOrFactory: Module | (void => Module),
) => void;

const registerCallableModule: RegisterCallableModule = (function () {
if (global.RN$Bridgeless === true) {
if (isBridgeless) {
return (name, moduleOrFactory) => {
if (typeof moduleOrFactory === 'function') {
global.RN$registerCallableModule(name, moduleOrFactory);
nativeRegisterCallableModule?.(name, moduleOrFactory);
return;
}

global.RN$registerCallableModule(name, () => moduleOrFactory);
nativeRegisterCallableModule?.(name, () => moduleOrFactory);
};
}

Expand Down
3 changes: 2 additions & 1 deletion packages/react-native/Libraries/Core/setUpBatchedBridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

'use strict';

import {isBridgeless} from '../../src/private/runtime/ReactNativeRuntimeGlobals';
import registerModule from './registerCallableModule';

registerModule('Systrace', () => require('../Performance/Systrace'));
if (!(global.RN$Bridgeless === true)) {
if (!isBridgeless) {
registerModule('JSTimers', () => require('./Timers/JSTimers').default);
}
registerModule('RCTLog', () => require('../Utilities/RCTLog').default);
Expand Down
9 changes: 7 additions & 2 deletions packages/react-native/Libraries/Core/setUpErrorHandling.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@

'use strict';

if (global.RN$useAlwaysAvailableJSErrorHandling !== true) {
import {
disableExceptionsManager,
useAlwaysAvailableJSErrorHandling,
} from '../../src/private/runtime/ReactNativeRuntimeGlobals';

if (!useAlwaysAvailableJSErrorHandling) {
/**
* Sets up the console and exception handling (redbox) for React Native.
* You can use this module directly, or just require InitializeCore.
Expand All @@ -20,7 +25,7 @@ if (global.RN$useAlwaysAvailableJSErrorHandling !== true) {
ExceptionsManager.installConsoleErrorReporter();

// Set up error handler
if (!global.__fbDisableExceptionsManager) {
if (!disableExceptionsManager) {
const handleError = (e: unknown, isFatal: boolean) => {
try {
ExceptionsManager.handleException(e, isFatal);
Expand Down
3 changes: 2 additions & 1 deletion packages/react-native/Libraries/Core/setUpPerformance.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @format
*/

import {nativePerformanceNow} from '../../src/private/runtime/ReactNativeRuntimeGlobals';
import setUpPerformanceModern from '../../src/private/setup/setUpPerformanceModern';
import NativePerformance from '../../src/private/webapis/performance/specs/NativePerformance';

Expand All @@ -24,7 +25,7 @@ if (NativePerformance) {
measure: () => {},
clearMeasures: () => {},
now: () => {
const performanceNow = global.nativePerformanceNow || Date.now;
const performanceNow = nativePerformanceNow || Date.now;
return performanceNow();
},
};
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/Libraries/Core/setUpReactDevTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type {Domain} from '../../src/private/devsupport/rndevtools/setUpFuseboxR
import type {Spec as NativeReactDevToolsRuntimeSettingsModuleSpec} from '../../src/private/devsupport/rndevtools/specs/NativeReactDevToolsRuntimeSettingsModule';

if (__DEV__) {
if (typeof global.queueMicrotask !== 'function') {
if (typeof queueMicrotask !== 'function') {
console.error(
'queueMicrotask should exist before setting up React DevTools.',
);
Expand Down
Loading
Loading