Skip to content
Merged
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
13 changes: 5 additions & 8 deletions app/worker/devMenu.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
/* eslint-disable no-underscore-dangle */

import { avoidWarnForRequire } from './utils';
import { toggleNetworkInspect } from './networkInspect';

let availableDevMenuMethods = {};

export const checkAvailableDevMenuMethods = async (enableNetworkInspect = false) => {
const done = await avoidWarnForRequire('NativeModules', 'AsyncStorage');
const NativeModules = window.__DEV__ ? window.require('NativeModules') : {};
const AsyncStorage = window.__DEV__ ? window.require('AsyncStorage') : {};
done();

export const checkAvailableDevMenuMethods = async (
{ NativeModules, AsyncStorage },
enableNetworkInspect = false
) => {
// RN 0.43 use DevSettings, DevMenu will be deprecated
const DevSettings = NativeModules.DevSettings || NativeModules.DevMenu;
// Currently `show dev menu` is only on DevMenu
Expand All @@ -23,7 +20,7 @@ export const checkAvailableDevMenuMethods = async (enableNetworkInspect = false)
...DevSettings,
show: showDevMenu,
networkInspect: toggleNetworkInspect,
clearAsyncStorage: () => AsyncStorage.clear().catch(f => f),
clearAsyncStorage: AsyncStorage.clear ? () => AsyncStorage.clear().catch(f => f) : undefined,
};
const result = Object.keys(methods).filter(key => !!methods[key]);
availableDevMenuMethods = methods;
Expand Down
10 changes: 6 additions & 4 deletions app/worker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { checkAvailableDevMenuMethods, invokeDevMenuMethod } from './devMenu';
import { reportDefaultReactDevToolsPort } from './reactDevTools';
import devToolsEnhancer, { composeWithDevTools } from './reduxAPI';
import * as RemoteDev from './remotedev';
import { getRequiredModules, ignoreRNDIntervalSpy } from './utils';

/* eslint-disable no-underscore-dangle */
self.__REMOTEDEV__ = RemoteDev;
Expand All @@ -34,14 +35,15 @@ const setupRNDebuggerBeforeImportScript = message => {
self.__REACT_DEVTOOLS_PORT__ = message.reactDevToolsPort;
};

const setupRNDebugger = message => {
const setupRNDebugger = async message => {
// We need to regularly update JS runtime
// because the changes of worker message (Redux DevTools, DevMenu)
// doesn't notify to the remote JS runtime
self.__RND_INTERVAL__ = setInterval(function() {}, 100); // eslint-disable-line

checkAvailableDevMenuMethods(message.networkInspect);
reportDefaultReactDevToolsPort();
const modules = await getRequiredModules();
ignoreRNDIntervalSpy(modules);
checkAvailableDevMenuMethods(modules, message.networkInspect);
reportDefaultReactDevToolsPort(modules);
};

const messageHandlers = {
Expand Down
9 changes: 2 additions & 7 deletions app/worker/reactDevTools.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/* eslint-disable no-underscore-dangle */

import { avoidWarnForRequire } from './utils';

const methodGlobalName = '__REPORT_REACT_DEVTOOLS_PORT__';

const reportReactDevToolsPort = (port, platform) =>
Expand All @@ -10,11 +8,8 @@ const reportReactDevToolsPort = (port, platform) =>
platform,
});

export const reportDefaultReactDevToolsPort = async () => {
const done = await avoidWarnForRequire('setupDevtools', 'Platform');
const setupDevtools = window.__DEV__ ? window.require('setupDevtools') : undefined;
const Platform = window.__DEV__ ? window.require('Platform') : {};
done();
export const reportDefaultReactDevToolsPort = async ({ setupDevtools, Platform }) => {
if (Platform.__empty) return;
/*
* [Fallback] React Native version under 0.39 can't specified the port
*/
Expand Down
61 changes: 60 additions & 1 deletion app/worker/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable no-underscore-dangle */

// Avoid warning of use `window.require` on dev mode
export const avoidWarnForRequire = (...moduleNames) => {
const avoidWarnForRequire = moduleNames => {
if (!moduleNames.length) moduleNames.push('NativeModules');
return new Promise(resolve =>
setTimeout(() => {
Expand All @@ -20,3 +22,60 @@ export const avoidWarnForRequire = (...moduleNames) => {
})
);
};

const requiredModules = [
'MessageQueue',
'NativeModules',
'AsyncStorage',
'Platform',
'setupDevtools',
];
export const getRequiredModules = async () => {
const done = await avoidWarnForRequire(requiredModules);
const modules = {};
requiredModules.forEach(
name => (modules[name] = window.__DEV__ ? window.require(name) : { __empty: true })
);
done();
return modules;
};

const TO_JS = 0;
const isRNDInterval = info =>
info.type === TO_JS &&
info.module === 'JSTimersExecution' &&
info.method === 'callTimers' &&
info.args &&
info.args[0] &&
info.args[0][0] === self.__RND_INTERVAL__;

export const ignoreRNDIntervalSpy = async ({ MessageQueue }) => {
if (MessageQueue.__empty) return;
// Wrap spy function if it already set
if (MessageQueue.prototype.__spy) {
const originalSpyFn = MessageQueue.prototype.__spy;
MessageQueue.prototype.__spy = info => {
if (isRNDInterval(info)) return;
return originalSpyFn(info);
};
}
MessageQueue.spy = spyOrToggle => {
if (spyOrToggle === true) {
MessageQueue.prototype.__spy = info => {
if (isRNDInterval(info)) return;
console.log(
`${info.type === TO_JS ? 'N->JS' : 'JS->N'} : ` +
`${info.module ? `${info.module}.` : ''}${info.method}` +
`(${JSON.stringify(info.args)})`
);
};
} else if (spyOrToggle === false) {
MessageQueue.prototype.__spy = null;
} else {
MessageQueue.prototype.__spy = info => {
if (isRNDInterval(info)) return;
return spyOrToggle(info);
};
}
};
};
4 changes: 4 additions & 0 deletions test/e2e/fixture/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const requiredModules = {
Platform: {},
setupDevtools: undefined,
AsyncStorage: {},
MessageQueue: {
spy: () => {},
prototype: { __spy: null },
},
};
// Simulate React Native's window.require polyfill
window.require = moduleName => {
Expand Down