Auto merge of #27088 - jdm:group, r=ferjm

Implement Console grouping APIs.

These are used by Hubs and other sites we want to run.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #9274
- [x] These changes do not require tests because we can't test stdout content or devtools messages.
This commit is contained in:
bors-servo 2020-07-07 01:24:03 -04:00 committed by GitHub
commit cbbbe16936
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 59 deletions

View file

@ -52,88 +52,83 @@ where
f() 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)] #[allow(non_snake_case)]
impl Console { impl Console {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
pub fn Log(global: &GlobalScope, messages: Vec<DOMString>) { pub fn Log(global: &GlobalScope, messages: Vec<DOMString>) {
with_stderr_lock(move || { console_messages(global, &messages, LogLevel::Log)
for message in messages {
println!("{}", message);
Self::send_to_devtools(global, LogLevel::Log, message);
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console // https://developer.mozilla.org/en-US/docs/Web/API/Console
pub fn Debug(global: &GlobalScope, messages: Vec<DOMString>) { pub fn Debug(global: &GlobalScope, messages: Vec<DOMString>) {
with_stderr_lock(move || { console_messages(global, &messages, LogLevel::Debug)
for message in messages {
println!("{}", message);
Self::send_to_devtools(global, LogLevel::Debug, message);
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/info // https://developer.mozilla.org/en-US/docs/Web/API/Console/info
pub fn Info(global: &GlobalScope, messages: Vec<DOMString>) { pub fn Info(global: &GlobalScope, messages: Vec<DOMString>) {
with_stderr_lock(move || { console_messages(global, &messages, LogLevel::Info)
for message in messages {
println!("{}", message);
Self::send_to_devtools(global, LogLevel::Info, message);
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/warn // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
pub fn Warn(global: &GlobalScope, messages: Vec<DOMString>) { pub fn Warn(global: &GlobalScope, messages: Vec<DOMString>) {
with_stderr_lock(move || { console_messages(global, &messages, LogLevel::Warn)
for message in messages {
println!("{}", message);
Self::send_to_devtools(global, LogLevel::Warn, message);
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/error // https://developer.mozilla.org/en-US/docs/Web/API/Console/error
pub fn Error(global: &GlobalScope, messages: Vec<DOMString>) { pub fn Error(global: &GlobalScope, messages: Vec<DOMString>) {
with_stderr_lock(move || { console_messages(global, &messages, LogLevel::Error)
for message in messages {
println!("{}", message);
Self::send_to_devtools(global, LogLevel::Error, message);
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/assert // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
pub fn Assert(global: &GlobalScope, condition: bool, message: Option<DOMString>) { pub fn Assert(global: &GlobalScope, condition: bool, message: Option<DOMString>) {
with_stderr_lock(move || { if !condition {
if !condition { let message = message.unwrap_or_else(|| DOMString::from("no message"));
let message = message.unwrap_or_else(|| DOMString::from("no message")); let message = DOMString::from(format!("Assertion failed: {}", message));
println!("Assertion failed: {}", message); console_message(global, message, LogLevel::Error)
Self::send_to_devtools(global, LogLevel::Error, message); };
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/time // https://developer.mozilla.org/en-US/docs/Web/API/Console/time
pub fn Time(global: &GlobalScope, label: DOMString) { pub fn Time(global: &GlobalScope, label: DOMString) {
with_stderr_lock(move || { if let Ok(()) = global.time(label.clone()) {
if let Ok(()) = global.time(label.clone()) { let message = DOMString::from(format!("{}: timer started", label));
let message = DOMString::from(format!("{}: timer started", label)); console_message(global, message, LogLevel::Log);
println!("{}", message); }
Self::send_to_devtools(global, LogLevel::Log, message);
}
})
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd // https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd
pub fn TimeEnd(global: &GlobalScope, label: DOMString) { pub fn TimeEnd(global: &GlobalScope, label: DOMString) {
with_stderr_lock(move || { if let Ok(delta) = global.time_end(&label) {
if let Ok(delta) = global.time_end(&label) { let message = DOMString::from(format!("{}: {}ms", label, delta));
let message = DOMString::from(format!("{}: {}ms", label, delta)); console_message(global, message, LogLevel::Log);
println!("{}", message); }
Self::send_to_devtools(global, LogLevel::Log, message); }
};
}) // https://console.spec.whatwg.org/#group
pub fn Group(global: &GlobalScope, messages: Vec<DOMString>) {
global.push_console_group(DOMString::from(messages.join(" ")));
}
// https://console.spec.whatwg.org/#groupcollapsed
pub fn GroupCollapsed(global: &GlobalScope, messages: Vec<DOMString>) {
global.push_console_group(DOMString::from(messages.join(" ")));
}
// https://console.spec.whatwg.org/#groupend
pub fn GroupEnd(global: &GlobalScope) {
global.pop_console_group();
} }
} }

View file

@ -295,6 +295,9 @@ pub struct GlobalScope {
/// currect https state (from previous request) /// currect https state (from previous request)
https_state: Cell<HttpsState>, https_state: Cell<HttpsState>,
/// The stack of active group labels for the Console APIs.
console_group_stack: DomRefCell<Vec<DOMString>>,
} }
/// A wrapper for glue-code between the ipc router and the event-loop. /// A wrapper for glue-code between the ipc router and the event-loop.
@ -744,6 +747,7 @@ impl GlobalScope {
gpu_id_hub, gpu_id_hub,
frozen_supported_performance_entry_types: DomRefCell::new(Default::default()), frozen_supported_performance_entry_types: DomRefCell::new(Default::default()),
https_state: Cell::new(HttpsState::None), 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<Mutex<Identities>> { pub fn wgpu_id_hub(&self) -> Arc<Mutex<Identities>> {
self.gpu_id_hub.clone() self.gpu_id_hub.clone()
} }
pub(crate) fn current_group_label(&self) -> Option<DOMString> {
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 { fn timestamp_in_ms(time: Timespec) -> u64 {

View file

@ -1,25 +1,27 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/*
* References: // https://console.spec.whatwg.org/
* MDN Docs - https://developer.mozilla.org/en-US/docs/Web/API/console
* Draft Spec - https://sideshowbarker.github.io/console-spec/
*
* © Copyright 2014 Mozilla Foundation.
*/
[ClassString="Console", [ClassString="Console",
Exposed=(Window,Worker,Worklet), Exposed=(Window,Worker,Worklet),
ProtoObjectHack] ProtoObjectHack]
namespace console { namespace console {
// These should be DOMString message, DOMString message2, ... // Logging
void log(DOMString... messages); void log(DOMString... messages);
void debug(DOMString... messages); void debug(DOMString... messages);
void info(DOMString... messages); void info(DOMString... messages);
void warn(DOMString... messages); void warn(DOMString... messages);
void error(DOMString... messages); void error(DOMString... messages);
void assert(boolean condition, optional DOMString message); void assert(boolean condition, optional DOMString message);
// Grouping
void group(DOMString... data);
void groupCollapsed(DOMString... data);
void groupEnd();
// Timing
void time(DOMString message); void time(DOMString message);
void timeEnd(DOMString message); void timeEnd(DOMString message);
}; };

View file

@ -90,6 +90,7 @@ WEBIDL_STANDARDS = [
b"//drafts.csswg.org", b"//drafts.csswg.org",
b"//drafts.css-houdini.org", b"//drafts.css-houdini.org",
b"//drafts.fxtf.org", b"//drafts.fxtf.org",
b"//console.spec.whatwg.org",
b"//encoding.spec.whatwg.org", b"//encoding.spec.whatwg.org",
b"//fetch.spec.whatwg.org", b"//fetch.spec.whatwg.org",
b"//html.spec.whatwg.org", b"//html.spec.whatwg.org",