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

122 lines
2.9 KiB
JavaScript

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