🐛not rebind non-native global properties (#2733)
This commit is contained in:
parent
aa4a75c5a6
commit
3524195989
|
|
@ -13,11 +13,14 @@ writeFileSync(
|
||||||
globalsFilePath,
|
globalsFilePath,
|
||||||
`// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part
|
`// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part
|
||||||
// only init its values while Proxy is supported
|
// only init its values while Proxy is supported
|
||||||
export const globals = window.Proxy ? ${JSON.stringify(
|
export const globalsInES2015 = window.Proxy ? ${JSON.stringify(
|
||||||
Object.keys(globals.es2015),
|
Object.keys(globals.es2015),
|
||||||
null,
|
null,
|
||||||
2,
|
2,
|
||||||
)}.filter(p => /* just keep the available properties in current window context */ p in window) : [];`,
|
)}.filter(p => /* just keep the available properties in current window context */ p in window) : [];
|
||||||
|
|
||||||
|
export const globalsInBrowser = ${JSON.stringify(Object.keys(globals.browser), null, 2)};
|
||||||
|
`,
|
||||||
);
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,17 @@
|
||||||
* @since 2021-04-12
|
* @since 2021-04-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getTargetValue } from '../common';
|
import { rebindTarget2Fn } from '../common';
|
||||||
|
|
||||||
describe('getTargetValue', () => {
|
describe('getTargetValue', () => {
|
||||||
it('should work well', () => {
|
it('should work well', () => {
|
||||||
const a1 = getTargetValue(window, undefined);
|
const a1 = rebindTarget2Fn(window, undefined);
|
||||||
expect(a1).toEqual(undefined);
|
expect(a1).toEqual(undefined);
|
||||||
|
|
||||||
const a2 = getTargetValue(window, null);
|
const a2 = rebindTarget2Fn(window, null);
|
||||||
expect(a2).toEqual(null);
|
expect(a2).toEqual(null);
|
||||||
|
|
||||||
const a3 = getTargetValue(window, function bindThis(this: any) {
|
const a3 = rebindTarget2Fn(window, function bindThis(this: any) {
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
const a3returns = a3();
|
const a3returns = a3();
|
||||||
|
|
@ -24,7 +24,7 @@ describe('getTargetValue', () => {
|
||||||
function prototypeAddedAfterFirstInvocation(this: any, field: string) {
|
function prototypeAddedAfterFirstInvocation(this: any, field: string) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
const notConstructableFunction = getTargetValue(window, prototypeAddedAfterFirstInvocation);
|
const notConstructableFunction = rebindTarget2Fn(window, prototypeAddedAfterFirstInvocation);
|
||||||
// `this` of not constructable function will be bound automatically, and it can not be changed by calling with special `this`
|
// `this` of not constructable function will be bound automatically, and it can not be changed by calling with special `this`
|
||||||
const result = {};
|
const result = {};
|
||||||
notConstructableFunction.call(result, '123');
|
notConstructableFunction.call(result, '123');
|
||||||
|
|
@ -32,7 +32,7 @@ describe('getTargetValue', () => {
|
||||||
expect(window.field).toEqual('123');
|
expect(window.field).toEqual('123');
|
||||||
|
|
||||||
prototypeAddedAfterFirstInvocation.prototype.addedFn = () => {};
|
prototypeAddedAfterFirstInvocation.prototype.addedFn = () => {};
|
||||||
const constructableFunction = getTargetValue(window, prototypeAddedAfterFirstInvocation);
|
const constructableFunction = rebindTarget2Fn(window, prototypeAddedAfterFirstInvocation);
|
||||||
// `this` coule be available if it be predicated as a constructable function
|
// `this` coule be available if it be predicated as a constructable function
|
||||||
const result2 = {};
|
const result2 = {};
|
||||||
constructableFunction.call(result2, '456');
|
constructableFunction.call(result2, '456');
|
||||||
|
|
@ -40,7 +40,7 @@ describe('getTargetValue', () => {
|
||||||
// window.field not be affected
|
// window.field not be affected
|
||||||
expect(window.field).toEqual('123');
|
expect(window.field).toEqual('123');
|
||||||
// reference should be stable after first running
|
// reference should be stable after first running
|
||||||
expect(constructableFunction).toBe(getTargetValue(window, prototypeAddedAfterFirstInvocation));
|
expect(constructableFunction).toBe(rebindTarget2Fn(window, prototypeAddedAfterFirstInvocation));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work well while value have a readonly prototype on its prototype chain', () => {
|
it('should work well while value have a readonly prototype on its prototype chain', () => {
|
||||||
|
|
@ -56,7 +56,7 @@ describe('getTargetValue', () => {
|
||||||
|
|
||||||
Object.setPrototypeOf(callableFunction, functionWithReadonlyPrototype);
|
Object.setPrototypeOf(callableFunction, functionWithReadonlyPrototype);
|
||||||
|
|
||||||
const boundFn = getTargetValue(window, callableFunction);
|
const boundFn = rebindTarget2Fn(window, callableFunction);
|
||||||
expect(boundFn.prototype).toBe(callableFunction.prototype);
|
expect(boundFn.prototype).toBe(callableFunction.prototype);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -71,9 +71,9 @@ describe('getTargetValue', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const boundFn1 = getTargetValue(window, callableFunction1);
|
const boundFn1 = rebindTarget2Fn(window, callableFunction1);
|
||||||
const boundFn2 = getTargetValue(window, callableFunction2);
|
const boundFn2 = rebindTarget2Fn(window, callableFunction2);
|
||||||
const boundFn3 = getTargetValue(window, callableFunction3);
|
const boundFn3 = rebindTarget2Fn(window, callableFunction3);
|
||||||
|
|
||||||
expect(boundFn1.toString()).toBe(callableFunction1.toString());
|
expect(boundFn1.toString()).toBe(callableFunction1.toString());
|
||||||
expect(boundFn2.toString()).toBe(callableFunction2.toString());
|
expect(boundFn2.toString()).toBe(callableFunction2.toString());
|
||||||
|
|
|
||||||
|
|
@ -293,16 +293,35 @@ it('document should work well with MutationObserver', (done) => {
|
||||||
docProxy.document.body.innerHTML = '<div></div>';
|
docProxy.document.body.innerHTML = '<div></div>';
|
||||||
});
|
});
|
||||||
|
|
||||||
it('bounded function should not be rebounded', () => {
|
it('native window function calling should always be bound with window', () => {
|
||||||
const proxy = new ProxySandbox('bound-fn-test').proxy as any;
|
window.mockNativeWindowFunction = function mockNativeWindowFunction(this: any) {
|
||||||
const fn = () => {};
|
if (this !== undefined && this !== window) {
|
||||||
const boundedFn = fn.bind(null);
|
throw new Error('Illegal Invocation!');
|
||||||
proxy.fn1 = fn;
|
}
|
||||||
proxy.fn2 = boundedFn;
|
|
||||||
|
|
||||||
expect(proxy.fn1 === fn).toBeFalsy();
|
return 'success';
|
||||||
expect(proxy.fn2 === boundedFn).toBeTruthy();
|
};
|
||||||
expect(isBoundedFunction(proxy.fn1)).toBeTruthy();
|
|
||||||
|
const { proxy } = new ProxySandbox('mustBeBoundWithWindowReference');
|
||||||
|
expect(proxy.mockNativeWindowFunction()).toBe('success');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('native bounded function should not be rebounded', () => {
|
||||||
|
const proxy = new ProxySandbox('bound-native-fn-test').proxy as any;
|
||||||
|
const boundedFn = atob.bind(null);
|
||||||
|
proxy.atob = boundedFn;
|
||||||
|
|
||||||
|
expect(proxy.atob === boundedFn).toBeTruthy();
|
||||||
|
expect(isBoundedFunction(proxy.atob)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('non-native function should not be rebounded', () => {
|
||||||
|
const proxy = new ProxySandbox('non-native-fn-bound-test').proxy as any;
|
||||||
|
function test() {}
|
||||||
|
proxy.fn = test;
|
||||||
|
|
||||||
|
expect(proxy.fn === test).toBeTruthy();
|
||||||
|
expect(isBoundedFunction(proxy.fn)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('frozen property should not be overwrite', () => {
|
it('frozen property should not be overwrite', () => {
|
||||||
|
|
@ -332,12 +351,8 @@ it('frozen property should not be overwrite', () => {
|
||||||
|
|
||||||
it('the prototype should be kept while we create a function with prototype on proxy', () => {
|
it('the prototype should be kept while we create a function with prototype on proxy', () => {
|
||||||
const proxy = new ProxySandbox('new-function').proxy as any;
|
const proxy = new ProxySandbox('new-function').proxy as any;
|
||||||
|
proxy.CustomEvent = CustomEvent;
|
||||||
function test() {}
|
expect(proxy.CustomEvent.prototype).toBe(CustomEvent.prototype);
|
||||||
|
|
||||||
proxy.fn = test;
|
|
||||||
expect(proxy.fn === test).toBeFalsy();
|
|
||||||
expect(proxy.fn.prototype).toBe(test.prototype);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('some native window property was defined with getter in safari and firefox, and they will check the caller source', () => {
|
it('some native window property was defined with getter in safari and firefox, and they will check the caller source', () => {
|
||||||
|
|
@ -399,19 +414,6 @@ it('should get current running sandbox proxy correctly', async () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('native window function calling should always be bound with window', () => {
|
|
||||||
window.nativeWindowFunction = function nativeWindowFunction(this: any) {
|
|
||||||
if (this !== undefined && this !== window) {
|
|
||||||
throw new Error('Illegal Invocation!');
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'success';
|
|
||||||
};
|
|
||||||
|
|
||||||
const { proxy } = new ProxySandbox('mustBeBoundWithWindowReference');
|
|
||||||
expect(proxy.nativeWindowFunction()).toBe('success');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('should work well while the property existed in global context before', () => {
|
describe('should work well while the property existed in global context before', () => {
|
||||||
it('should not write value while the readonly property existed in global context but not in sandbox', () => {
|
it('should not write value while the readonly property existed in global context but not in sandbox', () => {
|
||||||
Object.defineProperty(window, 'readonlyPropertyInGlobalContext', {
|
Object.defineProperty(window, 'readonlyPropertyInGlobalContext', {
|
||||||
|
|
|
||||||
|
|
@ -26,60 +26,60 @@ export function clearCurrentRunningApp() {
|
||||||
|
|
||||||
const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>();
|
const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>();
|
||||||
|
|
||||||
export function getTargetValue(target: any, value: any): any {
|
export function rebindTarget2Fn(target: any, fn: any): any {
|
||||||
/*
|
/*
|
||||||
仅绑定 isCallable && !isBoundedFunction && !isConstructable 的函数对象,如 window.console、window.atob 这类,不然微应用中调用时会抛出 Illegal invocation 异常
|
仅绑定 isCallable && !isBoundedFunction && !isConstructable 的函数对象,如 window.console、window.atob 这类,不然微应用中调用时会抛出 Illegal invocation 异常
|
||||||
目前没有完美的检测方式,这里通过 prototype 中是否还有可枚举的拓展方法的方式来判断
|
目前没有完美的检测方式,这里通过 prototype 中是否还有可枚举的拓展方法的方式来判断
|
||||||
@warning 这里不要随意替换成别的判断方式,因为可能触发一些 edge case(比如在 lodash.isFunction 在 iframe 上下文中可能由于调用了 top window 对象触发的安全异常)
|
@warning 这里不要随意替换成别的判断方式,因为可能触发一些 edge case(比如在 lodash.isFunction 在 iframe 上下文中可能由于调用了 top window 对象触发的安全异常)
|
||||||
*/
|
*/
|
||||||
if (isCallable(value) && !isBoundedFunction(value) && !isConstructable(value)) {
|
if (isCallable(fn) && !isBoundedFunction(fn) && !isConstructable(fn)) {
|
||||||
const cachedBoundFunction = functionBoundedValueMap.get(value);
|
const cachedBoundFunction = functionBoundedValueMap.get(fn);
|
||||||
if (cachedBoundFunction) {
|
if (cachedBoundFunction) {
|
||||||
return cachedBoundFunction;
|
return cachedBoundFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
const boundValue = Function.prototype.bind.call(value, target);
|
const boundValue = Function.prototype.bind.call(fn, target);
|
||||||
|
|
||||||
// some callable function has custom fields, we need to copy the own props to boundValue. such as moment function.
|
// some callable function has custom fields, we need to copy the own props to boundValue. such as moment function.
|
||||||
Object.getOwnPropertyNames(value).forEach((key) => {
|
Object.getOwnPropertyNames(fn).forEach((key) => {
|
||||||
// boundValue might be a proxy, we need to check the key whether exist in it
|
// boundValue might be a proxy, we need to check the key whether exist in it
|
||||||
if (!boundValue.hasOwnProperty(key)) {
|
if (!boundValue.hasOwnProperty(key)) {
|
||||||
Object.defineProperty(boundValue, key, Object.getOwnPropertyDescriptor(value, key)!);
|
Object.defineProperty(boundValue, key, Object.getOwnPropertyDescriptor(fn, key)!);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// copy prototype if bound function not have but target one have
|
// copy prototype if bound function not have but target one have
|
||||||
// as prototype is non-enumerable mostly, we need to copy it from target function manually
|
// as prototype is non-enumerable mostly, we need to copy it from target function manually
|
||||||
if (value.hasOwnProperty('prototype') && !boundValue.hasOwnProperty('prototype')) {
|
if (fn.hasOwnProperty('prototype') && !boundValue.hasOwnProperty('prototype')) {
|
||||||
// we should not use assignment operator to set boundValue prototype like `boundValue.prototype = value.prototype`
|
// we should not use assignment operator to set boundValue prototype like `boundValue.prototype = fn.prototype`
|
||||||
// as the assignment will also look up prototype chain while it hasn't own prototype property,
|
// as the assignment will also look up prototype chain while it hasn't own prototype property,
|
||||||
// when the lookup succeed, the assignment will throw an TypeError like `Cannot assign to read only property 'prototype' of function` if its descriptor configured with writable false or just have a getter accessor
|
// when the lookup succeed, the assignment will throw an TypeError like `Cannot assign to read only property 'prototype' of function` if its descriptor configured with writable false or just have a getter accessor
|
||||||
// see https://github.com/umijs/qiankun/issues/1121
|
// see https://github.com/umijs/qiankun/issues/1121
|
||||||
Object.defineProperty(boundValue, 'prototype', { value: value.prototype, enumerable: false, writable: true });
|
Object.defineProperty(boundValue, 'prototype', { value: fn.prototype, enumerable: false, writable: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some util, like `function isNative() { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) }` relies on the original `toString()` result
|
// Some util, like `function isNative() { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) }` relies on the original `toString()` result
|
||||||
// but bound functions will always return "function() {[native code]}" for `toString`, which is misleading
|
// but bound functions will always return "function() {[native code]}" for `toString`, which is misleading
|
||||||
if (typeof value.toString === 'function') {
|
if (typeof fn.toString === 'function') {
|
||||||
const valueHasInstanceToString = value.hasOwnProperty('toString') && !boundValue.hasOwnProperty('toString');
|
const valueHasInstanceToString = fn.hasOwnProperty('toString') && !boundValue.hasOwnProperty('toString');
|
||||||
const boundValueHasPrototypeToString = boundValue.toString === Function.prototype.toString;
|
const boundValueHasPrototypeToString = boundValue.toString === Function.prototype.toString;
|
||||||
|
|
||||||
if (valueHasInstanceToString || boundValueHasPrototypeToString) {
|
if (valueHasInstanceToString || boundValueHasPrototypeToString) {
|
||||||
const originToStringDescriptor = Object.getOwnPropertyDescriptor(
|
const originToStringDescriptor = Object.getOwnPropertyDescriptor(
|
||||||
valueHasInstanceToString ? value : Function.prototype,
|
valueHasInstanceToString ? fn : Function.prototype,
|
||||||
'toString',
|
'toString',
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.defineProperty(boundValue, 'toString', {
|
Object.defineProperty(boundValue, 'toString', {
|
||||||
...originToStringDescriptor,
|
...originToStringDescriptor,
|
||||||
...(originToStringDescriptor?.get ? null : { value: () => value.toString() }),
|
...(originToStringDescriptor?.get ? null : { value: () => fn.toString() }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
functionBoundedValueMap.set(value, boundValue);
|
functionBoundedValueMap.set(fn, boundValue);
|
||||||
return boundValue;
|
return boundValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part
|
// generated from https://github.com/sindresorhus/globals/blob/main/globals.json es2015 part
|
||||||
// only init its values while Proxy is supported
|
// only init its values while Proxy is supported
|
||||||
export const globals = window.Proxy
|
export const globalsInES2015 = window.Proxy
|
||||||
? [
|
? [
|
||||||
'Array',
|
'Array',
|
||||||
'ArrayBuffer',
|
'ArrayBuffer',
|
||||||
|
|
@ -61,3 +61,743 @@ export const globals = window.Proxy
|
||||||
'WeakSet',
|
'WeakSet',
|
||||||
].filter((p) => /* just keep the available properties in current window context */ p in window)
|
].filter((p) => /* just keep the available properties in current window context */ p in window)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
export const globalsInBrowser = [
|
||||||
|
'AbortController',
|
||||||
|
'AbortSignal',
|
||||||
|
'addEventListener',
|
||||||
|
'alert',
|
||||||
|
'AnalyserNode',
|
||||||
|
'Animation',
|
||||||
|
'AnimationEffectReadOnly',
|
||||||
|
'AnimationEffectTiming',
|
||||||
|
'AnimationEffectTimingReadOnly',
|
||||||
|
'AnimationEvent',
|
||||||
|
'AnimationPlaybackEvent',
|
||||||
|
'AnimationTimeline',
|
||||||
|
'applicationCache',
|
||||||
|
'ApplicationCache',
|
||||||
|
'ApplicationCacheErrorEvent',
|
||||||
|
'atob',
|
||||||
|
'Attr',
|
||||||
|
'Audio',
|
||||||
|
'AudioBuffer',
|
||||||
|
'AudioBufferSourceNode',
|
||||||
|
'AudioContext',
|
||||||
|
'AudioDestinationNode',
|
||||||
|
'AudioListener',
|
||||||
|
'AudioNode',
|
||||||
|
'AudioParam',
|
||||||
|
'AudioProcessingEvent',
|
||||||
|
'AudioScheduledSourceNode',
|
||||||
|
'AudioWorkletGlobalScope',
|
||||||
|
'AudioWorkletNode',
|
||||||
|
'AudioWorkletProcessor',
|
||||||
|
'BarProp',
|
||||||
|
'BaseAudioContext',
|
||||||
|
'BatteryManager',
|
||||||
|
'BeforeUnloadEvent',
|
||||||
|
'BiquadFilterNode',
|
||||||
|
'Blob',
|
||||||
|
'BlobEvent',
|
||||||
|
'blur',
|
||||||
|
'BroadcastChannel',
|
||||||
|
'btoa',
|
||||||
|
'BudgetService',
|
||||||
|
'ByteLengthQueuingStrategy',
|
||||||
|
'Cache',
|
||||||
|
'caches',
|
||||||
|
'CacheStorage',
|
||||||
|
'cancelAnimationFrame',
|
||||||
|
'cancelIdleCallback',
|
||||||
|
'CanvasCaptureMediaStreamTrack',
|
||||||
|
'CanvasGradient',
|
||||||
|
'CanvasPattern',
|
||||||
|
'CanvasRenderingContext2D',
|
||||||
|
'ChannelMergerNode',
|
||||||
|
'ChannelSplitterNode',
|
||||||
|
'CharacterData',
|
||||||
|
'clearInterval',
|
||||||
|
'clearTimeout',
|
||||||
|
'clientInformation',
|
||||||
|
'ClipboardEvent',
|
||||||
|
'ClipboardItem',
|
||||||
|
'close',
|
||||||
|
'closed',
|
||||||
|
'CloseEvent',
|
||||||
|
'Comment',
|
||||||
|
'CompositionEvent',
|
||||||
|
'CompressionStream',
|
||||||
|
'confirm',
|
||||||
|
'console',
|
||||||
|
'ConstantSourceNode',
|
||||||
|
'ConvolverNode',
|
||||||
|
'CountQueuingStrategy',
|
||||||
|
'createImageBitmap',
|
||||||
|
'Credential',
|
||||||
|
'CredentialsContainer',
|
||||||
|
'crypto',
|
||||||
|
'Crypto',
|
||||||
|
'CryptoKey',
|
||||||
|
'CSS',
|
||||||
|
'CSSConditionRule',
|
||||||
|
'CSSFontFaceRule',
|
||||||
|
'CSSGroupingRule',
|
||||||
|
'CSSImportRule',
|
||||||
|
'CSSKeyframeRule',
|
||||||
|
'CSSKeyframesRule',
|
||||||
|
'CSSMatrixComponent',
|
||||||
|
'CSSMediaRule',
|
||||||
|
'CSSNamespaceRule',
|
||||||
|
'CSSPageRule',
|
||||||
|
'CSSPerspective',
|
||||||
|
'CSSRotate',
|
||||||
|
'CSSRule',
|
||||||
|
'CSSRuleList',
|
||||||
|
'CSSScale',
|
||||||
|
'CSSSkew',
|
||||||
|
'CSSSkewX',
|
||||||
|
'CSSSkewY',
|
||||||
|
'CSSStyleDeclaration',
|
||||||
|
'CSSStyleRule',
|
||||||
|
'CSSStyleSheet',
|
||||||
|
'CSSSupportsRule',
|
||||||
|
'CSSTransformValue',
|
||||||
|
'CSSTranslate',
|
||||||
|
'CustomElementRegistry',
|
||||||
|
'customElements',
|
||||||
|
'CustomEvent',
|
||||||
|
'DataTransfer',
|
||||||
|
'DataTransferItem',
|
||||||
|
'DataTransferItemList',
|
||||||
|
'DecompressionStream',
|
||||||
|
'defaultstatus',
|
||||||
|
'defaultStatus',
|
||||||
|
'DelayNode',
|
||||||
|
'DeviceMotionEvent',
|
||||||
|
'DeviceOrientationEvent',
|
||||||
|
'devicePixelRatio',
|
||||||
|
'dispatchEvent',
|
||||||
|
'document',
|
||||||
|
'Document',
|
||||||
|
'DocumentFragment',
|
||||||
|
'DocumentType',
|
||||||
|
'DOMError',
|
||||||
|
'DOMException',
|
||||||
|
'DOMImplementation',
|
||||||
|
'DOMMatrix',
|
||||||
|
'DOMMatrixReadOnly',
|
||||||
|
'DOMParser',
|
||||||
|
'DOMPoint',
|
||||||
|
'DOMPointReadOnly',
|
||||||
|
'DOMQuad',
|
||||||
|
'DOMRect',
|
||||||
|
'DOMRectList',
|
||||||
|
'DOMRectReadOnly',
|
||||||
|
'DOMStringList',
|
||||||
|
'DOMStringMap',
|
||||||
|
'DOMTokenList',
|
||||||
|
'DragEvent',
|
||||||
|
'DynamicsCompressorNode',
|
||||||
|
'Element',
|
||||||
|
'ErrorEvent',
|
||||||
|
'event',
|
||||||
|
'Event',
|
||||||
|
'EventSource',
|
||||||
|
'EventTarget',
|
||||||
|
'external',
|
||||||
|
'fetch',
|
||||||
|
'File',
|
||||||
|
'FileList',
|
||||||
|
'FileReader',
|
||||||
|
'find',
|
||||||
|
'focus',
|
||||||
|
'FocusEvent',
|
||||||
|
'FontFace',
|
||||||
|
'FontFaceSetLoadEvent',
|
||||||
|
'FormData',
|
||||||
|
'FormDataEvent',
|
||||||
|
'frameElement',
|
||||||
|
'frames',
|
||||||
|
'GainNode',
|
||||||
|
'Gamepad',
|
||||||
|
'GamepadButton',
|
||||||
|
'GamepadEvent',
|
||||||
|
'getComputedStyle',
|
||||||
|
'getSelection',
|
||||||
|
'HashChangeEvent',
|
||||||
|
'Headers',
|
||||||
|
'history',
|
||||||
|
'History',
|
||||||
|
'HTMLAllCollection',
|
||||||
|
'HTMLAnchorElement',
|
||||||
|
'HTMLAreaElement',
|
||||||
|
'HTMLAudioElement',
|
||||||
|
'HTMLBaseElement',
|
||||||
|
'HTMLBodyElement',
|
||||||
|
'HTMLBRElement',
|
||||||
|
'HTMLButtonElement',
|
||||||
|
'HTMLCanvasElement',
|
||||||
|
'HTMLCollection',
|
||||||
|
'HTMLContentElement',
|
||||||
|
'HTMLDataElement',
|
||||||
|
'HTMLDataListElement',
|
||||||
|
'HTMLDetailsElement',
|
||||||
|
'HTMLDialogElement',
|
||||||
|
'HTMLDirectoryElement',
|
||||||
|
'HTMLDivElement',
|
||||||
|
'HTMLDListElement',
|
||||||
|
'HTMLDocument',
|
||||||
|
'HTMLElement',
|
||||||
|
'HTMLEmbedElement',
|
||||||
|
'HTMLFieldSetElement',
|
||||||
|
'HTMLFontElement',
|
||||||
|
'HTMLFormControlsCollection',
|
||||||
|
'HTMLFormElement',
|
||||||
|
'HTMLFrameElement',
|
||||||
|
'HTMLFrameSetElement',
|
||||||
|
'HTMLHeadElement',
|
||||||
|
'HTMLHeadingElement',
|
||||||
|
'HTMLHRElement',
|
||||||
|
'HTMLHtmlElement',
|
||||||
|
'HTMLIFrameElement',
|
||||||
|
'HTMLImageElement',
|
||||||
|
'HTMLInputElement',
|
||||||
|
'HTMLLabelElement',
|
||||||
|
'HTMLLegendElement',
|
||||||
|
'HTMLLIElement',
|
||||||
|
'HTMLLinkElement',
|
||||||
|
'HTMLMapElement',
|
||||||
|
'HTMLMarqueeElement',
|
||||||
|
'HTMLMediaElement',
|
||||||
|
'HTMLMenuElement',
|
||||||
|
'HTMLMetaElement',
|
||||||
|
'HTMLMeterElement',
|
||||||
|
'HTMLModElement',
|
||||||
|
'HTMLObjectElement',
|
||||||
|
'HTMLOListElement',
|
||||||
|
'HTMLOptGroupElement',
|
||||||
|
'HTMLOptionElement',
|
||||||
|
'HTMLOptionsCollection',
|
||||||
|
'HTMLOutputElement',
|
||||||
|
'HTMLParagraphElement',
|
||||||
|
'HTMLParamElement',
|
||||||
|
'HTMLPictureElement',
|
||||||
|
'HTMLPreElement',
|
||||||
|
'HTMLProgressElement',
|
||||||
|
'HTMLQuoteElement',
|
||||||
|
'HTMLScriptElement',
|
||||||
|
'HTMLSelectElement',
|
||||||
|
'HTMLShadowElement',
|
||||||
|
'HTMLSlotElement',
|
||||||
|
'HTMLSourceElement',
|
||||||
|
'HTMLSpanElement',
|
||||||
|
'HTMLStyleElement',
|
||||||
|
'HTMLTableCaptionElement',
|
||||||
|
'HTMLTableCellElement',
|
||||||
|
'HTMLTableColElement',
|
||||||
|
'HTMLTableElement',
|
||||||
|
'HTMLTableRowElement',
|
||||||
|
'HTMLTableSectionElement',
|
||||||
|
'HTMLTemplateElement',
|
||||||
|
'HTMLTextAreaElement',
|
||||||
|
'HTMLTimeElement',
|
||||||
|
'HTMLTitleElement',
|
||||||
|
'HTMLTrackElement',
|
||||||
|
'HTMLUListElement',
|
||||||
|
'HTMLUnknownElement',
|
||||||
|
'HTMLVideoElement',
|
||||||
|
'IDBCursor',
|
||||||
|
'IDBCursorWithValue',
|
||||||
|
'IDBDatabase',
|
||||||
|
'IDBFactory',
|
||||||
|
'IDBIndex',
|
||||||
|
'IDBKeyRange',
|
||||||
|
'IDBObjectStore',
|
||||||
|
'IDBOpenDBRequest',
|
||||||
|
'IDBRequest',
|
||||||
|
'IDBTransaction',
|
||||||
|
'IDBVersionChangeEvent',
|
||||||
|
'IdleDeadline',
|
||||||
|
'IIRFilterNode',
|
||||||
|
'Image',
|
||||||
|
'ImageBitmap',
|
||||||
|
'ImageBitmapRenderingContext',
|
||||||
|
'ImageCapture',
|
||||||
|
'ImageData',
|
||||||
|
'indexedDB',
|
||||||
|
'innerHeight',
|
||||||
|
'innerWidth',
|
||||||
|
'InputEvent',
|
||||||
|
'IntersectionObserver',
|
||||||
|
'IntersectionObserverEntry',
|
||||||
|
'Intl',
|
||||||
|
'isSecureContext',
|
||||||
|
'KeyboardEvent',
|
||||||
|
'KeyframeEffect',
|
||||||
|
'KeyframeEffectReadOnly',
|
||||||
|
'length',
|
||||||
|
'localStorage',
|
||||||
|
'location',
|
||||||
|
'Location',
|
||||||
|
'locationbar',
|
||||||
|
'matchMedia',
|
||||||
|
'MediaDeviceInfo',
|
||||||
|
'MediaDevices',
|
||||||
|
'MediaElementAudioSourceNode',
|
||||||
|
'MediaEncryptedEvent',
|
||||||
|
'MediaError',
|
||||||
|
'MediaKeyMessageEvent',
|
||||||
|
'MediaKeySession',
|
||||||
|
'MediaKeyStatusMap',
|
||||||
|
'MediaKeySystemAccess',
|
||||||
|
'MediaList',
|
||||||
|
'MediaMetadata',
|
||||||
|
'MediaQueryList',
|
||||||
|
'MediaQueryListEvent',
|
||||||
|
'MediaRecorder',
|
||||||
|
'MediaSettingsRange',
|
||||||
|
'MediaSource',
|
||||||
|
'MediaStream',
|
||||||
|
'MediaStreamAudioDestinationNode',
|
||||||
|
'MediaStreamAudioSourceNode',
|
||||||
|
'MediaStreamEvent',
|
||||||
|
'MediaStreamTrack',
|
||||||
|
'MediaStreamTrackEvent',
|
||||||
|
'menubar',
|
||||||
|
'MessageChannel',
|
||||||
|
'MessageEvent',
|
||||||
|
'MessagePort',
|
||||||
|
'MIDIAccess',
|
||||||
|
'MIDIConnectionEvent',
|
||||||
|
'MIDIInput',
|
||||||
|
'MIDIInputMap',
|
||||||
|
'MIDIMessageEvent',
|
||||||
|
'MIDIOutput',
|
||||||
|
'MIDIOutputMap',
|
||||||
|
'MIDIPort',
|
||||||
|
'MimeType',
|
||||||
|
'MimeTypeArray',
|
||||||
|
'MouseEvent',
|
||||||
|
'moveBy',
|
||||||
|
'moveTo',
|
||||||
|
'MutationEvent',
|
||||||
|
'MutationObserver',
|
||||||
|
'MutationRecord',
|
||||||
|
'name',
|
||||||
|
'NamedNodeMap',
|
||||||
|
'NavigationPreloadManager',
|
||||||
|
'navigator',
|
||||||
|
'Navigator',
|
||||||
|
'NavigatorUAData',
|
||||||
|
'NetworkInformation',
|
||||||
|
'Node',
|
||||||
|
'NodeFilter',
|
||||||
|
'NodeIterator',
|
||||||
|
'NodeList',
|
||||||
|
'Notification',
|
||||||
|
'OfflineAudioCompletionEvent',
|
||||||
|
'OfflineAudioContext',
|
||||||
|
'offscreenBuffering',
|
||||||
|
'OffscreenCanvas',
|
||||||
|
'OffscreenCanvasRenderingContext2D',
|
||||||
|
'onabort',
|
||||||
|
'onafterprint',
|
||||||
|
'onanimationend',
|
||||||
|
'onanimationiteration',
|
||||||
|
'onanimationstart',
|
||||||
|
'onappinstalled',
|
||||||
|
'onauxclick',
|
||||||
|
'onbeforeinstallprompt',
|
||||||
|
'onbeforeprint',
|
||||||
|
'onbeforeunload',
|
||||||
|
'onblur',
|
||||||
|
'oncancel',
|
||||||
|
'oncanplay',
|
||||||
|
'oncanplaythrough',
|
||||||
|
'onchange',
|
||||||
|
'onclick',
|
||||||
|
'onclose',
|
||||||
|
'oncontextmenu',
|
||||||
|
'oncuechange',
|
||||||
|
'ondblclick',
|
||||||
|
'ondevicemotion',
|
||||||
|
'ondeviceorientation',
|
||||||
|
'ondeviceorientationabsolute',
|
||||||
|
'ondrag',
|
||||||
|
'ondragend',
|
||||||
|
'ondragenter',
|
||||||
|
'ondragleave',
|
||||||
|
'ondragover',
|
||||||
|
'ondragstart',
|
||||||
|
'ondrop',
|
||||||
|
'ondurationchange',
|
||||||
|
'onemptied',
|
||||||
|
'onended',
|
||||||
|
'onerror',
|
||||||
|
'onfocus',
|
||||||
|
'ongotpointercapture',
|
||||||
|
'onhashchange',
|
||||||
|
'oninput',
|
||||||
|
'oninvalid',
|
||||||
|
'onkeydown',
|
||||||
|
'onkeypress',
|
||||||
|
'onkeyup',
|
||||||
|
'onlanguagechange',
|
||||||
|
'onload',
|
||||||
|
'onloadeddata',
|
||||||
|
'onloadedmetadata',
|
||||||
|
'onloadstart',
|
||||||
|
'onlostpointercapture',
|
||||||
|
'onmessage',
|
||||||
|
'onmessageerror',
|
||||||
|
'onmousedown',
|
||||||
|
'onmouseenter',
|
||||||
|
'onmouseleave',
|
||||||
|
'onmousemove',
|
||||||
|
'onmouseout',
|
||||||
|
'onmouseover',
|
||||||
|
'onmouseup',
|
||||||
|
'onmousewheel',
|
||||||
|
'onoffline',
|
||||||
|
'ononline',
|
||||||
|
'onpagehide',
|
||||||
|
'onpageshow',
|
||||||
|
'onpause',
|
||||||
|
'onplay',
|
||||||
|
'onplaying',
|
||||||
|
'onpointercancel',
|
||||||
|
'onpointerdown',
|
||||||
|
'onpointerenter',
|
||||||
|
'onpointerleave',
|
||||||
|
'onpointermove',
|
||||||
|
'onpointerout',
|
||||||
|
'onpointerover',
|
||||||
|
'onpointerup',
|
||||||
|
'onpopstate',
|
||||||
|
'onprogress',
|
||||||
|
'onratechange',
|
||||||
|
'onrejectionhandled',
|
||||||
|
'onreset',
|
||||||
|
'onresize',
|
||||||
|
'onscroll',
|
||||||
|
'onsearch',
|
||||||
|
'onseeked',
|
||||||
|
'onseeking',
|
||||||
|
'onselect',
|
||||||
|
'onstalled',
|
||||||
|
'onstorage',
|
||||||
|
'onsubmit',
|
||||||
|
'onsuspend',
|
||||||
|
'ontimeupdate',
|
||||||
|
'ontoggle',
|
||||||
|
'ontransitionend',
|
||||||
|
'onunhandledrejection',
|
||||||
|
'onunload',
|
||||||
|
'onvolumechange',
|
||||||
|
'onwaiting',
|
||||||
|
'onwheel',
|
||||||
|
'open',
|
||||||
|
'openDatabase',
|
||||||
|
'opener',
|
||||||
|
'Option',
|
||||||
|
'origin',
|
||||||
|
'OscillatorNode',
|
||||||
|
'outerHeight',
|
||||||
|
'outerWidth',
|
||||||
|
'OverconstrainedError',
|
||||||
|
'PageTransitionEvent',
|
||||||
|
'pageXOffset',
|
||||||
|
'pageYOffset',
|
||||||
|
'PannerNode',
|
||||||
|
'parent',
|
||||||
|
'Path2D',
|
||||||
|
'PaymentAddress',
|
||||||
|
'PaymentRequest',
|
||||||
|
'PaymentRequestUpdateEvent',
|
||||||
|
'PaymentResponse',
|
||||||
|
'performance',
|
||||||
|
'Performance',
|
||||||
|
'PerformanceEntry',
|
||||||
|
'PerformanceLongTaskTiming',
|
||||||
|
'PerformanceMark',
|
||||||
|
'PerformanceMeasure',
|
||||||
|
'PerformanceNavigation',
|
||||||
|
'PerformanceNavigationTiming',
|
||||||
|
'PerformanceObserver',
|
||||||
|
'PerformanceObserverEntryList',
|
||||||
|
'PerformancePaintTiming',
|
||||||
|
'PerformanceResourceTiming',
|
||||||
|
'PerformanceTiming',
|
||||||
|
'PeriodicWave',
|
||||||
|
'Permissions',
|
||||||
|
'PermissionStatus',
|
||||||
|
'personalbar',
|
||||||
|
'PhotoCapabilities',
|
||||||
|
'Plugin',
|
||||||
|
'PluginArray',
|
||||||
|
'PointerEvent',
|
||||||
|
'PopStateEvent',
|
||||||
|
'postMessage',
|
||||||
|
'Presentation',
|
||||||
|
'PresentationAvailability',
|
||||||
|
'PresentationConnection',
|
||||||
|
'PresentationConnectionAvailableEvent',
|
||||||
|
'PresentationConnectionCloseEvent',
|
||||||
|
'PresentationConnectionList',
|
||||||
|
'PresentationReceiver',
|
||||||
|
'PresentationRequest',
|
||||||
|
'print',
|
||||||
|
'ProcessingInstruction',
|
||||||
|
'ProgressEvent',
|
||||||
|
'PromiseRejectionEvent',
|
||||||
|
'prompt',
|
||||||
|
'PushManager',
|
||||||
|
'PushSubscription',
|
||||||
|
'PushSubscriptionOptions',
|
||||||
|
'queueMicrotask',
|
||||||
|
'RadioNodeList',
|
||||||
|
'Range',
|
||||||
|
'ReadableByteStreamController',
|
||||||
|
'ReadableStream',
|
||||||
|
'ReadableStreamBYOBReader',
|
||||||
|
'ReadableStreamBYOBRequest',
|
||||||
|
'ReadableStreamDefaultController',
|
||||||
|
'ReadableStreamDefaultReader',
|
||||||
|
'registerProcessor',
|
||||||
|
'RemotePlayback',
|
||||||
|
'removeEventListener',
|
||||||
|
'reportError',
|
||||||
|
'Request',
|
||||||
|
'requestAnimationFrame',
|
||||||
|
'requestIdleCallback',
|
||||||
|
'resizeBy',
|
||||||
|
'ResizeObserver',
|
||||||
|
'ResizeObserverEntry',
|
||||||
|
'resizeTo',
|
||||||
|
'Response',
|
||||||
|
'RTCCertificate',
|
||||||
|
'RTCDataChannel',
|
||||||
|
'RTCDataChannelEvent',
|
||||||
|
'RTCDtlsTransport',
|
||||||
|
'RTCIceCandidate',
|
||||||
|
'RTCIceGatherer',
|
||||||
|
'RTCIceTransport',
|
||||||
|
'RTCPeerConnection',
|
||||||
|
'RTCPeerConnectionIceEvent',
|
||||||
|
'RTCRtpContributingSource',
|
||||||
|
'RTCRtpReceiver',
|
||||||
|
'RTCRtpSender',
|
||||||
|
'RTCSctpTransport',
|
||||||
|
'RTCSessionDescription',
|
||||||
|
'RTCStatsReport',
|
||||||
|
'RTCTrackEvent',
|
||||||
|
'screen',
|
||||||
|
'Screen',
|
||||||
|
'screenLeft',
|
||||||
|
'ScreenOrientation',
|
||||||
|
'screenTop',
|
||||||
|
'screenX',
|
||||||
|
'screenY',
|
||||||
|
'ScriptProcessorNode',
|
||||||
|
'scroll',
|
||||||
|
'scrollbars',
|
||||||
|
'scrollBy',
|
||||||
|
'scrollTo',
|
||||||
|
'scrollX',
|
||||||
|
'scrollY',
|
||||||
|
'SecurityPolicyViolationEvent',
|
||||||
|
'Selection',
|
||||||
|
'self',
|
||||||
|
'ServiceWorker',
|
||||||
|
'ServiceWorkerContainer',
|
||||||
|
'ServiceWorkerRegistration',
|
||||||
|
'sessionStorage',
|
||||||
|
'setInterval',
|
||||||
|
'setTimeout',
|
||||||
|
'ShadowRoot',
|
||||||
|
'SharedWorker',
|
||||||
|
'SourceBuffer',
|
||||||
|
'SourceBufferList',
|
||||||
|
'speechSynthesis',
|
||||||
|
'SpeechSynthesisEvent',
|
||||||
|
'SpeechSynthesisUtterance',
|
||||||
|
'StaticRange',
|
||||||
|
'status',
|
||||||
|
'statusbar',
|
||||||
|
'StereoPannerNode',
|
||||||
|
'stop',
|
||||||
|
'Storage',
|
||||||
|
'StorageEvent',
|
||||||
|
'StorageManager',
|
||||||
|
'structuredClone',
|
||||||
|
'styleMedia',
|
||||||
|
'StyleSheet',
|
||||||
|
'StyleSheetList',
|
||||||
|
'SubmitEvent',
|
||||||
|
'SubtleCrypto',
|
||||||
|
'SVGAElement',
|
||||||
|
'SVGAngle',
|
||||||
|
'SVGAnimatedAngle',
|
||||||
|
'SVGAnimatedBoolean',
|
||||||
|
'SVGAnimatedEnumeration',
|
||||||
|
'SVGAnimatedInteger',
|
||||||
|
'SVGAnimatedLength',
|
||||||
|
'SVGAnimatedLengthList',
|
||||||
|
'SVGAnimatedNumber',
|
||||||
|
'SVGAnimatedNumberList',
|
||||||
|
'SVGAnimatedPreserveAspectRatio',
|
||||||
|
'SVGAnimatedRect',
|
||||||
|
'SVGAnimatedString',
|
||||||
|
'SVGAnimatedTransformList',
|
||||||
|
'SVGAnimateElement',
|
||||||
|
'SVGAnimateMotionElement',
|
||||||
|
'SVGAnimateTransformElement',
|
||||||
|
'SVGAnimationElement',
|
||||||
|
'SVGCircleElement',
|
||||||
|
'SVGClipPathElement',
|
||||||
|
'SVGComponentTransferFunctionElement',
|
||||||
|
'SVGDefsElement',
|
||||||
|
'SVGDescElement',
|
||||||
|
'SVGDiscardElement',
|
||||||
|
'SVGElement',
|
||||||
|
'SVGEllipseElement',
|
||||||
|
'SVGFEBlendElement',
|
||||||
|
'SVGFEColorMatrixElement',
|
||||||
|
'SVGFEComponentTransferElement',
|
||||||
|
'SVGFECompositeElement',
|
||||||
|
'SVGFEConvolveMatrixElement',
|
||||||
|
'SVGFEDiffuseLightingElement',
|
||||||
|
'SVGFEDisplacementMapElement',
|
||||||
|
'SVGFEDistantLightElement',
|
||||||
|
'SVGFEDropShadowElement',
|
||||||
|
'SVGFEFloodElement',
|
||||||
|
'SVGFEFuncAElement',
|
||||||
|
'SVGFEFuncBElement',
|
||||||
|
'SVGFEFuncGElement',
|
||||||
|
'SVGFEFuncRElement',
|
||||||
|
'SVGFEGaussianBlurElement',
|
||||||
|
'SVGFEImageElement',
|
||||||
|
'SVGFEMergeElement',
|
||||||
|
'SVGFEMergeNodeElement',
|
||||||
|
'SVGFEMorphologyElement',
|
||||||
|
'SVGFEOffsetElement',
|
||||||
|
'SVGFEPointLightElement',
|
||||||
|
'SVGFESpecularLightingElement',
|
||||||
|
'SVGFESpotLightElement',
|
||||||
|
'SVGFETileElement',
|
||||||
|
'SVGFETurbulenceElement',
|
||||||
|
'SVGFilterElement',
|
||||||
|
'SVGForeignObjectElement',
|
||||||
|
'SVGGElement',
|
||||||
|
'SVGGeometryElement',
|
||||||
|
'SVGGradientElement',
|
||||||
|
'SVGGraphicsElement',
|
||||||
|
'SVGImageElement',
|
||||||
|
'SVGLength',
|
||||||
|
'SVGLengthList',
|
||||||
|
'SVGLinearGradientElement',
|
||||||
|
'SVGLineElement',
|
||||||
|
'SVGMarkerElement',
|
||||||
|
'SVGMaskElement',
|
||||||
|
'SVGMatrix',
|
||||||
|
'SVGMetadataElement',
|
||||||
|
'SVGMPathElement',
|
||||||
|
'SVGNumber',
|
||||||
|
'SVGNumberList',
|
||||||
|
'SVGPathElement',
|
||||||
|
'SVGPatternElement',
|
||||||
|
'SVGPoint',
|
||||||
|
'SVGPointList',
|
||||||
|
'SVGPolygonElement',
|
||||||
|
'SVGPolylineElement',
|
||||||
|
'SVGPreserveAspectRatio',
|
||||||
|
'SVGRadialGradientElement',
|
||||||
|
'SVGRect',
|
||||||
|
'SVGRectElement',
|
||||||
|
'SVGScriptElement',
|
||||||
|
'SVGSetElement',
|
||||||
|
'SVGStopElement',
|
||||||
|
'SVGStringList',
|
||||||
|
'SVGStyleElement',
|
||||||
|
'SVGSVGElement',
|
||||||
|
'SVGSwitchElement',
|
||||||
|
'SVGSymbolElement',
|
||||||
|
'SVGTextContentElement',
|
||||||
|
'SVGTextElement',
|
||||||
|
'SVGTextPathElement',
|
||||||
|
'SVGTextPositioningElement',
|
||||||
|
'SVGTitleElement',
|
||||||
|
'SVGTransform',
|
||||||
|
'SVGTransformList',
|
||||||
|
'SVGTSpanElement',
|
||||||
|
'SVGUnitTypes',
|
||||||
|
'SVGUseElement',
|
||||||
|
'SVGViewElement',
|
||||||
|
'TaskAttributionTiming',
|
||||||
|
'Text',
|
||||||
|
'TextDecoder',
|
||||||
|
'TextDecoderStream',
|
||||||
|
'TextEncoder',
|
||||||
|
'TextEncoderStream',
|
||||||
|
'TextEvent',
|
||||||
|
'TextMetrics',
|
||||||
|
'TextTrack',
|
||||||
|
'TextTrackCue',
|
||||||
|
'TextTrackCueList',
|
||||||
|
'TextTrackList',
|
||||||
|
'TimeRanges',
|
||||||
|
'toolbar',
|
||||||
|
'top',
|
||||||
|
'Touch',
|
||||||
|
'TouchEvent',
|
||||||
|
'TouchList',
|
||||||
|
'TrackEvent',
|
||||||
|
'TransformStream',
|
||||||
|
'TransformStreamDefaultController',
|
||||||
|
'TransitionEvent',
|
||||||
|
'TreeWalker',
|
||||||
|
'UIEvent',
|
||||||
|
'URL',
|
||||||
|
'URLSearchParams',
|
||||||
|
'ValidityState',
|
||||||
|
'visualViewport',
|
||||||
|
'VisualViewport',
|
||||||
|
'VTTCue',
|
||||||
|
'WaveShaperNode',
|
||||||
|
'WebAssembly',
|
||||||
|
'WebGL2RenderingContext',
|
||||||
|
'WebGLActiveInfo',
|
||||||
|
'WebGLBuffer',
|
||||||
|
'WebGLContextEvent',
|
||||||
|
'WebGLFramebuffer',
|
||||||
|
'WebGLProgram',
|
||||||
|
'WebGLQuery',
|
||||||
|
'WebGLRenderbuffer',
|
||||||
|
'WebGLRenderingContext',
|
||||||
|
'WebGLSampler',
|
||||||
|
'WebGLShader',
|
||||||
|
'WebGLShaderPrecisionFormat',
|
||||||
|
'WebGLSync',
|
||||||
|
'WebGLTexture',
|
||||||
|
'WebGLTransformFeedback',
|
||||||
|
'WebGLUniformLocation',
|
||||||
|
'WebGLVertexArrayObject',
|
||||||
|
'WebSocket',
|
||||||
|
'WheelEvent',
|
||||||
|
'window',
|
||||||
|
'Window',
|
||||||
|
'Worker',
|
||||||
|
'WritableStream',
|
||||||
|
'WritableStreamDefaultController',
|
||||||
|
'WritableStreamDefaultWriter',
|
||||||
|
'XMLDocument',
|
||||||
|
'XMLHttpRequest',
|
||||||
|
'XMLHttpRequestEventTarget',
|
||||||
|
'XMLHttpRequestUpload',
|
||||||
|
'XMLSerializer',
|
||||||
|
'XPathEvaluator',
|
||||||
|
'XPathExpression',
|
||||||
|
'XPathResult',
|
||||||
|
'XSLTProcessor',
|
||||||
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
import type { SandBox } from '../../interfaces';
|
import type { SandBox } from '../../interfaces';
|
||||||
import { SandBoxType } from '../../interfaces';
|
import { SandBoxType } from '../../interfaces';
|
||||||
import { getTargetValue } from '../common';
|
import { rebindTarget2Fn } from '../common';
|
||||||
|
|
||||||
function isPropConfigurable(target: WindowProxy, prop: PropertyKey) {
|
function isPropConfigurable(target: WindowProxy, prop: PropertyKey) {
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(target, prop);
|
const descriptor = Object.getOwnPropertyDescriptor(target, prop);
|
||||||
|
|
@ -125,7 +125,7 @@ export default class LegacySandbox implements SandBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = (rawWindow as any)[p];
|
const value = (rawWindow as any)[p];
|
||||||
return getTargetValue(rawWindow, value);
|
return rebindTarget2Fn(rawWindow, value);
|
||||||
},
|
},
|
||||||
|
|
||||||
// trap in operator
|
// trap in operator
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import { without } from 'lodash';
|
|
||||||
/**
|
/**
|
||||||
* @author Kuitos
|
* @author Kuitos
|
||||||
* @since 2020-3-31
|
* @since 2020-3-31
|
||||||
*/
|
*/
|
||||||
|
import { without } from 'lodash';
|
||||||
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 { clearCurrentRunningApp, getCurrentRunningApp, getTargetValue, setCurrentRunningApp } from './common';
|
import { clearCurrentRunningApp, getCurrentRunningApp, rebindTarget2Fn, setCurrentRunningApp } from './common';
|
||||||
import { globals } from './globals';
|
import { globalsInBrowser, globalsInES2015 } from './globals';
|
||||||
|
|
||||||
type SymbolTarget = 'target' | 'globalContext';
|
type SymbolTarget = 'target' | 'globalContext';
|
||||||
|
|
||||||
|
|
@ -24,6 +24,13 @@ function uniq(array: Array<string | symbol>) {
|
||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cachedGlobalsInBrowser = globalsInBrowser
|
||||||
|
.concat(process.env.NODE_ENV === 'test' ? ['mockNativeWindowFunction'] : [])
|
||||||
|
.reduce<Record<string, true>>((acc, key) => ({ ...acc, [key]: true }), Object.create(null));
|
||||||
|
function isNativeGlobalProp(prop: string): boolean {
|
||||||
|
return prop in cachedGlobalsInBrowser;
|
||||||
|
}
|
||||||
|
|
||||||
// zone.js will overwrite Object.defineProperty
|
// zone.js will overwrite Object.defineProperty
|
||||||
const rawObjectDefineProperty = Object.defineProperty;
|
const rawObjectDefineProperty = Object.defineProperty;
|
||||||
|
|
||||||
|
|
@ -58,7 +65,9 @@ const mockGlobalThis = 'mockGlobalThis';
|
||||||
const accessingSpiedGlobals = ['document', 'top', 'parent', 'eval'];
|
const accessingSpiedGlobals = ['document', 'top', 'parent', 'eval'];
|
||||||
const overwrittenGlobals = ['window', 'self', 'globalThis', 'hasOwnProperty'].concat(inTest ? [mockGlobalThis] : []);
|
const overwrittenGlobals = ['window', 'self', 'globalThis', 'hasOwnProperty'].concat(inTest ? [mockGlobalThis] : []);
|
||||||
export const cachedGlobals = Array.from(
|
export const cachedGlobals = Array.from(
|
||||||
new Set(without(globals.concat(overwrittenGlobals).concat('requestAnimationFrame'), ...accessingSpiedGlobals)),
|
new Set(
|
||||||
|
without(globalsInES2015.concat(overwrittenGlobals).concat('requestAnimationFrame'), ...accessingSpiedGlobals),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// transform cachedGlobals to object for faster element check
|
// transform cachedGlobals to object for faster element check
|
||||||
|
|
@ -297,14 +306,20 @@ export default class ProxySandbox implements SandBox {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// non-native property return directly to avoid rebind
|
||||||
|
if (!isNativeGlobalProp(p as string) && !useNativeWindowForBindingsProps.has(p)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/* Some dom api must be bound to native window, otherwise it would cause exception like 'TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation'
|
/* Some dom api must be bound to native window, otherwise it would cause exception like 'TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation'
|
||||||
See this code:
|
See this code:
|
||||||
const proxy = new Proxy(window, {});
|
const proxy = new Proxy(window, {});
|
||||||
|
// in nest sandbox fetch will be bind to proxy rather than window in master
|
||||||
const proxyFetch = fetch.bind(proxy);
|
const proxyFetch = fetch.bind(proxy);
|
||||||
proxyFetch('https://qiankun.com');
|
proxyFetch('https://qiankun.com');
|
||||||
*/
|
*/
|
||||||
const boundTarget = useNativeWindowForBindingsProps.get(p) ? nativeGlobal : globalContext;
|
const boundTarget = useNativeWindowForBindingsProps.get(p) ? nativeGlobal : globalContext;
|
||||||
return getTargetValue(boundTarget, value);
|
return rebindTarget2Fn(boundTarget, value);
|
||||||
},
|
},
|
||||||
|
|
||||||
// trap in operator
|
// trap in operator
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
* @author Kuitos
|
* @author Kuitos
|
||||||
* @since 2019-05-15
|
* @since 2019-05-15
|
||||||
*/
|
*/
|
||||||
|
import { isFunction, memoize, once, snakeCase } from 'lodash';
|
||||||
import { isFunction, once, snakeCase, memoize } from 'lodash';
|
|
||||||
import type { FrameworkConfiguration } from './interfaces';
|
import type { FrameworkConfiguration } from './interfaces';
|
||||||
import { version } from './version';
|
import { version } from './version';
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user