From 7ba514b4168605341d30ab3b60ad87d4ef9b0303 Mon Sep 17 00:00:00 2001 From: Jason Williams Date: Thu, 21 Mar 2019 16:49:36 +0000 Subject: [PATCH] string objects now display their primitive value, to_function() method has been added to value, test added for String() --- Cargo.lock | 28 ++++++++++++++++++++- src/lib/js/console.rs | 57 +++++++++++++++++++++++++++++++++++++------ src/lib/js/string.rs | 8 +++--- src/lib/js/value.rs | 26 ++++++++++++++++++-- tests/string_test.rs | 11 +++++++++ 5 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 tests/string_test.rs diff --git a/Cargo.lock b/Cargo.lock index 822f35cbcc..cb310f1845 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,11 +4,11 @@ name = "Boa" version = "0.1.5" dependencies = [ + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "gc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gc_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -16,6 +16,16 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chrono" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -63,6 +73,19 @@ name = "libc" version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.3.15" @@ -181,6 +204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -188,6 +212,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gc_derive 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2501c15cbaf28a0c2214617aa85351982a933161d7937fe6cd71c855364e0ea6" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" diff --git a/src/lib/js/console.rs b/src/lib/js/console.rs index 4621ee8b8f..50436be7b2 100644 --- a/src/lib/js/console.rs +++ b/src/lib/js/console.rs @@ -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) -> ResultValue { - let args: Vec = FromIterator::from_iter( - args.iter() - .map(|x| from_value::(x.clone()).unwrap()), - ); + let args: Vec = 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::(x.clone()).unwrap(), + }; - println!("{}: {}", Local::now().format("%X").to_string(), args.join(" ")); + // from_value::(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) -> ResultValue { args.iter() .map(|x| from_value::(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 diff --git a/src/lib/js/string.rs b/src/lib/js/string.rs index a165b25fe7..85586afc51 100644 --- a/src/lib/js/string.rs +++ b/src/lib/js/string.rs @@ -23,9 +23,11 @@ pub fn get_string_length(this: Value, _: Value, _: Vec) -> ResultValue { Ok(to_value::(this_str.len() as i32)) } -/// Get the string representation of the error -pub fn to_string(_: Value, _: Value, _: Vec) -> ResultValue { - Ok(to_value(format!("{}", String::from("test")).to_string())) +/// Get the string value to a primitive string +pub fn to_string(this: Value, _: Value, _: Vec) -> ResultValue { + // Get String from String Object and send it back as a new value + let primitive_val = this.get_private_field(String::from("PrimitiveValue")); + Ok(to_value(format!("{}", primitive_val).to_string())) } /// Create a new `String` object diff --git a/src/lib/js/value.rs b/src/lib/js/value.rs index bfc439e208..0d8ed0d01f 100644 --- a/src/lib/js/value.rs +++ b/src/lib/js/value.rs @@ -80,6 +80,14 @@ impl ValueData { } } + /// Returns true if the value is a function + pub fn is_function(&self) -> bool { + match *self { + ValueData::Function(_) => true, + _ => false, + } + } + /// Returns true if the value is undefined pub fn is_undefined(&self) -> bool { match *self { @@ -419,8 +427,9 @@ impl Display for ValueData { _ => v.to_string(), } ), - ValueData::Object(ref v, _) => { + ValueData::Object(ref v, ref p) => { write!(f, "{}", "{")?; + // Print public properties match v.borrow().iter().last() { Some((last_key, _)) => { for (key, val) in v.borrow().iter() { @@ -431,7 +440,20 @@ impl Display for ValueData { } } None => (), - } + }; + + // Print private properties + match p.borrow().iter().last() { + Some((last_key, _)) => { + for (key, val) in p.borrow().iter() { + r#try!(write!(f, "(Private) {}: {}", key, val.value.clone())); + if key != last_key { + r#try!(write!(f, "{}", ", ")); + } + } + } + None => (), + }; write!(f, "{}", "}") } ValueData::Integer(v) => write!(f, "{}", v), diff --git a/tests/string_test.rs b/tests/string_test.rs new file mode 100644 index 0000000000..5f05fa45e6 --- /dev/null +++ b/tests/string_test.rs @@ -0,0 +1,11 @@ +extern crate boa; +use boa::js::string::_create; +use boa::js::object::PROTOTYPE; +use boa::js::value::{ValueData}; + +#[test] +fn check_string_constructor_is_function() { + let global = ValueData::new_obj(None); + let string_constructor = _create(global); + assert_eq!(string_constructor.is_function(), true); +} \ No newline at end of file