mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
Extract native module logic from BatchedBridge
Reviewed By: lexs Differential Revision: D3901630 fbshipit-source-id: c119ffe54a4d1e716e6ae98895e5a3a48b16cf43
This commit is contained in:
committed by
Facebook Github Bot 8
parent
31b158c9fe
commit
76c54847bb
@@ -9,13 +9,12 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const MessageQueueTestConfig = require('MessageQueueTestConfig');
|
||||
// const MessageQueueTestConfig = require('MessageQueueTestConfig');
|
||||
jest.unmock('MessageQueue');
|
||||
jest.unmock('defineLazyObjectProperty');
|
||||
|
||||
let MessageQueue;
|
||||
let MessageQueueTestModule1;
|
||||
let MessageQueueTestModule2;
|
||||
let MessageQueueTestModule;
|
||||
let queue;
|
||||
|
||||
const MODULE_IDS = 0;
|
||||
@@ -30,169 +29,59 @@ const assertQueue = (flushedQueue, index, moduleID, methodID, params) => {
|
||||
|
||||
// Important things to test:
|
||||
//
|
||||
// [x] Calling remote method on queue actually queues it up.
|
||||
//
|
||||
// [x] Both error and success callbacks are invoked.
|
||||
//
|
||||
// [x] When simulating an error callback from remote method, both error and
|
||||
// success callbacks are cleaned up.
|
||||
//
|
||||
// [x] Local modules can be invoked through the queue.
|
||||
//
|
||||
// [ ] Local modules that throw exceptions are gracefully caught. In that case
|
||||
// local callbacks stored by IDs are cleaned up.
|
||||
//
|
||||
// [ ] Remote invocation throws if not supplying an error callback.
|
||||
describe('MessageQueue', function() {
|
||||
beforeEach(function() {
|
||||
jest.resetModuleRegistry();
|
||||
MessageQueue = require('MessageQueue');
|
||||
MessageQueueTestModule1 = require('MessageQueueTestModule1');
|
||||
MessageQueueTestModule2 = require('MessageQueueTestModule2');
|
||||
queue = new MessageQueue(
|
||||
() => MessageQueueTestConfig
|
||||
);
|
||||
|
||||
MessageQueueTestModule = require('MessageQueueTestModule');
|
||||
queue = new MessageQueue();
|
||||
queue.registerCallableModule(
|
||||
'MessageQueueTestModule1',
|
||||
MessageQueueTestModule1
|
||||
);
|
||||
queue.registerCallableModule(
|
||||
'MessageQueueTestModule2',
|
||||
MessageQueueTestModule2
|
||||
'MessageQueueTestModule',
|
||||
MessageQueueTestModule
|
||||
);
|
||||
queue.createDebugLookup(0, 'MessageQueueTestModule',
|
||||
['testHook1', 'testHook2']);
|
||||
});
|
||||
|
||||
it('should enqueue native calls', () => {
|
||||
queue.__nativeCall(0, 1, [2]);
|
||||
queue.enqueueNativeCall(0, 1, [2]);
|
||||
const flushedQueue = queue.flushedQueue();
|
||||
assertQueue(flushedQueue, 0, 0, 1, [2]);
|
||||
});
|
||||
|
||||
it('should call a local function with the function name', () => {
|
||||
MessageQueueTestModule1.testHook2 = jasmine.createSpy();
|
||||
expect(MessageQueueTestModule1.testHook2.calls.count()).toEqual(0);
|
||||
queue.__callFunction('MessageQueueTestModule1', 'testHook2', [2]);
|
||||
expect(MessageQueueTestModule1.testHook2.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should generate native modules', () => {
|
||||
queue.RemoteModules.RemoteModule1.remoteMethod1('foo');
|
||||
const flushedQueue = queue.flushedQueue();
|
||||
assertQueue(flushedQueue, 0, 0, 0, ['foo']);
|
||||
MessageQueueTestModule.testHook2 = jasmine.createSpy();
|
||||
expect(MessageQueueTestModule.testHook2.calls.count()).toEqual(0);
|
||||
queue.__callFunction('MessageQueueTestModule', 'testHook2', [2]);
|
||||
expect(MessageQueueTestModule.testHook2.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should store callbacks', () => {
|
||||
queue.RemoteModules.RemoteModule1.remoteMethod2('foo', () => {}, () => {});
|
||||
queue.enqueueNativeCall(0, 1, ['foo'], null, null);
|
||||
const flushedQueue = queue.flushedQueue();
|
||||
assertQueue(flushedQueue, 0, 0, 1, ['foo', 0, 1]);
|
||||
assertQueue(flushedQueue, 0, 0, 1, ['foo']);
|
||||
});
|
||||
|
||||
it('should call the stored callback', () => {
|
||||
var done = false;
|
||||
queue.RemoteModules.RemoteModule1.remoteMethod1(() => { done = true; });
|
||||
let done = false;
|
||||
queue.enqueueNativeCall(0, 1, [], () => {}, () => { done = true; });
|
||||
queue.__invokeCallback(1);
|
||||
expect(done).toEqual(true);
|
||||
});
|
||||
|
||||
it('should throw when calling the same callback twice', () => {
|
||||
queue.RemoteModules.RemoteModule1.remoteMethod1(() => {});
|
||||
queue.enqueueNativeCall(0, 1, [], () => {}, () => {});
|
||||
queue.__invokeCallback(1);
|
||||
expect(() => queue.__invokeCallback(1)).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when calling both success and failure callback', () => {
|
||||
queue.RemoteModules.RemoteModule1.remoteMethod1(() => {}, () => {});
|
||||
queue.enqueueNativeCall(0, 1, [], () => {}, () => {});
|
||||
queue.__invokeCallback(1);
|
||||
expect(() => queue.__invokeCallback(0)).toThrow();
|
||||
});
|
||||
|
||||
it('should make round trip and clear memory', function() {
|
||||
// Perform communication
|
||||
|
||||
// First we're going to call into this (overriden) test hook pretending to
|
||||
// be a remote module making a "local" invocation into JS.
|
||||
const onFail = jasmine.createSpy();
|
||||
const onSucc = jasmine.createSpy();
|
||||
MessageQueueTestModule1.testHook1 = function() {
|
||||
// Then inside of this local module, we're going to fire off a remote
|
||||
// request.
|
||||
queue.__nativeCall(
|
||||
0,
|
||||
0,
|
||||
Array.prototype.slice.apply(arguments),
|
||||
onFail,
|
||||
onSucc,
|
||||
);
|
||||
};
|
||||
|
||||
// The second test hook does the same thing as the first, but fires off a
|
||||
// remote request to a different remote module/method.
|
||||
MessageQueueTestModule1.testHook2 = function() {
|
||||
queue.__nativeCall(
|
||||
1,
|
||||
1,
|
||||
Array.prototype.slice.apply(arguments),
|
||||
onFail,
|
||||
onSucc,
|
||||
);
|
||||
};
|
||||
|
||||
/* MessageQueueTestModule1.testHook1 */
|
||||
queue.__callFunction('MessageQueueTestModule1', 'testHook1', ['paloAlto', 'menloPark']);
|
||||
/* MessageQueueTestModule1.testHook2 */
|
||||
queue.__callFunction('MessageQueueTestModule1', 'testHook2', ['mac', 'windows']);
|
||||
|
||||
// And how do we know that it executed those local modules correctly? Well,
|
||||
// these particular test method echo their arguments back to remote methods!
|
||||
|
||||
var resultingRemoteInvocations = queue.flushedQueue();
|
||||
// As always, the message queue has five fields
|
||||
expect(resultingRemoteInvocations.length).toBe(4);
|
||||
expect(resultingRemoteInvocations[0].length).toBe(2);
|
||||
expect(resultingRemoteInvocations[1].length).toBe(2);
|
||||
expect(resultingRemoteInvocations[2].length).toBe(2);
|
||||
expect(typeof resultingRemoteInvocations[3]).toEqual('number');
|
||||
|
||||
expect(resultingRemoteInvocations[0][0]).toBe(0); // `RemoteModule1`
|
||||
expect(resultingRemoteInvocations[1][0]).toBe(0); // `remoteMethod1`
|
||||
expect([ // the arguments
|
||||
resultingRemoteInvocations[2][0][0],
|
||||
resultingRemoteInvocations[2][0][1]
|
||||
]).toEqual(['paloAlto', 'menloPark']);
|
||||
// Callbacks ids are tacked onto the end of the remote arguments.
|
||||
var firstFailCBID = resultingRemoteInvocations[2][0][2];
|
||||
var firstSuccCBID = resultingRemoteInvocations[2][0][3];
|
||||
|
||||
expect(resultingRemoteInvocations[0][1]).toBe(1); // `RemoteModule2`
|
||||
expect(resultingRemoteInvocations[1][1]).toBe(1); // `remoteMethod2`
|
||||
expect([ // the arguments
|
||||
resultingRemoteInvocations[2][1][0],
|
||||
resultingRemoteInvocations[2][1][1]
|
||||
]).toEqual(['mac', 'windows']);
|
||||
var secondFailCBID = resultingRemoteInvocations[2][1][2];
|
||||
var secondSuccCBID = resultingRemoteInvocations[2][1][3];
|
||||
|
||||
// Trigger init
|
||||
queue.RemoteModules;
|
||||
// Handle the first remote invocation by signaling failure.
|
||||
// -------------------------------------------------------
|
||||
queue.__invokeCallback(firstFailCBID, ['firstFailure']);
|
||||
// The failure callback was already invoked, the success is no longer valid
|
||||
expect(function() {
|
||||
queue.__invokeCallback(firstSuccCBID, ['firstSucc']);
|
||||
}).toThrow();
|
||||
expect(onFail.calls.count()).toBe(1);
|
||||
expect(onSucc.calls.count()).toBe(0);
|
||||
|
||||
// Handle the second remote invocation by signaling success.
|
||||
// -------------------------------------------------------
|
||||
queue.__invokeCallback(secondSuccCBID, ['secondSucc']);
|
||||
// The success callback was already invoked, the fail cb is no longer valid
|
||||
expect(function() {
|
||||
queue.__invokeCallback(secondFailCBID, ['secondFail']);
|
||||
}).toThrow();
|
||||
expect(onFail.calls.count()).toBe(1);
|
||||
expect(onSucc.calls.count()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user