diff --git a/moli-renderer-v8/src/custom_elements/parser_handoff.rs b/moli-renderer-v8/src/custom_elements/parser_handoff.rs index 106911d2be..03be911fa4 100644 --- a/moli-renderer-v8/src/custom_elements/parser_handoff.rs +++ b/moli-renderer-v8/src/custom_elements/parser_handoff.rs @@ -18,7 +18,6 @@ pub(crate) fn create_and_construct_parser_custom_element_direct_for_document( scope: &mut v8::PinScope<'_, '_>, host_ptr: *mut JsContextHost, document_handle: DomHandle, - document_has_body: bool, local_name: &str, namespace: &str, prefix: Option<&str>, @@ -29,7 +28,6 @@ pub(crate) fn create_and_construct_parser_custom_element_direct_for_document( let definition_match = lookup_parser_custom_element_definition_for_token( host_ptr, document_handle, - document_has_body, local_name, namespace, token_attributes, diff --git a/moli-renderer-v8/src/custom_elements/parser_handoff_definition.rs b/moli-renderer-v8/src/custom_elements/parser_handoff_definition.rs index ca8fbba343..9bbc17bdf5 100644 --- a/moli-renderer-v8/src/custom_elements/parser_handoff_definition.rs +++ b/moli-renderer-v8/src/custom_elements/parser_handoff_definition.rs @@ -16,7 +16,6 @@ pub(super) struct ParserCustomElementDefinitionMatch { pub(super) fn lookup_parser_custom_element_definition_for_token( host_ptr: *mut JsContextHost, document_handle: DomHandle, - document_has_body: bool, local_name: &str, namespace: &str, token_attributes: &[Attribute], @@ -25,9 +24,6 @@ pub(super) fn lookup_parser_custom_element_definition_for_token( if namespace != XHTML_NS { return None; } - if !document_has_body { - return None; - } let host = unsafe { &*host_ptr }; let document_default = host.default_custom_element_registry_association_for_document(document_handle); diff --git a/moli-renderer-v8/src/document_runtime/document_write.rs b/moli-renderer-v8/src/document_runtime/document_write.rs index 0e44a9a98e..796d579660 100644 --- a/moli-renderer-v8/src/document_runtime/document_write.rs +++ b/moli-renderer-v8/src/document_runtime/document_write.rs @@ -337,15 +337,11 @@ impl ParserElementCreationConsumer for DocumentWriteParserMutationOwner<'_, '_, &mut self, request: ParserElementCreationRequest<'_>, ) -> Option { - let document_has_body = self - .document_body_handle_for_document(request.document_handle) - .is_some(); let runtime = &mut *self.runtime; custom_elements::create_and_construct_parser_custom_element_direct_for_document( self.scope, self.host_ptr, request.document_handle, - document_has_body, request.local_name, request.namespace, request.prefix, diff --git a/moli-renderer-v8/src/runtime/phase_one/parser_turn.rs b/moli-renderer-v8/src/runtime/phase_one/parser_turn.rs index dc7e3f0eb5..ad9deec3fc 100644 --- a/moli-renderer-v8/src/runtime/phase_one/parser_turn.rs +++ b/moli-renderer-v8/src/runtime/phase_one/parser_turn.rs @@ -375,14 +375,10 @@ impl ParserElementCreationConsumer for PhaseOneParserOwner<'_> { &mut self, request: ParserElementCreationRequest<'_>, ) -> Option { - let document_has_body = self - .document_body_handle_for_document(request.document_handle) - .is_some(); self.vm .create_and_construct_parser_custom_element_direct_in_default_context( request.construction, request.document_handle, - document_has_body, request.local_name, request.namespace, request.prefix, diff --git a/moli-renderer-v8/src/script_vm.rs b/moli-renderer-v8/src/script_vm.rs index e5fbff6176..b29bcb9c9f 100644 --- a/moli-renderer-v8/src/script_vm.rs +++ b/moli-renderer-v8/src/script_vm.rs @@ -4733,7 +4733,6 @@ impl ScriptVm { &mut self, construction: &moli_dom::native::ParserConstruction, document_handle: DomHandle, - document_has_body: bool, local_name: &str, namespace: &str, prefix: Option<&str>, @@ -4758,7 +4757,6 @@ impl ScriptVm { scope, host_ptr, document_handle, - document_has_body, local_name, namespace, prefix, diff --git a/moli-renderer-v8/src/script_vm/tests/dom_elements/custom_elements/detached_documents_and_reactions.rs b/moli-renderer-v8/src/script_vm/tests/dom_elements/custom_elements/detached_documents_and_reactions.rs index 59716432a8..2857f2c970 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_elements/custom_elements/detached_documents_and_reactions.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_elements/custom_elements/detached_documents_and_reactions.rs @@ -2082,3 +2082,77 @@ async fn child_document_write_custom_element_reaction_queue_wpt_shape() { assert_eq!(result, expected); } + +#[test] +fn child_document_write_constructs_predefined_custom_elements_without_a_body() { + let mut vm = new_storage_test_vm("https://document-write-custom-elements.test/"); + + vm.eval( + r#" + (() => { + const target = document.body || document.documentElement || document; + window.__writeCustomElementFrames = ["write", "writeln"].map(() => { + const frame = document.createElement("iframe"); + target.appendChild(frame); + frame.srcdoc = ""; + return frame; + }); + return "scheduled"; + })() + "#, + ) + .expect("child document.write predefined custom element setup should evaluate"); + vm.drain_pending_child_frame_work_for_test(); + + let result = vm + .eval( + r#" + (() => { + const exercise = (frame, method, name) => { + const childWindow = frame.contentWindow; + const childDocument = frame.contentDocument; + const registry = childWindow.customElements; + let constructorCount = 0; + let errorName = null; + childWindow.addEventListener("error", event => { + errorName = event.error && event.error.name; + event.preventDefault(); + }, { once: true }); + class DefinedElement extends childWindow.HTMLElement { + constructor() { + super(); + constructorCount++; + } + } + registry.define(name, DefinedElement); + const definitionBeforeWrite = registry.get(name) === DefinedElement; + + childDocument[method](`<${name}>`); + const element = childDocument.querySelector(name); + return { + registryPreserved: childWindow.customElements === registry, + definitionBeforeWrite, + definitionAfterWrite: registry.get(name) === DefinedElement, + constructorCount, + errorName, + htmlElement: element instanceof childWindow.HTMLElement, + customElement: element instanceof DefinedElement, + ownerDocument: element.ownerDocument === childDocument + }; + }; + + const [writeFrame, writelnFrame] = window.__writeCustomElementFrames; + return JSON.stringify({ + write: exercise(writeFrame, "write", "write-defined-element"), + writeln: exercise(writelnFrame, "writeln", "writeln-defined-element") + }); + })() + "#, + ) + .expect("child document.write predefined custom element result should evaluate"); + + assert_eq!( + result, + r#"{"write":{"registryPreserved":true,"definitionBeforeWrite":true,"definitionAfterWrite":true,"constructorCount":1,"errorName":null,"htmlElement":true,"customElement":true,"ownerDocument":true},"writeln":{"registryPreserved":true,"definitionBeforeWrite":true,"definitionAfterWrite":true,"constructorCount":1,"errorName":null,"htmlElement":true,"customElement":true,"ownerDocument":true}}"# + ); +}