Skip to content

Commit

Permalink
Integrate new JsString in the codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Feb 17, 2022
1 parent 113bfa2 commit b069478
Show file tree
Hide file tree
Showing 38 changed files with 1,703 additions and 2,168 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions boa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ unicode-normalization = "0.1.19"
dyn-clone = "1.0.4"
once_cell = "1.9.0"
const-utf16 = "0.2.1"
itertools = "0.10.3"

# Optional Dependencies
measureme = { version = "10.0.0", optional = true }
Expand Down
18 changes: 6 additions & 12 deletions boa/examples/classes.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// NOTE: this example requires the `console` feature to run correctly.

use boa::{
builtins::JsArgs,
class::{Class, ClassBuilder},
gc::{Finalize, Trace},
property::Attribute,
Context, JsResult, JsValue,
Context, JsResult, JsString, JsValue,
};

// We create a new struct that is going to represent a person.
Expand All @@ -17,7 +18,7 @@ use boa::{
#[derive(Debug, Trace, Finalize)]
struct Person {
/// The name of the person.
name: String,
name: JsString,
/// The age of the preson.
age: u32,
}
Expand All @@ -36,7 +37,7 @@ impl Person {
// and print a message to stdout.
println!(
"Hello my name is {}, I'm {} years old",
person.name,
person.name.as_std_string_lossy(),
person.age // Here we can access the native rust fields of the struct.
);
return Ok(JsValue::undefined());
Expand Down Expand Up @@ -64,22 +65,15 @@ impl Class for Person {
// and then we call `to_string()`.
//
// This is equivalent to `String(arg)`.
let name = args
.get(0)
.cloned()
.unwrap_or_default()
.to_string(context)?;
let name = args.get_or_undefined(0).to_string(context)?;
// We get the second argument. If it is unavailable we default to `undefined`,
// and then we call `to_u32`.
//
// This is equivalent to `arg | 0`.
let age = args.get(1).cloned().unwrap_or_default().to_u32(context)?;

// We construct a new native struct `Person`
let person = Person {
name: name.to_string(),
age,
};
let person = Person { name, age };

Ok(person) // and we return it.
}
Expand Down
18 changes: 10 additions & 8 deletions boa/examples/closures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

use boa::{
gc::{Finalize, Trace},
js_string,
object::{FunctionBuilder, JsObject},
property::{Attribute, PropertyDescriptor},
string::utf16,
Context, JsString, JsValue,
};

Expand Down Expand Up @@ -67,17 +69,17 @@ fn main() -> Result<(), JsValue> {
let name = captures.object.get("name", context)?;

// We create a new message from our captured variable.
let message = JsString::concat_array(&[
"message from `",
name.to_string(context)?.as_str(),
"`: ",
captures.greeting.as_str(),
]);
let message = js_string!(
utf16!("message from `"),
&name.to_string(context)?,
utf16!("`: "),
&captures.greeting
);

// We can also mutate the moved data inside the closure.
captures.greeting = format!("{} Hello!", captures.greeting).into();
captures.greeting = js_string!(&captures.greeting, utf16!(" Hello!"));

println!("{message}");
println!("{}", message.as_std_string_lossy());
println!();

// We convert `message` into `Jsvalue` to be able to return it.
Expand Down
15 changes: 8 additions & 7 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ use crate::{
builtins::BuiltIn,
builtins::Number,
context::StandardObjects,
js_string,
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder,
JsObject, ObjectData,
},
property::{Attribute, PropertyDescriptor, PropertyNameKind},
symbol::WellKnownSymbols,
value::{IntegerOrInfinity, JsValue},
BoaProfiler, Context, JsResult, JsString,
BoaProfiler, Context, JsResult,
};
use std::cmp::{max, min, Ordering};

Expand Down Expand Up @@ -739,34 +740,34 @@ impl Array {
// 4. Else, let sep be ? ToString(separator).
let separator = args.get_or_undefined(0);
let separator = if separator.is_undefined() {
JsString::new(",")
js_string!(",")
} else {
separator.to_string(context)?
};

// 5. Let R be the empty String.
let mut r = String::new();
let mut r = vec![];
// 6. Let k be 0.
// 7. Repeat, while k < len,
for k in 0..len {
// a. If k > 0, set R to the string-concatenation of R and sep.
if k > 0 {
r.push_str(&separator);
r.extend_from_slice(&separator);
}
// b. Let element be ? Get(O, ! ToString(𝔽(k))).
let element = o.get(k, context)?;
// c. If element is undefined or null, let next be the empty String; otherwise, let next be ? ToString(element).
let next = if element.is_null_or_undefined() {
JsString::new("")
js_string!()
} else {
element.to_string(context)?
};
// d. Set R to the string-concatenation of R and next.
r.push_str(&next);
r.extend_from_slice(&next);
// e. Set k to k + 1.
}
// 8. Return R.
Ok(r.into())
Ok(js_string!(&r[..]).into())
}

/// `Array.prototype.toString( separator )`
Expand Down
40 changes: 29 additions & 11 deletions boa/src/builtins/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ pub fn formatter(data: &[JsValue], context: &mut Context) -> JsResult<String> {

match data.len() {
0 => Ok(String::new()),
1 => Ok(target.to_string()),
1 => Ok(target.as_std_string_lossy()),
_ => {
let mut formatted = String::new();
let mut arg_index = 1;
let target = target.as_std_string_lossy();
let mut chars = target.chars();
while let Some(c) = chars.next() {
if c == '%' {
Expand Down Expand Up @@ -100,7 +101,8 @@ pub fn formatter(data: &[JsValue], context: &mut Context) -> JsResult<String> {
.get(arg_index)
.cloned()
.unwrap_or_default()
.to_string(context)?;
.to_string(context)?
.as_std_string_lossy();
formatted.push_str(&arg);
arg_index += 1;
}
Expand All @@ -118,7 +120,10 @@ pub fn formatter(data: &[JsValue], context: &mut Context) -> JsResult<String> {

/* unformatted data */
for rest in data.iter().skip(arg_index) {
formatted.push_str(&format!(" {}", rest.to_string(context)?));
formatted.push_str(&format!(
" {}",
rest.to_string(context)?.as_std_string_lossy()
));
}

Ok(formatted)
Expand Down Expand Up @@ -375,7 +380,7 @@ impl Console {
None => "default".into(),
};

let msg = format!("count {label}:");
let msg = format!("count {}:", label.as_std_string_lossy());
let c = context.console_mut().count_map.entry(label).or_insert(0);
*c += 1;

Expand Down Expand Up @@ -406,7 +411,7 @@ impl Console {
context.console_mut().count_map.remove(&label);

logger(
LogMessage::Warn(format!("countReset {label}")),
LogMessage::Warn(format!("countReset {}", label.as_std_string_lossy())),
context.console(),
);

Expand Down Expand Up @@ -439,7 +444,10 @@ impl Console {

if context.console().timer_map.get(&label).is_some() {
logger(
LogMessage::Warn(format!("Timer '{label}' already exist")),
LogMessage::Warn(format!(
"Timer '{}' already exist",
label.as_std_string_lossy()
)),
context.console(),
);
} else {
Expand Down Expand Up @@ -472,14 +480,17 @@ impl Console {

if let Some(t) = context.console().timer_map.get(&label) {
let time = Self::system_time_in_ms();
let mut concat = format!("{label}: {} ms", time - t);
let mut concat = format!("{}: {} ms", label.as_std_string_lossy(), time - t);
for msg in args.iter().skip(1) {
concat = concat + " " + &msg.display().to_string();
}
logger(LogMessage::Log(concat), context.console());
} else {
logger(
LogMessage::Warn(format!("Timer '{label}' doesn't exist")),
LogMessage::Warn(format!(
"Timer '{}' doesn't exist",
label.as_std_string_lossy()
)),
context.console(),
);
}
Expand Down Expand Up @@ -507,15 +518,22 @@ impl Console {
None => "default".into(),
};

if let Some(t) = context.console_mut().timer_map.remove(label.as_str()) {
if let Some(t) = context.console_mut().timer_map.remove(&label) {
let time = Self::system_time_in_ms();
logger(
LogMessage::Info(format!("{label}: {} ms - timer removed", time - t)),
LogMessage::Info(format!(
"{}: {} ms - timer removed",
label.as_std_string_lossy(),
time - t
)),
context.console(),
);
} else {
logger(
LogMessage::Warn(format!("Timer '{label}' doesn't exist")),
LogMessage::Warn(format!(
"Timer '{}' doesn't exist",
label.as_std_string_lossy()
)),
context.console(),
);
}
Expand Down
36 changes: 23 additions & 13 deletions boa/src/builtins/date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
property::Attribute,
string::utf16,
symbol::WellKnownSymbols,
value::{JsValue, PreferredType},
BoaProfiler, Context, JsResult, JsString,
Expand Down Expand Up @@ -403,10 +404,11 @@ impl Date {
let tv = match this_time_value(value, context) {
Ok(dt) => dt.0,
_ => match value.to_primitive(context, PreferredType::Default)? {
JsValue::String(ref str) => match chrono::DateTime::parse_from_rfc3339(str) {
Ok(dt) => Some(dt.naive_utc()),
_ => None,
},
JsValue::String(ref str) => str
.as_std_string()
.ok()
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s.as_str()).ok())
.map(|dt| dt.naive_utc()),
tv => {
let tv = tv.to_number(context)?;
if tv.is_nan() {
Expand Down Expand Up @@ -522,13 +524,15 @@ impl Date {

let hint = args.get_or_undefined(0);

let try_first = match hint.as_string().map(JsString::as_str) {
let try_first = match hint.as_string() {
// 3. If hint is "string" or "default", then
// a. Let tryFirst be string.
Some("string" | "default") => PreferredType::String,
Some(string) if string == utf16!("string") || string == utf16!("default") => {
PreferredType::String
}
// 4. Else if hint is "number", then
// a. Let tryFirst be number.
Some("number") => PreferredType::Number,
Some(number) if number == utf16!("number") => PreferredType::Number,
// 5. Else, throw a TypeError exception.
_ => {
return context
Expand Down Expand Up @@ -1847,14 +1851,20 @@ impl Date {
// This method is implementation-defined and discouraged, so we just require the same format as the string
// constructor.

if args.is_empty() {
let date = if let Some(arg) = args.get(0) {
arg
} else {
return Ok(JsValue::nan());
}
};

match DateTime::parse_from_rfc3339(&args[0].to_string(context)?) {
Ok(v) => Ok(JsValue::new(v.naive_utc().timestamp_millis() as f64)),
_ => Ok(JsValue::new(f64::NAN)),
}
let date = date.to_string(context)?;

Ok(JsValue::new(
date.as_std_string()
.ok()
.and_then(|s| DateTime::parse_from_rfc3339(s.as_str()).ok())
.map_or(f64::NAN, |v| v.naive_utc().timestamp_millis() as f64),
))
}

/// `Date.UTC()`
Expand Down
20 changes: 9 additions & 11 deletions boa/src/builtins/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
use crate::{
builtins::BuiltIn,
context::StandardObjects,
js_string,
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, JsObject, ObjectData,
},
profiler::BoaProfiler,
property::Attribute,
string::utf16,
Context, JsResult, JsValue,
};

Expand Down Expand Up @@ -111,30 +113,26 @@ impl Error {
if !this.is_object() {
return context.throw_type_error("'this' is not an Object");
}
let name = this.get_field("name", context)?;
let name_to_string;
let name = this.get_field(js_string!("name"), context)?;
let name = if name.is_undefined() {
"Error"
js_string!("Error")
} else {
name_to_string = name.to_string(context)?;
name_to_string.as_str()
name.to_string(context)?
};

let message = this.get_field("message", context)?;
let message_to_string;
let message = this.get_field(js_string!("message"), context)?;
let message = if message.is_undefined() {
""
js_string!()
} else {
message_to_string = message.to_string(context)?;
message_to_string.as_str()
message.to_string(context)?
};

if name.is_empty() {
Ok(message.into())
} else if message.is_empty() {
Ok(name.into())
} else {
Ok(format!("{name}: {message}").into())
Ok(js_string!(&name, utf16!(": "), &message).into())
}
}
}
Loading

0 comments on commit b069478

Please sign in to comment.