diff --git a/src/sandbox/patchers/dynamicAppend/__tests__/forStrictSandbox.test.ts b/src/sandbox/patchers/dynamicAppend/__tests__/forStrictSandbox.test.ts new file mode 100644 index 0000000..54512c1 --- /dev/null +++ b/src/sandbox/patchers/dynamicAppend/__tests__/forStrictSandbox.test.ts @@ -0,0 +1,53 @@ +import { SandBoxType } from '../../../../interfaces'; +import { noop } from 'lodash'; +import { patchStrictSandbox } from '../forStrictSandbox'; + +jest.mock('import-html-entry', () => ({ + execScripts: jest.fn(), +})); + +describe('forStrictSandbox test', () => { + const { + prototype: { createTreeWalker: originalCreateTreeWalker }, + } = Document; + + beforeAll(() => { + Document.prototype.createTreeWalker = function createTreeWalker( + this: Document, + root: Node, + whatToShow?: number | undefined, + filter?: NodeFilter | null | undefined, + ) { + if (document !== root) { + throw new TypeError('error'); + } + return originalCreateTreeWalker.call(this, root, whatToShow, filter); + }; + }); + + afterAll(() => { + Document.prototype.createTreeWalker = originalCreateTreeWalker; + }); + + it('should not throw on patched document', () => { + let patchedDocument!: Document; + const appName = 'test-app'; + const wrapper = document.createElement('div'); + const sandbox = { + name: appName, + type: SandBoxType.Proxy, + proxy: window, + sandboxRunning: true, + latestSetProp: null, + patchDocument: (patched: Document) => { + patchedDocument = patched; + }, + active: noop, + inactive: noop, + }; + patchStrictSandbox(appName, () => wrapper, sandbox, true, false, undefined, true); + + expect(patchedDocument).toBeDefined(); + expect(() => patchedDocument?.createTreeWalker(patchedDocument)).not.toThrow(); + }); +}); diff --git a/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts b/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts index a170a15..da1f9e5 100644 --- a/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts +++ b/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts @@ -53,7 +53,7 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) { (target)[p] = value; return true; }, - get: (target, p) => { + get: (target, p, receiver) => { if (p === 'createElement') { // Must store the original createElement function to avoid error in nested sandbox const targetCreateElement = target.createElement; @@ -67,7 +67,9 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) { const value = (target)[p]; // must rebind the function to the target otherwise it will cause illegal invocation error if (typeof value === 'function' && !isBoundedFunction(value)) { - return value.bind(target); + return function proxiedFunction(...args: unknown[]) { + return value.call(target, ...args.map((arg) => (arg === receiver ? target : arg))); + }; } return value;