From 2d6e93cc83685a0f6b8efa88bb3bfbb14011701d Mon Sep 17 00:00:00 2001 From: Halid Odat Date: Sun, 17 Apr 2022 08:03:09 +0000 Subject: [PATCH] Fix `Symbol` and `BigInt` constructors (#2032) It changes the following: - `Symbol` object has `[[Construct]]` internal method - Fix and comment step 1 in `Symbol` constructor. - Implement step 1 in `BigInt` constructor. --- boa_engine/src/builtins/bigint/mod.rs | 15 ++++++++++++--- boa_engine/src/builtins/symbol/mod.rs | 11 ++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/boa_engine/src/builtins/bigint/mod.rs b/boa_engine/src/builtins/bigint/mod.rs index 7258d56d1f..dc1ddd3485 100644 --- a/boa_engine/src/builtins/bigint/mod.rs +++ b/boa_engine/src/builtins/bigint/mod.rs @@ -46,12 +46,12 @@ impl BuiltIn for BigInt { ) .name(Self::NAME) .length(Self::LENGTH) + .callable(true) + .constructor(true) .method(Self::to_string, "toString", 0) .method(Self::value_of, "valueOf", 0) .static_method(Self::as_int_n, "asIntN", 2) .static_method(Self::as_uint_n, "asUintN", 2) - .callable(true) - .constructor(true) .property( to_string_tag, Self::NAME, @@ -77,7 +77,16 @@ impl BigInt { /// /// [spec]: https://tc39.es/ecma262/#sec-bigint-objects /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt - fn constructor(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult { + fn constructor( + new_target: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + // 1. If NewTarget is not undefined, throw a TypeError exception. + if !new_target.is_undefined() { + return context.throw_type_error("BigInt is not a constructor"); + } + let value = args.get_or_undefined(0); // 2. Let prim be ? ToPrimitive(value, number). diff --git a/boa_engine/src/builtins/symbol/mod.rs b/boa_engine/src/builtins/symbol/mod.rs index df98d652c1..3dd58078e4 100644 --- a/boa_engine/src/builtins/symbol/mod.rs +++ b/boa_engine/src/builtins/symbol/mod.rs @@ -112,6 +112,8 @@ impl BuiltIn for Symbol { ) .name(Self::NAME) .length(Self::LENGTH) + .callable(true) + .constructor(true) .static_method(Self::for_, "for", 1) .static_method(Self::key_for, "keyFor", 1) .static_property("asyncIterator", symbol_async_iterator, attribute) @@ -135,8 +137,6 @@ impl BuiltIn for Symbol { None, Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE, ) - .callable(true) - .constructor(false) .property( symbol_to_string_tag, Self::NAME, @@ -173,14 +173,19 @@ impl Symbol { args: &[JsValue], context: &mut Context, ) -> JsResult { - if new_target.is_undefined() { + // 1. If NewTarget is not undefined, throw a TypeError exception. + if !new_target.is_undefined() { return context.throw_type_error("Symbol is not a constructor"); } + + // 2. If description is undefined, let descString be undefined. + // 3. Else, let descString be ? ToString(description). let description = match args.get(0) { Some(value) if !value.is_undefined() => Some(value.to_string(context)?), _ => None, }; + // 4. Return a new unique Symbol value whose [[Description]] value is descString. Ok(JsSymbol::new(description).into()) }