isolated-vm
Advanced tools
Comparing version 3.3.10 to 4.0.0
@@ -6,5 +6,4 @@ 'use strict'; | ||
/** | ||
* Note that allowing untrusted users to access the v8 inspector may result in security issues. | ||
* Maybe it won't though, I don't know. I haven't really looked into everything the inspector can | ||
* do. | ||
* IMPORTANT: Allowing untrusted users to access the v8 inspector will almost certainly result in a | ||
* security vulnerability. Access to these endpoints should be restricted. | ||
*/ | ||
@@ -11,0 +10,0 @@ |
@@ -12,2 +12,3 @@ declare module "isolated-vm" { | ||
| ExternalCopy<any> | ||
| Callback<any> | ||
| Copy<any> | ||
@@ -17,2 +18,3 @@ | Reference<any> | ||
| Module | ||
| ((...args: any[]) => any) | ||
| typeof import("isolated-vm"); | ||
@@ -41,3 +43,3 @@ | ||
*/ | ||
readonly cpuTime: [number, number]; | ||
readonly cpuTime: bigint; | ||
@@ -55,3 +57,3 @@ /** | ||
*/ | ||
readonly wallTime: Hrtime; | ||
readonly wallTime: bigint; | ||
@@ -158,10 +160,2 @@ /** | ||
/** | ||
* Format is [ seconds, nanoseconds ], which is the same as the nodejs method | ||
* [process.hrtime](https://nodejs.org/api/process.html#process_process_hrtime_time). To convert | ||
* this value to milliseconds you could do something like: (ret[0] + ret[1] / 1e9) * 1000. Some | ||
* precision is lost in this conversion but for most applications it's probably not a big deal. | ||
*/ | ||
export type Hrtime = [ number, number ]; | ||
/** | ||
* A context is a sandboxed execution environment within an isolate. Each context contains its own | ||
@@ -186,7 +180,7 @@ * built-in objects and global space. | ||
code: string, options?: Options | ||
): Promise<ContextEvalResult<ResultTypeSync<Options>>>; // `ResultTypeSync` used intentionally | ||
): Promise<ResultTypeSync<Options>>; // `ResultTypeSync` used intentionally | ||
evalIgnored(code: string, options?: ContextEvalOptions): void | ||
evalSync<Options extends ContextEvalOptions>( | ||
code: string, options?: Options | ||
): ContextEvalResult<ResultTypeSync<Options>>; | ||
): ResultTypeSync<Options>; | ||
@@ -200,3 +194,3 @@ /** | ||
code: string, arguments?: ArgumentsTypeBidirectional<Options>, options?: Options | ||
): Promise<ContextEvalResult<ResultTypeBidirectionalSync<Options>>>; // `ResultTypeBidirectionalSync` used intentionally | ||
): Promise<ResultTypeBidirectionalSync<Options>>; // `ResultTypeBidirectionalSync` used intentionally | ||
evalClosureIgnored<Options extends ContextEvalClosureOptions>( | ||
@@ -207,3 +201,3 @@ code: string, arguments?: ArgumentsTypeBidirectional<Options>, options?: Options | ||
code: string, arguments?: ArgumentsTypeBidirectional<Options>, options?: Options | ||
): ContextEvalResult<ResultTypeBidirectionalSync<Options>>; | ||
): ResultTypeBidirectionalSync<Options>; | ||
@@ -219,5 +213,4 @@ /** | ||
export type ContextEvalOptions = CachedDataOptions & RunOptions & TransferOptions; | ||
export type ContextEvalClosureOptions = CachedDataOptions & RunOptions & TransferOptionsBidirectional; | ||
export type ContextEvalResult<Result> = CachedDataResult & { result: Result }; | ||
export type ContextEvalOptions = RunOptions & TransferOptions; | ||
export type ContextEvalClosureOptions = RunOptions & TransferOptionsBidirectional; | ||
@@ -305,3 +298,3 @@ /** | ||
private __ivm_reference: T; | ||
constructor(value: T); | ||
constructor(value: T, options?: { unsafeInherit?: boolean }); | ||
@@ -353,27 +346,25 @@ /** | ||
*/ | ||
delete(property: keyof T): Promise<boolean>; | ||
delete(property: keyof T): Promise<void>; | ||
deleteIgnored(property: keyof T): void; | ||
deleteSync(property: keyof T): boolean; | ||
deleteSync(property: keyof T): void; | ||
/** | ||
* Will access a reference as if using reference[property] and return a reference to that value. | ||
* | ||
* If the object is a proxy, or if the property is a getter, this method will throw. | ||
*/ | ||
get<Options extends TransferOptions, Key extends keyof T>( | ||
property: Key, options?: Options): ResultTypeAsync<Options & AsReference, T[Key]>; | ||
property: Key, options?: Options): ResultTypeAsync<Options & FallbackReference, T[Key]>; | ||
getSync<Options extends TransferOptions, Key extends keyof T>( | ||
property: Key, options?: Options): ResultTypeSync<Options & AsReference, T[Key]>; | ||
property: Key, options?: Options): ResultTypeSync<Options & FallbackReference, T[Key]>; | ||
/** | ||
* Will access a reference as if using reference[property] and return a reference to that value. | ||
* | ||
* @return {boolean} Indicating whether or not this operation succeeded. I'm actually not really | ||
* sure when false would be returned, I'm just giving you the result back straight from the v8 | ||
* API. | ||
*/ | ||
set<Options extends TransferOptions, Key extends keyof T>( | ||
property: Key, value: ArgumentType<Options, T[Key]>, options?: Options): Promise<boolean>; | ||
property: Key, value: ArgumentType<Options, T[Key]>, options?: Options): Promise<void>; | ||
setIgnored<Options extends TransferOptions, Key extends keyof T>( | ||
property: Key, value: ArgumentType<Options, T[Key]>, options?: Options): void; | ||
setSync<Options extends TransferOptions, Key extends keyof T>( | ||
property: Key, value: ArgumentType<Options, T[Key]>, options?: Options): boolean; | ||
property: Key, value: ArgumentType<Options, T[Key]>, options?: Options): void; | ||
@@ -389,6 +380,6 @@ /** | ||
options?: Options | ||
): ResultTypeBidirectionalAsync<Options & ApplyAsReference, ApplyResult<T>>; | ||
): ResultTypeBidirectionalAsync<Options & FallbackReference, ApplyResult<T>>; | ||
applyIgnored<Options extends ReferenceApplyOptions>( | ||
receiver?: ArgumentType<Options['arguments'], ApplyArgumentThis<T>>, | ||
arguments?: ArgumentsTypeBidirectional<Options & ApplyAsReference, ApplyArguments<T>>, | ||
arguments?: ArgumentsTypeBidirectional<Options & FallbackReference, ApplyArguments<T>>, | ||
options?: Options | ||
@@ -400,3 +391,3 @@ ): void; | ||
options?: Options | ||
): ResultTypeBidirectionalSync<Options & ApplyAsReference, ApplyResult<T>>; | ||
): ResultTypeBidirectionalSync<Options & FallbackReference, ApplyResult<T>>; | ||
@@ -417,3 +408,3 @@ /** | ||
options?: Options | ||
): ResultTypeBidirectionalSync<Options & ApplyAsReference, ApplyResult<T>>; | ||
): ResultTypeBidirectionalSync<Options & FallbackReference, ApplyResult<T>>; | ||
} | ||
@@ -513,2 +504,48 @@ | ||
/** | ||
* Callbacks can be used to create cross-isolate references to simple functions. This can be | ||
* easier and safer than dealing with the more flexible | ||
* [`Reference`](#class-reference-transferable) class. Arguments passed to and returned from | ||
* callbacks are always copied using the same method as | ||
* [`ExternalCopy`](#class-externalcopy-transferable). When transferred to another isolate, | ||
* instances of `Callback` will turn into a plain old function. Callbacks are created | ||
* automatically when passing functions to most isolated-vm functions. | ||
*/ | ||
export class Callback<T extends (...args: any[]) => any = any> { | ||
private __ivm_callback: T; | ||
constructor(value: T, options?: CallbackOptions); | ||
} | ||
export type CallbackOptions = { | ||
/** | ||
* Callback will be invoked asynchronously and will return a promise. | ||
*/ | ||
async?: boolean; | ||
/** | ||
* Callback will be invoked asynchronously and will return a value (default). | ||
*/ | ||
sync?: boolean; | ||
/** | ||
* Callback will be invoked asynchronously and will ignore the result (including exceptions). | ||
*/ | ||
ignored?: boolean; | ||
// The following ensures only 1 invocation option is given. | ||
} & ({ | ||
async?: true; | ||
sync?: never; | ||
ignored?: never; | ||
} | { | ||
async?: never; | ||
sync?: true; | ||
ignored?: never; | ||
} | { | ||
async?: never; | ||
sync?: never; | ||
ignored?: true; | ||
}); | ||
/** | ||
* C++ native module for v8 representation. | ||
@@ -656,4 +693,18 @@ */ | ||
reference?: boolean; | ||
}; | ||
// The following ensures only 1 transfer option is given. | ||
} & ({ | ||
copy?: true; | ||
externalCopy?: never; | ||
reference?: never; | ||
} | { | ||
copy?: never; | ||
externalCopy?: true; | ||
reference?: never; | ||
} | { | ||
copy?: never; | ||
externalCopy?: never; | ||
reference?: true; | ||
}); | ||
export type TransferOptionsBidirectional = { | ||
@@ -675,2 +726,3 @@ /** | ||
type AsReference = { reference: true }; | ||
type FallbackReference = { _reference: true }; | ||
type ApplyAsReference = { result: AsReference }; | ||
@@ -696,2 +748,3 @@ type WithTransfer = AsCopy | AsExternal | AsReference; | ||
Result extends void ? void : | ||
Options extends FallbackReference ? Reference<Result> : | ||
Transferable; | ||
@@ -716,4 +769,4 @@ type ResultTypeAsync<Options extends TransferOptions, Result = any> = Promise<ResultTypeBase<Options, Result>>; | ||
type ApplyArguments<Value> = Value extends (...args: infer Args) => unknown ? Args : any[]; | ||
type ApplyArgumentThis<Value> = Value extends (this: infer This, ...args: unknown[]) => unknown ? This : undefined | null; | ||
type ApplyResult<Value> = Value extends (...args: unknown[]) => infer Result ? Result : unknown; | ||
type ApplyArgumentThis<Value> = Value extends (this: infer This, ...args: any) => unknown ? This : undefined | null; | ||
type ApplyResult<Value> = Value extends (...args: any) => infer Result ? Result : unknown; | ||
} |
{ | ||
"name": "isolated-vm", | ||
"version": "3.3.10", | ||
"version": "4.0.0", | ||
"description": "Access to multiple isolates", | ||
@@ -16,2 +16,5 @@ "main": "isolated-vm.js", | ||
}, | ||
"devDependencies": { | ||
"isolated-vm": "." | ||
}, | ||
"repository": { | ||
@@ -18,0 +21,0 @@ "type": "git", |
115
README.md
@@ -156,3 +156,3 @@ [![npm version](https://badgen.now.sh/npm/v/isolated-vm)](https://www.npmjs.com/package/isolated-vm) | ||
Note that a [`Module`](#class-script-transferable) can only run in the isolate which created it. | ||
Note that a [`Module`](#class-module-transferable) can only run in the isolate which created it. | ||
@@ -181,16 +181,14 @@ ##### `isolate.createContext()` *[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)* | ||
##### `isolate.cpuTime` *[Array]* | ||
##### `isolate.wallTime` *[Array]* | ||
The total CPU and wall time spent in this isolate. CPU time is the amount of time the isolate has | ||
spent actively doing work on the CPU. Wall time is the amount of time the isolate has been running, | ||
including passive time spent waiting (think "wall" like a clock on the wall). For instance, if an | ||
isolate makes a call into another isolate, wall time will continue increasing while CPU time will | ||
remain the same. | ||
##### `isolate.cpuTime` *bigint* | ||
##### `isolate.wallTime` *bigint* | ||
The total CPU and wall time spent in this isolate, in nanoseconds. CPU time is the amount of time | ||
the isolate has spent actively doing work on the CPU. Wall time is the amount of time the isolate | ||
has been running, including passive time spent waiting (think "wall" like a clock on the wall). For | ||
instance, if an isolate makes a call into another isolate, wall time will continue increasing while | ||
CPU time will remain the same. | ||
The return format is `[ seconds, nanoseconds ]`, which is the same as the nodejs method | ||
[`process.hrtime`](https://nodejs.org/api/process.html#process_process_hrtime_time). To convert this | ||
value to milliseconds you could do something like: `(ret[0] + ret[1] / 1e9) * 1000`. Some precision | ||
is lost in this conversion but for most applications it's probably not a big deal. | ||
Note that in nodejs v10.x the return value is a regular number, since bigint isn't supported on | ||
earlier versions. | ||
Note that CPU time may vary drastically if there is contention for the CPU. This could occur if | ||
Also note that CPU time may vary drastically if there is contention for the CPU. This could occur if | ||
other processes are trying to do work, or if you have more than `require('os').cpus().length` | ||
@@ -226,7 +224,5 @@ isolates currently doing work in the same nodejs process. | ||
before execution is canceled. Default is no timeout. | ||
* [`{ ...CachedDataOptions }`](#cacheddataoptions) | ||
* [`{ ...ScriptOrigin }`](#scriptorigin) | ||
* [`{ ...TransferOptions }`](#transferoptions) | ||
* **return** *[object]* | ||
* `result` *[transferable]* | ||
* **return** *[transferable]* | ||
@@ -244,3 +240,2 @@ Compiles and executes a script within a context. This will return the last value evaluated, as long | ||
before execution is canceled. Default is no timeout. | ||
* [`{ ...CachedDataOptions }`](#cacheddataoptions) | ||
* [`{ ...ScriptOrigin }`](#scriptorigin) | ||
@@ -251,4 +246,3 @@ * `arguments` *[object]* | ||
* [`{ ...TransferOptions }`](#transferoptions) | ||
* **return** *[object]* | ||
* `result` *[transferable]* | ||
* **return** `*[transferable]* | ||
@@ -334,5 +328,30 @@ Compiles and runs code as if it were inside a function, similar to the seldom-used `new | ||
### Class: `Callback` *[transferable]* | ||
Callbacks can be used to create cross-isolate references to simple functions. This can be easier and | ||
safer than dealing with the more flexible [`Reference`](#class-reference-transferable) class. | ||
Arguments passed to and returned from callbacks are always copied using the same method as | ||
[`ExternalCopy`](#class-externalcopy-transferable). When transferred to another isolate, instances | ||
of `Callback` will turn into a plain old function. Callbacks are created automatically when passing | ||
functions to most isolated-vm functions. | ||
##### `new ivm.Callback(fn, options)` | ||
* `options` *[object]* | ||
* `async` *[boolean]* - Function will invoke the callback in "async" mode, which immediately | ||
returns a promise. | ||
* `ignored` *[boolean]* - Function will invoke the callback in "ignored" mode, which immediately | ||
returns `undefined` and ignores the result of the function (including thrown exceptions) | ||
* `sync` *[boolean]* - Function will invoke the callback in "sync" mode, blocking for a response | ||
(default). | ||
### Class: `Reference` *[transferable]* | ||
A instance of [`Reference`](#class-reference-transferable) is a pointer to a value stored in any isolate. | ||
##### `new ivm.Reference(value, options)` | ||
* `value` - The value to create a reference to. | ||
* `options` *[object]* | ||
* `unsafeInherit` *[boolean]* - If enabled then the `get` family of functions will follow the | ||
object's prototype chain. References created with this option should never be given to untrusted | ||
code. | ||
##### `reference.typeof` *[string]* | ||
@@ -378,3 +397,2 @@ | ||
* `property` *[transferable]* - The property to access on this object. | ||
* **return** `true` or `false` | ||
@@ -392,2 +410,4 @@ Delete a property from this reference, as if using `delete reference[property]` | ||
If the object is a proxy, or if the property is a getter, this method will throw. | ||
##### `reference.set(property, value, options)` *[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)* | ||
@@ -400,7 +420,3 @@ ##### `reference.setIgnored(property, value, options)` | ||
* [`{ ...TransferOptions }`](#transferoptions) | ||
* **return** `true` or `false` | ||
Returns a boolean indicating whether or not this operation succeeded. I'm actually not really sure | ||
when `false` would be returned, I'm just giving you the result back straight from the v8 API. | ||
##### `reference.apply(receiver, arguments, options)` *[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)* | ||
@@ -542,2 +558,36 @@ ##### `reference.applyIgnored(receiver, arguments, options)` | ||
SECURITY | ||
-------- | ||
Use of `isolated-vm` to run untrusted code does not automatically make your application safe. | ||
Through carelessness or misuse of the library it can be possible to leak sensitive data or grant | ||
undesired privileges to an isolate. | ||
At a minimum you should take care not to leak any instances of `isolated-vm` objects (`Reference`, | ||
`ExternalCopy`, etc) to untrusted code. It is usually trivial for an attacker to use these instances | ||
as a springboard back into the nodejs isolate which will yield complete control over a process. | ||
Simply wrapping these instances in closures is usually enough to keep the internal objects safe. An | ||
example of a safe logging function follows: | ||
```js | ||
context.evalClosureSync( | ||
`globalThis.log = (...args) => | ||
$0.applyIgnored(undefined, args, { arguments: { copy: true } });`, | ||
[ (...args) => console.log(...args) ], | ||
{ arguments: { reference: true } }); | ||
``` | ||
Against potentially hostile code you should also consider turning on [v8 untrusted code | ||
mitigations](https://v8.dev/docs/untrusted-code-mitigations), which addresses the class of | ||
speculative execution attacks known as Spectre and Meltdown. You can enable this feature by running | ||
`node` with the `--untrusted-code-mitigations` flag. This feature comes with a slight performance | ||
cost and must be enabled per-process, therefore nodejs disables it by default. | ||
v8 is a relatively robust runtime, but there are always new and exciting ways to crash, hang, or | ||
otherwise disrupt a process with plain old JavaScript. Your application must be resilient to these | ||
kinds of issues. It's a good idea to keep instances of `isolated-vm` in a different nodejs process | ||
than other critical infrastructure. | ||
EXAMPLES | ||
@@ -561,3 +611,3 @@ -------- | ||
// This make the global object available in the context as `global`. We use `derefInto()` here | ||
// This makes the global object available in the context as `global`. We use `derefInto()` here | ||
// because otherwise `global` would actually be a Reference{} object in the new isolate. | ||
@@ -567,8 +617,5 @@ jail.setSync('global', jail.derefInto()); | ||
// We will create a basic `log` function for the new isolate to use. | ||
const logCallback = function(...args) { | ||
jail.setSync('log', function(...args) { | ||
console.log(...args); | ||
}; | ||
context.evalClosureSync(`global.log = function(...args) { | ||
$0.applyIgnored(undefined, args, { arguments: { copy: true } }); | ||
}`, [ logCallback ], { arguments: { reference: true } }); | ||
}); | ||
@@ -663,4 +710,4 @@ // And let's test it out: | ||
JavaScript code. isolated-vm is also a good way to build single-process multithreaded JavaScript | ||
applications, though if parallelism is your only goal then there are probably better options out | ||
there. | ||
applications, though if parallelism of trusted code is your only goal then there are probably better | ||
options out there. | ||
@@ -680,7 +727,5 @@ Below is a quick summary of some other options available on nodejs and how they differ from | ||
| [vm](https://nodejs.org/api/vm.html) | | | | | ✅ | ✅ | | ||
| [worker_threads](https://nodejs.org/api/worker_threads.html) | | | ✅ | ✅ | ✅ | | | ||
| [worker_threads](https://nodejs.org/api/worker_threads.html) | | | ✅ | ✅ | ✅ | ✅ | | ||
| [vm2](https://github.com/patriksimek/vm2) | ✅ | | | | ✅ | ✅ | | ||
| [napajs](https://github.com/Microsoft/napajs) | | | ✅ | ✅ | Partial | | | ||
| [webworker-threads](https://github.com/audreyt/node-webworker-threads) | | | ✅ | ✅ | | | | ||
| [tiny-worker](https://github.com/avoidwork/tiny-worker) | | | ✅ | | ✅ | | | ||
| isolated-vm | ✅ | ✅ | ✅ | ✅ | | ✅ | |
@@ -29,5 +29,5 @@ 'use strict'; | ||
isolate.compileScriptSync(''+ function recursive() { | ||
isolate.compileScriptSync(`function recursive() { | ||
throw new Error('passed the test'); | ||
}).runSync(context); | ||
}`).runSync(context); | ||
let recursiveFn = global.getSync('recursive'); | ||
@@ -40,3 +40,3 @@ | ||
try { | ||
console.log(recursiveFn.applySync(undefined, [])); | ||
console.log(recursiveFn()); | ||
} catch (err) { | ||
@@ -43,0 +43,0 @@ if (/passed the test/.test(err)) { |
@@ -75,32 +75,2 @@ 'use strict'; | ||
// Check eval cached data | ||
{ | ||
const cachedData = (() => { | ||
const isolate = new ivm.Isolate; | ||
const result = isolate.createContextSync().evalSync(src, { produceCachedData: true }); | ||
assert.ok(result.cachedData); | ||
assert.strictEqual(result.cachedDataRejected, undefined); | ||
return result.cachedData; | ||
})(); | ||
const isolate = new ivm.Isolate; | ||
const result = isolate.createContextSync().evalSync(src, { cachedData }); | ||
assert.strictEqual(result.cachedData, undefined); | ||
assert.ok(!result.cachedDataRejected); | ||
} | ||
// Check evalClosure cached data | ||
{ | ||
const cachedData = (() => { | ||
const isolate = new ivm.Isolate; | ||
const result = isolate.createContextSync().evalClosureSync(src, [], { produceCachedData: true }); | ||
assert.ok(result.cachedData); | ||
assert.strictEqual(result.cachedDataRejected, undefined); | ||
return result.cachedData; | ||
})(); | ||
const isolate = new ivm.Isolate; | ||
const result = isolate.createContextSync().evalClosureSync(src, [], { cachedData }); | ||
assert.strictEqual(result.cachedData, undefined); | ||
assert.ok(!result.cachedDataRejected); | ||
} | ||
console.log('pass'); |
@@ -26,4 +26,4 @@ const ivm = require('isolated-vm'); | ||
context.release(); | ||
await job.result; | ||
await job; | ||
console.log(result); | ||
})().catch(console.error); |
@@ -15,7 +15,3 @@ 'use strict'; | ||
function hrToFloat(hr) { | ||
let time = (hr[0] + hr[1] / 1e9) * 1000; | ||
if (time > 1000) { | ||
console.log('time is too high'); | ||
} | ||
return time; | ||
return Number(hr) / 1e6; | ||
} | ||
@@ -22,0 +18,0 @@ |
@@ -25,12 +25,12 @@ let ivm = require('isolated-vm'); | ||
[ context1, context2 ].forEach(context => { | ||
if (!context.isReference.applySync(null, [ new ivm.Reference({}) ])) { | ||
if (!context.isReference(new ivm.Reference({}))) { | ||
console.log('fail1'); | ||
} | ||
if (!context.isReference.applySync(null, [ context.makeReference.applySync(null, [ 1 ]) ])) { | ||
if (!context.isReference(context.makeReference(1))) { | ||
console.log('fail2'); | ||
} | ||
}); | ||
if (context1.isReference.applySync(null, [ context2.makeReference.applySync(null, [ 1 ]).derefInto() ])) { | ||
if (context1.isReference(context2.makeReference(1).derefInto())) { | ||
console.log('fail3'); | ||
} | ||
console.log('pass'); |
@@ -43,3 +43,3 @@ 'use strict'; | ||
let ref = context.global.getSync('sabotage'); | ||
ref.applySync(undefined, []); | ||
ref(); | ||
}); | ||
@@ -46,0 +46,0 @@ await script.run(env.context); |
@@ -38,3 +38,3 @@ // node-args: --expose-gc | ||
strictEqual(reference.typeof, 'object'); | ||
const defaultExport = reference.getSync('default'); | ||
const defaultExport = reference.getSync('default', { reference: true }); | ||
strictEqual(typeof defaultExport, 'object'); | ||
@@ -102,3 +102,3 @@ strictEqual(defaultExport.typeof, 'function'); | ||
strictEqual(reference.typeof, 'object'); | ||
const add = reference.getSync('add'); | ||
const add = reference.getSync('add', { reference: true }); | ||
strictEqual(typeof add, 'object'); | ||
@@ -108,3 +108,3 @@ strictEqual(add.typeof, 'function'); | ||
const sub = reference.getSync('sub'); | ||
const sub = reference.getSync('sub', { reference: true }); | ||
strictEqual(typeof sub, 'object'); | ||
@@ -132,3 +132,3 @@ strictEqual(sub.typeof, 'function'); | ||
strictEqual(reference.getSync('value'), 0); | ||
countUp.applySync(null, [ ]); | ||
countUp(); | ||
strictEqual(reference.getSync('value'), 1); | ||
@@ -135,0 +135,0 @@ } |
@@ -19,3 +19,3 @@ const ivm = require('isolated-vm'); | ||
await assert.rejects(() => | ||
context.evalSync(`Promise.reject(new Error('hello'))`, { promise: true }).result, | ||
context.evalSync(`Promise.reject(new Error('hello'))`, { promise: true }), | ||
/hello/); | ||
@@ -22,0 +22,0 @@ |
@@ -7,3 +7,3 @@ let ivm = require('isolated-vm'); | ||
function recur1() { | ||
return global.getSync('recur2').applySync(undefined, []); | ||
return global.getSync('recur2')(); | ||
} | ||
@@ -10,0 +10,0 @@ |
@@ -10,3 +10,3 @@ 'use strict'; | ||
isolate.compileScriptSync('global.run = () => { function the_stack() { for(;;); }; the_stack(); }').runSync(context); | ||
let run = global.getSync('run'); | ||
let run = global.getSync('run', { reference: true }); | ||
let uhoh = false; | ||
@@ -13,0 +13,0 @@ let timeout = setTimeout(function() { |
@@ -18,8 +18,8 @@ const ivm = require('isolated-vm'); | ||
global.getSync('test', { copy: true, promise: true }).then(resolved => assert.deepEqual(resolved, value)).then(resolved); | ||
assert.deepEqual(context.evalSync('test', { copy: true }).result, value); | ||
assert.deepEqual(context.evalSync('test', { copy: true }), value); | ||
const fn = context.evalSync('(function foo(arg1) { return arg1; })', { reference: true }).result; | ||
const fn = context.evalSync('(function foo(arg1) { return arg1; })', { reference: true }); | ||
assert.deepEqual(fn.applySync(undefined, [ value ], { arguments: { copy: true }, result: { copy: true } }), value); | ||
const closureResult = context.evalClosureSync('return [ $0, $1 ];', [ value, value ], { arguments: { copy: true }, result: { copy: true } }).result; | ||
const closureResult = context.evalClosureSync('return [ $0, $1 ];', [ value, value ], { arguments: { copy: true }, result: { copy: true } }); | ||
assert.deepEqual(closureResult[0], closureResult[1]); | ||
@@ -32,3 +32,3 @@ assert.deepEqual(closureResult[0], value); | ||
global.getSync('promise', { copy: true, promise: true }).then(resolved => assert.deepEqual(value, resolved)).then(resolved); | ||
global.getSync('resolve').applySync(undefined, [ value ], { arguments: { copy: true } }); | ||
global.getSync('resolve', { reference: true }).applySync(undefined, [ value ], { arguments: { copy: true } }); | ||
promise.then(resolved => assert.deepEqual(value, resolved)).then(resolved); | ||
@@ -42,3 +42,3 @@ | ||
{ arguments: { reference: true }, result: { promise: true, copy: true } }); | ||
delegatedPromise.result.then(resolved => assert.deepEqual(resolved, value)).then(resolved); | ||
delegatedPromise.then(resolved => assert.deepEqual(resolved, value)).then(resolved); | ||
@@ -48,3 +48,3 @@ context.evalClosure( | ||
[ async() => new ivm.ExternalCopy(value).copyInto() ], { arguments: { reference: true }, result: { copy: true }} | ||
).then(result => assert.deepEqual(result.result, value)); | ||
).then(result => assert.deepEqual(result, value)); | ||
@@ -51,0 +51,0 @@ let ii = 0; |
@@ -15,5 +15,5 @@ 'use strict'; | ||
wasmExports.foo(); | ||
`).result; | ||
`); | ||
if (result === 123) { | ||
console.log('pass'); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
525427
160
2888
718
1