From dbb70ca46b2fbb5bfede4acad7cbcd71eac9e36e Mon Sep 17 00:00:00 2001 From: ldm0 Date: Fri, 18 Sep 2026 23:38:59 +0800 Subject: [PATCH] fix(dom): return empty shallow clones of detached HTML documents Clear the initialized HTML shell before returning a shallow Document clone. This removes the unexpected doctype/root and allows callers to append a new document element. Deep clones still copy the source children. Cover omitted/false/undefined deep arguments, rootless and custom-root HTML, doctype-only documents, XHTML/XML controls, and preserved source identity. All 273 shared browser assertions pass; 15 upstream cases retain all 1442 passing subtests. Validation: cargo fmt --all; workspace/all-targets/all-features Clippy with -D warnings; cargo nextest run --no-fail-fast (19464 passed, 13 skipped). --- moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs | 2 +- moli-renderer-v8/tests/fixtures/document-shallow-clone.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs b/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs index 23f2f41d61..15c673b637 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs @@ -9,7 +9,7 @@ fn detached_document_shallow_clones_are_empty_and_accept_a_new_root() { .expect("Document shallow clone probe should evaluate"); let result: serde_json::Value = serde_json::from_str(&result).unwrap(); assert_eq!(result["failures"], serde_json::json!([]), "{result}"); - assert_eq!(result["checks"], 245); + assert_eq!(result["checks"], 273); } #[test] diff --git a/moli-renderer-v8/tests/fixtures/document-shallow-clone.js b/moli-renderer-v8/tests/fixtures/document-shallow-clone.js index 97972fa60d..91e3975565 100644 --- a/moli-renderer-v8/tests/fixtures/document-shallow-clone.js +++ b/moli-renderer-v8/tests/fixtures/document-shallow-clone.js @@ -31,6 +31,7 @@ equal(label + " doctype", copy.doctype, null); equal(label + " HTML structure", copy.head === null && copy.body === null, true); equal(label + " owner", copy.ownerDocument, null); + equal(label + " MIME", copy.contentType, source.contentType); equal(label + " view", copy.defaultView, null); const node = copy.createElement("probe"); let error = null; @@ -44,6 +45,7 @@ equal(name + ": deep identity", deep !== source, true); equal(name + ": deep equality", deep.isEqualNode(source), true); equal(name + ": deep count", deep.childNodes.length, original.length); + equal(name + ": deep MIME", deep.contentType, source.contentType); equal(name + ": deep children", Array.from(deep.childNodes).every((child, i) => child !== original[i] && child.ownerDocument === deep), true); equal(name + ": source unchanged", source.childNodes.length === original.length && original.every((child, i) => child === source.childNodes[i] && child.parentNode === source), true); }