Skip to content

Commit

Permalink
fix: NodeList is not defined on window (#272)
Browse files Browse the repository at this point in the history
  • Loading branch information
itxch committed Oct 3, 2022
1 parent 7690c31 commit f24fd22
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 5 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ node_modules/
/utils/
/index.cjs
/index.mjs
/index.d.ts
/index.d.ts
.idea
11 changes: 8 additions & 3 deletions src/lib/web-worker/worker-serialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
webWorkerRefsByRefId,
WinIdKey,
} from './worker-constants';
import { getConstructorName, len, noop } from '../utils';
import { defineConstructorName, getConstructorName, len, noop } from '../utils';
import { getOrCreateNodeInstance } from './worker-constructors';
import { setWorkerRef } from './worker-state';

Expand Down Expand Up @@ -147,7 +147,8 @@ export const deserializeFromMain = (

if (serializedType === SerializedType.Function) {
if (winId && applyPath.length > 0) {
return (...args: any[]) => callMethod(environments[winId].$window$, applyPath, args, CallType.Blocking);
return (...args: any[]) =>
callMethod(environments[winId].$window$, applyPath, args, CallType.Blocking);
}

return noop;
Expand Down Expand Up @@ -278,7 +279,7 @@ class CustomError extends Error {
}
}

const NodeList = class {
export class NodeList {
private _: WorkerNode[];

constructor(nodes: WorkerNode[]) {
Expand All @@ -305,6 +306,10 @@ const NodeList = class {
[Symbol.iterator]() {
return this._[Symbol.iterator]();
}
}

export const createNodeListCstr = (win: any) => {
win.NodeList = defineConstructorName(NodeList, 'NodeList');
};

const Attr = class {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/web-worker/worker-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import { patchHTMLIFrameElement } from './worker-iframe';
import { patchHTMLScriptElement } from './worker-script';
import { patchSvgElement } from './worker-svg';
import { resolveUrl } from './worker-exec';
import { createNodeListCstr } from './worker-serialization';

export const createWindow = (
$winId$: WinId,
Expand Down Expand Up @@ -198,6 +199,7 @@ export const createWindow = (
win.name = name + (debug ? `${normalizedWinId($winId$)} (${$winId$})` : ($winId$ as any));

createNodeCstr(win, env, WorkerBase);
createNodeListCstr(win);
createCSSStyleDeclarationCstr(win, WorkerBase, 'CSSStyleDeclaration');
createPerformanceConstructor(win, WorkerBase, 'Performance');
createCustomElementRegistry(win, nodeCstrs);
Expand Down
5 changes: 4 additions & 1 deletion tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ <h2>Platform Tests</h2>
<li><a href="/tests/platform/mutation-observer/">MutationObserver</a></li>
<li><a href="/tests/platform/navigator/">Navigator</a></li>
<li><a href="/tests/platform/node/">Node</a></li>
<li><a href="/tests/platform/node-list/">NodeList</a></li>
<li><a href="/tests/platform/no-partytown-script/">No Partytown</a></li>
<li><a href="/tests/platform/resize-observer/">ResizeObserver</a></li>
<li><a href="/tests/platform/screen/">Screen</a></li>
Expand All @@ -117,7 +118,9 @@ <h2>Service Integration Tests</h2>
<li><a href="/tests/integrations/config/">Config</a></li>
<li><a href="/tests/integrations/event-forwarding/">Event Forwarding</a></li>
<li><a href="/tests/integrations/main-window-accessors/">Main Window Accessors</a></li>
<li><a href="/tests/integrations/load-scripts-on-main-thread/">Load Scripts on Main Thread</a></li>
<li>
<a href="/tests/integrations/load-scripts-on-main-thread/">Load Scripts on Main Thread</a>
</li>
<li><a href="/tests/integrations/facebook-pixel/">Facebook Pixel</a></li>
<li><a href="/tests/integrations/gtm/">Google Tag Manager (GTM)</a></li>
<li><a href="/tests/integrations/javascript-request/">Javascript Request Execution</a></li>
Expand Down
242 changes: 242 additions & 0 deletions tests/platform/node-list/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Partytown Test Page" />
<title>NodeList</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif,
Apple Color Emoji, Segoe UI Emoji;
font-size: 12px;
}
h1 {
margin: 0 0 15px 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
a {
display: block;
padding: 16px 8px;
}
a:link,
a:visited {
text-decoration: none;
color: blue;
}
a:hover {
background-color: #eee;
}
li {
display: flex;
margin: 15px 0;
}
li strong,
li code,
li button {
white-space: nowrap;
flex: 1;
margin: 0 5px;
}
</style>
<script>
partytown = {
logCalls: true,
logGetters: true,
logSetters: true,
logStackTraces: false,
logScriptExecution: true,
logMainAccess: true,
};
</script>
<script src="/~partytown/debug/partytown.js"></script>
</head>
<body>
<h1>NodeList</h1>
<ul>
<li>
<strong>NodeList is defined</strong>
<code id="testNodeList"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

const isNodeListDefined = Boolean(NodeList && nodeList instanceof NodeList);

document.getElementById('testNodeList').textContent += String(isNodeListDefined);
})();
</script>
</li>

<li>
<strong>entries()</strong>
<code id="testNodeListEntries"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

for (const [index, node] of nodeList.entries()) {
document.getElementById('testNodeListEntries').textContent +=
index + ' ' + node.nodeName + ' ';
}
})();
</script>
</li>

<li>
<strong>forEach()</strong>
<code id="testNodeListForEach"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

nodeList.forEach((childNode) => {
document.getElementById('testNodeListForEach').textContent +=
childNode.nodeName + ' ';
});
})();
</script>
</li>

<li>
<strong>item()</strong>
<code id="testNodeListItem"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

document.getElementById('testNodeListItem').textContent +=
nodeList.item(0).nodeName + ' ';
document.getElementById('testNodeListItem').textContent +=
nodeList.item(1).nodeName + ' ';
document.getElementById('testNodeListItem').textContent += nodeList.item(2).nodeName;
})();
</script>
</li>

<li>
<strong>keys()</strong>
<code id="testNodeListKeys"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

for (const key of nodeList.keys()) {
document.getElementById('testNodeListKeys').textContent += key + ' ';
}
})();
</script>
</li>

<li>
<strong>length</strong>
<code id="testNodeListLength"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

document.getElementById('testNodeListLength').textContent = String(nodeList.length);
})();
</script>
</li>

<li>
<strong>values()</strong>
<code id="testNodeListValues"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

for (const value of nodeList.values()) {
document.getElementById('testNodeListValues').textContent += value.nodeName + ' ';
}
})();
</script>
</li>

<li>
<strong>Symbol.iterator</strong>
<code id="testNodeListSymbolIterator"></code>
<script type="text/partytown">
(function () {
const parentNode = document.createElement('div');
const childNodeOne = document.createElement('p');
const childNodeTwo = document.createElement('a');
const childNodeThree = document.createElement('span');
parentNode.appendChild(childNodeOne);
parentNode.appendChild(childNodeTwo);
parentNode.appendChild(childNodeThree);
const nodeList = parentNode.childNodes;

for (const value of nodeList[Symbol.iterator]()) {
document.getElementById('testNodeListSymbolIterator').textContent +=
value.nodeName + ' ';
}
})();
</script>
</li>

<script type="text/partytown">
(function () {
document.body.className = 'completed';
})();
</script>
</ul>

<hr />
<p><a href="/tests/">All Tests</a></p>
</body>
</html>
31 changes: 31 additions & 0 deletions tests/platform/node-list/node-list.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { test, expect } from '@playwright/test';

test('node-list', async ({ page }) => {
await page.goto('/tests/platform/node-list/');

await page.waitForSelector('.completed');

const testNodeList = page.locator('#testNodeList');
await expect(testNodeList).toHaveText('true');

const testNodeListEntries = page.locator('#testNodeListEntries');
await expect(testNodeListEntries).toHaveText('0 P 1 A 2 SPAN');

const testNodeListForEach = page.locator('#testNodeListForEach');
await expect(testNodeListForEach).toHaveText('P A SPAN');

const testNodeListItem = page.locator('#testNodeListItem');
await expect(testNodeListItem).toHaveText('P A SPAN');

const testNodeListKeys = page.locator('#testNodeListKeys');
await expect(testNodeListKeys).toHaveText('0 1 2');

const testNodeListLength = page.locator('#testNodeListLength');
await expect(testNodeListLength).toHaveText('3');

const testNodeListValues = page.locator('#testNodeListValues');
await expect(testNodeListValues).toHaveText('P A SPAN');

const testNodeListSymbolIterator = page.locator('#testNodeListSymbolIterator');
await expect(testNodeListSymbolIterator).toHaveText('P A SPAN');
});

1 comment on commit f24fd22

@vercel
Copy link

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