123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- /*
- * Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
- * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/Function.h>
- #include <AK/TypeCasts.h>
- #include <LibJS/Runtime/Completion.h>
- #include <LibJS/Runtime/Error.h>
- #include <LibJS/Runtime/GlobalObject.h>
- #include <LibJS/Runtime/Object.h>
- #include <LibJS/Runtime/PrimitiveString.h>
- #include <LibJS/Runtime/SymbolObject.h>
- #include <LibJS/Runtime/SymbolPrototype.h>
- #include <LibJS/Runtime/Value.h>
- namespace JS {
- GC_DEFINE_ALLOCATOR(SymbolPrototype);
- SymbolPrototype::SymbolPrototype(Realm& realm)
- : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype())
- {
- }
- void SymbolPrototype::initialize(Realm& realm)
- {
- auto& vm = this->vm();
- Base::initialize(realm);
- u8 attr = Attribute::Writable | Attribute::Configurable;
- define_native_function(realm, vm.names.toString, to_string, 0, attr);
- define_native_function(realm, vm.names.valueOf, value_of, 0, attr);
- define_native_accessor(realm, vm.names.description, description_getter, {}, Attribute::Configurable);
- define_native_function(realm, vm.well_known_symbol_to_primitive(), symbol_to_primitive, 1, Attribute::Configurable);
- // 20.4.3.6 Symbol.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
- define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Symbol"_string), Attribute::Configurable);
- }
- // thisSymbolValue ( value ), https://tc39.es/ecma262/#thissymbolvalue
- static ThrowCompletionOr<GC::Ref<Symbol>> this_symbol_value(VM& vm, Value value)
- {
- // 1. If value is a Symbol, return value.
- if (value.is_symbol())
- return value.as_symbol();
- // 2. If value is an Object and value has a [[SymbolData]] internal slot, then
- if (value.is_object() && is<SymbolObject>(value.as_object())) {
- // a. Let s be value.[[SymbolData]].
- // b. Assert: s is a Symbol.
- // c. Return s.
- return static_cast<SymbolObject&>(value.as_object()).primitive_symbol();
- }
- // 3. Throw a TypeError exception.
- return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "Symbol");
- }
- // 20.4.3.2 get Symbol.prototype.description, https://tc39.es/ecma262/#sec-symbol.prototype.description
- JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::description_getter)
- {
- // 1. Let s be the this value.
- // 2. Let sym be ? thisSymbolValue(s).
- auto symbol = TRY(this_symbol_value(vm, vm.this_value()));
- // 3. Return sym.[[Description]].
- auto& description = symbol->description();
- return description.has_value()
- ? PrimitiveString::create(vm, *description)
- : js_undefined();
- }
- // 20.4.3.3 Symbol.prototype.toString ( ), https://tc39.es/ecma262/#sec-symbol.prototype.tostring
- JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::to_string)
- {
- // 1. Let sym be ? thisSymbolValue(this value).
- auto symbol = TRY(this_symbol_value(vm, vm.this_value()));
- // 2. Return SymbolDescriptiveString(sym).
- return PrimitiveString::create(vm, TRY_OR_THROW_OOM(vm, symbol->descriptive_string()));
- }
- // 20.4.3.4 Symbol.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-symbol.prototype.valueof
- JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::value_of)
- {
- // 1. Return ? thisSymbolValue(this value).
- return TRY(this_symbol_value(vm, vm.this_value()));
- }
- // 20.4.3.5 Symbol.prototype [ @@toPrimitive ] ( hint ), https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
- JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::symbol_to_primitive)
- {
- // 1. Return ? thisSymbolValue(this value).
- // NOTE: The argument is ignored.
- return TRY(this_symbol_value(vm, vm.this_value()));
- }
- }
|