[JSC] Add Symbol.prototype.description getter
[WebKit-https.git] / Source / JavaScriptCore / runtime / SymbolPrototype.cpp
1 /*
2  * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "SymbolPrototype.h"
29
30 #include "Error.h"
31 #include "JSCInlines.h"
32 #include "JSString.h"
33 #include "SymbolObject.h"
34
35 namespace JSC {
36
37 static EncodedJSValue JSC_HOST_CALL symbolProtoGetterDescription(ExecState*);
38 static EncodedJSValue JSC_HOST_CALL symbolProtoFuncToString(ExecState*);
39 static EncodedJSValue JSC_HOST_CALL symbolProtoFuncValueOf(ExecState*);
40
41 }
42
43 #include "SymbolPrototype.lut.h"
44
45 namespace JSC {
46
47 const ClassInfo SymbolPrototype::s_info = { "Symbol", &Base::s_info, &symbolPrototypeTable, nullptr, CREATE_METHOD_TABLE(SymbolPrototype) };
48
49 /* Source for SymbolPrototype.lut.h
50 @begin symbolPrototypeTable
51   description       symbolProtoGetterDescription    DontEnum|Accessor 0
52   toString          symbolProtoFuncToString         DontEnum|Function 0
53   valueOf           symbolProtoFuncValueOf          DontEnum|Function 0
54 @end
55 */
56
57 SymbolPrototype::SymbolPrototype(VM& vm, Structure* structure)
58     : Base(vm, structure)
59 {
60 }
61
62 void SymbolPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
63 {
64     Base::finishCreation(vm);
65     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Symbol"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
66     ASSERT(inherits(vm, info()));
67
68     JSFunction* toPrimitiveFunction = JSFunction::create(vm, globalObject, 1, ASCIILiteral("[Symbol.toPrimitive]"), symbolProtoFuncValueOf, NoIntrinsic);
69     putDirectWithoutTransition(vm, vm.propertyNames->toPrimitiveSymbol, toPrimitiveFunction, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
70 }
71
72 // ------------------------------ Functions ---------------------------
73
74 static const char* SymbolDescriptionTypeError = "Symbol.prototype.description requires that |this| be a symbol or a symbol object";
75 static const char* SymbolToStringTypeError = "Symbol.prototype.toString requires that |this| be a symbol or a symbol object";
76 static const char* SymbolValueOfTypeError = "Symbol.prototype.valueOf requires that |this| be a symbol or a symbol object";
77
78 inline Symbol* tryExtractSymbol(VM& vm, JSValue thisValue)
79 {
80     if (thisValue.isSymbol())
81         return asSymbol(thisValue);
82
83     if (!thisValue.isObject())
84         return nullptr;
85     JSObject* thisObject = asObject(thisValue);
86     if (!thisObject->inherits<SymbolObject>(vm))
87         return nullptr;
88     return asSymbol(jsCast<SymbolObject*>(thisObject)->internalValue());
89 }
90
91 EncodedJSValue JSC_HOST_CALL symbolProtoGetterDescription(ExecState* exec)
92 {
93     VM& vm = exec->vm();
94     auto scope = DECLARE_THROW_SCOPE(vm);
95
96     Symbol* symbol = tryExtractSymbol(vm, exec->thisValue());
97     if (!symbol)
98         return throwVMTypeError(exec, scope, SymbolDescriptionTypeError);
99     scope.release();
100     return JSValue::encode(jsString(&vm, symbol->description()));
101 }
102
103 EncodedJSValue JSC_HOST_CALL symbolProtoFuncToString(ExecState* exec)
104 {
105     VM& vm = exec->vm();
106     auto scope = DECLARE_THROW_SCOPE(vm);
107
108     Symbol* symbol = tryExtractSymbol(vm, exec->thisValue());
109     if (!symbol)
110         return throwVMTypeError(exec, scope, SymbolToStringTypeError);
111     scope.release();
112     return JSValue::encode(jsNontrivialString(&vm, symbol->descriptiveString()));
113 }
114
115 EncodedJSValue JSC_HOST_CALL symbolProtoFuncValueOf(ExecState* exec)
116 {
117     VM& vm = exec->vm();
118     auto scope = DECLARE_THROW_SCOPE(vm);
119
120     Symbol* symbol = tryExtractSymbol(vm, exec->thisValue());
121     if (!symbol)
122         return throwVMTypeError(exec, scope, SymbolValueOfTypeError);
123
124     scope.release();
125     return JSValue::encode(symbol);
126 }
127
128 } // namespace JSC