mirror of
https://github.com/lexmount/moli.git
synced 2026-11-13 08:08:10 +00:00
fix(dom): clear document handlers without invoking author setters
This commit is contained in:
@@ -217,7 +217,7 @@ impl JsContextHost {
|
||||
ChildDocumentCommitResult::from_install(install)
|
||||
} else {
|
||||
self.disconnect_shared_worker_clients_for_child_context(handle);
|
||||
self.clear_child_window_document_event_state(scope, handle);
|
||||
self.clear_child_window_event_listeners(handle);
|
||||
self.replace_child_custom_elements_registry_for_document_commit(scope, handle);
|
||||
self.clear_child_browsing_context_current_document(handle);
|
||||
ChildDocumentCommitResult::ready(None)
|
||||
|
||||
@@ -355,7 +355,7 @@ impl JsContextHost {
|
||||
FrameLocalWindowOwnerTransition::Replaced { .. } => {
|
||||
self.disconnect_shared_worker_clients_for_child_context(handle);
|
||||
if !preserve_window_event_state {
|
||||
self.clear_child_window_document_event_state(scope, handle);
|
||||
self.clear_child_window_event_listeners(handle);
|
||||
}
|
||||
self.replace_child_custom_elements_registry_for_document_commit(scope, handle);
|
||||
}
|
||||
|
||||
@@ -779,7 +779,7 @@ impl JsContextHost {
|
||||
if replaces_existing_document {
|
||||
self.disconnect_shared_worker_clients_for_child_context(handle);
|
||||
}
|
||||
self.clear_child_window_document_event_state(scope, handle);
|
||||
self.clear_child_window_event_listeners(handle);
|
||||
self.replace_child_custom_elements_registry_for_document_commit(scope, handle);
|
||||
self.clear_child_browsing_context_current_document(handle);
|
||||
self.clear_pending_service_worker_child_client(handle);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{JsContextHost, child_frame_runtime::WINDOW_EVENT_HANDLER_PROPERTIES};
|
||||
use super::JsContextHost;
|
||||
use crate::{
|
||||
context_bootstrap::{
|
||||
EVENT_DISPATCHING_SLOT, EVENT_STOP_IMMEDIATE_PROPAGATION_SLOT, EVENT_STOP_PROPAGATION_SLOT,
|
||||
@@ -81,20 +81,6 @@ impl JsContextHost {
|
||||
ChildWindowEventRegistrationId(self.next_child_window_event_registration_id)
|
||||
}
|
||||
|
||||
pub(in crate::native_bridge::context_host) fn clear_child_window_document_event_state(
|
||||
&mut self,
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
handle: DomHandle,
|
||||
) {
|
||||
if let Some(window) = self.child_window_proxy_records.live_window(scope, handle) {
|
||||
let null = v8::null(scope).into();
|
||||
for name in WINDOW_EVENT_HANDLER_PROPERTIES {
|
||||
let _ = window.set(scope, v8str(scope, name).into(), null);
|
||||
}
|
||||
}
|
||||
self.clear_child_window_event_listeners(handle);
|
||||
}
|
||||
|
||||
pub(crate) fn child_window_event_listener_callback_ids(
|
||||
&self,
|
||||
handle: DomHandle,
|
||||
|
||||
@@ -676,7 +676,7 @@ impl JsContextHost {
|
||||
),
|
||||
);
|
||||
|
||||
host.clear_child_window_document_event_state(scope, child_handle);
|
||||
host.clear_child_window_event_listeners(child_handle);
|
||||
host.clear_event_callbacks_for_document_replacement(document_handle, false);
|
||||
for child in children {
|
||||
let _ = remove_child_to_current_reaction_queue(
|
||||
|
||||
@@ -2,6 +2,7 @@ use super::*;
|
||||
|
||||
mod child_window;
|
||||
mod compilation;
|
||||
mod document_replacement;
|
||||
mod object_values;
|
||||
mod parser_merged_body;
|
||||
mod popup;
|
||||
|
||||
+28
-7
@@ -13,18 +13,31 @@
|
||||
before[key] === after[key]);
|
||||
}
|
||||
function withWindow(owner, run) {
|
||||
if (owner !== 'root') throw new Error('unexpected document owner');
|
||||
// Finish a replacement stream first so write() starts a destructive stream.
|
||||
document.open();
|
||||
document.close();
|
||||
return run(window);
|
||||
let frame;
|
||||
let target;
|
||||
if (owner === 'root') target = window;
|
||||
else if (owner === 'popup') target = open();
|
||||
else {
|
||||
frame = document.createElement('iframe');
|
||||
document.body.appendChild(frame);
|
||||
target = frame.contentWindow;
|
||||
}
|
||||
try {
|
||||
// Finish a replacement stream first so the write case is destructive.
|
||||
target.document.open();
|
||||
target.document.close();
|
||||
return run(target);
|
||||
} finally {
|
||||
if (frame) frame.remove();
|
||||
if (owner === 'popup') target.close();
|
||||
}
|
||||
}
|
||||
function replace(target, operation) {
|
||||
if (operation === 'open') target.document.open();
|
||||
else target.document.write('<!doctype html><body>replacement');
|
||||
target.document.close();
|
||||
}
|
||||
for (const owner of ['root']) {
|
||||
for (const owner of ['child', 'popup', 'root']) {
|
||||
for (const operation of ['open', 'write']) {
|
||||
for (const mode of ['native', 'deleted', 'replaced', 'throwing-setter', 'read-only']) {
|
||||
check(`${owner}:${operation}:${mode}`, () => withWindow(owner, target => {
|
||||
@@ -51,7 +64,15 @@
|
||||
} finally { Object.defineProperty(target, 'onresize', native); }
|
||||
}));
|
||||
}
|
||||
|
||||
check(`${owner}:${operation}:pending-content-cleared`, () => withWindow(owner, target => {
|
||||
target.document.body.setAttribute('onresize', '}');
|
||||
replace(target, operation);
|
||||
let errors = 0;
|
||||
try {
|
||||
target.onerror = () => { ++errors; return true; };
|
||||
return target.onresize === null && errors === 0;
|
||||
} finally { target.onerror = null; }
|
||||
}));
|
||||
}
|
||||
}
|
||||
const failures = rows.filter(row => !row.pass);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn root_document_replacement_clears_native_handlers_without_changing_public_descriptors() {
|
||||
fn document_replacement_clears_native_handlers_without_changing_public_descriptors() {
|
||||
let mut vm = new_storage_html_test_vm("https://document-handler-cleanup.test/");
|
||||
vm.eval(include_str!("document_replacement.js")).unwrap();
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user