feat: ✨ Created a mini nodeJS server with NewMan for testing without PostMan GUI.
This will mimic a run in a CD/CI environment or docker container.
This commit is contained in:
79
node_modules/uvm/lib/bridge-client.js
generated
vendored
Normal file
79
node_modules/uvm/lib/bridge-client.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* This is a cross-platform event emitter with bridge interface.
|
||||
* It uses Flatted as dependency where code is modified slightly to allow loading as a string
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hold reference to this for security purpose
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
const toString = String.prototype.toString;
|
||||
|
||||
/**
|
||||
* Generate code to be executed inside a VM for bootstrap.
|
||||
*
|
||||
* @param {String|Buffer} bootCode
|
||||
* @return {String}
|
||||
*/
|
||||
/* eslint-disable max-len */
|
||||
module.exports = function (bootCode) {
|
||||
return `;
|
||||
(function (emit) {
|
||||
/*! (c) 2020 Andrea Giammarchi, (ISC) */
|
||||
var Flatted=function(n){"use strict";var t=JSON.parse,r=JSON.stringify,e=Object.keys,a=String,u="string",f={},i="object",c=function(n,t){return t},l=function(n){return n instanceof a?a(n):n},o=function(n,t){return typeof t===u?new a(t):t},s=function(n,t,r){var e=a(t.push(r)-1);return n.set(r,e),e};return n.parse=function(n,r){var u=t(n,o).map(l),s=u[0],p=r||c,v=typeof s===i&&s?function n(t,r,u,c){for(var l=[],o=e(u),s=o.length,p=0;p<s;p++){var v=o[p],y=u[v];if(y instanceof a){var g=t[y];typeof g!==i||r.has(g)?u[v]=c.call(u,v,g):(r.add(g),u[v]=f,l.push({k:v,a:[t,r,g,c]}))}else u[v]!==f&&(u[v]=c.call(u,v,y))}for(var h=l.length,d=0;d<h;d++){var w=l[d],O=w.k,S=w.a;u[O]=c.call(u,O,n.apply(null,S))}return u}(u,new Set,s,p):s;return p.call({"":v},"",v)},n.stringify=function(n,t,e){for(var a=t&&typeof t===i?function(n,r){return""===n||-1<t.indexOf(n)?r:void 0}:t||c,f=new Map,l=[],o=[],p=+s(f,l,a.call({"":n},"",n)),v=!p;p<l.length;)v=!0,o[p]=r(l[p++],y,e);return"["+o.join(",")+"]";function y(n,t){if(v)return v=!v,t;var r=a.call(this,n,t);switch(typeof r){case i:if(null===r)return r;case u:return f.get(r)||s(f,l,r)}return r}},n}({});
|
||||
|
||||
/*! (C) Postdot Technologies, Inc (Apache-2.0) */
|
||||
var arrayProtoSlice = Array.prototype.slice;
|
||||
|
||||
bridge = { // ensure global using no var
|
||||
_events: {},
|
||||
emit: function (name) {
|
||||
var self = this,
|
||||
args = arrayProtoSlice.call(arguments, 1);
|
||||
this._events[name] && this._events[name].forEach(function (listener) {
|
||||
listener.apply(self, args);
|
||||
});
|
||||
},
|
||||
|
||||
dispatch: function () {
|
||||
emit(Flatted.stringify(arrayProtoSlice.call(arguments)));
|
||||
},
|
||||
|
||||
on: function (name, listener) {
|
||||
if (typeof listener !== 'function') { return; }
|
||||
!this._events[name] && (this._events[name] = []);
|
||||
this._events[name].push(listener);
|
||||
},
|
||||
|
||||
off: function (name, listener) {
|
||||
var e = this._events[name],
|
||||
i = e && e.length || 0;
|
||||
|
||||
if (!e) { return; }
|
||||
if (arguments.length === 1) {
|
||||
return delete this._events[name];
|
||||
}
|
||||
|
||||
if (typeof listener === 'function' && (i >= 1)) {
|
||||
while (i >= 0) {
|
||||
(e[i] === listener) && e.splice(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
if (!e.length) { delete this._events[name]; }
|
||||
}
|
||||
};
|
||||
|
||||
// create the dispatch function inside a closure to ensure that actual function references are never modified
|
||||
__uvm_dispatch = (function (bridge, bridgeEmit) { // ensure global by not using var statement
|
||||
return function (args) {
|
||||
bridgeEmit.apply(bridge, Flatted.parse(args));
|
||||
};
|
||||
}(bridge, bridge.emit));
|
||||
|
||||
}(__uvm_emit));
|
||||
|
||||
// boot code starts hereafter
|
||||
${(typeof bootCode === 'string') ? toString.call(bootCode) : ''};`;
|
||||
};
|
154
node_modules/uvm/lib/bridge.browser.js
generated
vendored
Normal file
154
node_modules/uvm/lib/bridge.browser.js
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/* istanbul ignore file */
|
||||
/*
|
||||
* @note options.dispatchTimeout is not implemented in browser sandbox because
|
||||
* there is no way to interrupt an infinite loop.
|
||||
* Maybe terminate and restart the worker or execute in nested worker.
|
||||
*/
|
||||
const Flatted = require('flatted'),
|
||||
{ randomNumber } = require('./utils'),
|
||||
|
||||
ERROR = 'error',
|
||||
MESSAGE = 'message',
|
||||
UVM_ID_ = '__id_uvm_',
|
||||
|
||||
// code for bridge
|
||||
bridgeClientCode = require('./bridge-client'),
|
||||
|
||||
/**
|
||||
* Returns the firmware code to be executed inside Web Worker.
|
||||
*
|
||||
* @private
|
||||
* @param {String} code -
|
||||
* @param {String} id -
|
||||
* @return {String}
|
||||
*/
|
||||
sandboxFirmware = (code, id) => {
|
||||
// @note self.postMessage and self.addEventListener methods are cached
|
||||
// in variable or closure because bootCode might mutate the global scope
|
||||
return `
|
||||
__uvm_emit = function (postMessage, args) {
|
||||
postMessage({__id_uvm: "${id}",__emit_uvm: args});
|
||||
}.bind(null, self.postMessage);
|
||||
__uvm_addEventListener = self.addEventListener;
|
||||
try {${code}} catch (e) { setTimeout(function () { throw e; }, 0); }
|
||||
(function (emit, id) {
|
||||
__uvm_addEventListener("message", function (e) {
|
||||
(e && e.data && (typeof e.data.__emit_uvm === 'string') && (e.data.__id_uvm === id)) &&
|
||||
emit(e.data.__emit_uvm);
|
||||
});
|
||||
}(__uvm_dispatch, "${id}"));
|
||||
__uvm_emit('${Flatted.stringify(['load.' + id])}');
|
||||
__uvm_dispatch = null; __uvm_emit = null; __uvm_addEventListener = null;
|
||||
delete __uvm_dispatch; delete __uvm_emit; delete __uvm_addEventListener;
|
||||
`;
|
||||
};
|
||||
|
||||
module.exports = function (bridge, options, callback) {
|
||||
if (!(Blob && Worker && window && window.URL && window.URL.createObjectURL)) {
|
||||
return callback(new Error('uvm: unable to setup communication bridge, missing required APIs'));
|
||||
}
|
||||
|
||||
let worker,
|
||||
bootTimer,
|
||||
firmwareCode,
|
||||
firmwareObjectURL;
|
||||
|
||||
const id = UVM_ID_ + randomNumber(),
|
||||
|
||||
// function to forward messages emitted
|
||||
forwardEmits = (e) => {
|
||||
if (!(e && e.data && (typeof e.data.__emit_uvm === 'string') && (e.data.__id_uvm === id))) { return; }
|
||||
|
||||
let args;
|
||||
|
||||
try { args = Flatted.parse(e.data.__emit_uvm); }
|
||||
catch (err) { return bridge.emit(ERROR, err); }
|
||||
bridge.emit(...args);
|
||||
},
|
||||
|
||||
// function to forward errors emitted
|
||||
forwardErrors = (e) => {
|
||||
bridge.emit(ERROR, e);
|
||||
},
|
||||
|
||||
// function to terminate worker
|
||||
terminateWorker = function () {
|
||||
if (!worker) { return; }
|
||||
|
||||
// remove event listeners for this sandbox
|
||||
worker.removeEventListener(MESSAGE, forwardEmits);
|
||||
worker.removeEventListener(ERROR, forwardErrors);
|
||||
|
||||
// do not terminate sandbox worker if not spawned for the bridge
|
||||
if (!options._sandbox) {
|
||||
worker.terminate();
|
||||
|
||||
// revoke after termination. otherwise, blob reference is retained until GC
|
||||
// refer: "chrome://blob-internals"
|
||||
window.URL.revokeObjectURL(firmwareObjectURL);
|
||||
}
|
||||
|
||||
worker = null;
|
||||
};
|
||||
|
||||
// on load attach the dispatcher
|
||||
bridge.once('load.' + id, () => {
|
||||
// stop boot timer first
|
||||
clearTimeout(bootTimer);
|
||||
|
||||
bridge._dispatch = function () {
|
||||
if (!worker) {
|
||||
return bridge.emit(ERROR,
|
||||
new Error('uvm: unable to dispatch "' + arguments[0] + '" post disconnection.'));
|
||||
}
|
||||
|
||||
worker.postMessage({
|
||||
__emit_uvm: Flatted.stringify(Array.prototype.slice.call(arguments)),
|
||||
__id_uvm: id
|
||||
});
|
||||
};
|
||||
|
||||
callback(null, bridge);
|
||||
});
|
||||
|
||||
// get firmware code string with boot code
|
||||
firmwareCode = sandboxFirmware(bridgeClientCode(options.bootCode), id);
|
||||
|
||||
// start boot timer, stops once we get the load signal, terminate otherwise
|
||||
bootTimer = setTimeout(() => {
|
||||
terminateWorker();
|
||||
callback(new Error(`uvm: boot timed out after ${options.bootTimeout}ms.`));
|
||||
}, options.bootTimeout);
|
||||
|
||||
// if sandbox worker is provided, we simply need to init with firmware code
|
||||
// @todo validate sandbox type or APIs
|
||||
if (options._sandbox) {
|
||||
worker = options._sandbox;
|
||||
worker.postMessage({ __init_uvm: firmwareCode });
|
||||
}
|
||||
// else, spawn a new worker
|
||||
else {
|
||||
// convert the firmware code into a blob URL
|
||||
firmwareObjectURL = window.URL.createObjectURL(new Blob([firmwareCode], { type: 'text/javascript' }));
|
||||
|
||||
// catch CSP:worker-src violations
|
||||
try { worker = new Worker(firmwareObjectURL); }
|
||||
catch (error) {
|
||||
// clear blob reference
|
||||
window.URL.revokeObjectURL(firmwareObjectURL);
|
||||
|
||||
return callback(new Error(`uvm: unable to spawn worker.\n${error.message || error}`));
|
||||
}
|
||||
}
|
||||
|
||||
// add event listener for receiving events from worker (is removed on disconnect)
|
||||
// don't set `onmessage` and `onerror` as it might override external sandbox
|
||||
worker.addEventListener(MESSAGE, forwardEmits);
|
||||
worker.addEventListener(ERROR, forwardErrors);
|
||||
|
||||
// equip bridge to disconnect (i.e. terminate the worker)
|
||||
bridge._disconnect = terminateWorker;
|
||||
|
||||
// help GC collect large variables
|
||||
firmwareCode = null;
|
||||
};
|
142
node_modules/uvm/lib/bridge.js
generated
vendored
Normal file
142
node_modules/uvm/lib/bridge.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
const vm = require('vm'),
|
||||
Flatted = require('flatted'),
|
||||
|
||||
{ isString, randomNumber } = require('./utils'),
|
||||
|
||||
bridgeClientCode = require('./bridge-client'),
|
||||
delegateTimers = require('./vm-delegate-timers'),
|
||||
|
||||
ERROR = 'error',
|
||||
UVM_DATA_ = '__uvm_data_',
|
||||
UVM_DISPATCH_ = '__uvm_dispatch_',
|
||||
|
||||
/**
|
||||
* Convert array or arguments object to JSON
|
||||
*
|
||||
* @private
|
||||
* @param {Array|Argument} arr
|
||||
* @return {String}
|
||||
*
|
||||
* @note This has been held as reference to avoid being misused if modified in global context;
|
||||
*/
|
||||
jsonArray = (function (arrayProtoSlice, jsonStringify) {
|
||||
return function (arr) {
|
||||
return jsonStringify(arrayProtoSlice.call(arr));
|
||||
};
|
||||
}(Array.prototype.slice, Flatted.stringify)),
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {String} str
|
||||
* @return {Array}
|
||||
*/
|
||||
unJsonArray = (function (jsonParse) {
|
||||
return function (str) {
|
||||
return jsonParse(str);
|
||||
};
|
||||
}(Flatted.parse));
|
||||
|
||||
/**
|
||||
* This function equips an event emitter with communication capability with a VM.
|
||||
*
|
||||
* @param {EventEmitter} emitter -
|
||||
* @param {Object} options -
|
||||
* @param {String} options.bootCode -
|
||||
* @param {vm~Context=} [options._sandbox] -
|
||||
* @param {Function} callback -
|
||||
*/
|
||||
module.exports = function (emitter, options, callback) {
|
||||
let code = bridgeClientCode(options.bootCode),
|
||||
context = options._sandbox || vm.createContext(Object.create(null)),
|
||||
bridgeDispatch;
|
||||
|
||||
// inject console on debug mode
|
||||
options.debug && (context.console = console);
|
||||
|
||||
// we need to inject the timers inside vm since VM does not have timers
|
||||
if (!options._sandbox) {
|
||||
delegateTimers(context);
|
||||
}
|
||||
|
||||
try {
|
||||
// inject the emitter via context. it will be referenced by the bridge and then deleted to prevent
|
||||
// additional access
|
||||
context.__uvm_emit = function (args) {
|
||||
/* istanbul ignore if */
|
||||
if (!isString(args)) { return; }
|
||||
|
||||
try { args = unJsonArray(args); }
|
||||
catch (err) { /* istanbul ignore next */ emitter.emit(ERROR, err); }
|
||||
|
||||
emitter.emit(...args);
|
||||
};
|
||||
|
||||
vm.runInContext(code, context, {
|
||||
timeout: options.bootTimeout
|
||||
});
|
||||
|
||||
// we keep a reference to the dispatcher so that we can preemptively re inject it in case it is deleted
|
||||
// by user scripts
|
||||
bridgeDispatch = context.__uvm_dispatch;
|
||||
}
|
||||
catch (err) {
|
||||
return callback(err);
|
||||
}
|
||||
finally { // set all raw interface methods to null (except the dispatcher since we need it later)
|
||||
vm.runInContext(`
|
||||
__uvm_emit = null; delete __uvm_emit; __uvm_dispatch = null; delete __uvm_dispatch;
|
||||
`, context);
|
||||
delete context.__uvm_emit;
|
||||
delete context.__uvm_dispatch;
|
||||
}
|
||||
|
||||
// since context is created and emitter is bound, we would now attach the send function
|
||||
emitter._dispatch = function () {
|
||||
const id = UVM_DATA_ + randomNumber(),
|
||||
dispatchId = UVM_DISPATCH_ + id;
|
||||
|
||||
// trigger event if any dispatch happens post disconnection
|
||||
if (!context) {
|
||||
return this.emit(ERROR, new Error(`uvm: unable to dispatch "${arguments[0]}" post disconnection.`));
|
||||
}
|
||||
|
||||
try {
|
||||
// save the data in context. by this method, we avoid needless string and character encoding or escaping
|
||||
// issues. this is slightly prone to race condition issues, but using random numbers we intend to solve it
|
||||
context[id] = jsonArray(arguments);
|
||||
context[dispatchId] = bridgeDispatch;
|
||||
|
||||
// restore the dispatcher for immediate use!
|
||||
vm.runInContext(`
|
||||
(function (dispatch, data) {
|
||||
${id} = null; (delete ${id});
|
||||
${dispatchId} = null; (delete ${dispatchId});
|
||||
dispatch(String(data));
|
||||
}(${dispatchId}, ${id}));
|
||||
`, context, {
|
||||
timeout: options.dispatchTimeout
|
||||
});
|
||||
}
|
||||
// swallow errors since other platforms will not trigger error if execution fails
|
||||
catch (e) { this.emit(ERROR, e); }
|
||||
finally { // precautionary delete
|
||||
if (context) {
|
||||
delete context[id];
|
||||
delete context[dispatchId];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
emitter._disconnect = function () {
|
||||
/* istanbul ignore if */
|
||||
if (!context) { return; }
|
||||
|
||||
// clear only if the context was created inside this function
|
||||
!options._sandbox && Object.keys(context).forEach((prop) => {
|
||||
delete context[prop];
|
||||
});
|
||||
context = null;
|
||||
};
|
||||
|
||||
callback(null, emitter);
|
||||
};
|
206
node_modules/uvm/lib/index.js
generated
vendored
Normal file
206
node_modules/uvm/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
const EventEmitter = require('events'),
|
||||
|
||||
bridge = require('./bridge'),
|
||||
{ isFunction, isObject } = require('./utils'),
|
||||
|
||||
/**
|
||||
* The time to wait for UVM boot to finish. In milliseconds.
|
||||
*
|
||||
* @private
|
||||
* @type {Number}
|
||||
*/
|
||||
DEFAULT_BOOT_TIMEOUT = 30 * 1000,
|
||||
|
||||
/**
|
||||
* The time to wait for UVM dispatch process to finish. In milliseconds.
|
||||
*
|
||||
* @private
|
||||
* @type {Number}
|
||||
*/
|
||||
DEFAULT_DISPATCH_TIMEOUT = 30 * 1000,
|
||||
|
||||
E = '',
|
||||
ERROR_EVENT = 'error',
|
||||
DISPATCH_QUEUE_EVENT = 'dispatchQueued';
|
||||
|
||||
/**
|
||||
* Configuration options for UniversalVM connection.
|
||||
*
|
||||
* @typedef UniversalVM.connectOptions
|
||||
*
|
||||
* @property {Boolean} [bootCode] Code to be executed inside a VM on boot
|
||||
* @property {Boolean} [_sandbox] Custom sandbox instance
|
||||
* @property {Boolean} [debug] Inject global console object in Node.js VM
|
||||
* @property {Boolean} [bootTimeout=30 * 1000] The time (in milliseconds) to wait for UVM boot to finish
|
||||
* @property {Boolean} [dispatchTimeout=30 * 1000] The time (in milliseconds) to wait for UVM dispatch process to finish
|
||||
*/
|
||||
|
||||
/**
|
||||
* Universal Virtual Machine for Node and Browser.
|
||||
*/
|
||||
class UniversalVM extends EventEmitter {
|
||||
constructor () {
|
||||
super();
|
||||
|
||||
/**
|
||||
* Boolean representing the bridge connectivity state.
|
||||
*
|
||||
* @private
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this._bridgeConnected = false;
|
||||
|
||||
/**
|
||||
* Stores the pending dispatch events until the context is ready for use.
|
||||
* Useful when not using the asynchronous construction.
|
||||
*
|
||||
* @private
|
||||
* @type {Array}
|
||||
*/
|
||||
this._dispatchQueue = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of UniversalVM.
|
||||
* This is merely an alias of the construction creation without needing to
|
||||
* write the `new` keyword and creating explicit connection.
|
||||
*
|
||||
* @param {UniversalVM.connectOptions} [options] Options to configure the UVM
|
||||
* @param {Function(error, context)} callback Callback function
|
||||
* @returns {Object} UVM event emitter instance
|
||||
*
|
||||
* @example
|
||||
* const uvm = require('uvm');
|
||||
*
|
||||
* uvm.spawn({
|
||||
* bootCode: `
|
||||
* bridge.on('loopback', function (data) {
|
||||
* bridge.dispatch('loopback', 'pong');
|
||||
* });
|
||||
* `
|
||||
* }, (err, context) => {
|
||||
* context.on('loopback', function (data) {
|
||||
* console.log(data); // pong
|
||||
* });
|
||||
*
|
||||
* context.dispatch('loopback', 'ping');
|
||||
* });
|
||||
*/
|
||||
static spawn (options, callback) {
|
||||
const uvm = new UniversalVM(options, callback);
|
||||
|
||||
// connect with the bridge
|
||||
uvm.connect(options, callback);
|
||||
|
||||
// return event emitter for chaining
|
||||
return uvm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection with the communication bridge.
|
||||
*
|
||||
* @param {UniversalVM.connectOptions} [options] Options to configure the UVM
|
||||
* @param {Function(error, context)} callback Callback function
|
||||
*/
|
||||
connect (options, callback) {
|
||||
// set defaults for parameters
|
||||
!isObject(options) && (options = {});
|
||||
|
||||
/**
|
||||
* Wrap the callback for unified result and reduce chance of bug.
|
||||
* We also abandon all dispatch replay.
|
||||
*
|
||||
* @private
|
||||
* @param {Error=} [err] -
|
||||
*/
|
||||
const done = (err) => {
|
||||
if (err) {
|
||||
// on error during bridging, we simply abandon all dispatch replay
|
||||
this._dispatchQueue.length = 0;
|
||||
|
||||
try { this.emit(ERROR_EVENT, err); }
|
||||
// nothing to do if listeners fail, we need to move on and execute callback!
|
||||
catch (e) { } // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
isFunction(callback) && callback.call(this, err, this);
|
||||
};
|
||||
|
||||
// bail out if bridge is connected
|
||||
if (this._bridgeConnected) {
|
||||
return done();
|
||||
}
|
||||
|
||||
// start connection with the communication bridge
|
||||
this._bridgeConnected = true;
|
||||
|
||||
// we bridge this event emitter with the context (bridge usually creates the context as well)
|
||||
bridge(this, Object.assign({ // eslint-disable-line prefer-object-spread
|
||||
bootCode: E,
|
||||
bootTimeout: DEFAULT_BOOT_TIMEOUT,
|
||||
dispatchTimeout: DEFAULT_DISPATCH_TIMEOUT
|
||||
}, options), (err) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
let args;
|
||||
|
||||
try {
|
||||
// we dispatch all pending messages provided nothing had errors
|
||||
while ((args = this._dispatchQueue.shift())) {
|
||||
this.dispatch(...args);
|
||||
}
|
||||
}
|
||||
// since there us no further work after dispatching events, we re-use the err parameter.
|
||||
// at this point err variable is falsy since truthy case is already handled before
|
||||
catch (e) { /* istanbul ignore next */ err = e; }
|
||||
|
||||
done(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit an event on the other end of bridge.
|
||||
* The parameters are same as `emit` function of the event emitter.
|
||||
*/
|
||||
dispatch () {
|
||||
try { this._dispatch(...arguments); }
|
||||
catch (e) { /* istanbul ignore next */ this.emit(ERROR_EVENT, e); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the bridge and release memory.
|
||||
*/
|
||||
disconnect () {
|
||||
// reset the bridge connection state
|
||||
this._bridgeConnected = false;
|
||||
|
||||
try { this._disconnect(...arguments); }
|
||||
catch (e) { this.emit(ERROR_EVENT, e); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub dispatch handler to queue dispatched messages until bridge is ready.
|
||||
*
|
||||
* @private
|
||||
* @param {String} name -
|
||||
*/
|
||||
_dispatch (name) {
|
||||
this._dispatchQueue.push(arguments);
|
||||
this.emit(DISPATCH_QUEUE_EVENT, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The bridge should be ready to disconnect when this is called. If not,
|
||||
* then this prototype stub would throw an error
|
||||
*
|
||||
* @private
|
||||
* @throws {Error} If bridge is not ready and this function is called
|
||||
*/
|
||||
_disconnect () { // eslint-disable-line class-methods-use-this
|
||||
throw new Error('uvm: cannot disconnect, communication bridge is broken');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UniversalVM;
|
17
node_modules/uvm/lib/utils.js
generated
vendored
Normal file
17
node_modules/uvm/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
isObject (subject) {
|
||||
return (typeof subject === 'object' && subject !== null);
|
||||
},
|
||||
|
||||
isFunction (subject) {
|
||||
return (typeof subject === 'function');
|
||||
},
|
||||
|
||||
isString (subject) {
|
||||
return (typeof subject === 'string');
|
||||
},
|
||||
|
||||
randomNumber () {
|
||||
return ~~(Math.random() * 100000000);
|
||||
}
|
||||
};
|
55
node_modules/uvm/lib/vm-delegate-timers.js
generated
vendored
Normal file
55
node_modules/uvm/lib/vm-delegate-timers.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
const vm = require('vm'),
|
||||
timers = require('timers'),
|
||||
|
||||
{ isFunction } = require('./utils'),
|
||||
|
||||
timerSetDelegates = ['setTimeout', 'setInterval', 'setImmediate'],
|
||||
timerClearDelegates = ['clearImmediate', 'clearInterval', 'clearTimeout'];
|
||||
|
||||
/* istanbul ignore if */
|
||||
// normalize immediate functions (usually for browsers)
|
||||
if (!(isFunction(timers.setImmediate) && isFunction(timers.clearImmediate))) {
|
||||
timers.setImmediate = function (fn) {
|
||||
return timers.setTimeout(fn, 0);
|
||||
};
|
||||
|
||||
timers.clearImmediate = function (id) {
|
||||
return timers.clearTimeout(id);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function (context) {
|
||||
// prepare all set timer functions by putting the function inside a closure and exposing a proxy variant while
|
||||
// deleting the original function from global scope
|
||||
timerSetDelegates.forEach((setFn) => {
|
||||
context[`${setFn}_`] = timers[setFn];
|
||||
vm.runInContext(`
|
||||
${setFn} = (function (_setFn, bind){
|
||||
return function (cb, time) {
|
||||
if (typeof cb !== 'function') { return; } // do not validate time for setImmediate
|
||||
return _setFn(cb, time);
|
||||
}
|
||||
}(${setFn}_));
|
||||
|
||||
delete ${setFn}_;
|
||||
(typeof ${setFn}_ !== 'undefined') && (${setFn}_ = undefined);
|
||||
`, context);
|
||||
});
|
||||
|
||||
// prepare all clear timer functions by putting the function inside a closure and exposing a proxy variant while
|
||||
// deleting the original function from global scope
|
||||
timerClearDelegates.forEach((clearFn) => {
|
||||
context[`${clearFn}_`] = timers[clearFn]; // set the function in context
|
||||
vm.runInContext(`
|
||||
${clearFn} = (function (_clearFn) {
|
||||
return function (id) { return _clearFn(id); };
|
||||
}(${clearFn}_));
|
||||
|
||||
delete ${clearFn}_;
|
||||
(typeof ${clearFn}_ !== 'undefined') && (${clearFn}_ = undefined);
|
||||
`, context);
|
||||
delete context[`${clearFn}_`]; // delete the function from context
|
||||
});
|
||||
|
||||
return context;
|
||||
};
|
Reference in New Issue
Block a user