Skip to content

Commit

Permalink
refactor: queue setters
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Oct 23, 2021
1 parent 854f5f4 commit a70799d
Show file tree
Hide file tree
Showing 18 changed files with 75 additions and 174 deletions.
1 change: 0 additions & 1 deletion scripts/minify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ function managlePropsPlugin(): Plugin {
$forwardedTriggers$: '',
$head$: '',
$htmlConstructors$: '',
$immediateSetters$: '',
$implementation$: '',
$interfaces$: '',
$instanceId$: '',
Expand Down
6 changes: 0 additions & 6 deletions src/lib/sandbox/main-access-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ export const mainAccessHandler = async (
if (instance) {
rtnValue = applyToInstance(worker, instance, applyPath);

if (task.$immediateSetters$) {
task.$immediateSetters$.map((immediateSetter) =>
applyToInstance(worker, rtnValue, immediateSetter)
);
}

if (task.$assignInstanceId$) {
setInstanceId(rtnValue, task.$assignInstanceId$);
}
Expand Down
1 change: 0 additions & 1 deletion src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ export interface MainAccessTask {
$interfaceType$: InterfaceType;
$applyPath$: ApplyPath;
$nodeName$?: string;
$immediateSetters$?: ApplyPath[];
$assignInstanceId$?: number;
}

Expand Down
8 changes: 7 additions & 1 deletion src/lib/web-worker/init-web-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { defineConstructorName, EMPTY_ARRAY, logWorker } from '../utils';
import { elementConstructors, getTagNameFromConstructor } from './worker-constructors';
import { HTMLAnchorElement } from './worker-anchor';
import { HTMLCanvasElement } from './worker-canvas';
import { HTMLElement } from './worker-element';
import { HTMLElement, HTMLSrcElement } from './worker-element';
import { HTMLDocument } from './worker-document';
import { HTMLIFrameElement } from './worker-iframe';
import { HTMLScriptElement } from './worker-script';
import { HTMLStyleElement } from './worker-style';
import type { InitWebWorkerData } from '../types';
import { Node } from './worker-node';
import { webWorkerCtx } from './worker-constants';

export const initWebWorker = (initWebWorkerData: InitWebWorkerData) => {
Expand All @@ -25,6 +27,10 @@ export const initWebWorker = (initWebWorkerData: InitWebWorkerData) => {

(self as any).postMessage = (self as any).importScripts = undefined;

(self as any).Node = Node;
(self as any).Element = (self as any).HTMLElement = HTMLSrcElement;
(self as any).Document = HTMLDocument;

// create the same HTMLElement constructors that were found on main's window
// and add each constructor to the elementConstructors map, to be used by windows later
webWorkerCtx.$htmlConstructors$.map(
Expand Down
1 change: 1 addition & 0 deletions src/lib/web-worker/worker-anchor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class HTMLAnchorElement extends HTMLElement {
return getUrl(this) + '';
}
set href(href: string) {
href = href + '';
setInstanceStateValue(this, StateProp.url, href);
setter(this, ['href'], href);
}
Expand Down
2 changes: 0 additions & 2 deletions src/lib/web-worker/worker-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ export const WinIdKey = Symbol();
export const InstanceIdKey = Symbol();
export const InterfaceTypeKey = Symbol();
export const NodeNameKey = Symbol();
export const ProxyKey = Symbol();
export const ImmediateSettersKey = Symbol();

export const webWorkerRefsByRefId: { [refId: number]: RefHandler } = {};
export const webWorkerRefIdsByRef = new WeakMap<RefHandler, number>();
Expand Down
3 changes: 1 addition & 2 deletions src/lib/web-worker/worker-constructors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { HTMLElement } from './worker-element';
import { InterfaceType, NodeName } from '../types';
import { Node } from './worker-node';
import { toUpper } from '../utils';
import { WorkerProxy } from './worker-proxy-constructor';

Expand Down Expand Up @@ -29,7 +28,7 @@ const getConstructor = (interfaceType: InterfaceType, nodeName?: string): typeof
if (interfaceType === InterfaceType.Element) {
return getElementConstructor(nodeName!);
} else if (interfaceType <= InterfaceType.DocumentFragmentNode) {
return Node;
return (self as any).Node;
} else {
return WorkerProxy;
}
Expand Down
22 changes: 7 additions & 15 deletions src/lib/web-worker/worker-document.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { ApplyPath, ApplyPathType, InterfaceType, NodeName } from '../types';
import { callMethod } from './worker-proxy';
import { callMethod, setter } from './worker-proxy';
import { constructInstance, getElementConstructor } from './worker-constructors';
import { createEnvironment, getEnv, getEnvWindow } from './worker-environment';
import { getPartytownScript } from './worker-exec';
import { HTMLElement } from './worker-element';
import { ImmediateSettersKey, WinIdKey } from './worker-constants';
import { InterfaceType, NodeName } from '../types';
import { SCRIPT_TYPE, randomId, toUpper, defineConstructorName } from '../utils';
import { serializeForMain } from './worker-serialization';
import { WinIdKey } from './worker-constants';

export class HTMLDocument extends HTMLElement {
get body() {
Expand All @@ -20,24 +19,17 @@ export class HTMLDocument extends HTMLElement {
const instanceId = randomId();
const ElementCstr = getElementConstructor(tagName);
const elm = new ElementCstr(InterfaceType.Element, instanceId, winId, tagName);
const immediateSetter: ApplyPath = (elm[ImmediateSettersKey] = []);

callMethod(this, ['createElement'], [tagName], instanceId);

if (tagName === NodeName.IFrame) {
// an iframe element's instanceId is the same as its contentWindow's winId
// and the contentWindow's parentWinId is the iframe element's winId
createEnvironment({ $winId$: instanceId, $parentWinId$: winId, $url$: 'about:blank' });

immediateSetter.push([
'srcdoc',
serializeForMain(winId, instanceId, getPartytownScript()),
ApplyPathType.SetValue,
]);
setter(elm, ['srcdoc'], getPartytownScript());
} else if (tagName === NodeName.Script) {
immediateSetter.push([
'type',
serializeForMain(winId, instanceId, SCRIPT_TYPE),
ApplyPathType.SetValue,
]);
setter(elm, ['type'], SCRIPT_TYPE);
}

return elm;
Expand Down
5 changes: 0 additions & 5 deletions src/lib/web-worker/worker-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
webWorkerCtx,
WinIdKey,
} from './worker-constants';
import { HTMLElement } from './worker-element';
import {
InitializeEnvironmentData,
InterfaceType,
Expand All @@ -20,7 +19,6 @@ import {
WorkerMessageType,
} from '../types';
import { Location } from './worker-location';
import { Node } from './worker-node';

export const createEnvironment = ({
$winId$,
Expand Down Expand Up @@ -188,10 +186,7 @@ export const createEnvironment = ({
win[memberName] = createGlobalConstructorProxy($winId$, interfaceType, memberName);
});

win.Document = HTMLDocument;
win.Element = win.HTMLElement = HTMLElement;
win.Image = createImageConstructor($winId$);
win.Node = Node;
win.Window = Window;

win.performance = self.performance;
Expand Down
46 changes: 4 additions & 42 deletions src/lib/web-worker/worker-exec.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import { debug, logWorker, nextTick, SCRIPT_TYPE, SCRIPT_TYPE_EXEC } from '../utils';
import {
ApplyPathType,
EventHandler,
InitializeScriptData,
WebWorkerEnvironment,
StateProp,
WorkerMessageType,
} from '../types';
import { debug, logWorker, nextTick, SCRIPT_TYPE, SCRIPT_TYPE_EXEC } from '../utils';
import {
environments,
ImmediateSettersKey,
InstanceIdKey,
webWorkerCtx,
WinIdKey,
} from './worker-constants';
import { environments, InstanceIdKey, webWorkerCtx, WinIdKey } from './worker-constants';
import { getEnv } from './worker-environment';
import { getInstanceStateValue, getStateValue, setStateValue } from './worker-state';
import type { HTMLElement } from './worker-element';
import type { Location } from './worker-location';
import type { Node } from './worker-node';
import { serializeForMain } from './worker-serialization';
import type { WorkerProxy } from './worker-proxy-constructor';

export const initNextScriptsInWebWorker = async (initScript: InitializeScriptData) => {
let winId = initScript.$winId$;
Expand Down Expand Up @@ -155,36 +147,6 @@ export const insertIframe = (iframe: Node) => {
callback();
};

export const insertScriptContent = (script: Node) => {
const scriptContent = getInstanceStateValue<string>(script, StateProp.innerHTML);

if (scriptContent) {
const winId = script[WinIdKey];
const instanceId = script[InstanceIdKey];
const immediateSetters = script[ImmediateSettersKey];
const errorMsg = runScriptContent(getEnv(script), instanceId, scriptContent, winId);
const datasetType = errorMsg ? 'pterror' : 'ptid';
const datasetValue = errorMsg || instanceId;

if (immediateSetters) {
immediateSetters.push(
[
'type',
serializeForMain(winId, instanceId, SCRIPT_TYPE + SCRIPT_TYPE_EXEC),
ApplyPathType.SetValue,
],
[
'dataset',
datasetType,
serializeForMain(winId, instanceId, datasetValue),
ApplyPathType.SetValue,
],
['innerHTML', serializeForMain(winId, instanceId, scriptContent), ApplyPathType.SetValue]
);
}
}
};

const resolveToUrl = (env: WebWorkerEnvironment, url?: string, baseLocation?: Location) => {
baseLocation = env.$location$;
while (!baseLocation.host) {
Expand All @@ -199,7 +161,7 @@ const resolveToUrl = (env: WebWorkerEnvironment, url?: string, baseLocation?: Lo

export const resolveUrl = (env: WebWorkerEnvironment, url?: string) => resolveToUrl(env, url) + '';

export const getUrl = (elm: HTMLElement) =>
export const getUrl = (elm: WorkerProxy) =>
resolveToUrl(getEnv(elm), getInstanceStateValue(elm, StateProp.url));

export const updateIframeContent = (url: string, html: string) =>
Expand Down
17 changes: 3 additions & 14 deletions src/lib/web-worker/worker-iframe.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { ApplyPathType, StateProp } from '../types';
import { environments, ImmediateSettersKey, InstanceIdKey } from './worker-constants';
import { environments, InstanceIdKey } from './worker-constants';
import { getEnv } from './worker-environment';
import { getInstanceStateValue, setInstanceStateValue } from './worker-state';
import { HTMLSrcElement } from './worker-element';
import { resolveUrl, updateIframeContent } from './worker-exec';
import { serializeInstanceForMain } from './worker-serialization';
import { setter } from './worker-proxy';
import { StateProp } from '../types';

export class HTMLIFrameElement extends HTMLSrcElement {
get contentDocument() {
Expand All @@ -25,7 +24,6 @@ export class HTMLIFrameElement extends HTMLSrcElement {
}
set src(url: string) {
let xhr = new XMLHttpRequest();
let iframeContent: string;
let xhrStatus: number;

url = resolveUrl(getEnv(this), url);
Expand All @@ -38,16 +36,7 @@ export class HTMLIFrameElement extends HTMLSrcElement {
xhrStatus = xhr.status;

if (xhrStatus > 199 && xhrStatus < 300) {
iframeContent = updateIframeContent(url, xhr.responseText);
if (this[ImmediateSettersKey]) {
this[ImmediateSettersKey]!.push([
'srcdoc',
serializeInstanceForMain(this, iframeContent),
ApplyPathType.SetValue,
]);
} else {
setter(this, ['srcdoc'], iframeContent);
}
setter(this, ['srcdoc'], updateIframeContent(url, xhr.responseText));
} else {
setInstanceStateValue(this, StateProp.loadErrorStatus, xhrStatus);
}
Expand Down
26 changes: 18 additions & 8 deletions src/lib/web-worker/worker-node.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { applyBeforeSyncSetters, callMethod } from './worker-proxy';
import { callMethod, setter } from './worker-proxy';
import { getEnv } from './worker-environment';
import type { HTMLDocument } from './worker-document';
import { insertIframe, insertScriptContent } from './worker-exec';
import { insertIframe, runScriptContent } from './worker-exec';
import {
InstanceIdKey,
InterfaceTypeKey,
NodeNameKey,
webWorkerCtx,
WinIdKey,
} from './worker-constants';
import { NodeName, WorkerMessageType } from '../types';
import { NodeName, StateProp, WorkerMessageType } from '../types';
import { getInstanceStateValue } from './worker-state';
import type { HTMLDocument } from './worker-document';
import { SCRIPT_TYPE, SCRIPT_TYPE_EXEC } from '../utils';
import { WorkerProxy } from './worker-proxy-constructor';

export class Node extends WorkerProxy {
Expand All @@ -36,12 +38,20 @@ export class Node extends WorkerProxy {
const isIFrame = nodeName === NodeName.IFrame;

if (isScript) {
insertScriptContent(newNode);
}
const scriptContent = getInstanceStateValue<string>(newNode, StateProp.innerHTML);

applyBeforeSyncSetters(newNode);
if (scriptContent) {
const errorMsg = runScriptContent(getEnv(newNode), instanceId, scriptContent, winId);
const datasetType = errorMsg ? 'pterror' : 'ptid';
const datasetValue = errorMsg || instanceId;

setter(newNode, ['type'], SCRIPT_TYPE + SCRIPT_TYPE_EXEC);
setter(newNode, ['dataset', datasetType], datasetValue);
setter(newNode, ['innerHTML'], scriptContent);
}
}

newNode = callMethod(this, ['insertBefore'], [newNode, referenceNode], undefined, instanceId);
newNode = callMethod(this, ['insertBefore'], [newNode, referenceNode]);

if (isIFrame) {
insertIframe(newNode);
Expand Down
12 changes: 2 additions & 10 deletions src/lib/web-worker/worker-proxy-constructor.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import type { ApplyPath, InterfaceType } from '../types';
import {
ImmediateSettersKey,
InstanceIdKey,
InterfaceTypeKey,
NodeNameKey,
WinIdKey,
} from './worker-constants';
import type { InterfaceType } from '../types';
import { InstanceIdKey, InterfaceTypeKey, NodeNameKey, WinIdKey } from './worker-constants';
import { proxy } from './worker-proxy';

export class WorkerProxy {
[WinIdKey]: number;
[InstanceIdKey]: number;
[InterfaceTypeKey]: InterfaceType;
[NodeNameKey]: string | undefined;
[ImmediateSettersKey]: ApplyPath | undefined;

constructor(interfaceType: InterfaceType, instanceId: number, winId?: number, nodeName?: string) {
this[WinIdKey] = winId!;
this[InstanceIdKey] = instanceId!;
this[NodeNameKey] = nodeName;
this[ImmediateSettersKey] = undefined;
return proxy((this[InterfaceTypeKey] = interfaceType), this, []);
}
}
Loading

1 comment on commit a70799d

@vercel
Copy link

@vercel vercel bot commented on a70799d Oct 23, 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.