File indexing completed on 2024-05-12 15:43:31
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 * 0020 */ 0021 0022 #include "operations.h" 0023 0024 #include "object.h" 0025 #include "internal.h" 0026 0027 namespace KJS 0028 { 0029 // ECMA 11.9.3 0030 bool equal(ExecState *exec, JSValue *v1, JSValue *v2) 0031 { 0032 JSType t1 = JSValue::type(v1); 0033 JSType t2 = JSValue::type(v2); 0034 0035 if (t1 != t2) { 0036 if (t1 == UndefinedType) { 0037 t1 = NullType; 0038 } 0039 if (t2 == UndefinedType) { 0040 t2 = NullType; 0041 } 0042 0043 if (t1 == BooleanType) { 0044 t1 = NumberType; 0045 } 0046 if (t2 == BooleanType) { 0047 t2 = NumberType; 0048 } 0049 0050 if (t1 == NumberType && t2 == StringType) { 0051 // use toNumber 0052 } else if (t1 == StringType && t2 == NumberType) { 0053 t1 = NumberType; 0054 } 0055 // use toNumber 0056 else { 0057 if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType) { 0058 return equal(exec, v1, JSValue::toPrimitive(v2, exec)); 0059 } 0060 if (t1 == NullType && t2 == ObjectType) { 0061 return static_cast<JSObject *>(v2)->masqueradeAsUndefined(); 0062 } 0063 if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType)) { 0064 return equal(exec, JSValue::toPrimitive(v1, exec), v2); 0065 } 0066 if (t1 == ObjectType && t2 == NullType) { 0067 return static_cast<JSObject *>(v1)->masqueradeAsUndefined(); 0068 } 0069 if (t1 != t2) { 0070 return false; 0071 } 0072 } 0073 } 0074 0075 if (t1 == UndefinedType || t1 == NullType) { 0076 return true; 0077 } 0078 0079 if (t1 == NumberType) { 0080 double d1 = JSValue::toNumber(v1, exec); 0081 double d2 = JSValue::toNumber(v2, exec); 0082 return d1 == d2; 0083 } 0084 0085 if (t1 == StringType) { 0086 return JSValue::toString(v1, exec) == JSValue::toString(v2, exec); 0087 } 0088 0089 if (t1 == BooleanType) { 0090 return JSValue::toBoolean(v1, exec) == JSValue::toBoolean(v2, exec); 0091 } 0092 0093 // types are Object 0094 return v1 == v2; 0095 } 0096 0097 bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2) 0098 { 0099 JSType t1 = JSValue::type(v1); 0100 JSType t2 = JSValue::type(v2); 0101 0102 if (t1 != t2) { 0103 return false; 0104 } 0105 if (t1 == UndefinedType || t1 == NullType) { 0106 return true; 0107 } 0108 if (t1 == NumberType) { 0109 double n1 = JSValue::toNumber(v1, exec); 0110 double n2 = JSValue::toNumber(v2, exec); 0111 if (n1 == n2) { 0112 return true; 0113 } 0114 return false; 0115 } else if (t1 == StringType) { 0116 return JSValue::toString(v1, exec) == JSValue::toString(v2, exec); 0117 } else if (t2 == BooleanType) { 0118 return JSValue::toBoolean(v1, exec) == JSValue::toBoolean(v2, exec); 0119 } 0120 0121 if (v1 == v2) { 0122 return true; 0123 } 0124 /* TODO: joined objects */ 0125 0126 return false; 0127 } 0128 0129 int relation(ExecState *exec, JSValue *v1, JSValue *v2, bool leftFirst) 0130 { 0131 double n1; 0132 double n2; 0133 JSValue *p1; 0134 JSValue *p2; 0135 0136 bool wasNotString1; 0137 bool wasNotString2; 0138 0139 if (leftFirst) { 0140 wasNotString1 = JSValue::getPrimitiveNumber(v1, exec, n1, p1); 0141 if (exec->hadException()) { 0142 return -1; 0143 } 0144 wasNotString2 = JSValue::getPrimitiveNumber(v2, exec, n2, p2); 0145 } else { 0146 wasNotString1 = JSValue::getPrimitiveNumber(v2, exec, n2, p2); 0147 if (exec->hadException()) { 0148 return -1; 0149 } 0150 wasNotString2 = JSValue::getPrimitiveNumber(v1, exec, n1, p1); 0151 } 0152 0153 if (wasNotString1 || wasNotString2) { 0154 if (n1 < n2) { 0155 return 1; 0156 } 0157 if (n1 >= n2) { 0158 return 0; 0159 } 0160 return -1; // must be NaN, so undefined 0161 } 0162 0163 assert(JSValue::isString(p1) && JSValue::isString(p2)); 0164 return static_cast<const StringImp *>(p1)->value() < static_cast<const StringImp *>(p2)->value() ? 1 : 0; 0165 } 0166 0167 //EMCA 9.12 0168 bool sameValue(ExecState *exec, JSValue *v1, JSValue *v2) 0169 { 0170 using namespace std; 0171 JSType t1 = JSValue::type(v1); 0172 JSType t2 = JSValue::type(v2); 0173 0174 if (t1 != t2) { 0175 return false; 0176 } 0177 if (t1 == UndefinedType || t1 == NullType) { 0178 return true; 0179 } 0180 if (t1 == NumberType) { 0181 double n1 = JSValue::toNumber(v1, exec); 0182 double n2 = JSValue::toNumber(v2, exec); 0183 if (isNaN(n1) && isNaN(n2)) { 0184 return true; 0185 } 0186 if (signbit(n1) != signbit(n2)) { 0187 return false; 0188 } 0189 if (n1 == n2) { 0190 return true; 0191 } 0192 return false; 0193 } else if (t1 == StringType) { 0194 return JSValue::toString(v1, exec) == JSValue::toString(v2, exec); 0195 } else if (t2 == BooleanType) { 0196 return JSValue::toBoolean(v1, exec) == JSValue::toBoolean(v2, exec); 0197 } 0198 0199 if (v1 == v2) { 0200 return true; 0201 } 0202 /* TODO: joined objects */ 0203 0204 return false; 0205 } 0206 0207 int relation(ExecState *exec, JSValue *v1, double n2) 0208 { 0209 double n1; 0210 JSValue *p1; 0211 0212 JSValue::getPrimitiveNumber(v1, exec, n1, p1); 0213 if (exec->hadException()) { 0214 return -1; 0215 } 0216 0217 if (n1 < n2) { 0218 return 1; 0219 } 0220 if (n1 >= n2) { 0221 return 0; 0222 } 0223 return -1; // must be NaN, so undefined 0224 } 0225 0226 int maxInt(int d1, int d2) 0227 { 0228 return (d1 > d2) ? d1 : d2; 0229 } 0230 0231 int minInt(int d1, int d2) 0232 { 0233 return (d1 < d2) ? d1 : d2; 0234 } 0235 0236 double exponentiation(double base, double exponent) 0237 { 0238 if (isNaN(exponent)) 0239 return NaN; 0240 if (abs(base) == 1 && isInf(exponent)) 0241 return NaN; 0242 return pow(base, exponent); 0243 } 0244 0245 }