Skip to content

Commit

Permalink
global HTML constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Oct 1, 2021
1 parent fe8d685 commit 0a018c2
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 22 deletions.
1 change: 1 addition & 0 deletions scripts/minify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function managlePropsPlugin(): Plugin {
$firstScriptId$: '',
$forward$: '',
$forwardToWorkerAccess$: '',
$htmlConstructors$: '',
$immediateSetters$: '',
$importScripts$: '',
$instanceId$: '',
Expand Down
12 changes: 6 additions & 6 deletions src/lib/sandbox/messenger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@ import {
WorkerMessageType,
} from '../types';
import { initializedWorkerScript, readNextScript } from './read-main-scripts';
import { readMainInterfaces } from './read-interfaces';
import { readMainInterfaces } from './read-main-interfaces';

export const onMessageFromWebWorker = (
winCtx: MainWindowContext,
msg: MessageFromWorkerToSandbox
) => {
const msgType = msg[0];
const doc = winCtx.$window$.document;
const win = winCtx.$window$;
const doc = win.document;

if (msgType === WorkerMessageType.MainDataRequestFromWorker) {
// web worker has requested data from the main thread
const firstScriptId = getAndSetInstanceId(winCtx, doc.querySelector('script'));
const mainInterfaces = readMainInterfaces(winCtx.$window$, doc);
const initWebWorkerData: InitWebWorkerData = {
$winId$: winCtx.$winId$,
$parentWinId$: winCtx.$parentWinId$,
Expand All @@ -32,8 +31,9 @@ export const onMessageFromWebWorker = (
$documentReadyState$: doc.readyState,
$documentReferrer$: doc.referrer,
$documentTitle$: doc.title,
$firstScriptId$: firstScriptId,
$interfaces$: mainInterfaces,
$firstScriptId$: getAndSetInstanceId(winCtx, doc.querySelector('script')),
$htmlConstructors$: Object.getOwnPropertyNames(win).filter((c) => c.startsWith('HTML')),
$interfaces$: readMainInterfaces(win, doc),
$libPath$: new URL(winCtx.$libPath$, winCtx.$url$) + '',
$url$: winCtx.$url$,
};
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export interface InitWebWorkerData {
$documentReferrer$: string;
$documentTitle$: string;
$firstScriptId$: number;
$htmlConstructors$: string[];
$interfaces$: InterfaceInfo[];
$libPath$?: string;
$url$: string;
Expand Down
8 changes: 6 additions & 2 deletions src/lib/web-worker/init-worker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InitWebWorkerData, InterfaceType } from '../types';
import type { InitWebWorkerData } from '../types';
import { initWebWorkerGlobal } from './worker-global';
import { Location } from './worker-location';
import { logWorker, TOP_WIN_ID } from '../utils';
Expand All @@ -22,7 +22,11 @@ export const initWebWorker = (self: Worker, initWebWorkerData: InitWebWorkerData

webWorkerCtx.$location$ = new Location(initWebWorkerData.$url$);

initWebWorkerGlobal(self, initWebWorkerData.$interfaces$[InterfaceType.Window][1]);
initWebWorkerGlobal(
self,
initWebWorkerData.$interfaces$[0][1],
initWebWorkerData.$htmlConstructors$
);

webWorkerCtx.$isInitialized$ = true;
};
32 changes: 21 additions & 11 deletions src/lib/web-worker/worker-constructors.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { InterfaceType, NodeName } from '../types';
import { HTMLAnchorElement } from './worker-anchor';
import { HTMLDocument } from './worker-document';
import { HTMLElement } from './worker-element';
import { HTMLScriptElement } from './worker-script';
import { Node } from './worker-node';
import { Window, HTMLIFrameElement } from './worker-iframe';
import { WorkerDocumentElementChild, HTMLDocument } from './worker-document';
import { toUpper } from '../utils';
import { Window } from './worker-iframe';
import { WorkerProxy } from './worker-instance';

export const constructInstance = (
Expand Down Expand Up @@ -45,10 +44,21 @@ const getConstructor = (interfaceType: InterfaceType, nodeName?: string): typeof
};

export const getElementConstructor = (nodeName: string): typeof HTMLElement =>
({
A: HTMLAnchorElement,
BODY: WorkerDocumentElementChild,
HEAD: WorkerDocumentElementChild,
IFRAME: HTMLIFrameElement,
SCRIPT: HTMLScriptElement,
}[nodeName] || HTMLElement);
elementConstructors[nodeName] || HTMLElement;

export const elementConstructors: { [tagName: string]: typeof HTMLElement } = {};

export const getTagNameFromConstructor = (t: string) => {
t = toUpper(t.substr(4).replace('Element', ''));
if (t === 'IMAGE') {
return 'IMG';
} else if (t === 'PARAGRAPH') {
return 'P';
} else if (t === 'TABLEROW') {
return 'TR';
} else if (t === 'TableCell') {
return 'TD';
} else {
return t;
}
};
39 changes: 36 additions & 3 deletions src/lib/web-worker/worker-global.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { callMethod } from './worker-proxy';
import { constructInstance } from './worker-constructors';
import {
constructInstance,
elementConstructors,
getTagNameFromConstructor,
} from './worker-constructors';
import { HTMLAnchorElement } from './worker-anchor';
import { HTMLDocument, WorkerDocumentElementChild } from './worker-document';
import { HTMLElement } from './worker-element';
import { HTMLIFrameElement, Window } from './worker-iframe';
import { HTMLImageElement } from './worker-image';
import { HTMLScriptElement } from './worker-script';
import { InstanceIdKey, webWorkerCtx, WinIdKey } from './worker-constants';
import { InterfaceType, MemberTypeInfo, PlatformInstanceId } from '../types';
import { nextTick, TOP_WIN_ID } from '../utils';
import { Node } from './worker-node';
import { sendBeacon } from './worker-exec';

export const initWebWorkerGlobal = (self: any, windowMemberTypeInfo: MemberTypeInfo) => {
export const initWebWorkerGlobal = (
self: any,
windowMemberTypeInfo: MemberTypeInfo,
htmlCstrNames: string[]
) => {
self[WinIdKey] = webWorkerCtx.$winId$;
self[InstanceIdKey] = PlatformInstanceId.window;

Expand All @@ -29,7 +43,6 @@ export const initWebWorkerGlobal = (self: any, windowMemberTypeInfo: MemberTypeI
self.localStorage = constructInstance(InterfaceType.Storage, PlatformInstanceId.localStorage);
self.sessionStorage = constructInstance(InterfaceType.Storage, PlatformInstanceId.sessionStorage);

self.Image = HTMLImageElement;
navigator.sendBeacon = sendBeacon;

self.self = self.window = self;
Expand All @@ -45,4 +58,24 @@ export const initWebWorkerGlobal = (self: any, windowMemberTypeInfo: MemberTypeI

self.top = constructInstance(InterfaceType.Window, PlatformInstanceId.window, TOP_WIN_ID);
}

self.HTMLDocument = self.Document = HTMLDocument;
self.HTMLElement = self.Element = HTMLElement;
self.Image = HTMLImageElement;
self.Node = Node;
self.Window = Window;

htmlCstrNames.map((htmlCstrName) => {
if (!self[htmlCstrName]) {
elementConstructors[getTagNameFromConstructor(htmlCstrName)] = self[htmlCstrName] =
Object.defineProperty(class extends HTMLElement {}, 'name', {
value: htmlCstrName,
});
}
});

elementConstructors.A = self.HTMLAnchorElement = HTMLAnchorElement;
elementConstructors.BODY = elementConstructors.HEAD = WorkerDocumentElementChild;
elementConstructors.IFRAME = self.HTMLIFrameElement = HTMLIFrameElement;
elementConstructors.SCRIPT = self.HTMLScriptElement = HTMLScriptElement;
};
4 changes: 4 additions & 0 deletions tests/platform/anchor/anchor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ test('anchor', async ({ page }) => {
const testAnchor = page.locator('#testAnchor');
await expect(testAnchor).toHaveText('/platform/anchor/some/other/path');

await page.waitForSelector('.testAnchorConstructor');
const testAnchorConstructor = page.locator('#testAnchorConstructor');
await expect(testAnchorConstructor).toHaveText('HTMLAnchorElement HTMLAnchorElement');

await page.waitForSelector('.testCreateAnchorNoAppend');
const testCreateAnchorNoAppend = page.locator('#testCreateAnchorNoAppend');
await expect(testCreateAnchorNoAppend).toHaveText('/platform/anchor/no-append-child');
Expand Down
12 changes: 12 additions & 0 deletions tests/platform/anchor/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ <h1>Anchor</h1>
</script>
</li>

<li>
<strong>constructor.name</strong>
<div><a id="testAnchorConstructor"></a></div>
<script type="text/partytown">
(function () {
const elm = document.getElementById('testAnchorConstructor');
elm.className = 'testAnchorConstructor';
elm.textContent = elm.constructor.name + ' ' + HTMLAnchorElement.name;
})();
</script>
</li>

<li>
<strong>createElement('a'), no appendChild</strong>
<div id="testCreateAnchorNoAppend"></a>
Expand Down
3 changes: 3 additions & 0 deletions tests/platform/element/element.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ test('element', async ({ page }) => {
const testAttrsStyleValue = page.locator('#testAttrsStyleValue');
await expect(testAttrsStyleValue).toHaveText('color: red');
await expect(testAttrsStyleValue).toHaveCSS('color', 'rgb(255, 0, 0)');

const testParagraphConstructor = page.locator('#testParagraphConstructor');
await expect(testParagraphConstructor).toHaveText('HTMLParagraphElement HTMLParagraphElement');
});
11 changes: 11 additions & 0 deletions tests/platform/element/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,17 @@ <h1>Element</h1>
</script>
</li>

<li>
<strong>paragraph constructor.name</strong>
<div><p style="margin: 0; padding: 0" id="testParagraphConstructor"></p></div>
<script type="text/partytown">
(function () {
const elm = document.getElementById('testParagraphConstructor');
elm.textContent = elm.constructor.name + ' ' + HTMLParagraphElement.name;
})();
</script>
</li>

<script type="text/partytown">
(function () {
document.body.classList.add('completed');
Expand Down
37 changes: 37 additions & 0 deletions tests/platform/window/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,43 @@ <h1>Window</h1>
</script>
</li>

<li>
<strong>Window.name</strong>
<code id="testWindowName"></code>
<script type="text/partytown">
(function () {
const elm = document.getElementById('testWindowName');
elm.textContent = Window.name;
})();
</script>
</li>

<li>
<strong>Worker HTML Constructors</strong>
<code id="wwHTMLConstructors"></code>
<script type="text/partytown">
(function () {
const htmlCstrs = Object.getOwnPropertyNames(window).filter((c) => c.startsWith('HTML')).sort();
const elm = document.getElementById('wwHTMLConstructors');
elm.textContent = htmlCstrs.join(' ');
})();
</script>
</li>

<li>
<strong>Main HTML Constructors</strong>
<code id="mainHTMLConstructors"></code>
<script>
(function () {
const htmlCstrs = Object.getOwnPropertyNames(window)
.filter((c) => c.startsWith('HTML'))
.sort();
const elm = document.getElementById('mainHTMLConstructors');
elm.textContent = htmlCstrs.join(' ');
})();
</script>
</li>

<script type="text/partytown">
(function () {
document.body.classList.add('completed');
Expand Down
6 changes: 6 additions & 0 deletions tests/platform/window/window.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ test('window', async ({ page }) => {
await promptButton.click();
const testPrompt = page.locator('#testPrompt');
await expect(testPrompt).toHaveText('88');

const wwHTMLConstructors = page.locator('#wwHTMLConstructors');
const ww = await wwHTMLConstructors.innerText();
const mainHTMLConstructors = page.locator('#mainHTMLConstructors');
const main = await mainHTMLConstructors.innerText();
expect(ww).toBe(main);
});

1 comment on commit 0a018c2

@vercel
Copy link

@vercel vercel bot commented on 0a018c2 Oct 1, 2021

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.