JavaScriptCore:
[WebKit.git] / JavaScriptCore / kjs / operations.cpp
1 /*
2  * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  * Copyright (C) 2008 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 Library 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  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public License
16  *  along with this library; see the file COPYING.LIB.  If not, write to
17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  *  Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "operations.h"
24
25 #include "Error.h"
26 #include "JSObject.h"
27 #include "JSString.h"
28 #include <math.h>
29 #include <stdio.h>
30 #include <wtf/MathExtras.h>
31
32 #if HAVE(FLOAT_H)
33 #include <float.h>
34 #endif
35
36 namespace JSC {
37
38 // ECMA 11.9.3
39 bool equal(ExecState* exec, JSValue* v1, JSValue* v2)
40 {
41 startOver:
42     if (JSImmediate::areBothImmediateNumbers(v1, v2))
43         return v1 == v2;
44
45     if (v1->isNumber() && v2->isNumber())
46         return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
47
48     bool s1 = v1->isString();
49     bool s2 = v2->isString();
50     if (s1 && s2)
51         return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
52
53     if (v1->isUndefinedOrNull()) {
54         if (v2->isUndefinedOrNull())
55             return true;
56         if (JSImmediate::isImmediate(v2))
57             return false;
58         return v2->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
59     }
60
61     if (v2->isUndefinedOrNull()) {
62         if (JSImmediate::isImmediate(v1))
63             return false;
64         return v1->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
65     }
66
67     if (v1->isObject()) {
68         if (v2->isObject())
69             return v1 == v2;
70         JSValue* p1 = v1->toPrimitive(exec);
71         if (exec->hadException())
72             return false;
73         v1 = p1;
74         goto startOver;
75     }
76
77     if (v2->isObject()) {
78         JSValue* p2 = v2->toPrimitive(exec);
79         if (exec->hadException())
80             return false;
81         v2 = p2;
82         goto startOver;
83     }
84
85     if (s1 || s2) {
86         double d1 = v1->toNumber(exec);
87         double d2 = v2->toNumber(exec);
88         return d1 == d2;
89     }
90
91     if (v1->isBoolean()) {
92         if (v2->isNumber())
93             return static_cast<double>(v1->getBoolean()) == v2->uncheckedGetNumber();
94     } else if (v2->isBoolean()) {
95         if (v1->isNumber())
96             return v1->uncheckedGetNumber() == static_cast<double>(v2->getBoolean());
97     }
98
99     return v1 == v2;
100 }
101
102 bool strictEqual(JSValue* v1, JSValue* v2)
103 {
104     if (JSImmediate::areBothImmediate(v1, v2))
105         return v1 == v2;
106
107     if (JSImmediate::isEitherImmediate(v1, v2) & (v1 != JSImmediate::from(0)) & (v2 != JSImmediate::from(0)))
108         return false;
109
110     return strictEqualSlowCaseInline(v1, v2);
111 }
112
113 bool strictEqualSlowCase(JSValue* v1, JSValue* v2)
114 {
115     return strictEqualSlowCaseInline(v1, v2);
116 }
117
118 NEVER_INLINE JSValue* throwOutOfMemoryError(ExecState* exec)
119 {
120     JSObject* error = Error::create(exec, GeneralError, "Out of memory");
121     exec->setException(error);
122     return error;
123 }
124
125 } // namespace JSC