diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index d8eae6f3a7d..3075073c04a 100644 --- a/boa/src/builtins/array/mod.rs +++ b/boa/src/builtins/array/mod.rs @@ -25,7 +25,6 @@ use crate::{ use std::{ borrow::Borrow, cmp::{max, min}, - ops::Deref, }; /// JavaScript `Array` built-in implementation. @@ -33,6 +32,12 @@ use std::{ pub(crate) struct Array; impl Array { + /// The name of the object. + pub(crate) const NAME: &'static str = "Array"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// Creates a new `Array` instance. pub(crate) fn new_array(interpreter: &Interpreter) -> ResultValue { let array = Value::new_object(Some( @@ -167,25 +172,9 @@ impl Array { args: &[Value], _interpreter: &mut Interpreter, ) -> ResultValue { - let value_true = Value::boolean(true); - let value_false = Value::boolean(false); - - match args.get(0) { - Some(arg) => { - match arg.data() { - // 1. - ValueData::Object(ref obj) => { - // 2. - if let ObjectData::Array = (*obj).deref().borrow().data { - return Ok(value_true); - } - Ok(value_false) - } - // 3. - _ => Ok(value_false), - } - } - None => Ok(value_false), + match args.get(0).and_then(|x| x.as_object()) { + Some(object) => Ok(Value::from(object.is_array())), + None => Ok(Value::from(false)), } } @@ -1031,7 +1020,14 @@ impl Array { make_builtin_fn(Self::slice, "slice", &prototype, 2); make_builtin_fn(Self::some, "some", &prototype, 2); - let array = make_constructor_fn("Array", 1, Self::make_array, global, prototype, true); + let array = make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_array, + global, + prototype, + true, + ); // Static Methods make_builtin_fn(Self::is_array, "isArray", &array, 1); @@ -1042,8 +1038,8 @@ impl Array { /// Initialise the `Array` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("array", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("Array", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/bigint/mod.rs b/boa/src/builtins/bigint/mod.rs index afbe6a303c5..dbe456c911f 100644 --- a/boa/src/builtins/bigint/mod.rs +++ b/boa/src/builtins/bigint/mod.rs @@ -44,6 +44,12 @@ mod tests; pub struct BigInt(num_bigint::BigInt); impl BigInt { + /// The name of the object. + pub(crate) const NAME: &'static str = "BigInt"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// The abstract operation thisBigIntValue takes argument value. /// /// The phrase “this BigInt value” within the specification of a method refers to the @@ -213,7 +219,14 @@ impl BigInt { make_builtin_fn(Self::to_string, "toString", &prototype, 1); make_builtin_fn(Self::value_of, "valueOf", &prototype, 0); - let big_int = make_constructor_fn("BigInt", 1, Self::make_bigint, global, prototype, false); + let big_int = make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_bigint, + global, + prototype, + false, + ); make_builtin_fn(Self::as_int_n, "asIntN", &big_int, 2); make_builtin_fn(Self::as_uint_n, "asUintN", &big_int, 2); @@ -224,9 +237,9 @@ impl BigInt { /// Initialise the `BigInt` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("bigint", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("BigInt", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/boolean/mod.rs b/boa/src/builtins/boolean/mod.rs index c87d681c46e..6f384da7ecf 100644 --- a/boa/src/builtins/boolean/mod.rs +++ b/boa/src/builtins/boolean/mod.rs @@ -27,6 +27,12 @@ use crate::{ pub(crate) struct Boolean; impl Boolean { + /// The name of the object. + pub(crate) const NAME: &'static str = "Boolean"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// An Utility function used to get the internal [[BooleanData]]. /// /// More information: @@ -101,8 +107,8 @@ impl Boolean { make_builtin_fn(Self::value_of, "valueOf", &prototype, 0); make_constructor_fn( - "Boolean", - 1, + Self::NAME, + Self::LENGTH, Self::construct_boolean, global, prototype, @@ -113,8 +119,8 @@ impl Boolean { /// Initialise the `Boolean` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("boolean", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("Boolean", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/error/mod.rs b/boa/src/builtins/error/mod.rs index 409ebdfd53b..49d3cafad2f 100644 --- a/boa/src/builtins/error/mod.rs +++ b/boa/src/builtins/error/mod.rs @@ -35,6 +35,12 @@ pub(crate) use self::range::RangeError; pub(crate) struct Error; impl Error { + /// The name of the object. + pub(crate) const NAME: &'static str = "Error"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// Create a new error object. pub(crate) fn make_error(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { if !args.is_empty() { @@ -77,13 +83,20 @@ impl Error { make_builtin_fn(Self::to_string, "toString", &prototype, 0); - make_constructor_fn("Error", 1, Self::make_error, global, prototype, true) + make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_error, + global, + prototype, + true, + ) } /// Initialise the global object with the `Error` object. pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("error", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("Error", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/error/range.rs b/boa/src/builtins/error/range.rs index 924d93ac0cf..e45ae14a830 100644 --- a/boa/src/builtins/error/range.rs +++ b/boa/src/builtins/error/range.rs @@ -25,6 +25,12 @@ use crate::{ pub(crate) struct RangeError; impl RangeError { + /// The name of the object. + pub(crate) const NAME: &'static str = "RangeError"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// Create a new error object. pub(crate) fn make_error(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { if !args.is_empty() { @@ -67,13 +73,20 @@ impl RangeError { make_builtin_fn(Self::to_string, "toString", &prototype, 0); - make_constructor_fn("RangeError", 1, Self::make_error, global, prototype, true) + make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_error, + global, + prototype, + true, + ) } /// Initialise the global object with the `RangeError` object. pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("rangeerror", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("RangeError", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/error/type.rs b/boa/src/builtins/error/type.rs index 6122185f659..d61afae6d0a 100644 --- a/boa/src/builtins/error/type.rs +++ b/boa/src/builtins/error/type.rs @@ -31,6 +31,12 @@ use crate::{ pub(crate) struct TypeError; impl TypeError { + /// The name of the object. + pub(crate) const NAME: &'static str = "TypeError"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// Create a new error object. pub(crate) fn make_error(this: &mut Value, args: &[Value], _: &mut Interpreter) -> ResultValue { if !args.is_empty() { @@ -74,13 +80,20 @@ impl TypeError { make_builtin_fn(Self::to_string, "toString", &prototype, 0); - make_constructor_fn("TypeError", 1, Self::make_error, global, prototype, true) + make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_error, + global, + prototype, + true, + ) } /// Initialise the global object with the `RangeError` object. pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("typeerror", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("TypeError", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/json/mod.rs b/boa/src/builtins/json/mod.rs index db3262d6de7..60f9231ef9f 100644 --- a/boa/src/builtins/json/mod.rs +++ b/boa/src/builtins/json/mod.rs @@ -29,6 +29,9 @@ mod tests; pub(crate) struct Json; impl Json { + /// The name of the object. + pub(crate) const NAME: &'static str = "JSON"; + /// `JSON.parse( text[, reviver] )` /// /// This `JSON` method parses a JSON string, constructing the JavaScript value or object described by the string. @@ -178,8 +181,8 @@ impl Json { /// Initialise the `JSON` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("json", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("JSON", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/math/mod.rs b/boa/src/builtins/math/mod.rs index babb9a197a1..08db86df1d4 100644 --- a/boa/src/builtins/math/mod.rs +++ b/boa/src/builtins/math/mod.rs @@ -28,6 +28,9 @@ mod tests; pub(crate) struct Math; impl Math { + /// The name of the object. + pub(crate) const NAME: &'static str = "Math"; + /// Get the absolute value of a number. /// /// More information: @@ -561,8 +564,8 @@ impl Math { /// Initialise the `Math` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("math", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("Math", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/nan/mod.rs b/boa/src/builtins/nan/mod.rs index a797e13e41d..1e046499e46 100644 --- a/boa/src/builtins/nan/mod.rs +++ b/boa/src/builtins/nan/mod.rs @@ -20,11 +20,14 @@ use crate::{builtins::value::Value, BoaProfiler}; pub(crate) struct NaN; impl NaN { + /// The name of the property. + pub(crate) const NAME: &'static str = "NaN"; + /// Initialize the `NaN` property on the global object. #[inline] pub(crate) fn init(_: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("NaN", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("NaN", Value::from(f64::NAN)) + (Self::NAME, Value::from(f64::NAN)) } } diff --git a/boa/src/builtins/number/mod.rs b/boa/src/builtins/number/mod.rs index c8ec8ba7c91..e7cf809820f 100644 --- a/boa/src/builtins/number/mod.rs +++ b/boa/src/builtins/number/mod.rs @@ -40,6 +40,12 @@ const PARSE_INT_MAX_ARG_COUNT: usize = 2; const PARSE_FLOAT_MAX_ARG_COUNT: usize = 1; impl Number { + /// The name of the object. + pub(crate) const NAME: &'static str = "Number"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + /// This function returns a `Result` of the number `Value`. /// /// If the `Value` is a `Number` primitive of `Number` object the number is returned. @@ -546,7 +552,14 @@ impl Number { PARSE_FLOAT_MAX_ARG_COUNT as i32, ); - let number = make_constructor_fn("Number", 1, Self::make_number, global, prototype, true); + let number = make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_number, + global, + prototype, + true, + ); // Constants from: // https://tc39.es/ecma262/#sec-properties-of-the-number-constructor @@ -568,9 +581,9 @@ impl Number { /// Initialise the `Number` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("number", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("Number", Self::create(global)) + (Self::NAME, Self::create(global)) } /// The abstract operation Number::equal takes arguments diff --git a/boa/src/builtins/object/internal_methods.rs b/boa/src/builtins/object/internal_methods.rs index be47ba6ac99..9c809e829b2 100644 --- a/boa/src/builtins/object/internal_methods.rs +++ b/boa/src/builtins/object/internal_methods.rs @@ -392,10 +392,11 @@ impl Object { #[inline] pub fn get_internal_slot(&self, name: &str) -> Value { let _timer = BoaProfiler::global().start_event("Object::get_internal_slot", "object"); - match self.internal_slots.get(name) { - Some(v) => v.clone(), - None => Value::null(), - } + + self.internal_slots() + .get(name) + .cloned() + .unwrap_or_else(Value::null) } /// Helper function to set an internal slot. @@ -406,7 +407,7 @@ impl Object { /// Helper function for property insertion. #[inline] - pub fn insert_property(&mut self, name: N, p: Property) + pub(crate) fn insert_property(&mut self, name: N, p: Property) where N: Into, { @@ -415,12 +416,16 @@ impl Object { /// Helper function for property removal. #[inline] - pub fn remove_property(&mut self, name: &str) { + pub(crate) fn remove_property(&mut self, name: &str) { self.properties.remove(name); } + /// Inserts a field in the object `properties` without checking if it's writable. + /// + /// If a field was already in the object with the same name that a `Some` is returned + /// with that field, otherwise None is retuned. #[inline] - pub fn insert_field(&mut self, name: N, value: Value) -> Option + pub(crate) fn insert_field(&mut self, name: N, value: Value) -> Option where N: Into, { @@ -434,6 +439,10 @@ impl Object { ) } + /// This function returns an Optional reference value to the objects field. + /// + /// if it exist `Some` is returned with a reference to that fields value. + /// Otherwise `None` is retuned. #[inline] pub fn get_field(&self, name: &str) -> Option<&Value> { self.properties.get(name).and_then(|x| x.value.as_ref()) diff --git a/boa/src/builtins/object/mod.rs b/boa/src/builtins/object/mod.rs index 5a2d60d043c..24bdf573bac 100644 --- a/boa/src/builtins/object/mod.rs +++ b/boa/src/builtins/object/mod.rs @@ -252,9 +252,9 @@ impl Object { } #[inline] - pub fn as_string(&self) -> Option<&String> { + pub fn as_string(&self) -> Option<&str> { match self.data { - ObjectData::String(ref string) => Some(string), + ObjectData::String(ref string) => Some(string.as_str()), _ => None, } } diff --git a/boa/src/builtins/regexp/mod.rs b/boa/src/builtins/regexp/mod.rs index 4c5d0faf189..569e6dd56af 100644 --- a/boa/src/builtins/regexp/mod.rs +++ b/boa/src/builtins/regexp/mod.rs @@ -61,6 +61,12 @@ pub(crate) struct RegExp { impl InternalState for RegExp {} impl RegExp { + /// The name of the object. + pub(crate) const NAME: &'static str = "RegExp"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 2; + /// Create a new `RegExp` pub(crate) fn make_regexp( this: &mut Value, @@ -487,14 +493,21 @@ impl RegExp { make_builtin_fn(Self::get_sticky, "sticky", &prototype, 0); make_builtin_fn(Self::get_unicode, "unicode", &prototype, 0); - make_constructor_fn("RegExp", 1, Self::make_regexp, global, prototype, true) + make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_regexp, + global, + prototype, + true, + ) } /// Initialise the `RegExp` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("regexp", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("RegExp", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index 860b101fcb2..d3da1ed3e7f 100644 --- a/boa/src/builtins/string/mod.rs +++ b/boa/src/builtins/string/mod.rs @@ -36,13 +36,19 @@ use std::{ pub(crate) struct String; impl String { + /// The name of the object. + pub(crate) const NAME: &'static str = "String"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 1; + fn this_string_value(this: &Value, ctx: &mut Interpreter) -> Result { match this.data() { ValueData::String(ref string) => return Ok(string.clone()), ValueData::Object(ref object) => { let object = object.borrow(); if let Some(string) = object.as_string() { - return Ok(string.clone()); + return Ok(string.to_owned()); } } _ => {} @@ -1082,14 +1088,21 @@ impl String { make_builtin_fn(Self::match_all, "matchAll", &prototype, 1); make_builtin_fn(Self::replace, "replace", &prototype, 2); - make_constructor_fn("String", 1, Self::make_string, global, prototype, true) + make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::make_string, + global, + prototype, + true, + ) } /// Initialise the `String` object on the global object. #[inline] pub(crate) fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("string", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("String", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/symbol/mod.rs b/boa/src/builtins/symbol/mod.rs index ed6c3ed47ed..deb1d3553d5 100644 --- a/boa/src/builtins/symbol/mod.rs +++ b/boa/src/builtins/symbol/mod.rs @@ -30,6 +30,12 @@ use gc::{Finalize, Trace}; pub struct Symbol(Option>, u32); impl Symbol { + /// The name of the object. + pub(crate) const NAME: &'static str = "Symbol"; + + /// The amount of arguments this function object takes. + pub(crate) const LENGTH: i32 = 0; + /// Returns the `Symbol`s description. pub fn description(&self) -> Option<&str> { self.0.as_deref() @@ -101,14 +107,21 @@ impl Symbol { let prototype = Value::new_object(Some(global)); make_builtin_fn(Self::to_string, "toString", &prototype, 0); - make_constructor_fn("Symbol", 1, Self::call, global, prototype, false) + make_constructor_fn( + Self::NAME, + Self::LENGTH, + Self::call, + global, + prototype, + false, + ) } /// Initialise the `Symbol` object on the global object. #[inline] pub fn init(global: &Value) -> (&str, Value) { - let _timer = BoaProfiler::global().start_event("symbol", "init"); + let _timer = BoaProfiler::global().start_event(Self::NAME, "init"); - ("Symbol", Self::create(global)) + (Self::NAME, Self::create(global)) } } diff --git a/boa/src/builtins/value/display.rs b/boa/src/builtins/value/display.rs index 39f1a256038..fef09251920 100644 --- a/boa/src/builtins/value/display.rs +++ b/boa/src/builtins/value/display.rs @@ -112,7 +112,7 @@ pub(crate) fn log_string_from(x: &ValueData, print_internals: bool) -> String { } } ValueData::Symbol(ref symbol) => match symbol.description() { - Some(description) => format!("Symbol({})", description), + Some(ref desc) => format!("Symbol({})", desc), None => String::from("Symbol()"), }, _ => format!("{}", x), diff --git a/boa/src/builtins/value/hash.rs b/boa/src/builtins/value/hash.rs index c32f9afc7dd..2ddc7dc3eb0 100644 --- a/boa/src/builtins/value/hash.rs +++ b/boa/src/builtins/value/hash.rs @@ -11,12 +11,13 @@ impl PartialEq for Value { impl Eq for Value {} -#[derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] struct UndefinedHashable; -#[derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] struct NullHashable; +#[derive(Debug, Clone, Copy)] struct RationalHashable(f64); impl PartialEq for RationalHashable { diff --git a/boa/src/builtins/value/mod.rs b/boa/src/builtins/value/mod.rs index 546901fee2b..b69541374c2 100644 --- a/boa/src/builtins/value/mod.rs +++ b/boa/src/builtins/value/mod.rs @@ -418,7 +418,7 @@ impl ValueData { /// Returns true if the value is true. /// - /// [toBoolean](https://tc39.es/ecma262/#sec-toboolean + /// [toBoolean](https://tc39.es/ecma262/#sec-toboolean) pub fn is_true(&self) -> bool { match *self { Self::Object(_) => true, @@ -515,10 +515,10 @@ impl ValueData { let object = object.borrow(); match object.properties().get(field) { Some(value) => Some(value.clone()), - None => match object.internal_slots().get(INSTANCE_PROTOTYPE) { - Some(value) => value.get_property(field), - None => None, - }, + None => object + .internal_slots() + .get(INSTANCE_PROTOTYPE) + .and_then(|value| value.get_property(field)), } } _ => None, @@ -555,17 +555,9 @@ impl ValueData { pub fn get_internal_slot(&self, field: &str) -> Value { let _timer = BoaProfiler::global().start_event("Value::get_internal_slot", "value"); - let property = self - .as_object() - .and_then(|x| match x.internal_slots().get(field) { - Some(value) => Some(value.clone()), - None => None, - }); - - match property { - Some(value) => value, - None => Value::undefined(), - } + self.as_object() + .and_then(|x| x.internal_slots().get(field).cloned()) + .unwrap_or_else(Value::undefined) } /// Resolve the property in the object and get its value, or undefined if this is not an object or the field doesn't exist @@ -608,18 +600,13 @@ impl ValueData { /// Check whether an object has an internal state set. pub fn has_internal_state(&self) -> bool { - match self.as_object() { - Some(object) => object.state().is_some(), - None => false, - } + matches!(self.as_object(), Some(object) if object.state().is_some()) } /// Get the internal state of an object. pub fn get_internal_state(&self) -> Option { - match self.as_object() { - Some(object) => object.state().clone(), - None => None, - } + self.as_object() + .and_then(|object| object.state().as_ref().cloned()) } /// Run a function with a reference to the internal state. diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index f45a692063f..034f9f9e3eb 100644 --- a/boa/src/exec/mod.rs +++ b/boa/src/exec/mod.rs @@ -89,6 +89,9 @@ impl Interpreter { &mut self.realm } + /// Generates a new `Symbol` internal hash. + /// + /// This currently is an incremented value. pub(crate) fn generate_hash(&mut self) -> u32 { let hash = self.symbol_count; self.symbol_count += 1; @@ -271,10 +274,8 @@ impl Interpreter { ValueData::Null => Ok(0.0), ValueData::Undefined => Ok(f64::NAN), ValueData::Boolean(b) => Ok(if b { 1.0 } else { 0.0 }), - ValueData::String(ref string) => match string.parse() { - Ok(number) => Ok(number), - Err(_) => Ok(f64::NAN), - }, // this is probably not 100% correct, see https://tc39.es/ecma262/#sec-tonumber-applied-to-the-string-type + // TODO: this is probably not 100% correct, see https://tc39.es/ecma262/#sec-tonumber-applied-to-the-string-type + ValueData::String(ref string) => Ok(string.parse().unwrap_or(f64::NAN)), ValueData::Rational(number) => Ok(number), ValueData::Integer(integer) => Ok(f64::from(integer)), ValueData::Symbol(_) => {