diff --git a/lib/bridge.js b/lib/bridge.js index bae700d..8690b51 100644 --- a/lib/bridge.js +++ b/lib/bridge.js @@ -102,6 +102,8 @@ const thisErrorCaptureStackTrace = Error.captureStackTrace; const thisSymbolToString = Symbol.prototype.toString; const thisSymbolToStringTag = Symbol.toStringTag; +const thisSymbolIterator = Symbol.iterator; +const thisSymbolNodeJSUtilInspectCustom = Symbol.for('nodejs.util.inspect.custom'); /** * VMError. @@ -348,7 +350,11 @@ function createBridge(otherInit, registerProxy) { constructor(object) { // Note: object@other(unsafe) throws@this(unsafe) super(); - this.object = object; + this.objectWrapper = () => object; + } + + getObject() { + return this.objectWrapper(); } getFactory() { @@ -408,7 +414,7 @@ function createBridge(otherInit, registerProxy) { get(target, key, receiver) { // Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) switch (key) { case 'constructor': { const desc = otherSafeGetOwnPropertyDescriptor(object, key); @@ -447,7 +453,7 @@ function createBridge(otherInit, registerProxy) { set(target, key, value, receiver) { // Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) if (key === '__proto__' && !thisOtherHasOwnProperty(object, key)) { return this.setPrototypeOf(target, value); } @@ -471,7 +477,7 @@ function createBridge(otherInit, registerProxy) { apply(target, context, args) { // Note: target@this(unsafe) context@this(unsafe) args@this(safe-array) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) let ret; // @other(unsafe) try { context = otherFromThis(context); @@ -485,7 +491,7 @@ function createBridge(otherInit, registerProxy) { construct(target, args, newTarget) { // Note: target@this(unsafe) args@this(safe-array) newTarget@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) let ret; // @other(unsafe) try { args = otherFromThisArguments(args); @@ -498,14 +504,14 @@ function createBridge(otherInit, registerProxy) { getOwnPropertyDescriptorDesc(target, prop, desc) { // Note: target@this(unsafe) prop@prim desc@other{safe} throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) if (desc && typeof object === 'function' && (prop === 'arguments' || prop === 'caller' || prop === 'callee')) desc.value = null; return desc; } getOwnPropertyDescriptor(target, prop) { // Note: target@this(unsafe) prop@prim throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) let desc; // @other(safe) try { desc = otherSafeGetOwnPropertyDescriptor(object, prop); @@ -551,7 +557,7 @@ function createBridge(otherInit, registerProxy) { defineProperty(target, prop, desc) { // Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected(); desc = this.definePropertyDesc(target, prop, desc); @@ -604,7 +610,7 @@ function createBridge(otherInit, registerProxy) { deleteProperty(target, prop) { // Note: target@this(unsafe) prop@prim throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) try { return otherReflectDeleteProperty(object, prop) === true; } catch (e) { // @other(unsafe) @@ -614,7 +620,7 @@ function createBridge(otherInit, registerProxy) { has(target, key) { // Note: target@this(unsafe) key@prim throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) try { return otherReflectHas(object, key) === true; } catch (e) { // @other(unsafe) @@ -624,7 +630,7 @@ function createBridge(otherInit, registerProxy) { isExtensible(target) { // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) try { if (otherReflectIsExtensible(object)) return true; } catch (e) { // @other(unsafe) @@ -638,7 +644,7 @@ function createBridge(otherInit, registerProxy) { ownKeys(target) { // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) let res; // @other(unsafe) try { res = otherReflectOwnKeys(object); @@ -650,7 +656,7 @@ function createBridge(otherInit, registerProxy) { preventExtensions(target) { // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) try { if (!otherReflectPreventExtensions(object)) return false; } catch (e) { // @other(unsafe) @@ -664,7 +670,7 @@ function createBridge(otherInit, registerProxy) { enumerate(target) { // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) let res; // @other(unsafe) try { res = otherReflectEnumerate(object); @@ -676,6 +682,10 @@ function createBridge(otherInit, registerProxy) { } + BaseHandler.prototype[thisSymbolNodeJSUtilInspectCustom] = undefined; + BaseHandler.prototype[thisSymbolToStringTag] = 'VM2 Wrapper'; + BaseHandler.prototype[thisSymbolIterator] = undefined; + function defaultFactory(object) { // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe) return new BaseHandler(object); @@ -773,7 +783,7 @@ function createBridge(otherInit, registerProxy) { get(target, key, receiver) { // Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) + const object = this.getObject(); // @other(unsafe) const mock = this.mock; if (thisReflectApply(thisObjectHasOwnProperty, mock, key) && !thisOtherHasOwnProperty(object, key)) { return mock[key]; diff --git a/test/vm.js b/test/vm.js index 1bae3e5..7dda4db 100644 --- a/test/vm.js +++ b/test/vm.js @@ -91,9 +91,10 @@ describe('node', () => { before(() => { vm = new VM(); }); - it.skip('inspect', () => { + it('inspect', () => { assert.throws(() => inspect(doubleProxy), /Expected/); - if (NODE_VERSION !== 10) { + assert.doesNotThrow(() => inspect(vm.run('({})'), {showProxy: true, customInspect: true})); + if (NODE_VERSION !== 10 && false) { // This failes on node 10 since they do not unwrap proxys. // And the hack to fix this is only in the inner proxy. // We could add another hack, but that one would require