react-native-firebase/tests-new/bridge/env/node/vm.js

115 lines
2.7 KiB
JavaScript
Raw Normal View History

/* eslint-disable guard-for-in,no-restricted-syntax,no-return-assign */
2018-03-24 02:02:59 +00:00
const url = require('url');
const http = require('http');
const invariant = require('assert');
const { Script } = require('vm');
const context = require('./context');
2018-03-24 02:02:59 +00:00
let send;
let bundle;
2018-03-24 02:02:59 +00:00
const PREPARE = 'prepareJSRuntime';
const EXECUTE = 'executeApplicationScript';
2018-03-24 02:02:59 +00:00
const TEMP_BUNDLE_PATH = '/tmp/bridge/react-native.js';
function reply(id, result) {
send({
replyID: id,
result,
});
2018-03-24 02:02:59 +00:00
}
function handleError(message) {
throw new Error(message);
2018-03-24 02:02:59 +00:00
}
async function downloadBundle(bundleUrl) {
const res = await new Promise((resolve, reject) =>
http.get(bundleUrl, resolve).on('error', reject)
);
2018-03-24 02:02:59 +00:00
let buffer = '';
2018-03-24 02:02:59 +00:00
res.setEncoding('utf8');
res.on('data', chunk => (buffer += chunk));
await new Promise(resolve => res.on('end', resolve));
2018-03-24 05:53:49 +00:00
bundle = new Script(buffer, {
timeout: 120000,
displayErrors: true,
filename: TEMP_BUNDLE_PATH,
});
2018-03-24 05:53:49 +00:00
return bundle;
2018-03-24 05:53:49 +00:00
}
async function getBundle(request) {
if (bundle) return bundle;
console.log('Downloading app bundle...');
2018-03-24 05:53:49 +00:00
const parsedUrl = url.parse(request.url, true);
invariant(parsedUrl.query);
parsedUrl.query.inlineSourceMap = true;
delete parsedUrl.search;
2018-03-24 05:53:49 +00:00
return downloadBundle(url.format(parsedUrl));
}
2018-03-24 02:02:59 +00:00
module.exports = {
set send(fn) {
send = fn;
},
async message(request) {
const { method } = request;
// console.log(request.method);
switch (method) {
case PREPARE:
await context.cleanup();
context.create();
reply(request.id);
break;
case EXECUTE: {
const script = await getBundle(request);
2018-03-24 07:09:45 +00:00
if (global.bridge.context == null) {
throw new Error('VM context was not prepared.');
2018-03-24 02:02:59 +00:00
}
if (request.inject) {
for (const name in request.inject) {
2018-03-24 07:09:45 +00:00
global.bridge.context[name] = JSON.parse(request.inject[name]);
2018-03-24 02:02:59 +00:00
}
}
script.runInContext(global.bridge.context, {
filename: TEMP_BUNDLE_PATH,
});
reply(request.id);
break;
}
2018-03-24 02:02:59 +00:00
default: {
let returnValue = [[], [], [], 0];
2018-03-24 02:02:59 +00:00
try {
if (
global.bridge.context != null &&
typeof global.bridge.context.__fbBatchedBridge === 'object'
) {
returnValue = global.bridge.context.__fbBatchedBridge[method].apply(
null,
request.arguments
);
}
2018-03-24 02:02:59 +00:00
} catch (e) {
if (method !== '$disconnected') {
handleError(
`Failed while making a call bridge call ${method}::${e.message}`
);
}
} finally {
reply(request.id, JSON.stringify(returnValue));
2018-03-24 05:53:49 +00:00
}
2018-03-24 02:02:59 +00:00
}
}
},
};