SymbolPrototype.cpp [plain text]
#include "config.h"
#include "SymbolPrototype.h"
#include "IntegrityInlines.h"
#include "JSCInlines.h"
#include "SymbolObject.h"
namespace JSC {
static JSC_DECLARE_HOST_FUNCTION(symbolProtoGetterDescription);
static JSC_DECLARE_HOST_FUNCTION(symbolProtoFuncToString);
static JSC_DECLARE_HOST_FUNCTION(symbolProtoFuncValueOf);
}
#include "SymbolPrototype.lut.h"
namespace JSC {
const ClassInfo SymbolPrototype::s_info = { "Symbol", &Base::s_info, &symbolPrototypeTable, nullptr, CREATE_METHOD_TABLE(SymbolPrototype) };
SymbolPrototype::SymbolPrototype(VM& vm, Structure* structure)
: Base(vm, structure)
{
}
void SymbolPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
{
Base::finishCreation(vm);
ASSERT(inherits(vm, info()));
JSFunction* toPrimitiveFunction = JSFunction::create(vm, globalObject, 1, "[Symbol.toPrimitive]"_s, symbolProtoFuncValueOf, NoIntrinsic);
putDirectWithoutTransition(vm, vm.propertyNames->toPrimitiveSymbol, toPrimitiveFunction, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
}
static const ASCIILiteral SymbolDescriptionTypeError { "Symbol.prototype.description requires that |this| be a symbol or a symbol object"_s };
static const ASCIILiteral SymbolToStringTypeError { "Symbol.prototype.toString requires that |this| be a symbol or a symbol object"_s };
static const ASCIILiteral SymbolValueOfTypeError { "Symbol.prototype.valueOf requires that |this| be a symbol or a symbol object"_s };
inline Symbol* tryExtractSymbol(VM& vm, JSValue thisValue)
{
if (thisValue.isSymbol())
return asSymbol(thisValue);
if (!thisValue.isObject())
return nullptr;
JSObject* thisObject = asObject(thisValue);
if (!thisObject->inherits<SymbolObject>(vm))
return nullptr;
return asSymbol(jsCast<SymbolObject*>(thisObject)->internalValue());
}
JSC_DEFINE_HOST_FUNCTION(symbolProtoGetterDescription, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
Symbol* symbol = tryExtractSymbol(vm, callFrame->thisValue());
if (!symbol)
return throwVMTypeError(globalObject, scope, SymbolDescriptionTypeError);
scope.release();
Integrity::auditStructureID(vm, symbol->structureID());
const auto description = symbol->description();
return JSValue::encode(description.isNull() ? jsUndefined() : jsString(vm, description));
}
JSC_DEFINE_HOST_FUNCTION(symbolProtoFuncToString, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
Symbol* symbol = tryExtractSymbol(vm, callFrame->thisValue());
if (!symbol)
return throwVMTypeError(globalObject, scope, SymbolToStringTypeError);
Integrity::auditStructureID(vm, symbol->structureID());
RELEASE_AND_RETURN(scope, JSValue::encode(jsNontrivialString(vm, symbol->descriptiveString())));
}
JSC_DEFINE_HOST_FUNCTION(symbolProtoFuncValueOf, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
Symbol* symbol = tryExtractSymbol(vm, callFrame->thisValue());
if (!symbol)
return throwVMTypeError(globalObject, scope, SymbolValueOfTypeError);
Integrity::auditStructureID(vm, symbol->structureID());
RELEASE_AND_RETURN(scope, JSValue::encode(symbol));
}
}