diff --git a/packages/sandbox/src/constant.ts b/packages/sandbox/src/constant.ts new file mode 100644 index 00000000..26df7344 --- /dev/null +++ b/packages/sandbox/src/constant.ts @@ -0,0 +1,68 @@ + +export const globalsInES2015 = window.Proxy + ? [ + 'Array', + 'ArrayBuffer', + 'Boolean', + 'constructor', + 'DataView', + 'Date', + 'decodeURI', + 'decodeURIComponent', + 'encodeURI', + 'encodeURIComponent', + 'Error', + 'escape', + 'eval', + 'EvalError', + 'Float32Array', + 'Float64Array', + 'Function', + 'hasOwnProperty', + 'Infinity', + 'Int16Array', + 'Int32Array', + 'Int8Array', + 'isFinite', + 'isNaN', + 'isPrototypeOf', + 'JSON', + 'Map', + 'Math', + 'NaN', + 'Number', + 'Object', + 'parseFloat', + 'parseInt', + 'Promise', + 'propertyIsEnumerable', + 'Proxy', + 'RangeError', + 'ReferenceError', + 'Reflect', + 'RegExp', + 'Set', + 'String', + 'Symbol', + 'SyntaxError', + 'toLocaleString', + 'toString', + 'TypeError', + 'Uint16Array', + 'Uint32Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'undefined', + 'unescape', + 'URIError', + 'valueOf', + 'WeakMap', + 'WeakSet', + ].filter((p) => /* just keep the available properties in current window context */ p in window) + : []; + const overwrittenGlobals = ['window', 'self', 'hasOwnProperty'] + export const cachedGlobals = Array.from( + new Set( + globalsInES2015.concat(overwrittenGlobals).concat('requestAnimationFrame') + ), + ); \ No newline at end of file diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index b91cf98e..3f54570c 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -1,3 +1,4 @@ +import { cachedGlobals } from './constant'; export interface SandboxProps { multiMode?: boolean; } @@ -99,7 +100,7 @@ export default class Sandbox { if (!originalWindow.hasOwnProperty(p)) { // record value added in sandbox propertyAdded[p] = value; - // eslint-disable-next-line no-prototype-builtins + // eslint-disable-next-line no-prototype-builtins } else if (!originalValues.hasOwnProperty(p)) { // if it is already been setted in original window, record it's original value originalValues[p] = originalWindow[p]; @@ -191,6 +192,9 @@ export default class Sandbox { this.createProxySandbox(); } try { + // Concatenate scopedGlobalVariables into variable declarations to cache global variables, avoiding proxy traversal on every use. + const scopedGlobalVariableDefinition = cachedGlobals.length ? `const {${cachedGlobals.join(',')}}=sandbox;` : ''; + script = scopedGlobalVariableDefinition + script; const execScript = `with (sandbox) {;${script}\n}`; // eslint-disable-next-line no-new-func const code = new Function('sandbox', execScript).bind(this.sandbox);