@remote-dom/polyfill 1.5.1 → 1.6.0
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.
- package/CHANGELOG.md +88 -0
- package/README.md +51 -3
- package/build/cjs/Attr.cjs +33 -4
- package/build/cjs/CharacterData.cjs +10 -0
- package/build/cjs/ChildNode.cjs +79 -13
- package/build/cjs/Comment.cjs +1 -1
- package/build/cjs/CustomElementRegistry.cjs +27 -2
- package/build/cjs/CustomEvent.cjs +2 -2
- package/build/cjs/Document.cjs +56 -32
- package/build/cjs/DocumentFragment.cjs +6 -2
- package/build/cjs/Element.cjs +68 -8
- package/build/cjs/Event.cjs +29 -27
- package/build/cjs/EventTarget.cjs +128 -58
- package/build/cjs/HTMLTemplateElement.cjs +1 -0
- package/build/cjs/MutationObserver.cjs +167 -1
- package/build/cjs/NamedNodeMap.cjs +82 -45
- package/build/cjs/Node.cjs +47 -11
- package/build/cjs/NodeList.cjs +9 -1
- package/build/cjs/ParentNode.cjs +319 -77
- package/build/cjs/SVGElement.cjs +1 -1
- package/build/cjs/Text.cjs +1 -1
- package/build/cjs/Window.cjs +131 -38
- package/build/cjs/attribute-reactions.cjs +20 -0
- package/build/cjs/constants.cjs +48 -24
- package/build/cjs/custom-element-reactions.cjs +52 -0
- package/build/cjs/dom-exception.cjs +15 -0
- package/build/cjs/hook-effects.cjs +51 -0
- package/build/cjs/names.cjs +61 -0
- package/build/cjs/selectors.cjs +213 -122
- package/build/cjs/serialization.cjs +168 -65
- package/build/cjs/shared.cjs +177 -28
- package/build/esm/Attr.mjs +34 -5
- package/build/esm/CharacterData.mjs +10 -0
- package/build/esm/ChildNode.mjs +76 -15
- package/build/esm/Comment.mjs +2 -2
- package/build/esm/CustomElementRegistry.mjs +27 -2
- package/build/esm/CustomEvent.mjs +2 -2
- package/build/esm/Document.mjs +60 -35
- package/build/esm/DocumentFragment.mjs +7 -3
- package/build/esm/Element.mjs +69 -9
- package/build/esm/Event.mjs +27 -27
- package/build/esm/EventTarget.mjs +130 -60
- package/build/esm/HTMLTemplateElement.mjs +2 -1
- package/build/esm/MutationObserver.mjs +166 -2
- package/build/esm/NamedNodeMap.mjs +83 -46
- package/build/esm/Node.mjs +48 -12
- package/build/esm/NodeList.mjs +9 -1
- package/build/esm/ParentNode.mjs +322 -81
- package/build/esm/SVGElement.mjs +2 -2
- package/build/esm/Text.mjs +2 -2
- package/build/esm/Window.mjs +132 -39
- package/build/esm/attribute-reactions.mjs +16 -0
- package/build/esm/constants.mjs +28 -23
- package/build/esm/custom-element-reactions.mjs +47 -0
- package/build/esm/dom-exception.mjs +11 -0
- package/build/esm/hook-effects.mjs +46 -0
- package/build/esm/names.mjs +54 -0
- package/build/esm/selectors.mjs +202 -124
- package/build/esm/serialization.mjs +169 -66
- package/build/esm/shared.mjs +173 -30
- package/build/esnext/Attr.esnext +45 -5
- package/build/esnext/CharacterData.esnext +10 -0
- package/build/esnext/ChildNode.esnext +84 -15
- package/build/esnext/Comment.esnext +2 -2
- package/build/esnext/CustomElementRegistry.esnext +42 -0
- package/build/esnext/CustomEvent.esnext +2 -2
- package/build/esnext/Document.esnext +69 -32
- package/build/esnext/DocumentFragment.esnext +6 -2
- package/build/esnext/Element.esnext +78 -9
- package/build/esnext/Event.esnext +36 -37
- package/build/esnext/EventTarget.esnext +133 -61
- package/build/esnext/HTMLTemplateElement.esnext +3 -1
- package/build/esnext/MutationObserver.esnext +163 -2
- package/build/esnext/NamedNodeMap.esnext +110 -42
- package/build/esnext/Node.esnext +50 -12
- package/build/esnext/NodeList.esnext +1 -1
- package/build/esnext/ParentNode.esnext +352 -79
- package/build/esnext/SVGElement.esnext +2 -2
- package/build/esnext/Text.esnext +2 -2
- package/build/esnext/Window.esnext +120 -16
- package/build/esnext/attribute-reactions.esnext +21 -0
- package/build/esnext/constants.esnext +34 -21
- package/build/esnext/custom-element-reactions.esnext +49 -0
- package/build/esnext/dom-exception.esnext +11 -0
- package/build/esnext/hook-effects.esnext +46 -0
- package/build/esnext/names.esnext +61 -0
- package/build/esnext/selectors.esnext +202 -100
- package/build/esnext/serialization.esnext +171 -48
- package/build/esnext/shared.esnext +181 -34
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/Attr.d.ts +6 -4
- package/build/typescript/Attr.d.ts.map +1 -1
- package/build/typescript/CharacterData.d.ts.map +1 -1
- package/build/typescript/ChildNode.d.ts +5 -0
- package/build/typescript/ChildNode.d.ts.map +1 -1
- package/build/typescript/ClipboardEvent.d.ts.map +1 -1
- package/build/typescript/Comment.d.ts +2 -2
- package/build/typescript/Comment.d.ts.map +1 -1
- package/build/typescript/CustomElementRegistry.d.ts +1 -0
- package/build/typescript/CustomElementRegistry.d.ts.map +1 -1
- package/build/typescript/CustomEvent.d.ts.map +1 -1
- package/build/typescript/Document.d.ts +10 -5
- package/build/typescript/Document.d.ts.map +1 -1
- package/build/typescript/DocumentFragment.d.ts +2 -1
- package/build/typescript/DocumentFragment.d.ts.map +1 -1
- package/build/typescript/Element.d.ts +16 -7
- package/build/typescript/Element.d.ts.map +1 -1
- package/build/typescript/ErrorEvent.d.ts.map +1 -1
- package/build/typescript/Event.d.ts +9 -10
- package/build/typescript/Event.d.ts.map +1 -1
- package/build/typescript/EventTarget.d.ts +20 -3
- package/build/typescript/EventTarget.d.ts.map +1 -1
- package/build/typescript/FocusEvent.d.ts.map +1 -1
- package/build/typescript/HTMLTemplateElement.d.ts.map +1 -1
- package/build/typescript/MutationObserver.d.ts +42 -0
- package/build/typescript/MutationObserver.d.ts.map +1 -1
- package/build/typescript/NamedNodeMap.d.ts +5 -3
- package/build/typescript/NamedNodeMap.d.ts.map +1 -1
- package/build/typescript/Node.d.ts +4 -3
- package/build/typescript/Node.d.ts.map +1 -1
- package/build/typescript/NodeList.d.ts +3 -2
- package/build/typescript/NodeList.d.ts.map +1 -1
- package/build/typescript/ParentNode.d.ts +29 -10
- package/build/typescript/ParentNode.d.ts.map +1 -1
- package/build/typescript/PromiseRejectionEvent.d.ts.map +1 -1
- package/build/typescript/SVGElement.d.ts +1 -1
- package/build/typescript/SVGElement.d.ts.map +1 -1
- package/build/typescript/Text.d.ts +1 -1
- package/build/typescript/Text.d.ts.map +1 -1
- package/build/typescript/ToggleEvent.d.ts.map +1 -1
- package/build/typescript/Window.d.ts +5 -1
- package/build/typescript/Window.d.ts.map +1 -1
- package/build/typescript/attribute-reactions.d.ts +4 -0
- package/build/typescript/attribute-reactions.d.ts.map +1 -0
- package/build/typescript/constants.d.ts +27 -18
- package/build/typescript/constants.d.ts.map +1 -1
- package/build/typescript/custom-element-reactions.d.ts +6 -0
- package/build/typescript/custom-element-reactions.d.ts.map +1 -0
- package/build/typescript/dom-exception.d.ts +2 -0
- package/build/typescript/dom-exception.d.ts.map +1 -0
- package/build/typescript/extensions.d.ts +4 -0
- package/build/typescript/extensions.d.ts.map +1 -0
- package/build/typescript/hook-effects.d.ts +6 -0
- package/build/typescript/hook-effects.d.ts.map +1 -0
- package/build/typescript/hooks.d.ts +3 -3
- package/build/typescript/hooks.d.ts.map +1 -1
- package/build/typescript/index.d.ts +1 -0
- package/build/typescript/index.d.ts.map +1 -1
- package/build/typescript/names.d.ts +11 -0
- package/build/typescript/names.d.ts.map +1 -0
- package/build/typescript/selectors.d.ts +21 -22
- package/build/typescript/selectors.d.ts.map +1 -1
- package/build/typescript/serialization.d.ts.map +1 -1
- package/build/typescript/shared.d.ts +10 -0
- package/build/typescript/shared.d.ts.map +1 -1
- package/build/typescript/tests/ChildNode.test.d.ts +2 -0
- package/build/typescript/tests/ChildNode.test.d.ts.map +1 -0
- package/build/typescript/tests/MutationObserver.test.d.ts +2 -0
- package/build/typescript/tests/MutationObserver.test.d.ts.map +1 -0
- package/build/typescript/tests/adopt-inserted-subtrees.test.d.ts +2 -0
- package/build/typescript/tests/adopt-inserted-subtrees.test.d.ts.map +1 -0
- package/build/typescript/tests/attr-mutation.test.d.ts +2 -0
- package/build/typescript/tests/attr-mutation.test.d.ts.map +1 -0
- package/build/typescript/tests/child-node-before-after.test.d.ts +2 -0
- package/build/typescript/tests/child-node-before-after.test.d.ts.map +1 -0
- package/build/typescript/tests/child-node-replace-with.test.d.ts +2 -0
- package/build/typescript/tests/child-node-replace-with.test.d.ts.map +1 -0
- package/build/typescript/tests/clone-import-namespaces.test.d.ts +2 -0
- package/build/typescript/tests/clone-import-namespaces.test.d.ts.map +1 -0
- package/build/typescript/tests/constants.test.d.ts +2 -0
- package/build/typescript/tests/constants.test.d.ts.map +1 -0
- package/build/typescript/tests/create-element-namespaces.test.d.ts +2 -0
- package/build/typescript/tests/create-element-namespaces.test.d.ts.map +1 -0
- package/build/typescript/tests/create-text-node.test.d.ts +2 -0
- package/build/typescript/tests/create-text-node.test.d.ts.map +1 -0
- package/build/typescript/tests/custom-element-reactions.test.d.ts +2 -0
- package/build/typescript/tests/custom-element-reactions.test.d.ts.map +1 -0
- package/build/typescript/tests/custom-element-registry.test.d.ts +2 -0
- package/build/typescript/tests/custom-element-registry.test.d.ts.map +1 -0
- package/build/typescript/tests/custom-event.test.d.ts +2 -0
- package/build/typescript/tests/custom-event.test.d.ts.map +1 -0
- package/build/typescript/tests/document-clone-import-contract.test.d.ts +2 -0
- package/build/typescript/tests/document-clone-import-contract.test.d.ts.map +1 -0
- package/build/typescript/tests/document.test.d.ts +2 -0
- package/build/typescript/tests/document.test.d.ts.map +1 -0
- package/build/typescript/tests/dom-mutation-selector-errors.test.d.ts +2 -0
- package/build/typescript/tests/dom-mutation-selector-errors.test.d.ts.map +1 -0
- package/build/typescript/tests/event-dispatch.test.d.ts +2 -0
- package/build/typescript/tests/event-dispatch.test.d.ts.map +1 -0
- package/build/typescript/tests/event-target.test.d.ts +2 -0
- package/build/typescript/tests/event-target.test.d.ts.map +1 -0
- package/build/typescript/tests/event.test.d.ts +2 -0
- package/build/typescript/tests/event.test.d.ts.map +1 -0
- package/build/typescript/tests/extensions.test.d.ts +2 -0
- package/build/typescript/tests/extensions.test.d.ts.map +1 -0
- package/build/typescript/tests/get-elements-by-tag-name.test.d.ts +2 -0
- package/build/typescript/tests/get-elements-by-tag-name.test.d.ts.map +1 -0
- package/build/typescript/tests/getElementsByClassName.test.d.ts +2 -0
- package/build/typescript/tests/getElementsByClassName.test.d.ts.map +1 -0
- package/build/typescript/tests/hooks.test.d.ts +2 -0
- package/build/typescript/tests/hooks.test.d.ts.map +1 -0
- package/build/typescript/tests/inner-html-parsing.test.d.ts +2 -0
- package/build/typescript/tests/inner-html-parsing.test.d.ts.map +1 -0
- package/build/typescript/tests/is-default-namespace.test.d.ts +2 -0
- package/build/typescript/tests/is-default-namespace.test.d.ts.map +1 -0
- package/build/typescript/tests/name-and-namespace-normalization.test.d.ts +2 -0
- package/build/typescript/tests/name-and-namespace-normalization.test.d.ts.map +1 -0
- package/build/typescript/tests/named-node-map.test.d.ts +2 -0
- package/build/typescript/tests/named-node-map.test.d.ts.map +1 -0
- package/build/typescript/tests/namespaced-attribute-reactions.test.d.ts +2 -0
- package/build/typescript/tests/namespaced-attribute-reactions.test.d.ts.map +1 -0
- package/build/typescript/tests/node.test.d.ts +2 -0
- package/build/typescript/tests/node.test.d.ts.map +1 -0
- package/build/typescript/tests/parent-node-mutation-return-values.test.d.ts +2 -0
- package/build/typescript/tests/parent-node-mutation-return-values.test.d.ts.map +1 -0
- package/build/typescript/tests/parent-node-mutation-validation.test.d.ts +2 -0
- package/build/typescript/tests/parent-node-mutation-validation.test.d.ts.map +1 -0
- package/build/typescript/tests/parent-node.test.d.ts +2 -0
- package/build/typescript/tests/parent-node.test.d.ts.map +1 -0
- package/build/typescript/tests/serialization-template.test.d.ts +2 -0
- package/build/typescript/tests/serialization-template.test.d.ts.map +1 -0
- package/build/typescript/tests/slot-attribute.test.d.ts +2 -0
- package/build/typescript/tests/slot-attribute.test.d.ts.map +1 -0
- package/build/typescript/tests/text-content.test.d.ts +2 -0
- package/build/typescript/tests/text-content.test.d.ts.map +1 -0
- package/build/typescript/tests/toggle-attribute.test.d.ts +2 -0
- package/build/typescript/tests/toggle-attribute.test.d.ts.map +1 -0
- package/build/typescript/tests/wide-tree-traversal.test.d.ts +2 -0
- package/build/typescript/tests/wide-tree-traversal.test.d.ts.map +1 -0
- package/build/typescript/tests/window-set-global.test.d.ts +2 -0
- package/build/typescript/tests/window-set-global.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/source/Attr.ts +60 -8
- package/source/CharacterData.ts +13 -0
- package/source/ChildNode.ts +107 -14
- package/source/Comment.ts +2 -2
- package/source/CustomElementRegistry.ts +56 -0
- package/source/CustomEvent.ts +2 -2
- package/source/Document.ts +104 -38
- package/source/DocumentFragment.ts +12 -2
- package/source/Element.ts +129 -14
- package/source/Event.ts +34 -32
- package/source/EventTarget.ts +203 -79
- package/source/HTMLTemplateElement.ts +2 -1
- package/source/MutationObserver.ts +279 -1
- package/source/NamedNodeMap.ts +141 -60
- package/source/Node.ts +70 -14
- package/source/NodeList.ts +13 -3
- package/source/ParentNode.ts +500 -88
- package/source/SVGElement.ts +2 -2
- package/source/Text.ts +2 -2
- package/source/Window.ts +156 -17
- package/source/attribute-reactions.ts +32 -0
- package/source/constants.ts +40 -17
- package/source/custom-element-reactions.ts +64 -0
- package/source/dom-exception.ts +14 -0
- package/source/extensions.ts +4 -0
- package/source/hook-effects.ts +56 -0
- package/source/hooks.ts +11 -3
- package/source/index.ts +1 -0
- package/source/names.ts +94 -0
- package/source/selectors.ts +301 -138
- package/source/serialization.ts +224 -66
- package/source/shared.ts +269 -40
- package/source/tests/ChildNode.test.ts +178 -0
- package/source/tests/MutationObserver.test.ts +303 -0
- package/source/tests/adopt-inserted-subtrees.test.ts +584 -0
- package/source/tests/attr-mutation.test.ts +112 -0
- package/source/tests/child-node-before-after.test.ts +421 -0
- package/source/tests/child-node-replace-with.test.ts +251 -0
- package/source/tests/clone-import-namespaces.test.ts +365 -0
- package/source/tests/constants.test.ts +46 -0
- package/source/tests/create-element-namespaces.test.ts +142 -0
- package/source/tests/create-text-node.test.ts +38 -0
- package/source/tests/custom-element-reactions.test.ts +600 -0
- package/source/tests/custom-element-registry.test.ts +137 -0
- package/source/tests/custom-event.test.ts +26 -0
- package/source/tests/document-clone-import-contract.test.ts +77 -0
- package/source/tests/document.test.ts +122 -0
- package/source/tests/dom-mutation-selector-errors.test.ts +484 -0
- package/source/tests/event-dispatch.test.ts +270 -0
- package/source/tests/event-target.test.ts +208 -0
- package/source/tests/event.test.ts +98 -0
- package/source/tests/extensions.test.ts +159 -0
- package/source/tests/get-elements-by-tag-name.test.ts +79 -0
- package/source/tests/getElementsByClassName.test.ts +109 -0
- package/source/tests/hooks.test.ts +43 -0
- package/source/tests/inner-html-parsing.test.ts +461 -0
- package/source/tests/is-default-namespace.test.ts +111 -0
- package/source/tests/name-and-namespace-normalization.test.ts +319 -0
- package/source/tests/named-node-map.test.ts +122 -0
- package/source/tests/namespaced-attribute-reactions.test.ts +141 -0
- package/source/tests/node.test.ts +56 -0
- package/source/tests/parent-node-mutation-return-values.test.ts +63 -0
- package/source/tests/parent-node-mutation-validation.test.ts +362 -0
- package/source/tests/parent-node.test.ts +169 -0
- package/source/tests/selectors.test.ts +533 -22
- package/source/tests/serialization-template.test.ts +232 -0
- package/source/tests/slot-attribute.test.ts +133 -0
- package/source/tests/text-content.test.ts +440 -0
- package/source/tests/toggle-attribute.test.ts +113 -0
- package/source/tests/wide-tree-traversal.test.ts +699 -0
- package/source/tests/window-set-global.test.ts +321 -0
- package/tsconfig.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# @remote-dom/polyfill
|
|
2
2
|
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#620](https://github.com/Shopify/remote-dom/pull/620) [`4be18ef`](https://github.com/Shopify/remote-dom/commit/4be18ef20017587835e7275e3901cd5fcdcdc50e) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Add `getElementById()` to `Document` and `DocumentFragment`, with reflected `Element.id` properties. Add `getElementsByTagName()` to `Document` and `Element`, supporting HTML, non-HTML, and wildcard descendant searches. `querySelector` and `querySelectorAll` accept a pre-parsed `Matcher[]` in addition to string selectors, with `MatcherType`, `Combinator`, `Matcher`, and `Part` exported from `selectors.ts`; `getElementById` and `getElementsByTagName` delegate to this shared selector engine instead of independent tree-walk implementations.
|
|
8
|
+
|
|
9
|
+
Fixed `insertBefore()` leaving the previous sibling pointing at the reference node when inserting before a middle child, causing `NEXT` traversals (including `getElementById`) to skip the inserted subtree even though `childNodes` contained it, and return the inserted child as required by the DOM specification. Fixed `appendChild()` to return the appended child and `NodeList.item()` to return `null` for out-of-range indexes. Fixed case-insensitive HTML tag-name matching in the selector engine so `querySelector('DIV')` now matches `<div>` per the CSS spec. Fixed CSS-escaping issues so `getElementById` matches ids containing special characters (`.`, `:`, `#`, etc.) literally instead of treating them as selector syntax.
|
|
10
|
+
|
|
11
|
+
- [#625](https://github.com/Shopify/remote-dom/pull/625) [`ab6c549`](https://github.com/Shopify/remote-dom/commit/ab6c5494908a5efb53fc8e5534b2b2967b9cbe41) Thanks [@airhorns](https://github.com/airhorns)! - Add `getElementsByClassName()` to polyfilled documents and elements.
|
|
12
|
+
|
|
13
|
+
- [#624](https://github.com/Shopify/remote-dom/pull/624) [`e2a9eef`](https://github.com/Shopify/remote-dom/commit/e2a9eef700edd7f46a0cafb3e3a63d757ccfbc2e) Thanks [@airhorns](https://github.com/airhorns)! - Implement the standard `MutationObserver` methods for child, attribute, and character-data changes in the polyfilled DOM.
|
|
14
|
+
|
|
15
|
+
- [#652](https://github.com/Shopify/remote-dom/pull/652) [`0789d12`](https://github.com/Shopify/remote-dom/commit/0789d12f61ae3a93bd659543b4607eb496efa090) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Add composable `Window` extensions for installing DOM APIs and subscribing to DOM operations.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [#681](https://github.com/Shopify/remote-dom/pull/681) [`fc245ba`](https://github.com/Shopify/remote-dom/commit/fc245ba6edd7622c4cccbd98e744d6934f04ab46) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Adopt complete subtrees, including initialized template content, during cross-document insertion so descendant and attribute mutations use the destination document.
|
|
20
|
+
|
|
21
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`dff700b`](https://github.com/Shopify/remote-dom/commit/dff700bcc9610903ad4f9e6d8b23e6017f113af8) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Dispatch attribute hooks when mutating an attached attribute's value or nodeValue.
|
|
22
|
+
|
|
23
|
+
- [#679](https://github.com/Shopify/remote-dom/pull/679) [`da43e02`](https://github.com/Shopify/remote-dom/commit/da43e02ef1662763d242ed3b386b5b57130aaef3) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Correct chained combinators, whitespace, exact attribute equality, and scoped relative `:has()` selectors, including leading combinators, nested functional pseudo-classes, and ASCII-case-insensitive pseudo-class names.
|
|
24
|
+
|
|
25
|
+
- [#642](https://github.com/Shopify/remote-dom/pull/642) [`85cefcd`](https://github.com/Shopify/remote-dom/commit/85cefcd63efe62de20aadb2fa75d08485b4f1d96) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Add the missing `CustomElementRegistry.initialize()` compatibility method so TypeScript 7 type checks cleanly.
|
|
26
|
+
|
|
27
|
+
- [#653](https://github.com/Shopify/remote-dom/pull/653) [`a9aee3e`](https://github.com/Shopify/remote-dom/commit/a9aee3e3834b621e0c9a4fd432a9eb674447403a) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Make the Polyfill source compatible with type stripping by replacing TypeScript enums and a parameter property with erasable syntax.
|
|
28
|
+
|
|
29
|
+
- [#668](https://github.com/Shopify/remote-dom/pull/668) [`f4af17f`](https://github.com/Shopify/remote-dom/commit/f4af17fb2739cd6cbbf3adf52c1af1fb695c749b) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Preserve attribute ownership and linked-list integrity when attributes are reinstalled, replaced, removed, or reused.
|
|
30
|
+
|
|
31
|
+
- [#683](https://github.com/Shopify/remote-dom/pull/683) [`c13d18b`](https://github.com/Shopify/remote-dom/commit/c13d18b5469de4e87900d7c8123ad18b653f6d4e) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Throw a named `NotSupportedError` when cloning a document or importing one with `Document.importNode()`.
|
|
32
|
+
|
|
33
|
+
- [#681](https://github.com/Shopify/remote-dom/pull/681) [`9904cdd`](https://github.com/Shopify/remote-dom/commit/9904cdd79af5589c3b43e884e27fa2ce10721b58) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Make `ChildNode.replaceWith()`, `before()`, and `after()` validate all arguments before changing existing trees, preserve sibling argument order, and commit each operation before custom-element reactions run.
|
|
34
|
+
|
|
35
|
+
- [#664](https://github.com/Shopify/remote-dom/pull/664) [`8de0600`](https://github.com/Shopify/remote-dom/commit/8de06005c7e4d843182fbd403699dc2df67bee33) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Correct event dispatch lifecycle state, isolate composed paths, and defer listener registrations added during dispatch.
|
|
36
|
+
|
|
37
|
+
- [#692](https://github.com/Shopify/remote-dom/pull/692) [`ee48d52`](https://github.com/Shopify/remote-dom/commit/ee48d5290023a22de7632d7e652438514a1c1cfb) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Throw named DOM errors for invalid tree mutations and selector syntax.
|
|
38
|
+
|
|
39
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`7eb8a18`](https://github.com/Shopify/remote-dom/commit/7eb8a18aa6753ac34e58d51cfda0533a99e88523) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Return `null` from `Document.textContent` and ignore assignments to preserve the initialized document structure.
|
|
40
|
+
|
|
41
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`6ddc71f`](https://github.com/Shopify/remote-dom/commit/6ddc71f50e2c492d71c8b506eebc08cf40559199) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Clear parent children without creating an empty text node when assigning an empty `textContent` value, and finish the complete replacement before running custom-element reactions.
|
|
42
|
+
|
|
43
|
+
- [#662](https://github.com/Shopify/remote-dom/pull/662) [`e249e3e`](https://github.com/Shopify/remote-dom/commit/e249e3e8055b7878442ad72fdd2b151cdc3c0171) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Correct event listener identity and AbortSignal handling in the EventTarget polyfill.
|
|
44
|
+
|
|
45
|
+
- [#663](https://github.com/Shopify/remote-dom/pull/663) [`44e3b36`](https://github.com/Shopify/remote-dom/commit/44e3b3677920a43a98a92b8179470d7ede0dac96) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Fix event cancellation semantics for `preventDefault()`, `returnValue`, and `dispatchEvent()`.
|
|
46
|
+
|
|
47
|
+
- [#666](https://github.com/Shopify/remote-dom/pull/666) [`072b7e8`](https://github.com/Shopify/remote-dom/commit/072b7e8a68855144cc359d11107874007c043f2b) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Install missing event methods and error handlers consistently without replacing native global event delivery.
|
|
48
|
+
|
|
49
|
+
- [#685](https://github.com/Shopify/remote-dom/pull/685) [`fd4de61`](https://github.com/Shopify/remote-dom/commit/fd4de61b0be8eac8e056941f288f0592404b57dc) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Preserve character references and literal ampersands when parsing `innerHTML`, decode attribute references without double-escaping, handle nested `innerHTML` parsing from synchronous callbacks, and handle HTML void elements without nesting following content or serializing closing tags.
|
|
50
|
+
|
|
51
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`fd8e186`](https://github.com/Shopify/remote-dom/commit/fd8e186d49bc1b3fa68ec0a26eb1de1a59c218c5) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Remove `slot` attributes without recreating them as empty attributes, keeping local and host state synchronized.
|
|
52
|
+
|
|
53
|
+
- [#688](https://github.com/Shopify/remote-dom/pull/688) [`5f0b228`](https://github.com/Shopify/remote-dom/commit/5f0b2281bddfc7ac37c64503f40f38f4f9b98243) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Default omitted CustomEvent detail values to null.
|
|
54
|
+
|
|
55
|
+
- [#688](https://github.com/Shopify/remote-dom/pull/688) [`08e3223`](https://github.com/Shopify/remote-dom/commit/08e3223a5fb340e80693168e04ed03a01764ef2a) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Include `Comment` nodes in the polyfill hook type contract.
|
|
56
|
+
|
|
57
|
+
- [#677](https://github.com/Shopify/remote-dom/pull/677) [`a629e25`](https://github.com/Shopify/remote-dom/commit/a629e25eb4eba6aae495257a40f30883b6dce53a) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Normalize and validate DOM element and attribute names across HTML and namespaced APIs, including `toggleAttribute()` and custom-element attribute reactions.
|
|
58
|
+
|
|
59
|
+
- [#688](https://github.com/Shopify/remote-dom/pull/688) [`e1acf97`](https://github.com/Shopify/remote-dom/commit/e1acf97baa3786d3284b6a0164ccc7206e3ec956) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Normalize `createTextNode()` hook data to match the created text node.
|
|
60
|
+
|
|
61
|
+
- [#685](https://github.com/Shopify/remote-dom/pull/685) [`0a39389`](https://github.com/Shopify/remote-dom/commit/0a3938987f46fd962ac84ed00808680852263df9) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Parse template descendants into template content and serialize that content with stack-safe HTML output.
|
|
62
|
+
|
|
63
|
+
- [#623](https://github.com/Shopify/remote-dom/pull/623) [`c3918c6`](https://github.com/Shopify/remote-dom/commit/c3918c61c3ee6b3aa6ec7fbf4d53aa76532ec29d) Thanks [@airhorns](https://github.com/airhorns)! - Fix `ChildNode.replaceWith()` throwing instead of replacing the node
|
|
64
|
+
|
|
65
|
+
`replaceWith()` passed its arguments to `replaceChild()` in the wrong order — `replaceChild(newChild, oldChild)` was called as `parent.replaceChild(this, node)`, naming the incoming node as the child to replace. Since that node is usually fresh and has no parent, the reference check rejected it and every call threw `reference node is not a child of this parent`. It also read the following sibling off the incoming node rather than off `this`, so the remaining arguments had no correct insertion point to anchor to.
|
|
66
|
+
|
|
67
|
+
The method now removes `this` and inserts the given nodes at its position, in argument order, anchored on the first following sibling that is not itself being moved. Strings become text nodes, calling it with no arguments removes the node (matching `remove()`), and a node with no parent is still left alone.
|
|
68
|
+
|
|
69
|
+
- [#714](https://github.com/Shopify/remote-dom/pull/714) [`516fcfa`](https://github.com/Shopify/remote-dom/commit/516fcfa4c4a04e8ff5a0e7c6b7da0d38d2dd1f57) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Resolve `Node.isDefaultNamespace()` with DOM locate-a-namespace semantics.
|
|
70
|
+
|
|
71
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`23ceb4d`](https://github.com/Shopify/remote-dom/commit/23ceb4d22c62096ffdb00d4d107ab2cacdc54935) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Return removed and replaced nodes from `removeChild` and `replaceChild`.
|
|
72
|
+
|
|
73
|
+
- [#679](https://github.com/Shopify/remote-dom/pull/679) [`5466415`](https://github.com/Shopify/remote-dom/commit/54664151820316d9f655e9964de232854fdec5c4) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Return a NodeList-compatible collection from `querySelectorAll()`.
|
|
74
|
+
|
|
75
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`d916fab`](https://github.com/Shopify/remote-dom/commit/d916fabc327a9352c1f3e8b2d37f939527d2027a) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Queue custom-element reactions so compound tree and attribute mutations commit their local state and Remote DOM hooks before callbacks run. Drain nested reactions in FIFO order, and finish the queue before rethrowing the first callback error.
|
|
76
|
+
|
|
77
|
+
- [#669](https://github.com/Shopify/remote-dom/pull/669) [`4b8bae9`](https://github.com/Shopify/remote-dom/commit/4b8bae9a507cf80492fb3b03975b90872b76465c) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Traverse wide and deep trees without overflowing the call stack during text collection, selector queries, and subtree connectivity updates. Prepare insertion snapshots transactionally before committing links, connectivity, hooks, and reactions so traversal failures preserve local and remote tree state. Capture lifecycle reactions in mutation order before emitting reentrant tree-mutation hook effects through a FIFO queue.
|
|
78
|
+
|
|
79
|
+
- [#676](https://github.com/Shopify/remote-dom/pull/676) [`6b42b09`](https://github.com/Shopify/remote-dom/commit/6b42b0980b3d2b01a1029ae1cab52345e0fb021a) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Make `CustomElementRegistry.define()` reject invalid custom element names and duplicate name or constructor registrations, matching browser behavior.
|
|
80
|
+
|
|
81
|
+
- [#660](https://github.com/Shopify/remote-dom/pull/660) [`685dff1`](https://github.com/Shopify/remote-dom/commit/685dff1a617c97afc5079edb742940bb6ff92022) Thanks [@andrewiggins](https://github.com/andrewiggins)! - Correct class selector whitespace parsing and return polyfilled `NodeList` collections from selector queries.
|
|
82
|
+
|
|
83
|
+
- [#683](https://github.com/Shopify/remote-dom/pull/683) [`7181475`](https://github.com/Shopify/remote-dom/commit/71814754bcd9a06155e9a284867c93031c133007) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Preserve established element and attribute names, namespaces, and both direct and template-content trees when cloning or importing nodes without recursive traversal.
|
|
84
|
+
|
|
85
|
+
- [#688](https://github.com/Shopify/remote-dom/pull/688) [`3c57e5b`](https://github.com/Shopify/remote-dom/commit/3c57e5b6202f0779eb7ee99ad3298f6d17032c51) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Fix `Node.contains()` for nested descendants and nodes outside the current subtree.
|
|
86
|
+
|
|
87
|
+
- [#667](https://github.com/Shopify/remote-dom/pull/667) [`cdfd5dd`](https://github.com/Shopify/remote-dom/commit/cdfd5dd2bc3fecbea7799d3921bb8d93bd6103dd) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Validate tree insertions and replacements before changing node links so invalid ancestor, template-content cycle, and reference-node mutations preserve the existing trees. Treat inserting a node before itself as a no-op and safely replace a child with its next sibling.
|
|
88
|
+
|
|
89
|
+
- [#687](https://github.com/Shopify/remote-dom/pull/687) [`db32f49`](https://github.com/Shopify/remote-dom/commit/db32f49fbbe0bdfd1e14450008b5b8634d2362d7) Thanks [@olavoasantos](https://github.com/olavoasantos)! - Ignore unmatched closing tags, preserve SVG and HTML namespace boundaries, and retain literal parser names while parsing `innerHTML`.
|
|
90
|
+
|
|
3
91
|
## 1.5.1
|
|
4
92
|
|
|
5
93
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -34,12 +34,60 @@ This process will install polyfilled versions of the following globals:
|
|
|
34
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
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
36
|
|
|
37
|
-
|
|
37
|
+
## Extensions
|
|
38
|
+
|
|
39
|
+
Use `Window.with()` to create a reusable `Window` subclass with additional DOM
|
|
40
|
+
APIs or behavior. An extension is a function with two distinct parts:
|
|
41
|
+
|
|
42
|
+
- **The function body runs once per window, during construction.** It receives
|
|
43
|
+
the new `Window` instance and can install or replace APIs on it, like
|
|
44
|
+
`window.MutationObserver`. Use it for setup, not for reacting to DOM changes.
|
|
45
|
+
- **The returned hooks run for the lifetime of the window.** They subscribe to
|
|
46
|
+
DOM operations on that window, such as creating elements, setting attributes,
|
|
47
|
+
and adding event listeners, and are called each time one of those operations
|
|
48
|
+
happens. Returning hooks is optional.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import {Window, type WindowExtension} from '@remote-dom/polyfill';
|
|
52
|
+
|
|
53
|
+
class CustomMutationObserver {}
|
|
54
|
+
|
|
55
|
+
const mutationObserverExtension: WindowExtension = (window) => {
|
|
56
|
+
// Construction time: extend this window instance.
|
|
57
|
+
window.MutationObserver = CustomMutationObserver;
|
|
58
|
+
|
|
59
|
+
// Runtime: subscribe to DOM operations on this window.
|
|
60
|
+
return {
|
|
61
|
+
setAttribute(element, name, value) {
|
|
62
|
+
// Notify observers associated with this window.
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const ExtendedWindow = Window.with(mutationObserverExtension);
|
|
68
|
+
const window = new ExtendedWindow();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Extensions are installed in the order passed to `Window.with()` and across
|
|
72
|
+
chained `.with()` calls. The two parts compose differently:
|
|
73
|
+
|
|
74
|
+
- **Window APIs override.** Assignments like `window.MutationObserver = …` are
|
|
75
|
+
plain property writes, so when multiple extensions set the same API, the last
|
|
76
|
+
extension installed wins.
|
|
77
|
+
- **Hooks are additive.** Every installed extension’s hooks are called in
|
|
78
|
+
installation order for each DOM operation.
|
|
79
|
+
|
|
80
|
+
Extensions are installed after the base window and its initial document have
|
|
81
|
+
been constructed, so their hooks do not observe the document’s bootstrap.
|
|
82
|
+
|
|
83
|
+
Assigning hooks directly through the exported `HOOKS` symbol is the legacy
|
|
84
|
+
integration API. New integrations should use extensions instead. Extension
|
|
85
|
+
hooks run first, followed by the legacy hook assigned through `window[HOOKS]`:
|
|
38
86
|
|
|
39
87
|
```ts
|
|
40
|
-
import {
|
|
88
|
+
import {HOOKS} from '@remote-dom/polyfill';
|
|
41
89
|
|
|
42
|
-
|
|
90
|
+
window[HOOKS].createElement = (element) => {
|
|
43
91
|
console.log('Creating element:', element);
|
|
44
92
|
};
|
|
45
93
|
```
|
package/build/cjs/Attr.cjs
CHANGED
|
@@ -4,9 +4,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4
4
|
|
|
5
5
|
const constants = require('./constants.cjs');
|
|
6
6
|
const Node = require('./Node.cjs');
|
|
7
|
+
const MutationObserver = require('./MutationObserver.cjs');
|
|
8
|
+
const attributeReactions = require('./attribute-reactions.cjs');
|
|
9
|
+
const customElementReactions = require('./custom-element-reactions.cjs');
|
|
7
10
|
|
|
8
11
|
class Attr extends Node.Node {
|
|
9
|
-
nodeType =
|
|
12
|
+
nodeType = constants.NODE_TYPE_ATTRIBUTE;
|
|
10
13
|
[constants.NS] = null;
|
|
11
14
|
[constants.NEXT] = null;
|
|
12
15
|
[constants.OWNER_ELEMENT] = null;
|
|
@@ -24,15 +27,41 @@ class Attr extends Node.Node {
|
|
|
24
27
|
return this[constants.NAME];
|
|
25
28
|
}
|
|
26
29
|
set name(_readonly) {}
|
|
30
|
+
get localName() {
|
|
31
|
+
if (this[constants.NS] == null) return this[constants.NAME];
|
|
32
|
+
const separator = this[constants.NAME].indexOf(':');
|
|
33
|
+
return separator < 0 ? this[constants.NAME] : this[constants.NAME].slice(separator + 1);
|
|
34
|
+
}
|
|
35
|
+
get prefix() {
|
|
36
|
+
if (this[constants.NS] == null) return null;
|
|
37
|
+
const separator = this[constants.NAME].indexOf(':');
|
|
38
|
+
return separator < 0 ? null : this[constants.NAME].slice(0, separator);
|
|
39
|
+
}
|
|
27
40
|
get value() {
|
|
28
41
|
return this[constants.VALUE];
|
|
29
42
|
}
|
|
30
43
|
set value(value) {
|
|
31
44
|
const str = String(value);
|
|
32
|
-
this[constants.VALUE] = str;
|
|
33
45
|
const ownerElement = this[constants.OWNER_ELEMENT];
|
|
34
|
-
if (!ownerElement)
|
|
35
|
-
|
|
46
|
+
if (!ownerElement) {
|
|
47
|
+
this[constants.VALUE] = str;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
customElementReactions.performWithCustomElementReactions(() => {
|
|
51
|
+
const oldValue = this[constants.VALUE];
|
|
52
|
+
this[constants.VALUE] = str;
|
|
53
|
+
if (MutationObserver.attributeObserversActive && oldValue !== str) {
|
|
54
|
+
MutationObserver.queueMutationRecord({
|
|
55
|
+
type: 'attributes',
|
|
56
|
+
target: ownerElement,
|
|
57
|
+
attributeName: this[constants.NAME],
|
|
58
|
+
attributeNamespace: this[constants.NS],
|
|
59
|
+
oldValue
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
this[constants.HOOKS].setAttribute?.(ownerElement, this[constants.NAME], str, this[constants.NS]);
|
|
63
|
+
attributeReactions.enqueueAttributeReaction(ownerElement, this.localName, oldValue, str, this[constants.NS]);
|
|
64
|
+
});
|
|
36
65
|
}
|
|
37
66
|
get nodeValue() {
|
|
38
67
|
return this.value;
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4
4
|
|
|
5
5
|
const constants = require('./constants.cjs');
|
|
6
6
|
const ChildNode = require('./ChildNode.cjs');
|
|
7
|
+
const MutationObserver = require('./MutationObserver.cjs');
|
|
7
8
|
|
|
8
9
|
class CharacterData extends ChildNode.ChildNode {
|
|
9
10
|
[constants.DATA] = '';
|
|
@@ -12,11 +13,20 @@ class CharacterData extends ChildNode.ChildNode {
|
|
|
12
13
|
this[constants.DATA] = data == null ? '' : String(data);
|
|
13
14
|
}
|
|
14
15
|
setData(data) {
|
|
16
|
+
const shouldQueueMutation = MutationObserver.characterDataObserversActive;
|
|
17
|
+
const oldValue = shouldQueueMutation ? this[constants.DATA] : null;
|
|
15
18
|
let str = '';
|
|
16
19
|
if (data != null) {
|
|
17
20
|
str = typeof data === 'string' ? data : String(data);
|
|
18
21
|
}
|
|
19
22
|
this[constants.DATA] = str;
|
|
23
|
+
if (shouldQueueMutation && oldValue !== str) {
|
|
24
|
+
MutationObserver.queueMutationRecord({
|
|
25
|
+
type: 'characterData',
|
|
26
|
+
target: this,
|
|
27
|
+
oldValue
|
|
28
|
+
});
|
|
29
|
+
}
|
|
20
30
|
this[constants.HOOKS].setText?.(this, str);
|
|
21
31
|
}
|
|
22
32
|
get data() {
|
package/build/cjs/ChildNode.cjs
CHANGED
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
5
|
const constants = require('./constants.cjs');
|
|
6
|
+
const customElementReactions = require('./custom-element-reactions.cjs');
|
|
7
|
+
const hookEffects = require('./hook-effects.cjs');
|
|
8
|
+
const domException = require('./dom-exception.cjs');
|
|
6
9
|
const Node = require('./Node.cjs');
|
|
7
10
|
|
|
11
|
+
const INSERT_NODE = Symbol('insertNode');
|
|
12
|
+
const PREFLIGHT_INSERTIONS = Symbol('preflightInsertions');
|
|
13
|
+
const REPLACE_NODE = Symbol('replaceNode');
|
|
8
14
|
class ChildNode extends Node.Node {
|
|
9
15
|
remove() {
|
|
10
16
|
const parent = this.parentNode;
|
|
@@ -12,36 +18,96 @@ class ChildNode extends Node.Node {
|
|
|
12
18
|
parent.removeChild(this);
|
|
13
19
|
}
|
|
14
20
|
replaceWith(...nodes) {
|
|
21
|
+
const staged = stageNodes(nodes);
|
|
15
22
|
const parent = this.parentNode;
|
|
16
23
|
if (!parent) return;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
return performChildNodeMutation(hookEffects => {
|
|
25
|
+
validateInsertionNodes(parent, staged);
|
|
26
|
+
let next = this[constants.NEXT];
|
|
27
|
+
while (next && staged.includes(next)) next = next[constants.NEXT];
|
|
28
|
+
const replacement = convertNodesIntoNode(parent, staged, hookEffects);
|
|
29
|
+
if (this.parentNode === parent) {
|
|
30
|
+
parent[REPLACE_NODE](replacement, this, hookEffects);
|
|
31
|
+
} else {
|
|
32
|
+
parent[INSERT_NODE](replacement, next, hookEffects);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
23
35
|
}
|
|
24
36
|
before(...nodes) {
|
|
37
|
+
const staged = stageNodes(nodes);
|
|
25
38
|
const parent = this.parentNode;
|
|
26
39
|
if (!parent) return;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
return performChildNodeMutation(hookEffects => {
|
|
41
|
+
validateInsertionNodes(parent, staged);
|
|
42
|
+
let previous = this[constants.PREV];
|
|
43
|
+
while (previous && staged.includes(previous)) previous = previous[constants.PREV];
|
|
44
|
+
const node = convertNodesIntoNode(parent, staged, hookEffects);
|
|
45
|
+
parent[INSERT_NODE](node, previous ? previous[constants.NEXT] : parent.firstChild, hookEffects);
|
|
46
|
+
});
|
|
30
47
|
}
|
|
31
48
|
after(...nodes) {
|
|
49
|
+
const staged = stageNodes(nodes);
|
|
32
50
|
const parent = this.parentNode;
|
|
33
51
|
if (!parent) return;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
return performChildNodeMutation(hookEffects => {
|
|
53
|
+
validateInsertionNodes(parent, staged);
|
|
54
|
+
let next = this[constants.NEXT];
|
|
55
|
+
while (next && staged.includes(next)) next = next[constants.NEXT];
|
|
56
|
+
const node = convertNodesIntoNode(parent, staged, hookEffects);
|
|
57
|
+
parent[INSERT_NODE](node, next, hookEffects);
|
|
58
|
+
});
|
|
38
59
|
}
|
|
39
60
|
}
|
|
61
|
+
function performChildNodeMutation(mutation) {
|
|
62
|
+
return customElementReactions.performWithCustomElementReactions(() => {
|
|
63
|
+
const hookEffects$1 = [];
|
|
64
|
+
try {
|
|
65
|
+
mutation(hookEffects$1);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
try {
|
|
68
|
+
hookEffects.performHookEffects(hookEffects$1);
|
|
69
|
+
} catch {}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
hookEffects.performHookEffects(hookEffects$1);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function stageNodes(nodes) {
|
|
76
|
+
return nodes.map(node => node instanceof Node.Node ? node : String(node));
|
|
77
|
+
}
|
|
40
78
|
function toNode(parent, node) {
|
|
41
79
|
if (node instanceof Node.Node) return node;
|
|
42
80
|
const ownerDocument = parent.ownerDocument;
|
|
43
81
|
return ownerDocument.createTextNode(String(node));
|
|
44
82
|
}
|
|
83
|
+
function validateInsertionNodes(parent, nodes) {
|
|
84
|
+
for (const node of nodes) {
|
|
85
|
+
if (!(node instanceof Node.Node)) continue;
|
|
86
|
+
let ancestor = parent;
|
|
87
|
+
while (ancestor) {
|
|
88
|
+
if (ancestor === node) {
|
|
89
|
+
throw domException.createDOMException('Cannot insert a node into itself or one of its descendants', 'HierarchyRequestError');
|
|
90
|
+
}
|
|
91
|
+
ancestor = ancestor[constants.PARENT] ?? ancestor[constants.HOST];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function convertNodesIntoNode(parent, nodes, hookEffects) {
|
|
96
|
+
const convertedNodes = [];
|
|
97
|
+
for (const node of nodes) convertedNodes.push(toNode(parent, node));
|
|
98
|
+
if (convertedNodes.length === 1) return convertedNodes[0];
|
|
99
|
+
const fragment = parent.ownerDocument.createDocumentFragment();
|
|
100
|
+
fragment[PREFLIGHT_INSERTIONS](convertedNodes);
|
|
101
|
+
for (const node of convertedNodes) {
|
|
102
|
+
fragment[INSERT_NODE](node, null, hookEffects);
|
|
103
|
+
}
|
|
104
|
+
return fragment;
|
|
105
|
+
}
|
|
45
106
|
|
|
46
107
|
exports.ChildNode = ChildNode;
|
|
108
|
+
exports.INSERT_NODE = INSERT_NODE;
|
|
109
|
+
exports.PREFLIGHT_INSERTIONS = PREFLIGHT_INSERTIONS;
|
|
110
|
+
exports.REPLACE_NODE = REPLACE_NODE;
|
|
111
|
+
exports.stageNodes = stageNodes;
|
|
47
112
|
exports.toNode = toNode;
|
|
113
|
+
exports.validateInsertionNodes = validateInsertionNodes;
|
package/build/cjs/Comment.cjs
CHANGED
|
@@ -2,10 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
|
+
const domException = require('./dom-exception.cjs');
|
|
6
|
+
|
|
7
|
+
const VALID_CUSTOM_ELEMENT_NAME = /^[a-z][^A-Z\u0000\t\n\f\r />]*-[^A-Z\u0000\t\n\f\r />]*$/u;
|
|
8
|
+
const RESERVED_CUSTOM_ELEMENT_NAMES = new Set(['annotation-xml', 'color-profile', 'font-face', 'font-face-src', 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph']);
|
|
9
|
+
function isValidCustomElementName(name) {
|
|
10
|
+
return VALID_CUSTOM_ELEMENT_NAME.test(name) && !RESERVED_CUSTOM_ELEMENT_NAMES.has(name);
|
|
11
|
+
}
|
|
12
|
+
function createInvalidCustomElementNameError(name) {
|
|
13
|
+
return domException.createDOMException(`Invalid custom element name: "${name}"`, 'SyntaxError');
|
|
14
|
+
}
|
|
5
15
|
class CustomElementRegistryImplementation {
|
|
6
|
-
registry =
|
|
7
|
-
listenersByName =
|
|
16
|
+
registry = new Map();
|
|
17
|
+
listenersByName = new Map();
|
|
8
18
|
define(name, Constructor, _options) {
|
|
19
|
+
if (!isValidCustomElementName(name)) {
|
|
20
|
+
throw createInvalidCustomElementNameError(name);
|
|
21
|
+
}
|
|
22
|
+
if (this.registry.has(name)) {
|
|
23
|
+
throw domException.createDOMException(`A custom element named "${name}" has already been defined`, 'NotSupportedError');
|
|
24
|
+
}
|
|
25
|
+
if (this.getName(Constructor) != null) {
|
|
26
|
+
throw domException.createDOMException('This constructor has already been registered in this custom element registry', 'NotSupportedError');
|
|
27
|
+
}
|
|
9
28
|
this.registry.set(name, Constructor);
|
|
10
29
|
const listeners = this.listenersByName.get(name);
|
|
11
30
|
if (listeners == null) return;
|
|
@@ -24,6 +43,9 @@ class CustomElementRegistryImplementation {
|
|
|
24
43
|
return null;
|
|
25
44
|
}
|
|
26
45
|
whenDefined(name) {
|
|
46
|
+
if (!isValidCustomElementName(name)) {
|
|
47
|
+
return Promise.reject(createInvalidCustomElementNameError(name));
|
|
48
|
+
}
|
|
27
49
|
const Constructor = this.registry.get(name);
|
|
28
50
|
if (Constructor != null) return Promise.resolve(Constructor);
|
|
29
51
|
let listeners = this.listenersByName.get(name);
|
|
@@ -38,6 +60,9 @@ class CustomElementRegistryImplementation {
|
|
|
38
60
|
upgrade(_root) {
|
|
39
61
|
// TODO
|
|
40
62
|
}
|
|
63
|
+
initialize(_root) {
|
|
64
|
+
// TODO
|
|
65
|
+
}
|
|
41
66
|
}
|
|
42
67
|
|
|
43
68
|
exports.CustomElementRegistryImplementation = CustomElementRegistryImplementation;
|
|
@@ -13,7 +13,7 @@ class CustomEvent extends Event.Event {
|
|
|
13
13
|
|
|
14
14
|
constructor(type, eventInitDict) {
|
|
15
15
|
super(type, eventInitDict);
|
|
16
|
-
this.detail = eventInitDict?.detail;
|
|
16
|
+
this.detail = eventInitDict?.detail ?? null;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -23,7 +23,7 @@ class CustomEvent extends Event.Event {
|
|
|
23
23
|
*/
|
|
24
24
|
initCustomEvent(type, bubbles, cancelable, detail) {
|
|
25
25
|
super.initEvent(type, bubbles, cancelable);
|
|
26
|
-
this.detail = detail;
|
|
26
|
+
this.detail = detail ?? null;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
package/build/cjs/Document.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
5
|
const constants = require('./constants.cjs');
|
|
6
|
+
const names = require('./names.cjs');
|
|
6
7
|
const Event = require('./Event.cjs');
|
|
7
8
|
const ParentNode = require('./ParentNode.cjs');
|
|
8
9
|
const Element = require('./Element.cjs');
|
|
@@ -15,9 +16,11 @@ const shared = require('./shared.cjs');
|
|
|
15
16
|
const HTMLBodyElement = require('./HTMLBodyElement.cjs');
|
|
16
17
|
const HTMLHeadElement = require('./HTMLHeadElement.cjs');
|
|
17
18
|
const HTMLHtmlElement = require('./HTMLHtmlElement.cjs');
|
|
19
|
+
const customElementReactions = require('./custom-element-reactions.cjs');
|
|
20
|
+
const domException = require('./dom-exception.cjs');
|
|
18
21
|
|
|
19
22
|
class Document extends ParentNode.ParentNode {
|
|
20
|
-
nodeType =
|
|
23
|
+
nodeType = constants.NODE_TYPE_DOCUMENT;
|
|
21
24
|
[constants.NAME] = '#document';
|
|
22
25
|
[constants.IS_CONNECTED] = true;
|
|
23
26
|
constructor(defaultView) {
|
|
@@ -31,15 +34,29 @@ class Document extends ParentNode.ParentNode {
|
|
|
31
34
|
this.documentElement.appendChild(this.head);
|
|
32
35
|
this.documentElement.appendChild(this.body);
|
|
33
36
|
}
|
|
37
|
+
get textContent() {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
set textContent(data) {
|
|
41
|
+
}
|
|
42
|
+
getElementsByClassName(classNames) {
|
|
43
|
+
return shared.getElementsByClassName(this, classNames);
|
|
44
|
+
}
|
|
34
45
|
createElement(localName) {
|
|
35
|
-
|
|
46
|
+
const name = String(localName);
|
|
47
|
+
names.validateElementLocalName(name);
|
|
48
|
+
return createElement(this, constants.asciiLowercase(name));
|
|
36
49
|
}
|
|
37
|
-
createElementNS(namespaceURI,
|
|
38
|
-
|
|
50
|
+
createElementNS(namespaceURI, qualifiedName) {
|
|
51
|
+
const name = names.validateAndExtractQualifiedName(namespaceURI, qualifiedName, 'element');
|
|
52
|
+
return createElement(this, name.qualifiedName, name.namespace, name.prefix, name.localName);
|
|
53
|
+
}
|
|
54
|
+
[constants.CREATE_ELEMENT](qualifiedName, namespace, prefix, localName) {
|
|
55
|
+
return createElement(this, qualifiedName, namespace, prefix, localName);
|
|
39
56
|
}
|
|
40
57
|
createTextNode(data) {
|
|
41
58
|
const text = createNode(new Text.Text(data), this);
|
|
42
|
-
this[constants.HOOKS].createText?.(text,
|
|
59
|
+
this[constants.HOOKS].createText?.(text, text.data);
|
|
43
60
|
return text;
|
|
44
61
|
}
|
|
45
62
|
createComment(data) {
|
|
@@ -51,14 +68,26 @@ class Document extends ParentNode.ParentNode {
|
|
|
51
68
|
createEvent() {
|
|
52
69
|
return new Event.Event('');
|
|
53
70
|
}
|
|
71
|
+
getElementById(elementId) {
|
|
72
|
+
return shared.getElementById(this, elementId);
|
|
73
|
+
}
|
|
74
|
+
getElementsByTagName(qualifiedName) {
|
|
75
|
+
return shared.getElementsByTagName(this, qualifiedName);
|
|
76
|
+
}
|
|
54
77
|
importNode(node, deep) {
|
|
78
|
+
if (node.nodeType === constants.NODE_TYPE_DOCUMENT) {
|
|
79
|
+
throw domException.createDOMException('Cannot import a document node', 'NotSupportedError');
|
|
80
|
+
}
|
|
55
81
|
return shared.cloneNode(node, deep, this);
|
|
56
82
|
}
|
|
57
83
|
adoptNode(node) {
|
|
58
84
|
if (node[constants.OWNER_DOCUMENT] === this) return node;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
85
|
+
const adoption = shared.collectAdoptionSnapshot(node);
|
|
86
|
+
return customElementReactions.performWithCustomElementReactions(() => {
|
|
87
|
+
const parent = node.parentNode;
|
|
88
|
+
if (parent) ParentNode.removeChildForAdoption(parent, node, adoption, this);else shared.adoptNodes(adoption.nodes, this);
|
|
89
|
+
return node;
|
|
90
|
+
});
|
|
62
91
|
}
|
|
63
92
|
}
|
|
64
93
|
function createNode(node, ownerDocument) {
|
|
@@ -69,43 +98,38 @@ function createNode(node, ownerDocument) {
|
|
|
69
98
|
});
|
|
70
99
|
return node;
|
|
71
100
|
}
|
|
72
|
-
function createElement(ownerDocument,
|
|
101
|
+
function createElement(ownerDocument, qualifiedName, namespace = constants.HTML_NAMESPACE, prefix = null, localName = qualifiedName) {
|
|
73
102
|
let element;
|
|
74
|
-
|
|
75
|
-
if (namespace === constants.NamespaceURI.SVG) {
|
|
103
|
+
if (namespace === constants.SVG_NAMESPACE) {
|
|
76
104
|
element = new SVGElement.SVGElement();
|
|
77
|
-
} else if (
|
|
105
|
+
} else if (namespace === constants.HTML_NAMESPACE && localName === 'template') {
|
|
78
106
|
element = new HTMLTemplateElement.HTMLTemplateElement();
|
|
79
|
-
} else {
|
|
80
|
-
const CustomElement = ownerDocument.defaultView.customElements.get(
|
|
107
|
+
} else if (namespace === constants.HTML_NAMESPACE) {
|
|
108
|
+
const CustomElement = ownerDocument.defaultView.customElements.get(localName);
|
|
81
109
|
element = CustomElement ? new CustomElement() : new Element.Element();
|
|
110
|
+
} else {
|
|
111
|
+
element = new Element.Element();
|
|
82
112
|
}
|
|
83
|
-
return setupElement(element, ownerDocument,
|
|
113
|
+
return setupElement(element, ownerDocument, qualifiedName, namespace, prefix);
|
|
84
114
|
}
|
|
85
|
-
function setupElement(element, ownerDocument,
|
|
115
|
+
function setupElement(element, ownerDocument, qualifiedName, namespace = constants.HTML_NAMESPACE, prefix = null) {
|
|
86
116
|
createNode(element, ownerDocument);
|
|
87
|
-
Object.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
117
|
+
Object.defineProperties(element, {
|
|
118
|
+
[constants.NAME]: {
|
|
119
|
+
value: qualifiedName
|
|
120
|
+
},
|
|
121
|
+
[constants.NS]: {
|
|
92
122
|
value: namespace
|
|
93
|
-
}
|
|
94
|
-
|
|
123
|
+
},
|
|
124
|
+
[constants.PREFIX]: {
|
|
125
|
+
value: prefix
|
|
126
|
+
}
|
|
127
|
+
});
|
|
95
128
|
ownerDocument[constants.HOOKS].createElement?.(element, namespace);
|
|
96
129
|
return element;
|
|
97
130
|
}
|
|
98
|
-
function adoptNode(node, document) {
|
|
99
|
-
node[constants.OWNER_DOCUMENT] = document;
|
|
100
|
-
if (shared.isParentNode(node)) {
|
|
101
|
-
for (const child of node.childNodes) {
|
|
102
|
-
adoptNode(child, document);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
131
|
|
|
107
132
|
exports.Document = Document;
|
|
108
|
-
exports.adoptNode = adoptNode;
|
|
109
133
|
exports.createElement = createElement;
|
|
110
134
|
exports.createNode = createNode;
|
|
111
135
|
exports.setupElement = setupElement;
|
|
@@ -4,11 +4,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4
4
|
|
|
5
5
|
const constants = require('./constants.cjs');
|
|
6
6
|
const ParentNode = require('./ParentNode.cjs');
|
|
7
|
+
const shared = require('./shared.cjs');
|
|
7
8
|
|
|
8
9
|
class DocumentFragment extends ParentNode.ParentNode {
|
|
9
|
-
nodeType =
|
|
10
|
+
nodeType = constants.NODE_TYPE_DOCUMENT_FRAGMENT;
|
|
10
11
|
[constants.NAME] = '#document-fragment';
|
|
11
|
-
[constants.OWNER_DOCUMENT] =
|
|
12
|
+
[constants.OWNER_DOCUMENT] = typeof window !== 'undefined' ? window.document : null;
|
|
13
|
+
getElementById(elementId) {
|
|
14
|
+
return shared.getElementById(this, elementId);
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
exports.DocumentFragment = DocumentFragment;
|