@miaskiewicz/turbo-dom 0.1.52 → 0.1.54

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/Cargo.lock CHANGED
@@ -359,6 +359,12 @@ version = "0.8.10"
359
359
  source = "registry+https://github.com/rust-lang/crates.io-index"
360
360
  checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
361
361
 
362
+ [[package]]
363
+ name = "rustc-hash"
364
+ version = "2.1.2"
365
+ source = "registry+https://github.com/rust-lang/crates.io-index"
366
+ checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
367
+
362
368
  [[package]]
363
369
  name = "rustversion"
364
370
  version = "1.0.22"
@@ -491,6 +497,7 @@ dependencies = [
491
497
  "napi",
492
498
  "napi-build",
493
499
  "napi-derive",
500
+ "rustc-hash",
494
501
  "serde",
495
502
  "serde-wasm-bindgen",
496
503
  "wasm-bindgen",
package/Cargo.toml CHANGED
@@ -11,6 +11,7 @@ crate-type = ["cdylib", "rlib"]
11
11
  # Shared parser core
12
12
  html5ever = "0.39"
13
13
  markup5ever_rcdom = "0.39"
14
+ rustc-hash = "2" # fast non-crypto FxHashMap for string interning (parse hot path)
14
15
 
15
16
  # napi-rs front-end (native addon). Gated so the wasm build doesn't pull it.
16
17
  napi = { version = "2", default-features = false, features = ["napi6"], optional = true }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miaskiewicz/turbo-dom",
3
- "version": "0.1.52",
3
+ "version": "0.1.54",
4
4
  "description": "Faster, more spec-correct DOM for test runners — native html5ever (Rust/WASM) parser + lazy copy-on-write DOM. A drop-in-style alternative to jsdom/happy-dom for vitest & jest.",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
package/src/core.rs CHANGED
@@ -101,10 +101,10 @@ pub struct Soa {
101
101
 
102
102
  struct SoaBuilder {
103
103
  soa: Soa,
104
- tag_map: std::collections::HashMap<String, u32>,
105
- attr_name_map: std::collections::HashMap<String, u32>,
106
- attr_prefix_map: std::collections::HashMap<String, u32>,
107
- attr_value_map: std::collections::HashMap<String, u32>,
104
+ tag_map: rustc_hash::FxHashMap<String, u32>,
105
+ attr_name_map: rustc_hash::FxHashMap<String, u32>,
106
+ attr_prefix_map: rustc_hash::FxHashMap<String, u32>,
107
+ attr_value_map: rustc_hash::FxHashMap<String, u32>,
108
108
  }
109
109
 
110
110
  impl SoaBuilder {
@@ -261,10 +261,10 @@ pub fn parse_html_soa(html: &str) -> Soa {
261
261
  .expect("RcDom read_from is infallible over a byte slice");
262
262
  let mut b = SoaBuilder {
263
263
  soa: Soa::default(),
264
- tag_map: std::collections::HashMap::new(),
265
- attr_name_map: std::collections::HashMap::new(),
266
- attr_prefix_map: std::collections::HashMap::new(),
267
- attr_value_map: std::collections::HashMap::new(),
264
+ tag_map: rustc_hash::FxHashMap::default(),
265
+ attr_name_map: rustc_hash::FxHashMap::default(),
266
+ attr_prefix_map: rustc_hash::FxHashMap::default(),
267
+ attr_value_map: rustc_hash::FxHashMap::default(),
268
268
  };
269
269
  b.alloc(&dom.document, -1);
270
270
  b.soa
@@ -934,7 +934,14 @@ export class DocumentFragment extends Node {
934
934
  querySelectorAll(sel) { return cachedQSA(this, sel); }
935
935
  get children() { if (this.__childrenList) return this.__childrenList; const self = this; return (this.__childrenList = liveHTMLCollection(() => self.__children().filter((n) => n.nodeType === ELEMENT_NODE))); }
936
936
  append(...nodes) { for (const n of nodes) this.appendChild(toNode(this.ownerDocument, n)); }
937
- cloneNode(deep = false) { const f = new DocumentFragment(this.ownerDocument); if (deep) for (const c of this.__children()) f.appendChild(c.cloneNode(true)); return f; }
937
+ cloneNode(deep = false) {
938
+ const f = new DocumentFragment(this.ownerDocument);
939
+ if (deep) { // direct __kids build — detached clone, per-child appendChild bookkeeping is waste (see Element.cloneNode)
940
+ const src = this.__children(), od = f.ownerDocument, kids = f.__kids = new Array(src.length);
941
+ for (let i = 0; i < src.length; i++) { const cl = src[i].cloneNode(true); cl.parentNode = f; cl.ownerDocument = od; kids[i] = cl; }
942
+ }
943
+ return f;
944
+ }
938
945
  }
939
946
 
940
947
  // A real shadow root: a detached document-fragment subtree with a back-reference
Binary file
Binary file