X-Git-Url: https://git.ladys.computer/Lemon/blobdiff_plain/0bcf6926ddc22baf9ba097bf644c908ffcf12c3f..3cfb1515952fbda9622c2a5d4d7b9925db1a03e3:/window/mod.js diff --git a/window/mod.js b/window/mod.js new file mode 100644 index 0000000..5e97d4f --- /dev/null +++ b/window/mod.js @@ -0,0 +1,101 @@ +// 🍋🏷 Lemon ∷ window/mod.js +// ==================================================================== +// +// Copyright © 2022 Lady [@ Lady’s Computer]. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at . + +import { DOMImplementation, Node, xhtmlNamespace } from "./deps.js"; + +{ // Polyfill document. + globalThis.document = new DOMImplementation().createDocument( + xhtmlNamespace, + "html", + null, + ); + const { documentElement } = document; + documentElement.appendChild( + document.createElementNS(xhtmlNamespace, "head"), + ); + documentElement.appendChild( + document.createElementNS(xhtmlNamespace, "body"), + ); +} + +{ // Polyfill `element.append`. + Object.getPrototypeOf( + globalThis.document.documentElement, + ).append = function (...children) { + for (const child of children) { + this.appendChild( + typeof child === "string" + ? this.ownerDocument.createTextNode(child) + : child, + ); + } + }; +} + +{ // Apply patches to `Node.nodeType` and `Node.normalize`. + const { TEXT_NODE, prototype: nodePrototype } = Node; + const originalNodeTypeGetter = Object.getOwnPropertyDescriptor( + nodePrototype, + "nodeType", + )?.get ?? (() => { + const originalNodeTypeValue = nodePrototype.nodeType; + return () => originalNodeTypeValue; + })(); + Object.defineProperty(nodePrototype, "nodeType", { + configurable: true, + enumerable: true, + /** + * To simulate restrictions on calling `nodeType` only on actual + * Nodes, check for inheritance first. + */ + get() { + if (!(this instanceof Node)) { + // This is not a Node. + throw new TypeError("nodeType requires this be a Node."); + } else { + // This is a Node; walk the prototype chain and attempt to get + // the node type. + for ( + //deno-lint-ignore no-this-alias + let target = this; + target != null && target != nodePrototype; + target = Object.getPrototypeOf(target) + ) { + if (Object.hasOwn(target, "nodeType")) { + return Reflect.get(target, "nodeType", this); + } else { + continue; + } + } + return originalNodeTypeGetter.call(this); + } + }, + set: undefined, + }); + nodePrototype.normalize = function () { + let child = this.firstChild; + while (child) { + const next = child.nextSibling; + if ( + next && next.nodeType == TEXT_NODE && + child.nodeType == TEXT_NODE + ) { + this.removeChild(next); + child.appendData(next.data); + } else { + if (child.nodeType == TEXT_NODE && !child.data) { + this.removeChild(child); + } else { + child.normalize(); + } + child = next; + } + } + }; +}