From 743473ae518ca46c04486ce36aca64aaadbbcbc1 Mon Sep 17 00:00:00 2001 From: Kuitos Date: Sun, 30 Oct 2022 19:37:58 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20enable=20speedy=20sandbox=20mode=20?= =?UTF-8?q?by=20default=20(#2320)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .fatherrc.js | 5 +- src/interfaces.ts | 3 + src/loader.ts | 7 +- src/sandbox/common.ts | 7 +- src/sandbox/globals.ts | 132 +++++++++---------- src/sandbox/patchers/dynamicAppend/common.ts | 4 +- src/sandbox/proxySandbox.ts | 9 +- 7 files changed, 82 insertions(+), 85 deletions(-) diff --git a/.fatherrc.js b/.fatherrc.js index d9663d3..970f613 100644 --- a/.fatherrc.js +++ b/.fatherrc.js @@ -11,8 +11,9 @@ writeFileSync(versionFilePath, `export const version = '${version}';`); const globalsFilePath = join(__dirname, './src/sandbox/globals.ts'); writeFileSync( globalsFilePath, - `// generated from https://github.com/sindresorhus/globals/blob/main/globals.json builtin part -export const globals = ${JSON.stringify(Object.keys(globals.builtin), null, 2)};`, + `// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part +// only init its values while Proxy is supported +export const globals = window.Proxy ? ${JSON.stringify(Object.keys(globals.es2015), null, 2)} : [];`, ); export default { diff --git a/src/interfaces.ts b/src/interfaces.ts index 8a14e50..a49afdf 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -75,6 +75,9 @@ type QiankunSpecialOpts = { * @deprecated We use strict mode by default */ loose?: boolean; + /** + * use speed sandbox mode, enabled by default from 2.9.0 + */ speedy?: boolean; patchers?: Patcher[]; }; diff --git a/src/loader.ts b/src/loader.ts index e940d16..6172ceb 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -18,7 +18,7 @@ import type { ObjectType, } from './interfaces'; import { createSandboxContainer, css } from './sandbox'; -import { lexicalGlobals } from './sandbox/common'; +import { trustedGlobals } from './sandbox/common'; import { Deferred, genAppInstanceIdByName, @@ -311,7 +311,8 @@ export async function loadApp( let mountSandbox = () => Promise.resolve(); let unmountSandbox = () => Promise.resolve(); const useLooseSandbox = typeof sandbox === 'object' && !!sandbox.loose; - const speedySandbox = typeof sandbox === 'object' && !!sandbox.speedy; + // enable speedy mode by default + const speedySandbox = typeof sandbox === 'object' ? sandbox.speedy !== false : true; let sandboxContainer; if (sandbox) { sandboxContainer = createSandboxContainer( @@ -342,7 +343,7 @@ export async function loadApp( // get the lifecycle hooks from module exports const scriptExports: any = await execScripts(global, sandbox && !useLooseSandbox, { - scopedGlobalVariables: speedySandbox ? lexicalGlobals : [], + scopedGlobalVariables: speedySandbox ? trustedGlobals : [], }); const { bootstrap, mount, unmount, update } = getLifecyclesFromExports( scriptExports, diff --git a/src/sandbox/common.ts b/src/sandbox/common.ts index 1e29e67..063217f 100644 --- a/src/sandbox/common.ts +++ b/src/sandbox/common.ts @@ -18,13 +18,12 @@ export function getCurrentRunningApp() { } export function setCurrentRunningApp(appInstance: { name: string; window: WindowProxy } | null) { - // set currentRunningApp and it's proxySandbox to global window, as its only use case is for document.createElement from now on, which hijacked by a global way + // Set currentRunningApp and it's proxySandbox to global window, as its only use case is for document.createElement from now on, which hijacked by a global way currentRunningApp = appInstance; } -const scopedGlobals = ['window', 'self', 'globalThis', 'top', 'parent', 'hasOwnProperty', 'document', 'eval']; -export const unscopedGlobals = [...without(globals, ...scopedGlobals), 'requestAnimationFrame']; -export const lexicalGlobals = [...unscopedGlobals, ...scopedGlobals]; +const spiedGlobals = ['window', 'self', 'globalThis', 'top', 'parent', 'hasOwnProperty', 'document', 'eval']; +export const trustedGlobals = [...without(globals, ...spiedGlobals), 'requestAnimationFrame']; const functionBoundedValueMap = new WeakMap(); diff --git a/src/sandbox/globals.ts b/src/sandbox/globals.ts index 0ed743c..57681a2 100644 --- a/src/sandbox/globals.ts +++ b/src/sandbox/globals.ts @@ -1,69 +1,63 @@ -// generated from https://github.com/sindresorhus/globals/blob/main/globals.json builtin part -export const globals = [ - 'AggregateError', - 'Array', - 'ArrayBuffer', - 'Atomics', - 'BigInt', - 'BigInt64Array', - 'BigUint64Array', - 'Boolean', - 'constructor', - 'DataView', - 'Date', - 'decodeURI', - 'decodeURIComponent', - 'encodeURI', - 'encodeURIComponent', - 'Error', - 'escape', - 'eval', - 'EvalError', - 'FinalizationRegistry', - 'Float32Array', - 'Float64Array', - 'Function', - 'globalThis', - 'hasOwnProperty', - 'Infinity', - 'Int16Array', - 'Int32Array', - 'Int8Array', - 'isFinite', - 'isNaN', - 'isPrototypeOf', - 'JSON', - 'Map', - 'Math', - 'NaN', - 'Number', - 'Object', - 'parseFloat', - 'parseInt', - 'Promise', - 'propertyIsEnumerable', - 'Proxy', - 'RangeError', - 'ReferenceError', - 'Reflect', - 'RegExp', - 'Set', - 'SharedArrayBuffer', - 'String', - 'Symbol', - 'SyntaxError', - 'toLocaleString', - 'toString', - 'TypeError', - 'Uint16Array', - 'Uint32Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'undefined', - 'unescape', - 'URIError', - 'valueOf', - 'WeakMap', - 'WeakRef', - 'WeakSet', -]; +// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part +// only init its values while Proxy is supported +export const globals = 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', + ] + : []; diff --git a/src/sandbox/patchers/dynamicAppend/common.ts b/src/sandbox/patchers/dynamicAppend/common.ts index af5085d..cfc3096 100644 --- a/src/sandbox/patchers/dynamicAppend/common.ts +++ b/src/sandbox/patchers/dynamicAppend/common.ts @@ -6,7 +6,7 @@ import { execScripts } from 'import-html-entry'; import { isFunction } from 'lodash'; import { frameworkConfiguration } from '../../../apis'; import { qiankunHeadTagName } from '../../../utils'; -import { lexicalGlobals } from '../../common'; +import { trustedGlobals } from '../../common'; import * as css from '../css'; export const rawHeadAppendChild = HTMLHeadElement.prototype.appendChild; @@ -280,7 +280,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: { const { fetch } = frameworkConfiguration; const referenceNode = mountDOM.contains(refChild) ? refChild : null; - const scopedGlobalVariables = speedySandbox ? lexicalGlobals : []; + const scopedGlobalVariables = speedySandbox ? trustedGlobals : []; if (src) { execScripts(null, [src], proxy, { diff --git a/src/sandbox/proxySandbox.ts b/src/sandbox/proxySandbox.ts index 9d5a9a3..23f263e 100644 --- a/src/sandbox/proxySandbox.ts +++ b/src/sandbox/proxySandbox.ts @@ -6,7 +6,7 @@ import type { SandBox } from '../interfaces'; import { SandBoxType } from '../interfaces'; import { isPropertyFrozen, nativeGlobal, nextTask } from '../utils'; -import { getCurrentRunningApp, getTargetValue, setCurrentRunningApp, unscopedGlobals } from './common'; +import { getCurrentRunningApp, getTargetValue, trustedGlobals, setCurrentRunningApp } from './common'; type SymbolTarget = 'target' | 'globalContext'; @@ -49,7 +49,7 @@ const globalVariableWhiteList: string[] = [ variables who are impossible to be overwritten need to be escaped from proxy sandbox for performance reasons see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/unscopables */ -const unscopables = unscopedGlobals.reduce((acc, key) => ({ ...acc, [key]: true }), { __proto__: null }); +const unscopables = trustedGlobals.reduce((acc, key) => ({ ...acc, [key]: true }), { __proto__: null }); const useNativeWindowForBindingsProps = new Map([ ['fetch', true], @@ -132,9 +132,6 @@ export default class ProxySandbox implements SandBox { sandboxRunning = true; latestSetProp: PropertyKey | null = null; - // the descriptor of global variables in whitelist before it been modified - globalWhitelistPrevDescriptor: { [p in typeof globalVariableWhiteList[number]]: PropertyDescriptor | undefined } = {}; - active() { if (!this.sandboxRunning) activeSandboxCount++; this.sandboxRunning = true; @@ -163,6 +160,8 @@ export default class ProxySandbox implements SandBox { this.sandboxRunning = false; } + // the descriptor of global variables in whitelist before it been modified + globalWhitelistPrevDescriptor: { [p in typeof globalVariableWhiteList[number]]: PropertyDescriptor | undefined } = {}; globalContext: typeof window; constructor(name: string, globalContext = window) {