@remote-dom/polyfill 1.5.0 → 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.
Files changed (304) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +51 -3
  3. package/build/cjs/Attr.cjs +33 -4
  4. package/build/cjs/CharacterData.cjs +10 -0
  5. package/build/cjs/ChildNode.cjs +79 -13
  6. package/build/cjs/Comment.cjs +1 -1
  7. package/build/cjs/CustomElementRegistry.cjs +27 -2
  8. package/build/cjs/CustomEvent.cjs +2 -2
  9. package/build/cjs/Document.cjs +56 -32
  10. package/build/cjs/DocumentFragment.cjs +6 -2
  11. package/build/cjs/Element.cjs +68 -8
  12. package/build/cjs/Event.cjs +29 -27
  13. package/build/cjs/EventTarget.cjs +128 -58
  14. package/build/cjs/HTMLTemplateElement.cjs +1 -0
  15. package/build/cjs/MutationObserver.cjs +167 -1
  16. package/build/cjs/NamedNodeMap.cjs +82 -45
  17. package/build/cjs/Node.cjs +47 -11
  18. package/build/cjs/NodeList.cjs +9 -1
  19. package/build/cjs/ParentNode.cjs +319 -77
  20. package/build/cjs/SVGElement.cjs +1 -1
  21. package/build/cjs/Text.cjs +1 -1
  22. package/build/cjs/Window.cjs +131 -38
  23. package/build/cjs/attribute-reactions.cjs +20 -0
  24. package/build/cjs/constants.cjs +48 -24
  25. package/build/cjs/custom-element-reactions.cjs +52 -0
  26. package/build/cjs/dom-exception.cjs +15 -0
  27. package/build/cjs/hook-effects.cjs +51 -0
  28. package/build/cjs/names.cjs +61 -0
  29. package/build/cjs/selectors.cjs +213 -122
  30. package/build/cjs/serialization.cjs +168 -65
  31. package/build/cjs/shared.cjs +177 -28
  32. package/build/esm/Attr.mjs +34 -5
  33. package/build/esm/CharacterData.mjs +10 -0
  34. package/build/esm/ChildNode.mjs +76 -15
  35. package/build/esm/Comment.mjs +2 -2
  36. package/build/esm/CustomElementRegistry.mjs +27 -2
  37. package/build/esm/CustomEvent.mjs +2 -2
  38. package/build/esm/Document.mjs +60 -35
  39. package/build/esm/DocumentFragment.mjs +7 -3
  40. package/build/esm/Element.mjs +69 -9
  41. package/build/esm/Event.mjs +27 -27
  42. package/build/esm/EventTarget.mjs +130 -60
  43. package/build/esm/HTMLTemplateElement.mjs +2 -1
  44. package/build/esm/MutationObserver.mjs +166 -2
  45. package/build/esm/NamedNodeMap.mjs +83 -46
  46. package/build/esm/Node.mjs +48 -12
  47. package/build/esm/NodeList.mjs +9 -1
  48. package/build/esm/ParentNode.mjs +322 -81
  49. package/build/esm/SVGElement.mjs +2 -2
  50. package/build/esm/Text.mjs +2 -2
  51. package/build/esm/Window.mjs +132 -39
  52. package/build/esm/attribute-reactions.mjs +16 -0
  53. package/build/esm/constants.mjs +28 -23
  54. package/build/esm/custom-element-reactions.mjs +47 -0
  55. package/build/esm/dom-exception.mjs +11 -0
  56. package/build/esm/hook-effects.mjs +46 -0
  57. package/build/esm/names.mjs +54 -0
  58. package/build/esm/selectors.mjs +202 -124
  59. package/build/esm/serialization.mjs +169 -66
  60. package/build/esm/shared.mjs +173 -30
  61. package/build/esnext/Attr.esnext +45 -5
  62. package/build/esnext/CharacterData.esnext +10 -0
  63. package/build/esnext/ChildNode.esnext +84 -15
  64. package/build/esnext/Comment.esnext +2 -2
  65. package/build/esnext/CustomElementRegistry.esnext +42 -0
  66. package/build/esnext/CustomEvent.esnext +2 -2
  67. package/build/esnext/Document.esnext +69 -32
  68. package/build/esnext/DocumentFragment.esnext +7 -3
  69. package/build/esnext/Element.esnext +78 -9
  70. package/build/esnext/Event.esnext +36 -37
  71. package/build/esnext/EventTarget.esnext +133 -61
  72. package/build/esnext/HTMLTemplateElement.esnext +3 -1
  73. package/build/esnext/MutationObserver.esnext +163 -2
  74. package/build/esnext/NamedNodeMap.esnext +110 -42
  75. package/build/esnext/Node.esnext +50 -12
  76. package/build/esnext/NodeList.esnext +1 -1
  77. package/build/esnext/ParentNode.esnext +352 -79
  78. package/build/esnext/SVGElement.esnext +2 -2
  79. package/build/esnext/Text.esnext +2 -2
  80. package/build/esnext/Window.esnext +120 -16
  81. package/build/esnext/attribute-reactions.esnext +21 -0
  82. package/build/esnext/constants.esnext +34 -21
  83. package/build/esnext/custom-element-reactions.esnext +49 -0
  84. package/build/esnext/dom-exception.esnext +11 -0
  85. package/build/esnext/hook-effects.esnext +46 -0
  86. package/build/esnext/names.esnext +61 -0
  87. package/build/esnext/selectors.esnext +202 -100
  88. package/build/esnext/serialization.esnext +171 -48
  89. package/build/esnext/shared.esnext +181 -34
  90. package/build/tsconfig.tsbuildinfo +1 -1
  91. package/build/typescript/Attr.d.ts +6 -4
  92. package/build/typescript/Attr.d.ts.map +1 -1
  93. package/build/typescript/CharacterData.d.ts.map +1 -1
  94. package/build/typescript/ChildNode.d.ts +5 -0
  95. package/build/typescript/ChildNode.d.ts.map +1 -1
  96. package/build/typescript/ClipboardEvent.d.ts.map +1 -1
  97. package/build/typescript/Comment.d.ts +2 -2
  98. package/build/typescript/Comment.d.ts.map +1 -1
  99. package/build/typescript/CustomElementRegistry.d.ts +1 -0
  100. package/build/typescript/CustomElementRegistry.d.ts.map +1 -1
  101. package/build/typescript/CustomEvent.d.ts.map +1 -1
  102. package/build/typescript/Document.d.ts +10 -5
  103. package/build/typescript/Document.d.ts.map +1 -1
  104. package/build/typescript/DocumentFragment.d.ts +2 -1
  105. package/build/typescript/DocumentFragment.d.ts.map +1 -1
  106. package/build/typescript/Element.d.ts +16 -7
  107. package/build/typescript/Element.d.ts.map +1 -1
  108. package/build/typescript/ErrorEvent.d.ts.map +1 -1
  109. package/build/typescript/Event.d.ts +9 -10
  110. package/build/typescript/Event.d.ts.map +1 -1
  111. package/build/typescript/EventTarget.d.ts +20 -3
  112. package/build/typescript/EventTarget.d.ts.map +1 -1
  113. package/build/typescript/FocusEvent.d.ts.map +1 -1
  114. package/build/typescript/HTMLTemplateElement.d.ts.map +1 -1
  115. package/build/typescript/MutationObserver.d.ts +42 -0
  116. package/build/typescript/MutationObserver.d.ts.map +1 -1
  117. package/build/typescript/NamedNodeMap.d.ts +5 -3
  118. package/build/typescript/NamedNodeMap.d.ts.map +1 -1
  119. package/build/typescript/Node.d.ts +4 -3
  120. package/build/typescript/Node.d.ts.map +1 -1
  121. package/build/typescript/NodeList.d.ts +3 -2
  122. package/build/typescript/NodeList.d.ts.map +1 -1
  123. package/build/typescript/ParentNode.d.ts +29 -10
  124. package/build/typescript/ParentNode.d.ts.map +1 -1
  125. package/build/typescript/PromiseRejectionEvent.d.ts.map +1 -1
  126. package/build/typescript/SVGElement.d.ts +1 -1
  127. package/build/typescript/SVGElement.d.ts.map +1 -1
  128. package/build/typescript/Text.d.ts +1 -1
  129. package/build/typescript/Text.d.ts.map +1 -1
  130. package/build/typescript/ToggleEvent.d.ts.map +1 -1
  131. package/build/typescript/Window.d.ts +5 -1
  132. package/build/typescript/Window.d.ts.map +1 -1
  133. package/build/typescript/attribute-reactions.d.ts +4 -0
  134. package/build/typescript/attribute-reactions.d.ts.map +1 -0
  135. package/build/typescript/constants.d.ts +27 -18
  136. package/build/typescript/constants.d.ts.map +1 -1
  137. package/build/typescript/custom-element-reactions.d.ts +6 -0
  138. package/build/typescript/custom-element-reactions.d.ts.map +1 -0
  139. package/build/typescript/dom-exception.d.ts +2 -0
  140. package/build/typescript/dom-exception.d.ts.map +1 -0
  141. package/build/typescript/extensions.d.ts +4 -0
  142. package/build/typescript/extensions.d.ts.map +1 -0
  143. package/build/typescript/hook-effects.d.ts +6 -0
  144. package/build/typescript/hook-effects.d.ts.map +1 -0
  145. package/build/typescript/hooks.d.ts +3 -3
  146. package/build/typescript/hooks.d.ts.map +1 -1
  147. package/build/typescript/index.d.ts +1 -0
  148. package/build/typescript/index.d.ts.map +1 -1
  149. package/build/typescript/names.d.ts +11 -0
  150. package/build/typescript/names.d.ts.map +1 -0
  151. package/build/typescript/selectors.d.ts +21 -22
  152. package/build/typescript/selectors.d.ts.map +1 -1
  153. package/build/typescript/serialization.d.ts.map +1 -1
  154. package/build/typescript/shared.d.ts +10 -0
  155. package/build/typescript/shared.d.ts.map +1 -1
  156. package/build/typescript/tests/ChildNode.test.d.ts +2 -0
  157. package/build/typescript/tests/ChildNode.test.d.ts.map +1 -0
  158. package/build/typescript/tests/MutationObserver.test.d.ts +2 -0
  159. package/build/typescript/tests/MutationObserver.test.d.ts.map +1 -0
  160. package/build/typescript/tests/adopt-inserted-subtrees.test.d.ts +2 -0
  161. package/build/typescript/tests/adopt-inserted-subtrees.test.d.ts.map +1 -0
  162. package/build/typescript/tests/attr-mutation.test.d.ts +2 -0
  163. package/build/typescript/tests/attr-mutation.test.d.ts.map +1 -0
  164. package/build/typescript/tests/child-node-before-after.test.d.ts +2 -0
  165. package/build/typescript/tests/child-node-before-after.test.d.ts.map +1 -0
  166. package/build/typescript/tests/child-node-replace-with.test.d.ts +2 -0
  167. package/build/typescript/tests/child-node-replace-with.test.d.ts.map +1 -0
  168. package/build/typescript/tests/clone-import-namespaces.test.d.ts +2 -0
  169. package/build/typescript/tests/clone-import-namespaces.test.d.ts.map +1 -0
  170. package/build/typescript/tests/constants.test.d.ts +2 -0
  171. package/build/typescript/tests/constants.test.d.ts.map +1 -0
  172. package/build/typescript/tests/create-element-namespaces.test.d.ts +2 -0
  173. package/build/typescript/tests/create-element-namespaces.test.d.ts.map +1 -0
  174. package/build/typescript/tests/create-text-node.test.d.ts +2 -0
  175. package/build/typescript/tests/create-text-node.test.d.ts.map +1 -0
  176. package/build/typescript/tests/custom-element-reactions.test.d.ts +2 -0
  177. package/build/typescript/tests/custom-element-reactions.test.d.ts.map +1 -0
  178. package/build/typescript/tests/custom-element-registry.test.d.ts +2 -0
  179. package/build/typescript/tests/custom-element-registry.test.d.ts.map +1 -0
  180. package/build/typescript/tests/custom-event.test.d.ts +2 -0
  181. package/build/typescript/tests/custom-event.test.d.ts.map +1 -0
  182. package/build/typescript/tests/document-clone-import-contract.test.d.ts +2 -0
  183. package/build/typescript/tests/document-clone-import-contract.test.d.ts.map +1 -0
  184. package/build/typescript/tests/document.test.d.ts +2 -0
  185. package/build/typescript/tests/document.test.d.ts.map +1 -0
  186. package/build/typescript/tests/dom-mutation-selector-errors.test.d.ts +2 -0
  187. package/build/typescript/tests/dom-mutation-selector-errors.test.d.ts.map +1 -0
  188. package/build/typescript/tests/event-dispatch.test.d.ts +2 -0
  189. package/build/typescript/tests/event-dispatch.test.d.ts.map +1 -0
  190. package/build/typescript/tests/event-target.test.d.ts +2 -0
  191. package/build/typescript/tests/event-target.test.d.ts.map +1 -0
  192. package/build/typescript/tests/event.test.d.ts +2 -0
  193. package/build/typescript/tests/event.test.d.ts.map +1 -0
  194. package/build/typescript/tests/extensions.test.d.ts +2 -0
  195. package/build/typescript/tests/extensions.test.d.ts.map +1 -0
  196. package/build/typescript/tests/get-elements-by-tag-name.test.d.ts +2 -0
  197. package/build/typescript/tests/get-elements-by-tag-name.test.d.ts.map +1 -0
  198. package/build/typescript/tests/getElementsByClassName.test.d.ts +2 -0
  199. package/build/typescript/tests/getElementsByClassName.test.d.ts.map +1 -0
  200. package/build/typescript/tests/hooks.test.d.ts +2 -0
  201. package/build/typescript/tests/hooks.test.d.ts.map +1 -0
  202. package/build/typescript/tests/inner-html-parsing.test.d.ts +2 -0
  203. package/build/typescript/tests/inner-html-parsing.test.d.ts.map +1 -0
  204. package/build/typescript/tests/is-default-namespace.test.d.ts +2 -0
  205. package/build/typescript/tests/is-default-namespace.test.d.ts.map +1 -0
  206. package/build/typescript/tests/name-and-namespace-normalization.test.d.ts +2 -0
  207. package/build/typescript/tests/name-and-namespace-normalization.test.d.ts.map +1 -0
  208. package/build/typescript/tests/named-node-map.test.d.ts +2 -0
  209. package/build/typescript/tests/named-node-map.test.d.ts.map +1 -0
  210. package/build/typescript/tests/namespaced-attribute-reactions.test.d.ts +2 -0
  211. package/build/typescript/tests/namespaced-attribute-reactions.test.d.ts.map +1 -0
  212. package/build/typescript/tests/node.test.d.ts +2 -0
  213. package/build/typescript/tests/node.test.d.ts.map +1 -0
  214. package/build/typescript/tests/parent-node-mutation-return-values.test.d.ts +2 -0
  215. package/build/typescript/tests/parent-node-mutation-return-values.test.d.ts.map +1 -0
  216. package/build/typescript/tests/parent-node-mutation-validation.test.d.ts +2 -0
  217. package/build/typescript/tests/parent-node-mutation-validation.test.d.ts.map +1 -0
  218. package/build/typescript/tests/parent-node.test.d.ts +2 -0
  219. package/build/typescript/tests/parent-node.test.d.ts.map +1 -0
  220. package/build/typescript/tests/serialization-template.test.d.ts +2 -0
  221. package/build/typescript/tests/serialization-template.test.d.ts.map +1 -0
  222. package/build/typescript/tests/slot-attribute.test.d.ts +2 -0
  223. package/build/typescript/tests/slot-attribute.test.d.ts.map +1 -0
  224. package/build/typescript/tests/text-content.test.d.ts +2 -0
  225. package/build/typescript/tests/text-content.test.d.ts.map +1 -0
  226. package/build/typescript/tests/toggle-attribute.test.d.ts +2 -0
  227. package/build/typescript/tests/toggle-attribute.test.d.ts.map +1 -0
  228. package/build/typescript/tests/wide-tree-traversal.test.d.ts +2 -0
  229. package/build/typescript/tests/wide-tree-traversal.test.d.ts.map +1 -0
  230. package/build/typescript/tests/window-set-global.test.d.ts +2 -0
  231. package/build/typescript/tests/window-set-global.test.d.ts.map +1 -0
  232. package/package.json +1 -1
  233. package/source/Attr.ts +60 -8
  234. package/source/CharacterData.ts +13 -0
  235. package/source/ChildNode.ts +107 -14
  236. package/source/Comment.ts +2 -2
  237. package/source/CustomElementRegistry.ts +56 -0
  238. package/source/CustomEvent.ts +2 -2
  239. package/source/Document.ts +104 -38
  240. package/source/DocumentFragment.ts +15 -3
  241. package/source/Element.ts +129 -14
  242. package/source/Event.ts +34 -32
  243. package/source/EventTarget.ts +203 -79
  244. package/source/HTMLTemplateElement.ts +2 -1
  245. package/source/MutationObserver.ts +279 -1
  246. package/source/NamedNodeMap.ts +141 -60
  247. package/source/Node.ts +70 -14
  248. package/source/NodeList.ts +13 -3
  249. package/source/ParentNode.ts +500 -88
  250. package/source/SVGElement.ts +2 -2
  251. package/source/Text.ts +2 -2
  252. package/source/Window.ts +156 -17
  253. package/source/attribute-reactions.ts +32 -0
  254. package/source/constants.ts +40 -17
  255. package/source/custom-element-reactions.ts +64 -0
  256. package/source/dom-exception.ts +14 -0
  257. package/source/extensions.ts +4 -0
  258. package/source/hook-effects.ts +56 -0
  259. package/source/hooks.ts +11 -3
  260. package/source/index.ts +1 -0
  261. package/source/names.ts +94 -0
  262. package/source/selectors.ts +301 -138
  263. package/source/serialization.ts +224 -66
  264. package/source/shared.ts +269 -40
  265. package/source/tests/ChildNode.test.ts +178 -0
  266. package/source/tests/MutationObserver.test.ts +303 -0
  267. package/source/tests/adopt-inserted-subtrees.test.ts +584 -0
  268. package/source/tests/attr-mutation.test.ts +112 -0
  269. package/source/tests/child-node-before-after.test.ts +421 -0
  270. package/source/tests/child-node-replace-with.test.ts +251 -0
  271. package/source/tests/clone-import-namespaces.test.ts +365 -0
  272. package/source/tests/constants.test.ts +46 -0
  273. package/source/tests/create-element-namespaces.test.ts +142 -0
  274. package/source/tests/create-text-node.test.ts +38 -0
  275. package/source/tests/custom-element-reactions.test.ts +600 -0
  276. package/source/tests/custom-element-registry.test.ts +137 -0
  277. package/source/tests/custom-event.test.ts +26 -0
  278. package/source/tests/document-clone-import-contract.test.ts +77 -0
  279. package/source/tests/document.test.ts +122 -0
  280. package/source/tests/dom-mutation-selector-errors.test.ts +484 -0
  281. package/source/tests/event-dispatch.test.ts +270 -0
  282. package/source/tests/event-target.test.ts +208 -0
  283. package/source/tests/event.test.ts +98 -0
  284. package/source/tests/extensions.test.ts +159 -0
  285. package/source/tests/get-elements-by-tag-name.test.ts +79 -0
  286. package/source/tests/getElementsByClassName.test.ts +109 -0
  287. package/source/tests/hooks.test.ts +43 -0
  288. package/source/tests/inner-html-parsing.test.ts +461 -0
  289. package/source/tests/is-default-namespace.test.ts +111 -0
  290. package/source/tests/name-and-namespace-normalization.test.ts +319 -0
  291. package/source/tests/named-node-map.test.ts +122 -0
  292. package/source/tests/namespaced-attribute-reactions.test.ts +141 -0
  293. package/source/tests/node.test.ts +56 -0
  294. package/source/tests/parent-node-mutation-return-values.test.ts +63 -0
  295. package/source/tests/parent-node-mutation-validation.test.ts +362 -0
  296. package/source/tests/parent-node.test.ts +169 -0
  297. package/source/tests/selectors.test.ts +533 -22
  298. package/source/tests/serialization-template.test.ts +232 -0
  299. package/source/tests/slot-attribute.test.ts +133 -0
  300. package/source/tests/text-content.test.ts +440 -0
  301. package/source/tests/toggle-attribute.test.ts +113 -0
  302. package/source/tests/wide-tree-traversal.test.ts +699 -0
  303. package/source/tests/window-set-global.test.ts +321 -0
  304. package/tsconfig.json +1 -1
@@ -1,93 +1,196 @@
1
- import { CHILD, NEXT, NodeType, DATA, NAME, ATTRIBUTES, VALUE } from './constants.mjs';
1
+ import { CHILD, asciiLowercase, NS, SVG_NAMESPACE, HTML_NAMESPACE, CREATE_ELEMENT, NAME, NEXT, NODE_TYPE_COMMENT, DATA, NODE_TYPE_TEXT, NODE_TYPE_ELEMENT, ATTRIBUTES, VALUE, CONTENT } from './constants.mjs';
2
2
 
3
- // const voidElements = {
4
- // img: true,
5
- // image: true,
6
- // };
7
- // const elementTokenizer =
8
- // /(?:<([a-z][a-z0-9-:]*)( [^<>'"\n=\s]+=(['"])[^>'"\n]*\3)*\s*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|([^&<>]+))/gi;
9
- // const attributeTokenizer = / ([^<>'"\n=\s]+)=(['"])([^>'"\n]*)\2/g;
10
-
11
- const elementTokenizer = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^&<>]+))/gi;
12
- const attributeTokenizer = /\s([^<>'"=\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
3
+ const CHARACTER_REFERENCES = {
4
+ amp: '&',
5
+ AMP: '&',
6
+ apos: "'",
7
+ gt: '>',
8
+ GT: '>',
9
+ lt: '<',
10
+ LT: '<',
11
+ quot: '"',
12
+ QUOT: '"'
13
+ };
14
+ const VOID_ELEMENTS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
15
+ const ELEMENT_TOKENIZER = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=/\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^<>]+))/gi;
16
+ const ATTRIBUTE_TOKENIZER = /\s([^<>'"=/\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
17
+ const SVG_HTML_BREAKOUTS = '|b|big|blockquote|body|br|center|code|dd|div|dl|dt|em|embed|h1|h2|h3|h4|h5|h6|head|hr|i|img|li|listing|menu|meta|nobr|ol|p|pre|ruby|s|small|span|strong|strike|sub|sup|table|tt|u|ul|var|';
18
+ const SVG_HTML_FONT_ATTRIBUTE = /^(?:color|face|size)$/i;
19
+ function decodeCharacterReferences(value) {
20
+ return value.replace(/&(?:(amp|AMP|apos|gt|GT|lt|LT|quot|QUOT)|#(\d+)|#[xX]([\da-fA-F]+));/g, (reference, name, decimal, hexadecimal) => {
21
+ if (name) return CHARACTER_REFERENCES[name];
22
+ const codePoint = Number.parseInt(decimal ?? hexadecimal, decimal ? 10 : 16);
23
+ try {
24
+ return String.fromCodePoint(codePoint);
25
+ } catch {
26
+ return reference;
27
+ }
28
+ });
29
+ }
30
+ function isVoidElement(element) {
31
+ return element.namespaceURI === HTML_NAMESPACE && VOID_ELEMENTS.has(element.localName);
32
+ }
33
+ function isHtmlIntegrationPoint(element) {
34
+ const name = element.localName;
35
+ return element[NS] === SVG_NAMESPACE && (name === 'foreignObject' || name === 'desc' || name === 'title');
36
+ }
37
+ function isSvgHtmlBreakout(tag, attributes) {
38
+ if (SVG_HTML_BREAKOUTS.includes(`|${tag}|`)) return true;
39
+ if (tag !== 'font') return false;
40
+ for (const attribute of attributes.matchAll(ATTRIBUTE_TOKENIZER)) {
41
+ if (SVG_HTML_FONT_ATTRIBUTE.test(attribute[1])) return true;
42
+ }
43
+ return false;
44
+ }
13
45
  function parseHtml(html, contextNode) {
14
46
  const document = contextNode.ownerDocument;
15
47
  const root = document.createDocumentFragment();
16
- const stack = [root];
48
+ const stack = [];
17
49
  let parent = root;
18
- let token;
19
- elementTokenizer.lastIndex = 0;
20
- while (token = elementTokenizer.exec(html)) {
50
+ for (const token of html.matchAll(ELEMENT_TOKENIZER)) {
21
51
  const tag = token[1];
22
52
  if (tag) {
23
- const node = document.createElement(tag);
24
53
  const attrs = token[2];
25
- attributeTokenizer.lastIndex = 0;
26
- let t;
27
- while (t = attributeTokenizer.exec(attrs)) {
28
- node.setAttribute(t[1], t[3] || t[4] || '');
54
+ const normalizedTag = asciiLowercase(tag);
55
+ const openElement = stack[stack.length - 1]?.element ?? contextNode;
56
+ let namespace = openElement[NS] === SVG_NAMESPACE ? SVG_NAMESPACE : HTML_NAMESPACE;
57
+ if (normalizedTag === 'svg') {
58
+ namespace = SVG_NAMESPACE;
59
+ } else if (namespace === SVG_NAMESPACE) {
60
+ if (isHtmlIntegrationPoint(openElement)) {
61
+ namespace = HTML_NAMESPACE;
62
+ } else if (isSvgHtmlBreakout(normalizedTag, attrs)) {
63
+ while (stack.length > 0) {
64
+ const frame = stack[stack.length - 1];
65
+ if (frame.element[NS] !== SVG_NAMESPACE || isHtmlIntegrationPoint(frame.element)) {
66
+ break;
67
+ }
68
+ stack.pop();
69
+ parent = frame.target;
70
+ }
71
+ namespace = HTML_NAMESPACE;
72
+ }
73
+ }
74
+ const name = namespace === HTML_NAMESPACE ? normalizedTag : tag;
75
+ const node = document[CREATE_ELEMENT](name, namespace, null, name);
76
+ for (const attribute of attrs.matchAll(ATTRIBUTE_TOKENIZER)) {
77
+ node.setAttribute(attribute[1], decodeCharacterReferences(attribute[3] || attribute[4] || ''));
29
78
  }
30
79
  parent.append(node);
31
- // if (voidElements[tag] === true) continue;
32
- stack.push(parent);
33
- parent = node;
80
+ if (isVoidElement(node) || namespace !== HTML_NAMESPACE && token[4]) {
81
+ continue;
82
+ }
83
+ stack.push({
84
+ element: node,
85
+ target: parent
86
+ });
87
+ parent = namespace === HTML_NAMESPACE && normalizedTag === 'template' ? node.content : node;
34
88
  } else if (token[5]) {
35
- parent = stack.pop() || root;
89
+ const closingTag = asciiLowercase(token[5]);
90
+ for (let index = stack.length - 1; index >= 0; index--) {
91
+ const frame = stack[index];
92
+ const frameName = asciiLowercase(frame.element[NAME]);
93
+ if (frameName === closingTag) {
94
+ parent = frame.target;
95
+ stack.length = index;
96
+ break;
97
+ }
98
+ if (frame.element[NS] === HTML_NAMESPACE && frameName === 'template') {
99
+ break;
100
+ }
101
+ }
36
102
  } else if (token[6]) {
37
103
  parent.append(document.createComment(token[6]));
38
104
  } else {
39
- parent.append(token[7]);
105
+ parent.append(decodeCharacterReferences(token[7]));
40
106
  }
41
107
  }
42
108
  return root;
43
109
  }
44
110
  function serializeChildren(parentNode) {
45
- let out = '';
46
- let child = parentNode[CHILD];
47
- while (child) {
48
- out += serializeNode(child);
49
- child = child[NEXT];
50
- }
51
- return out;
111
+ return serialize([{
112
+ type: 'content',
113
+ child: parentNode[CHILD]
114
+ }]);
52
115
  }
53
116
  function serializeNode(node) {
54
- switch (node.nodeType) {
55
- case NodeType.ELEMENT_NODE:
56
- {
57
- const el = node;
58
- let out = `<${el[NAME]}`;
59
- let attr = el[ATTRIBUTES]?.[CHILD];
60
- while (attr) {
61
- out += ` ${attr[NAME]}`;
62
- let value = attr[VALUE];
63
- if (value !== '') {
64
- value = String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
65
- out += `="${value}"`;
117
+ return serialize([{
118
+ type: 'opening',
119
+ node
120
+ }]);
121
+ }
122
+ function serialize(workItems) {
123
+ const chunks = [];
124
+ let workItem;
125
+ while (workItem = workItems.pop()) {
126
+ switch (workItem.type) {
127
+ case 'opening':
128
+ {
129
+ const node = workItem.node;
130
+ switch (node.nodeType) {
131
+ case NODE_TYPE_ELEMENT:
132
+ {
133
+ const el = node;
134
+ chunks.push(`<${el[NAME]}`);
135
+ let attr = el[ATTRIBUTES]?.[CHILD];
136
+ while (attr) {
137
+ chunks.push(` ${attr[NAME]}`);
138
+ let value = attr[VALUE];
139
+ if (value !== '') {
140
+ value = String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
141
+ chunks.push(`="${value}"`);
142
+ }
143
+ attr = attr[NEXT];
144
+ }
145
+ chunks.push('>');
146
+ if (isVoidElement(el)) break;
147
+ const content = el.namespaceURI === HTML_NAMESPACE && el.localName === 'template' ? el[CONTENT] : el;
148
+ workItems.push({
149
+ type: 'closing',
150
+ name: el[NAME]
151
+ });
152
+ workItems.push({
153
+ type: 'content',
154
+ child: content?.[CHILD] ?? null
155
+ });
156
+ break;
157
+ }
158
+ case NODE_TYPE_TEXT:
159
+ {
160
+ const text = node;
161
+ chunks.push(text[DATA].replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;'));
162
+ break;
163
+ }
164
+ case NODE_TYPE_COMMENT:
165
+ {
166
+ const text = node;
167
+ chunks.push(`<!--${text[DATA]}-->`);
168
+ break;
169
+ }
66
170
  }
67
- attr = attr[NEXT];
171
+ break;
68
172
  }
69
- out += '>';
70
- out += serializeChildren(el);
71
- // let child = el[CHILD];
72
- // while (child) {
73
- // out += serialize(child);
74
- // child = child[NEXT];
75
- // }
76
- out += `</${el[NAME]}>`;
77
- return out;
78
- }
79
- case NodeType.TEXT_NODE:
80
- {
81
- const text = node;
82
- return text[DATA].replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
83
- }
84
- case NodeType.COMMENT_NODE:
85
- {
86
- const text = node;
87
- return `<!--${text[DATA]}-->`;
88
- }
173
+ case 'content':
174
+ {
175
+ const child = workItem.child;
176
+ if (child) {
177
+ workItems.push({
178
+ type: 'content',
179
+ child: child[NEXT]
180
+ });
181
+ workItems.push({
182
+ type: 'opening',
183
+ node: child
184
+ });
185
+ }
186
+ break;
187
+ }
188
+ case 'closing':
189
+ chunks.push(`</${workItem.name}>`);
190
+ break;
191
+ }
89
192
  }
90
- return '';
193
+ return chunks.join('');
91
194
  }
92
195
 
93
196
  export { parseHtml, serializeChildren, serializeNode };
@@ -1,67 +1,210 @@
1
- import { DATA, NodeType, ATTRIBUTES, OWNER_DOCUMENT, CHILD, NEXT } from './constants.mjs';
1
+ import { asciiLowercase, HTML_NAMESPACE, NAME, splitOnASCIIWhitespace, NODE_TYPE_DOCUMENT, CONTENT, ATTRIBUTES, DATA, CHILD, NEXT, NODE_TYPE_TEXT, OWNER_DOCUMENT, NODE_TYPE_ELEMENT, CREATE_ELEMENT, PREFIX, NODE_TYPE_DOCUMENT_FRAGMENT, NODE_TYPE_COMMENT, NODE_TYPE_ATTRIBUTE } from './constants.mjs';
2
+ import { querySelectorAll, querySelector, MATCHER_ID, MATCHER_CLASS } from './selectors.mjs';
3
+ import { createDOMException } from './dom-exception.mjs';
2
4
 
5
+ function isAttributeNode(node) {
6
+ return node.nodeType === NODE_TYPE_ATTRIBUTE;
7
+ }
3
8
  function isCharacterData(node) {
4
9
  return DATA in node;
5
10
  }
6
11
  function isTextNode(node) {
7
- return node.nodeType === NodeType.TEXT_NODE;
12
+ return node.nodeType === NODE_TYPE_TEXT;
8
13
  }
9
14
  function isCommentNode(node) {
10
- return node.nodeType === NodeType.COMMENT_NODE;
15
+ return node.nodeType === NODE_TYPE_COMMENT;
11
16
  }
12
17
  function isElementNode(node) {
13
- return node.nodeType === NodeType.ELEMENT_NODE;
18
+ return node.nodeType === NODE_TYPE_ELEMENT;
14
19
  }
15
20
  function isDocumentFragmentNode(node) {
16
- return node.nodeType === NodeType.DOCUMENT_FRAGMENT_NODE;
21
+ return node.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT;
17
22
  }
18
23
  function isParentNode(node) {
19
24
  return 'appendChild' in node;
20
25
  }
21
- function cloneNode(node, deep, document = node.ownerDocument) {
26
+ function collectAdoptionSnapshot(root) {
27
+ const nodes = [];
28
+ const pendingRoots = [root];
29
+ const pending = new Set(pendingRoots);
30
+ const visited = new Set();
31
+ let treeNodes;
32
+ while (pendingRoots.length > 0) {
33
+ const currentRoot = pendingRoots.pop();
34
+ pending.delete(currentRoot);
35
+ if (visited.has(currentRoot)) continue;
36
+ const currentTreeNodes = [];
37
+ for (const node of selfAndDescendants(currentRoot)) {
38
+ if (visited.has(node)) continue;
39
+ visited.add(node);
40
+ nodes.push(node);
41
+ currentTreeNodes.push(node);
42
+ if (!isElementNode(node)) continue;
43
+ const attributes = node[ATTRIBUTES];
44
+ if (attributes) {
45
+ for (const attribute of attributes) {
46
+ if (visited.has(attribute)) continue;
47
+ visited.add(attribute);
48
+ nodes.push(attribute);
49
+ }
50
+ }
51
+ const content = node[CONTENT];
52
+ if (content && !visited.has(content) && !pending.has(content)) {
53
+ pending.add(content);
54
+ pendingRoots.push(content);
55
+ }
56
+ }
57
+ treeNodes ??= currentTreeNodes;
58
+ }
59
+ return {
60
+ nodes,
61
+ treeNodes: treeNodes
62
+ };
63
+ }
64
+ function adoptNodes(nodes, document) {
65
+ for (const node of nodes) node[OWNER_DOCUMENT] = document;
66
+ }
67
+ function cloneAttribute(attribute, document) {
68
+ const Attribute = attribute.constructor;
69
+ const cloned = new Attribute(attribute.name, attribute.value, attribute.namespaceURI);
70
+ cloned[OWNER_DOCUMENT] = document;
71
+ return cloned;
72
+ }
73
+ function cloneNodeShallow(node, document) {
22
74
  if (isTextNode(node)) {
23
75
  return document.createTextNode(node.data);
24
76
  } else if (isCommentNode(node)) {
25
77
  return document.createComment(node.data);
78
+ } else if (isAttributeNode(node)) {
79
+ return cloneAttribute(node, document);
26
80
  } else if (isElementNode(node)) {
27
- const cloned = document.createElement(node.localName);
81
+ const cloned = document[CREATE_ELEMENT](node[NAME], node.namespaceURI, node[PREFIX], node.localName);
28
82
  if (node[ATTRIBUTES]) {
29
83
  for (let i = 0; i < node[ATTRIBUTES].length; i++) {
30
84
  const attribute = node[ATTRIBUTES].item(i);
31
- cloned.setAttributeNS(attribute.namespaceURI, attribute.name, attribute.value);
32
- }
33
- }
34
- if (deep) {
35
- for (const child of node.childNodes) {
36
- cloned.appendChild(cloneNode(child, true, document));
85
+ cloned.attributes.setNamedItem(cloneAttribute(attribute, document));
37
86
  }
38
87
  }
39
88
  return cloned;
40
89
  } else if (isDocumentFragmentNode(node)) {
41
- const fragment = document.createDocumentFragment();
42
- if (deep) {
43
- for (const child of node.childNodes) {
44
- fragment.appendChild(cloneNode(child, true, document));
45
- }
46
- }
47
- return fragment;
90
+ return document.createDocumentFragment();
48
91
  } else {
49
92
  const cloned = new node.constructor();
50
93
  cloned[OWNER_DOCUMENT] = document;
51
94
  return cloned;
52
95
  }
53
96
  }
97
+ function cloneNode(node, deep, document = node.ownerDocument) {
98
+ if (node.nodeType === NODE_TYPE_DOCUMENT) {
99
+ throw createDOMException('Cannot clone a document node', 'NotSupportedError');
100
+ }
101
+ const cloned = cloneNodeShallow(node, document);
102
+ if (!deep || !isElementNode(node) && !isDocumentFragmentNode(node)) {
103
+ return cloned;
104
+ }
105
+ const visited = new Set([node]);
106
+ const frames = [{
107
+ source: node,
108
+ destination: cloned,
109
+ childIndex: 0,
110
+ cloningContent: false
111
+ }];
112
+ while (frames.length > 0) {
113
+ const frame = frames[frames.length - 1];
114
+ let sourceChild;
115
+ let destinationParent;
116
+ if (!frame.cloningContent) {
117
+ sourceChild = frame.source.childNodes[frame.childIndex++];
118
+ destinationParent = frame.destination;
119
+ if (!sourceChild) {
120
+ frame.cloningContent = true;
121
+ frame.childIndex = 0;
122
+ if (isElementNode(frame.source) && frame.source.namespaceURI === HTML_NAMESPACE && frame.source.localName === 'template') {
123
+ const content = frame.source[CONTENT];
124
+ if (content) {
125
+ if (visited.has(content)) throwCloneGraphError();
126
+ visited.add(content);
127
+ frame.contentSource = content;
128
+ frame.contentDestination = frame.destination.content;
129
+ }
130
+ }
131
+ continue;
132
+ }
133
+ } else if (frame.contentSource && frame.contentDestination) {
134
+ sourceChild = frame.contentSource.childNodes[frame.childIndex++];
135
+ destinationParent = frame.contentDestination;
136
+ } else {
137
+ frames.pop();
138
+ if (frame.appendTo) frame.appendTo.appendChild(frame.destination);
139
+ continue;
140
+ }
141
+ if (!sourceChild) {
142
+ frames.pop();
143
+ if (frame.appendTo) frame.appendTo.appendChild(frame.destination);
144
+ continue;
145
+ }
146
+ if (visited.has(sourceChild)) throwCloneGraphError();
147
+ visited.add(sourceChild);
148
+ const clonedChild = cloneNodeShallow(sourceChild, document);
149
+ if (isElementNode(sourceChild) || isDocumentFragmentNode(sourceChild)) {
150
+ frames.push({
151
+ source: sourceChild,
152
+ destination: clonedChild,
153
+ appendTo: destinationParent,
154
+ childIndex: 0,
155
+ cloningContent: false
156
+ });
157
+ } else {
158
+ destinationParent.appendChild(clonedChild);
159
+ }
160
+ }
161
+ return cloned;
162
+ }
163
+ function throwCloneGraphError() {
164
+ throw new Error('Cannot clone a cyclic or repeated node graph');
165
+ }
166
+ function getElementById(within, elementId) {
167
+ const id = String(elementId);
168
+ if (id === '') return null;
169
+ return querySelector(within, [{
170
+ type: MATCHER_ID,
171
+ name: id
172
+ }]);
173
+ }
174
+ function getElementsByClassName(within, classNames) {
175
+ const names = [...new Set(splitOnASCIIWhitespace(String(classNames)))];
176
+ return querySelectorAll(within, names.map(name => ({
177
+ type: MATCHER_CLASS,
178
+ name
179
+ })));
180
+ }
181
+ function getElementsByTagName(within, qualifiedName) {
182
+ const name = String(qualifiedName);
183
+ const normalizedHtmlName = asciiLowercase(name);
184
+ const elements = [];
185
+ for (const node of descendants(within)) {
186
+ if (!isElementNode(node)) continue;
187
+ if (name === '*' || (node.namespaceURI === HTML_NAMESPACE ? node[NAME] === normalizedHtmlName : node[NAME] === name)) {
188
+ elements.push(node);
189
+ }
190
+ }
191
+ return elements;
192
+ }
54
193
  function descendants(node) {
55
194
  const nodes = [];
56
- const walk = node => {
57
- nodes.push(node);
58
- const child = node[CHILD];
59
- if (child) walk(child);
60
- const sibling = node[NEXT];
61
- if (sibling) walk(sibling);
62
- };
63
- const child = node[CHILD];
64
- if (child) walk(child);
195
+ const pendingSiblings = [];
196
+ let current = node[CHILD];
197
+ while (current) {
198
+ nodes.push(current);
199
+ const child = current[CHILD];
200
+ const sibling = current[NEXT];
201
+ if (child) {
202
+ if (sibling) pendingSiblings.push(sibling);
203
+ current = child;
204
+ } else {
205
+ current = sibling ?? pendingSiblings.pop() ?? null;
206
+ }
207
+ }
65
208
  return nodes;
66
209
  }
67
210
  function selfAndDescendants(node) {
@@ -70,4 +213,4 @@ function selfAndDescendants(node) {
70
213
  return nodes;
71
214
  }
72
215
 
73
- export { cloneNode, descendants, isCharacterData, isCommentNode, isDocumentFragmentNode, isElementNode, isParentNode, isTextNode, selfAndDescendants };
216
+ export { adoptNodes, cloneNode, collectAdoptionSnapshot, descendants, getElementById, getElementsByClassName, getElementsByTagName, isAttributeNode, isCharacterData, isCommentNode, isDocumentFragmentNode, isElementNode, isParentNode, isTextNode, selfAndDescendants };
@@ -1,8 +1,11 @@
1
- import { NodeType, NS, NEXT, VALUE, OWNER_ELEMENT, NAME, HOOKS } from './constants.esnext';
1
+ import { NODE_TYPE_ATTRIBUTE, NS, NEXT, VALUE, OWNER_ELEMENT, NAME, HOOKS } from './constants.esnext';
2
2
  import { Node } from './Node.esnext';
3
+ import { attributeObserversActive, queueMutationRecord } from './MutationObserver.esnext';
4
+ import { enqueueAttributeReaction } from './attribute-reactions.esnext';
5
+ import { performWithCustomElementReactions } from './custom-element-reactions.esnext';
3
6
 
4
7
  class Attr extends Node {
5
- nodeType = NodeType.ATTRIBUTE_NODE;
8
+ nodeType = NODE_TYPE_ATTRIBUTE;
6
9
  [NS] = null;
7
10
  [NEXT] = null;
8
11
  [VALUE];
@@ -23,15 +26,52 @@ class Attr extends Node {
23
26
  }
24
27
  set name(_readonly) {
25
28
  }
29
+ get localName() {
30
+ if (this[NS] == null) return this[NAME];
31
+ const separator = this[NAME].indexOf(":");
32
+ return separator < 0 ? this[NAME] : this[NAME].slice(separator + 1);
33
+ }
34
+ get prefix() {
35
+ if (this[NS] == null) return null;
36
+ const separator = this[NAME].indexOf(":");
37
+ return separator < 0 ? null : this[NAME].slice(0, separator);
38
+ }
26
39
  get value() {
27
40
  return this[VALUE];
28
41
  }
29
42
  set value(value) {
30
43
  const str = String(value);
31
- this[VALUE] = str;
32
44
  const ownerElement = this[OWNER_ELEMENT];
33
- if (!ownerElement) return;
34
- this[HOOKS].setAttribute?.(ownerElement, this[NAME], str, this[NS]);
45
+ if (!ownerElement) {
46
+ this[VALUE] = str;
47
+ return;
48
+ }
49
+ performWithCustomElementReactions(() => {
50
+ const oldValue = this[VALUE];
51
+ this[VALUE] = str;
52
+ if (attributeObserversActive && oldValue !== str) {
53
+ queueMutationRecord({
54
+ type: "attributes",
55
+ target: ownerElement,
56
+ attributeName: this[NAME],
57
+ attributeNamespace: this[NS],
58
+ oldValue
59
+ });
60
+ }
61
+ this[HOOKS].setAttribute?.(
62
+ ownerElement,
63
+ this[NAME],
64
+ str,
65
+ this[NS]
66
+ );
67
+ enqueueAttributeReaction(
68
+ ownerElement,
69
+ this.localName,
70
+ oldValue,
71
+ str,
72
+ this[NS]
73
+ );
74
+ });
35
75
  }
36
76
  get nodeValue() {
37
77
  return this.value;
@@ -1,5 +1,6 @@
1
1
  import { DATA, HOOKS } from './constants.esnext';
2
2
  import { ChildNode } from './ChildNode.esnext';
3
+ import { queueMutationRecord, characterDataObserversActive } from './MutationObserver.esnext';
3
4
 
4
5
  class CharacterData extends ChildNode {
5
6
  [DATA] = "";
@@ -8,11 +9,20 @@ class CharacterData extends ChildNode {
8
9
  this[DATA] = data == null ? "" : String(data);
9
10
  }
10
11
  setData(data) {
12
+ const shouldQueueMutation = characterDataObserversActive;
13
+ const oldValue = shouldQueueMutation ? this[DATA] : null;
11
14
  let str = "";
12
15
  if (data != null) {
13
16
  str = typeof data === "string" ? data : String(data);
14
17
  }
15
18
  this[DATA] = str;
19
+ if (shouldQueueMutation && oldValue !== str) {
20
+ queueMutationRecord({
21
+ type: "characterData",
22
+ target: this,
23
+ oldValue
24
+ });
25
+ }
16
26
  this[HOOKS].setText?.(this, str);
17
27
  }
18
28
  get data() {