Unreviewed, rolling out r226937.
[WebKit-https.git] / Source / JavaScriptCore / runtime / BigIntPrototype.cpp
1 /*
2  * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>.
3  * Copyright (C) 2017 Apple Inc. All rights reserved.
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 "BigIntPrototype.h"
29
30 #include "Error.h"
31 #include "JSBigInt.h"
32 #include "JSCBuiltins.h"
33 #include "JSCInlines.h"
34 #include "JSCell.h"
35 #include "JSFunction.h"
36 #include "JSGlobalObject.h"
37 #include "JSString.h"
38 #include <wtf/Assertions.h>
39
40 namespace JSC {
41
42 static EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToString(ExecState*);
43 static EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToLocaleString(ExecState*);
44 static EncodedJSValue JSC_HOST_CALL bigIntProtoFuncValueOf(ExecState*);
45
46 }
47
48 #include "BigIntPrototype.lut.h"
49
50 namespace JSC {
51
52 const ClassInfo BigIntPrototype::s_info = { "BigInt", &Base::s_info, &bigIntPrototypeTable, nullptr, CREATE_METHOD_TABLE(BigIntPrototype) };
53
54 /* Source for BigIntPrototype.lut.h
55 @begin bigIntPrototypeTable
56   toString          bigIntProtoFuncToString         DontEnum|Function 0
57   toLocaleString    bigIntProtoFuncToLocaleString   DontEnum|Function 0
58   valueOf           bigIntProtoFuncValueOf          DontEnum|Function 0
59 @end
60 */
61
62 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(BigIntPrototype);
63
64 BigIntPrototype::BigIntPrototype(VM& vm, Structure* structure)
65     : JSNonFinalObject(vm, structure)
66 {
67 }
68
69 void BigIntPrototype::finishCreation(VM& vm, JSGlobalObject*)
70 {
71     Base::finishCreation(vm);
72     ASSERT(inherits(vm, info()));
73     putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "BigInt"), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
74 }
75
76 // ------------------------------ Functions ---------------------------
77
78 static ALWAYS_INLINE JSBigInt* toThisBigIntValue(VM& vm, JSValue thisValue)
79 {
80     if (thisValue.isCell()) {
81         if (JSBigInt* bigInt = jsDynamicCast<JSBigInt*>(vm, thisValue.asCell()))
82             return bigInt;
83         
84         if (BigIntObject* bigIntObject = jsDynamicCast<BigIntObject*>(vm, thisValue.asCell()))
85             return bigIntObject->internalValue();
86     }
87
88     return nullptr;
89 }
90
91 EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToString(ExecState* state)
92 {
93     VM& vm = state->vm();
94     auto scope = DECLARE_THROW_SCOPE(vm);
95
96     JSBigInt* value = toThisBigIntValue(vm, state->thisValue());
97     if (!value)
98         return throwVMTypeError(state, scope, ASCIILiteral("'this' value must be a BigInt or BigIntObject"));
99     
100     ASSERT(value);
101
102     int64_t radix;
103     JSValue radixValue = state->argument(0);
104     if (radixValue.isInt32())
105         radix = radixValue.asInt32();
106     else if (radixValue.isUndefined())
107         radix = 10;
108     else {
109         radix = static_cast<int64_t>(radixValue.toInteger(state));
110         RETURN_IF_EXCEPTION(scope, encodedJSValue());
111     }
112
113     if (radix < 2 || radix > 36)
114         return throwVMError(state, scope, createRangeError(state, ASCIILiteral("toString() radix argument must be between 2 and 36")));
115
116     String resultString = value->toString(*state, static_cast<int32_t>(radix));
117     RETURN_IF_EXCEPTION(scope, encodedJSValue());
118     if (resultString.length() == 1)
119         return JSValue::encode(vm.smallStrings.singleCharacterString(resultString[0]));
120
121     scope.release();
122     return JSValue::encode(jsNontrivialString(&vm, resultString));
123 }
124
125 EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToLocaleString(ExecState* state)
126 {
127     return bigIntProtoFuncToString(state);
128 }
129
130 EncodedJSValue JSC_HOST_CALL bigIntProtoFuncValueOf(ExecState* state)
131 {
132     VM& vm = state->vm();
133     if (JSBigInt* value = toThisBigIntValue(vm, state->thisValue()))
134         return JSValue::encode(value);
135     
136     auto scope = DECLARE_THROW_SCOPE(vm);
137     return throwVMTypeError(state, scope, ASCIILiteral("'this' value must be a BigInt or BigIntObject"));
138 }
139
140 } // namespace JSC