script: document.visibilityState and document.hidden (#32635)

* Squashed commit of the following:

commit 5e0ea9996cb0d8137c3e1cd04487a1065b61289d
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Thu Jul 11 13:37:51 2024 +0900

    Move lint to new_inherited

    Signed-off-by: Wu Yu Wei <yuweiwu@pm.me>

commit a8cbfb1eef2650d153ef41c232d9e80e1118fc37
Merge: b819968f3e 7a33f8f008
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Thu Jul 11 13:32:18 2024 +0900

    Merge branch 'main' into visibility

commit b819968f3eaa361c8a2cf3af679943ae2065ab32
Merge: eda2ec4c22 1c6b74e1f1
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Tue Jul 9 14:26:43 2024 +0900

    Merge branch 'main' into visibility

commit eda2ec4c225c63236d6851ea525455cad8874ce5
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Thu Jul 4 14:25:05 2024 +0900

    Include page-visibility tests to wpt

commit 9da7b4ee39b141e59e4a21a64445c4b08499463f
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Thu Jul 4 12:50:40 2024 +0900

    Add TODO comment for future update

commit 11f55fea3ead0c8fa07f16557a63cc6a77c15c3f
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Wed Jul 3 11:01:51 2024 +0900

    Add spaces between steps

commit 408c3e51f25867e85f894cd77a6355bc32f2aa00
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Tue Jul 2 18:33:53 2024 +0900

    Update MANIFEST.json

commit 679fe4ffdd28554b11b4018395fac22a08ccbc34
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Tue Jul 2 18:27:02 2024 +0900

    Add VisibilityStateEntry to mozilla/interfaces.html

commit 4a456a2b4a473fa795274edf56ecf660616f90eb
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Tue Jul 2 14:28:11 2024 +0900

    Update meta results

commit cd191447ff61de392526e00c13f765c2df7a269e
Merge: 7ff480a698 ad01342f00
Author: Ngo Iok Ui (Wu Yu Wei) <yuweiwu@pm.me>
Date:   Tue Jul 2 13:47:49 2024 +0900

    Merge branch 'main' into visibility

commit 7ff480a698413ac5526edfb1b8731373bb9d04ae
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Tue Jul 2 13:12:44 2024 +0900

    Update description text of update_visibility_state

commit 0e496b7bce4fd5476a1919737b00e8f0c9e2fdc8
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Tue Jul 2 12:59:40 2024 +0900

    Add specification link to VisibilityStateEntry methods

commit 3e4a061450621bd17f19ff81099dd4daaeaea478
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Tue Jul 2 12:31:53 2024 +0900

    Add descriptive text to each step

commit 8bbdfcae97db5002b09e5f5ecec6ae80d080dc95
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Fri Jun 28 19:15:34 2024 +0900

    mach fmt

commit dc1c7a4aec6aba56af7afcfee6feadbee242a643
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Fri Jun 28 19:01:00 2024 +0900

    Add update_visibility_state

commit 6aa18143319044dc084a9585ab064cd853bccc21
Author: Wu Wayne <yuweiwu@pm.me>
Date:   Fri Jun 28 16:06:25 2024 +0900

    Add VisibilityStateEntry.webidl

commit 638ae3cd563004334d35cc3fbdc1f918d29833d0
Author: Wu Yu Wei <yuweiwu@pm.me>
Date:   Fri Jun 28 13:39:29 2024 +0900

    Add visibilityState and hidden in Document.webidl

Signed-off-by: Wu Yu Wei <yuweiwu@pm.me>

* Move creation into reflect call

Signed-off-by: Wu Yu Wei <yuweiwu@pm.me>

---------

Signed-off-by: Wu Yu Wei <yuweiwu@pm.me>
This commit is contained in:
Ngo Iok Ui (Wu Yu Wei) 2024-07-12 17:32:25 +09:00 committed by GitHub
parent b206a0f4a3
commit 40bac8c3df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 186 additions and 63 deletions

View file

@ -67,7 +67,6 @@ use url::Host;
use uuid::Uuid;
use webrender_api::units::DeviceIntRect;
use super::bindings::trace::{HashMapTracedValues, NoTrace};
use crate::animation_timeline::AnimationTimeline;
use crate::animations::Animations;
use crate::document_loader::{DocumentLoader, LoadType};
@ -77,7 +76,7 @@ use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref, RefMut};
use crate::dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnloadEvent_Binding::BeforeUnloadEventMethods;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::{
DocumentMethods, DocumentReadyState, NamedPropertyValue,
DocumentMethods, DocumentReadyState, DocumentVisibilityState, NamedPropertyValue,
};
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElement_Binding::HTMLIFrameElementMethods;
@ -100,6 +99,7 @@ use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot, DomSlice, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::trace::{HashMapTracedValues, NoTrace};
use crate::dom::bindings::xmlname::XMLName::Invalid;
use crate::dom::bindings::xmlname::{
namespace_from_domstring, validate_and_extract, xml_name_type,
@ -153,6 +153,7 @@ use crate::dom::node::{
use crate::dom::nodeiterator::NodeIterator;
use crate::dom::nodelist::NodeList;
use crate::dom::pagetransitionevent::PageTransitionEvent;
use crate::dom::performanceentry::PerformanceEntry;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::promise::Promise;
use crate::dom::range::Range;
@ -167,6 +168,7 @@ use crate::dom::touch::Touch;
use crate::dom::touchevent::TouchEvent;
use crate::dom::touchlist::TouchList;
use crate::dom::treewalker::TreeWalker;
use crate::dom::types::VisibilityStateEntry;
use crate::dom::uievent::UIEvent;
use crate::dom::virtualmethods::vtable_for;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
@ -470,6 +472,8 @@ pub struct Document {
/// The set of all fonts loaded by this document.
/// <https://drafts.csswg.org/css-font-loading/#font-face-source>
fonts: MutNullableDom<FontFaceSet>,
/// <https://html.spec.whatwg.org/multipage/#visibility-state>
visibility_state: Cell<DocumentVisibilityState>,
}
#[derive(JSTraceable, MallocSizeOf)]
@ -708,8 +712,9 @@ impl Document {
return;
}
// html.spec.whatwg.org/multipage/#history-traversal
// Step 4.6
// This step used to be Step 4.6 in html.spec.whatwg.org/multipage/#history-traversal
// But it's now Step 4 in https://html.spec.whatwg.org/multipage/#reactivate-a-document
// TODO: See #32687 for more information.
let document = Trusted::new(self);
self.window
.task_manager()
@ -722,9 +727,12 @@ impl Document {
if document.page_showing.get() {
return;
}
// Step 4.6.2
// Step 4.6.2 Set document's page showing flag to true.
document.page_showing.set(true);
// Step 4.6.4
// Step 4.6.3 Update the visibility state of document to "visible".
document.update_visibility_state(DocumentVisibilityState::Visible);
// Step 4.6.4 Fire a page transition event named pageshow at document's relevant
// global object with true.
let event = PageTransitionEvent::new(
window,
atom!("pageshow"),
@ -2220,9 +2228,12 @@ impl Document {
// TODO: Step 1, increase the event loop's termination nesting level by 1.
// Step 2
self.incr_ignore_opens_during_unload_counter();
// Step 3-6
// Step 3-6 If oldDocument's page showing is true:
if self.page_showing.get() {
// Set oldDocument's page showing to false.
self.page_showing.set(false);
// Fire a page transition event named pagehide at oldDocument's relevant global object with oldDocument's
// salvageable state.
let event = PageTransitionEvent::new(
&self.window,
atom!("pagehide"),
@ -2233,7 +2244,8 @@ impl Document {
let event = event.upcast::<Event>();
event.set_trusted(true);
let _ = self.window.dispatch_event_with_target_override(event);
// TODO Step 6, document visibility steps.
// Step 6 Update the visibility state of oldDocument to "hidden".
self.update_visibility_state(DocumentVisibilityState::Hidden);
}
// Step 7
if !self.fired_unload.get() {
@ -3297,6 +3309,7 @@ impl Document {
mouse_move_event_index: Default::default(),
resize_observers: Default::default(),
fonts: Default::default(),
visibility_state: Cell::new(DocumentVisibilityState::Hidden),
}
}
@ -4083,6 +4096,39 @@ impl Document {
pub(crate) fn set_declarative_refresh(&self, refresh: DeclarativeRefresh) {
*self.declarative_refresh.borrow_mut() = Some(refresh);
}
/// <https://html.spec.whatwg.org/multipage/#visibility-state>
fn update_visibility_state(&self, visibility_state: DocumentVisibilityState) {
// Step 1 If document's visibility state equals visibilityState, then return.
if self.visibility_state.get() == visibility_state {
return;
}
// Step 2 Set document's visibility state to visibilityState.
self.visibility_state.set(visibility_state);
// Step 3 Queue a new VisibilityStateEntry whose visibility state is visibilityState and whose timestamp is
// the current high resolution time given document's relevant global object.
let entry = VisibilityStateEntry::new(
&self.global(),
visibility_state,
*self.global().performance().Now(),
);
self.window
.Performance()
.queue_entry(entry.upcast::<PerformanceEntry>());
// Step 4 Run the screen orientation change steps with document.
// TODO ScreenOrientation hasn't implemented yet
// Step 5 Run the view transition page visibility change steps with document.
// TODO ViewTransition hasn't implemented yet
// Step 6 Run any page visibility change steps which may be defined in other specifications, with visibility
// state and document. Any other specs' visibility steps will go here.
// Step 7 Fire an event named visibilitychange at document, with its bubbles attribute initialized to true.
self.upcast::<EventTarget>()
.fire_bubbling_event(atom!("visibilitychange"));
}
}
impl ProfilerMetadataFactory for Document {
@ -5376,6 +5422,16 @@ impl DocumentMethods for Document {
self.fonts
.or_init(|| FontFaceSet::new(&self.global(), None))
}
/// <https://html.spec.whatwg.org/multipage/#dom-document-hidden>
fn Hidden(&self) -> bool {
self.visibility_state.get() == DocumentVisibilityState::Hidden
}
/// <https://html.spec.whatwg.org/multipage/#dom-document-visibilitystate>
fn VisibilityState(&self) -> DocumentVisibilityState {
self.visibility_state.get()
}
}
fn update_with_current_time_ms(marker: &Cell<u64>) {

View file

@ -580,6 +580,7 @@ pub mod vertexarrayobject;
pub mod videotrack;
pub mod videotracklist;
pub mod virtualmethods;
pub mod visibilitystateentry;
pub mod vttcue;
pub mod vttregion;
pub mod webgl2renderingcontext;

View file

@ -0,0 +1,73 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::ops::Deref;
use dom_struct::dom_struct;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentVisibilityState;
use crate::dom::bindings::codegen::Bindings::PerformanceEntryBinding::PerformanceEntryMethods;
use crate::dom::bindings::codegen::Bindings::VisibilityStateEntryBinding::VisibilityStateEntryMethods;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::performanceentry::PerformanceEntry;
#[dom_struct]
pub struct VisibilityStateEntry {
entry: PerformanceEntry,
}
impl VisibilityStateEntry {
#[allow(crown::unrooted_must_root)]
fn new_inherited(state: DocumentVisibilityState, timestamp: f64) -> VisibilityStateEntry {
let name = match state {
DocumentVisibilityState::Visible => DOMString::from("visible"),
DocumentVisibilityState::Hidden => DOMString::from("hidden"),
};
VisibilityStateEntry {
entry: PerformanceEntry::new_inherited(
name,
DOMString::from("visibility-state"),
timestamp,
0.,
),
}
}
pub fn new(
global: &GlobalScope,
state: DocumentVisibilityState,
timestamp: f64,
) -> DomRoot<VisibilityStateEntry> {
reflect_dom_object(
Box::new(VisibilityStateEntry::new_inherited(state, timestamp)),
global,
)
}
}
impl VisibilityStateEntryMethods for VisibilityStateEntry {
/// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-name>
fn Name(&self) -> DOMString {
self.entry.Name()
}
/// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-entrytype>
fn EntryType(&self) -> DOMString {
self.entry.EntryType()
}
/// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-starttime>
fn StartTime(&self) -> Finite<f64> {
self.entry.StartTime()
}
/// <https://html.spec.whatwg.org/multipage/#visibilitystateentry-duration>
fn Duration(&self) -> u32 {
*self.entry.Duration().deref() as u32
}
}

View file

@ -78,6 +78,7 @@ Document includes NonElementParentNode;
Document includes ParentNode;
enum DocumentReadyState { "loading", "interactive", "complete" };
enum DocumentVisibilityState { "visible", "hidden" };
dictionary ElementCreationOptions {
DOMString is;
@ -144,6 +145,8 @@ partial /*sealed*/ interface Document {
// boolean queryCommandState(DOMString commandId);
boolean queryCommandSupported(DOMString commandId);
// DOMString queryCommandValue(DOMString commandId);
readonly attribute boolean hidden;
readonly attribute DocumentVisibilityState visibilityState;
// special event handler IDL attributes that only apply to Document objects
[LegacyLenientThis] attribute EventHandler onreadystatechange;

View file

@ -0,0 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#visibilitystateentry
[Exposed=(Window)]
interface VisibilityStateEntry : PerformanceEntry {
readonly attribute DOMString name; // shadows inherited name
readonly attribute DOMString entryType; // shadows inherited entryType
readonly attribute DOMHighResTimeStamp startTime; // shadows inherited startTime
readonly attribute unsigned long duration; // shadows inherited duration
};