mirror of
https://github.com/lexmount/moli.git
synced 2026-10-30 16:07:24 +00:00
fix(dom): resolve foreign reflectors in their owning page
Validation on this branch: cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings. Nextest and WPT reruns omitted at the user's request. Includes the ablation-confirmed cleanup from c1fe3ea895.
This commit is contained in:
+23
@@ -999,6 +999,29 @@ async fn auxiliary_cross_origin_functions_and_descriptors_use_each_accessing_rea
|
||||
abort_test_cdp_server(server).await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn auxiliary_page_adoption_preserves_native_node_and_owner_document_identity() {
|
||||
let (addr, server) = spawn_test_protocol_server().await;
|
||||
let (mut browser, _) =
|
||||
connect_async(format!("ws://{addr}/devtools/browser/{DEFAULT_BROWSER_ID}"))
|
||||
.await
|
||||
.unwrap();
|
||||
let opener_id = create_dynamic_target(&mut browser, 1).await;
|
||||
let mut opener = connect_dynamic_page(addr, &opener_id).await;
|
||||
let (_, _child) = open_auxiliary(addr, &mut opener, "").await;
|
||||
assert_eq!(evaluate_window_name_probe(&mut opener, 2, r#"(()=>{
|
||||
window.div=document.createElement('div');
|
||||
window.span=document.createElement('span');div.append(span);
|
||||
p.document.body.append(div);
|
||||
return [div.ownerDocument===p.document,span.ownerDocument===p.document,p.document.body.firstChild===div,div.ownerDocument===document,div.ownerDocument.defaultView===p,p.document.defaultView===p];
|
||||
})()"#).await, json!([true,true,true,false,true,true]));
|
||||
assert_eq!(evaluate_window_name_probe(&mut opener, 3, r#"(()=>{
|
||||
document.body.append(div);
|
||||
return [div.ownerDocument===document,span.ownerDocument===document,document.body.lastChild===div];
|
||||
})()"#).await, json!([true,true,true]));
|
||||
abort_test_cdp_server(server).await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn initial_same_origin_popup_commit_preserves_window_and_replaces_document() {
|
||||
let (fixture_addr, _fixture) = spawn_dedicated_fixture_server(
|
||||
|
||||
@@ -49,6 +49,20 @@ impl NativeDomBridge {
|
||||
host_ptr: *mut JsContextHost,
|
||||
handle: BridgeHandle,
|
||||
) -> Option<v8::Local<'s, v8::Object>> {
|
||||
if crate::util::context_host_ptr_from_context_slot(scope.get_current_context())
|
||||
.is_some_and(|current| current != host_ptr)
|
||||
{
|
||||
// Reflector IDs are local to a DOM bridge. Related Pages share
|
||||
// an isolate, but must never consult one another's wrapper cache.
|
||||
let host = unsafe { &*host_ptr };
|
||||
let dispatch_scope = crate::native_bridge::OwnerDispatchScope::Top;
|
||||
let owner = host.current_window_execution_context_owner(dispatch_scope)?;
|
||||
let context = host
|
||||
.window_execution_context(scope, owner, dispatch_scope)?
|
||||
.1;
|
||||
let scope = &mut v8::ContextScope::new(scope, context);
|
||||
return self.wrap_bridge_handle(scope, host_ptr, handle);
|
||||
}
|
||||
let reflector_id = self.identity.reflector_id(&handle);
|
||||
if let Some(wrapper) = self.identity.cached_wrapper(scope, reflector_id) {
|
||||
return Some(wrapper);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::super::{BridgeHandle, JsContextHost, ReflectorId};
|
||||
use crate::util::context_host_ptr_from_global_bridge;
|
||||
use crate::util::{context_host_ptr_from_context_slot, context_host_ptr_from_global_bridge};
|
||||
use anyhow::{Context, bail, ensure};
|
||||
|
||||
fn object_reflector_id(
|
||||
@@ -32,7 +32,12 @@ pub(in crate::native_bridge) fn bridge_handle_from_object(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
object: v8::Local<'_, v8::Object>,
|
||||
) -> anyhow::Result<(*mut JsContextHost, BridgeHandle)> {
|
||||
let runtime_ptr = context_host_ptr_from_global_bridge(scope)
|
||||
// Related Pages share an isolate, but reflector IDs belong to the
|
||||
// wrapper's original DOM bridge rather than the calling Window's bridge.
|
||||
let runtime_ptr = object
|
||||
.get_creation_context(scope)
|
||||
.and_then(context_host_ptr_from_context_slot)
|
||||
.or_else(|| context_host_ptr_from_global_bridge(scope))
|
||||
.context("current context has no JsContextHost")?;
|
||||
let reflector_id = object_reflector_id(scope, object)?;
|
||||
let handle = unsafe { &*runtime_ptr }
|
||||
|
||||
@@ -1216,6 +1216,12 @@ pub(crate) fn node_runtime_and_handle_from_object(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
object: v8::Local<'_, v8::Object>,
|
||||
) -> anyhow::Result<(*mut JsContextHost, DomHandle)> {
|
||||
let object = v8::Local::new(scope, object);
|
||||
if let Some(delegate) =
|
||||
crate::util::get_private_object(scope, object, super::document::DETACHED_LIVE_DELEGATE_SLOT)
|
||||
{
|
||||
return node_runtime_and_handle_from_object(scope, delegate);
|
||||
}
|
||||
let (runtime_ptr, handle) = super::bridge_handle_from_object(scope, object)
|
||||
.context("failed to resolve Node wrapper")?;
|
||||
match handle {
|
||||
|
||||
Reference in New Issue
Block a user