We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / runtime / BigIntConstructor.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. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "BigIntConstructor.h"
29
30 #include "BigIntPrototype.h"
31 #include "JSBigInt.h"
32 #include "JSCInlines.h"
33 #include "JSGlobalObjectFunctions.h"
34 #include "Lookup.h"
35 #include "ParseInt.h"
36 #include "StructureInlines.h"
37
38 namespace JSC {
39
40 static EncodedJSValue JSC_HOST_CALL bigIntConstructorFuncAsUintN(ExecState*);
41 static EncodedJSValue JSC_HOST_CALL bigIntConstructorFuncAsIntN(ExecState*);
42
43 } // namespace JSC
44
45 #include "BigIntConstructor.lut.h"
46
47 namespace JSC {
48
49 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(BigIntConstructor);
50
51 const ClassInfo BigIntConstructor::s_info = { "Function", &Base::s_info, &bigIntConstructorTable, nullptr, CREATE_METHOD_TABLE(BigIntConstructor) };
52
53 /* Source for BigIntConstructor.lut.h
54 @begin bigIntConstructorTable
55   asUintN   bigIntConstructorFuncAsUintN   DontEnum|Function 2
56   asIntN    bigIntConstructorFuncAsIntN    DontEnum|Function 2
57 @end
58 */
59
60 static EncodedJSValue JSC_HOST_CALL callBigIntConstructor(ExecState*);
61
62 BigIntConstructor::BigIntConstructor(VM& vm, Structure* structure)
63     : InternalFunction(vm, structure, callBigIntConstructor, nullptr)
64 {
65 }
66
67 void BigIntConstructor::finishCreation(VM& vm, BigIntPrototype* bigIntPrototype)
68 {
69     Base::finishCreation(vm, BigIntPrototype::info()->className);
70     ASSERT(inherits(vm, info()));
71
72     putDirectWithoutTransition(vm, vm.propertyNames->prototype, bigIntPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
73     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
74     putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String("BigInt"_s)), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
75 }
76
77 // ------------------------------ Functions ---------------------------
78
79 static bool isSafeInteger(JSValue argument)
80 {
81     if (argument.isInt32())
82         return true;
83
84     if (!argument.isDouble())
85         return false;
86
87     double number = argument.asDouble();
88     return trunc(number) == number && std::abs(number) <= maxSafeInteger();
89 }
90
91 static EncodedJSValue toBigInt(ExecState& state, JSValue argument)
92 {
93     ASSERT(argument.isPrimitive());
94     VM& vm = state.vm();
95     
96     if (argument.isBigInt())
97         return JSValue::encode(argument);
98     
99     auto scope = DECLARE_THROW_SCOPE(vm);
100     
101     if (argument.isBoolean()) {
102         scope.release();
103         return JSValue::encode(JSBigInt::createFrom(vm, argument.asBoolean()));
104     }
105     
106     if (argument.isUndefinedOrNull() || argument.isNumber() || argument.isSymbol())
107         return throwVMTypeError(&state, scope, "Invalid argument type in ToBigInt operation"_s);
108     
109     ASSERT(argument.isString());
110     
111     scope.release();
112     return toStringView(&state, argument, [&] (StringView view) {
113         return JSValue::encode(JSBigInt::parseInt(&state, view));
114     });
115 }
116
117 static EncodedJSValue JSC_HOST_CALL callBigIntConstructor(ExecState* state)
118 {
119     VM& vm = state->vm();
120     auto scope = DECLARE_THROW_SCOPE(vm);
121     
122     JSValue value = state->argument(0);
123     JSValue primitive = value.toPrimitive(state);
124     RETURN_IF_EXCEPTION(scope, encodedJSValue());
125
126     if (primitive.isNumber()) {
127         if (!isSafeInteger(primitive))
128             return throwVMError(state, scope, createRangeError(state, "Not safe integer"_s));
129         
130         scope.release();
131         if (primitive.isInt32())
132             return JSValue::encode(JSBigInt::createFrom(vm, primitive.asInt32()));
133
134         if (primitive.isUInt32())
135             return JSValue::encode(JSBigInt::createFrom(vm, primitive.asUInt32()));
136
137         return JSValue::encode(JSBigInt::createFrom(vm, static_cast<int64_t>(primitive.asDouble())));
138     }
139     
140     EncodedJSValue result = toBigInt(*state, primitive);
141     RETURN_IF_EXCEPTION(scope, encodedJSValue());
142     return result;
143 }
144
145 EncodedJSValue JSC_HOST_CALL bigIntConstructorFuncAsUintN(ExecState*)
146 {
147     // FIXME: [ESNext][BigInt] Implement BigInt.asIntN and BigInt.asUintN
148     // https://bugs.webkit.org/show_bug.cgi?id=181144
149     CRASH();
150     return JSValue::encode(JSValue());
151 }
152
153 EncodedJSValue JSC_HOST_CALL bigIntConstructorFuncAsIntN(ExecState*)
154 {
155     // FIXME: [ESNext][BigInt] Implement BigInt.asIntN and BigInt.asUintN
156     // https://bugs.webkit.org/show_bug.cgi?id=181144
157     CRASH();
158     return JSValue::encode(JSValue());
159 }
160
161 } // namespace JSC