]> Lady’s Gitweb - Lemon/blob - window/mod.js
9ddbf4bd6055ddbedfd50140a1dc8c946b9de367
[Lemon] / window / mod.js
1 // 🍋🏷 Lemon ∷ window/mod.js
2 // ====================================================================
3 //
4 // Copyright © 2022 Lady [@ Lady’s Computer].
5 //
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
9
10 import { DOMImplementation, xhtmlNamespace } from "./deps.js";
11
12 { // Polyfill document.
13 globalThis.document = new DOMImplementation().createDocument(
14 xhtmlNamespace,
15 "html",
16 null,
17 );
18 const { documentElement } = document;
19 documentElement.appendChild(
20 document.createElementNS(xhtmlNamespace, "head"),
21 );
22 documentElement.appendChild(
23 document.createElementNS(xhtmlNamespace, "body"),
24 );
25 }
26
27 { // Polyfill `element.append`.
28 Object.getPrototypeOf(
29 globalThis.document.documentElement,
30 ).append = function (...children) {
31 for (const child of children) {
32 this.appendChild(
33 typeof child === "string"
34 ? this.ownerDocument.createTextNode(child)
35 : child,
36 );
37 }
38 };
39 }
40
41 { // Apply patches to `Node.nodeType` and `Node.normalize`.
42 const nodePrototype = Object.getPrototypeOf(
43 Object.getPrototypeOf(document.createDocumentFragment()),
44 );
45 const originalNodeTypeGetter = Object.getOwnPropertyDescriptor(
46 nodePrototype,
47 "nodeType",
48 )?.get ?? (() => {
49 const originalNodeTypeValue = nodePrototype.nodeType;
50 return () => originalNodeTypeValue;
51 })();
52 Object.defineProperty(nodePrototype, "nodeType", {
53 configurable: true,
54 enumerable: true,
55 /**
56 * To simulate restrictions on calling `nodeType` only on actual
57 * Nodes, check for inheritance first.
58 */
59 get() {
60 if (
61 !(() => {
62 // Test whether this object has the node prototype in its
63 // prototype chain.
64 for (
65 let prototype = this === Object(this)
66 ? Object.getPrototypeOf(this)
67 : null;
68 prototype != null;
69 prototype = Object.getPrototypeOf(prototype)
70 ) {
71 if (prototype === nodePrototype) {
72 // This object inherits from the Node prototype.
73 return true;
74 } else {
75 // This object is not yet known to inherits from the Node
76 // prototype.
77 continue;
78 }
79 }
80 })()
81 ) {
82 // This is not a Node.
83 throw new TypeError("nodeType requires this be a Node.");
84 } else {
85 // This is a Node; walk the prototype chain and attempt to get
86 // the node type.
87 for (
88 //deno-lint-ignore no-this-alias
89 let target = this;
90 target != null && target != nodePrototype;
91 target = Object.getPrototypeOf(target)
92 ) {
93 if (Object.hasOwn(target, "nodeType")) {
94 return Reflect.get(target, "nodeType", this);
95 } else {
96 continue;
97 }
98 }
99 return originalNodeTypeGetter.call(this);
100 }
101 },
102 set: undefined,
103 });
104 nodePrototype.normalize = function () {
105 let child = this.firstChild;
106 while (child) {
107 const next = child.nextSibling;
108 if (next && next.nodeType == 3 && child.nodeType == 3) {
109 this.removeChild(next);
110 child.appendData(next.data);
111 } else {
112 if (child.nodeType == 3 && !child.data) {
113 this.removeChild(child);
114 } else {
115 child.normalize();
116 }
117 child = next;
118 }
119 }
120 };
121 }
This page took 0.053941 seconds and 3 git commands to generate.