fix(document): throw stream errors in the relevant realm

This commit is contained in:
ldm0
2026-09-09 06:52:22 +08:00
parent e9d32a36ec
commit a06fbbdd28
2 changed files with 95 additions and 5 deletions
@@ -287,7 +287,7 @@ fn child_document_open_callback<'s>(
return;
}
if child_document_has_throw_on_dynamic_markup_insertion_counter(scope, document) {
throw_dynamic_markup_invalid_state(scope);
throw_dynamic_markup_invalid_state(scope, document);
return;
}
let _ = begin_child_document_stream_replacement(scope, handle, document);
@@ -322,7 +322,7 @@ fn child_document_write_or_writeln_callback<'s>(
};
let document = args.this();
if child_document_has_throw_on_dynamic_markup_insertion_counter(scope, document) {
throw_dynamic_markup_invalid_state(scope);
throw_dynamic_markup_invalid_state(scope, document);
return;
}
let mut chunk = String::new();
@@ -392,7 +392,7 @@ fn child_document_close_callback<'s>(
};
let document = args.this();
if child_document_has_throw_on_dynamic_markup_insertion_counter(scope, document) {
throw_dynamic_markup_invalid_state(scope);
throw_dynamic_markup_invalid_state(scope, document);
return;
}
let Some(host_ptr) = context_host_ptr_from_global_bridge(scope) else {
@@ -507,9 +507,15 @@ fn child_document_has_throw_on_dynamic_markup_insertion_counter<'s>(
.unwrap_or(false)
}
fn throw_dynamic_markup_invalid_state(scope: &mut v8::PinScope<'_, '_>) {
fn throw_dynamic_markup_invalid_state<'s>(
scope: &mut v8::PinScope<'s, '_>,
document: v8::Local<'s, v8::Object>,
) {
let relevant_context = crate::native_bridge::node_relevant_context(scope, document)
.unwrap_or_else(|| scope.get_current_context());
let relevant_scope = &mut v8::ContextScope::new(scope, relevant_context);
throw_dom_exception(
scope,
relevant_scope,
"InvalidStateError",
11,
"The object is in an invalid state.",
@@ -8268,6 +8268,90 @@ async fn child_document_write_custom_element_reaction_queue_wpt_shape() {
assert_eq!(result, expected);
}
#[tokio::test(flavor = "current_thread")]
async fn child_dynamic_markup_counter_exceptions_use_document_realm() {
let loader = ResourceRequestClient::new(&moli_fetch::FetchConfig::default()).expect("loader");
let mut vm = new_page_task_executor_test_vm_with_loader(
"https://dynamic-markup-exception-realm.test/",
&loader,
);
vm.eval(
r#"
(() => {
globalThis.__dynamicMarkupExceptionRealm = "pending";
new Promise((resolve) => {
const frame = document.createElement("iframe");
frame.srcdoc = "";
frame.onload = () => resolve(frame.contentWindow);
(document.body || document.documentElement || document).appendChild(frame);
}).then((childWindow) => {
const childDocument = childWindow.document;
childDocument.open();
const results = [];
class DynamicMarkupProbe extends childWindow.HTMLElement {
constructor() {
super();
const probe = (label, callback) => {
try {
callback();
results.push([label, "no throw"]);
} catch (error) {
results.push([
label,
error.name,
error.code,
error instanceof childWindow.DOMException,
error instanceof DOMException
]);
}
};
probe("open", () => childDocument.open());
probe("open-type", () => childDocument.open("text/html"));
probe("close", () => childDocument.close());
probe("write", () => childDocument.write("<b>write</b>"));
probe("writeln", () => childDocument.writeln("<b>writeln</b>"));
globalThis.__dynamicMarkupExceptionRealm = JSON.stringify({
distinctConstructors: childWindow.DOMException !== DOMException,
results
});
}
}
childWindow.customElements.define(
"dynamic-markup-probe",
DynamicMarkupProbe
);
childDocument.write(
"<!doctype html><body><dynamic-markup-probe></dynamic-markup-probe>"
);
childDocument.close();
}, (error) => {
globalThis.__dynamicMarkupExceptionRealm =
"reject:" + error.name + ":" + error.message;
});
return "scheduled";
})()
"#,
)
.expect("dynamic markup exception realm setup should evaluate");
let expected = r#"{"distinctConstructors":true,"results":[["open","InvalidStateError",11,true,false],["open-type","InvalidStateError",11,true,false],["close","InvalidStateError",11,true,false],["write","InvalidStateError",11,true,false],["writeln","InvalidStateError",11,true,false]]}"#;
advance_page_task_executor_until_eval_equals(
&mut vm,
&loader,
"globalThis.__dynamicMarkupExceptionRealm",
expected,
"child dynamic-markup exception realm",
)
.await;
let result = vm
.eval("globalThis.__dynamicMarkupExceptionRealm")
.expect("dynamic markup exception realm result should evaluate");
assert_eq!(result, expected);
}
#[test]
fn child_document_write_constructs_and_connects_predefined_custom_elements_without_a_body() {
let mut vm = new_storage_test_vm("https://document-write-custom-elements.test/");