From ca0eaeadb286b5869fe7ae090e0fa3c47b980c13 Mon Sep 17 00:00:00 2001 From: HalidOdat Date: Tue, 7 Jul 2020 16:17:13 +0200 Subject: [PATCH] Removed `console`s dependency of `InternalState` (#544) --- boa/src/builtins/console/mod.rs | 721 +++++++++++++++----------------- boa/src/builtins/mod.rs | 3 +- boa/src/exec/mod.rs | 16 +- boa_cli/src/main.rs | 3 +- 4 files changed, 360 insertions(+), 383 deletions(-) diff --git a/boa/src/builtins/console/mod.rs b/boa/src/builtins/console/mod.rs index 056e5b7281b..4414853ac84 100644 --- a/boa/src/builtins/console/mod.rs +++ b/boa/src/builtins/console/mod.rs @@ -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, - timer_map: FxHashMap, - groups: Vec, -} - -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 } } -/// `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::(args, 0).unwrap_or_default(); - - if !assertion { - let mut args: Vec = 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, + timer_map: FxHashMap, + groups: Vec, +} + +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::(args, 0).unwrap_or_default(); + + if !assertion { + let mut args: Vec = 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: ".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)) + } } diff --git a/boa/src/builtins/mod.rs b/boa/src/builtins/mod.rs index 46ba43b777d..d5a4f9cf41c 100644 --- a/boa/src/builtins/mod.rs +++ b/boa/src/builtins/mod.rs @@ -24,6 +24,7 @@ pub(crate) use self::{ array::Array, bigint::BigInt, boolean::Boolean, + console::Console, error::{Error, RangeError, ReferenceError, SyntaxError, TypeError}, global_this::GlobalThis, infinity::Infinity, @@ -54,7 +55,7 @@ pub fn init(global: &Value) { RegExp::init, String::init, Symbol::init, - console::init, + Console::init, // Global error types. Error::init, RangeError::init, diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index 479ebf775a9..fc244830e76 100644 --- a/boa/src/exec/mod.rs +++ b/boa/src/exec/mod.rs @@ -29,7 +29,7 @@ use crate::{ object::{Object, ObjectData, INSTANCE_PROTOTYPE, PROTOTYPE}, property::Property, value::{RcBigInt, RcString, ResultValue, Type, Value}, - BigInt, Number, + BigInt, Console, Number, }, realm::Realm, syntax::ast::{ @@ -70,6 +70,9 @@ pub struct Interpreter { /// This is for generating an unique internal `Symbol` hash. symbol_count: u32, + + /// console object state. + console: Console, } impl Interpreter { @@ -79,6 +82,7 @@ impl Interpreter { state: InterpreterState::Executing, realm, symbol_count: 0, + console: Console::default(), } } @@ -612,6 +616,16 @@ impl Interpreter { Ok(value) } } + + /// A helper function for getting a immutable reference to the `console` object. + pub(crate) fn console(&self) -> &Console { + &self.console + } + + /// A helper function for getting a mutable reference to the `console` object. + pub(crate) fn console_mut(&mut self) -> &mut Console { + &mut self.console + } } impl Executable for Node { diff --git a/boa_cli/src/main.rs b/boa_cli/src/main.rs index a24c941a39c..e3b44cf3e97 100644 --- a/boa_cli/src/main.rs +++ b/boa_cli/src/main.rs @@ -26,7 +26,6 @@ )] use boa::{ - builtins::console::log, exec::Interpreter, forward_val, realm::Realm, @@ -175,7 +174,7 @@ fn dump(src: &str, args: &Opt) -> Result<(), String> { pub fn main() -> Result<(), std::io::Error> { let args = Opt::from_args(); - let realm = Realm::create().register_global_func("print", log); + let realm = Realm::create(); let mut engine = Interpreter::new(realm);