beforeunload and unload infrastructure

This commit is contained in:
Gregory Terzian 2018-03-18 13:20:24 +08:00
parent a1d1b18710
commit 427eaed535
28 changed files with 267 additions and 60 deletions

View file

@ -48,6 +48,7 @@ none
number number
onchange onchange
open open
pagehide
pageshow pageshow
password password
pause pause
@ -77,6 +78,7 @@ time
timeupdate timeupdate
toggle toggle
transitionend transitionend
unload
url url
waiting waiting
webglcontextcreationerror webglcontextcreationerror

View file

@ -1033,6 +1033,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::PipelineExited => { FromScriptMsg::PipelineExited => {
self.handle_pipeline_exited(source_pipeline_id); self.handle_pipeline_exited(source_pipeline_id);
} }
FromScriptMsg::DiscardDocument => {
self.handle_discard_document(source_top_ctx_id, source_pipeline_id);
}
FromScriptMsg::InitiateNavigateRequest(req_init, cancel_chan) => { FromScriptMsg::InitiateNavigateRequest(req_init, cancel_chan) => {
debug!("constellation got initiate navigate request message"); debug!("constellation got initiate navigate request message");
self.handle_navigate_request(source_pipeline_id, req_init, cancel_chan); self.handle_navigate_request(source_pipeline_id, req_init, cancel_chan);
@ -2547,6 +2550,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.notify_history_changed(change.top_level_browsing_context_id); self.notify_history_changed(change.top_level_browsing_context_id);
}, },
Some(old_pipeline_id) => { Some(old_pipeline_id) => {
// https://html.spec.whatwg.org/multipage/#unload-a-document
self.unload_document(old_pipeline_id);
// Deactivate the old pipeline, and activate the new one. // Deactivate the old pipeline, and activate the new one.
let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) = change.replace { let (pipelines_to_close, states_to_close) = if let Some(replace_reloader) = change.replace {
let session_history = self.joint_session_histories let session_history = self.joint_session_histories
@ -2997,6 +3002,28 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
debug!("Closed browsing context children {}.", browsing_context_id); debug!("Closed browsing context children {}.", browsing_context_id);
} }
// Discard the pipeline for a given document, udpdate the joint session history.
fn handle_discard_document(&mut self,
top_level_browsing_context_id: TopLevelBrowsingContextId,
pipeline_id: PipelineId) {
let load_data = match self.pipelines.get(&pipeline_id) {
Some(pipeline) => pipeline.load_data.clone(),
None => return
};
self.joint_session_histories
.entry(top_level_browsing_context_id).or_insert(JointSessionHistory::new())
.replace_reloader(NeedsToReload::No(pipeline_id), NeedsToReload::Yes(pipeline_id, load_data));
self.close_pipeline(pipeline_id, DiscardBrowsingContext::No, ExitPipelineMode::Normal);
}
// Send a message to script requesting the document associated with this pipeline runs the 'unload' algorithm.
fn unload_document(&self, pipeline_id: PipelineId) {
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
let msg = ConstellationControlMsg::UnloadDocument(pipeline_id);
let _ = pipeline.event_loop.send(msg);
}
}
// Close all pipelines at and beneath a given browsing context // Close all pipelines at and beneath a given browsing context
fn close_pipeline(&mut self, pipeline_id: PipelineId, dbc: DiscardBrowsingContext, exit_mode: ExitPipelineMode) { fn close_pipeline(&mut self, pipeline_id: PipelineId, dbc: DiscardBrowsingContext, exit_mode: ExitPipelineMode) {
debug!("Closing pipeline {:?}.", pipeline_id); debug!("Closing pipeline {:?}.", pipeline_id);

View file

@ -63,7 +63,8 @@ use dom::keyboardevent::KeyboardEvent;
use dom::location::Location; use dom::location::Location;
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
use dom::mouseevent::MouseEvent; use dom::mouseevent::MouseEvent;
use dom::node::{self, CloneChildrenFlag, Node, NodeDamage, window_from_node, NodeFlags, LayoutNodeHelpers}; use dom::node::{self, CloneChildrenFlag, document_from_node, window_from_node};
use dom::node::{Node, NodeDamage, NodeFlags, LayoutNodeHelpers};
use dom::node::VecPreOrderInsertionHelper; use dom::node::VecPreOrderInsertionHelper;
use dom::nodeiterator::NodeIterator; use dom::nodeiterator::NodeIterator;
use dom::nodelist::NodeList; use dom::nodelist::NodeList;
@ -348,6 +349,8 @@ pub struct Document {
last_click_info: DomRefCell<Option<(Instant, Point2D<f32>)>>, last_click_info: DomRefCell<Option<(Instant, Point2D<f32>)>>,
/// <https://html.spec.whatwg.org/multipage/#ignore-destructive-writes-counter> /// <https://html.spec.whatwg.org/multipage/#ignore-destructive-writes-counter>
ignore_destructive_writes_counter: Cell<u32>, ignore_destructive_writes_counter: Cell<u32>,
/// <https://html.spec.whatwg.org/multipage/#ignore-opens-during-unload-counter>
ignore_opens_during_unload_counter: Cell<u32>,
/// The number of spurious `requestAnimationFrame()` requests we've received. /// The number of spurious `requestAnimationFrame()` requests we've received.
/// ///
/// A rAF request is considered spurious if nothing was actually reflowed. /// A rAF request is considered spurious if nothing was actually reflowed.
@ -375,6 +378,10 @@ pub struct Document {
throw_on_dynamic_markup_insertion_counter: Cell<u64>, throw_on_dynamic_markup_insertion_counter: Cell<u64>,
/// https://html.spec.whatwg.org/multipage/#page-showing /// https://html.spec.whatwg.org/multipage/#page-showing
page_showing: Cell<bool>, page_showing: Cell<bool>,
/// Whether the document is salvageable.
salvageable: Cell<bool>,
/// Whether the unload event has already been fired.
fired_unload: Cell<bool>,
} }
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
@ -483,18 +490,21 @@ impl Document {
self.dirty_all_nodes(); self.dirty_all_nodes();
self.window().reflow(ReflowGoal::Full, ReflowReason::CachedPageNeededReflow); self.window().reflow(ReflowGoal::Full, ReflowReason::CachedPageNeededReflow);
self.window().resume(); self.window().resume();
// html.spec.whatwg.org/multipage/browsing-the-web.html#history-traversal // html.spec.whatwg.org/multipage/#history-traversal
// Step 6 // Step 4.6
if self.ready_state.get() == DocumentReadyState::Complete { if self.ready_state.get() == DocumentReadyState::Complete {
let document = Trusted::new(self); let document = Trusted::new(self);
self.window.dom_manipulation_task_source().queue( self.window.dom_manipulation_task_source().queue(
task!(fire_pageshow_event: move || { task!(fire_pageshow_event: move || {
let document = document.root(); let document = document.root();
let window = document.window(); let window = document.window();
if document.page_showing.get() || !window.is_alive() { // Step 4.6.1
if document.page_showing.get() {
return; return;
} }
// Step 4.6.2
document.page_showing.set(true); document.page_showing.set(true);
// Step 4.6.4
let event = PageTransitionEvent::new( let event = PageTransitionEvent::new(
window, window,
atom!("pageshow"), atom!("pageshow"),
@ -1623,6 +1633,112 @@ impl Document {
ScriptThread::mark_document_with_no_blocked_loads(self); ScriptThread::mark_document_with_no_blocked_loads(self);
} }
// https://html.spec.whatwg.org/multipage/#prompt-to-unload-a-document
pub fn prompt_to_unload(&self, recursive_flag: bool) -> bool {
// TODO: Step 1, increase the event loop's termination nesting level by 1.
// Step 2
self.incr_ignore_opens_during_unload_counter();
//Step 3-5.
let document = Trusted::new(self);
let beforeunload_event = BeforeUnloadEvent::new(&self.window,
atom!("beforeunload"),
EventBubbles::Bubbles,
EventCancelable::Cancelable);
let event = beforeunload_event.upcast::<Event>();
event.set_trusted(true);
self.window.upcast::<EventTarget>().dispatch_event_with_target(
document.root().upcast(),
&event,
);
// TODO: Step 6, decrease the event loop's termination nesting level by 1.
// Step 7
if event.get_cancel_state() != EventDefault::Allowed {
self.salvageable.set(false);
}
let mut can_unload = true;
// TODO: Step 8 send a message to embedder to prompt user.
// Step 9
if !recursive_flag {
for iframe in self.iter_iframes() {
// TODO: handle the case of cross origin iframes.
let document = document_from_node(&*iframe);
if !document.prompt_to_unload(true) {
self.salvageable.set(document.salvageable());
can_unload = false;
break;
}
}
}
// Step 10
self.decr_ignore_opens_during_unload_counter();
can_unload
}
// https://html.spec.whatwg.org/multipage/#unload-a-document
pub fn unload(&self, recursive_flag: bool, recycle: bool) {
// TODO: Step 1, increase the event loop's termination nesting level by 1.
// Step 2
self.incr_ignore_opens_during_unload_counter();
let document = Trusted::new(self);
// Step 3-6
if self.page_showing.get() {
self.page_showing.set(false);
let event = PageTransitionEvent::new(
&self.window,
atom!("pagehide"),
false, // bubbles
false, // cancelable
self.salvageable.get(), // persisted
);
let event = event.upcast::<Event>();
event.set_trusted(true);
let _ = self.window.upcast::<EventTarget>().dispatch_event_with_target(
document.root().upcast(),
&event,
);
// TODO Step 6, document visibility steps.
}
let mut event_handled = false;
// Step 7
if !self.fired_unload.get() {
let event = Event::new(
&self.window.upcast(),
atom!("unload"),
EventBubbles::Bubbles,
EventCancelable::Cancelable,
);
event.set_trusted(true);
let _ = self.window.upcast::<EventTarget>().dispatch_event_with_target(
document.root().upcast(),
&event,
);
self.fired_unload.set(true);
event_handled = event.get_cancel_state() != EventDefault::Allowed;
}
// TODO: Step 8, decrease the event loop's termination nesting level by 1.
// Step 9
self.salvageable.set(!event_handled);
// Step 13
if !recursive_flag {
for iframe in self.iter_iframes() {
// TODO: handle the case of cross origin iframes.
let document = document_from_node(&*iframe);
document.unload(true, recycle);
if !document.salvageable() {
self.salvageable.set(false);
}
}
}
// Step 10, 14
if !self.salvageable.get() {
// https://html.spec.whatwg.org/multipage/#unloading-document-cleanup-steps
let msg = ScriptMsg::DiscardDocument;
let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg);
}
// Step 15, End
self.decr_ignore_opens_during_unload_counter();
}
// https://html.spec.whatwg.org/multipage/#the-end // https://html.spec.whatwg.org/multipage/#the-end
pub fn maybe_queue_document_completion(&self) { pub fn maybe_queue_document_completion(&self) {
if self.loader.borrow().is_blocked() { if self.loader.borrow().is_blocked() {
@ -2297,6 +2413,7 @@ impl Document {
target_element: MutNullableDom::new(None), target_element: MutNullableDom::new(None),
last_click_info: DomRefCell::new(None), last_click_info: DomRefCell::new(None),
ignore_destructive_writes_counter: Default::default(), ignore_destructive_writes_counter: Default::default(),
ignore_opens_during_unload_counter: Default::default(),
spurious_animation_frames: Cell::new(0), spurious_animation_frames: Cell::new(0),
dom_count: Cell::new(1), dom_count: Cell::new(1),
fullscreen_element: MutNullableDom::new(None), fullscreen_element: MutNullableDom::new(None),
@ -2306,6 +2423,8 @@ impl Document {
canceller: canceller, canceller: canceller,
throw_on_dynamic_markup_insertion_counter: Cell::new(0), throw_on_dynamic_markup_insertion_counter: Cell::new(0),
page_showing: Cell::new(false), page_showing: Cell::new(false),
salvageable: Cell::new(true),
fired_unload: Cell::new(false)
} }
} }
@ -2485,6 +2604,10 @@ impl Document {
self.stylesheets.borrow().len() self.stylesheets.borrow().len()
} }
pub fn salvageable(&self) -> bool {
self.salvageable.get()
}
pub fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> { pub fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> {
let stylesheets = self.stylesheets.borrow(); let stylesheets = self.stylesheets.borrow();
@ -2608,6 +2731,20 @@ impl Document {
self.ignore_destructive_writes_counter.get() - 1); self.ignore_destructive_writes_counter.get() - 1);
} }
pub fn is_prompting_or_unloading(&self) -> bool {
self.ignore_opens_during_unload_counter.get() > 0
}
fn incr_ignore_opens_during_unload_counter(&self) {
self.ignore_opens_during_unload_counter.set(
self.ignore_opens_during_unload_counter.get() + 1);
}
fn decr_ignore_opens_during_unload_counter(&self) {
self.ignore_opens_during_unload_counter.set(
self.ignore_opens_during_unload_counter.get() - 1);
}
/// Whether we've seen so many spurious animation frames (i.e. animation frames that didn't /// Whether we've seen so many spurious animation frames (i.e. animation frames that didn't
/// mutate the DOM) that we've decided to fall back to fake ones. /// mutate the DOM) that we've decided to fall back to fake ones.
fn is_faking_animation_frames(&self) -> bool { fn is_faking_animation_frames(&self) -> bool {

View file

@ -482,7 +482,14 @@ fn invoke(window: Option<&Window>,
event.current_target.set(Some(object)); event.current_target.set(Some(object));
// Step 5. // Step 5.
inner_invoke(window, object, event, &listeners); if inner_invoke(window, object, event, &listeners) {
// <https://html.spec.whatwg.org/multipage/#unload-a-document>
// Step 9.
// Required to establish the 'salvageable' state of document as part of unloading.
if event.canceled.get() != EventDefault::Prevented {
event.mark_as_handled();
}
}
// TODO: step 6. // TODO: step 6.
} }

View file

@ -187,22 +187,21 @@ impl CompiledEventListener {
CommonEventHandler::BeforeUnloadEventHandler(ref handler) => { CommonEventHandler::BeforeUnloadEventHandler(ref handler) => {
if let Some(event) = event.downcast::<BeforeUnloadEvent>() { if let Some(event) = event.downcast::<BeforeUnloadEvent>() {
let rv = event.ReturnValue(); // Step 5
if let Ok(value) = handler.Call_(object, if let Ok(value) = handler.Call_(object,
event.upcast::<Event>(), event.upcast::<Event>(),
exception_handle) { exception_handle) {
match value { let rv = event.ReturnValue();
Some(value) => { if let Some(v) = value {
if rv.is_empty() { if rv.is_empty() {
event.SetReturnValue(value); event.SetReturnValue(v);
} }
}
None => {
event.upcast::<Event>().PreventDefault(); event.upcast::<Event>().PreventDefault();
} }
} }
} } else {
// Step 5, "Otherwise" clause
let _ = handler.Call_(object, event.upcast::<Event>(), exception_handle);
} }
} }

View file

@ -1550,7 +1550,7 @@ impl Window {
// https://html.spec.whatwg.org/multipage/#navigating-across-documents // https://html.spec.whatwg.org/multipage/#navigating-across-documents
if !force_reload && url.as_url()[..Position::AfterQuery] == if !force_reload && url.as_url()[..Position::AfterQuery] ==
doc.url().as_url()[..Position::AfterQuery] { doc.url().as_url()[..Position::AfterQuery] {
// Step 5 // Step 6
if let Some(fragment) = url.fragment() { if let Some(fragment) = url.fragment() {
doc.check_and_scroll_fragment(fragment); doc.check_and_scroll_fragment(fragment);
doc.set_url(url.clone()); doc.set_url(url.clone());
@ -1559,9 +1559,24 @@ impl Window {
} }
let pipeline_id = self.upcast::<GlobalScope>().pipeline_id(); let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
// Step 4
let window_proxy = self.window_proxy();
if let Some(active) = window_proxy.currently_active() {
if pipeline_id == active {
if doc.is_prompting_or_unloading() {
return;
}
}
}
// Step 7
if doc.prompt_to_unload(false) {
self.main_thread_script_chan().send( self.main_thread_script_chan().send(
MainThreadScriptMsg::Navigate(pipeline_id, MainThreadScriptMsg::Navigate(pipeline_id,
LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), replace)).unwrap(); LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), replace)).unwrap();
};
} }
pub fn handle_fire_timer(&self, timer_id: TimerEventId) { pub fn handle_fire_timer(&self, timer_id: TimerEventId) {

View file

@ -1157,6 +1157,7 @@ impl ScriptThread {
AttachLayout(ref new_layout_info) => Some(new_layout_info.new_pipeline_id), AttachLayout(ref new_layout_info) => Some(new_layout_info.new_pipeline_id),
Resize(id, ..) => Some(id), Resize(id, ..) => Some(id),
ResizeInactive(id, ..) => Some(id), ResizeInactive(id, ..) => Some(id),
UnloadDocument(id) => Some(id),
ExitPipeline(id, ..) => Some(id), ExitPipeline(id, ..) => Some(id),
ExitScriptThread => None, ExitScriptThread => None,
SendEvent(id, ..) => Some(id), SendEvent(id, ..) => Some(id),
@ -1275,6 +1276,8 @@ impl ScriptThread {
}, },
ConstellationControlMsg::Navigate(parent_pipeline_id, browsing_context_id, load_data, replace) => ConstellationControlMsg::Navigate(parent_pipeline_id, browsing_context_id, load_data, replace) =>
self.handle_navigate(parent_pipeline_id, Some(browsing_context_id), load_data, replace), self.handle_navigate(parent_pipeline_id, Some(browsing_context_id), load_data, replace),
ConstellationControlMsg::UnloadDocument(pipeline_id) =>
self.handle_unload_document(pipeline_id),
ConstellationControlMsg::SendEvent(id, event) => ConstellationControlMsg::SendEvent(id, event) =>
self.handle_event(id, event), self.handle_event(id, event),
ConstellationControlMsg::ResizeInactive(id, new_size) => ConstellationControlMsg::ResizeInactive(id, new_size) =>
@ -1668,6 +1671,13 @@ impl ScriptThread {
} }
} }
fn handle_unload_document(&self, pipeline_id: PipelineId) {
let document = self.documents.borrow().find_document(pipeline_id);
if let Some(document) = document {
document.unload(false, false);
}
}
fn handle_update_pipeline_id(&self, fn handle_update_pipeline_id(&self,
parent_pipeline_id: PipelineId, parent_pipeline_id: PipelineId,
browsing_context_id: BrowsingContextId, browsing_context_id: BrowsingContextId,

View file

@ -241,7 +241,7 @@ impl OneshotTimers {
} }
pub fn resume(&self) { pub fn resume(&self) {
// Suspend is idempotent: do nothing if the timers are already suspended. // Resume is idempotent: do nothing if the timers are already resumed.
let additional_offset = match self.suspended_since.get() { let additional_offset = match self.suspended_since.get() {
Some(suspended_since) => precise_time_ms() - suspended_since, Some(suspended_since) => precise_time_ms() - suspended_since,
None => return warn!("Resuming an already resumed timer."), None => return warn!("Resuming an already resumed timer."),

View file

@ -262,6 +262,8 @@ pub enum ConstellationControlMsg {
Resize(PipelineId, WindowSizeData, WindowSizeType), Resize(PipelineId, WindowSizeData, WindowSizeType),
/// Notifies script that window has been resized but to not take immediate action. /// Notifies script that window has been resized but to not take immediate action.
ResizeInactive(PipelineId, WindowSizeData), ResizeInactive(PipelineId, WindowSizeData),
/// Notifies the script that the document associated with this pipeline should 'unload'.
UnloadDocument(PipelineId),
/// Notifies the script that a pipeline should be closed. /// Notifies the script that a pipeline should be closed.
ExitPipeline(PipelineId, DiscardBrowsingContext), ExitPipeline(PipelineId, DiscardBrowsingContext),
/// Notifies the script that the whole thread should be closed. /// Notifies the script that the whole thread should be closed.
@ -335,6 +337,7 @@ impl fmt::Debug for ConstellationControlMsg {
AttachLayout(..) => "AttachLayout", AttachLayout(..) => "AttachLayout",
Resize(..) => "Resize", Resize(..) => "Resize",
ResizeInactive(..) => "ResizeInactive", ResizeInactive(..) => "ResizeInactive",
UnloadDocument(..) => "UnloadDocument",
ExitPipeline(..) => "ExitPipeline", ExitPipeline(..) => "ExitPipeline",
ExitScriptThread => "ExitScriptThread", ExitScriptThread => "ExitScriptThread",
SendEvent(..) => "SendEvent", SendEvent(..) => "SendEvent",

View file

@ -148,6 +148,8 @@ pub enum ScriptMsg {
TouchEventProcessed(EventResult), TouchEventProcessed(EventResult),
/// A log entry, with the top-level browsing context id and thread name /// A log entry, with the top-level browsing context id and thread name
LogEntry(Option<String>, LogEntry), LogEntry(Option<String>, LogEntry),
/// Discard the document.
DiscardDocument,
/// Notifies the constellation that this pipeline has exited. /// Notifies the constellation that this pipeline has exited.
PipelineExited, PipelineExited,
/// Send messages from postMessage calls from serviceworker /// Send messages from postMessage calls from serviceworker

View file

@ -1,10 +1,7 @@
[url-in-tags-revoke.window.html] [url-in-tags-revoke.window.html]
expected: TIMEOUT
[Fetching a blob URL immediately before revoking it works in an iframe.] [Fetching a blob URL immediately before revoking it works in an iframe.]
expected: FAIL expected: FAIL
[Fetching a blob URL immediately before revoking it works in <script> tags.]
expected: TIMEOUT
[Fetching a blob URL immediately before revoking it works in an iframe navigation.] [Fetching a blob URL immediately before revoking it works in an iframe navigation.]
expected: TIMEOUT expected: TIMEOUT

View file

@ -1,3 +1,4 @@
[007.html] [007.html]
type: testharness type: testharness
expected: TIMEOUT [Link with onclick javascript url and href navigation ]
expected: FAIL

View file

@ -1,6 +0,0 @@
[child_navigates_parent_location.html]
type: testharness
expected: TIMEOUT
[Child document navigating parent via location ]
expected: TIMEOUT

View file

@ -0,0 +1,4 @@
[001.html]
type: testharness
[document.open in unload]
expected: FAIL

View file

@ -0,0 +1,4 @@
[002.html]
type: testharness
[document.open in unload]
expected: FAIL

View file

@ -0,0 +1,4 @@
[003.html]
type: testharness
[document.open in beforeunload with link]
expected: FAIL

View file

@ -0,0 +1,4 @@
[004.html]
type: testharness
[document.open in beforeunload with button]
expected: FAIL

View file

@ -0,0 +1,4 @@
[005.html]
type: testharness
[document.open in pagehide in iframe]
expected: FAIL

View file

@ -0,0 +1,4 @@
[beforeunload-on-history-back.html]
type: testharness
[beforeunload event fires on history navigation back]
expected: FAIL

View file

@ -0,0 +1,6 @@
[beforeunload-on-navigation-of-parent.html]
type: testharness
[Triggering navigation from within beforeunload event]
expected: FAIL
[beforeunload in iframe on navigation of parent]
expected: FAIL

View file

@ -0,0 +1,4 @@
[navigation-within-beforeunload.html]
type: testharness
[Triggering navigation from within beforeunload event]
expected: FAIL

View file

@ -0,0 +1,4 @@
[003.html]
type: testharness
[unload event properties]
expected: FAIL

View file

@ -0,0 +1,5 @@
[006.html]
type: testharness
expected: TIMEOUT
[salvagable state of document after setting pagehide listener]
expected: TIMEOUT

View file

@ -1,6 +0,0 @@
[assign_after_load.html]
type: testharness
expected: TIMEOUT
[Assignment to location after document is completely loaded]
expected: TIMEOUT

View file

@ -1,6 +0,0 @@
[assign_before_load.html]
type: testharness
expected: TIMEOUT
[Assignment to location before document is completely loaded]
expected: TIMEOUT

View file

@ -44,9 +44,6 @@
[Document interface: attribute onsecuritypolicyviolation] [Document interface: attribute onsecuritypolicyviolation]
expected: FAIL expected: FAIL
[Document interface: iframe.contentDocument must have own property "location"]
expected: FAIL
[Document interface: iframe.contentDocument must inherit property "dir" with the proper type] [Document interface: iframe.contentDocument must inherit property "dir" with the proper type]
expected: FAIL expected: FAIL
@ -113,9 +110,6 @@
[Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type] [Document interface: iframe.contentDocument must inherit property "onsecuritypolicyviolation" with the proper type]
expected: FAIL expected: FAIL
[Document interface: new Document() must have own property "location"]
expected: FAIL
[Document interface: new Document() must inherit property "dir" with the proper type] [Document interface: new Document() must inherit property "dir" with the proper type]
expected: FAIL expected: FAIL
@ -179,9 +173,6 @@
[Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type] [Document interface: new Document() must inherit property "onsecuritypolicyviolation" with the proper type]
expected: FAIL expected: FAIL
[Document interface: document.implementation.createDocument(null, "", null) must have own property "location"]
expected: FAIL
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "dir" with the proper type] [Document interface: document.implementation.createDocument(null, "", null) must inherit property "dir" with the proper type]
expected: FAIL expected: FAIL
@ -4991,9 +4982,6 @@
[Window interface: window must inherit property "self" with the proper type] [Window interface: window must inherit property "self" with the proper type]
expected: FAIL expected: FAIL
[Window interface: window must have own property "location"]
expected: FAIL
[Window interface: window must inherit property "locationbar" with the proper type] [Window interface: window must inherit property "locationbar" with the proper type]
expected: FAIL expected: FAIL

View file

@ -1,5 +0,0 @@
[079.html]
type: testharness
[ setting location to javascript URL from event handler ]
expected: FAIL