Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

uvm

Package Overview
Dependencies
Maintainers
4
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

uvm - npm Package Compare versions

Comparing version 1.7.9 to 1.8.0-beta.1

13

firmware/sandbox-base.js
module.exports = `
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta charset="UTF-8"><script type="text/javascript">
(function (win) {
(function (self) {
var init = function (e) {
win.removeEventListener('message', init);
self.removeEventListener('message', init);
// eslint-disable-next-line no-eval
(e && e.data && (typeof e.data.__init_uvm === 'string')) && eval(e.data.__init_uvm);
};
win.addEventListener('message', init);
}(window));
</script>
</head></html>`;
self.addEventListener('message', init);
}(self));
`;
/*
* @note
* options.bootTimeout is not implemented in browser sandbox. Reason is that as long as we use iFrame, there is no way
* to interrupt an infinite loop.
* options.bootTimeout is not implemented in browser sandbox because there is no way to interrupt an infinite loop.
*/
var _ = require('lodash'),
uuid = require('uuid'),
var uuid = require('uuid'),
Flatted = require('flatted'),
MESSAGE = 'message',
LOAD = 'load',
ERROR = 'error',
TARGET_ALL = '*',
SANDBOX_ELEMENT_TAG = 'iframe',

@@ -19,27 +14,14 @@ // code for bridge

/**
* Default DOM attributes of sandbox
* @type {Object}
*/
sandboxAttributes = {
'class': 'postman-uvm-context',
'style': 'display:none;',
'sandbox': 'allow-scripts'
},
/**
* Returns the HTML to be executed inside iFrame.
* Returns the firmware code to be executed inside Web Worker.
*
* @param {String} code
* @param {String} id
* @param {Boolean} firmwareOnly
* @return {String}
*/
sandboxCode = function (code, id, firmwareOnly) {
var firmware = `
__uvm_emit = function (args) {window.parent.postMessage({__id_uvm: "${id}",__emit_uvm: args}, "*");};
sandboxFirmware = function (code, id) {
return `
__uvm_emit = function (args) {self.postMessage({__id_uvm: "${id}",__emit_uvm: args});};
try {${code}} catch (e) { setTimeout(function () { throw e; }, 0); }
(function (emit, id) {
window.addEventListener("message", function (e) {
self.addEventListener("message", function (e) {
(e && e.data && (typeof e.data.__emit_uvm === 'string') && (e.data.__id_uvm === id)) &&

@@ -49,9 +31,4 @@ emit(e.data.__emit_uvm);

}(__uvm_dispatch, "${id}"));
__uvm_emit('${Flatted.stringify(['load.' + id])}');
__uvm_dispatch = null; __uvm_emit = null;
`;
return firmwareOnly ? firmware : `<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><meta charset="UTF-8">
<script type="text/javascript">${firmware}</script></head></html>`;
};

@@ -61,12 +38,7 @@

var id = uuid(),
code = bridgeClientCode(options.bootCode),
firmwareCode = sandboxFirmware(bridgeClientCode(options.bootCode), id),
// make sure we escape the code only once
serializedFirmware = unescape(encodeURIComponent(sandboxCode(code, id))),
iframe = options._sandbox || document.createElement(SANDBOX_ELEMENT_TAG),
// function to forward messages emitted
forwardEmits = function (e) {
if (!(e && e.data && _.isString(e.data.__emit_uvm) && (e.data.__id_uvm === id))) { return; }
if (!(e && e.data && (typeof e.data.__emit_uvm === 'string') && (e.data.__id_uvm === id))) { return; }

@@ -79,68 +51,67 @@ var args;

processCallback = function () {
!options._sandbox && iframe.removeEventListener(LOAD, processCallback);
// function to forward errors emitted
forwardErrors = function (e) {
bridge.emit(ERROR, e);
},
bridge._dispatch = function () {
if (!iframe) {
return bridge.emit(ERROR,
new Error('uvm: unable to dispatch "' + arguments[0] + '" post disconnection.'));
}
firmwareObjectURL,
worker;
iframe.contentWindow.postMessage({
__emit_uvm: Flatted.stringify(Array.prototype.slice.call(arguments)),
__id_uvm: id
}, TARGET_ALL);
};
// 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' })
);
callback(null, bridge);
};
worker = new Worker(firmwareObjectURL);
}
// add event listener for receiving events from iframe (is removed on disconnect)
window.addEventListener(MESSAGE, forwardEmits);
// 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. delete the iframe)
bridge._disconnect = function () {
if (!iframe) { return; }
bridge._dispatch = function () {
if (!worker) {
return bridge.emit(ERROR,
new Error('uvm: unable to dispatch "' + arguments[0] + '" post disconnection.'));
}
// remove the message handler for this sandbox
window.removeEventListener(MESSAGE, forwardEmits);
// do not delete sandbox element if not created for the bridge
!options._sandbox && iframe.parentNode && iframe.parentNode.removeChild(iframe);
iframe = null;
worker.postMessage({
__emit_uvm: Flatted.stringify(Array.prototype.slice.call(arguments)),
__id_uvm: id
});
};
// if sandbox element is provided, we simply need to init with firmware code and wait for load event to be fired
if (options._sandbox) {
bridge.once('load.' + id, processCallback); // on load attach the dispatcher
// equip bridge to disconnect (i.e. terminate the worker)
bridge._disconnect = function () {
if (!worker) { return; }
iframe.contentWindow.postMessage({
__init_uvm: sandboxCode(code, id, true) // the last `true` param indicates firmwareOnly
}, TARGET_ALL);
// remove event listeners for this sandbox
worker.removeEventListener(MESSAGE, forwardEmits);
worker.removeEventListener(ERROR, forwardErrors);
return;
}
// do not terminate sandbox worker if not spawned for the bridge
if (!options._sandbox) {
worker.terminate();
// this point onwards, it is our own iframe, so we do all the appending and other stuff to DOM
iframe.addEventListener(LOAD, processCallback); // removed right when executed
// revoke after termination. otherwise, blob reference is retained until GC
// refer: "chrome://blob-internals"
window.URL.revokeObjectURL(firmwareObjectURL);
}
// prepare an iframe as context
_.forEach(sandboxAttributes, function (val, prop) {
iframe.setAttribute(prop, val);
});
worker = null;
};
// add HTML and bootstrap code to the iframe
iframe.setAttribute('src', 'data:text/html;base64, ' + btoa(serializedFirmware));
// help GC collect large variables
firmwareCode = null;
// data uri has size limits depending on the browsers
// in browsers that don't support srcdoc attribute the src attribute is accepted
// https://www.w3.org/TR/html5/semantics-embedded-content.html#an-iframe-srcdoc-document
iframe.setAttribute('srcdoc', serializedFirmware);
// now append the iframe to start processing stuff
document.body.appendChild(iframe);
// help GC collect large variables
code = null;
serializedFirmware = null;
callback(null, bridge);
};
{
"name": "uvm",
"version": "1.7.9",
"version": "1.8.0-beta.1",
"description": "Universal Virtual Machine for Node and Browser",

@@ -5,0 +5,0 @@ "main": "index.js",

# uvm [![Build Status](https://travis-ci.org/postmanlabs/uvm.svg?branch=develop)](https://travis-ci.org/postmanlabs/uvm) [![codecov](https://codecov.io/gh/postmanlabs/uvm/branch/develop/graph/badge.svg)](https://codecov.io/gh/postmanlabs/uvm)
Module that exposes an event emitter to send data across contexts (vm in node and iframe in browser)
Module that exposes an event emitter to send data across contexts ([VM](https://nodejs.org/api/vm.html) in Node.js and [Web Workers](https://www.w3.org/TR/workers/) in browser)

@@ -5,0 +5,0 @@ ## Usage

@@ -1,19 +0,23 @@

(typeof window !== 'undefined' ? describe : describe.skip)('custom iframe in browser', function () {
(typeof window !== 'undefined' ? describe : describe.skip)('custom sandbox in browser', function () {
var uvm = require('../../lib'),
firmware = require('../../firmware/sandbox-base'),
iframe;
firmwareUrl,
worker;
beforeEach(function (done) {
iframe = document.createElement('iframe');
iframe.setAttribute('src', 'data:text/html;base64, ' +
btoa(unescape(encodeURIComponent(firmware))));
iframe.addEventListener('load', function () {
done();
});
document.body.appendChild(iframe);
beforeEach(function () {
firmwareUrl = window.URL.createObjectURL(
new Blob([firmware], { type: 'text/javascript' })
);
worker = new Worker(firmwareUrl);
});
afterEach(function () {
worker.terminate();
window.URL.revokeObjectURL(firmwareUrl);
worker = firmwareUrl = null;
});
it('should load and dispatch messages', function (done) {
uvm.spawn({
_sandbox: iframe,
_sandbox: worker,
bootCode: `

@@ -35,7 +39,2 @@ bridge.on('loopback', function (data) {

});
afterEach(function () {
iframe.parentNode.removeChild(iframe);
iframe = null;
});
});

@@ -1,2 +0,2 @@

(typeof window !== 'undefined' ? describe : describe.skip)('custom iframe in browser', function () {
(typeof window !== 'undefined' ? describe : describe.skip)('custom sandbox in browser', function () {
var _ = require('lodash'),

@@ -17,38 +17,36 @@ uvm = require('../../lib'),

return `
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta charset="UTF-8">
<script type="text/javascript">
${code}
</script>
<script type="text/javascript">
(function (win) {
var init = function (e) {
win.removeEventListener('message', init);
// eslint-disable-next-line no-eval
(e && e.data && (typeof e.data.__init_uvm === 'string')) && eval(e.data.__init_uvm);
};
win.addEventListener('message', init);
}(window));
</script>
</head></html>`;
${code}
(function (self) {
var init = function (e) {
self.removeEventListener('message', init);
// eslint-disable-next-line no-eval
(e && e.data && (typeof e.data.__init_uvm === 'string')) && eval(e.data.__init_uvm);
};
self.addEventListener('message', init);
}(self));
`;
},
iframe;
firmwareUrl,
worker;
beforeEach(function (done) {
var fakeBundleSize = 5 * 1024 * 1024, // 10mb (5 million characters with 2 bytes each)
beforeEach(function () {
var fakeBundleSize = 5 * 1024 * 1024, // 10MB (5 million characters with 2 bytes each)
largeJSStatement = `var x = '${getLargeString(fakeBundleSize)}';`;
iframe = document.createElement('iframe');
iframe.setAttribute('src', 'data:text/html;base64, ' +
btoa(unescape(encodeURIComponent(getFirmware(largeJSStatement)))));
iframe.setAttribute('srcdoc', unescape(encodeURIComponent(getFirmware(largeJSStatement))));
iframe.addEventListener('load', function () {
done();
});
document.body.appendChild(iframe);
firmwareUrl = window.URL.createObjectURL(
new Blob([getFirmware(largeJSStatement)], { type: 'text/javascript' })
);
worker = new Worker(firmwareUrl);
});
afterEach(function () {
worker.terminate();
window.URL.revokeObjectURL(firmwareUrl);
worker = firmwareUrl = null;
});
it('should load and dispatch messages', function (done) {
uvm.spawn({
_sandbox: iframe,
_sandbox: worker,
bootCode: `

@@ -70,7 +68,2 @@ bridge.on('loopback', function (data) {

});
afterEach(function () {
iframe.parentNode.removeChild(iframe);
iframe = null;
});
});
((typeof window === 'undefined') ? describe : describe.skip)('uvm timeout option', function () {
var uvm = require('../../lib');
// options.bootTimeout is not implemented in browser sandbox. Reason is that as long as we use iFrame, there is no
// way to interrupt an infinite loop.
// options.bootTimeout is not implemented in browser sandbox because there
// is no way to interrupt an infinite loop.
it('must exit if bootCode has infinite loop', function (done) {

@@ -23,4 +23,4 @@ uvm.spawn({

// options.dispatchTimeout is not implemented in browser sandbox. Reason is that as long as we use iFrame, there is
// no way to interrupt an infinite loop.
// options.dispatchTimeout is not implemented in browser sandbox because
// there is no way to interrupt an infinite loop.
it('must exit if dispatch is has infinite loop', function (done) {

@@ -27,0 +27,0 @@ uvm.spawn({

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc