diff --git a/moli-renderer-v8/src/native_bridge/bindings.rs b/moli-renderer-v8/src/native_bridge/bindings.rs index f74eaf2298..93d741b491 100644 --- a/moli-renderer-v8/src/native_bridge/bindings.rs +++ b/moli-renderer-v8/src/native_bridge/bindings.rs @@ -68,21 +68,21 @@ pub(crate) struct NativeBridgeBindings { fn wrapper_kind_for_handle(handle: &BridgeHandle) -> WrapperKind { match handle { BridgeHandle::Window => WrapperKind::Window, - BridgeHandle::ClassList(_, _, _) => WrapperKind::ClassList, - BridgeHandle::Dataset(_, _) => WrapperKind::Dataset, - BridgeHandle::Style(_, _) => WrapperKind::Style, - BridgeHandle::ComputedStyle(_, _, _) => WrapperKind::ComputedStyle, - BridgeHandle::Node(_, _) => WrapperKind::Node, + BridgeHandle::ClassList(_, _) => WrapperKind::ClassList, + BridgeHandle::Dataset(_) => WrapperKind::Dataset, + BridgeHandle::Style(_) => WrapperKind::Style, + BridgeHandle::ComputedStyle(_, _) => WrapperKind::ComputedStyle, + BridgeHandle::Node(_) => WrapperKind::Node, } } fn prototype_name_for_handle(host_ptr: *mut JsContextHost, handle: &BridgeHandle) -> &'static str { match handle { BridgeHandle::Window => "Window", - BridgeHandle::ClassList(_, _, _) => "DOMTokenList", - BridgeHandle::Dataset(_, _) => "DOMStringMap", - BridgeHandle::Style(_, _) | BridgeHandle::ComputedStyle(_, _, _) => "CSSStyleProperties", - BridgeHandle::Node(node_handle, _) => { + BridgeHandle::ClassList(_, _) => "DOMTokenList", + BridgeHandle::Dataset(_) => "DOMStringMap", + BridgeHandle::Style(_) | BridgeHandle::ComputedStyle(_, _) => "CSSStyleProperties", + BridgeHandle::Node(node_handle) => { let runtime = unsafe { &*host_ptr }; if runtime.dom_host().is_shadow_root(*node_handle) { "ShadowRoot" @@ -275,7 +275,7 @@ impl NativeBridgeBindings { window::sync_window_wrapper_function_identity(scope, wrapper); return; } - let BridgeHandle::Node(node_handle, _) = handle else { + let BridgeHandle::Node(node_handle) = handle else { return; }; let child_handle = { diff --git a/moli-renderer-v8/src/native_bridge/bridge/callbacks.rs b/moli-renderer-v8/src/native_bridge/bridge/callbacks.rs index 540c99fb9e..92cafb5570 100644 --- a/moli-renderer-v8/src/native_bridge/bridge/callbacks.rs +++ b/moli-renderer-v8/src/native_bridge/bridge/callbacks.rs @@ -136,12 +136,12 @@ pub(crate) fn callback_value_dom_handle( let object = v8::Local::::try_from(value).ok()?; let (_, handle) = bridge_handle_from_object(scope, object).ok()?; match handle { - BridgeHandle::Node(handle, _) => Some(handle), + BridgeHandle::Node(handle) => Some(handle), BridgeHandle::Window - | BridgeHandle::ClassList(_, _, _) - | BridgeHandle::Dataset(_, _) - | BridgeHandle::Style(_, _) - | BridgeHandle::ComputedStyle(_, _, _) => None, + | BridgeHandle::ClassList(_, _) + | BridgeHandle::Dataset(_) + | BridgeHandle::Style(_) + | BridgeHandle::ComputedStyle(_, _) => None, } } diff --git a/moli-renderer-v8/src/native_bridge/bridge/wrappers.rs b/moli-renderer-v8/src/native_bridge/bridge/wrappers.rs index 292b628396..43b1b4edc8 100644 --- a/moli-renderer-v8/src/native_bridge/bridge/wrappers.rs +++ b/moli-renderer-v8/src/native_bridge/bridge/wrappers.rs @@ -15,20 +15,17 @@ impl NativeDomBridge { host_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*host_ptr }.runtime_reset_generation(); - self.wrap_bridge_handle(scope, host_ptr, BridgeHandle::Node(handle, generation)) + self.wrap_bridge_handle(scope, host_ptr, BridgeHandle::Node(handle)) } pub(crate) fn cached_handle_wrapper<'s>( &self, scope: &mut v8::PinScope<'s, '_>, - host_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*host_ptr }.runtime_reset_generation(); let reflector_id = self .identity - .existing_reflector_id(BridgeHandle::Node(handle, generation))?; + .existing_reflector_id(BridgeHandle::Node(handle))?; self.identity.cached_wrapper(scope, reflector_id) } @@ -40,15 +37,6 @@ impl NativeDomBridge { .retire_default_world_wrappers_for_realm(realm_token); } - pub(crate) fn rebind_wrapper_generation( - &mut self, - old_generation: u64, - new_generation: u64, - ) -> Option { - self.identity - .rebind_generation(old_generation, new_generation) - } - pub(crate) fn wrap_window<'s, 'i>( &mut self, scope: &mut v8::PinScope<'s, 'i>, @@ -87,8 +75,7 @@ impl NativeDomBridge { handle: DomHandle, ) -> Option> { let creation_context = receiver.get_creation_context(scope)?; - let generation = unsafe { &*host_ptr }.runtime_reset_generation(); - let bridge_handle = BridgeHandle::Node(handle, generation); + let bridge_handle = BridgeHandle::Node(handle); if creation_context == scope.get_current_context() { return self.wrap_bridge_handle(scope, host_ptr, bridge_handle); } @@ -107,11 +94,10 @@ impl NativeDomBridge { runtime_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); self.wrap_bridge_handle( scope, runtime_ptr, - BridgeHandle::ClassList(handle, generation, DomTokenListKind::Class), + BridgeHandle::ClassList(handle, DomTokenListKind::Class), ) } @@ -121,11 +107,10 @@ impl NativeDomBridge { runtime_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); self.wrap_bridge_handle( scope, runtime_ptr, - BridgeHandle::ClassList(handle, generation, DomTokenListKind::Part), + BridgeHandle::ClassList(handle, DomTokenListKind::Part), ) } @@ -135,11 +120,10 @@ impl NativeDomBridge { runtime_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); self.wrap_bridge_handle( scope, runtime_ptr, - BridgeHandle::ClassList(handle, generation, DomTokenListKind::Rel), + BridgeHandle::ClassList(handle, DomTokenListKind::Rel), ) } @@ -149,12 +133,7 @@ impl NativeDomBridge { runtime_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); - self.wrap_bridge_handle( - scope, - runtime_ptr, - BridgeHandle::Dataset(handle, generation), - ) + self.wrap_bridge_handle(scope, runtime_ptr, BridgeHandle::Dataset(handle)) } pub(crate) fn wrap_style<'s, 'i>( @@ -163,8 +142,7 @@ impl NativeDomBridge { runtime_ptr: *mut JsContextHost, handle: DomHandle, ) -> Option> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); - self.wrap_bridge_handle(scope, runtime_ptr, BridgeHandle::Style(handle, generation)) + self.wrap_bridge_handle(scope, runtime_ptr, BridgeHandle::Style(handle)) } pub(crate) fn wrap_computed_style<'s, 'i>( @@ -174,23 +152,22 @@ impl NativeDomBridge { handle: DomHandle, descriptor: ComputedStyleDescriptor, ) -> Option> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); self.wrap_bridge_handle( scope, runtime_ptr, - BridgeHandle::ComputedStyle(handle, generation, descriptor), + BridgeHandle::ComputedStyle(handle, descriptor), ) } pub(crate) fn resolve_node_handle(&self, reflector_id: ReflectorId) -> Option { match self.bridge_handle(reflector_id) { - Some(BridgeHandle::Node(handle, _)) => Some(handle), + Some(BridgeHandle::Node(handle)) => Some(handle), Some( BridgeHandle::Window - | BridgeHandle::ClassList(_, _, _) - | BridgeHandle::Dataset(_, _) - | BridgeHandle::Style(_, _) - | BridgeHandle::ComputedStyle(_, _, _), + | BridgeHandle::ClassList(_, _) + | BridgeHandle::Dataset(_) + | BridgeHandle::Style(_) + | BridgeHandle::ComputedStyle(_, _), ) | None => None, } diff --git a/moli-renderer-v8/src/native_bridge/collections/bridge_callbacks.rs b/moli-renderer-v8/src/native_bridge/collections/bridge_callbacks.rs index dbe7933ce0..7c0417fb0d 100644 --- a/moli-renderer-v8/src/native_bridge/collections/bridge_callbacks.rs +++ b/moli-renderer-v8/src/native_bridge/collections/bridge_callbacks.rs @@ -215,7 +215,6 @@ fn bridge_create_live_collection_callback( return; }; - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); let tag_name_html_document = (query_kind == LiveCollectionQueryKind::TagName).then(|| { unsafe { &*runtime_ptr } .dom_host() @@ -226,7 +225,6 @@ fn bridge_create_live_collection_callback( collection_kind, query_kind, root, - generation, query, include_root, tag_name_html_document, diff --git a/moli-renderer-v8/src/native_bridge/collections/builders.rs b/moli-renderer-v8/src/native_bridge/collections/builders.rs index 1413c2d96e..c6cc1cc002 100644 --- a/moli-renderer-v8/src/native_bridge/collections/builders.rs +++ b/moli-renderer-v8/src/native_bridge/collections/builders.rs @@ -182,7 +182,6 @@ pub(in crate::native_bridge) fn build_live_collection_for_node<'s>( query: Option, include_root: bool, ) -> v8::Local<'s, v8::Object> { - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); let tag_name_html_document = (query_kind == LiveCollectionQueryKind::TagName).then(|| { unsafe { &*runtime_ptr } .dom_host() @@ -196,7 +195,6 @@ pub(in crate::native_bridge) fn build_live_collection_for_node<'s>( collection_kind, query_kind, root, - generation, query, include_root, tag_name_html_document, diff --git a/moli-renderer-v8/src/native_bridge/collections/iteration.rs b/moli-renderer-v8/src/native_bridge/collections/iteration.rs index 056b3416f0..1cbc4d55de 100644 --- a/moli-renderer-v8/src/native_bridge/collections/iteration.rs +++ b/moli-renderer-v8/src/native_bridge/collections/iteration.rs @@ -64,7 +64,6 @@ fn collection_named_value<'s>( collection_kind: CollectionKind::RadioNodeList, query_kind: LiveCollectionQueryKind::FormControlsByName, root: descriptor.root, - generation: descriptor.generation, query: Some(key.to_owned()), include_root: false, tag_name_html_document: None, diff --git a/moli-renderer-v8/src/native_bridge/collections/live_handlers.rs b/moli-renderer-v8/src/native_bridge/collections/live_handlers.rs index 71d070943b..1227d27d36 100644 --- a/moli-renderer-v8/src/native_bridge/collections/live_handlers.rs +++ b/moli-renderer-v8/src/native_bridge/collections/live_handlers.rs @@ -369,7 +369,6 @@ fn live_collection_named_value<'s>( collection_kind: CollectionKind::RadioNodeList, query_kind: LiveCollectionQueryKind::FormControlsByName, root: descriptor.root, - generation: descriptor.generation, query: Some(key), include_root: false, tag_name_html_document: None, diff --git a/moli-renderer-v8/src/native_bridge/context_host/child_frame_runtime/document.rs b/moli-renderer-v8/src/native_bridge/context_host/child_frame_runtime/document.rs index 58ee900b93..d54a83e331 100644 --- a/moli-renderer-v8/src/native_bridge/context_host/child_frame_runtime/document.rs +++ b/moli-renderer-v8/src/native_bridge/context_host/child_frame_runtime/document.rs @@ -118,14 +118,13 @@ impl JsContextHost { scope: &mut v8::PinScope<'_, '_>, document_handle: DomHandle, ) { - let host_ptr = self as *mut JsContextHost; let mut stack = vec![document_handle]; while let Some(current) = stack.pop() { let children = self.dom_host().child_handles(current).collect::>(); stack.extend(children); if let Some(wrapper) = self .native_bridge_mut() - .cached_handle_wrapper(scope, host_ptr, current) + .cached_handle_wrapper(scope, current) { let undefined = v8::undefined(scope); set_private_value( diff --git a/moli-renderer-v8/src/native_bridge/document.rs b/moli-renderer-v8/src/native_bridge/document.rs index a8027e4b2b..d447b08a7d 100644 --- a/moli-renderer-v8/src/native_bridge/document.rs +++ b/moli-renderer-v8/src/native_bridge/document.rs @@ -1234,7 +1234,6 @@ fn document_html_collection_getter<'s>( } return; } - let generation = runtime.runtime_reset_generation(); let (query_kind, query, tag_name_html_document) = match kind { DocumentCollectionAccessorKind::Forms => (LiveCollectionQueryKind::Forms, None, None), DocumentCollectionAccessorKind::Images => (LiveCollectionQueryKind::Images, None, None), @@ -1256,7 +1255,6 @@ fn document_html_collection_getter<'s>( collection_kind: CollectionKind::HtmlCollection, query_kind, root: handle, - generation, query, include_root: true, tag_name_html_document, diff --git a/moli-renderer-v8/src/native_bridge/document/detached_objects/state_tree.rs b/moli-renderer-v8/src/native_bridge/document/detached_objects/state_tree.rs index 79d2305ede..687334d119 100644 --- a/moli-renderer-v8/src/native_bridge/document/detached_objects/state_tree.rs +++ b/moli-renderer-v8/src/native_bridge/document/detached_objects/state_tree.rs @@ -492,7 +492,7 @@ pub(crate) fn paired_detached_native_object_for_handle<'s>( let runtime = unsafe { &mut *runtime_ptr }; runtime .native_bridge_mut() - .cached_handle_wrapper(scope, runtime_ptr, handle) + .cached_handle_wrapper(scope, handle) }?; get_private_object(scope, wrapper, DOM_PARSER_FOREIGN_NODE_SLOT) } diff --git a/moli-renderer-v8/src/native_bridge/document/lifecycle.rs b/moli-renderer-v8/src/native_bridge/document/lifecycle.rs index fd0725d016..3173466a04 100644 --- a/moli-renderer-v8/src/native_bridge/document/lifecycle.rs +++ b/moli-renderer-v8/src/native_bridge/document/lifecycle.rs @@ -196,21 +196,6 @@ fn clear_window_event_handlers(scope: &mut v8::PinScope<'_, '_>) { } } -fn require_collision_free_wrapper_generation_rebind( - rebound: Option, - old_generation: u64, - new_generation: u64, -) -> usize { - // Page.setDocumentContent may replace a document before page script has - // materialized any DOM wrapper. Some(0) is therefore a successful no-op; - // None alone reports an identity-key collision. - rebound.unwrap_or_else(|| { - panic!( - "wrapper identity collision while rebinding document replacement from generation {old_generation} to {new_generation}" - ) - }) -} - impl JsContextHost { fn prepare_root_document_replacement( &mut self, @@ -218,7 +203,6 @@ impl JsContextHost { host_ptr: *mut JsContextHost, document_handle: DomHandle, ) { - let old_generation = self.runtime_reset_generation(); self.dispatch_document_open_descendant_frame_unload_lifecycle(scope, document_handle); self.clear_event_callbacks_for_document_replacement(document_handle, true); custom_elements::with_custom_element_reaction_scope(scope, host_ptr, |scope| { @@ -229,16 +213,6 @@ impl JsContextHost { ); }); self.open_root_document(scope); - - let new_generation = self.runtime_reset_generation(); - let rebound = self - .native_bridge_mut() - .rebind_wrapper_generation(old_generation, new_generation); - let _ = require_collision_free_wrapper_generation_rebind( - rebound, - old_generation, - new_generation, - ); } /// Replaces the active root document through the native document stream. @@ -988,17 +962,3 @@ fn boundary_after_protected_inert_root( let offset = u32::try_from(index + 1).ok()?; Some((parent, offset)) } - -#[cfg(test)] -mod tests { - #[test] - fn document_replacement_accepts_an_empty_wrapper_identity_store() { - let mut identity = crate::native_bridge::identity::BridgeIdentityStore::default(); - let rebound = identity.rebind_generation(4, 5); - - assert_eq!( - super::require_collision_free_wrapper_generation_rebind(rebound, 4, 5), - 0 - ); - } -} diff --git a/moli-renderer-v8/src/native_bridge/element/attributes/inspector.rs b/moli-renderer-v8/src/native_bridge/element/attributes/inspector.rs index 9939c46e62..37073c812c 100644 --- a/moli-renderer-v8/src/native_bridge/element/attributes/inspector.rs +++ b/moli-renderer-v8/src/native_bridge/element/attributes/inspector.rs @@ -88,7 +88,7 @@ pub(crate) fn mutate_live_element_attribute_for_inspector( if let Some((namespace, local_name)) = attr_cache_target && let Some(wrapper) = unsafe { &mut *runtime_ptr } .native_bridge_mut() - .cached_handle_wrapper(scope, runtime_ptr, handle) + .cached_handle_wrapper(scope, handle) { clear_live_attr_cache_entry_ns(scope, wrapper, namespace.as_deref(), &local_name); } diff --git a/moli-renderer-v8/src/native_bridge/element/class_list/identity.rs b/moli-renderer-v8/src/native_bridge/element/class_list/identity.rs index 94efbc4bd6..b6d0295865 100644 --- a/moli-renderer-v8/src/native_bridge/element/class_list/identity.rs +++ b/moli-renderer-v8/src/native_bridge/element/class_list/identity.rs @@ -6,12 +6,12 @@ pub(super) fn class_list_runtime_handle_and_kind_from_object( ) -> std::result::Result<(*mut JsContextHost, DomHandle, DomTokenListKind), String> { let (runtime_ptr, handle) = bridge_handle_from_object(scope, object)?; match handle { - BridgeHandle::ClassList(handle, _, kind) => Ok((runtime_ptr, handle, kind)), + BridgeHandle::ClassList(handle, kind) => Ok((runtime_ptr, handle, kind)), BridgeHandle::Window - | BridgeHandle::Node(_, _) - | BridgeHandle::Dataset(_, _) - | BridgeHandle::Style(_, _) - | BridgeHandle::ComputedStyle(_, _, _) => { + | BridgeHandle::Node(_) + | BridgeHandle::Dataset(_) + | BridgeHandle::Style(_) + | BridgeHandle::ComputedStyle(_, _) => { Err("wrapper did not contain a DOMTokenList identity".to_owned()) } } diff --git a/moli-renderer-v8/src/native_bridge/element/dataset.rs b/moli-renderer-v8/src/native_bridge/element/dataset.rs index aef92b0949..467ff19c14 100644 --- a/moli-renderer-v8/src/native_bridge/element/dataset.rs +++ b/moli-renderer-v8/src/native_bridge/element/dataset.rs @@ -46,12 +46,12 @@ fn dataset_runtime_and_handle_from_object( ) -> std::result::Result<(*mut JsContextHost, DomHandle), String> { let (runtime_ptr, handle) = bridge_handle_from_object(scope, object)?; match handle { - BridgeHandle::Dataset(handle, _) => Ok((runtime_ptr, handle)), + BridgeHandle::Dataset(handle) => Ok((runtime_ptr, handle)), BridgeHandle::Window - | BridgeHandle::Node(_, _) - | BridgeHandle::ClassList(_, _, _) - | BridgeHandle::Style(_, _) - | BridgeHandle::ComputedStyle(_, _, _) => { + | BridgeHandle::Node(_) + | BridgeHandle::ClassList(_, _) + | BridgeHandle::Style(_) + | BridgeHandle::ComputedStyle(_, _) => { Err("wrapper did not contain a DOMStringMap identity".to_owned()) } } diff --git a/moli-renderer-v8/src/native_bridge/element/forms/form_element.rs b/moli-renderer-v8/src/native_bridge/element/forms/form_element.rs index 7721ccca94..ad6512f8df 100644 --- a/moli-renderer-v8/src/native_bridge/element/forms/form_element.rs +++ b/moli-renderer-v8/src/native_bridge/element/forms/form_element.rs @@ -255,12 +255,10 @@ pub(in crate::native_bridge) fn form_elements_getter_function<'s>( rv.set_null(); return; }; - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); let descriptor = LiveCollectionDescriptor { collection_kind: CollectionKind::FormControlsCollection, query_kind: LiveCollectionQueryKind::FormControls, root: handle, - generation, query: None, include_root: false, tag_name_html_document: None, @@ -440,12 +438,10 @@ pub(in crate::native_bridge) fn fieldset_elements_getter_function<'s>( rv.set_null(); return; }; - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); let descriptor = LiveCollectionDescriptor { collection_kind: CollectionKind::HtmlCollection, query_kind: LiveCollectionQueryKind::FormControls, root: handle, - generation, query: None, include_root: false, tag_name_html_document: None, @@ -571,7 +567,6 @@ pub(in crate::native_bridge) fn form_named_getter( collection_kind: CollectionKind::RadioNodeList, query_kind: LiveCollectionQueryKind::FormControlsByName, root: handle, - generation: runtime.runtime_reset_generation(), query: Some(key), include_root: false, tag_name_html_document: None, @@ -631,7 +626,6 @@ pub(in crate::native_bridge) fn form_named_descriptor( collection_kind: CollectionKind::RadioNodeList, query_kind: LiveCollectionQueryKind::FormControlsByName, root: handle, - generation: runtime.runtime_reset_generation(), query: Some(key), include_root: false, tag_name_html_document: None, diff --git a/moli-renderer-v8/src/native_bridge/element/forms/select/select_element.rs b/moli-renderer-v8/src/native_bridge/element/forms/select/select_element.rs index d03dc5a807..1f502082b5 100644 --- a/moli-renderer-v8/src/native_bridge/element/forms/select/select_element.rs +++ b/moli-renderer-v8/src/native_bridge/element/forms/select/select_element.rs @@ -557,12 +557,10 @@ pub(in crate::native_bridge) fn select_options_getter_function<'s>( rv.set_null(); return; }; - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); let descriptor = LiveCollectionDescriptor { collection_kind: CollectionKind::OptionsCollection, query_kind: LiveCollectionQueryKind::Options, root: handle, - generation, query: None, include_root: false, tag_name_html_document: None, @@ -582,12 +580,10 @@ pub(in crate::native_bridge) fn select_selected_options_getter_function<'s>( rv.set_null(); return; }; - let generation = unsafe { &*runtime_ptr }.runtime_reset_generation(); let descriptor = LiveCollectionDescriptor { collection_kind: CollectionKind::HtmlCollection, query_kind: LiveCollectionQueryKind::SelectedOptions, root: handle, - generation, query: None, include_root: false, tag_name_html_document: None, diff --git a/moli-renderer-v8/src/native_bridge/element/query.rs b/moli-renderer-v8/src/native_bridge/element/query.rs index 0ea840b484..e6a96c503b 100644 --- a/moli-renderer-v8/src/native_bridge/element/query.rs +++ b/moli-renderer-v8/src/native_bridge/element/query.rs @@ -5,15 +5,13 @@ use super::super::{ node_runtime_and_handle_from_args_or_detached, node_runtime_and_handle_from_object_or_detached, receiver_has_detached_state, require_element_method_receiver, require_parent_node_receiver, set_wrapped_node_or_null, - stale_node_runtime_and_handle_from_object, throw_incompatible_method_receiver, - throw_native_selector_error_for_selector, + throw_incompatible_method_receiver, throw_native_selector_error_for_selector, }, }; use super::forms::control_matches_validity_pseudo; use crate::{ util::{ - call_object_method, constructor_prototype, object_chain_contains, object_number_property, - object_property_as_object, v8_string, v8str, walk_object_chain, + call_object_method, object_number_property, object_property_as_object, v8_string, v8str, }, webidl, }; @@ -195,27 +193,6 @@ pub(in crate::native_bridge) fn node_matches_callback<'s>( super::super::document::detached_matches_method_callback(scope, args, rv); return; } - if stale_node_is_element_receiver(scope, args.this()) { - let Some(parsed) = webidl::parse_args::(scope, &args) else { - return; - }; - if let Some((runtime_ptr, _)) = - stale_node_runtime_and_handle_from_object(scope, args.this()) - { - match unsafe { &*runtime_ptr }.matches( - unsafe { &*runtime_ptr }.document_handle(), - &parsed.selectors, - ) { - Ok(_) => rv.set_bool(false), - Err(error) => { - throw_native_selector_error_for_selector(scope, &parsed.selectors, &error) - } - } - } else { - rv.set_bool(false); - } - return; - } let Ok((runtime_ptr, handle)) = node_runtime_and_handle_from_object_or_detached(scope, args.this()) else { @@ -256,23 +233,6 @@ pub(in crate::native_bridge) fn node_matches_callback<'s>( } } -fn stale_node_is_element_receiver<'s>( - scope: &mut v8::PinScope<'s, '_>, - receiver: v8::Local<'s, v8::Object>, -) -> bool { - if stale_node_runtime_and_handle_from_object(scope, receiver).is_none() { - return false; - } - let global = scope.get_current_context().global(scope); - let Some(element_prototype) = constructor_prototype(scope, global, "Element") else { - return false; - }; - object_chain_contains( - &walk_object_chain(scope, receiver, "__proto__"), - element_prototype, - ) -} - fn node_matches_needs_owner_document_query<'s>( scope: &mut v8::PinScope<'s, '_>, node: v8::Local<'s, v8::Object>, diff --git a/moli-renderer-v8/src/native_bridge/element/styles.rs b/moli-renderer-v8/src/native_bridge/element/styles.rs index b8398b7dc5..fca902de54 100644 --- a/moli-renderer-v8/src/native_bridge/element/styles.rs +++ b/moli-renderer-v8/src/native_bridge/element/styles.rs @@ -113,7 +113,7 @@ fn style_object_forces_empty_computed<'s>( return value.boolean_value(scope); } match bridge_handle { - BridgeHandle::ComputedStyle(handle, _, descriptor) => match descriptor.target { + BridgeHandle::ComputedStyle(handle, descriptor) => match descriptor.target { ComputedStyleTargetKey::ChildFrame(frame_handle) => { let runtime = unsafe { &*runtime_ptr }; let empty = !child_frame_target_document_is_current(runtime, handle, frame_handle) diff --git a/moli-renderer-v8/src/native_bridge/element/styles/declaration/identity.rs b/moli-renderer-v8/src/native_bridge/element/styles/declaration/identity.rs index 370666523e..6c9fc4da86 100644 --- a/moli-renderer-v8/src/native_bridge/element/styles/declaration/identity.rs +++ b/moli-renderer-v8/src/native_bridge/element/styles/declaration/identity.rs @@ -14,12 +14,12 @@ pub(in crate::native_bridge::element::styles) fn style_runtime_and_handle_from_o ) -> std::result::Result<(*mut JsContextHost, DomHandle, StyleMode), String> { let (runtime_ptr, handle) = bridge_handle_from_object(scope, object)?; match handle { - BridgeHandle::Style(handle, _) => Ok((runtime_ptr, handle, StyleMode::Inline)), - BridgeHandle::ComputedStyle(handle, _, _) => Ok((runtime_ptr, handle, StyleMode::Computed)), + BridgeHandle::Style(handle) => Ok((runtime_ptr, handle, StyleMode::Inline)), + BridgeHandle::ComputedStyle(handle, _) => Ok((runtime_ptr, handle, StyleMode::Computed)), BridgeHandle::Window - | BridgeHandle::Node(_, _) - | BridgeHandle::ClassList(_, _, _) - | BridgeHandle::Dataset(_, _) => { + | BridgeHandle::Node(_) + | BridgeHandle::ClassList(_, _) + | BridgeHandle::Dataset(_) => { Err("wrapper did not contain a CSSStyleDeclaration identity".to_owned()) } } diff --git a/moli-renderer-v8/src/native_bridge/identity.rs b/moli-renderer-v8/src/native_bridge/identity.rs index 4eafc658f9..86289d5100 100644 --- a/moli-renderer-v8/src/native_bridge/identity.rs +++ b/moli-renderer-v8/src/native_bridge/identity.rs @@ -15,45 +15,11 @@ use super::{JsContextHost, RuntimeObservableContextToken}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub(super) enum BridgeHandle { Window, - Node(DomHandle, u64), - ClassList(DomHandle, u64, DomTokenListKind), - Dataset(DomHandle, u64), - Style(DomHandle, u64), - ComputedStyle(DomHandle, u64, ComputedStyleDescriptor), -} - -impl BridgeHandle { - fn with_rebound_generation(&self, old_generation: u64, new_generation: u64) -> Option { - match self { - Self::Window => None, - Self::Node(handle, generation) if *generation == old_generation => { - Some(Self::Node(*handle, new_generation)) - } - Self::ClassList(handle, generation, kind) if *generation == old_generation => { - Some(Self::ClassList(*handle, new_generation, *kind)) - } - Self::Dataset(handle, generation) if *generation == old_generation => { - Some(Self::Dataset(*handle, new_generation)) - } - Self::Style(handle, generation) if *generation == old_generation => { - Some(Self::Style(*handle, new_generation)) - } - Self::ComputedStyle(handle, generation, descriptor) - if *generation == old_generation => - { - Some(Self::ComputedStyle( - *handle, - new_generation, - descriptor.clone(), - )) - } - Self::Node(_, _) - | Self::ClassList(_, _, _) - | Self::Dataset(_, _) - | Self::Style(_, _) - | Self::ComputedStyle(_, _, _) => None, - } - } + Node(DomHandle), + ClassList(DomHandle, DomTokenListKind), + Dataset(DomHandle), + Style(DomHandle), + ComputedStyle(DomHandle, ComputedStyleDescriptor), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -223,7 +189,6 @@ pub(super) struct LiveCollectionDescriptor { pub(super) collection_kind: CollectionKind, pub(super) query_kind: LiveCollectionQueryKind, pub(super) root: DomHandle, - pub(super) generation: u64, pub(super) query: Option, pub(super) include_root: bool, pub(super) tag_name_html_document: Option, @@ -237,7 +202,6 @@ pub(super) struct LiveCollectionResolutionCache( #[derive(Debug)] struct LiveCollectionResolutionCacheEntry { - runtime_generation: u64, query_version: u64, handles: Rc<[DomHandle]>, } @@ -247,7 +211,6 @@ impl PartialEq for LiveCollectionDescriptor { self.collection_kind == other.collection_kind && self.query_kind == other.query_kind && self.root == other.root - && self.generation == other.generation && self.query == other.query && self.include_root == other.include_root && self.tag_name_html_document == other.tag_name_html_document @@ -261,7 +224,6 @@ impl Hash for LiveCollectionDescriptor { self.collection_kind.hash(state); self.query_kind.hash(state); self.root.hash(state); - self.generation.hash(state); self.query.hash(state); self.include_root.hash(state); self.tag_name_html_document.hash(state); @@ -270,20 +232,13 @@ impl Hash for LiveCollectionDescriptor { impl LiveCollectionDescriptor { pub(super) fn resolve(&self, host: &JsContextHost) -> Rc<[DomHandle]> { - let runtime_generation = host.runtime_reset_generation(); - if self.generation != runtime_generation { - return Rc::from(Vec::::new()); - } let query_version = host.dom_host().query_version(); if let Some(handles) = self .resolution_cache .0 .borrow() .as_ref() - .filter(|entry| { - entry.runtime_generation == runtime_generation - && entry.query_version == query_version - }) + .filter(|entry| entry.query_version == query_version) .map(|entry| entry.handles.clone()) { return handles; @@ -333,7 +288,6 @@ impl LiveCollectionDescriptor { }; let handles = Rc::<[DomHandle]>::from(handles); *self.resolution_cache.0.borrow_mut() = Some(LiveCollectionResolutionCacheEntry { - runtime_generation, query_version, handles: handles.clone(), }); @@ -359,8 +313,15 @@ impl Default for LiveCollectionStore { impl LiveCollectionStore { fn register(&mut self, descriptor: LiveCollectionDescriptor) -> u32 { let collection_id = self.next_id; - self.next_id += 1; - self.descriptors.insert(collection_id, descriptor); + self.next_id = self + .next_id + .checked_add(1) + .expect("live collection id overflow"); + let replaced = self.descriptors.insert(collection_id, descriptor); + assert!( + replaced.is_none(), + "live collection ids must never be reused" + ); collection_id } @@ -387,8 +348,15 @@ impl Default for StaticHandleCollectionStore { impl StaticHandleCollectionStore { fn register(&mut self, handles: Vec) -> u32 { let collection_id = self.next_id; - self.next_id += 1; - self.handles.insert(collection_id, handles); + self.next_id = self + .next_id + .checked_add(1) + .expect("static handle collection id overflow"); + let replaced = self.handles.insert(collection_id, handles); + assert!( + replaced.is_none(), + "static handle collection ids must never be reused" + ); collection_id } @@ -553,15 +521,6 @@ impl BridgeIdentityStore { self.reflectors.key_for_id(reflector_id) } - pub(super) fn rebind_generation( - &mut self, - old_generation: u64, - new_generation: u64, - ) -> Option { - self.reflectors - .rekey_matching(|handle| handle.with_rebound_generation(old_generation, new_generation)) - } - pub(super) fn cached_wrapper<'s>( &self, scope: &mut v8::PinScope<'s, '_>, diff --git a/moli-renderer-v8/src/native_bridge/mod.rs b/moli-renderer-v8/src/native_bridge/mod.rs index 44a1cd79b0..880cb3f4ae 100644 --- a/moli-renderer-v8/src/native_bridge/mod.rs +++ b/moli-renderer-v8/src/native_bridge/mod.rs @@ -86,6 +86,6 @@ pub(crate) fn object_is_native_event_target_wrapper_or_detached<'s>( return true; } bridge_handle_from_object(scope, object) - .is_ok_and(|(_, handle)| matches!(handle, BridgeHandle::Node(_, _) | BridgeHandle::Window)) + .is_ok_and(|(_, handle)| matches!(handle, BridgeHandle::Node(_) | BridgeHandle::Window)) } pub(crate) use traversal::install_traversal_template_bindings; diff --git a/moli-renderer-v8/src/native_bridge/node.rs b/moli-renderer-v8/src/native_bridge/node.rs index 316b5b5e7e..b745cb9682 100644 --- a/moli-renderer-v8/src/native_bridge/node.rs +++ b/moli-renderer-v8/src/native_bridge/node.rs @@ -1236,29 +1236,17 @@ pub(crate) fn node_runtime_and_handle_from_object( ) -> std::result::Result<(*mut JsContextHost, DomHandle), String> { let (runtime_ptr, handle) = super::bridge_handle_from_object(scope, object)?; match handle { - super::BridgeHandle::Node(handle, _) => Ok((runtime_ptr, handle)), + super::BridgeHandle::Node(handle) => Ok((runtime_ptr, handle)), super::BridgeHandle::Window - | super::BridgeHandle::ClassList(_, _, _) - | super::BridgeHandle::Dataset(_, _) - | super::BridgeHandle::Style(_, _) - | super::BridgeHandle::ComputedStyle(_, _, _) => { + | super::BridgeHandle::ClassList(_, _) + | super::BridgeHandle::Dataset(_) + | super::BridgeHandle::Style(_) + | super::BridgeHandle::ComputedStyle(_, _) => { Err("wrapper did not contain a node identity".to_owned()) } } } -pub(crate) fn stale_node_runtime_and_handle_from_object( - scope: &mut v8::PinScope<'_, '_>, - object: v8::Local<'_, v8::Object>, -) -> Option<(*mut JsContextHost, DomHandle)> { - let (runtime_ptr, handle) = super::bridge_handle_from_object(scope, object).ok()?; - let super::BridgeHandle::Node(handle, generation) = handle else { - return None; - }; - (generation != unsafe { &*runtime_ptr }.runtime_reset_generation()) - .then_some((runtime_ptr, handle)) -} - pub(crate) fn object_is_node_wrapper_or_detached<'s>( scope: &mut v8::PinScope<'s, '_>, object: v8::Local<'s, v8::Object>, diff --git a/moli-renderer-v8/src/reflector.rs b/moli-renderer-v8/src/reflector.rs index de8730b7d1..418d0dd3f3 100644 --- a/moli-renderer-v8/src/reflector.rs +++ b/moli-renderer-v8/src/reflector.rs @@ -1,7 +1,4 @@ -use std::{ - collections::{HashMap, HashSet}, - hash::Hash, -}; +use std::{collections::HashMap, hash::Hash}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ReflectorId(u64); @@ -82,7 +79,7 @@ where return Reflector { id: existing, key }; } - self.next_id += 1; + self.next_id = self.next_id.checked_add(1).expect("reflector id overflow"); let id = ReflectorId(self.next_id); self.ids_by_key.insert(key.clone(), id); self.keys_by_id.insert(id, key.clone()); @@ -106,45 +103,6 @@ where self.keys_by_id.get(&id).cloned() } - pub fn rekey(&mut self, old_key: K, new_key: K) -> Option { - if old_key == new_key { - return self.ids_by_key.get(&old_key).copied(); - } - if self.ids_by_key.contains_key(&new_key) { - return None; - } - - let id = self.ids_by_key.remove(&old_key)?; - self.ids_by_key.insert(new_key.clone(), id); - self.keys_by_id.insert(id, new_key); - Some(id) - } - - pub fn rekey_matching( - &mut self, - mut replacement: impl FnMut(&K) -> Option, - ) -> Option { - let replacements = self - .ids_by_key - .keys() - .filter_map(|old_key| replacement(old_key).map(|new_key| (old_key.clone(), new_key))) - .collect::>(); - let mut destinations = HashSet::with_capacity(replacements.len()); - if replacements - .iter() - .any(|(_, new_key)| !destinations.insert(new_key.clone())) - || replacements.iter().any(|(old_key, new_key)| { - old_key != new_key && self.ids_by_key.contains_key(new_key) - }) - { - return None; - } - for (old_key, new_key) in &replacements { - self.rekey(old_key.clone(), new_key.clone())?; - } - Some(replacements.len()) - } - pub fn len(&self) -> usize { self.ids_by_key.len() } @@ -204,54 +162,4 @@ mod tests { assert_eq!(registry.len(), 2); assert!(!registry.is_empty()); } - - #[test] - fn reflector_registry_rekeys_an_existing_identity_without_changing_its_id() { - let mut registry = ReflectorRegistry::default(); - let reflector = registry.intern(7_u32); - - assert_eq!(registry.rekey(7, 9), Some(reflector.id())); - assert_eq!(registry.existing(7), None); - assert_eq!( - registry.existing(9).map(|entry| entry.id()), - Some(reflector.id()) - ); - assert_eq!(registry.key_for_id(reflector.id()), Some(9)); - assert_eq!(registry.len(), 1); - } - - #[test] - fn reflector_registry_does_not_rekey_over_an_existing_identity() { - let mut registry = ReflectorRegistry::default(); - let first = registry.intern(7_u32); - let second = registry.intern(9_u32); - - assert_eq!(registry.rekey(7, 9), None); - assert_eq!(registry.existing(7), Some(first)); - assert_eq!(registry.existing(9), Some(second)); - } - - #[test] - fn reflector_registry_rekeys_a_matching_key_set_atomically() { - let mut registry = ReflectorRegistry::default(); - let first = registry.intern((7_u32, 1_u32)); - let second = registry.intern((9_u32, 1_u32)); - let unchanged = registry.intern((11_u32, 2_u32)); - - assert_eq!( - registry.rekey_matching(|(value, generation)| { - (*generation == 1).then_some((*value, 3)) - }), - Some(2) - ); - assert_eq!( - registry.existing((7, 3)).map(|entry| entry.id()), - Some(first.id()) - ); - assert_eq!( - registry.existing((9, 3)).map(|entry| entry.id()), - Some(second.id()) - ); - assert_eq!(registry.existing((11, 2)), Some(unchanged)); - } } diff --git a/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs b/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs index f02506c65c..e4049ff650 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs @@ -5384,7 +5384,10 @@ fn document_open_preserves_document_identity_and_detaches_the_replaced_tree() { const oldBody = document.body; const oldText = oldNode.firstChild; const oldClassList = oldNode.classList; + const oldDataset = oldNode.dataset; const oldStyle = oldNode.style; + const oldDocumentMains = document.getElementsByTagName("main"); + const oldBodyChildren = oldBody.children; const oldShadowHost = document.createElement("section"); oldBody.append(oldShadowHost); const oldShadow = oldShadowHost.attachShadow({ mode: "open" }); @@ -5423,7 +5426,17 @@ fn document_open_preserves_document_identity_and_detaches_the_replaced_tree() { oldNodeParentPreserved: oldNode.parentNode === oldBody, oldTextIdentityPreserved: oldNode.firstChild === oldText, oldClassListIdentityPreserved: oldNode.classList === oldClassList, + oldDatasetIdentityPreserved: oldNode.dataset === oldDataset, oldStyleIdentityPreserved: oldNode.style === oldStyle, + documentCollectionIdentityPreserved: + document.getElementsByTagName("main") === oldDocumentMains, + documentCollectionTracksReplacement: + Array.from(oldDocumentMains, node => node.id).join(","), + detachedCollectionIdentityPreserved: + oldBody.children === oldBodyChildren, + detachedCollectionKeepsOldTree: + Array.from(oldBodyChildren, node => node.id || node.localName).join(","), + oldNodeStillMatches: oldNode.matches('#old'), oldBodyConnected: oldBody.isConnected, oldShadowIdentityPreserved: oldShadowHost.shadowRoot === oldShadow, oldShadowChildIdentityPreserved: oldShadow.firstChild === oldShadowChild, @@ -5440,7 +5453,7 @@ fn document_open_preserves_document_identity_and_detaches_the_replaced_tree() { assert_eq!( result, - r#"{"sameDocument":true,"oldNodeConnected":false,"oldNodeText":"old text","oldNodeOwnerPreserved":true,"oldNodeParentPreserved":true,"oldTextIdentityPreserved":true,"oldClassListIdentityPreserved":true,"oldStyleIdentityPreserved":true,"oldBodyConnected":false,"oldShadowIdentityPreserved":true,"oldShadowChildIdentityPreserved":true,"oldShadowText":"shadow text","oldShadowConnected":false,"listenerRuns":{"node":0,"document":0,"window":0,"handler":0,"preDetachedNode":1,"preDetachedHandler":1},"oldLookupMissing":true,"newText":"new text"}"# + r#"{"sameDocument":true,"oldNodeConnected":false,"oldNodeText":"old text","oldNodeOwnerPreserved":true,"oldNodeParentPreserved":true,"oldTextIdentityPreserved":true,"oldClassListIdentityPreserved":true,"oldDatasetIdentityPreserved":true,"oldStyleIdentityPreserved":true,"documentCollectionIdentityPreserved":true,"documentCollectionTracksReplacement":"new","detachedCollectionIdentityPreserved":true,"detachedCollectionKeepsOldTree":"old,section","oldNodeStillMatches":true,"oldBodyConnected":false,"oldShadowIdentityPreserved":true,"oldShadowChildIdentityPreserved":true,"oldShadowText":"shadow text","oldShadowConnected":false,"listenerRuns":{"node":0,"document":0,"window":0,"handler":0,"preDetachedNode":1,"preDetachedHandler":1},"oldLookupMissing":true,"newText":"new text"}"# ); }