Skip to content

Commit

Permalink
fix: window === window.top
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Mar 8, 2022
1 parent 46f73a5 commit 833ba36
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 46 deletions.
1 change: 1 addition & 0 deletions scripts/minify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ function managlePropsPlugin(): Plugin {
$isInitialized$: '',
$isLoading$: '',
$isPromise$: '',
$isSameOrigin$: '',
$libPath$: '',
$localStorage$: '',
$location$: '',
Expand Down
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export interface WebWorkerEnvironment {
$isInitialized$?: number;
$isLoading$?: number;
$runWindowLoadEvent$?: number;
$isSameOrigin$?: boolean;
}

export interface MembersInterfaceTypeInfo {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/web-worker/worker-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export const environments: { [winId: WinId]: WebWorkerEnvironment } = {};
export const cachedDimensions = /*#__PURE__*/ new Map<string, any>();
export const cachedStructure = /*#__PURE__*/ new Map<string, any>();

export const ABOUT_BLANK = 'about:blank';

export const commaSplit = (str: string) => str.split(',');

export const partytownLibUrl = (url: string) => {
Expand Down
9 changes: 4 additions & 5 deletions src/lib/web-worker/worker-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { createEnvironment } from './worker-environment';
import { createWindow } from './worker-window';
import { debug, definePrototypePropertyDescriptor, randomId, SCRIPT_TYPE } from '../utils';
import { elementStructurePropNames, IS_TAG_REG, WinIdKey } from './worker-constants';
import { ABOUT_BLANK, elementStructurePropNames, IS_TAG_REG, WinIdKey } from './worker-constants';
import { getInstanceStateValue } from './worker-state';
import { getPartytownScript } from './worker-exec';
import { isScriptJsType } from './worker-script';
Expand All @@ -25,7 +25,6 @@ import { warnCrossOrgin } from '../log';
export const patchDocument = (
WorkerDocument: any,
env: WebWorkerEnvironment,
isSameOrigin: boolean,
isDocumentImplementation?: boolean
) => {
const DocumentDescriptorMap: PropertyDescriptorMap & ThisType<WorkerNode> = {
Expand All @@ -37,15 +36,15 @@ export const patchDocument = (

cookie: {
get() {
if (isSameOrigin) {
if (env.$isSameOrigin$) {
return getter(this, ['cookie']);
} else {
warnCrossOrgin('get', 'cookie', env);
return '';
}
},
set(value) {
if (isSameOrigin) {
if (env.$isSameOrigin$) {
setter(this, ['cookie'], value);
} else if (debug) {
warnCrossOrgin('set', 'cookie', env);
Expand Down Expand Up @@ -74,7 +73,7 @@ export const patchDocument = (
{
$winId$: instanceId,
$parentWinId$: winId,
$url$: 'about:blank',
$url$: ABOUT_BLANK,
},
true
);
Expand Down
11 changes: 8 additions & 3 deletions src/lib/web-worker/worker-exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,20 @@ export const runScriptContent = (
export const run = (env: WebWorkerEnvironment, scriptContent: string, scriptUrl?: string) => {
env.$runWindowLoadEvent$ = 1;

new Function(
scriptContent =
`with(this){${
(webWorkerCtx.$config$.globalFns || [])
.filter((globalFnName) => /[a-zA-Z_$][0-9a-zA-Z_$]*/.test(globalFnName))
.map((g) => `(typeof ${g}=='function'&&(window.${g}=${g}))`)
.join(';') +
scriptContent.replace(/\bthis\b/g, '(thi$(this)?window:this)').replace(/\/\/# so/g, '//Xso')
}\n;function thi$(t){return t===this}}` + (scriptUrl ? '\n//# sourceURL=' + scriptUrl : '')
).call(env.$window$);
}\n;function thi$(t){return t===this}}` + (scriptUrl ? '\n//# sourceURL=' + scriptUrl : '');

if (!env.$isSameOrigin$) {
scriptContent = scriptContent.replace(/.postMessage\(/g, `.postMessage('${env.$winId$}',`);
}

new Function(scriptContent).call(env.$window$);

env.$runWindowLoadEvent$ = 0;
};
Expand Down
10 changes: 8 additions & 2 deletions src/lib/web-worker/worker-iframe.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { createEnvironment } from './worker-environment';
import { definePrototypePropertyDescriptor, SCRIPT_TYPE } from '../utils';
import { environments, InstanceIdKey, webWorkerCtx, WinIdKey } from './worker-constants';
import {
ABOUT_BLANK,
environments,
InstanceIdKey,
webWorkerCtx,
WinIdKey,
} from './worker-constants';
import { getPartytownScript, resolveUrl } from './worker-exec';
import { getter, sendToMain, setter } from './worker-proxy';
import { HTMLSrcElementDescriptorMap } from './worker-src-element';
Expand Down Expand Up @@ -86,7 +92,7 @@ const getIframeEnv = (iframe: WorkerInstance) => {
$winId$,
// iframe contentWindow parent winId is the iframe element's winId
$parentWinId$: iframe[WinIdKey],
$url$: getter(iframe, ['src']) || 'about:blank',
$url$: getter(iframe, ['src']) || ABOUT_BLANK,
},
true
);
Expand Down
56 changes: 28 additions & 28 deletions src/lib/web-worker/worker-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
WorkerWindow,
} from '../types';
import {
ABOUT_BLANK,
ApplyPathKey,
commaSplit,
environments,
Expand Down Expand Up @@ -125,7 +126,8 @@ export const createWindow = (
);

const $location$ = new WorkerLocation(url);
const isSameOrigin = $location$.origin === webWorkerCtx.$origin$;
const $isSameOrigin$ =
$location$.origin === webWorkerCtx.$origin$ || $location$.origin === ABOUT_BLANK;

const env: WebWorkerEnvironment = {} as any;

Expand Down Expand Up @@ -312,7 +314,7 @@ export const createWindow = (

// patch this window's global constructors with some additional props
patchElement(win.Element);
patchDocument(win.Document, env, isSameOrigin, isDocumentImplementation);
patchDocument(win.Document, env, isDocumentImplementation);
patchDocumentFragment(win.DocumentFragment);
patchHTMLAnchorElement(win.HTMLAnchorElement, env);
patchHTMLFormElement(win.HTMLFormElement);
Expand Down Expand Up @@ -346,6 +348,7 @@ export const createWindow = (
$body$: $createNode$(NodeName.Body, $winId$ + WinDocId.body) as any,
$location$,
$visibilityState$,
$isSameOrigin$,
$createNode$,
});

Expand Down Expand Up @@ -373,10 +376,10 @@ export const createWindow = (
win.cancelIdleCallback = (id: number) => clearTimeout(id);

// add storage APIs to the window
addStorageApi(win, 'localStorage', webWorkerlocalStorage, isSameOrigin, env);
addStorageApi(win, 'sessionStorage', webWorkerSessionStorage, isSameOrigin, env);
addStorageApi(win, 'localStorage', webWorkerlocalStorage, $isSameOrigin$, env);
addStorageApi(win, 'sessionStorage', webWorkerSessionStorage, $isSameOrigin$, env);

if (!isSameOrigin) {
if (!$isSameOrigin$) {
win.indexeddb = undefined;
}

Expand Down Expand Up @@ -469,11 +472,26 @@ export const createWindow = (
}
set origin(_) {}

get parent() {
return proxyAncestorPostMessage(environments[$parentWinId$].$window$, $winId$);
get parent(): any {
for (let envWinId in environments) {
if (environments[envWinId].$winId$ === $parentWinId$) {
return environments[envWinId].$window$;
}
}
return this;
}

postMessage(...args: any[]) {
if (environments[args[0]]) {
if (len(postMessages) > 50) {
postMessages.splice(0, 5);
}
postMessages.push({
$winId$: args[0],
$data$: JSON.stringify(args[1]),
});
args = args.slice(1);
}
callMethod(this, ['postMessage'], args, CallType.NonBlockingNoSideEffect);
}

Expand All @@ -484,9 +502,11 @@ export const createWindow = (
get top(): any {
for (let envWinId in environments) {
if (environments[envWinId].$winId$ === environments[envWinId].$parentWinId$) {
return proxyAncestorPostMessage(environments[envWinId].$window$, $winId$);
// when winId and parentWinId are the same it's the top window
return environments[envWinId].$window$;
}
}
return this;
}

get window() {
Expand Down Expand Up @@ -550,26 +570,6 @@ export const createWindow = (
return env;
};

const proxyAncestorPostMessage = (parentWin: any, $winId$: WinId) =>
new Proxy<any>(parentWin, {
get: (targetParent, propName) => {
if (propName === 'postMessage') {
return (...args: any[]) => {
if (len(postMessages) > 20) {
postMessages.splice(0, 5);
}
postMessages.push({
$data$: JSON.stringify(args[0]),
$winId$,
});
targetParent.postMessage(...args);
};
} else {
return targetParent[propName];
}
},
});

// Trap Constructors are ones where all properties have
// proxy traps, such as dataset.name
const TrapConstructors: { [cstrName: string]: 1 } = {
Expand Down
4 changes: 2 additions & 2 deletions tests/platform/window/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ <h1>Window</h1>
<script type="text/partytown">
(function () {
const elm = document.getElementById('testTop');
elm.textContent = window.top.name === window.name;
elm.textContent = String(window.top === window);
})();
</script>
</li>
Expand All @@ -101,7 +101,7 @@ <h1>Window</h1>
<script type="text/partytown">
(function () {
const elm = document.getElementById('testParent');
elm.textContent = window.parent.name === window.name;
elm.textContent = String(window.parent === window);
})();
</script>
</li>
Expand Down
1 change: 1 addition & 0 deletions tests/unit/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ function createWorkerWindownEnvironment(ctx: TestContext) {
$location$: ctx.window.location,
$visibilityState$: 'visible',
$createNode$: () => null as any,
$isSameOrigin$: true,
};

return environments[ctx.winId];
Expand Down
38 changes: 32 additions & 6 deletions tests/unit/worker-exec.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,46 @@ import { suite } from './utils';

const test = suite();

test('add window id to postMessage() when cross-origin', ({ env, win, winId }) => {
env.$isSameOrigin$ = false;
let result = false;
win.parent.postMessage = function (postMessageWinId: string, msg: string) {
result = postMessageWinId === winId && msg === '88';
};
const s = `
parent.postMessage('88');
`;
run(env, s);
assert.is(result, true);
});

test('do not add window id to postMessage() when same-origin', ({ env, win }) => {
env.$isSameOrigin$ = true;
let result = '';
win.parent.postMessage = function (msg: string) {
result = msg;
};
const s = `
parent.postMessage('88');
`;
run(env, s);
assert.is(result, '88');
});

test('Class this', ({ env, win }) => {
const s = `
class Cls {
constructor() {
window.result = this === window;
class Cls {
constructor() {
window.result = this === window;
}
}
}
new Cls();
new Cls();
`;
run(env, s);
assert.is(win.result, false);
});

test.only('manually define global functions', ({ env, win, config }) => {
test('manually define global functions', ({ env, win, config }) => {
config.globalFns = ['abc', 'xyz'];
const s = `
function abc() {
Expand Down

1 comment on commit 833ba36

@vercel
Copy link

@vercel vercel bot commented on 833ba36 Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.