|
|
|
@ -19,7 +19,6 @@ mod tests;
|
|
|
|
|
use crate::{ |
|
|
|
|
builtins::{ |
|
|
|
|
function::make_builtin_fn, |
|
|
|
|
object::InternalState, |
|
|
|
|
value::{display_obj, RcString, ResultValue, Value}, |
|
|
|
|
}, |
|
|
|
|
exec::Interpreter, |
|
|
|
@ -28,16 +27,6 @@ use crate::{
|
|
|
|
|
use rustc_hash::FxHashMap; |
|
|
|
|
use std::time::SystemTime; |
|
|
|
|
|
|
|
|
|
/// This is the internal console object state.
|
|
|
|
|
#[derive(Debug, Default)] |
|
|
|
|
pub struct ConsoleState { |
|
|
|
|
count_map: FxHashMap<RcString, u32>, |
|
|
|
|
timer_map: FxHashMap<RcString, u128>, |
|
|
|
|
groups: Vec<String>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl InternalState for ConsoleState {} |
|
|
|
|
|
|
|
|
|
/// This represents the different types of log messages.
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub enum LogMessage { |
|
|
|
@ -56,7 +45,7 @@ where
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Helper function for logging messages.
|
|
|
|
|
pub fn logger(msg: LogMessage, console_state: &ConsoleState) { |
|
|
|
|
pub(crate) fn logger(msg: LogMessage, console_state: &Console) { |
|
|
|
|
let indent = 2 * console_state.groups.len(); |
|
|
|
|
|
|
|
|
|
match msg { |
|
|
|
@ -130,432 +119,406 @@ pub fn formatter(data: &[Value], ctx: &mut Interpreter) -> Result<String, Value>
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.assert(condition, ...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript value to the standard error if first argument evaluates to `false` or there
|
|
|
|
|
/// were no arguments.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#assert
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/assert
|
|
|
|
|
pub fn assert(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let assertion = get_arg_at_index::<bool>(args, 0).unwrap_or_default(); |
|
|
|
|
|
|
|
|
|
if !assertion { |
|
|
|
|
let mut args: Vec<Value> = args.iter().skip(1).cloned().collect(); |
|
|
|
|
let message = "Assertion failed".to_string(); |
|
|
|
|
if args.is_empty() { |
|
|
|
|
args.push(Value::from(message)); |
|
|
|
|
} else if !args[0].is_string() { |
|
|
|
|
args.insert(0, Value::from(message)); |
|
|
|
|
} else { |
|
|
|
|
let concat = format!("{}: {}", message, args[0]); |
|
|
|
|
args[0] = Value::from(concat); |
|
|
|
|
/// This is the internal console object state.
|
|
|
|
|
#[derive(Debug, Default)] |
|
|
|
|
pub(crate) struct Console { |
|
|
|
|
count_map: FxHashMap<RcString, u32>, |
|
|
|
|
timer_map: FxHashMap<RcString, u128>, |
|
|
|
|
groups: Vec<String>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Console { |
|
|
|
|
/// The name of the object.
|
|
|
|
|
pub(crate) const NAME: &'static str = "console"; |
|
|
|
|
|
|
|
|
|
/// `console.assert(condition, ...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript value to the standard error if first argument evaluates to `false` or there
|
|
|
|
|
/// were no arguments.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#assert
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/assert
|
|
|
|
|
pub(crate) fn assert(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let assertion = get_arg_at_index::<bool>(args, 0).unwrap_or_default(); |
|
|
|
|
|
|
|
|
|
if !assertion { |
|
|
|
|
let mut args: Vec<Value> = args.iter().skip(1).cloned().collect(); |
|
|
|
|
let message = "Assertion failed".to_string(); |
|
|
|
|
if args.is_empty() { |
|
|
|
|
args.push(Value::from(message)); |
|
|
|
|
} else if !args[0].is_string() { |
|
|
|
|
args.insert(0, Value::from(message)); |
|
|
|
|
} else { |
|
|
|
|
let concat = format!("{}: {}", message, args[0]); |
|
|
|
|
args[0] = Value::from(concat); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
logger(LogMessage::Error(formatter(&args, ctx)?), ctx.console()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Error(formatter(&args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.clear()`
|
|
|
|
|
///
|
|
|
|
|
/// Removes all groups and clears console if possible.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#clear
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/clear
|
|
|
|
|
pub fn clear(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
state.groups.clear(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.clear()`
|
|
|
|
|
///
|
|
|
|
|
/// Removes all groups and clears console if possible.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#clear
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/clear
|
|
|
|
|
pub(crate) fn clear(_: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
ctx.console_mut().groups.clear(); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.debug(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "debug" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#debug
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/debug
|
|
|
|
|
pub fn debug(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Log(formatter(args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.debug(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "debug" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#debug
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/debug
|
|
|
|
|
pub(crate) fn debug(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console()); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.error(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "error" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#error
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/error
|
|
|
|
|
pub fn error(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Error(formatter(args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.error(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "error" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#error
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/error
|
|
|
|
|
pub(crate) fn error(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
logger(LogMessage::Error(formatter(args, ctx)?), ctx.console()); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.info(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "info" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#info
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/info
|
|
|
|
|
pub fn info(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Info(formatter(args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.info(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "info" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#info
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/info
|
|
|
|
|
pub(crate) fn info(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
logger(LogMessage::Info(formatter(args, ctx)?), ctx.console()); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.log(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "log" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#log
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/log
|
|
|
|
|
pub fn log(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Log(formatter(args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.log(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "log" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#log
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/log
|
|
|
|
|
pub(crate) fn log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console()); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.trace(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a stack trace with "trace" logLevel, optionally labelled by data.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#trace
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/trace
|
|
|
|
|
pub fn trace(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
if !args.is_empty() { |
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Log(formatter(args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
|
|
|
|
|
/* TODO: get and print stack trace */ |
|
|
|
|
this.with_internal_state_ref(|state| { |
|
|
|
|
/// `console.trace(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a stack trace with "trace" logLevel, optionally labelled by data.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#trace
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/trace
|
|
|
|
|
pub(crate) fn trace(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
if !args.is_empty() { |
|
|
|
|
logger(LogMessage::Log(formatter(args, ctx)?), ctx.console()); |
|
|
|
|
|
|
|
|
|
/* TODO: get and print stack trace */ |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Log("Not implemented: <stack trace>".to_string()), |
|
|
|
|
state, |
|
|
|
|
ctx.console(), |
|
|
|
|
) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.warn(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "warn" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#warn
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/warn
|
|
|
|
|
pub(crate) fn warn(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
logger(LogMessage::Warn(formatter(args, ctx)?), ctx.console()); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.warn(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints a JavaScript values with "warn" logLevel.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#warn
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/warn
|
|
|
|
|
pub fn warn(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_ref::<_, Result<(), Value>, _>(|state| { |
|
|
|
|
logger(LogMessage::Warn(formatter(args, ctx)?), state); |
|
|
|
|
Ok(()) |
|
|
|
|
})?; |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.count(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints number of times the function was called with that particular label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#count
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/count
|
|
|
|
|
pub(crate) fn count(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// `console.count(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints number of times the function was called with that particular label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#count
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/count
|
|
|
|
|
pub fn count(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
let msg = format!("count {}:", &label); |
|
|
|
|
let c = state.count_map.entry(label).or_insert(0); |
|
|
|
|
let c = ctx.console_mut().count_map.entry(label).or_insert(0); |
|
|
|
|
*c += 1; |
|
|
|
|
|
|
|
|
|
logger(LogMessage::Info(format!("{} {}", msg, c)), state); |
|
|
|
|
}); |
|
|
|
|
logger(LogMessage::Info(format!("{} {}", msg, c)), ctx.console()); |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.countReset(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Resets the counter for label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#countreset
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/countReset
|
|
|
|
|
pub(crate) fn count_reset(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ctx.console_mut().count_map.remove(&label); |
|
|
|
|
|
|
|
|
|
/// `console.countReset(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Resets the counter for label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#countreset
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/countReset
|
|
|
|
|
pub fn count_reset(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
state.count_map.remove(&label); |
|
|
|
|
|
|
|
|
|
logger(LogMessage::Warn(format!("countReset {}", label)), state); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Warn(format!("countReset {}", label)), |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
/// Returns current system time in ms.
|
|
|
|
|
fn system_time_in_ms() -> u128 { |
|
|
|
|
let now = SystemTime::now(); |
|
|
|
|
now.duration_since(SystemTime::UNIX_EPOCH) |
|
|
|
|
.expect("negative duration") |
|
|
|
|
.as_millis() |
|
|
|
|
} |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Returns current system time in ms.
|
|
|
|
|
fn system_time_in_ms() -> u128 { |
|
|
|
|
let now = SystemTime::now(); |
|
|
|
|
now.duration_since(SystemTime::UNIX_EPOCH) |
|
|
|
|
.expect("negative duration") |
|
|
|
|
.as_millis() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.time(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Starts the timer for given label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#time
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/time
|
|
|
|
|
pub fn time(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
if state.timer_map.get(&label).is_some() { |
|
|
|
|
/// `console.time(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Starts the timer for given label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#time
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/time
|
|
|
|
|
pub(crate) fn time(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if ctx.console().timer_map.get(&label).is_some() { |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Warn(format!("Timer '{}' already exist", label)), |
|
|
|
|
state, |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
} else { |
|
|
|
|
let time = system_time_in_ms(); |
|
|
|
|
state.timer_map.insert(label, time); |
|
|
|
|
let time = Self::system_time_in_ms(); |
|
|
|
|
ctx.console_mut().timer_map.insert(label, time); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.timeLog(label, ...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints elapsed time for timer with given label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#timelog
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeLog
|
|
|
|
|
pub fn time_log(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
if let Some(t) = state.timer_map.get(&label) { |
|
|
|
|
let time = system_time_in_ms(); |
|
|
|
|
/// `console.timeLog(label, ...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints elapsed time for timer with given label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#timelog
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeLog
|
|
|
|
|
pub(crate) fn time_log(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if let Some(t) = ctx.console().timer_map.get(&label) { |
|
|
|
|
let time = Self::system_time_in_ms(); |
|
|
|
|
let mut concat = format!("{}: {} ms", label, time - t); |
|
|
|
|
for msg in args.iter().skip(1) { |
|
|
|
|
concat = concat + " " + &msg.to_string(); |
|
|
|
|
} |
|
|
|
|
logger(LogMessage::Log(concat), state); |
|
|
|
|
logger(LogMessage::Log(concat), ctx.console()); |
|
|
|
|
} else { |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Warn(format!("Timer '{}' doesn't exist", label)), |
|
|
|
|
state, |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.timeEnd(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Removes the timer with given label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#timeend
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeEnd
|
|
|
|
|
pub fn time_end(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
if let Some(t) = state.timer_map.remove(label.as_str()) { |
|
|
|
|
let time = system_time_in_ms(); |
|
|
|
|
/// `console.timeEnd(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Removes the timer with given label.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#timeend
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/timeEnd
|
|
|
|
|
pub(crate) fn time_end(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let label = match args.get(0) { |
|
|
|
|
Some(value) => ctx.to_string(value)?, |
|
|
|
|
None => "default".into(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if let Some(t) = ctx.console_mut().timer_map.remove(label.as_str()) { |
|
|
|
|
let time = Self::system_time_in_ms(); |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Info(format!("{}: {} ms - timer removed", label, time - t)), |
|
|
|
|
state, |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
} else { |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Warn(format!("Timer '{}' doesn't exist", label)), |
|
|
|
|
state, |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.group(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Adds new group with name from formatted data to stack.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#group
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/group
|
|
|
|
|
pub fn group(this: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let group_label = formatter(args, ctx)?; |
|
|
|
|
|
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
logger(LogMessage::Info(format!("group: {}", &group_label)), state); |
|
|
|
|
state.groups.push(group_label); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
/// `console.group(...data)`
|
|
|
|
|
///
|
|
|
|
|
/// Adds new group with name from formatted data to stack.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#group
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/group
|
|
|
|
|
pub(crate) fn group(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let group_label = formatter(args, ctx)?; |
|
|
|
|
|
|
|
|
|
/// `console.groupEnd(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Removes the last group from the stack.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#groupend
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/groupEnd
|
|
|
|
|
pub fn group_end(this: &Value, _: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
state.groups.pop(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Info(format!("group: {}", &group_label)), |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
ctx.console_mut().groups.push(group_label); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.dir(item, options)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints info about item
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#dir
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/dir
|
|
|
|
|
pub fn dir(this: &Value, args: &[Value], _: &mut Interpreter) -> ResultValue { |
|
|
|
|
this.with_internal_state_mut(|state: &mut ConsoleState| { |
|
|
|
|
/// `console.groupEnd(label)`
|
|
|
|
|
///
|
|
|
|
|
/// Removes the last group from the stack.
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#groupend
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/groupEnd
|
|
|
|
|
pub(crate) fn group_end(_: &Value, _: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
ctx.console_mut().groups.pop(); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// `console.dir(item, options)`
|
|
|
|
|
///
|
|
|
|
|
/// Prints info about item
|
|
|
|
|
///
|
|
|
|
|
/// More information:
|
|
|
|
|
/// - [MDN documentation][mdn]
|
|
|
|
|
/// - [WHATWG `console` specification][spec]
|
|
|
|
|
///
|
|
|
|
|
/// [spec]: https://console.spec.whatwg.org/#dir
|
|
|
|
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/console/dir
|
|
|
|
|
pub(crate) fn dir(_: &Value, args: &[Value], ctx: &mut Interpreter) -> ResultValue { |
|
|
|
|
let undefined = Value::undefined(); |
|
|
|
|
logger( |
|
|
|
|
LogMessage::Info(display_obj(args.get(0).unwrap_or(&undefined), true)), |
|
|
|
|
state, |
|
|
|
|
ctx.console(), |
|
|
|
|
); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
Ok(Value::undefined()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Create a new `console` object
|
|
|
|
|
pub fn create(global: &Value) -> Value { |
|
|
|
|
let console = Value::new_object(Some(global)); |
|
|
|
|
|
|
|
|
|
make_builtin_fn(assert, "assert", &console, 0); |
|
|
|
|
make_builtin_fn(clear, "clear", &console, 0); |
|
|
|
|
make_builtin_fn(debug, "debug", &console, 0); |
|
|
|
|
make_builtin_fn(error, "error", &console, 0); |
|
|
|
|
make_builtin_fn(info, "info", &console, 0); |
|
|
|
|
make_builtin_fn(log, "log", &console, 0); |
|
|
|
|
make_builtin_fn(trace, "trace", &console, 0); |
|
|
|
|
make_builtin_fn(warn, "warn", &console, 0); |
|
|
|
|
make_builtin_fn(error, "exception", &console, 0); |
|
|
|
|
make_builtin_fn(count, "count", &console, 0); |
|
|
|
|
make_builtin_fn(count_reset, "countReset", &console, 0); |
|
|
|
|
make_builtin_fn(group, "group", &console, 0); |
|
|
|
|
make_builtin_fn(group, "groupCollapsed", &console, 0); |
|
|
|
|
make_builtin_fn(group_end, "groupEnd", &console, 0); |
|
|
|
|
make_builtin_fn(time, "time", &console, 0); |
|
|
|
|
make_builtin_fn(time_log, "timeLog", &console, 0); |
|
|
|
|
make_builtin_fn(time_end, "timeEnd", &console, 0); |
|
|
|
|
make_builtin_fn(dir, "dir", &console, 0); |
|
|
|
|
make_builtin_fn(dir, "dirxml", &console, 0); |
|
|
|
|
|
|
|
|
|
console.set_internal_state(ConsoleState::default()); |
|
|
|
|
|
|
|
|
|
console |
|
|
|
|
} |
|
|
|
|
/// Create a new `console` object
|
|
|
|
|
pub(crate) fn create(global: &Value) -> Value { |
|
|
|
|
let console = Value::new_object(Some(global)); |
|
|
|
|
|
|
|
|
|
make_builtin_fn(Self::assert, "assert", &console, 0); |
|
|
|
|
make_builtin_fn(Self::clear, "clear", &console, 0); |
|
|
|
|
make_builtin_fn(Self::debug, "debug", &console, 0); |
|
|
|
|
make_builtin_fn(Self::error, "error", &console, 0); |
|
|
|
|
make_builtin_fn(Self::info, "info", &console, 0); |
|
|
|
|
make_builtin_fn(Self::log, "log", &console, 0); |
|
|
|
|
make_builtin_fn(Self::trace, "trace", &console, 0); |
|
|
|
|
make_builtin_fn(Self::warn, "warn", &console, 0); |
|
|
|
|
make_builtin_fn(Self::error, "exception", &console, 0); |
|
|
|
|
make_builtin_fn(Self::count, "count", &console, 0); |
|
|
|
|
make_builtin_fn(Self::count_reset, "countReset", &console, 0); |
|
|
|
|
make_builtin_fn(Self::group, "group", &console, 0); |
|
|
|
|
make_builtin_fn(Self::group, "groupCollapsed", &console, 0); |
|
|
|
|
make_builtin_fn(Self::group_end, "groupEnd", &console, 0); |
|
|
|
|
make_builtin_fn(Self::time, "time", &console, 0); |
|
|
|
|
make_builtin_fn(Self::time_log, "timeLog", &console, 0); |
|
|
|
|
make_builtin_fn(Self::time_end, "timeEnd", &console, 0); |
|
|
|
|
make_builtin_fn(Self::dir, "dir", &console, 0); |
|
|
|
|
make_builtin_fn(Self::dir, "dirxml", &console, 0); |
|
|
|
|
|
|
|
|
|
console |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Initialise the `console` object on the global object.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn init(global: &Value) -> (&str, Value) { |
|
|
|
|
let _timer = BoaProfiler::global().start_event("console", "init"); |
|
|
|
|
/// Initialise the `console` object on the global object.
|
|
|
|
|
#[inline] |
|
|
|
|
pub(crate) fn init(global: &Value) -> (&str, Value) { |
|
|
|
|
let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); |
|
|
|
|
|
|
|
|
|
("console", create(global)) |
|
|
|
|
(Self::NAME, Self::create(global)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|