diff --git a/packages/react-native/Libraries/BatchedBridge/MessageQueue.js b/packages/react-native/Libraries/BatchedBridge/MessageQueue.js index 2d0a98f2601..97ea2ca70b8 100644 --- a/packages/react-native/Libraries/BatchedBridge/MessageQueue.js +++ b/packages/react-native/Libraries/BatchedBridge/MessageQueue.js @@ -57,7 +57,8 @@ class MessageQueue { __spy: ?(data: SpyData) => void; constructor() { - this._lazyCallableModules = {}; + // $FlowFixMe[incompatible-type] Object.create(null) is used as a string-keyed map. + this._lazyCallableModules = Object.create(null); this._queue = [[], [], [], 0]; this._successCallbacks = new Map(); this._failureCallbacks = new Map(); diff --git a/packages/react-native/Libraries/BatchedBridge/__tests__/MessageQueue-itest.js b/packages/react-native/Libraries/BatchedBridge/__tests__/MessageQueue-itest.js index af908a23284..6b27b521c71 100644 --- a/packages/react-native/Libraries/BatchedBridge/__tests__/MessageQueue-itest.js +++ b/packages/react-native/Libraries/BatchedBridge/__tests__/MessageQueue-itest.js @@ -137,6 +137,18 @@ describe('MessageQueue', () => { expect(queue.getCallableModule(name)).toEqual(dummyModule); }); + it('should not return inherited Object properties as callable modules', () => { + expect(queue.getCallableModule('constructor')).toBeNull(); + expect(queue.getCallableModule('__proto__')).toBeNull(); + }); + + it('should register callable modules named __proto__', () => { + const dummyModule = {}; + queue.registerCallableModule('__proto__', dummyModule); + + expect(queue.getCallableModule('__proto__')).toBe(dummyModule); + }); + it('should not initialize lazily registered module before it was used for the first time', () => { const dummyModule = {}, name = 'modulesName';