diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs index cf6eb1668f8..43b97b3eec6 100644 --- a/components/script/dom/console.rs +++ b/components/script/dom/console.rs @@ -52,88 +52,83 @@ where f() } +fn console_messages(global: &GlobalScope, messages: &[DOMString], level: LogLevel) { + console_message(global, DOMString::from(messages.join(" ")), level) +} + +fn console_message(global: &GlobalScope, message: DOMString, level: LogLevel) { + with_stderr_lock(move || { + let prefix = global.current_group_label().unwrap_or_default(); + let message = DOMString::from(format!("{}{}", prefix, message)); + println!("{}", message); + Console::send_to_devtools(global, level, message); + }) +} + #[allow(non_snake_case)] impl Console { // https://developer.mozilla.org/en-US/docs/Web/API/Console/log pub fn Log(global: &GlobalScope, messages: Vec) { - with_stderr_lock(move || { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Log, message); - } - }) + console_messages(global, &messages, LogLevel::Log) } // https://developer.mozilla.org/en-US/docs/Web/API/Console pub fn Debug(global: &GlobalScope, messages: Vec) { - with_stderr_lock(move || { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Debug, message); - } - }) + console_messages(global, &messages, LogLevel::Debug) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/info pub fn Info(global: &GlobalScope, messages: Vec) { - with_stderr_lock(move || { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Info, message); - } - }) + console_messages(global, &messages, LogLevel::Info) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn pub fn Warn(global: &GlobalScope, messages: Vec) { - with_stderr_lock(move || { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Warn, message); - } - }) + console_messages(global, &messages, LogLevel::Warn) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/error pub fn Error(global: &GlobalScope, messages: Vec) { - with_stderr_lock(move || { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Error, message); - } - }) + console_messages(global, &messages, LogLevel::Error) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert pub fn Assert(global: &GlobalScope, condition: bool, message: Option) { - with_stderr_lock(move || { - if !condition { - let message = message.unwrap_or_else(|| DOMString::from("no message")); - println!("Assertion failed: {}", message); - Self::send_to_devtools(global, LogLevel::Error, message); - } - }) + if !condition { + let message = message.unwrap_or_else(|| DOMString::from("no message")); + let message = DOMString::from(format!("Assertion failed: {}", message)); + console_message(global, message, LogLevel::Error) + }; } // https://developer.mozilla.org/en-US/docs/Web/API/Console/time pub fn Time(global: &GlobalScope, label: DOMString) { - with_stderr_lock(move || { - if let Ok(()) = global.time(label.clone()) { - let message = DOMString::from(format!("{}: timer started", label)); - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Log, message); - } - }) + if let Ok(()) = global.time(label.clone()) { + let message = DOMString::from(format!("{}: timer started", label)); + console_message(global, message, LogLevel::Log); + } } // https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd pub fn TimeEnd(global: &GlobalScope, label: DOMString) { - with_stderr_lock(move || { - if let Ok(delta) = global.time_end(&label) { - let message = DOMString::from(format!("{}: {}ms", label, delta)); - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Log, message); - }; - }) + if let Ok(delta) = global.time_end(&label) { + let message = DOMString::from(format!("{}: {}ms", label, delta)); + console_message(global, message, LogLevel::Log); + } + } + + // https://console.spec.whatwg.org/#group + pub fn Group(global: &GlobalScope, messages: Vec) { + global.push_console_group(DOMString::from(messages.join(" "))); + } + + // https://console.spec.whatwg.org/#groupcollapsed + pub fn GroupCollapsed(global: &GlobalScope, messages: Vec) { + global.push_console_group(DOMString::from(messages.join(" "))); + } + + // https://console.spec.whatwg.org/#groupend + pub fn GroupEnd(global: &GlobalScope) { + global.pop_console_group(); } } diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index b82af6a1394..ea25d443ccb 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -295,6 +295,9 @@ pub struct GlobalScope { /// currect https state (from previous request) https_state: Cell, + + /// The stack of active group labels for the Console APIs. + console_group_stack: DomRefCell>, } /// A wrapper for glue-code between the ipc router and the event-loop. @@ -744,6 +747,7 @@ impl GlobalScope { gpu_id_hub, frozen_supported_performance_entry_types: DomRefCell::new(Default::default()), https_state: Cell::new(HttpsState::None), + console_group_stack: DomRefCell::new(Vec::new()), } } @@ -2934,6 +2938,21 @@ impl GlobalScope { pub fn wgpu_id_hub(&self) -> Arc> { self.gpu_id_hub.clone() } + + pub(crate) fn current_group_label(&self) -> Option { + self.console_group_stack + .borrow() + .last() + .map(|label| DOMString::from(format!("[{}]", label))) + } + + pub(crate) fn push_console_group(&self, group: DOMString) { + self.console_group_stack.borrow_mut().push(group); + } + + pub(crate) fn pop_console_group(&self) { + let _ = self.console_group_stack.borrow_mut().pop(); + } } fn timestamp_in_ms(time: Timespec) -> u64 { diff --git a/components/script/dom/webidls/Console.webidl b/components/script/dom/webidls/Console.webidl index 3a4d34e697f..1e371578ed7 100644 --- a/components/script/dom/webidls/Console.webidl +++ b/components/script/dom/webidls/Console.webidl @@ -1,25 +1,27 @@ /* 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/. */ -/* - * References: - * MDN Docs - https://developer.mozilla.org/en-US/docs/Web/API/console - * Draft Spec - https://sideshowbarker.github.io/console-spec/ - * - * © Copyright 2014 Mozilla Foundation. - */ + +// https://console.spec.whatwg.org/ [ClassString="Console", Exposed=(Window,Worker,Worklet), ProtoObjectHack] namespace console { - // These should be DOMString message, DOMString message2, ... + // Logging void log(DOMString... messages); void debug(DOMString... messages); void info(DOMString... messages); void warn(DOMString... messages); void error(DOMString... messages); void assert(boolean condition, optional DOMString message); + + // Grouping + void group(DOMString... data); + void groupCollapsed(DOMString... data); + void groupEnd(); + + // Timing void time(DOMString message); void timeEnd(DOMString message); }; diff --git a/python/tidy/servo_tidy/tidy.py b/python/tidy/servo_tidy/tidy.py index d8cf1823302..4bcc4f55ca1 100644 --- a/python/tidy/servo_tidy/tidy.py +++ b/python/tidy/servo_tidy/tidy.py @@ -90,6 +90,7 @@ WEBIDL_STANDARDS = [ b"//drafts.csswg.org", b"//drafts.css-houdini.org", b"//drafts.fxtf.org", + b"//console.spec.whatwg.org", b"//encoding.spec.whatwg.org", b"//fetch.spec.whatwg.org", b"//html.spec.whatwg.org",