Browse Source

Fix double conversion to primitive in `ToNumeric` (#2310)

This Pull Request changes the following:

- Fix double conversion to primitive in `ToNumeric`.
- Optimize object check in `ToPrimitive`.
pull/2311/head
raskad 2 years ago
parent
commit
5b5498d1ae
  1. 19
      boa_engine/src/value/mod.rs

19
boa_engine/src/value/mod.rs

@ -352,9 +352,9 @@ impl JsValue {
) -> JsResult<Self> { ) -> JsResult<Self> {
// 1. Assert: input is an ECMAScript language value. (always a value not need to check) // 1. Assert: input is an ECMAScript language value. (always a value not need to check)
// 2. If Type(input) is Object, then // 2. If Type(input) is Object, then
if self.is_object() { if let Some(input) = self.as_object() {
// a. Let exoticToPrim be ? GetMethod(input, @@toPrimitive). // a. Let exoticToPrim be ? GetMethod(input, @@toPrimitive).
let exotic_to_prim = self.get_method(WellKnownSymbols::to_primitive(), context)?; let exotic_to_prim = input.get_method(WellKnownSymbols::to_primitive(), context)?;
// b. If exoticToPrim is not undefined, then // b. If exoticToPrim is not undefined, then
if let Some(exotic_to_prim) = exotic_to_prim { if let Some(exotic_to_prim) = exotic_to_prim {
@ -388,14 +388,12 @@ impl JsValue {
}; };
// d. Return ? OrdinaryToPrimitive(input, preferredType). // d. Return ? OrdinaryToPrimitive(input, preferredType).
self.as_object() return input.ordinary_to_primitive(context, preferred_type);
.expect("self was not an object") }
.ordinary_to_primitive(context, preferred_type)
} else {
// 3. Return input. // 3. Return input.
Ok(self.clone()) Ok(self.clone())
} }
}
/// `7.1.13 ToBigInt ( argument )` /// `7.1.13 ToBigInt ( argument )`
/// ///
@ -565,11 +563,16 @@ impl JsValue {
/// ///
/// See: <https://tc39.es/ecma262/#sec-tonumeric> /// See: <https://tc39.es/ecma262/#sec-tonumeric>
pub fn to_numeric(&self, context: &mut Context) -> JsResult<Numeric> { pub fn to_numeric(&self, context: &mut Context) -> JsResult<Numeric> {
// 1. Let primValue be ? ToPrimitive(value, number).
let primitive = self.to_primitive(context, PreferredType::Number)?; let primitive = self.to_primitive(context, PreferredType::Number)?;
// 2. If primValue is a BigInt, return primValue.
if let Some(bigint) = primitive.as_bigint() { if let Some(bigint) = primitive.as_bigint() {
return Ok(bigint.clone().into()); return Ok(bigint.clone().into());
} }
Ok(self.to_number(context)?.into())
// 3. Return ? ToNumber(primValue).
Ok(primitive.to_number(context)?.into())
} }
/// Converts a value to an integral 32 bit unsigned integer. /// Converts a value to an integral 32 bit unsigned integer.

Loading…
Cancel
Save