ArrayPrototype methods should use JSValue::toLength for non-Arrays.
[WebKit-https.git] / Source / JavaScriptCore / runtime / NumberConstructor.cpp
1 /*
2  *  Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2007, 2008, 2011, 2015-2016 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
18  *  USA
19  *
20  */
21
22 #include "config.h"
23 #include "NumberConstructor.h"
24
25 #include "Lookup.h"
26 #include "NumberObject.h"
27 #include "NumberPrototype.h"
28 #include "JSCInlines.h"
29 #include "JSGlobalObjectFunctions.h"
30 #include "StructureInlines.h"
31
32 namespace JSC {
33
34 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsInteger(ExecState*);
35 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsSafeInteger(ExecState*);
36
37 } // namespace JSC
38
39 #include "NumberConstructor.lut.h"
40
41 namespace JSC {
42
43 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(NumberConstructor);
44
45 const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, &numberConstructorTable, nullptr, CREATE_METHOD_TABLE(NumberConstructor) };
46
47 /* Source for NumberConstructor.lut.h
48 @begin numberConstructorTable
49   isFinite       JSBuiltin                           DontEnum|Function 1
50   isInteger      numberConstructorFuncIsInteger      DontEnum|Function 1
51   isNaN          JSBuiltin                           DontEnum|Function 1
52   isSafeInteger  numberConstructorFuncIsSafeInteger  DontEnum|Function 1
53 @end
54 */
55
56 NumberConstructor::NumberConstructor(VM& vm, Structure* structure)
57     : InternalFunction(vm, structure)
58 {
59 }
60
61 void NumberConstructor::finishCreation(VM& vm, NumberPrototype* numberPrototype)
62 {
63     Base::finishCreation(vm, NumberPrototype::info()->className);
64     ASSERT(inherits(vm, info()));
65
66     putDirectWithoutTransition(vm, vm.propertyNames->prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
67     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum);
68
69     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "EPSILON"), jsDoubleNumber(std::numeric_limits<double>::epsilon()), DontDelete | DontEnum | ReadOnly);
70     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MAX_VALUE"), jsDoubleNumber(1.7976931348623157E+308), DontDelete | DontEnum | ReadOnly);
71     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MIN_VALUE"), jsDoubleNumber(5E-324), DontDelete | DontEnum | ReadOnly);
72     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MAX_SAFE_INTEGER"), jsDoubleNumber(maxSafeInteger()), DontDelete | DontEnum | ReadOnly);
73     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MIN_SAFE_INTEGER"), jsDoubleNumber(minSafeInteger()), DontDelete | DontEnum | ReadOnly);
74     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "NEGATIVE_INFINITY"), jsDoubleNumber(-std::numeric_limits<double>::infinity()), DontDelete | DontEnum | ReadOnly);
75     putDirectWithoutTransition(vm, Identifier::fromString(&vm, "POSITIVE_INFINITY"), jsDoubleNumber(std::numeric_limits<double>::infinity()), DontDelete | DontEnum | ReadOnly);
76     putDirectWithoutTransition(vm, vm.propertyNames->NaN, jsNaN(), DontDelete | DontEnum | ReadOnly);
77
78     putDirectWithoutTransition(vm, vm.propertyNames->parseInt, numberPrototype->globalObject()->parseIntFunction(), DontEnum);
79     putDirectWithoutTransition(vm, vm.propertyNames->parseFloat, numberPrototype->globalObject()->parseFloatFunction(), DontEnum);
80 }
81
82 // ECMA 15.7.1
83 static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
84 {
85     VM& vm = exec->vm();
86     auto scope = DECLARE_THROW_SCOPE(vm);
87     double n = exec->argumentCount() ? exec->uncheckedArgument(0).toNumber(exec) : 0;
88     RETURN_IF_EXCEPTION(scope, encodedJSValue());
89     Structure* structure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), exec->lexicalGlobalObject()->numberObjectStructure());
90     RETURN_IF_EXCEPTION(scope, encodedJSValue());
91
92     NumberObject* object = NumberObject::create(vm, structure);
93     object->setInternalValue(vm, jsNumber(n));
94     return JSValue::encode(object);
95 }
96
97 ConstructType NumberConstructor::getConstructData(JSCell*, ConstructData& constructData)
98 {
99     constructData.native.function = constructWithNumberConstructor;
100     return ConstructType::Host;
101 }
102
103 // ECMA 15.7.2
104 static EncodedJSValue JSC_HOST_CALL callNumberConstructor(ExecState* exec)
105 {
106     return JSValue::encode(jsNumber(!exec->argumentCount() ? 0 : exec->uncheckedArgument(0).toNumber(exec)));
107 }
108
109 CallType NumberConstructor::getCallData(JSCell*, CallData& callData)
110 {
111     callData.native.function = callNumberConstructor;
112     return CallType::Host;
113 }
114
115 // ECMA-262 20.1.2.3
116 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsInteger(ExecState* exec)
117 {
118     JSValue argument = exec->argument(0);
119     bool isInteger;
120     if (argument.isInt32())
121         isInteger = true;
122     else if (!argument.isDouble())
123         isInteger = false;
124     else {
125         double number = argument.asDouble();
126         isInteger = std::isfinite(number) && trunc(number) == number;
127     }
128     return JSValue::encode(jsBoolean(isInteger));
129 }
130
131 // ECMA-262 20.1.2.5
132 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsSafeInteger(ExecState* exec)
133 {
134     JSValue argument = exec->argument(0);
135     bool isInteger;
136     if (argument.isInt32())
137         isInteger = true;
138     else if (!argument.isDouble())
139         isInteger = false;
140     else {
141         double number = argument.asDouble();
142         isInteger = trunc(number) == number && std::abs(number) <= maxSafeInteger();
143     }
144     return JSValue::encode(jsBoolean(isInteger));
145 }
146
147 } // namespace JSC