diff --git a/.github/workflows/integration-test-workflow.yml b/.github/workflows/integration-test-workflow.yml index c88ac20..2202cbb 100644 --- a/.github/workflows/integration-test-workflow.yml +++ b/.github/workflows/integration-test-workflow.yml @@ -55,7 +55,11 @@ jobs: - name: Verify default Push Workflow if: ${{ github.event_name != 'pull_request' }} run: | - BASE_SHA=$(echo $(git rev-parse HEAD~1)) + if git merge-base --is-ancestor $NX_BASE HEAD; then + BASE_SHA=$NX_BASE; + else + BASE_SHA=""; + fi HEAD_SHA=$(echo $(git rev-parse HEAD)) node -e "if(process.env.NX_BASE == '${BASE_SHA}') console.log('Base set correctly'); else { throw new Error('Base not set correctly!');}" node -e "if(process.env.NX_HEAD == '${HEAD_SHA}') console.log('Head set correctly'); else { throw new Error('Head not set correctly!');}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1fe5d22..baf4166 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -68,7 +68,11 @@ jobs: if: github.event_name != 'pull_request' shell: bash run: | - BASE_SHA=$(echo $(git rev-parse HEAD~1)) + if git merge-base --is-ancestor $NX_BASE HEAD; then + BASE_SHA=$NX_BASE; + else + BASE_SHA=""; + fi HEAD_SHA=$(echo $(git rev-parse HEAD)) node -e "if(process.env.NX_BASE == '${BASE_SHA}') console.log('Base set correctly'); else { throw new Error('Base not set correctly!');}" node -e "if(process.env.NX_HEAD == '${HEAD_SHA}') console.log('Head set correctly'); else { throw new Error('Head not set correctly!');}" diff --git a/dist/bridge.js b/dist/bridge.js deleted file mode 100644 index bae700d..0000000 --- a/dist/bridge.js +++ /dev/null @@ -1,1000 +0,0 @@ -'use strict'; - -/** - * __ ___ ____ _ _ ___ _ _ ____ - * \ \ / / \ | _ \| \ | |_ _| \ | |/ ___| - * \ \ /\ / / _ \ | |_) | \| || || \| | | _ - * \ V V / ___ \| _ <| |\ || || |\ | |_| | - * \_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____| - * - * This file is critical for vm2. It implements the bridge between the host and the sandbox. - * If you do not know exactly what you are doing, you should NOT edit this file. - * - * The file is loaded in the host and sandbox to handle objects in both directions. - * This is done to ensure that RangeErrors are from the correct context. - * The boundary between the sandbox and host might throw RangeErrors from both contexts. - * Therefore, thisFromOther and friends can handle objects from both domains. - * - * Method parameters have comments to tell from which context they came. - * - */ - -const globalsList = [ - 'Number', - 'String', - 'Boolean', - 'Date', - 'RegExp', - 'Map', - 'WeakMap', - 'Set', - 'WeakSet', - 'Promise', - 'Function' -]; - -const errorsList = [ - 'RangeError', - 'ReferenceError', - 'SyntaxError', - 'TypeError', - 'EvalError', - 'URIError', - 'Error' -]; - -const OPNA = 'Operation not allowed on contextified object.'; - -const thisGlobalPrototypes = { - __proto__: null, - Object: Object.prototype, - Array: Array.prototype -}; - -for (let i = 0; i < globalsList.length; i++) { - const key = globalsList[i]; - const g = global[key]; - if (g) thisGlobalPrototypes[key] = g.prototype; -} - -for (let i = 0; i < errorsList.length; i++) { - const key = errorsList[i]; - const g = global[key]; - if (g) thisGlobalPrototypes[key] = g.prototype; -} - -const { - getPrototypeOf: thisReflectGetPrototypeOf, - setPrototypeOf: thisReflectSetPrototypeOf, - defineProperty: thisReflectDefineProperty, - deleteProperty: thisReflectDeleteProperty, - getOwnPropertyDescriptor: thisReflectGetOwnPropertyDescriptor, - isExtensible: thisReflectIsExtensible, - preventExtensions: thisReflectPreventExtensions, - apply: thisReflectApply, - construct: thisReflectConstruct, - set: thisReflectSet, - get: thisReflectGet, - has: thisReflectHas, - ownKeys: thisReflectOwnKeys, - enumerate: thisReflectEnumerate, -} = Reflect; - -const thisObject = Object; -const { - freeze: thisObjectFreeze, - prototype: thisObjectPrototype -} = thisObject; -const thisObjectHasOwnProperty = thisObjectPrototype.hasOwnProperty; -const ThisProxy = Proxy; -const ThisWeakMap = WeakMap; -const { - get: thisWeakMapGet, - set: thisWeakMapSet -} = ThisWeakMap.prototype; -const ThisMap = Map; -const thisMapGet = ThisMap.prototype.get; -const thisMapSet = ThisMap.prototype.set; -const thisFunction = Function; -const thisFunctionBind = thisFunction.prototype.bind; -const thisArrayIsArray = Array.isArray; -const thisErrorCaptureStackTrace = Error.captureStackTrace; - -const thisSymbolToString = Symbol.prototype.toString; -const thisSymbolToStringTag = Symbol.toStringTag; - -/** - * VMError. - * - * @public - * @extends {Error} - */ -class VMError extends Error { - - /** - * Create VMError instance. - * - * @public - * @param {string} message - Error message. - * @param {string} code - Error code. - */ - constructor(message, code) { - super(message); - - this.name = 'VMError'; - this.code = code; - - thisErrorCaptureStackTrace(this, this.constructor); - } -} - -thisGlobalPrototypes['VMError'] = VMError.prototype; - -function thisUnexpected() { - return new VMError('Unexpected'); -} - -if (!thisReflectSetPrototypeOf(exports, null)) throw thisUnexpected(); - -function thisSafeGetOwnPropertyDescriptor(obj, key) { - const desc = thisReflectGetOwnPropertyDescriptor(obj, key); - if (!desc) return desc; - if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected(); - return desc; -} - -function thisThrowCallerCalleeArgumentsAccess(key) { - 'use strict'; - thisThrowCallerCalleeArgumentsAccess[key]; - return thisUnexpected(); -} - -function thisIdMapping(factory, other) { - return other; -} - -const thisThrowOnKeyAccessHandler = thisObjectFreeze({ - __proto__: null, - get(target, key, receiver) { - if (typeof key === 'symbol') { - key = thisReflectApply(thisSymbolToString, key, []); - } - throw new VMError(`Unexpected access to key '${key}'`); - } -}); - -const emptyForzenObject = thisObjectFreeze({ - __proto__: null -}); - -const thisThrowOnKeyAccess = new ThisProxy(emptyForzenObject, thisThrowOnKeyAccessHandler); - -function SafeBase() {} - -if (!thisReflectDefineProperty(SafeBase, 'prototype', { - __proto__: null, - value: thisThrowOnKeyAccess -})) throw thisUnexpected(); - -function SHARED_FUNCTION() {} - -const TEST_PROXY_HANDLER = thisObjectFreeze({ - __proto__: thisThrowOnKeyAccess, - construct() { - return this; - } -}); - -function thisIsConstructor(obj) { - // Note: obj@any(unsafe) - const Func = new ThisProxy(obj, TEST_PROXY_HANDLER); - try { - // eslint-disable-next-line no-new - new Func(); - return true; - } catch (e) { - return false; - } -} - -function thisCreateTargetObject(obj, proto) { - // Note: obj@any(unsafe) proto@any(unsafe) returns@this(unsafe) throws@this(unsafe) - let base; - if (typeof obj === 'function') { - if (thisIsConstructor(obj)) { - // Bind the function since bound functions do not have a prototype property. - base = thisReflectApply(thisFunctionBind, SHARED_FUNCTION, [null]); - } else { - base = () => {}; - } - } else if (thisArrayIsArray(obj)) { - base = []; - } else { - return {__proto__: proto}; - } - if (!thisReflectSetPrototypeOf(base, proto)) throw thisUnexpected(); - return base; -} - -function createBridge(otherInit, registerProxy) { - - const mappingOtherToThis = new ThisWeakMap(); - const protoMappings = new ThisMap(); - const protoName = new ThisMap(); - - function thisAddProtoMapping(proto, other, name) { - // Note: proto@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe) - thisReflectApply(thisMapSet, protoMappings, [proto, thisIdMapping]); - thisReflectApply(thisMapSet, protoMappings, [other, - (factory, object) => thisProxyOther(factory, object, proto)]); - if (name) thisReflectApply(thisMapSet, protoName, [proto, name]); - } - - function thisAddProtoMappingFactory(protoFactory, other, name) { - // Note: protoFactory@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe) - let proto; - thisReflectApply(thisMapSet, protoMappings, [other, - (factory, object) => { - if (!proto) { - proto = protoFactory(); - thisReflectApply(thisMapSet, protoMappings, [proto, thisIdMapping]); - if (name) thisReflectApply(thisMapSet, protoName, [proto, name]); - } - return thisProxyOther(factory, object, proto); - }]); - } - - const result = { - __proto__: null, - globalPrototypes: thisGlobalPrototypes, - safeGetOwnPropertyDescriptor: thisSafeGetOwnPropertyDescriptor, - fromArguments: thisFromOtherArguments, - from: thisFromOther, - fromWithFactory: thisFromOtherWithFactory, - ensureThis: thisEnsureThis, - mapping: mappingOtherToThis, - connect: thisConnect, - reflectSet: thisReflectSet, - reflectGet: thisReflectGet, - reflectDefineProperty: thisReflectDefineProperty, - reflectDeleteProperty: thisReflectDeleteProperty, - reflectApply: thisReflectApply, - reflectConstruct: thisReflectConstruct, - reflectHas: thisReflectHas, - reflectOwnKeys: thisReflectOwnKeys, - reflectEnumerate: thisReflectEnumerate, - reflectGetPrototypeOf: thisReflectGetPrototypeOf, - reflectIsExtensible: thisReflectIsExtensible, - reflectPreventExtensions: thisReflectPreventExtensions, - objectHasOwnProperty: thisObjectHasOwnProperty, - weakMapSet: thisWeakMapSet, - addProtoMapping: thisAddProtoMapping, - addProtoMappingFactory: thisAddProtoMappingFactory, - defaultFactory, - protectedFactory, - readonlyFactory, - VMError - }; - - const isHost = typeof otherInit !== 'object'; - - if (isHost) { - otherInit = otherInit(result, registerProxy); - } - - result.other = otherInit; - - const { - globalPrototypes: otherGlobalPrototypes, - safeGetOwnPropertyDescriptor: otherSafeGetOwnPropertyDescriptor, - fromArguments: otherFromThisArguments, - from: otherFromThis, - mapping: mappingThisToOther, - reflectSet: otherReflectSet, - reflectGet: otherReflectGet, - reflectDefineProperty: otherReflectDefineProperty, - reflectDeleteProperty: otherReflectDeleteProperty, - reflectApply: otherReflectApply, - reflectConstruct: otherReflectConstruct, - reflectHas: otherReflectHas, - reflectOwnKeys: otherReflectOwnKeys, - reflectEnumerate: otherReflectEnumerate, - reflectGetPrototypeOf: otherReflectGetPrototypeOf, - reflectIsExtensible: otherReflectIsExtensible, - reflectPreventExtensions: otherReflectPreventExtensions, - objectHasOwnProperty: otherObjectHasOwnProperty, - weakMapSet: otherWeakMapSet - } = otherInit; - - function thisOtherHasOwnProperty(object, key) { - // Note: object@other(safe) key@prim throws@this(unsafe) - try { - return otherReflectApply(otherObjectHasOwnProperty, object, [key]) === true; - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - } - - function thisDefaultGet(handler, object, key, desc) { - // Note: object@other(unsafe) key@prim desc@other(safe) - let ret; // @other(unsafe) - if (desc.get || desc.set) { - const getter = desc.get; - if (!getter) return undefined; - try { - ret = otherReflectApply(getter, object, [key]); - } catch (e) { - throw thisFromOtherForThrow(e); - } - } else { - ret = desc.value; - } - return handler.fromOtherWithContext(ret); - } - - function otherFromThisIfAvailable(to, from, key) { - // Note: to@other(safe) from@this(safe) key@prim throws@this(unsafe) - if (!thisReflectApply(thisObjectHasOwnProperty, from, [key])) return false; - try { - to[key] = otherFromThis(from[key]); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - return true; - } - - class BaseHandler extends SafeBase { - - constructor(object) { - // Note: object@other(unsafe) throws@this(unsafe) - super(); - this.object = object; - } - - getFactory() { - return defaultFactory; - } - - fromOtherWithContext(other) { - // Note: other@other(unsafe) throws@this(unsafe) - return thisFromOtherWithFactory(this.getFactory(), other); - } - - doPreventExtensions(target, object, factory) { - // Note: target@this(unsafe) object@other(unsafe) throws@this(unsafe) - let keys; // @other(safe-array-of-prim) - try { - keys = otherReflectOwnKeys(object); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; // @prim - let desc; - try { - desc = otherSafeGetOwnPropertyDescriptor(object, key); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - if (!desc) continue; - if (!desc.configurable) { - const current = thisSafeGetOwnPropertyDescriptor(target, key); - if (current && !current.configurable) continue; - if (desc.get || desc.set) { - desc.get = this.fromOtherWithContext(desc.get); - desc.set = this.fromOtherWithContext(desc.set); - } else if (typeof object === 'function' && (key === 'caller' || key === 'callee' || key === 'arguments')) { - desc.value = null; - } else { - desc.value = this.fromOtherWithContext(desc.value); - } - } else { - if (desc.get || desc.set) { - desc = { - __proto__: null, - configurable: true, - enumerable: desc.enumerable, - writable: true, - value: null - }; - } else { - desc.value = null; - } - } - if (!thisReflectDefineProperty(target, key, desc)) throw thisUnexpected(); - } - if (!thisReflectPreventExtensions(target)) throw thisUnexpected(); - } - - get(target, key, receiver) { - // Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - switch (key) { - case 'constructor': { - const desc = otherSafeGetOwnPropertyDescriptor(object, key); - if (desc) return thisDefaultGet(this, object, key, desc); - const proto = thisReflectGetPrototypeOf(target); - return proto === null ? undefined : proto.constructor; - } - case '__proto__': { - const desc = otherSafeGetOwnPropertyDescriptor(object, key); - if (desc) return thisDefaultGet(this, object, key, desc); - return thisReflectGetPrototypeOf(target); - } - case thisSymbolToStringTag: - if (!thisOtherHasOwnProperty(object, thisSymbolToStringTag)) { - const proto = thisReflectGetPrototypeOf(target); - const name = thisReflectApply(thisMapGet, protoName, [proto]); - if (name) return name; - } - break; - case 'arguments': - case 'caller': - case 'callee': - if (typeof object === 'function' && thisOtherHasOwnProperty(object, key)) { - throw thisThrowCallerCalleeArgumentsAccess(key); - } - break; - } - let ret; // @other(unsafe) - try { - ret = otherReflectGet(object, key); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - return this.fromOtherWithContext(ret); - } - - 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) - if (key === '__proto__' && !thisOtherHasOwnProperty(object, key)) { - return this.setPrototypeOf(target, value); - } - try { - value = otherFromThis(value); - return otherReflectSet(object, key, value) === true; - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - } - - getPrototypeOf(target) { - // Note: target@this(unsafe) - return thisReflectGetPrototypeOf(target); - } - - setPrototypeOf(target, value) { - // Note: target@this(unsafe) throws@this(unsafe) - throw new VMError(OPNA); - } - - apply(target, context, args) { - // Note: target@this(unsafe) context@this(unsafe) args@this(safe-array) throws@this(unsafe) - const object = this.object; // @other(unsafe) - let ret; // @other(unsafe) - try { - context = otherFromThis(context); - args = otherFromThisArguments(args); - ret = otherReflectApply(object, context, args); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - return thisFromOther(ret); - } - - construct(target, args, newTarget) { - // Note: target@this(unsafe) args@this(safe-array) newTarget@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - let ret; // @other(unsafe) - try { - args = otherFromThisArguments(args); - ret = otherReflectConstruct(object, args); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - return thisFromOtherWithFactory(this.getFactory(), ret, thisFromOther(object)); - } - - getOwnPropertyDescriptorDesc(target, prop, desc) { - // Note: target@this(unsafe) prop@prim desc@other{safe} throws@this(unsafe) - const object = this.object; // @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) - let desc; // @other(safe) - try { - desc = otherSafeGetOwnPropertyDescriptor(object, prop); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - - desc = this.getOwnPropertyDescriptorDesc(target, prop, desc); - - if (!desc) return undefined; - - let thisDesc; - if (desc.get || desc.set) { - thisDesc = { - __proto__: null, - get: this.fromOtherWithContext(desc.get), - set: this.fromOtherWithContext(desc.set), - enumerable: desc.enumerable === true, - configurable: desc.configurable === true - }; - } else { - thisDesc = { - __proto__: null, - value: this.fromOtherWithContext(desc.value), - writable: desc.writable === true, - enumerable: desc.enumerable === true, - configurable: desc.configurable === true - }; - } - if (!thisDesc.configurable) { - const oldDesc = thisSafeGetOwnPropertyDescriptor(target, prop); - if (!oldDesc || oldDesc.configurable || oldDesc.writable !== thisDesc.writable) { - if (!thisReflectDefineProperty(target, prop, thisDesc)) throw thisUnexpected(); - } - } - return thisDesc; - } - - definePropertyDesc(target, prop, desc) { - // Note: target@this(unsafe) prop@prim desc@this(safe) throws@this(unsafe) - return desc; - } - - defineProperty(target, prop, desc) { - // Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected(); - - desc = this.definePropertyDesc(target, prop, desc); - - if (!desc) return false; - - let otherDesc = {__proto__: null}; - let hasFunc = true; - let hasValue = true; - let hasBasic = true; - hasFunc &= otherFromThisIfAvailable(otherDesc, desc, 'get'); - hasFunc &= otherFromThisIfAvailable(otherDesc, desc, 'set'); - hasValue &= otherFromThisIfAvailable(otherDesc, desc, 'value'); - hasValue &= otherFromThisIfAvailable(otherDesc, desc, 'writable'); - hasBasic &= otherFromThisIfAvailable(otherDesc, desc, 'enumerable'); - hasBasic &= otherFromThisIfAvailable(otherDesc, desc, 'configurable'); - - try { - if (!otherReflectDefineProperty(object, prop, otherDesc)) return false; - if (otherDesc.configurable !== true && (!hasBasic || !(hasFunc || hasValue))) { - otherDesc = otherSafeGetOwnPropertyDescriptor(object, prop); - } - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - - if (!otherDesc.configurable) { - let thisDesc; - if (otherDesc.get || otherDesc.set) { - thisDesc = { - __proto__: null, - get: this.fromOtherWithContext(otherDesc.get), - set: this.fromOtherWithContext(otherDesc.set), - enumerable: otherDesc.enumerable, - configurable: otherDesc.configurable - }; - } else { - thisDesc = { - __proto__: null, - value: this.fromOtherWithContext(otherDesc.value), - writable: otherDesc.writable, - enumerable: otherDesc.enumerable, - configurable: otherDesc.configurable - }; - } - if (!thisReflectDefineProperty(target, prop, thisDesc)) throw thisUnexpected(); - } - return true; - } - - deleteProperty(target, prop) { - // Note: target@this(unsafe) prop@prim throws@this(unsafe) - const object = this.object; // @other(unsafe) - try { - return otherReflectDeleteProperty(object, prop) === true; - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - } - - has(target, key) { - // Note: target@this(unsafe) key@prim throws@this(unsafe) - const object = this.object; // @other(unsafe) - try { - return otherReflectHas(object, key) === true; - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - } - - isExtensible(target) { - // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - try { - if (otherReflectIsExtensible(object)) return true; - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - if (thisReflectIsExtensible(target)) { - this.doPreventExtensions(target, object, this); - } - return false; - } - - ownKeys(target) { - // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - let res; // @other(unsafe) - try { - res = otherReflectOwnKeys(object); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - return thisFromOther(res); - } - - preventExtensions(target) { - // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - try { - if (!otherReflectPreventExtensions(object)) return false; - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - if (thisReflectIsExtensible(target)) { - this.doPreventExtensions(target, object, this); - } - return true; - } - - enumerate(target) { - // Note: target@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - let res; // @other(unsafe) - try { - res = otherReflectEnumerate(object); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - return this.fromOtherWithContext(res); - } - - } - - function defaultFactory(object) { - // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe) - return new BaseHandler(object); - } - - class ProtectedHandler extends BaseHandler { - - getFactory() { - return protectedFactory; - } - - set(target, key, value, receiver) { - // Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe) - if (typeof value === 'function') { - return thisReflectDefineProperty(receiver, key, { - __proto__: null, - value: value, - writable: true, - enumerable: true, - configurable: true - }) === true; - } - return super.set(target, key, value, receiver); - } - - definePropertyDesc(target, prop, desc) { - // Note: target@this(unsafe) prop@prim desc@this(safe) throws@this(unsafe) - if (desc && (desc.set || desc.get || typeof desc.value === 'function')) return undefined; - return desc; - } - - } - - function protectedFactory(object) { - // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe) - return new ProtectedHandler(object); - } - - class ReadOnlyHandler extends BaseHandler { - - getFactory() { - return readonlyFactory; - } - - set(target, key, value, receiver) { - // Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe) - return thisReflectDefineProperty(receiver, key, { - __proto__: null, - value: value, - writable: true, - enumerable: true, - configurable: true - }); - } - - setPrototypeOf(target, value) { - // Note: target@this(unsafe) throws@this(unsafe) - return false; - } - - defineProperty(target, prop, desc) { - // Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe) - return false; - } - - deleteProperty(target, prop) { - // Note: target@this(unsafe) prop@prim throws@this(unsafe) - return false; - } - - isExtensible(target) { - // Note: target@this(unsafe) throws@this(unsafe) - return false; - } - - preventExtensions(target) { - // Note: target@this(unsafe) throws@this(unsafe) - return false; - } - - } - - function readonlyFactory(object) { - // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe) - return new ReadOnlyHandler(object); - } - - class ReadOnlyMockHandler extends ReadOnlyHandler { - - constructor(object, mock) { - // Note: object@other(unsafe) mock:this(unsafe) throws@this(unsafe) - super(object); - this.mock = mock; - } - - get(target, key, receiver) { - // Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe) - const object = this.object; // @other(unsafe) - const mock = this.mock; - if (thisReflectApply(thisObjectHasOwnProperty, mock, key) && !thisOtherHasOwnProperty(object, key)) { - return mock[key]; - } - return super.get(target, key, receiver); - } - - } - - function thisFromOther(other) { - // Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe) - return thisFromOtherWithFactory(defaultFactory, other); - } - - function thisProxyOther(factory, other, proto) { - const target = thisCreateTargetObject(other, proto); - const handler = factory(other); - const proxy = new ThisProxy(target, handler); - try { - otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy, other]); - registerProxy(proxy, handler); - } catch (e) { - throw new VMError('Unexpected error'); - } - if (!isHost) { - thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, proxy]); - return proxy; - } - const proxy2 = new ThisProxy(proxy, emptyForzenObject); - try { - otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy2, other]); - registerProxy(proxy2, handler); - } catch (e) { - throw new VMError('Unexpected error'); - } - thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, proxy2]); - return proxy2; - } - - function thisEnsureThis(other) { - const type = typeof other; - switch (type) { - case 'object': - if (other === null) { - return null; - } - // fallthrough - case 'function': - let proto = thisReflectGetPrototypeOf(other); - if (!proto) { - return other; - } - while (proto) { - const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]); - if (mapping) { - const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]); - if (mapped) return mapped; - return mapping(defaultFactory, other); - } - proto = thisReflectGetPrototypeOf(proto); - } - return other; - case 'undefined': - case 'string': - case 'number': - case 'boolean': - case 'symbol': - case 'bigint': - return other; - - default: // new, unknown types can be dangerous - throw new VMError(`Unknown type '${type}'`); - } - } - - function thisFromOtherForThrow(other) { - for (let loop = 0; loop < 10; loop++) { - const type = typeof other; - switch (type) { - case 'object': - if (other === null) { - return null; - } - // fallthrough - case 'function': - const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]); - if (mapped) return mapped; - let proto; - try { - proto = otherReflectGetPrototypeOf(other); - } catch (e) { // @other(unsafe) - other = e; - break; - } - if (!proto) { - return thisProxyOther(defaultFactory, other, null); - } - for (;;) { - const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]); - if (mapping) return mapping(defaultFactory, other); - try { - proto = otherReflectGetPrototypeOf(proto); - } catch (e) { // @other(unsafe) - other = e; - break; - } - if (!proto) return thisProxyOther(defaultFactory, other, thisObjectPrototype); - } - break; - case 'undefined': - case 'string': - case 'number': - case 'boolean': - case 'symbol': - case 'bigint': - return other; - - default: // new, unknown types can be dangerous - throw new VMError(`Unknown type '${type}'`); - } - } - throw new VMError('Exception recursion depth'); - } - - function thisFromOtherWithFactory(factory, other, proto) { - const type = typeof other; - switch (type) { - case 'object': - if (other === null) { - return null; - } - // fallthrough - case 'function': - const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]); - if (mapped) return mapped; - if (proto) { - return thisProxyOther(factory, other, proto); - } - try { - proto = otherReflectGetPrototypeOf(other); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - if (!proto) { - return thisProxyOther(factory, other, null); - } - do { - const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]); - if (mapping) return mapping(factory, other); - try { - proto = otherReflectGetPrototypeOf(proto); - } catch (e) { // @other(unsafe) - throw thisFromOtherForThrow(e); - } - } while (proto); - return thisProxyOther(factory, other, thisObjectPrototype); - case 'undefined': - case 'string': - case 'number': - case 'boolean': - case 'symbol': - case 'bigint': - return other; - - default: // new, unknown types can be dangerous - throw new VMError(`Unknown type '${type}'`); - } - } - - function thisFromOtherArguments(args) { - // Note: args@other(safe-array) returns@this(safe-array) throws@this(unsafe) - const arr = []; - for (let i = 0; i < args.length; i++) { - const value = thisFromOther(args[i]); - thisReflectDefineProperty(arr, i, { - __proto__: null, - value: value, - writable: true, - enumerable: true, - configurable: true - }); - } - return arr; - } - - function thisConnect(obj, other) { - // Note: obj@this(unsafe) other@other(unsafe) throws@this(unsafe) - try { - otherReflectApply(otherWeakMapSet, mappingThisToOther, [obj, other]); - } catch (e) { - throw new VMError('Unexpected error'); - } - thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, obj]); - } - - thisAddProtoMapping(thisGlobalPrototypes.Object, otherGlobalPrototypes.Object); - thisAddProtoMapping(thisGlobalPrototypes.Array, otherGlobalPrototypes.Array); - - for (let i = 0; i < globalsList.length; i++) { - const key = globalsList[i]; - const tp = thisGlobalPrototypes[key]; - const op = otherGlobalPrototypes[key]; - if (tp && op) thisAddProtoMapping(tp, op, key); - } - - for (let i = 0; i < errorsList.length; i++) { - const key = errorsList[i]; - const tp = thisGlobalPrototypes[key]; - const op = otherGlobalPrototypes[key]; - if (tp && op) thisAddProtoMapping(tp, op, 'Error'); - } - - thisAddProtoMapping(thisGlobalPrototypes.VMError, otherGlobalPrototypes.VMError, 'Error'); - - result.BaseHandler = BaseHandler; - result.ProtectedHandler = ProtectedHandler; - result.ReadOnlyHandler = ReadOnlyHandler; - result.ReadOnlyMockHandler = ReadOnlyMockHandler; - - return result; -} - -exports.createBridge = createBridge; -exports.VMError = VMError; diff --git a/dist/events.js b/dist/events.js deleted file mode 100644 index 624e827..0000000 --- a/dist/events.js +++ /dev/null @@ -1,977 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Modified by the vm2 team to make this a standalone module to be loaded into the sandbox. - -'use strict'; - -const host = fromhost; - -const { - Boolean, - Error, - String, - Symbol -} = globalThis; - -const ReflectApply = Reflect.apply; -const ReflectOwnKeys = Reflect.ownKeys; - -const ErrorCaptureStackTrace = Error.captureStackTrace; - -const NumberIsNaN = Number.isNaN; - -const ObjectCreate = Object.create; -const ObjectDefineProperty = Object.defineProperty; -const ObjectDefineProperties = Object.defineProperties; -const ObjectGetPrototypeOf = Object.getPrototypeOf; - -const SymbolFor = Symbol.for; - -function uncurryThis(func) { - return (thiz, ...args) => ReflectApply(func, thiz, args); -} - -const ArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf); -const ArrayPrototypeJoin = uncurryThis(Array.prototype.join); -const ArrayPrototypeSlice = uncurryThis(Array.prototype.slice); -const ArrayPrototypeSplice = uncurryThis(Array.prototype.splice); -const ArrayPrototypeUnshift = uncurryThis(Array.prototype.unshift); - -const kRejection = SymbolFor('nodejs.rejection'); - -function inspect(obj) { - return typeof obj === 'symbol' ? obj.toString() : `${obj}`; -} - -function spliceOne(list, index) { - for (; index + 1 < list.length; index++) - list[index] = list[index + 1]; - list.pop(); -} - -function assert(what, message) { - if (!what) throw new Error(message); -} - -function E(key, msg, Base) { - return function NodeError(...args) { - const error = new Base(); - const message = ReflectApply(msg, error, args); - ObjectDefineProperties(error, { - message: { - value: message, - enumerable: false, - writable: true, - configurable: true, - }, - toString: { - value() { - return `${this.name} [${key}]: ${this.message}`; - }, - enumerable: false, - writable: true, - configurable: true, - }, - }); - error.code = key; - return error; - }; -} - - -const ERR_INVALID_ARG_TYPE = E('ERR_INVALID_ARG_TYPE', - (name, expected, actual) => { - assert(typeof name === 'string', "'name' must be a string"); - if (!ArrayIsArray(expected)) { - expected = [expected]; - } - - let msg = 'The '; - if (StringPrototypeEndsWith(name, ' argument')) { - // For cases like 'first argument' - msg += `${name} `; - } else { - const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument'; - msg += `"${name}" ${type} `; - } - msg += 'must be '; - - const types = []; - const instances = []; - const other = []; - - for (const value of expected) { - assert(typeof value === 'string', - 'All expected entries have to be of type string'); - if (ArrayPrototypeIncludes(kTypes, value)) { - ArrayPrototypePush(types, StringPrototypeToLowerCase(value)); - } else if (RegExpPrototypeTest(classRegExp, value)) { - ArrayPrototypePush(instances, value); - } else { - assert(value !== 'object', - 'The value "object" should be written as "Object"'); - ArrayPrototypePush(other, value); - } - } - - // Special handle `object` in case other instances are allowed to outline - // the differences between each other. - if (instances.length > 0) { - const pos = ArrayPrototypeIndexOf(types, 'object'); - if (pos !== -1) { - ArrayPrototypeSplice(types, pos, 1); - ArrayPrototypePush(instances, 'Object'); - } - } - - if (types.length > 0) { - if (types.length > 2) { - const last = ArrayPrototypePop(types); - msg += `one of type ${ArrayPrototypeJoin(types, ', ')}, or ${last}`; - } else if (types.length === 2) { - msg += `one of type ${types[0]} or ${types[1]}`; - } else { - msg += `of type ${types[0]}`; - } - if (instances.length > 0 || other.length > 0) - msg += ' or '; - } - - if (instances.length > 0) { - if (instances.length > 2) { - const last = ArrayPrototypePop(instances); - msg += - `an instance of ${ArrayPrototypeJoin(instances, ', ')}, or ${last}`; - } else { - msg += `an instance of ${instances[0]}`; - if (instances.length === 2) { - msg += ` or ${instances[1]}`; - } - } - if (other.length > 0) - msg += ' or '; - } - - if (other.length > 0) { - if (other.length > 2) { - const last = ArrayPrototypePop(other); - msg += `one of ${ArrayPrototypeJoin(other, ', ')}, or ${last}`; - } else if (other.length === 2) { - msg += `one of ${other[0]} or ${other[1]}`; - } else { - if (StringPrototypeToLowerCase(other[0]) !== other[0]) - msg += 'an '; - msg += `${other[0]}`; - } - } - - if (actual == null) { - msg += `. Received ${actual}`; - } else if (typeof actual === 'function' && actual.name) { - msg += `. Received function ${actual.name}`; - } else if (typeof actual === 'object') { - if (actual.constructor && actual.constructor.name) { - msg += `. Received an instance of ${actual.constructor.name}`; - } else { - const inspected = inspect(actual, { depth: -1 }); - msg += `. Received ${inspected}`; - } - } else { - let inspected = inspect(actual, { colors: false }); - if (inspected.length > 25) - inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`; - msg += `. Received type ${typeof actual} (${inspected})`; - } - return msg; - }, TypeError); - -const ERR_INVALID_THIS = E('ERR_INVALID_THIS', s => `Value of "this" must be of type ${s}`, TypeError); - -const ERR_OUT_OF_RANGE = E('ERR_OUT_OF_RANGE', - (str, range, input, replaceDefaultBoolean = false) => { - assert(range, 'Missing "range" argument'); - let msg = replaceDefaultBoolean ? str : - `The value of "${str}" is out of range.`; - const received = inspect(input); - msg += ` It must be ${range}. Received ${received}`; - return msg; - }, RangeError); - -const ERR_UNHANDLED_ERROR = E('ERR_UNHANDLED_ERROR', - err => { - const msg = 'Unhandled error.'; - if (err === undefined) return msg; - return `${msg} (${err})`; - }, Error); - -function validateBoolean(value, name) { - if (typeof value !== 'boolean') - throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value); -} - -function validateFunction(value, name) { - if (typeof value !== 'function') - throw new ERR_INVALID_ARG_TYPE(name, 'Function', value); -} - -function validateString(value, name) { - if (typeof value !== 'string') - throw new ERR_INVALID_ARG_TYPE(name, 'string', value); -} - -function nc(cond, e) { - return cond === undefined || cond === null ? e : cond; -} - -function oc(base, key) { - return base === undefined || base === null ? undefined : base[key]; -} - -const kCapture = Symbol('kCapture'); -const kErrorMonitor = host.kErrorMonitor || Symbol('events.errorMonitor'); -const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners'); -const kMaxEventTargetListenersWarned = - Symbol('events.maxEventTargetListenersWarned'); - -const kIsEventTarget = SymbolFor('nodejs.event_target'); - -function isEventTarget(obj) { - return oc(oc(obj, 'constructor'), kIsEventTarget); -} - -/** - * Creates a new `EventEmitter` instance. - * @param {{ captureRejections?: boolean; }} [opts] - * @constructs {EventEmitter} - */ -function EventEmitter(opts) { - EventEmitter.init.call(this, opts); -} -module.exports = EventEmitter; -if (host.once) module.exports.once = host.once; -if (host.on) module.exports.on = host.on; -if (host.getEventListeners) module.exports.getEventListeners = host.getEventListeners; -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.usingDomains = false; - -EventEmitter.captureRejectionSymbol = kRejection; -ObjectDefineProperty(EventEmitter, 'captureRejections', { - get() { - return EventEmitter.prototype[kCapture]; - }, - set(value) { - validateBoolean(value, 'EventEmitter.captureRejections'); - - EventEmitter.prototype[kCapture] = value; - }, - enumerable: true -}); - -if (host.EventEmitterReferencingAsyncResource) { - const kAsyncResource = Symbol('kAsyncResource'); - const EventEmitterReferencingAsyncResource = host.EventEmitterReferencingAsyncResource; - - class EventEmitterAsyncResource extends EventEmitter { - /** - * @param {{ - * name?: string, - * triggerAsyncId?: number, - * requireManualDestroy?: boolean, - * }} [options] - */ - constructor(options = undefined) { - let name; - if (typeof options === 'string') { - name = options; - options = undefined; - } else { - if (new.target === EventEmitterAsyncResource) { - validateString(oc(options, 'name'), 'options.name'); - } - name = oc(options, 'name') || new.target.name; - } - super(options); - - this[kAsyncResource] = - new EventEmitterReferencingAsyncResource(this, name, options); - } - - /** - * @param {symbol,string} event - * @param {...any} args - * @returns {boolean} - */ - emit(event, ...args) { - if (this[kAsyncResource] === undefined) - throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); - const { asyncResource } = this; - ArrayPrototypeUnshift(args, super.emit, this, event); - return ReflectApply(asyncResource.runInAsyncScope, asyncResource, - args); - } - - /** - * @returns {void} - */ - emitDestroy() { - if (this[kAsyncResource] === undefined) - throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); - this.asyncResource.emitDestroy(); - } - - /** - * @type {number} - */ - get asyncId() { - if (this[kAsyncResource] === undefined) - throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); - return this.asyncResource.asyncId(); - } - - /** - * @type {number} - */ - get triggerAsyncId() { - if (this[kAsyncResource] === undefined) - throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); - return this.asyncResource.triggerAsyncId(); - } - - /** - * @type {EventEmitterReferencingAsyncResource} - */ - get asyncResource() { - if (this[kAsyncResource] === undefined) - throw new ERR_INVALID_THIS('EventEmitterAsyncResource'); - return this[kAsyncResource]; - } - } - EventEmitter.EventEmitterAsyncResource = EventEmitterAsyncResource; -} - -EventEmitter.errorMonitor = kErrorMonitor; - -// The default for captureRejections is false -ObjectDefineProperty(EventEmitter.prototype, kCapture, { - value: false, - writable: true, - enumerable: false -}); - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._eventsCount = 0; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -let defaultMaxListeners = 10; - -function checkListener(listener) { - validateFunction(listener, 'listener'); -} - -ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', { - enumerable: true, - get: function() { - return defaultMaxListeners; - }, - set: function(arg) { - if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { - throw new ERR_OUT_OF_RANGE('defaultMaxListeners', - 'a non-negative number', - arg); - } - defaultMaxListeners = arg; - } -}); - -ObjectDefineProperties(EventEmitter, { - kMaxEventTargetListeners: { - value: kMaxEventTargetListeners, - enumerable: false, - configurable: false, - writable: false, - }, - kMaxEventTargetListenersWarned: { - value: kMaxEventTargetListenersWarned, - enumerable: false, - configurable: false, - writable: false, - } -}); - -/** - * Sets the max listeners. - * @param {number} n - * @param {EventTarget[] | EventEmitter[]} [eventTargets] - * @returns {void} - */ -EventEmitter.setMaxListeners = - function(n = defaultMaxListeners, ...eventTargets) { - if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) - throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n); - if (eventTargets.length === 0) { - defaultMaxListeners = n; - } else { - for (let i = 0; i < eventTargets.length; i++) { - const target = eventTargets[i]; - if (isEventTarget(target)) { - target[kMaxEventTargetListeners] = n; - target[kMaxEventTargetListenersWarned] = false; - } else if (typeof target.setMaxListeners === 'function') { - target.setMaxListeners(n); - } else { - throw new ERR_INVALID_ARG_TYPE( - 'eventTargets', - ['EventEmitter', 'EventTarget'], - target); - } - } - } - }; - -// If you're updating this function definition, please also update any -// re-definitions, such as the one in the Domain module (lib/domain.js). -EventEmitter.init = function(opts) { - - if (this._events === undefined || - this._events === ObjectGetPrototypeOf(this)._events) { - this._events = ObjectCreate(null); - this._eventsCount = 0; - } - - this._maxListeners = this._maxListeners || undefined; - - - if (oc(opts, 'captureRejections')) { - validateBoolean(opts.captureRejections, 'options.captureRejections'); - this[kCapture] = Boolean(opts.captureRejections); - } else { - // Assigning the kCapture property directly saves an expensive - // prototype lookup in a very sensitive hot path. - this[kCapture] = EventEmitter.prototype[kCapture]; - } -}; - -function addCatch(that, promise, type, args) { - if (!that[kCapture]) { - return; - } - - // Handle Promises/A+ spec, then could be a getter - // that throws on second use. - try { - const then = promise.then; - - if (typeof then === 'function') { - then.call(promise, undefined, function(err) { - // The callback is called with nextTick to avoid a follow-up - // rejection from this promise. - process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args); - }); - } - } catch (err) { - that.emit('error', err); - } -} - -function emitUnhandledRejectionOrErr(ee, err, type, args) { - if (typeof ee[kRejection] === 'function') { - ee[kRejection](err, type, ...args); - } else { - // We have to disable the capture rejections mechanism, otherwise - // we might end up in an infinite loop. - const prev = ee[kCapture]; - - // If the error handler throws, it is not catchable and it - // will end up in 'uncaughtException'. We restore the previous - // value of kCapture in case the uncaughtException is present - // and the exception is handled. - try { - ee[kCapture] = false; - ee.emit('error', err); - } finally { - ee[kCapture] = prev; - } - } -} - -/** - * Increases the max listeners of the event emitter. - * @param {number} n - * @returns {EventEmitter} - */ -EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { - throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n); - } - this._maxListeners = n; - return this; -}; - -function _getMaxListeners(that) { - if (that._maxListeners === undefined) - return EventEmitter.defaultMaxListeners; - return that._maxListeners; -} - -/** - * Returns the current max listener value for the event emitter. - * @returns {number} - */ -EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return _getMaxListeners(this); -}; - -/** - * Synchronously calls each of the listeners registered - * for the event. - * @param {string | symbol} type - * @param {...any} [args] - * @returns {boolean} - */ -EventEmitter.prototype.emit = function emit(type, ...args) { - let doError = (type === 'error'); - - const events = this._events; - if (events !== undefined) { - if (doError && events[kErrorMonitor] !== undefined) - this.emit(kErrorMonitor, ...args); - doError = (doError && events.error === undefined); - } else if (!doError) - return false; - - // If there is no 'error' event listener then throw. - if (doError) { - let er; - if (args.length > 0) - er = args[0]; - if (er instanceof Error) { - try { - const capture = {}; - ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit); - } catch (e) {} - - // Note: The comments on the `throw` lines are intentional, they show - // up in Node's output if this results in an unhandled exception. - throw er; // Unhandled 'error' event - } - - let stringifiedEr; - try { - stringifiedEr = inspect(er); - } catch (e) { - stringifiedEr = er; - } - - // At least give some kind of context to the user - const err = new ERR_UNHANDLED_ERROR(stringifiedEr); - err.context = er; - throw err; // Unhandled 'error' event - } - - const handler = events[type]; - - if (handler === undefined) - return false; - - if (typeof handler === 'function') { - const result = handler.apply(this, args); - - // We check if result is undefined first because that - // is the most common case so we do not pay any perf - // penalty - if (result !== undefined && result !== null) { - addCatch(this, result, type, args); - } - } else { - const len = handler.length; - const listeners = arrayClone(handler); - for (let i = 0; i < len; ++i) { - const result = listeners[i].apply(this, args); - - // We check if result is undefined first because that - // is the most common case so we do not pay any perf - // penalty. - // This code is duplicated because extracting it away - // would make it non-inlineable. - if (result !== undefined && result !== null) { - addCatch(this, result, type, args); - } - } - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - let m; - let events; - let existing; - - checkListener(listener); - - events = target._events; - if (events === undefined) { - events = target._events = ObjectCreate(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener !== undefined) { - target.emit('newListener', type, - nc(listener.listener, listener)); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (existing === undefined) { - // Optimize the case of one listener. Don't need the extra array object. - events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - // If we've already got an array, just append. - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - - // Check for listener leak - m = _getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - // No error code for this since it is a Warning - // eslint-disable-next-line no-restricted-syntax - const w = new Error('Possible EventEmitter memory leak detected. ' + - `${existing.length} ${String(type)} listeners ` + - `added to ${inspect(target, { depth: -1 })}. Use ` + - 'emitter.setMaxListeners() to increase limit'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - process.emitWarning(w); - } - } - - return target; -} - -/** - * Adds a listener to the event emitter. - * @param {string | symbol} type - * @param {Function} listener - * @returns {EventEmitter} - */ -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -/** - * Adds the `listener` function to the beginning of - * the listeners array. - * @param {string | symbol} type - * @param {Function} listener - * @returns {EventEmitter} - */ -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - if (arguments.length === 0) - return this.listener.call(this.target); - return this.listener.apply(this.target, arguments); - } -} - -function _onceWrap(target, type, listener) { - const state = { fired: false, wrapFn: undefined, target, type, listener }; - const wrapped = onceWrapper.bind(state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -/** - * Adds a one-time `listener` function to the event emitter. - * @param {string | symbol} type - * @param {Function} listener - * @returns {EventEmitter} - */ -EventEmitter.prototype.once = function once(type, listener) { - checkListener(listener); - - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -/** - * Adds a one-time `listener` function to the beginning of - * the listeners array. - * @param {string | symbol} type - * @param {Function} listener - * @returns {EventEmitter} - */ -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - checkListener(listener); - - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - - -/** - * Removes the specified `listener` from the listeners array. - * @param {string | symbol} type - * @param {Function} listener - * @returns {EventEmitter} - */ -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - checkListener(listener); - - const events = this._events; - if (events === undefined) - return this; - - const list = events[type]; - if (list === undefined) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = ObjectCreate(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - let position = -1; - - for (let i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else { - spliceOne(list, position); - } - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener !== undefined) - this.emit('removeListener', type, listener); - } - - return this; - }; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -/** - * Removes all listeners from the event emitter. (Only - * removes listeners for a specific event name if specified - * as `type`). - * @param {string | symbol} [type] - * @returns {EventEmitter} - */ -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - const events = this._events; - if (events === undefined) - return this; - - // Not listening for removeListener, no need to emit - if (events.removeListener === undefined) { - if (arguments.length === 0) { - this._events = ObjectCreate(null); - this._eventsCount = 0; - } else if (events[type] !== undefined) { - if (--this._eventsCount === 0) - this._events = ObjectCreate(null); - else - delete events[type]; - } - return this; - } - - // Emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (const key of ReflectOwnKeys(events)) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = ObjectCreate(null); - this._eventsCount = 0; - return this; - } - - const listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners !== undefined) { - // LIFO order - for (let i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - const events = target._events; - - if (events === undefined) - return []; - - const evlistener = events[type]; - if (evlistener === undefined) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? - unwrapListeners(evlistener) : arrayClone(evlistener); -} - -/** - * Returns a copy of the array of listeners for the event name - * specified as `type`. - * @param {string | symbol} type - * @returns {Function[]} - */ -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -/** - * Returns a copy of the array of listeners and wrappers for - * the event name specified as `type`. - * @param {string | symbol} type - * @returns {Function[]} - */ -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -/** - * Returns the number of listeners listening to the event name - * specified as `type`. - * @deprecated since v3.2.0 - * @param {EventEmitter} emitter - * @param {string | symbol} type - * @returns {number} - */ -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } - return emitter.listenerCount(type); -}; - -EventEmitter.prototype.listenerCount = listenerCount; - -/** - * Returns the number of listeners listening to event name - * specified as `type`. - * @param {string | symbol} type - * @returns {number} - */ -function listenerCount(type) { - const events = this._events; - - if (events !== undefined) { - const evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener !== undefined) { - return evlistener.length; - } - } - - return 0; -} - -/** - * Returns an array listing the events for which - * the emitter has registered listeners. - * @returns {any[]} - */ -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; -}; - -function arrayClone(arr) { - // At least since V8 8.3, this implementation is faster than the previous - // which always used a simple for-loop - switch (arr.length) { - case 2: return [arr[0], arr[1]]; - case 3: return [arr[0], arr[1], arr[2]]; - case 4: return [arr[0], arr[1], arr[2], arr[3]]; - case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]]; - case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]]; - } - return ArrayPrototypeSlice(arr); -} - -function unwrapListeners(arr) { - const ret = arrayClone(arr); - for (let i = 0; i < ret.length; ++i) { - const orig = ret[i].listener; - if (typeof orig === 'function') - ret[i] = orig; - } - return ret; -} diff --git a/dist/index.js b/dist/index.js index fd64d74..42f144c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13706,142 +13706,146 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { -const { Octokit } = __nccwpck_require__(1231); -const core = __nccwpck_require__(2186); -const github = __nccwpck_require__(5438); -const { execSync } = __nccwpck_require__(2081); -const { existsSync } = __nccwpck_require__(7147); - -const { runId, repo: { repo, owner }, eventName } = github.context; -process.env.GITHUB_TOKEN = process.argv[2]; -const mainBranchName = process.argv[3]; -const errorOnNoSuccessfulWorkflow = process.argv[4]; -const lastSuccessfulEvent = process.argv[5]; -const workingDirectory = process.argv[6]; -const workflowId = process.argv[7]; -const defaultWorkingDirectory = '.'; - -let BASE_SHA; -(async () => { - if (workingDirectory !== defaultWorkingDirectory) { - if (existsSync(workingDirectory)) { - process.chdir(workingDirectory); - } else { - process.stdout.write('\n'); - process.stdout.write(`WARNING: Working directory '${workingDirectory}' doesn't exist.\n`); - } - } - - const HEAD_SHA = execSync(`git rev-parse HEAD`, { encoding: 'utf-8' }); - - if (eventName === 'pull_request' && !github.context.payload.pull_request.merged) { - BASE_SHA = execSync(`git merge-base origin/${mainBranchName} HEAD`, { encoding: 'utf-8' }); - } else { - try { - BASE_SHA = await findSuccessfulCommit(workflowId, runId, owner, repo, mainBranchName, lastSuccessfulEvent); - } catch (e) { - core.setFailed(e.message); - return; - } - - if (!BASE_SHA) { - if (errorOnNoSuccessfulWorkflow === 'true') { - reportFailure(mainBranchName); - return; - } else { - process.stdout.write('\n'); - process.stdout.write(`WARNING: Unable to find a successful workflow run on 'origin/${mainBranchName}'\n`); - process.stdout.write(`We are therefore defaulting to use HEAD~1 on 'origin/${mainBranchName}'\n`); - process.stdout.write('\n'); - process.stdout.write(`NOTE: You can instead make this a hard error by setting 'error-on-no-successful-workflow' on the action in your workflow.\n`); - - BASE_SHA = execSync(`git rev-parse origin/${mainBranchName}~1`, { encoding: 'utf-8' }); - core.setOutput('noPreviousBuild', 'true'); - } - } else { - process.stdout.write('\n'); - process.stdout.write(`Found the last successful workflow run on 'origin/${mainBranchName}'\n`); - process.stdout.write(`Commit: ${BASE_SHA}\n`); - } - } - - const stripNewLineEndings = sha => sha.replace('\n', ''); - core.setOutput('base', stripNewLineEndings(BASE_SHA)); - core.setOutput('head', stripNewLineEndings(HEAD_SHA)); -})(); - -function reportFailure(branchName) { - core.setFailed(` - Unable to find a successful workflow run on 'origin/${branchName}' - NOTE: You have set 'error-on-no-successful-workflow' on the action so this is a hard error. - - Is it possible that you have no runs currently on 'origin/${branchName}'? - - If yes, then you should run the workflow without this flag first. - - If no, then you might have changed your git history and those commits no longer exist.`); -} - -/** - * Find last successful workflow run on the repo - * @param {string?} workflow_id - * @param {number} run_id - * @param {string} owner - * @param {string} repo - * @param {string} branch - * @returns - */ -async function findSuccessfulCommit(workflow_id, run_id, owner, repo, branch, lastSuccessfulEvent) { - const octokit = new Octokit(); - if (!workflow_id) { - workflow_id = await octokit.request(`GET /repos/${owner}/${repo}/actions/runs/${run_id}`, { - owner, - repo, - branch, - run_id - }).then(({ data: { workflow_id } }) => workflow_id); - process.stdout.write('\n'); - process.stdout.write(`Workflow Id not provided. Using workflow '${workflow_id}'\n`); - } - // fetch all workflow runs on a given repo/branch/workflow with push and success - const shas = await octokit.request(`GET /repos/${owner}/${repo}/actions/workflows/${workflow_id}/runs`, { - owner, - repo, - // on non-push workflow runs we do not have branch property - branch: lastSuccessfulEvent !== 'push' ? undefined : branch, - workflow_id, - event: lastSuccessfulEvent, - status: 'success' - }).then(({ data: { workflow_runs } }) => workflow_runs.map(run => run.head_sha)); - - return await findExistingCommit(shas); -} - -/** - * Get first existing commit - * @param {string[]} commit_shas - * @returns {string?} - */ -async function findExistingCommit(shas) { - for (const commitSha of shas) { - if (await commitExists(commitSha)) { - return commitSha; - } - } - return undefined; -} - -/** - * Check if given commit is valid - * @param {string} commitSha - * @returns {boolean} - */ -async function commitExists(commitSha) { - try { - execSync(`git cat-file -e ${commitSha}`, { stdio: ['pipe', 'pipe', null] }); - return true; - } catch { - return false; - } -} +const { Octokit } = __nccwpck_require__(1231); +const core = __nccwpck_require__(2186); +const github = __nccwpck_require__(5438); +const { spawnSync } = __nccwpck_require__(2081); +const { existsSync } = __nccwpck_require__(7147); + +const { runId, repo: { repo, owner }, eventName } = github.context; +process.env.GITHUB_TOKEN = process.argv[2]; +const mainBranchName = process.argv[3]; +const errorOnNoSuccessfulWorkflow = process.argv[4]; +const lastSuccessfulEvent = process.argv[5]; +const workingDirectory = process.argv[6]; +const workflowId = process.argv[7]; +const defaultWorkingDirectory = '.'; + +let BASE_SHA; +(async () => { + if (workingDirectory !== defaultWorkingDirectory) { + if (existsSync(workingDirectory)) { + process.chdir(workingDirectory); + } else { + process.stdout.write('\n'); + process.stdout.write(`WARNING: Working directory '${workingDirectory}' doesn't exist.\n`); + } + } + + const headResult = spawnSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf-8' }); + const HEAD_SHA = headResult.stdout; + + if (['pull_request','pull_request_target'].includes(eventName) && !github.context.payload.pull_request.merged) { + const baseResult = spawnSync('git', ['merge-base', `origin/${mainBranchName}`, 'HEAD'], { encoding: 'utf-8' }); + BASE_SHA = baseResult.stdout; + } else { + try { + BASE_SHA = await findSuccessfulCommit(workflowId, runId, owner, repo, mainBranchName, lastSuccessfulEvent); + } catch (e) { + core.setFailed(e.message); + return; + } + + if (!BASE_SHA) { + if (errorOnNoSuccessfulWorkflow === 'true') { + reportFailure(mainBranchName); + return; + } else { + process.stdout.write('\n'); + process.stdout.write(`WARNING: Unable to find a successful workflow run on 'origin/${mainBranchName}'\n`); + process.stdout.write(`We are therefore defaulting to use HEAD~1 on 'origin/${mainBranchName}'\n`); + process.stdout.write('\n'); + process.stdout.write(`NOTE: You can instead make this a hard error by setting 'error-on-no-successful-workflow' on the action in your workflow.\n`); + + const baseRes = spawnSync('git', ['rev-parse', `origin/${mainBranchName}~1`], { encoding: 'utf-8' }); + BASE_SHA = baseRes.stdout; + + core.setOutput('noPreviousBuild', 'true'); + } + } else { + process.stdout.write('\n'); + process.stdout.write(`Found the last successful workflow run on 'origin/${mainBranchName}'\n`); + process.stdout.write(`Commit: ${BASE_SHA}\n`); + } + } + + const stripNewLineEndings = sha => sha.replace('\n', ''); + core.setOutput('base', stripNewLineEndings(BASE_SHA)); + core.setOutput('head', stripNewLineEndings(HEAD_SHA)); +})(); + +function reportFailure(branchName) { + core.setFailed(` + Unable to find a successful workflow run on 'origin/${branchName}' + NOTE: You have set 'error-on-no-successful-workflow' on the action so this is a hard error. + + Is it possible that you have no runs currently on 'origin/${branchName}'? + - If yes, then you should run the workflow without this flag first. + - If no, then you might have changed your git history and those commits no longer exist.`); +} + +/** + * Find last successful workflow run on the repo + * @param {string?} workflow_id + * @param {number} run_id + * @param {string} owner + * @param {string} repo + * @param {string} branch + * @returns + */ +async function findSuccessfulCommit(workflow_id, run_id, owner, repo, branch, lastSuccessfulEvent) { + const octokit = new Octokit(); + if (!workflow_id) { + workflow_id = await octokit.request(`GET /repos/${owner}/${repo}/actions/runs/${run_id}`, { + owner, + repo, + branch, + run_id + }).then(({ data: { workflow_id } }) => workflow_id); + process.stdout.write('\n'); + process.stdout.write(`Workflow Id not provided. Using workflow '${workflow_id}'\n`); + } + // fetch all workflow runs on a given repo/branch/workflow with push and success + const shas = await octokit.request(`GET /repos/${owner}/${repo}/actions/workflows/${workflow_id}/runs`, { + owner, + repo, + // on non-push workflow runs we do not have branch property + branch: lastSuccessfulEvent !== 'push' ? undefined : branch, + workflow_id, + event: lastSuccessfulEvent, + status: 'success' + }).then(({ data: { workflow_runs } }) => workflow_runs.map(run => run.head_sha)); + + return await findExistingCommit(shas); +} + +/** + * Get first existing commit + * @param {string[]} commit_shas + * @returns {string?} + */ +async function findExistingCommit(shas) { + for (const commitSha of shas) { + if (await commitExists(commitSha)) { + return commitSha; + } + } + return undefined; +} + +/** + * Check if given commit is valid + * @param {string} commitSha + * @returns {boolean} + */ +async function commitExists(commitSha) { + try { + spawnSync('git', ['cat-file', '-e', commitSha], { stdio: ['pipe', 'pipe', null] }); + return true; + } catch { + return false; + } +} })(); diff --git a/dist/setup-node-sandbox.js b/dist/setup-node-sandbox.js deleted file mode 100644 index aecf2f6..0000000 --- a/dist/setup-node-sandbox.js +++ /dev/null @@ -1,464 +0,0 @@ -/* global host, data, VMError */ - -'use strict'; - -const LocalError = Error; -const LocalTypeError = TypeError; -const LocalWeakMap = WeakMap; - -const { - apply: localReflectApply, - defineProperty: localReflectDefineProperty -} = Reflect; - -const { - set: localWeakMapSet, - get: localWeakMapGet -} = LocalWeakMap.prototype; - -const { - isArray: localArrayIsArray -} = Array; - -function uncurryThis(func) { - return (thiz, ...args) => localReflectApply(func, thiz, args); -} - -const localArrayPrototypeSlice = uncurryThis(Array.prototype.slice); -const localArrayPrototypeIncludes = uncurryThis(Array.prototype.includes); -const localArrayPrototypePush = uncurryThis(Array.prototype.push); -const localArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf); -const localArrayPrototypeSplice = uncurryThis(Array.prototype.splice); -const localStringPrototypeStartsWith = uncurryThis(String.prototype.startsWith); -const localStringPrototypeSlice = uncurryThis(String.prototype.slice); -const localStringPrototypeIndexOf = uncurryThis(String.prototype.indexOf); - -const { - argv: optionArgv, - env: optionEnv, - console: optionConsole, - vm, - resolver, - extensions -} = data; - -function ensureSandboxArray(a) { - return localArrayPrototypeSlice(a); -} - -const globalPaths = ensureSandboxArray(resolver.globalPaths); - -class Module { - - constructor(id, path, parent) { - this.id = id; - this.filename = id; - this.path = path; - this.parent = parent; - this.loaded = false; - this.paths = path ? ensureSandboxArray(resolver.genLookupPaths(path)) : []; - this.children = []; - this.exports = {}; - } - - _updateChildren(child, isNew) { - const children = this.children; - if (children && (isNew || !localArrayPrototypeIncludes(children, child))) { - localArrayPrototypePush(children, child); - } - } - - require(id) { - return requireImpl(this, id, false); - } - -} - -const originalRequire = Module.prototype.require; -const cacheBuiltins = {__proto__: null}; - -function requireImpl(mod, id, direct) { - if (direct && mod.require !== originalRequire) { - return mod.require(id); - } - const filename = resolver.resolve(mod, id, undefined, Module._extensions, direct); - if (localStringPrototypeStartsWith(filename, 'node:')) { - id = localStringPrototypeSlice(filename, 5); - let nmod = cacheBuiltins[id]; - if (!nmod) { - nmod = resolver.loadBuiltinModule(vm, id); - if (!nmod) throw new VMError(`Cannot find module '${filename}'`, 'ENOTFOUND'); - cacheBuiltins[id] = nmod; - } - return nmod; - } - - const cachedModule = Module._cache[filename]; - if (cachedModule !== undefined) { - mod._updateChildren(cachedModule, false); - return cachedModule.exports; - } - - let nmod = cacheBuiltins[id]; - if (nmod) return nmod; - nmod = resolver.loadBuiltinModule(vm, id); - if (nmod) { - cacheBuiltins[id] = nmod; - return nmod; - } - - const path = resolver.pathDirname(filename); - const module = new Module(filename, path, mod); - resolver.registerModule(module, filename, path, mod, direct); - mod._updateChildren(module, true); - try { - Module._cache[filename] = module; - const handler = findBestExtensionHandler(filename); - handler(module, filename); - module.loaded = true; - } catch (e) { - delete Module._cache[filename]; - const children = mod.children; - if (localArrayIsArray(children)) { - const index = localArrayPrototypeIndexOf(children, module); - if (index !== -1) { - localArrayPrototypeSplice(children, index, 1); - } - } - throw e; - } - - return module.exports; -} - -Module.builtinModules = ensureSandboxArray(resolver.getBuiltinModulesList()); -Module.globalPaths = globalPaths; -Module._extensions = {__proto__: null}; -Module._cache = {__proto__: null}; - -{ - const keys = Object.getOwnPropertyNames(extensions); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const handler = extensions[key]; - Module._extensions[key] = (mod, filename) => handler(mod, filename); - } -} - -function findBestExtensionHandler(filename) { - const name = resolver.pathBasename(filename); - for (let i = 0; (i = localStringPrototypeIndexOf(name, '.', i + 1)) !== -1;) { - const ext = localStringPrototypeSlice(name, i); - const handler = Module._extensions[ext]; - if (handler) return handler; - } - const js = Module._extensions['.js']; - if (js) return js; - const keys = Object.getOwnPropertyNames(Module._extensions); - if (keys.length === 0) throw new VMError(`Failed to load '${filename}': Unknown type.`, 'ELOADFAIL'); - return Module._extensions[keys[0]]; -} - -function createRequireForModule(mod) { - // eslint-disable-next-line no-shadow - function require(id) { - return requireImpl(mod, id, true); - } - function resolve(id, options) { - return resolver.resolve(mod, id, options, Module._extensions, true); - } - require.resolve = resolve; - function paths(id) { - return ensureSandboxArray(resolver.lookupPaths(mod, id)); - } - resolve.paths = paths; - - require.extensions = Module._extensions; - - require.cache = Module._cache; - - return require; -} - -/** - * Prepare sandbox. - */ - -const TIMERS = new LocalWeakMap(); - -class Timeout { -} - -class Interval { -} - -class Immediate { -} - -function clearTimer(timer) { - const obj = localReflectApply(localWeakMapGet, TIMERS, [timer]); - if (obj) { - obj.clear(obj.value); - } -} - -// This is a function and not an arrow function, since the original is also a function -// eslint-disable-next-line no-shadow -global.setTimeout = function setTimeout(callback, delay, ...args) { - if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function'); - const obj = new Timeout(callback, args); - const cb = () => { - localReflectApply(callback, null, args); - }; - const tmr = host.setTimeout(cb, delay); - - const ref = { - __proto__: null, - clear: host.clearTimeout, - value: tmr - }; - - localReflectApply(localWeakMapSet, TIMERS, [obj, ref]); - return obj; -}; - -// eslint-disable-next-line no-shadow -global.setInterval = function setInterval(callback, interval, ...args) { - if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function'); - const obj = new Interval(); - const cb = () => { - localReflectApply(callback, null, args); - }; - const tmr = host.setInterval(cb, interval); - - const ref = { - __proto__: null, - clear: host.clearInterval, - value: tmr - }; - - localReflectApply(localWeakMapSet, TIMERS, [obj, ref]); - return obj; -}; - -// eslint-disable-next-line no-shadow -global.setImmediate = function setImmediate(callback, ...args) { - if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function'); - const obj = new Immediate(); - const cb = () => { - localReflectApply(callback, null, args); - }; - const tmr = host.setImmediate(cb); - - const ref = { - __proto__: null, - clear: host.clearImmediate, - value: tmr - }; - - localReflectApply(localWeakMapSet, TIMERS, [obj, ref]); - return obj; -}; - -// eslint-disable-next-line no-shadow -global.clearTimeout = function clearTimeout(timeout) { - clearTimer(timeout); -}; - -// eslint-disable-next-line no-shadow -global.clearInterval = function clearInterval(interval) { - clearTimer(interval); -}; - -// eslint-disable-next-line no-shadow -global.clearImmediate = function clearImmediate(immediate) { - clearTimer(immediate); -}; - -const localProcess = host.process; - -function vmEmitArgs(event, args) { - const allargs = [event]; - for (let i = 0; i < args.length; i++) { - if (!localReflectDefineProperty(allargs, i + 1, { - __proto__: null, - value: args[i], - writable: true, - enumerable: true, - configurable: true - })) throw new LocalError('Unexpected'); - } - return localReflectApply(vm.emit, vm, allargs); -} - -const LISTENERS = new LocalWeakMap(); -const LISTENER_HANDLER = new LocalWeakMap(); - -/** - * - * @param {*} name - * @param {*} handler - * @this process - * @return {this} - */ -function addListener(name, handler) { - if (name !== 'beforeExit' && name !== 'exit') { - throw new LocalError(`Access denied to listen for '${name}' event.`); - } - - let cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]); - if (!cb) { - cb = () => { - handler(); - }; - localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]); - localReflectApply(localWeakMapSet, LISTENERS, [handler, cb]); - } - - localProcess.on(name, cb); - - return this; -} - -/** - * - * @this process - * @return {this} - */ -// eslint-disable-next-line no-shadow -function process() { - return this; -} - -// FIXME wrong class structure -global.process = { - __proto__: process.prototype, - argv: optionArgv !== undefined ? optionArgv : [], - title: localProcess.title, - version: localProcess.version, - versions: localProcess.versions, - arch: localProcess.arch, - platform: localProcess.platform, - env: optionEnv !== undefined ? optionEnv : {}, - pid: localProcess.pid, - features: localProcess.features, - nextTick: function nextTick(callback, ...args) { - if (typeof callback !== 'function') { - throw new LocalError('Callback must be a function.'); - } - - localProcess.nextTick(()=>{ - localReflectApply(callback, null, args); - }); - }, - hrtime: function hrtime(time) { - return localProcess.hrtime(time); - }, - cwd: function cwd() { - return localProcess.cwd(); - }, - addListener, - on: addListener, - - once: function once(name, handler) { - if (name !== 'beforeExit' && name !== 'exit') { - throw new LocalError(`Access denied to listen for '${name}' event.`); - } - - let triggered = false; - const cb = () => { - if (triggered) return; - triggered = true; - localProcess.removeListener(name, cb); - handler(); - }; - localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]); - - localProcess.on(name, cb); - - return this; - }, - - listeners: function listeners(name) { - if (name !== 'beforeExit' && name !== 'exit') { - // Maybe add ({__proto__:null})[name] to throw when name fails in https://tc39.es/ecma262/#sec-topropertykey. - return []; - } - - // Filter out listeners, which were not created in this sandbox - const all = localProcess.listeners(name); - const filtered = []; - let j = 0; - for (let i = 0; i < all.length; i++) { - const h = localReflectApply(localWeakMapGet, LISTENER_HANDLER, [all[i]]); - if (h) { - if (!localReflectDefineProperty(filtered, j, { - __proto__: null, - value: h, - writable: true, - enumerable: true, - configurable: true - })) throw new LocalError('Unexpected'); - j++; - } - } - return filtered; - }, - - removeListener: function removeListener(name, handler) { - if (name !== 'beforeExit' && name !== 'exit') { - return this; - } - - const cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]); - if (cb) localProcess.removeListener(name, cb); - - return this; - }, - - umask: function umask() { - if (arguments.length) { - throw new LocalError('Access denied to set umask.'); - } - - return localProcess.umask(); - } -}; - -if (optionConsole === 'inherit') { - global.console = host.console; -} else if (optionConsole === 'redirect') { - global.console = { - debug(...args) { - vmEmitArgs('console.debug', args); - }, - log(...args) { - vmEmitArgs('console.log', args); - }, - info(...args) { - vmEmitArgs('console.info', args); - }, - warn(...args) { - vmEmitArgs('console.warn', args); - }, - error(...args) { - vmEmitArgs('console.error', args); - }, - dir(...args) { - vmEmitArgs('console.dir', args); - }, - time() {}, - timeEnd() {}, - trace(...args) { - vmEmitArgs('console.trace', args); - } - }; -} - -return { - __proto__: null, - Module, - jsonParse: JSON.parse, - createRequireForModule, - requireImpl -}; diff --git a/dist/setup-sandbox.js b/dist/setup-sandbox.js deleted file mode 100644 index 2149cc3..0000000 --- a/dist/setup-sandbox.js +++ /dev/null @@ -1,453 +0,0 @@ -/* global host, bridge, data, context */ - -'use strict'; - -const { - Object: localObject, - Array: localArray, - Error: LocalError, - Reflect: localReflect, - Proxy: LocalProxy, - WeakMap: LocalWeakMap, - Function: localFunction, - Promise: localPromise, - eval: localEval -} = global; - -const { - freeze: localObjectFreeze -} = localObject; - -const { - getPrototypeOf: localReflectGetPrototypeOf, - apply: localReflectApply, - deleteProperty: localReflectDeleteProperty, - has: localReflectHas, - defineProperty: localReflectDefineProperty, - setPrototypeOf: localReflectSetPrototypeOf, - getOwnPropertyDescriptor: localReflectGetOwnPropertyDescriptor -} = localReflect; - -const { - isArray: localArrayIsArray -} = localArray; - -const { - ensureThis, - ReadOnlyHandler, - from, - fromWithFactory, - readonlyFactory, - connect, - addProtoMapping, - VMError, - ReadOnlyMockHandler -} = bridge; - -const { - allowAsync, - GeneratorFunction, - AsyncFunction, - AsyncGeneratorFunction -} = data; - -const localWeakMapGet = LocalWeakMap.prototype.get; - -function localUnexpected() { - return new VMError('Should not happen'); -} - -// global is originally prototype of host.Object so it can be used to climb up from the sandbox. -if (!localReflectSetPrototypeOf(context, localObject.prototype)) throw localUnexpected(); - -Object.defineProperties(global, { - global: {value: global, writable: true, configurable: true, enumerable: true}, - globalThis: {value: global, writable: true, configurable: true}, - GLOBAL: {value: global, writable: true, configurable: true}, - root: {value: global, writable: true, configurable: true} -}); - -if (!localReflectDefineProperty(global, 'VMError', { - __proto__: null, - value: VMError, - writable: true, - enumerable: false, - configurable: true -})) throw localUnexpected(); - -// Fixes buffer unsafe allocation -/* eslint-disable no-use-before-define */ -class BufferHandler extends ReadOnlyHandler { - - apply(target, thiz, args) { - if (args.length > 0 && typeof args[0] === 'number') { - return LocalBuffer.alloc(args[0]); - } - return localReflectApply(LocalBuffer.from, LocalBuffer, args); - } - - construct(target, args, newTarget) { - if (args.length > 0 && typeof args[0] === 'number') { - return LocalBuffer.alloc(args[0]); - } - return localReflectApply(LocalBuffer.from, LocalBuffer, args); - } - -} -/* eslint-enable no-use-before-define */ - -const LocalBuffer = fromWithFactory(obj => new BufferHandler(obj), host.Buffer); - - -if (!localReflectDefineProperty(global, 'Buffer', { - __proto__: null, - value: LocalBuffer, - writable: true, - enumerable: false, - configurable: true -})) throw localUnexpected(); - -addProtoMapping(LocalBuffer.prototype, host.Buffer.prototype, 'Uint8Array'); - -/** - * - * @param {*} size Size of new buffer - * @this LocalBuffer - * @return {LocalBuffer} - */ -function allocUnsafe(size) { - return LocalBuffer.alloc(size); -} - -connect(allocUnsafe, host.Buffer.allocUnsafe); - -/** - * - * @param {*} size Size of new buffer - * @this LocalBuffer - * @return {LocalBuffer} - */ -function allocUnsafeSlow(size) { - return LocalBuffer.alloc(size); -} - -connect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow); - -/** - * Replacement for Buffer inspect - * - * @param {*} recurseTimes - * @param {*} ctx - * @this LocalBuffer - * @return {string} - */ -function inspect(recurseTimes, ctx) { - // Mimic old behavior, could throw but didn't pass a test. - const max = host.INSPECT_MAX_BYTES; - const actualMax = Math.min(max, this.length); - const remaining = this.length - max; - let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim(); - if (remaining > 0) str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`; - return `<${this.constructor.name} ${str}>`; -} - -connect(inspect, host.Buffer.prototype.inspect); - -connect(localFunction.prototype.bind, host.Function.prototype.bind); - -connect(localObject.prototype.__defineGetter__, host.Object.prototype.__defineGetter__); -connect(localObject.prototype.__defineSetter__, host.Object.prototype.__defineSetter__); -connect(localObject.prototype.__lookupGetter__, host.Object.prototype.__lookupGetter__); -connect(localObject.prototype.__lookupSetter__, host.Object.prototype.__lookupSetter__); - -/* - * PrepareStackTrace sanitization - */ - -const oldPrepareStackTraceDesc = localReflectGetOwnPropertyDescriptor(LocalError, 'prepareStackTrace'); - -let currentPrepareStackTrace = LocalError.prepareStackTrace; -const wrappedPrepareStackTrace = new LocalWeakMap(); -if (typeof currentPrepareStackTrace === 'function') { - wrappedPrepareStackTrace.set(currentPrepareStackTrace, currentPrepareStackTrace); -} - -let OriginalCallSite; -LocalError.prepareStackTrace = (e, sst) => { - OriginalCallSite = sst[0].constructor; -}; -new LocalError().stack; -if (typeof OriginalCallSite === 'function') { - LocalError.prepareStackTrace = undefined; - - function makeCallSiteGetters(list) { - const callSiteGetters = []; - for (let i=0; i { - return localReflectApply(func, thiz, []); - } - }; - } - return callSiteGetters; - } - - function applyCallSiteGetters(thiz, callSite, getters) { - for (let i=0; i { - if (localArrayIsArray(sst)) { - for (let i=0; i < sst.length; i++) { - const cs = sst[i]; - if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) { - sst[i] = new CallSite(cs); - } - } - } - return value(error, sst); - }; - wrappedPrepareStackTrace.set(value, newWrapped); - wrappedPrepareStackTrace.set(newWrapped, newWrapped); - currentPrepareStackTrace = newWrapped; - } - })) throw localUnexpected(); -} else if (oldPrepareStackTraceDesc) { - localReflectDefineProperty(LocalError, 'prepareStackTrace', oldPrepareStackTraceDesc); -} else { - localReflectDeleteProperty(LocalError, 'prepareStackTrace'); -} - -/* - * Exception sanitization - */ - -const withProxy = localObjectFreeze({ - __proto__: null, - has(target, key) { - if (key === host.INTERNAL_STATE_NAME) return false; - return localReflectHas(target, key); - } -}); - -const interanState = localObjectFreeze({ - __proto__: null, - wrapWith(x) { - if (x === null || x === undefined) return x; - return new LocalProxy(localObject(x), withProxy); - }, - handleException: ensureThis, - import(what) { - throw new VMError('Dynamic Import not supported'); - } -}); - -if (!localReflectDefineProperty(global, host.INTERNAL_STATE_NAME, { - __proto__: null, - configurable: false, - enumerable: false, - writable: false, - value: interanState -})) throw localUnexpected(); - -/* - * Eval sanitization - */ - -function throwAsync() { - return new VMError('Async not available'); -} - -function makeFunction(inputArgs, isAsync, isGenerator) { - const lastArgs = inputArgs.length - 1; - let code = lastArgs >= 0 ? `${inputArgs[lastArgs]}` : ''; - let args = lastArgs > 0 ? `${inputArgs[0]}` : ''; - for (let i = 1; i < lastArgs; i++) { - args += `,${inputArgs[i]}`; - } - try { - code = host.transformAndCheck(args, code, isAsync, isGenerator, allowAsync); - } catch (e) { - throw bridge.from(e); - } - return localEval(code); -} - -const FunctionHandler = { - __proto__: null, - apply(target, thiz, args) { - return makeFunction(args, this.isAsync, this.isGenerator); - }, - construct(target, args, newTarget) { - return makeFunction(args, this.isAsync, this.isGenerator); - } -}; - -const EvalHandler = { - __proto__: null, - apply(target, thiz, args) { - if (args.length === 0) return undefined; - let code = `${args[0]}`; - try { - code = host.transformAndCheck(null, code, false, false, allowAsync); - } catch (e) { - throw bridge.from(e); - } - return localEval(code); - } -}; - -const AsyncErrorHandler = { - __proto__: null, - apply(target, thiz, args) { - throw throwAsync(); - }, - construct(target, args, newTarget) { - throw throwAsync(); - } -}; - -function makeCheckFunction(isAsync, isGenerator) { - if (isAsync && !allowAsync) return AsyncErrorHandler; - return { - __proto__: FunctionHandler, - isAsync, - isGenerator - }; -} - -function overrideWithProxy(obj, prop, value, handler) { - const proxy = new LocalProxy(value, handler); - if (!localReflectDefineProperty(obj, prop, {__proto__: null, value: proxy})) throw localUnexpected(); - return proxy; -} - -const proxiedFunction = overrideWithProxy(localFunction.prototype, 'constructor', localFunction, makeCheckFunction(false, false)); -if (GeneratorFunction) { - if (!localReflectSetPrototypeOf(GeneratorFunction, proxiedFunction)) throw localUnexpected(); - overrideWithProxy(GeneratorFunction.prototype, 'constructor', GeneratorFunction, makeCheckFunction(false, true)); -} -if (AsyncFunction) { - if (!localReflectSetPrototypeOf(AsyncFunction, proxiedFunction)) throw localUnexpected(); - overrideWithProxy(AsyncFunction.prototype, 'constructor', AsyncFunction, makeCheckFunction(true, false)); -} -if (AsyncGeneratorFunction) { - if (!localReflectSetPrototypeOf(AsyncGeneratorFunction, proxiedFunction)) throw localUnexpected(); - overrideWithProxy(AsyncGeneratorFunction.prototype, 'constructor', AsyncGeneratorFunction, makeCheckFunction(true, true)); -} - -global.Function = proxiedFunction; -global.eval = new LocalProxy(localEval, EvalHandler); - -/* - * Promise sanitization - */ - -if (localPromise && !allowAsync) { - - const PromisePrototype = localPromise.prototype; - - overrideWithProxy(PromisePrototype, 'then', PromisePrototype.then, AsyncErrorHandler); - // This seems not to work, and will produce - // UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object]. - // This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object. - // Contextify.connect(host.Promise.prototype.then, Promise.prototype.then); - - if (PromisePrototype.finally) { - overrideWithProxy(PromisePrototype, 'finally', PromisePrototype.finally, AsyncErrorHandler); - // Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally); - } - if (Promise.prototype.catch) { - overrideWithProxy(PromisePrototype, 'catch', PromisePrototype.catch, AsyncErrorHandler); - // Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch); - } - -} - -function readonly(other, mock) { - // Note: other@other(unsafe) mock@other(unsafe) returns@this(unsafe) throws@this(unsafe) - if (!mock) return fromWithFactory(readonlyFactory, other); - const tmock = from(mock); - return fromWithFactory(obj=>new ReadOnlyMockHandler(obj, tmock), other); -} - -return { - __proto__: null, - readonly, - global -};