|
|
|
@ -1,17 +1,54 @@
|
|
|
|
|
use gc::Gc; |
|
|
|
|
use crate::js::function::NativeFunctionData; |
|
|
|
|
use crate::js::object::INSTANCE_PROTOTYPE; |
|
|
|
|
use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData}; |
|
|
|
|
use std::iter::FromIterator; |
|
|
|
|
use chrono::Local; |
|
|
|
|
use gc::Gc; |
|
|
|
|
use std::fmt::Write; |
|
|
|
|
use std::iter::FromIterator; |
|
|
|
|
|
|
|
|
|
/// Print a javascript value to the standard output stream
|
|
|
|
|
/// https://console.spec.whatwg.org/#logger
|
|
|
|
|
pub fn log(_: Value, _: Value, args: Vec<Value>) -> ResultValue { |
|
|
|
|
let args: Vec<String> = FromIterator::from_iter( |
|
|
|
|
args.iter() |
|
|
|
|
.map(|x| from_value::<String>(x.clone()).unwrap()), |
|
|
|
|
); |
|
|
|
|
let args: Vec<String> = FromIterator::from_iter(args.iter().map(|x| { |
|
|
|
|
// Welcome to console.log! The output here is what the developer sees, so its best matching through value types and stringifying to the correct output
|
|
|
|
|
// The input is a vector of Values, we generate a vector of strings then pass them to println!
|
|
|
|
|
return match *x.clone() { |
|
|
|
|
// We don't want to print private (compiler) or prototype properties
|
|
|
|
|
ValueData::Object(ref v, _) => { |
|
|
|
|
// Create empty formatted string to start writing to
|
|
|
|
|
// TODO: once constructor is set on objects, we can do specific output for Strings, Numbers etc
|
|
|
|
|
let mut s = String::new(); |
|
|
|
|
write!(s, "{}", "{").unwrap(); |
|
|
|
|
match v.borrow().iter().last() { |
|
|
|
|
Some((last_key, _)) => { |
|
|
|
|
for (key, val) in v.borrow().iter() { |
|
|
|
|
// Don't print prototype properties
|
|
|
|
|
if key == INSTANCE_PROTOTYPE { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
write!(s, "{}: {}", key, val.value.clone()).unwrap(); |
|
|
|
|
if key != last_key { |
|
|
|
|
write!(s, "{}", ", ").unwrap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
None => (), |
|
|
|
|
} |
|
|
|
|
write!(s, "{}", "}").unwrap(); |
|
|
|
|
s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ => from_value::<String>(x.clone()).unwrap(), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
println!("{}: {}", Local::now().format("%X").to_string(), args.join(" ")); |
|
|
|
|
// from_value::<String>(x.clone()).unwrap()
|
|
|
|
|
})); |
|
|
|
|
|
|
|
|
|
println!( |
|
|
|
|
"{}: {}", |
|
|
|
|
Local::now().format("%X").to_string(), |
|
|
|
|
args.join(" ") |
|
|
|
|
); |
|
|
|
|
Ok(Gc::new(ValueData::Undefined)) |
|
|
|
|
} |
|
|
|
|
/// Print a javascript value to the standard error stream
|
|
|
|
@ -20,7 +57,11 @@ pub fn error(_: Value, _: Value, args: Vec<Value>) -> ResultValue {
|
|
|
|
|
args.iter() |
|
|
|
|
.map(|x| from_value::<String>(x.clone()).unwrap()), |
|
|
|
|
); |
|
|
|
|
println!("{}: {}", Local::now().format("%X").to_string(), args.join(" ")); |
|
|
|
|
println!( |
|
|
|
|
"{}: {}", |
|
|
|
|
Local::now().format("%X").to_string(), |
|
|
|
|
args.join(" ") |
|
|
|
|
); |
|
|
|
|
Ok(Gc::new(ValueData::Undefined)) |
|
|
|
|
} |
|
|
|
|
/// Create a new `console` object
|
|
|
|
|