You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					458 lines
				
				12 KiB
			
		
		
			
		
	
	
					458 lines
				
				12 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/* 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 {
							 | 
						||
| 
								 | 
							
									get: localWeakMapGet,
							 | 
						||
| 
								 | 
							
									set: localWeakMapSet
							 | 
						||
| 
								 | 
							
								} = LocalWeakMap.prototype;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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},
							 | 
						||
| 
								 | 
							
									Error: {value: LocalError}
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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<list.length; i++) {
							 | 
						||
| 
								 | 
							
											const name = list[i];
							 | 
						||
| 
								 | 
							
											const func = OriginalCallSite.prototype[name];
							 | 
						||
| 
								 | 
							
											callSiteGetters[i] = {__proto__: null,
							 | 
						||
| 
								 | 
							
												name,
							 | 
						||
| 
								 | 
							
												propName: '_' + name,
							 | 
						||
| 
								 | 
							
												func: (thiz) => {
							 | 
						||
| 
								 | 
							
													return localReflectApply(func, thiz, []);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return callSiteGetters;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function applyCallSiteGetters(thiz, callSite, getters) {
							 | 
						||
| 
								 | 
							
										for (let i=0; i<getters.length; i++) {
							 | 
						||
| 
								 | 
							
											const getter = getters[i];
							 | 
						||
| 
								 | 
							
											localReflectDefineProperty(thiz, getter.propName, {
							 | 
						||
| 
								 | 
							
												__proto__: null,
							 | 
						||
| 
								 | 
							
												value: getter.func(callSite)
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const callSiteGetters = makeCallSiteGetters([
							 | 
						||
| 
								 | 
							
										'getTypeName',
							 | 
						||
| 
								 | 
							
										'getFunctionName',
							 | 
						||
| 
								 | 
							
										'getMethodName',
							 | 
						||
| 
								 | 
							
										'getFileName',
							 | 
						||
| 
								 | 
							
										'getLineNumber',
							 | 
						||
| 
								 | 
							
										'getColumnNumber',
							 | 
						||
| 
								 | 
							
										'getEvalOrigin',
							 | 
						||
| 
								 | 
							
										'isToplevel',
							 | 
						||
| 
								 | 
							
										'isEval',
							 | 
						||
| 
								 | 
							
										'isNative',
							 | 
						||
| 
								 | 
							
										'isConstructor',
							 | 
						||
| 
								 | 
							
										'isAsync',
							 | 
						||
| 
								 | 
							
										'isPromiseAll',
							 | 
						||
| 
								 | 
							
										'getPromiseIndex'
							 | 
						||
| 
								 | 
							
									]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									class CallSite {
							 | 
						||
| 
								 | 
							
										constructor(callSite) {
							 | 
						||
| 
								 | 
							
											applyCallSiteGetters(this, callSite, callSiteGetters);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										getThis() {
							 | 
						||
| 
								 | 
							
											return undefined;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										getFunction() {
							 | 
						||
| 
								 | 
							
											return undefined;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										toString() {
							 | 
						||
| 
								 | 
							
											return 'CallSite {}';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (let i=0; i<callSiteGetters.length; i++) {
							 | 
						||
| 
								 | 
							
										const name = callSiteGetters[i].name;
							 | 
						||
| 
								 | 
							
										const funcProp = localReflectGetOwnPropertyDescriptor(OriginalCallSite.prototype, name);
							 | 
						||
| 
								 | 
							
										if (!funcProp) continue;
							 | 
						||
| 
								 | 
							
										const propertyName = callSiteGetters[i].propName;
							 | 
						||
| 
								 | 
							
										const func = {func() {
							 | 
						||
| 
								 | 
							
											return this[propertyName];
							 | 
						||
| 
								 | 
							
										}}.func;
							 | 
						||
| 
								 | 
							
										const nameProp = localReflectGetOwnPropertyDescriptor(func, 'name');
							 | 
						||
| 
								 | 
							
										if (!nameProp) throw localUnexpected();
							 | 
						||
| 
								 | 
							
										nameProp.value = name;
							 | 
						||
| 
								 | 
							
										if (!localReflectDefineProperty(func, 'name', nameProp)) throw localUnexpected();
							 | 
						||
| 
								 | 
							
										funcProp.value = func;
							 | 
						||
| 
								 | 
							
										if (!localReflectDefineProperty(CallSite.prototype, name, funcProp)) throw localUnexpected();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!localReflectDefineProperty(LocalError, 'prepareStackTrace', {
							 | 
						||
| 
								 | 
							
										configurable: false,
							 | 
						||
| 
								 | 
							
										enumerable: false,
							 | 
						||
| 
								 | 
							
										get() {
							 | 
						||
| 
								 | 
							
											return currentPrepareStackTrace;
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										set(value) {
							 | 
						||
| 
								 | 
							
											if (typeof(value) !== 'function') {
							 | 
						||
| 
								 | 
							
												currentPrepareStackTrace = value;
							 | 
						||
| 
								 | 
							
												return;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											const wrapped = localReflectApply(localWeakMapGet, wrappedPrepareStackTrace, [value]);
							 | 
						||
| 
								 | 
							
											if (wrapped) {
							 | 
						||
| 
								 | 
							
												currentPrepareStackTrace = wrapped;
							 | 
						||
| 
								 | 
							
												return;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											const newWrapped = (error, sst) => {
							 | 
						||
| 
								 | 
							
												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);
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [value, newWrapped]);
							 | 
						||
| 
								 | 
							
											localReflectApply(localWeakMapSet, wrappedPrepareStackTrace, [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
							 | 
						||
| 
								 | 
							
								};
							 |