@remote-dom/polyfill 0.0.0-preview-20240219211553

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE.md +7 -0
  3. package/README.md +45 -0
  4. package/build/esm/Attr.mjs +52 -0
  5. package/build/esm/CharacterData.mjs +27 -0
  6. package/build/esm/ChildNode.mjs +42 -0
  7. package/build/esm/Comment.mjs +9 -0
  8. package/build/esm/CustomElementRegistry.mjs +33 -0
  9. package/build/esm/CustomEvent.mjs +26 -0
  10. package/build/esm/Document.mjs +89 -0
  11. package/build/esm/DocumentFragment.mjs +10 -0
  12. package/build/esm/Element.mjs +95 -0
  13. package/build/esm/Event.mjs +108 -0
  14. package/build/esm/EventTarget.mjs +99 -0
  15. package/build/esm/HTMLElement.mjs +5 -0
  16. package/build/esm/HTMLTemplateElement.mjs +24 -0
  17. package/build/esm/MutationObserver.mjs +5 -0
  18. package/build/esm/NamedNodeMap.mjs +121 -0
  19. package/build/esm/Node.mjs +100 -0
  20. package/build/esm/NodeList.mjs +7 -0
  21. package/build/esm/ParentNode.mjs +128 -0
  22. package/build/esm/SVGElement.mjs +17 -0
  23. package/build/esm/Text.mjs +9 -0
  24. package/build/esm/Window.mjs +66 -0
  25. package/build/esm/constants.mjs +39 -0
  26. package/build/esm/hooks.mjs +3 -0
  27. package/build/esm/index.mjs +2 -0
  28. package/build/esm/selectors.mjs +197 -0
  29. package/build/esm/serialization.mjs +92 -0
  30. package/build/esm/shared.mjs +55 -0
  31. package/build/esnext/Attr.esnext +57 -0
  32. package/build/esnext/CharacterData.esnext +27 -0
  33. package/build/esnext/ChildNode.esnext +47 -0
  34. package/build/esnext/Comment.esnext +9 -0
  35. package/build/esnext/CustomElementRegistry.esnext +34 -0
  36. package/build/esnext/CustomEvent.esnext +25 -0
  37. package/build/esnext/Document.esnext +86 -0
  38. package/build/esnext/DocumentFragment.esnext +10 -0
  39. package/build/esnext/Element.esnext +99 -0
  40. package/build/esnext/Event.esnext +109 -0
  41. package/build/esnext/EventTarget.esnext +99 -0
  42. package/build/esnext/HTMLElement.esnext +6 -0
  43. package/build/esnext/HTMLTemplateElement.esnext +26 -0
  44. package/build/esnext/MutationObserver.esnext +5 -0
  45. package/build/esnext/NamedNodeMap.esnext +131 -0
  46. package/build/esnext/Node.esnext +116 -0
  47. package/build/esnext/NodeList.esnext +7 -0
  48. package/build/esnext/ParentNode.esnext +138 -0
  49. package/build/esnext/SVGElement.esnext +17 -0
  50. package/build/esnext/Text.esnext +9 -0
  51. package/build/esnext/Window.esnext +59 -0
  52. package/build/esnext/constants.esnext +37 -0
  53. package/build/esnext/hooks.esnext +3 -0
  54. package/build/esnext/index.esnext +2 -0
  55. package/build/esnext/selectors.esnext +169 -0
  56. package/build/esnext/serialization.esnext +76 -0
  57. package/build/esnext/shared.esnext +59 -0
  58. package/build/tsconfig.tsbuildinfo +1 -0
  59. package/build/typescript/Attr.d.ts +24 -0
  60. package/build/typescript/Attr.d.ts.map +1 -0
  61. package/build/typescript/CharacterData.d.ts +10 -0
  62. package/build/typescript/CharacterData.d.ts.map +1 -0
  63. package/build/typescript/ChildNode.d.ts +10 -0
  64. package/build/typescript/ChildNode.d.ts.map +1 -0
  65. package/build/typescript/Comment.d.ts +7 -0
  66. package/build/typescript/Comment.d.ts.map +1 -0
  67. package/build/typescript/CustomElementRegistry.d.ts +9 -0
  68. package/build/typescript/CustomElementRegistry.d.ts.map +1 -0
  69. package/build/typescript/CustomEvent.d.ts +17 -0
  70. package/build/typescript/CustomEvent.d.ts.map +1 -0
  71. package/build/typescript/Document.d.ts +27 -0
  72. package/build/typescript/Document.d.ts.map +1 -0
  73. package/build/typescript/DocumentFragment.d.ts +8 -0
  74. package/build/typescript/DocumentFragment.d.ts.map +1 -0
  75. package/build/typescript/Element.d.ts +32 -0
  76. package/build/typescript/Element.d.ts.map +1 -0
  77. package/build/typescript/Event.d.ts +47 -0
  78. package/build/typescript/Event.d.ts.map +1 -0
  79. package/build/typescript/EventTarget.d.ts +12 -0
  80. package/build/typescript/EventTarget.d.ts.map +1 -0
  81. package/build/typescript/HTMLElement.d.ts +4 -0
  82. package/build/typescript/HTMLElement.d.ts.map +1 -0
  83. package/build/typescript/HTMLTemplateElement.d.ts +11 -0
  84. package/build/typescript/HTMLTemplateElement.d.ts.map +1 -0
  85. package/build/typescript/MutationObserver.d.ts +3 -0
  86. package/build/typescript/MutationObserver.d.ts.map +1 -0
  87. package/build/typescript/NamedNodeMap.d.ts +18 -0
  88. package/build/typescript/NamedNodeMap.d.ts.map +1 -0
  89. package/build/typescript/Node.d.ts +37 -0
  90. package/build/typescript/Node.d.ts.map +1 -0
  91. package/build/typescript/NodeList.d.ts +4 -0
  92. package/build/typescript/NodeList.d.ts.map +1 -0
  93. package/build/typescript/ParentNode.d.ts +18 -0
  94. package/build/typescript/ParentNode.d.ts.map +1 -0
  95. package/build/typescript/SVGElement.d.ts +7 -0
  96. package/build/typescript/SVGElement.d.ts.map +1 -0
  97. package/build/typescript/Text.d.ts +7 -0
  98. package/build/typescript/Text.d.ts.map +1 -0
  99. package/build/typescript/Window.d.ts +45 -0
  100. package/build/typescript/Window.d.ts.map +1 -0
  101. package/build/typescript/constants.d.ts +35 -0
  102. package/build/typescript/constants.d.ts.map +1 -0
  103. package/build/typescript/hooks.d.ts +13 -0
  104. package/build/typescript/hooks.d.ts.map +1 -0
  105. package/build/typescript/index.d.ts +3 -0
  106. package/build/typescript/index.d.ts.map +1 -0
  107. package/build/typescript/selectors.d.ts +32 -0
  108. package/build/typescript/selectors.d.ts.map +1 -0
  109. package/build/typescript/serialization.d.ts +6 -0
  110. package/build/typescript/serialization.d.ts.map +1 -0
  111. package/build/typescript/shared.d.ts +16 -0
  112. package/build/typescript/shared.d.ts.map +1 -0
  113. package/package.json +35 -0
  114. package/rollup.config.js +3 -0
  115. package/source/Attr.ts +70 -0
  116. package/source/CharacterData.ts +29 -0
  117. package/source/ChildNode.ts +45 -0
  118. package/source/Comment.ts +7 -0
  119. package/source/CustomElementRegistry.ts +52 -0
  120. package/source/CustomEvent.ts +30 -0
  121. package/source/Document.ts +112 -0
  122. package/source/DocumentFragment.ts +8 -0
  123. package/source/Element.ts +119 -0
  124. package/source/Event.ts +142 -0
  125. package/source/EventTarget.ts +139 -0
  126. package/source/HTMLElement.ts +3 -0
  127. package/source/HTMLTemplateElement.ts +28 -0
  128. package/source/MutationObserver.ts +3 -0
  129. package/source/NamedNodeMap.ts +156 -0
  130. package/source/Node.ts +139 -0
  131. package/source/NodeList.ts +5 -0
  132. package/source/ParentNode.ts +158 -0
  133. package/source/SVGElement.ts +16 -0
  134. package/source/Text.ts +7 -0
  135. package/source/Window.ts +64 -0
  136. package/source/constants.ts +37 -0
  137. package/source/hooks.ts +28 -0
  138. package/source/index.ts +2 -0
  139. package/source/selectors.ts +230 -0
  140. package/source/serialization.ts +110 -0
  141. package/source/shared.ts +80 -0
  142. package/tsconfig.json +10 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # @remote-dom/polyfill
2
+
3
+ ## 0.0.0-preview-20240219211553
4
+
5
+ ### Major Changes
6
+
7
+ - First release of Remote DOM. Read more about this [refactor of remote-ui on native DOM APIs](https://github.com/Shopify/remote-dom/discussions/267), and take a look at the [updated documentation](/README.md).
8
+
9
+ ## 1.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - [`37be652`](https://github.com/Shopify/remote-dom/commit/37be652f288d1eec170c0be13b2da516f8db5dcf) Thanks [@lemonmade](https://github.com/lemonmade)! - First release of Remote DOM. Read more about this [refactor of remote-ui on native DOM APIs](https://github.com/Shopify/remote-dom/discussions/267), and take a look at the [updated documentation](/README.md).
14
+
15
+ ## 0.1.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [`7061ded`](https://github.com/Shopify/remote-dom/commit/7061ded1da4699c6dd6a820eeb940a8af7c66d82) Thanks [@lemonmade](https://github.com/lemonmade)! - Test minor bump
20
+
21
+ ## 0.0.2
22
+
23
+ ### Patch Changes
24
+
25
+ - [#251](https://github.com/Shopify/remote-dom/pull/251) [`5939cca`](https://github.com/Shopify/remote-dom/commit/5939cca8112417124327bd26f9e2c21f4bf9b20a) Thanks [@lemonmade](https://github.com/lemonmade)! - Test version bump
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2020-present, Shopify Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # `@remote-dom/polyfill`
2
+
3
+ A polyfill for the browser APIs used by Remote DOM. This allows you to use Remote DOM in environments that don’t have a native DOM, like [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API).
4
+
5
+ This package provides a low-level polyfill, with hooks that allow other libraries to intercept changes to the DOM. Unless you know you need this package, you probably want to import from [`@remote-dom/core/polyfill`](../core/README.md#remote-domcorepolyfill) instead, which uses the hooks provided by this library to automatically synchronize remote elements between environments.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm install @remote-dom/polyfill --save # npm
11
+ pnpm install @remote-dom/polyfill --save # pnpm
12
+ yarn add @remote-dom/polyfill # yarn
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ This package provides a `Window` class, which implements a limited subset of the [`Window` browser interface](https://developer.mozilla.org/en-US/docs/Web/API/Window). You’ll create an instance of the `Window` class and install it to the global environment using the `Window.setGlobal()` method.
18
+
19
+ ```ts
20
+ import {Window} from '@remote-dom/polyfill';
21
+
22
+ const window = new Window();
23
+ Window.setGlobal(window);
24
+
25
+ // Now you can use many important DOM APIs, like `document` and `Element`:
26
+ const div = document.createElement('div');
27
+ ```
28
+
29
+ This process will install polyfilled versions of the following globals:
30
+
31
+ - [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window/window), [`parent`](https://developer.mozilla.org/en-US/docs/Web/API/Window/parent), [`top`](https://developer.mozilla.org/en-US/docs/Web/API/Window/top), and [`self`](https://developer.mozilla.org/en-US/docs/Web/API/Window/self) which are all references to the `Window` instance (`self` is only overwritten when it is not already defined, to avoid overwriting the Web Worker `self` binding).
32
+ - [`document`](https://developer.mozilla.org/en-US/docs/Web/API/Window/document)
33
+ - [`customElements`](https://developer.mozilla.org/en-US/docs/Web/API/Window/customElements)
34
+ - [`location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location) and [`navigator`](https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator), though these are just set to `globalThis.location` and `globalThis.navigator`.
35
+ - The [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event), [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget), [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent), [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node), [`ParentNode`](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode), [`ChildNode`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode), [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document), [`DocumentFragment`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment), [`CharacterData`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData), [`Comment`](https://developer.mozilla.org/en-US/docs/Web/API/Comment), [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text), [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element), [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement), [`SVGElement`](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement), [`HTMLTemplateElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement), and [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) constructors.
36
+
37
+ This polyfill lets you hook into many of the operations that happen in the DOM, like creating elements, updating attributes, and adding event listeners. You define these hooks by overwriting any of the properties on the `hooks` export of this library.
38
+
39
+ ```ts
40
+ import {hooks} from '@remote-dom/polyfill';
41
+
42
+ hooks.createElement = (element) => {
43
+ console.log('Creating element:', element);
44
+ };
45
+ ```
@@ -0,0 +1,52 @@
1
+ import { hooks } from './hooks.mjs';
2
+ import { NodeType, NS, NEXT, OWNER_ELEMENT, NAME, VALUE } from './constants.mjs';
3
+ import { Node } from './Node.mjs';
4
+
5
+ class Attr extends Node {
6
+ nodeType = NodeType.ATTRIBUTE_NODE;
7
+ [NS] = null;
8
+ [NEXT] = null;
9
+ [OWNER_ELEMENT] = null;
10
+ isConnected = false;
11
+ constructor(name, value, namespace) {
12
+ super();
13
+ this[NAME] = name;
14
+ this[VALUE] = value;
15
+ if (namespace) this[NS] = namespace;
16
+ }
17
+ get nodeName() {
18
+ return this[NAME];
19
+ }
20
+ set nodeName(_readonly) {}
21
+ get name() {
22
+ return this[NAME];
23
+ }
24
+ set name(_readonly) {}
25
+ get value() {
26
+ return this[VALUE];
27
+ }
28
+ set value(value) {
29
+ const str = String(value);
30
+ this[VALUE] = str;
31
+ const ownerElement = this[OWNER_ELEMENT];
32
+ if (!ownerElement) return;
33
+ hooks.setAttribute?.(ownerElement, this[NAME], str, this[NS]);
34
+ }
35
+ get nodeValue() {
36
+ return this.value;
37
+ }
38
+ set nodeValue(value) {
39
+ this.value = value;
40
+ }
41
+ get ownerElement() {
42
+ return this[OWNER_ELEMENT];
43
+ }
44
+ get namespaceURI() {
45
+ return this[NS];
46
+ }
47
+ get specified() {
48
+ return true;
49
+ }
50
+ }
51
+
52
+ export { Attr };
@@ -0,0 +1,27 @@
1
+ import { hooks } from './hooks.mjs';
2
+ import { DATA } from './constants.mjs';
3
+ import { ChildNode } from './ChildNode.mjs';
4
+
5
+ class CharacterData extends ChildNode {
6
+ [DATA] = '';
7
+ constructor(data) {
8
+ super();
9
+ this.setData(data);
10
+ }
11
+ setData(data) {
12
+ let str = '';
13
+ if (data != null) {
14
+ str = typeof data === 'string' ? data : String(data);
15
+ }
16
+ this[DATA] = str;
17
+ hooks.setText?.(this, str);
18
+ }
19
+ get data() {
20
+ return this[DATA];
21
+ }
22
+ set data(data) {
23
+ this.setData(data);
24
+ }
25
+ }
26
+
27
+ export { CharacterData };
@@ -0,0 +1,42 @@
1
+ import { NEXT } from './constants.mjs';
2
+ import { Node } from './Node.mjs';
3
+
4
+ class ChildNode extends Node {
5
+ remove() {
6
+ const parent = this.parentNode;
7
+ if (!parent) return;
8
+ parent.removeChild(this);
9
+ }
10
+ replaceWith(...nodes) {
11
+ const parent = this.parentNode;
12
+ if (!parent) return;
13
+ const node = toNode(parent, nodes[0]);
14
+ const next = node[NEXT];
15
+ parent.replaceChild(this, node);
16
+ for (let i = 1; i < nodes.length; i++) {
17
+ parent.insertBefore(toNode(parent, nodes[i]), next);
18
+ }
19
+ }
20
+ before(...nodes) {
21
+ const parent = this.parentNode;
22
+ if (!parent) return;
23
+ for (const node of nodes) {
24
+ parent.insertBefore(toNode(parent, node), this);
25
+ }
26
+ }
27
+ after(...nodes) {
28
+ const parent = this.parentNode;
29
+ if (!parent) return;
30
+ const next = this[NEXT];
31
+ for (const node of nodes) {
32
+ parent.insertBefore(toNode(parent, node), next);
33
+ }
34
+ }
35
+ }
36
+ function toNode(parent, node) {
37
+ if (node instanceof Node) return node;
38
+ const ownerDocument = parent.ownerDocument;
39
+ return ownerDocument.createTextNode(String(node));
40
+ }
41
+
42
+ export { ChildNode, toNode };
@@ -0,0 +1,9 @@
1
+ import { NAME } from './constants.mjs';
2
+ import { CharacterData } from './CharacterData.mjs';
3
+
4
+ class Comment extends CharacterData {
5
+ nodeType = 8;
6
+ [NAME] = '#comment';
7
+ }
8
+
9
+ export { Comment };
@@ -0,0 +1,33 @@
1
+ class CustomElementRegistryImplementation {
2
+ registry = new Map();
3
+ listenersByName = new Map();
4
+ define(name, Constructor, _options) {
5
+ this.registry.set(name, Constructor);
6
+ const listeners = this.listenersByName.get(name);
7
+ if (listeners == null) return;
8
+ this.listenersByName.delete(name);
9
+ for (const listener of listeners) {
10
+ listener(Constructor);
11
+ }
12
+ }
13
+ get(name) {
14
+ return this.registry.get(name);
15
+ }
16
+ whenDefined(name) {
17
+ const Constructor = this.registry.get(name);
18
+ if (Constructor != null) return Promise.resolve(Constructor);
19
+ let listeners = this.listenersByName.get(name);
20
+ if (listeners == null) {
21
+ listeners = [];
22
+ this.listenersByName.set(name, listeners);
23
+ }
24
+ return new Promise(resolve => {
25
+ listeners.push(resolve);
26
+ });
27
+ }
28
+ upgrade(_root) {
29
+ // TODO
30
+ }
31
+ }
32
+
33
+ export { CustomElementRegistryImplementation };
@@ -0,0 +1,26 @@
1
+ import { Event } from './Event.mjs';
2
+
3
+ class CustomEvent extends Event {
4
+ /**
5
+ * Returns any custom data event was created with. Typically used for synthetic events.
6
+ *
7
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/CustomEvent/detail)
8
+ */
9
+
10
+ constructor(type, eventInitDict) {
11
+ super(type, eventInitDict);
12
+ this.detail = eventInitDict?.detail;
13
+ }
14
+
15
+ /**
16
+ * Returns any custom data event was created with. Typically used for synthetic events.
17
+ *
18
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/CustomEvent/detail)
19
+ */
20
+ initCustomEvent(type, bubbles, cancelable, detail) {
21
+ super.initEvent(type, bubbles, cancelable);
22
+ this.detail = detail;
23
+ }
24
+ }
25
+
26
+ export { CustomEvent };
@@ -0,0 +1,89 @@
1
+ import { NodeType, NAME, OWNER_DOCUMENT, NamespaceURI, NS } from './constants.mjs';
2
+ import { Event } from './Event.mjs';
3
+ import { ParentNode } from './ParentNode.mjs';
4
+ import { Element } from './Element.mjs';
5
+ import { SVGElement } from './SVGElement.mjs';
6
+ import { Text } from './Text.mjs';
7
+ import { Comment } from './Comment.mjs';
8
+ import { DocumentFragment } from './DocumentFragment.mjs';
9
+ import { HTMLTemplateElement } from './HTMLTemplateElement.mjs';
10
+ import { cloneNode, isParentNode } from './shared.mjs';
11
+
12
+ class Document extends ParentNode {
13
+ nodeType = NodeType.DOCUMENT_NODE;
14
+ [NAME] = '#document';
15
+ constructor(defaultView) {
16
+ super();
17
+ this.defaultView = defaultView;
18
+ this[OWNER_DOCUMENT] = this;
19
+ }
20
+ createElement(localName) {
21
+ const lowerName = String(localName).toLowerCase();
22
+ if (lowerName === 'template') {
23
+ return createElement(new HTMLTemplateElement(), this, 'template');
24
+ }
25
+ const CustomElement = this.defaultView.customElements.get(localName);
26
+ if (CustomElement) {
27
+ return createElement(new CustomElement(), this, localName);
28
+ } else {
29
+ return createElement(new Element(), this, localName);
30
+ }
31
+ }
32
+ createElementNS(localName, namespaceURI) {
33
+ if (namespaceURI === NamespaceURI.SVG) {
34
+ return createElement(new SVGElement(), this, localName);
35
+ }
36
+ return createElement(new Element(), this, localName, namespaceURI);
37
+ }
38
+ createTextNode(data) {
39
+ return createNode(new Text(data), this);
40
+ }
41
+ createComment(data) {
42
+ return createNode(new Comment(data), this);
43
+ }
44
+ createDocumentFragment() {
45
+ return createNode(new DocumentFragment(), this);
46
+ }
47
+ createEvent() {
48
+ return new Event('');
49
+ }
50
+ importNode(node, deep) {
51
+ return cloneNode(node, deep, this);
52
+ }
53
+ adoptNode(node) {
54
+ if (node[OWNER_DOCUMENT] === this) return node;
55
+ node.parentNode?.removeChild(node);
56
+ adoptNode(node, this);
57
+ return node;
58
+ }
59
+ }
60
+ function createNode(node, ownerDocument) {
61
+ Object.defineProperty(node, OWNER_DOCUMENT, {
62
+ value: ownerDocument,
63
+ writable: true,
64
+ enumerable: false
65
+ });
66
+ return node;
67
+ }
68
+ function createElement(element, ownerDocument, name, namespace) {
69
+ createNode(element, ownerDocument);
70
+ Object.defineProperty(element, NAME, {
71
+ value: name
72
+ });
73
+ if (namespace) {
74
+ Object.defineProperty(element, NS, {
75
+ value: namespace
76
+ });
77
+ }
78
+ return element;
79
+ }
80
+ function adoptNode(node, document) {
81
+ node[OWNER_DOCUMENT] = document;
82
+ if (isParentNode(node)) {
83
+ for (const child of node.childNodes) {
84
+ adoptNode(child, document);
85
+ }
86
+ }
87
+ }
88
+
89
+ export { Document, adoptNode, createElement, createNode };
@@ -0,0 +1,10 @@
1
+ import { NodeType, NAME, OWNER_DOCUMENT } from './constants.mjs';
2
+ import { ParentNode } from './ParentNode.mjs';
3
+
4
+ class DocumentFragment extends ParentNode {
5
+ nodeType = NodeType.DOCUMENT_FRAGMENT_NODE;
6
+ [NAME] = '#document-fragment';
7
+ [OWNER_DOCUMENT] = window.document;
8
+ }
9
+
10
+ export { DocumentFragment };
@@ -0,0 +1,95 @@
1
+ import { NodeType, NS, NamespaceURI, SLOT, ATTRIBUTES } from './constants.mjs';
2
+ import { ParentNode } from './ParentNode.mjs';
3
+ import { NamedNodeMap } from './NamedNodeMap.mjs';
4
+ import { Attr } from './Attr.mjs';
5
+ import { serializeNode, serializeChildren, parseHtml } from './serialization.mjs';
6
+
7
+ class Element extends ParentNode {
8
+ nodeType = NodeType.ELEMENT_NODE;
9
+ [NS] = NamespaceURI.XHTML;
10
+ [SLOT] = '';
11
+ get namespaceURI() {
12
+ return this[NS];
13
+ }
14
+ get tagName() {
15
+ return this.nodeName;
16
+ }
17
+ get slot() {
18
+ return this[SLOT];
19
+ }
20
+ set slot(slot) {
21
+ const finalSlot = String(slot);
22
+ this[SLOT] = finalSlot;
23
+ if (this.getAttribute('slot') !== finalSlot) {
24
+ this.attributes.setNamedItem(new Attr('slot', finalSlot));
25
+ }
26
+ }
27
+ get attributes() {
28
+ let attributes = this[ATTRIBUTES];
29
+ if (!attributes) {
30
+ attributes = new NamedNodeMap(this);
31
+ this[ATTRIBUTES] = attributes;
32
+ }
33
+ return attributes;
34
+ }
35
+ get firstElementChild() {
36
+ return this.children[0] ?? null;
37
+ }
38
+ get lastElementChild() {
39
+ return this.children[this.children.length - 1] ?? null;
40
+ }
41
+ get nextElementSibling() {
42
+ let sib = this.nextSibling;
43
+ while (sib && sib.nodeType !== 1) sib = sib.nextSibling;
44
+ return sib;
45
+ }
46
+ get previewElementSibling() {
47
+ let sib = this.previousSibling;
48
+ while (sib && sib.nodeType !== 1) sib = sib.previousSibling;
49
+ return sib;
50
+ }
51
+ setAttribute(name, value) {
52
+ this.attributes.setNamedItem(new Attr(name, String(value)));
53
+ }
54
+ setAttributeNS(namespace, name, value) {
55
+ this.attributes.setNamedItemNS(new Attr(name, String(value), namespace));
56
+ }
57
+ getAttribute(name) {
58
+ const attr = this.attributes.getNamedItem(name);
59
+ return attr && attr.value;
60
+ }
61
+ getAttributeNS(namespace, name) {
62
+ const attr = this.attributes.getNamedItemNS(namespace, name);
63
+ return attr && attr.value;
64
+ }
65
+ hasAttribute(name) {
66
+ const attr = this.attributes.getNamedItem(name);
67
+ return attr != null;
68
+ }
69
+ hasAttributeNS(namespace, name) {
70
+ const attr = this.attributes.getNamedItemNS(namespace, name);
71
+ return attr != null;
72
+ }
73
+ removeAttribute(name) {
74
+ this.attributes.removeNamedItem(name);
75
+ }
76
+ removeAttributeNS(namespace, name) {
77
+ this.attributes.removeNamedItemNS(namespace, name);
78
+ }
79
+ get outerHTML() {
80
+ return serializeNode(this);
81
+ }
82
+ get innerHTML() {
83
+ return serializeChildren(this);
84
+ }
85
+ set innerHTML(html) {
86
+ if (html == null || html === '') {
87
+ this.replaceChildren();
88
+ } else {
89
+ const fragment = parseHtml(String(html), this);
90
+ this.replaceChildren(fragment);
91
+ }
92
+ }
93
+ }
94
+
95
+ export { Element };
@@ -0,0 +1,108 @@
1
+ import { IS_TRUSTED, LISTENERS } from './constants.mjs';
2
+
3
+ let EventPhase = /*#__PURE__*/function (EventPhase) {
4
+ EventPhase[EventPhase["NONE"] = 0] = "NONE";
5
+ EventPhase[EventPhase["CAPTURING_PHASE"] = 1] = "CAPTURING_PHASE";
6
+ EventPhase[EventPhase["AT_TARGET"] = 2] = "AT_TARGET";
7
+ EventPhase[EventPhase["BUBBLING_PHASE"] = 3] = "BUBBLING_PHASE";
8
+ return EventPhase;
9
+ }({});
10
+ const CAPTURE_MARKER = '@';
11
+ const now = typeof performance === 'undefined' ? Date.now : performance.now.bind(performance);
12
+ class Event {
13
+ static NONE = EventPhase.NONE;
14
+ static CAPTURING_PHASE = EventPhase.CAPTURING_PHASE;
15
+ static AT_TARGET = EventPhase.AT_TARGET;
16
+ static BUBBLING_PHASE = EventPhase.BUBBLING_PHASE;
17
+
18
+ // NONE = EventPhase.NONE;
19
+ // CAPTURING_PHASE = EventPhase.CAPTURING_PHASE;
20
+ // AT_TARGET = EventPhase.AT_TARGET;
21
+ // BUBBLING_PHASE = EventPhase.BUBBLING_PHASE;
22
+
23
+ timeStamp = now();
24
+ target = null;
25
+ currentTarget = null;
26
+ srcElement = null;
27
+ bubbles = false;
28
+ cancelable = false;
29
+ composed = false;
30
+ defaultPrevented = false;
31
+ cancelBubble = false;
32
+ immediatePropagationStopped = false;
33
+ eventPhase = 0;
34
+ path = [];
35
+ // private inPassiveListener = false;
36
+
37
+ constructor(type, options) {
38
+ this.type = type;
39
+ Object.defineProperty(this, IS_TRUSTED, {
40
+ writable: true,
41
+ value: false
42
+ });
43
+ if (options) {
44
+ if (options.bubbles) this.bubbles = options.bubbles;
45
+ if (options.cancelable) this.cancelable = options.cancelable;
46
+ if (options.composed) this.composed = options.composed;
47
+ }
48
+ }
49
+ get composedPath() {
50
+ return this.path;
51
+ }
52
+ get isTrusted() {
53
+ return this[IS_TRUSTED];
54
+ }
55
+ stopPropagation() {
56
+ this.cancelBubble = true;
57
+ }
58
+ stopImmediatePropagation() {
59
+ this.immediatePropagationStopped = true;
60
+ }
61
+ preventDefault() {
62
+ this.defaultPrevented = true;
63
+ }
64
+ set returnValue(value) {
65
+ this.defaultPrevented = value;
66
+ }
67
+ get returnValue() {
68
+ return this.defaultPrevented;
69
+ }
70
+
71
+ /** @deprecated */
72
+ initEvent(type, bubbles, cancelable) {
73
+ this.type = type;
74
+ this.bubbles = Boolean(bubbles);
75
+ this.cancelable = Boolean(cancelable);
76
+ }
77
+ }
78
+ function fireEvent(event, target, phase) {
79
+ const listeners = target[LISTENERS];
80
+ const list = listeners?.get(`${event.type}${phase === EventPhase.CAPTURING_PHASE ? CAPTURE_MARKER : ''}`);
81
+ if (!list) return false;
82
+ let defaultPrevented = false;
83
+ for (const listener of list) {
84
+ event.eventPhase = phase;
85
+ event.currentTarget = target;
86
+ try {
87
+ if (typeof listener === 'object') {
88
+ listener.handleEvent(event);
89
+ } else {
90
+ listener.call(target, event);
91
+ }
92
+ } catch (err) {
93
+ setTimeout(thrower, 0, err);
94
+ }
95
+ if (event.defaultPrevented === true) {
96
+ defaultPrevented = true;
97
+ }
98
+ if (event.immediatePropagationStopped) {
99
+ break;
100
+ }
101
+ }
102
+ return defaultPrevented;
103
+ }
104
+ function thrower(error) {
105
+ throw error;
106
+ }
107
+
108
+ export { CAPTURE_MARKER, Event, EventPhase, fireEvent };
@@ -0,0 +1,99 @@
1
+ import { hooks } from './hooks.mjs';
2
+ import { LISTENERS } from './constants.mjs';
3
+ import { fireEvent, EventPhase, CAPTURE_MARKER } from './Event.mjs';
4
+
5
+ const ONCE_LISTENERS = Symbol('onceListeners');
6
+ class EventTarget {
7
+ addEventListener(type, listener, options) {
8
+ if (listener == null) return;
9
+ const capture = options === true || options && options.capture === true;
10
+ const once = typeof options === 'object' && options.once === true;
11
+ const signal = typeof options === 'object' ? options.signal : undefined;
12
+ const key = `${type}${capture ? CAPTURE_MARKER : ''}`;
13
+ let normalizedListener = listener;
14
+ if (once) {
15
+ normalizedListener = function normalizedListener(...args) {
16
+ this.removeEventListener(type, listener, options);
17
+ return typeof listener === 'object' ? listener.handleEvent(...args) : listener.call(this, ...args);
18
+ };
19
+ let onceListeners = this[ONCE_LISTENERS];
20
+ if (!onceListeners) {
21
+ onceListeners = new WeakMap();
22
+ this[ONCE_LISTENERS] = onceListeners;
23
+ }
24
+ onceListeners.set(listener, normalizedListener);
25
+ }
26
+ let listeners = this[LISTENERS];
27
+ if (!listeners) {
28
+ listeners = new Map();
29
+ this[LISTENERS] = listeners;
30
+ }
31
+ let list = listeners.get(key);
32
+ if (!list) {
33
+ list = new Set();
34
+ listeners.set(key, list);
35
+ }
36
+ list.add(normalizedListener);
37
+ signal?.addEventListener('abort', () => {
38
+ removeEventListener.call(this, type, listener, options);
39
+ }, {
40
+ once: true
41
+ });
42
+ hooks.addEventListener?.(this, type, listener, options);
43
+ }
44
+ removeEventListener(type, listener, options) {
45
+ return removeEventListener.call(this, type, listener, options);
46
+ }
47
+
48
+ // function isChildNode(node: EventTarget): node is ChildNode {
49
+ // return PARENT in node;
50
+ // }
51
+
52
+ dispatchEvent(event) {
53
+ const path = [];
54
+ // instanceof here is just to keep TypeScript happy
55
+ let target = this;
56
+ while (target != null) {
57
+ path.push(target);
58
+ target = target.parentNode;
59
+ }
60
+ // while (target instanceof Node && (target = target.parentNode)) {
61
+ // path.push(target);
62
+ // }
63
+ event.target = this;
64
+ event.srcElement = this;
65
+ event.path = path;
66
+ let defaultPrevented = false;
67
+ for (let i = path.length; --i;) {
68
+ if (fireEvent(event, path[i], EventPhase.CAPTURING_PHASE)) {
69
+ defaultPrevented = true;
70
+ }
71
+ }
72
+ if (fireEvent(event, this, EventPhase.AT_TARGET)) {
73
+ defaultPrevented = true;
74
+ }
75
+ for (let i = 1; i < path.length; i++) {
76
+ if (fireEvent(event, path[i], EventPhase.BUBBLING_PHASE)) {
77
+ defaultPrevented = true;
78
+ }
79
+ }
80
+ return !defaultPrevented;
81
+ }
82
+ }
83
+ function removeEventListener(type, listener, options) {
84
+ if (listener == null) return;
85
+ const onceListeners = this[ONCE_LISTENERS];
86
+ const normalizedListener = onceListeners?.get(listener) ?? listener;
87
+ onceListeners?.delete(listener);
88
+ const capture = options === true || options && options.capture === true;
89
+ const key = `${type}${capture ? CAPTURE_MARKER : ''}`;
90
+ const list = this[LISTENERS]?.get(key);
91
+ if (list) {
92
+ const deleted = list.delete(normalizedListener);
93
+ if (deleted) {
94
+ hooks.removeEventListener?.(this, type, listener, options);
95
+ }
96
+ }
97
+ }
98
+
99
+ export { EventTarget };
@@ -0,0 +1,5 @@
1
+ import { Element } from './Element.mjs';
2
+
3
+ class HTMLElement extends Element {}
4
+
5
+ export { HTMLElement };