@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
@@ -4,94 +4,197 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const constants = require('./constants.cjs');
6
6
 
7
- // const voidElements = {
8
- // img: true,
9
- // image: true,
10
- // };
11
- // const elementTokenizer =
12
- // /(?:<([a-z][a-z0-9-:]*)( [^<>'"\n=\s]+=(['"])[^>'"\n]*\3)*\s*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|([^&<>]+))/gi;
13
- // const attributeTokenizer = / ([^<>'"\n=\s]+)=(['"])([^>'"\n]*)\2/g;
14
-
15
- const elementTokenizer = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^&<>]+))/gi;
16
- const attributeTokenizer = /\s([^<>'"=\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
7
+ const CHARACTER_REFERENCES = {
8
+ amp: '&',
9
+ AMP: '&',
10
+ apos: "'",
11
+ gt: '>',
12
+ GT: '>',
13
+ lt: '<',
14
+ LT: '<',
15
+ quot: '"',
16
+ QUOT: '"'
17
+ };
18
+ const VOID_ELEMENTS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
19
+ const ELEMENT_TOKENIZER = /(?:<([a-z][a-z0-9-:]*)((?:[\s]+[^<>'"=/\s]+(?:=(['"])[^]*?\3|=[^>'"\s]*|))*)[\s]*(\/?)\s*>|<\/([a-z][a-z0-9-:]*)>|<!--(.*?)-->|([^<>]+))/gi;
20
+ const ATTRIBUTE_TOKENIZER = /\s([^<>'"=/\n\s]+)(?:=(["'])([\s\S]*?)\2|=([^>'"\n\s]*)|)/g;
21
+ 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|';
22
+ const SVG_HTML_FONT_ATTRIBUTE = /^(?:color|face|size)$/i;
23
+ function decodeCharacterReferences(value) {
24
+ return value.replace(/&(?:(amp|AMP|apos|gt|GT|lt|LT|quot|QUOT)|#(\d+)|#[xX]([\da-fA-F]+));/g, (reference, name, decimal, hexadecimal) => {
25
+ if (name) return CHARACTER_REFERENCES[name];
26
+ const codePoint = Number.parseInt(decimal ?? hexadecimal, decimal ? 10 : 16);
27
+ try {
28
+ return String.fromCodePoint(codePoint);
29
+ } catch {
30
+ return reference;
31
+ }
32
+ });
33
+ }
34
+ function isVoidElement(element) {
35
+ return element.namespaceURI === constants.HTML_NAMESPACE && VOID_ELEMENTS.has(element.localName);
36
+ }
37
+ function isHtmlIntegrationPoint(element) {
38
+ const name = element.localName;
39
+ return element[constants.NS] === constants.SVG_NAMESPACE && (name === 'foreignObject' || name === 'desc' || name === 'title');
40
+ }
41
+ function isSvgHtmlBreakout(tag, attributes) {
42
+ if (SVG_HTML_BREAKOUTS.includes(`|${tag}|`)) return true;
43
+ if (tag !== 'font') return false;
44
+ for (const attribute of attributes.matchAll(ATTRIBUTE_TOKENIZER)) {
45
+ if (SVG_HTML_FONT_ATTRIBUTE.test(attribute[1])) return true;
46
+ }
47
+ return false;
48
+ }
17
49
  function parseHtml(html, contextNode) {
18
50
  const document = contextNode.ownerDocument;
19
51
  const root = document.createDocumentFragment();
20
- const stack = [root];
52
+ const stack = [];
21
53
  let parent = root;
22
- let token;
23
- elementTokenizer.lastIndex = 0;
24
- while (token = elementTokenizer.exec(html)) {
54
+ for (const token of html.matchAll(ELEMENT_TOKENIZER)) {
25
55
  const tag = token[1];
26
56
  if (tag) {
27
- const node = document.createElement(tag);
28
57
  const attrs = token[2];
29
- attributeTokenizer.lastIndex = 0;
30
- let t;
31
- while (t = attributeTokenizer.exec(attrs)) {
32
- node.setAttribute(t[1], t[3] || t[4] || '');
58
+ const normalizedTag = constants.asciiLowercase(tag);
59
+ const openElement = stack[stack.length - 1]?.element ?? contextNode;
60
+ let namespace = openElement[constants.NS] === constants.SVG_NAMESPACE ? constants.SVG_NAMESPACE : constants.HTML_NAMESPACE;
61
+ if (normalizedTag === 'svg') {
62
+ namespace = constants.SVG_NAMESPACE;
63
+ } else if (namespace === constants.SVG_NAMESPACE) {
64
+ if (isHtmlIntegrationPoint(openElement)) {
65
+ namespace = constants.HTML_NAMESPACE;
66
+ } else if (isSvgHtmlBreakout(normalizedTag, attrs)) {
67
+ while (stack.length > 0) {
68
+ const frame = stack[stack.length - 1];
69
+ if (frame.element[constants.NS] !== constants.SVG_NAMESPACE || isHtmlIntegrationPoint(frame.element)) {
70
+ break;
71
+ }
72
+ stack.pop();
73
+ parent = frame.target;
74
+ }
75
+ namespace = constants.HTML_NAMESPACE;
76
+ }
77
+ }
78
+ const name = namespace === constants.HTML_NAMESPACE ? normalizedTag : tag;
79
+ const node = document[constants.CREATE_ELEMENT](name, namespace, null, name);
80
+ for (const attribute of attrs.matchAll(ATTRIBUTE_TOKENIZER)) {
81
+ node.setAttribute(attribute[1], decodeCharacterReferences(attribute[3] || attribute[4] || ''));
33
82
  }
34
83
  parent.append(node);
35
- // if (voidElements[tag] === true) continue;
36
- stack.push(parent);
37
- parent = node;
84
+ if (isVoidElement(node) || namespace !== constants.HTML_NAMESPACE && token[4]) {
85
+ continue;
86
+ }
87
+ stack.push({
88
+ element: node,
89
+ target: parent
90
+ });
91
+ parent = namespace === constants.HTML_NAMESPACE && normalizedTag === 'template' ? node.content : node;
38
92
  } else if (token[5]) {
39
- parent = stack.pop() || root;
93
+ const closingTag = constants.asciiLowercase(token[5]);
94
+ for (let index = stack.length - 1; index >= 0; index--) {
95
+ const frame = stack[index];
96
+ const frameName = constants.asciiLowercase(frame.element[constants.NAME]);
97
+ if (frameName === closingTag) {
98
+ parent = frame.target;
99
+ stack.length = index;
100
+ break;
101
+ }
102
+ if (frame.element[constants.NS] === constants.HTML_NAMESPACE && frameName === 'template') {
103
+ break;
104
+ }
105
+ }
40
106
  } else if (token[6]) {
41
107
  parent.append(document.createComment(token[6]));
42
108
  } else {
43
- parent.append(token[7]);
109
+ parent.append(decodeCharacterReferences(token[7]));
44
110
  }
45
111
  }
46
112
  return root;
47
113
  }
48
114
  function serializeChildren(parentNode) {
49
- let out = '';
50
- let child = parentNode[constants.CHILD];
51
- while (child) {
52
- out += serializeNode(child);
53
- child = child[constants.NEXT];
54
- }
55
- return out;
115
+ return serialize([{
116
+ type: 'content',
117
+ child: parentNode[constants.CHILD]
118
+ }]);
56
119
  }
57
120
  function serializeNode(node) {
58
- switch (node.nodeType) {
59
- case constants.NodeType.ELEMENT_NODE:
60
- {
61
- const el = node;
62
- let out = `<${el[constants.NAME]}`;
63
- let attr = el[constants.ATTRIBUTES]?.[constants.CHILD];
64
- while (attr) {
65
- out += ` ${attr[constants.NAME]}`;
66
- let value = attr[constants.VALUE];
67
- if (value !== '') {
68
- value = String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
69
- out += `="${value}"`;
121
+ return serialize([{
122
+ type: 'opening',
123
+ node
124
+ }]);
125
+ }
126
+ function serialize(workItems) {
127
+ const chunks = [];
128
+ let workItem;
129
+ while (workItem = workItems.pop()) {
130
+ switch (workItem.type) {
131
+ case 'opening':
132
+ {
133
+ const node = workItem.node;
134
+ switch (node.nodeType) {
135
+ case constants.NODE_TYPE_ELEMENT:
136
+ {
137
+ const el = node;
138
+ chunks.push(`<${el[constants.NAME]}`);
139
+ let attr = el[constants.ATTRIBUTES]?.[constants.CHILD];
140
+ while (attr) {
141
+ chunks.push(` ${attr[constants.NAME]}`);
142
+ let value = attr[constants.VALUE];
143
+ if (value !== '') {
144
+ value = String(value).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
145
+ chunks.push(`="${value}"`);
146
+ }
147
+ attr = attr[constants.NEXT];
148
+ }
149
+ chunks.push('>');
150
+ if (isVoidElement(el)) break;
151
+ const content = el.namespaceURI === constants.HTML_NAMESPACE && el.localName === 'template' ? el[constants.CONTENT] : el;
152
+ workItems.push({
153
+ type: 'closing',
154
+ name: el[constants.NAME]
155
+ });
156
+ workItems.push({
157
+ type: 'content',
158
+ child: content?.[constants.CHILD] ?? null
159
+ });
160
+ break;
161
+ }
162
+ case constants.NODE_TYPE_TEXT:
163
+ {
164
+ const text = node;
165
+ chunks.push(text[constants.DATA].replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;'));
166
+ break;
167
+ }
168
+ case constants.NODE_TYPE_COMMENT:
169
+ {
170
+ const text = node;
171
+ chunks.push(`<!--${text[constants.DATA]}-->`);
172
+ break;
173
+ }
70
174
  }
71
- attr = attr[constants.NEXT];
175
+ break;
72
176
  }
73
- out += '>';
74
- out += serializeChildren(el);
75
- // let child = el[CHILD];
76
- // while (child) {
77
- // out += serialize(child);
78
- // child = child[NEXT];
79
- // }
80
- out += `</${el[constants.NAME]}>`;
81
- return out;
82
- }
83
- case constants.NodeType.TEXT_NODE:
84
- {
85
- const text = node;
86
- return text[constants.DATA].replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
87
- }
88
- case constants.NodeType.COMMENT_NODE:
89
- {
90
- const text = node;
91
- return `<!--${text[constants.DATA]}-->`;
92
- }
177
+ case 'content':
178
+ {
179
+ const child = workItem.child;
180
+ if (child) {
181
+ workItems.push({
182
+ type: 'content',
183
+ child: child[constants.NEXT]
184
+ });
185
+ workItems.push({
186
+ type: 'opening',
187
+ node: child
188
+ });
189
+ }
190
+ break;
191
+ }
192
+ case 'closing':
193
+ chunks.push(`</${workItem.name}>`);
194
+ break;
195
+ }
93
196
  }
94
- return '';
197
+ return chunks.join('');
95
198
  }
96
199
 
97
200
  exports.parseHtml = parseHtml;
@@ -3,69 +3,212 @@
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const constants = require('./constants.cjs');
6
+ const selectors = require('./selectors.cjs');
7
+ const domException = require('./dom-exception.cjs');
6
8
 
9
+ function isAttributeNode(node) {
10
+ return node.nodeType === constants.NODE_TYPE_ATTRIBUTE;
11
+ }
7
12
  function isCharacterData(node) {
8
13
  return constants.DATA in node;
9
14
  }
10
15
  function isTextNode(node) {
11
- return node.nodeType === constants.NodeType.TEXT_NODE;
16
+ return node.nodeType === constants.NODE_TYPE_TEXT;
12
17
  }
13
18
  function isCommentNode(node) {
14
- return node.nodeType === constants.NodeType.COMMENT_NODE;
19
+ return node.nodeType === constants.NODE_TYPE_COMMENT;
15
20
  }
16
21
  function isElementNode(node) {
17
- return node.nodeType === constants.NodeType.ELEMENT_NODE;
22
+ return node.nodeType === constants.NODE_TYPE_ELEMENT;
18
23
  }
19
24
  function isDocumentFragmentNode(node) {
20
- return node.nodeType === constants.NodeType.DOCUMENT_FRAGMENT_NODE;
25
+ return node.nodeType === constants.NODE_TYPE_DOCUMENT_FRAGMENT;
21
26
  }
22
27
  function isParentNode(node) {
23
28
  return 'appendChild' in node;
24
29
  }
25
- function cloneNode(node, deep, document = node.ownerDocument) {
30
+ function collectAdoptionSnapshot(root) {
31
+ const nodes = [];
32
+ const pendingRoots = [root];
33
+ const pending = new Set(pendingRoots);
34
+ const visited = new Set();
35
+ let treeNodes;
36
+ while (pendingRoots.length > 0) {
37
+ const currentRoot = pendingRoots.pop();
38
+ pending.delete(currentRoot);
39
+ if (visited.has(currentRoot)) continue;
40
+ const currentTreeNodes = [];
41
+ for (const node of selfAndDescendants(currentRoot)) {
42
+ if (visited.has(node)) continue;
43
+ visited.add(node);
44
+ nodes.push(node);
45
+ currentTreeNodes.push(node);
46
+ if (!isElementNode(node)) continue;
47
+ const attributes = node[constants.ATTRIBUTES];
48
+ if (attributes) {
49
+ for (const attribute of attributes) {
50
+ if (visited.has(attribute)) continue;
51
+ visited.add(attribute);
52
+ nodes.push(attribute);
53
+ }
54
+ }
55
+ const content = node[constants.CONTENT];
56
+ if (content && !visited.has(content) && !pending.has(content)) {
57
+ pending.add(content);
58
+ pendingRoots.push(content);
59
+ }
60
+ }
61
+ treeNodes ??= currentTreeNodes;
62
+ }
63
+ return {
64
+ nodes,
65
+ treeNodes: treeNodes
66
+ };
67
+ }
68
+ function adoptNodes(nodes, document) {
69
+ for (const node of nodes) node[constants.OWNER_DOCUMENT] = document;
70
+ }
71
+ function cloneAttribute(attribute, document) {
72
+ const Attribute = attribute.constructor;
73
+ const cloned = new Attribute(attribute.name, attribute.value, attribute.namespaceURI);
74
+ cloned[constants.OWNER_DOCUMENT] = document;
75
+ return cloned;
76
+ }
77
+ function cloneNodeShallow(node, document) {
26
78
  if (isTextNode(node)) {
27
79
  return document.createTextNode(node.data);
28
80
  } else if (isCommentNode(node)) {
29
81
  return document.createComment(node.data);
82
+ } else if (isAttributeNode(node)) {
83
+ return cloneAttribute(node, document);
30
84
  } else if (isElementNode(node)) {
31
- const cloned = document.createElement(node.localName);
85
+ const cloned = document[constants.CREATE_ELEMENT](node[constants.NAME], node.namespaceURI, node[constants.PREFIX], node.localName);
32
86
  if (node[constants.ATTRIBUTES]) {
33
87
  for (let i = 0; i < node[constants.ATTRIBUTES].length; i++) {
34
88
  const attribute = node[constants.ATTRIBUTES].item(i);
35
- cloned.setAttributeNS(attribute.namespaceURI, attribute.name, attribute.value);
36
- }
37
- }
38
- if (deep) {
39
- for (const child of node.childNodes) {
40
- cloned.appendChild(cloneNode(child, true, document));
89
+ cloned.attributes.setNamedItem(cloneAttribute(attribute, document));
41
90
  }
42
91
  }
43
92
  return cloned;
44
93
  } else if (isDocumentFragmentNode(node)) {
45
- const fragment = document.createDocumentFragment();
46
- if (deep) {
47
- for (const child of node.childNodes) {
48
- fragment.appendChild(cloneNode(child, true, document));
49
- }
50
- }
51
- return fragment;
94
+ return document.createDocumentFragment();
52
95
  } else {
53
96
  const cloned = new node.constructor();
54
97
  cloned[constants.OWNER_DOCUMENT] = document;
55
98
  return cloned;
56
99
  }
57
100
  }
101
+ function cloneNode(node, deep, document = node.ownerDocument) {
102
+ if (node.nodeType === constants.NODE_TYPE_DOCUMENT) {
103
+ throw domException.createDOMException('Cannot clone a document node', 'NotSupportedError');
104
+ }
105
+ const cloned = cloneNodeShallow(node, document);
106
+ if (!deep || !isElementNode(node) && !isDocumentFragmentNode(node)) {
107
+ return cloned;
108
+ }
109
+ const visited = new Set([node]);
110
+ const frames = [{
111
+ source: node,
112
+ destination: cloned,
113
+ childIndex: 0,
114
+ cloningContent: false
115
+ }];
116
+ while (frames.length > 0) {
117
+ const frame = frames[frames.length - 1];
118
+ let sourceChild;
119
+ let destinationParent;
120
+ if (!frame.cloningContent) {
121
+ sourceChild = frame.source.childNodes[frame.childIndex++];
122
+ destinationParent = frame.destination;
123
+ if (!sourceChild) {
124
+ frame.cloningContent = true;
125
+ frame.childIndex = 0;
126
+ if (isElementNode(frame.source) && frame.source.namespaceURI === constants.HTML_NAMESPACE && frame.source.localName === 'template') {
127
+ const content = frame.source[constants.CONTENT];
128
+ if (content) {
129
+ if (visited.has(content)) throwCloneGraphError();
130
+ visited.add(content);
131
+ frame.contentSource = content;
132
+ frame.contentDestination = frame.destination.content;
133
+ }
134
+ }
135
+ continue;
136
+ }
137
+ } else if (frame.contentSource && frame.contentDestination) {
138
+ sourceChild = frame.contentSource.childNodes[frame.childIndex++];
139
+ destinationParent = frame.contentDestination;
140
+ } else {
141
+ frames.pop();
142
+ if (frame.appendTo) frame.appendTo.appendChild(frame.destination);
143
+ continue;
144
+ }
145
+ if (!sourceChild) {
146
+ frames.pop();
147
+ if (frame.appendTo) frame.appendTo.appendChild(frame.destination);
148
+ continue;
149
+ }
150
+ if (visited.has(sourceChild)) throwCloneGraphError();
151
+ visited.add(sourceChild);
152
+ const clonedChild = cloneNodeShallow(sourceChild, document);
153
+ if (isElementNode(sourceChild) || isDocumentFragmentNode(sourceChild)) {
154
+ frames.push({
155
+ source: sourceChild,
156
+ destination: clonedChild,
157
+ appendTo: destinationParent,
158
+ childIndex: 0,
159
+ cloningContent: false
160
+ });
161
+ } else {
162
+ destinationParent.appendChild(clonedChild);
163
+ }
164
+ }
165
+ return cloned;
166
+ }
167
+ function throwCloneGraphError() {
168
+ throw new Error('Cannot clone a cyclic or repeated node graph');
169
+ }
170
+ function getElementById(within, elementId) {
171
+ const id = String(elementId);
172
+ if (id === '') return null;
173
+ return selectors.querySelector(within, [{
174
+ type: selectors.MATCHER_ID,
175
+ name: id
176
+ }]);
177
+ }
178
+ function getElementsByClassName(within, classNames) {
179
+ const names = [...new Set(constants.splitOnASCIIWhitespace(String(classNames)))];
180
+ return selectors.querySelectorAll(within, names.map(name => ({
181
+ type: selectors.MATCHER_CLASS,
182
+ name
183
+ })));
184
+ }
185
+ function getElementsByTagName(within, qualifiedName) {
186
+ const name = String(qualifiedName);
187
+ const normalizedHtmlName = constants.asciiLowercase(name);
188
+ const elements = [];
189
+ for (const node of descendants(within)) {
190
+ if (!isElementNode(node)) continue;
191
+ if (name === '*' || (node.namespaceURI === constants.HTML_NAMESPACE ? node[constants.NAME] === normalizedHtmlName : node[constants.NAME] === name)) {
192
+ elements.push(node);
193
+ }
194
+ }
195
+ return elements;
196
+ }
58
197
  function descendants(node) {
59
198
  const nodes = [];
60
- const walk = node => {
61
- nodes.push(node);
62
- const child = node[constants.CHILD];
63
- if (child) walk(child);
64
- const sibling = node[constants.NEXT];
65
- if (sibling) walk(sibling);
66
- };
67
- const child = node[constants.CHILD];
68
- if (child) walk(child);
199
+ const pendingSiblings = [];
200
+ let current = node[constants.CHILD];
201
+ while (current) {
202
+ nodes.push(current);
203
+ const child = current[constants.CHILD];
204
+ const sibling = current[constants.NEXT];
205
+ if (child) {
206
+ if (sibling) pendingSiblings.push(sibling);
207
+ current = child;
208
+ } else {
209
+ current = sibling ?? pendingSiblings.pop() ?? null;
210
+ }
211
+ }
69
212
  return nodes;
70
213
  }
71
214
  function selfAndDescendants(node) {
@@ -74,8 +217,14 @@ function selfAndDescendants(node) {
74
217
  return nodes;
75
218
  }
76
219
 
220
+ exports.adoptNodes = adoptNodes;
77
221
  exports.cloneNode = cloneNode;
222
+ exports.collectAdoptionSnapshot = collectAdoptionSnapshot;
78
223
  exports.descendants = descendants;
224
+ exports.getElementById = getElementById;
225
+ exports.getElementsByClassName = getElementsByClassName;
226
+ exports.getElementsByTagName = getElementsByTagName;
227
+ exports.isAttributeNode = isAttributeNode;
79
228
  exports.isCharacterData = isCharacterData;
80
229
  exports.isCommentNode = isCommentNode;
81
230
  exports.isDocumentFragmentNode = isDocumentFragmentNode;
@@ -1,8 +1,11 @@
1
- import { NodeType, NS, NEXT, OWNER_ELEMENT, NAME, VALUE, HOOKS } from './constants.mjs';
1
+ import { NODE_TYPE_ATTRIBUTE, NS, NEXT, OWNER_ELEMENT, NAME, VALUE, HOOKS } from './constants.mjs';
2
2
  import { Node } from './Node.mjs';
3
+ import { attributeObserversActive, queueMutationRecord } from './MutationObserver.mjs';
4
+ import { enqueueAttributeReaction } from './attribute-reactions.mjs';
5
+ import { performWithCustomElementReactions } from './custom-element-reactions.mjs';
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
  [OWNER_ELEMENT] = null;
@@ -20,15 +23,41 @@ class Attr extends Node {
20
23
  return this[NAME];
21
24
  }
22
25
  set name(_readonly) {}
26
+ get localName() {
27
+ if (this[NS] == null) return this[NAME];
28
+ const separator = this[NAME].indexOf(':');
29
+ return separator < 0 ? this[NAME] : this[NAME].slice(separator + 1);
30
+ }
31
+ get prefix() {
32
+ if (this[NS] == null) return null;
33
+ const separator = this[NAME].indexOf(':');
34
+ return separator < 0 ? null : this[NAME].slice(0, separator);
35
+ }
23
36
  get value() {
24
37
  return this[VALUE];
25
38
  }
26
39
  set value(value) {
27
40
  const str = String(value);
28
- this[VALUE] = str;
29
41
  const ownerElement = this[OWNER_ELEMENT];
30
- if (!ownerElement) return;
31
- this[HOOKS].setAttribute?.(ownerElement, this[NAME], str, this[NS]);
42
+ if (!ownerElement) {
43
+ this[VALUE] = str;
44
+ return;
45
+ }
46
+ performWithCustomElementReactions(() => {
47
+ const oldValue = this[VALUE];
48
+ this[VALUE] = str;
49
+ if (attributeObserversActive && oldValue !== str) {
50
+ queueMutationRecord({
51
+ type: 'attributes',
52
+ target: ownerElement,
53
+ attributeName: this[NAME],
54
+ attributeNamespace: this[NS],
55
+ oldValue
56
+ });
57
+ }
58
+ this[HOOKS].setAttribute?.(ownerElement, this[NAME], str, this[NS]);
59
+ enqueueAttributeReaction(ownerElement, this.localName, oldValue, str, this[NS]);
60
+ });
32
61
  }
33
62
  get nodeValue() {
34
63
  return this.value;
@@ -1,5 +1,6 @@
1
1
  import { DATA, HOOKS } from './constants.mjs';
2
2
  import { ChildNode } from './ChildNode.mjs';
3
+ import { queueMutationRecord, characterDataObserversActive } from './MutationObserver.mjs';
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() {