diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 15 | ||||
-rw-r--r-- | components/script/dom/event.rs | 5 | ||||
-rw-r--r-- | components/script/dom/htmlimageelement.rs | 25 | ||||
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 279 | ||||
-rw-r--r-- | components/script/dom/performance.rs | 40 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 4 | ||||
-rw-r--r-- | components/script/dom/webidls/Event.webidl | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/Performance.webidl | 4 | ||||
-rw-r--r-- | components/script/dom/webidls/PerformanceEntry.webidl | 3 | ||||
-rw-r--r-- | components/script/dom/webidls/PerformanceNavigation.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/PerformanceNavigationTiming.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/PerformanceResourceTiming.webidl | 2 | ||||
-rw-r--r-- | components/script/dom/window.rs | 21 | ||||
-rw-r--r-- | components/script/dom/xrwebgllayer.rs | 64 |
14 files changed, 289 insertions, 178 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 4a8cc573416..dece9a763d9 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -492,7 +492,7 @@ class CGMethodCall(CGThing): else: # Just throw; we have no idea what we're supposed to # do with this. - caseBody.append(CGGeneric("throw_internal_error(*cx, \"Could not convert JavaScript argument\");\n" + caseBody.append(CGGeneric("throw_type_error(*cx, \"Could not convert JavaScript argument\");\n" "return false;")) argCountCases.append(CGCase(str(argCount), @@ -2049,9 +2049,10 @@ class CGImports(CGWrapper): if name != 'GlobalScope': extras += [descriptor.path] parentName = descriptor.getParentName() - if parentName: + while parentName: descriptor = descriptorProvider.getDescriptor(parentName) extras += [descriptor.path, descriptor.bindingPath] + parentName = descriptor.getParentName() elif t.isType() and t.isRecord(): extras += ['crate::dom::bindings::mozmap::MozMap'] elif isinstance(t, IDLPromiseType): @@ -3662,6 +3663,7 @@ class CGDefaultToJSONMethod(CGSpecializedMethod): def definition_body(self): ret = dedent(""" + use crate::dom::bindings::inheritance::HasParent; rooted!(in(*cx) let result = JS_NewPlainObject(*cx)); if result.is_null() { return false; @@ -3676,16 +3678,19 @@ class CGDefaultToJSONMethod(CGSpecializedMethod): jsonDescriptors.append(descriptor) interface = interface.parent + parents = len(jsonDescriptors) - 1 form = """ - if !${parentclass}CollectJSONAttributes(cx, _obj, this, &result) { + if !${parentclass}CollectJSONAttributes(cx, _obj, this${asparent}, &result) { return false; } """ # Iterate the array in reverse: oldest ancestor first for descriptor in jsonDescriptors[:0:-1]: - ret += fill(form, parentclass=toBindingNamespace(descriptor.name) + "::") - ret += fill(form, parentclass="") + ret += fill(form, parentclass=toBindingNamespace(descriptor.name) + "::", + asparent=".as_ref().unwrap()" + ".as_parent()" * parents) + parents -= 1 + ret += fill(form, parentclass="", asparent="") ret += ('(*args).rval().set(ObjectValue(*result));\n' 'return true;\n') return CGGeneric(ret) diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index a14beccabe3..52c9af3b061 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -263,6 +263,11 @@ impl EventMethods for Event { self.target.get() } + // https://dom.spec.whatwg.org/#dom-event-srcelement + fn GetSrcElement(&self) -> Option<DomRoot<EventTarget>> { + self.target.get() + } + // https://dom.spec.whatwg.org/#dom-event-currenttarget fn GetCurrentTarget(&self) -> Option<DomRoot<EventTarget>> { self.current_target.get() diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 4a9a94dccde..505b649e50c 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -22,7 +22,7 @@ use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::document::Document; use crate::dom::element::{reflect_cross_origin_attribute, set_cross_origin_attribute}; use crate::dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; -use crate::dom::event::{Event, EventBubbles, EventCancelable}; +use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlareaelement::HTMLAreaElement; @@ -37,7 +37,6 @@ use crate::dom::node::{ document_from_node, window_from_node, BindContext, Node, NodeDamage, ShadowIncluding, }; use crate::dom::performanceresourcetiming::InitiatorType; -use crate::dom::progressevent::ProgressEvent; use crate::dom::values::UNSIGNED_LONG_MAX; use crate::dom::virtualmethods::VirtualMethods; use crate::dom::window::Window; @@ -809,26 +808,7 @@ impl HTMLImageElement { return; }, }; - // Step 10. - let target = Trusted::new(self.upcast::<EventTarget>()); - // FIXME(nox): Why are errors silenced here? - let _ = task_source.queue( - task!(fire_progress_event: move || { - let target = target.root(); - - let event = ProgressEvent::new( - &target.global(), - atom!("loadstart"), - EventBubbles::DoesNotBubble, - EventCancelable::NotCancelable, - false, - 0, - 0, - ); - event.upcast::<Event>().fire(&target); - }), - window.upcast(), - ); + // Step 11 let base_url = document.base_url(); let parsed_url = base_url.join(&src.0); @@ -850,7 +830,6 @@ impl HTMLImageElement { current_request.source_url = Some(USVString(src)) } this.upcast::<EventTarget>().fire_event(atom!("error")); - this.upcast::<EventTarget>().fire_event(atom!("loadend")); // FIXME(nox): According to the spec, setting the current // request to the broken state is done prior to queuing a diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index dbfda59db02..7c9e3ebd42d 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -125,35 +125,44 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[ "text/x-javascript", ]; +#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] +pub enum ScriptType { + Classic, + Module, +} + #[derive(JSTraceable, MallocSizeOf)] -pub struct ClassicScript { +pub struct ScriptOrigin { text: DOMString, url: ServoUrl, external: bool, + type_: ScriptType, } -impl ClassicScript { - fn internal(text: DOMString, url: ServoUrl) -> ClassicScript { - ClassicScript { +impl ScriptOrigin { + fn internal(text: DOMString, url: ServoUrl, type_: ScriptType) -> ScriptOrigin { + ScriptOrigin { text: text, url: url, external: false, + type_, } } - fn external(text: DOMString, url: ServoUrl) -> ClassicScript { - ClassicScript { + fn external(text: DOMString, url: ServoUrl, type_: ScriptType) -> ScriptOrigin { + ScriptOrigin { text: text, url: url, external: true, + type_, } } } -pub type ScriptResult = Result<ClassicScript, NetworkError>; +pub type ScriptResult = Result<ScriptOrigin, NetworkError>; /// The context required for asynchronously loading an external script source. -struct ScriptContext { +struct ClassicContext { /// The element that initiated the request. elem: Trusted<HTMLScriptElement>, /// The kind of external script. @@ -173,7 +182,7 @@ struct ScriptContext { resource_timing: ResourceFetchTiming, } -impl FetchResponseListener for ScriptContext { +impl FetchResponseListener for ClassicContext { fn process_request_body(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here? fn process_request_eof(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here? @@ -226,7 +235,11 @@ impl FetchResponseListener for ScriptContext { // Step 7. let (source_text, _, _) = encoding.decode(&self.data); - ClassicScript::external(DOMString::from(source_text), metadata.final_url) + ScriptOrigin::external( + DOMString::from(source_text), + metadata.final_url, + ScriptType::Classic, + ) }); // Step 9. @@ -260,7 +273,7 @@ impl FetchResponseListener for ScriptContext { } } -impl ResourceTimingListener for ScriptContext { +impl ResourceTimingListener for ClassicContext { fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) { let initiator_type = InitiatorType::LocalName( self.elem @@ -277,7 +290,7 @@ impl ResourceTimingListener for ScriptContext { } } -impl PreInvoke for ScriptContext {} +impl PreInvoke for ClassicContext {} /// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script> fn fetch_a_classic_script( @@ -313,7 +326,7 @@ fn fetch_a_classic_script( // TODO: Step 3, Add custom steps to perform fetch - let context = Arc::new(Mutex::new(ScriptContext { + let context = Arc::new(Mutex::new(ClassicContext { elem: Trusted::new(script), kind: kind, character_encoding: character_encoding, @@ -364,47 +377,49 @@ impl HTMLScriptElement { self.non_blocking.set(true); } - // Step 4. + // Step 4-5. let text = self.Text(); if text.is_empty() && !element.has_attribute(&local_name!("src")) { return; } - // Step 5. + // Step 6. if !self.upcast::<Node>().is_connected() { return; } - // Step 6. - if !self.is_javascript() { + let script_type = if let Some(ty) = self.get_script_type() { + ty + } else { + // Step 7. return; - } + }; - // Step 7. + // Step 8. if was_parser_inserted { self.parser_inserted.set(true); self.non_blocking.set(false); } - // Step 8. + // Step 9. self.already_started.set(true); - // Step 9. + // Step 10. let doc = document_from_node(self); if self.parser_inserted.get() && &*self.parser_document != &*doc { return; } - // Step 10. + // Step 11. if !doc.is_scripting_enabled() { return; } - // TODO: Step 11: nomodule content attribute + // TODO: Step 12: nomodule content attribute - // TODO(#4577): Step 12: CSP. + // TODO(#4577): Step 13: CSP. - // Step 13. + // Step 14. let for_attribute = element.get_attribute(&ns!(), &local_name!("for")); let event_attribute = element.get_attribute(&ns!(), &local_name!("event")); match (for_attribute, event_attribute) { @@ -424,20 +439,20 @@ impl HTMLScriptElement { (_, _) => (), } - // Step 14. + // Step 15. let encoding = element .get_attribute(&ns!(), &local_name!("charset")) .and_then(|charset| Encoding::for_label(charset.value().as_bytes())) .unwrap_or_else(|| doc.encoding()); - // Step 15. + // Step 16. let cors_setting = cors_setting_for_element(element); - // TODO: Step 16: Module script credentials mode. + // TODO: Step 17: Module script credentials mode. - // TODO: Step 17: Nonce. + // TODO: Step 18: Nonce. - // Step 18: Integrity metadata. + // Step 19: Integrity metadata. let im_attribute = element.get_attribute(&ns!(), &local_name!("integrity")); let integrity_val = im_attribute.as_ref().map(|a| a.value()); let integrity_metadata = match integrity_val { @@ -445,26 +460,30 @@ impl HTMLScriptElement { None => "", }; - // TODO: Step 19: parser state. + // TODO: Step 20: referrer policy + + // TODO: Step 21: parser state. + + // TODO: Step 22: Fetch options - // TODO: Step 20: environment settings object. + // TODO: Step 23: environment settings object. let base_url = doc.base_url(); if let Some(src) = element.get_attribute(&ns!(), &local_name!("src")) { - // Step 21. + // Step 24. - // Step 21.1. + // Step 24.1. let src = src.value(); - // Step 21.2. + // Step 24.2. if src.is_empty() { self.queue_error_event(); return; } - // Step 21.3: The "from an external file"" flag is stored in ClassicScript. + // Step 24.3: The "from an external file"" flag is stored in ScriptOrigin. - // Step 21.4-21.5. + // Step 24.4-24.5. let url = match base_url.join(&src) { Ok(url) => url, Err(_) => { @@ -474,64 +493,89 @@ impl HTMLScriptElement { }, }; - // Preparation for step 23. - let kind = if element.has_attribute(&local_name!("defer")) && - was_parser_inserted && - !r#async - { - // Step 23.a: classic, has src, has defer, was parser-inserted, is not async. - ExternalScriptKind::Deferred - } else if was_parser_inserted && !r#async { - // Step 23.c: classic, has src, was parser-inserted, is not async. - ExternalScriptKind::ParsingBlocking - } else if !r#async && !self.non_blocking.get() { - // Step 23.d: classic, has src, is not async, is not non-blocking. - ExternalScriptKind::AsapInOrder - } else { - // Step 23.f: classic, has src. - ExternalScriptKind::Asap - }; - - // Step 21.6. - fetch_a_classic_script( - self, - kind, - url, - cors_setting, - integrity_metadata.to_owned(), - encoding, - ); - - // Step 23. - match kind { - ExternalScriptKind::Deferred => doc.add_deferred_script(self), - ExternalScriptKind::ParsingBlocking => { - doc.set_pending_parsing_blocking_script(self, None) + match script_type { + ScriptType::Classic => { + // Preparation for step 26. + let kind = if element.has_attribute(&local_name!("defer")) && + was_parser_inserted && + !r#async + { + // Step 26.a: classic, has src, has defer, was parser-inserted, is not async. + ExternalScriptKind::Deferred + } else if was_parser_inserted && !r#async { + // Step 26.c: classic, has src, was parser-inserted, is not async. + ExternalScriptKind::ParsingBlocking + } else if !r#async && !self.non_blocking.get() { + // Step 26.d: classic, has src, is not async, is not non-blocking. + ExternalScriptKind::AsapInOrder + } else { + // Step 26.f: classic, has src. + ExternalScriptKind::Asap + }; + + // Step 24.6. + fetch_a_classic_script( + self, + kind, + url, + cors_setting, + integrity_metadata.to_owned(), + encoding, + ); + + // Step 23. + match kind { + ExternalScriptKind::Deferred => doc.add_deferred_script(self), + ExternalScriptKind::ParsingBlocking => { + doc.set_pending_parsing_blocking_script(self, None) + }, + ExternalScriptKind::AsapInOrder => doc.push_asap_in_order_script(self), + ExternalScriptKind::Asap => doc.add_asap_script(self), + } + }, + ScriptType::Module => { + warn!( + "{} is a module script. It should be fixed after #23545 landed.", + url.clone() + ); }, - ExternalScriptKind::AsapInOrder => doc.push_asap_in_order_script(self), - ExternalScriptKind::Asap => doc.add_asap_script(self), } } else { - // Step 22. + // Step 25. assert!(!text.is_empty()); - let result = Ok(ClassicScript::internal(text, base_url)); - // Step 23. + // Step 25-1. + let result = Ok(ScriptOrigin::internal( + text.clone(), + base_url.clone(), + script_type.clone(), + )); + + // TODO: Step 25-2. + if let ScriptType::Module = script_type { + warn!( + "{} is a module script. It should be fixed after #23545 landed.", + base_url.clone() + ); + return; + } + + // Step 26. if was_parser_inserted && doc.get_current_parser() .map_or(false, |parser| parser.script_nesting_level() <= 1) && doc.get_script_blocking_stylesheets_count() > 0 { - // Step 23.h: classic, has no src, was parser-inserted, is blocked on stylesheet. + // Step 26.h: classic, has no src, was parser-inserted, is blocked on stylesheet. doc.set_pending_parsing_blocking_script(self, Some(result)); } else { - // Step 23.i: otherwise. + // Step 26.i: otherwise. self.execute(result); } } } - fn unminify_js(&self, script: &mut ClassicScript) { + fn unminify_js(&self, script: &mut ScriptOrigin) { if !self.parser_document.window().unminify_js() { return; } @@ -584,7 +628,7 @@ impl HTMLScriptElement { } /// <https://html.spec.whatwg.org/multipage/#execute-the-script-block> - pub fn execute(&self, result: Result<ClassicScript, NetworkError>) { + pub fn execute(&self, result: Result<ScriptOrigin, NetworkError>) { // Step 1. let doc = document_from_node(self); if self.parser_inserted.get() && &*doc != &*self.parser_document { @@ -639,7 +683,7 @@ impl HTMLScriptElement { } // https://html.spec.whatwg.org/multipage/#run-a-classic-script - pub fn run_a_classic_script(&self, script: &ClassicScript) { + pub fn run_a_classic_script(&self, script: &ScriptOrigin) { // TODO use a settings object rather than this element's document/window // Step 2 let document = document_from_node(self); @@ -688,45 +732,58 @@ impl HTMLScriptElement { ); } - pub fn is_javascript(&self) -> bool { + // https://html.spec.whatwg.org/multipage/#prepare-a-script Step 7. + pub fn get_script_type(&self) -> Option<ScriptType> { let element = self.upcast::<Element>(); + let type_attr = element.get_attribute(&ns!(), &local_name!("type")); - let is_js = match type_attr.as_ref().map(|s| s.value()) { - Some(ref s) if s.is_empty() => { - // type attr exists, but empty means js + let language_attr = element.get_attribute(&ns!(), &local_name!("language")); + + let script_type = match ( + type_attr.as_ref().map(|t| t.value()), + language_attr.as_ref().map(|l| l.value()), + ) { + (Some(ref ty), _) if ty.is_empty() => { debug!("script type empty, inferring js"); - true + Some(ScriptType::Classic) }, - Some(s) => { - debug!("script type={}", &**s); - SCRIPT_JS_MIMES - .contains(&s.to_ascii_lowercase().trim_matches(HTML_SPACE_CHARACTERS)) + (None, Some(ref lang)) if lang.is_empty() => { + debug!("script type empty, inferring js"); + Some(ScriptType::Classic) }, - None => { - debug!("no script type"); - let language_attr = element.get_attribute(&ns!(), &local_name!("language")); - let is_js = match language_attr.as_ref().map(|s| s.value()) { - Some(ref s) if s.is_empty() => { - debug!("script language empty, inferring js"); - true - }, - Some(s) => { - debug!("script language={}", &**s); - let mut language = format!("text/{}", &**s); - language.make_ascii_lowercase(); - SCRIPT_JS_MIMES.contains(&&*language) - }, - None => { - debug!("no script type or language, inferring js"); - true - }, - }; - // https://github.com/rust-lang/rust/issues/21114 - is_js + (None, None) => { + debug!("script type empty, inferring js"); + Some(ScriptType::Classic) + }, + (None, Some(ref lang)) => { + debug!("script language={}", &***lang); + let language = format!("text/{}", &***lang); + + if SCRIPT_JS_MIMES.contains(&language.to_ascii_lowercase().as_str()) { + Some(ScriptType::Classic) + } else { + None + } + }, + (Some(ref ty), _) => { + debug!("script type={}", &***ty); + + if &***ty == String::from("module") { + return Some(ScriptType::Module); + } + + if SCRIPT_JS_MIMES + .contains(&ty.to_ascii_lowercase().trim_matches(HTML_SPACE_CHARACTERS)) + { + Some(ScriptType::Classic) + } else { + None + } }, }; + // https://github.com/rust-lang/rust/issues/21114 - is_js + script_type } pub fn set_parser_inserted(&self, parser_inserted: bool) { diff --git a/components/script/dom/performance.rs b/components/script/dom/performance.rs index b29858fdca5..6c418b44316 100644 --- a/components/script/dom/performance.rs +++ b/components/script/dom/performance.rs @@ -57,6 +57,7 @@ const INVALID_ENTRY_NAMES: &'static [&'static str] = &[ /// Performance and PerformanceObserverEntryList interfaces implementations. #[derive(JSTraceable, MallocSizeOf)] pub struct PerformanceEntryList { + /// https://w3c.github.io/performance-timeline/#dfn-performance-entry-buffer entries: DOMPerformanceEntryList, } @@ -137,10 +138,13 @@ struct PerformanceObserver { #[dom_struct] pub struct Performance { eventtarget: EventTarget, - entries: DomRefCell<PerformanceEntryList>, + buffer: DomRefCell<PerformanceEntryList>, observers: DomRefCell<Vec<PerformanceObserver>>, pending_notification_observers_task: Cell<bool>, navigation_start_precise: u64, + /// https://w3c.github.io/performance-timeline/#dfn-maxbuffersize + /// The max-size of the buffer, set to 0 once the pipeline exits. + /// TODO: have one max-size per entry type. resource_timing_buffer_size_limit: Cell<usize>, resource_timing_buffer_current_size: Cell<usize>, resource_timing_buffer_pending_full_event: Cell<bool>, @@ -151,7 +155,7 @@ impl Performance { fn new_inherited(navigation_start_precise: u64) -> Performance { Performance { eventtarget: EventTarget::new_inherited(), - entries: DomRefCell::new(PerformanceEntryList::new(Vec::new())), + buffer: DomRefCell::new(PerformanceEntryList::new(Vec::new())), observers: DomRefCell::new(Vec::new()), pending_notification_observers_task: Cell::new(false), navigation_start_precise, @@ -170,6 +174,15 @@ impl Performance { ) } + /// Clear all buffered performance entries, and disable the buffer. + /// Called as part of the window's "clear_js_runtime" workflow, + /// performed when exiting a pipeline. + pub fn clear_and_disable_performance_entry_buffer(&self) { + let mut buffer = self.buffer.borrow_mut(); + buffer.entries.clear(); + self.resource_timing_buffer_size_limit.set(0); + } + /// Add a PerformanceObserver to the list of observers with a set of /// observed entry types. pub fn add_observer( @@ -179,10 +192,10 @@ impl Performance { buffered: bool, ) { if buffered { - let entries = self.entries.borrow(); + let buffer = self.buffer.borrow(); let mut new_entries = entry_types .iter() - .flat_map(|e| entries.get_entries_by_name_and_type(None, Some(e.clone()))) + .flat_map(|e| buffer.get_entries_by_name_and_type(None, Some(e.clone()))) .collect::<DOMPerformanceEntryList>(); let mut obs_entries = observer.entries(); obs_entries.append(&mut new_entries); @@ -221,6 +234,7 @@ impl Performance { /// Also this algorithm has been extented according to : /// <https://w3c.github.io/resource-timing/#sec-extensions-performance-interface> pub fn queue_entry(&self, entry: &PerformanceEntry, add_to_performance_entries_buffer: bool) { + // https://w3c.github.io/performance-timeline/#dfn-determine-eligibility-for-adding-a-performance-entry if entry.entry_type() == "resource" && !self.should_queue_resource_entry(entry) { return; } @@ -242,7 +256,7 @@ impl Performance { // If the "add to performance entry buffer flag" is set, add the // new entry to the buffer. if add_to_performance_entries_buffer { - self.entries + self.buffer .borrow_mut() .entries .push(DomRoot::from_ref(entry)); @@ -390,14 +404,14 @@ impl PerformanceMethods for Performance { // https://www.w3.org/TR/performance-timeline-2/#dom-performance-getentries fn GetEntries(&self) -> Vec<DomRoot<PerformanceEntry>> { - self.entries + self.buffer .borrow() .get_entries_by_name_and_type(None, None) } // https://www.w3.org/TR/performance-timeline-2/#dom-performance-getentriesbytype fn GetEntriesByType(&self, entry_type: DOMString) -> Vec<DomRoot<PerformanceEntry>> { - self.entries + self.buffer .borrow() .get_entries_by_name_and_type(None, Some(entry_type)) } @@ -408,7 +422,7 @@ impl PerformanceMethods for Performance { name: DOMString, entry_type: Option<DOMString>, ) -> Vec<DomRoot<PerformanceEntry>> { - self.entries + self.buffer .borrow() .get_entries_by_name_and_type(Some(name), entry_type) } @@ -435,7 +449,7 @@ impl PerformanceMethods for Performance { // https://w3c.github.io/user-timing/#dom-performance-clearmarks fn ClearMarks(&self, mark_name: Option<DOMString>) { - self.entries + self.buffer .borrow_mut() .clear_entries_by_name_and_type(mark_name, Some(DOMString::from("mark"))); } @@ -450,7 +464,7 @@ impl PerformanceMethods for Performance { // Steps 1 and 2. let end_time = match end_mark { Some(name) => self - .entries + .buffer .borrow() .get_last_entry_start_time_with_name_and_type(DOMString::from("mark"), name), None => self.now(), @@ -459,7 +473,7 @@ impl PerformanceMethods for Performance { // Step 3. let start_time = match start_mark { Some(name) => self - .entries + .buffer .borrow() .get_last_entry_start_time_with_name_and_type(DOMString::from("mark"), name), None => 0., @@ -485,13 +499,13 @@ impl PerformanceMethods for Performance { // https://w3c.github.io/user-timing/#dom-performance-clearmeasures fn ClearMeasures(&self, measure_name: Option<DOMString>) { - self.entries + self.buffer .borrow_mut() .clear_entries_by_name_and_type(measure_name, Some(DOMString::from("measure"))); } // https://w3c.github.io/resource-timing/#dom-performance-clearresourcetimings fn ClearResourceTimings(&self) { - self.entries + self.buffer .borrow_mut() .clear_entries_by_name_and_type(None, Some(DOMString::from("resource"))); self.resource_timing_buffer_current_size.set(0); diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index c4c580cda32..e50d70cb916 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -1102,6 +1102,10 @@ impl WebGLRenderingContext { self.bound_framebuffer.get() } + pub fn bound_renderbuffer(&self) -> Option<DomRoot<WebGLRenderbuffer>> { + self.bound_renderbuffer.get() + } + pub fn extension_manager(&self) -> &WebGLExtensions { &self.extension_manager } diff --git a/components/script/dom/webidls/Event.webidl b/components/script/dom/webidls/Event.webidl index c688daedb2e..f3d281813a1 100644 --- a/components/script/dom/webidls/Event.webidl +++ b/components/script/dom/webidls/Event.webidl @@ -11,6 +11,7 @@ interface Event { [Pure] readonly attribute DOMString type; readonly attribute EventTarget? target; + readonly attribute EventTarget? srcElement; readonly attribute EventTarget? currentTarget; const unsigned short NONE = 0; diff --git a/components/script/dom/webidls/Performance.webidl b/components/script/dom/webidls/Performance.webidl index 77bca4392e7..0e2f7a960d5 100644 --- a/components/script/dom/webidls/Performance.webidl +++ b/components/script/dom/webidls/Performance.webidl @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* * The origin of this IDL file is - * https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#sec-window.performance-attribute + * https://w3c.github.io/hr-time/#sec-performance */ typedef double DOMHighResTimeStamp; @@ -13,7 +13,7 @@ typedef sequence<PerformanceEntry> PerformanceEntryList; interface Performance : EventTarget { DOMHighResTimeStamp now(); readonly attribute DOMHighResTimeStamp timeOrigin; - // [Default] object toJSON(); + [Default] object toJSON(); }; // https://w3c.github.io/performance-timeline/#extensions-to-the-performance-interface diff --git a/components/script/dom/webidls/PerformanceEntry.webidl b/components/script/dom/webidls/PerformanceEntry.webidl index 23f2f9c155a..5f6fee1cabd 100644 --- a/components/script/dom/webidls/PerformanceEntry.webidl +++ b/components/script/dom/webidls/PerformanceEntry.webidl @@ -12,6 +12,5 @@ interface PerformanceEntry { readonly attribute DOMString entryType; readonly attribute DOMHighResTimeStamp startTime; readonly attribute DOMHighResTimeStamp duration; - - // [Default] object toJSON(); + [Default] object toJSON(); }; diff --git a/components/script/dom/webidls/PerformanceNavigation.webidl b/components/script/dom/webidls/PerformanceNavigation.webidl index 5a1ccba61f1..3e5cba196f6 100644 --- a/components/script/dom/webidls/PerformanceNavigation.webidl +++ b/components/script/dom/webidls/PerformanceNavigation.webidl @@ -14,5 +14,5 @@ interface PerformanceNavigation { const unsigned short TYPE_RESERVED = 255; readonly attribute unsigned short type; readonly attribute unsigned short redirectCount; - // [Default] object toJSON(); + [Default] object toJSON(); }; diff --git a/components/script/dom/webidls/PerformanceNavigationTiming.webidl b/components/script/dom/webidls/PerformanceNavigationTiming.webidl index 0d2c808105b..5e369b4eb91 100644 --- a/components/script/dom/webidls/PerformanceNavigationTiming.webidl +++ b/components/script/dom/webidls/PerformanceNavigationTiming.webidl @@ -25,7 +25,7 @@ interface PerformanceNavigationTiming : PerformanceResourceTiming { readonly attribute DOMHighResTimeStamp loadEventEnd; readonly attribute NavigationType type; readonly attribute unsigned short redirectCount; - // [Default] object toJSON(); + [Default] object toJSON(); /* Servo-only attribute for measuring when the top-level document (not iframes) is complete. */ [Pref="dom.testperf.enabled"] readonly attribute DOMHighResTimeStamp topLevelDomComplete; diff --git a/components/script/dom/webidls/PerformanceResourceTiming.webidl b/components/script/dom/webidls/PerformanceResourceTiming.webidl index acf1682e800..e4f73197a8c 100644 --- a/components/script/dom/webidls/PerformanceResourceTiming.webidl +++ b/components/script/dom/webidls/PerformanceResourceTiming.webidl @@ -26,5 +26,5 @@ interface PerformanceResourceTiming : PerformanceEntry { /// readonly attribute unsigned long long transferSize; /// readonly attribute unsigned long long encodedBodySize; /// readonly attribute unsigned long long decodedBodySize; - // [Default] object toJSON(); + [Default] object toJSON(); }; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index ac261879079..a79669d6c2e 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -872,19 +872,10 @@ impl WindowMethods for Window { // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ // NavigationTiming/Overview.html#sec-window.performance-attribute fn Performance(&self) -> DomRoot<Performance> { - match self.current_state.get() { - WindowState::Alive => self.performance.or_init(|| { - let global_scope = self.upcast::<GlobalScope>(); - Performance::new(global_scope, self.navigation_start_precise.get()) - }), - WindowState::Zombie => { - // Don't store in Zombie state, - // as clear_js_runtime has already been called, - // and we won't have another opportunity to drop it. - let global_scope = self.upcast::<GlobalScope>(); - Performance::new(global_scope, self.navigation_start_precise.get()) - }, - } + self.performance.or_init(|| { + let global_scope = self.upcast::<GlobalScope>(); + Performance::new(global_scope, self.navigation_start_precise.get()) + }) } // https://html.spec.whatwg.org/multipage/#globaleventhandlers @@ -1308,7 +1299,9 @@ impl Window { self.current_state.set(WindowState::Zombie); *self.js_runtime.borrow_mut() = None; self.window_proxy.set(None); - self.performance.set(None); + if let Some(performance) = self.performance.get() { + performance.clear_and_disable_performance_entry_buffer(); + } self.ignore_all_events(); } diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs index 713546e1129..a1e912252e9 100644 --- a/components/script/dom/xrwebgllayer.rs +++ b/components/script/dom/xrwebgllayer.rs @@ -91,20 +91,25 @@ impl XRWebGLLayer { let cx = global.get_cx(); let old_fbo = context.bound_framebuffer(); + let old_rbo = context.bound_renderbuffer(); let old_texture = context .textures() .active_texture_for_image_target(TexImageTarget::Texture2D); - // Step 8.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with context." + // Step 9.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with + // context and layerInit’s depth, stencil, and alpha values." let framebuffer = context.CreateFramebuffer().ok_or(Error::Operation)?; - // Step 8.3. "Allocate and initialize resources compatible with session’s XR device, + // Step 9.3. "Allocate and initialize resources compatible with session’s XR device, // including GPU accessible memory buffers, as required to support the compositing of layer." // Create a new texture with size given by the session's recommended resolution let texture = context.CreateTexture().ok_or(Error::Operation)?; + let render_buffer = context.CreateRenderbuffer().ok_or(Error::Operation)?; let resolution = session.with_session(|s| s.recommended_framebuffer_resolution()); let mut pixels = CustomAutoRooter::new(None); + let mut clear_bits = constants::COLOR_BUFFER_BIT; + context.BindTexture(constants::TEXTURE_2D, Some(&texture)); let sc = context.TexImage2D( constants::TEXTURE_2D, @@ -128,15 +133,64 @@ impl XRWebGLLayer { 0, ); + // Create backing store and bind a renderbuffer if requested + if init.depth || init.stencil { + let (internal_format, attachment) = if init.depth && init.stencil { + clear_bits |= constants::DEPTH_BUFFER_BIT | constants::STENCIL_BUFFER_BIT; + ( + constants::DEPTH_STENCIL, + constants::DEPTH_STENCIL_ATTACHMENT, + ) + } else if init.depth { + clear_bits |= constants::DEPTH_BUFFER_BIT; + (constants::DEPTH_COMPONENT16, constants::DEPTH_ATTACHMENT) + } else { + clear_bits |= constants::STENCIL_BUFFER_BIT; + (constants::STENCIL_INDEX8, constants::STENCIL_ATTACHMENT) + }; + context.BindRenderbuffer(constants::RENDERBUFFER, Some(&render_buffer)); + context.RenderbufferStorage( + constants::RENDERBUFFER, + internal_format, + resolution.width, + resolution.height, + ); + context.FramebufferRenderbuffer( + constants::FRAMEBUFFER, + attachment, + constants::RENDERBUFFER, + Some(&render_buffer), + ); + } + + context.initialize_framebuffer(clear_bits); + // Restore the WebGL state while complaining about global mutable state + let fb_status = context.CheckFramebufferStatus(constants::FRAMEBUFFER); + let gl_status = context.GetError(); context.BindTexture(constants::TEXTURE_2D, old_texture.as_ref().map(|t| &**t)); context.BindFramebuffer(constants::FRAMEBUFFER, old_fbo.as_ref().map(|f| &**f)); + context.BindRenderbuffer(constants::RENDERBUFFER, old_rbo.as_ref().map(|f| &**f)); - // Step 8.4: "If layer’s resources were unable to be created for any reason, + // Step 9.4: "If layer’s resources were unable to be created for any reason, // throw an OperationError and abort these steps." - sc.or(Err(Error::Operation))?; + if let Err(err) = sc { + error!("TexImage2D error {:?} while creating XR context", err); + return Err(Error::Operation); + } + if fb_status != constants::FRAMEBUFFER_COMPLETE { + error!( + "Framebuffer error {:x} while creating XR context", + fb_status + ); + return Err(Error::Operation); + } + if gl_status != constants::NO_ERROR { + error!("GL error {:x} while creating XR context", gl_status); + return Err(Error::Operation); + } - // Step 9. "Return layer." + // Step 10. "Return layer." Ok(XRWebGLLayer::new( &global.global(), session, |