enable speedy sandbox mode by default (#2320)

This commit is contained in:
Kuitos 2022-10-30 19:37:58 +08:00 committed by GitHub
parent 6544b17f9b
commit 743473ae51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 85 deletions

View File

@ -11,8 +11,9 @@ writeFileSync(versionFilePath, `export const version = '${version}';`);
const globalsFilePath = join(__dirname, './src/sandbox/globals.ts'); const globalsFilePath = join(__dirname, './src/sandbox/globals.ts');
writeFileSync( writeFileSync(
globalsFilePath, globalsFilePath,
`// generated from https://github.com/sindresorhus/globals/blob/main/globals.json builtin part `// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part
export const globals = ${JSON.stringify(Object.keys(globals.builtin), null, 2)};`, // only init its values while Proxy is supported
export const globals = window.Proxy ? ${JSON.stringify(Object.keys(globals.es2015), null, 2)} : [];`,
); );
export default { export default {

View File

@ -75,6 +75,9 @@ type QiankunSpecialOpts = {
* @deprecated We use strict mode by default * @deprecated We use strict mode by default
*/ */
loose?: boolean; loose?: boolean;
/**
* use speed sandbox mode, enabled by default from 2.9.0
*/
speedy?: boolean; speedy?: boolean;
patchers?: Patcher[]; patchers?: Patcher[];
}; };

View File

@ -18,7 +18,7 @@ import type {
ObjectType, ObjectType,
} from './interfaces'; } from './interfaces';
import { createSandboxContainer, css } from './sandbox'; import { createSandboxContainer, css } from './sandbox';
import { lexicalGlobals } from './sandbox/common'; import { trustedGlobals } from './sandbox/common';
import { import {
Deferred, Deferred,
genAppInstanceIdByName, genAppInstanceIdByName,
@ -311,7 +311,8 @@ export async function loadApp<T extends ObjectType>(
let mountSandbox = () => Promise.resolve(); let mountSandbox = () => Promise.resolve();
let unmountSandbox = () => Promise.resolve(); let unmountSandbox = () => Promise.resolve();
const useLooseSandbox = typeof sandbox === 'object' && !!sandbox.loose; 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; let sandboxContainer;
if (sandbox) { if (sandbox) {
sandboxContainer = createSandboxContainer( sandboxContainer = createSandboxContainer(
@ -342,7 +343,7 @@ export async function loadApp<T extends ObjectType>(
// get the lifecycle hooks from module exports // get the lifecycle hooks from module exports
const scriptExports: any = await execScripts(global, sandbox && !useLooseSandbox, { const scriptExports: any = await execScripts(global, sandbox && !useLooseSandbox, {
scopedGlobalVariables: speedySandbox ? lexicalGlobals : [], scopedGlobalVariables: speedySandbox ? trustedGlobals : [],
}); });
const { bootstrap, mount, unmount, update } = getLifecyclesFromExports( const { bootstrap, mount, unmount, update } = getLifecyclesFromExports(
scriptExports, scriptExports,

View File

@ -18,13 +18,12 @@ export function getCurrentRunningApp() {
} }
export function setCurrentRunningApp(appInstance: { name: string; window: WindowProxy } | null) { 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; currentRunningApp = appInstance;
} }
const scopedGlobals = ['window', 'self', 'globalThis', 'top', 'parent', 'hasOwnProperty', 'document', 'eval']; const spiedGlobals = ['window', 'self', 'globalThis', 'top', 'parent', 'hasOwnProperty', 'document', 'eval'];
export const unscopedGlobals = [...without(globals, ...scopedGlobals), 'requestAnimationFrame']; export const trustedGlobals = [...without(globals, ...spiedGlobals), 'requestAnimationFrame'];
export const lexicalGlobals = [...unscopedGlobals, ...scopedGlobals];
const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>(); const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>();

View File

@ -1,12 +1,9 @@
// generated from https://github.com/sindresorhus/globals/blob/main/globals.json builtin part // generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part
export const globals = [ // only init its values while Proxy is supported
'AggregateError', export const globals = window.Proxy
? [
'Array', 'Array',
'ArrayBuffer', 'ArrayBuffer',
'Atomics',
'BigInt',
'BigInt64Array',
'BigUint64Array',
'Boolean', 'Boolean',
'constructor', 'constructor',
'DataView', 'DataView',
@ -19,11 +16,9 @@ export const globals = [
'escape', 'escape',
'eval', 'eval',
'EvalError', 'EvalError',
'FinalizationRegistry',
'Float32Array', 'Float32Array',
'Float64Array', 'Float64Array',
'Function', 'Function',
'globalThis',
'hasOwnProperty', 'hasOwnProperty',
'Infinity', 'Infinity',
'Int16Array', 'Int16Array',
@ -48,7 +43,6 @@ export const globals = [
'Reflect', 'Reflect',
'RegExp', 'RegExp',
'Set', 'Set',
'SharedArrayBuffer',
'String', 'String',
'Symbol', 'Symbol',
'SyntaxError', 'SyntaxError',
@ -64,6 +58,6 @@ export const globals = [
'URIError', 'URIError',
'valueOf', 'valueOf',
'WeakMap', 'WeakMap',
'WeakRef',
'WeakSet', 'WeakSet',
]; ]
: [];

View File

@ -6,7 +6,7 @@ import { execScripts } from 'import-html-entry';
import { isFunction } from 'lodash'; import { isFunction } from 'lodash';
import { frameworkConfiguration } from '../../../apis'; import { frameworkConfiguration } from '../../../apis';
import { qiankunHeadTagName } from '../../../utils'; import { qiankunHeadTagName } from '../../../utils';
import { lexicalGlobals } from '../../common'; import { trustedGlobals } from '../../common';
import * as css from '../css'; import * as css from '../css';
export const rawHeadAppendChild = HTMLHeadElement.prototype.appendChild; export const rawHeadAppendChild = HTMLHeadElement.prototype.appendChild;
@ -280,7 +280,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: {
const { fetch } = frameworkConfiguration; const { fetch } = frameworkConfiguration;
const referenceNode = mountDOM.contains(refChild) ? refChild : null; const referenceNode = mountDOM.contains(refChild) ? refChild : null;
const scopedGlobalVariables = speedySandbox ? lexicalGlobals : []; const scopedGlobalVariables = speedySandbox ? trustedGlobals : [];
if (src) { if (src) {
execScripts(null, [src], proxy, { execScripts(null, [src], proxy, {

View File

@ -6,7 +6,7 @@
import type { SandBox } from '../interfaces'; import type { SandBox } from '../interfaces';
import { SandBoxType } from '../interfaces'; import { SandBoxType } from '../interfaces';
import { isPropertyFrozen, nativeGlobal, nextTask } from '../utils'; import { isPropertyFrozen, nativeGlobal, nextTask } from '../utils';
import { getCurrentRunningApp, getTargetValue, setCurrentRunningApp, unscopedGlobals } from './common'; import { getCurrentRunningApp, getTargetValue, trustedGlobals, setCurrentRunningApp } from './common';
type SymbolTarget = 'target' | 'globalContext'; 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 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 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<PropertyKey, boolean>([ const useNativeWindowForBindingsProps = new Map<PropertyKey, boolean>([
['fetch', true], ['fetch', true],
@ -132,9 +132,6 @@ export default class ProxySandbox implements SandBox {
sandboxRunning = true; sandboxRunning = true;
latestSetProp: PropertyKey | null = null; latestSetProp: PropertyKey | null = null;
// the descriptor of global variables in whitelist before it been modified
globalWhitelistPrevDescriptor: { [p in typeof globalVariableWhiteList[number]]: PropertyDescriptor | undefined } = {};
active() { active() {
if (!this.sandboxRunning) activeSandboxCount++; if (!this.sandboxRunning) activeSandboxCount++;
this.sandboxRunning = true; this.sandboxRunning = true;
@ -163,6 +160,8 @@ export default class ProxySandbox implements SandBox {
this.sandboxRunning = false; 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; globalContext: typeof window;
constructor(name: string, globalContext = window) { constructor(name: string, globalContext = window) {