File indexing completed on 2024-05-12 15:43:36
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 0005 * Copyright (C) 2003 Apple Computer, Inc. 0006 * 0007 * This library is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU Library General Public 0009 * License as published by the Free Software Foundation; either 0010 * version 2 of the License, or (at your option) any later version. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Library General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Library General Public License 0018 * along with this library; see the file COPYING.LIB. If not, write to 0019 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 * Boston, MA 02110-1301, USA. 0021 * 0022 */ 0023 0024 #include "value.h" 0025 0026 #include "error_object.h" 0027 #include "nodes.h" 0028 #include "operations.h" 0029 #include <stdio.h> 0030 #include <string.h> 0031 #include <wtf/MathExtras.h> 0032 0033 namespace KJS 0034 { 0035 0036 static const double D16 = 65536.0; 0037 static const double D32 = 4294967296.0; 0038 0039 void *JSCell::operator new(size_t size) 0040 { 0041 return Collector::allocate(size); 0042 } 0043 0044 bool JSCell::getUInt32(uint32_t &) const 0045 { 0046 return false; 0047 } 0048 0049 bool JSCell::getTruncatedInt32(int32_t &) const 0050 { 0051 return false; 0052 } 0053 0054 bool JSCell::getTruncatedUInt32(uint32_t &) const 0055 { 0056 return false; 0057 } 0058 0059 // ECMA 9.4 0060 double JSValue::toInteger(ExecState *exec) const 0061 { 0062 return toInteger(this, exec); 0063 } 0064 0065 double JSValue::toInteger(const JSValue *value, ExecState *exec) 0066 { 0067 int32_t i; 0068 if (getTruncatedInt32(value, i)) { 0069 return i; 0070 } 0071 double d = toNumber(value, exec); 0072 return isNaN(d) ? 0.0 : trunc(d); 0073 } 0074 0075 double JSValue::toIntegerPreserveNaN(ExecState *exec) const 0076 { 0077 return toIntegerPreserveNaN(this, exec); 0078 } 0079 0080 double JSValue::toIntegerPreserveNaN(const JSValue *value, ExecState *exec) 0081 { 0082 int32_t i; 0083 if (getTruncatedInt32(value, i)) { 0084 return i; 0085 } 0086 return trunc(toNumber(value, exec)); 0087 } 0088 0089 int32_t JSValue::toInt32SlowCase(double d, bool &ok) 0090 { 0091 ok = true; 0092 0093 if (d >= -D32 / 2 && d < D32 / 2) { 0094 return static_cast<int32_t>(d); 0095 } 0096 0097 if (isNaN(d) || isInf(d)) { 0098 ok = false; 0099 return 0; 0100 } 0101 0102 double d32 = fmod(trunc(d), D32); 0103 if (d32 >= D32 / 2) { 0104 d32 -= D32; 0105 } else if (d32 < -D32 / 2) { 0106 d32 += D32; 0107 } 0108 return static_cast<int32_t>(d32); 0109 } 0110 0111 int32_t JSValue::toInt32SlowCase(const JSValue *value, ExecState *exec, bool &ok) 0112 { 0113 return JSValue::toInt32SlowCase(toNumber(value, exec), ok); 0114 } 0115 0116 uint32_t JSValue::toUInt32SlowCase(double d, bool &ok) 0117 { 0118 ok = true; 0119 0120 if (d >= 0.0 && d < D32) { 0121 return static_cast<uint32_t>(d); 0122 } 0123 0124 if (isNaN(d) || isInf(d)) { 0125 ok = false; 0126 return 0; 0127 } 0128 0129 double d32 = fmod(trunc(d), D32); 0130 if (d32 < 0) { 0131 d32 += D32; 0132 } 0133 return static_cast<uint32_t>(d32); 0134 } 0135 0136 uint32_t JSValue::toUInt32SlowCase(const JSValue *value, ExecState *exec, bool &ok) 0137 { 0138 return JSValue::toUInt32SlowCase(toNumber(value, exec), ok); 0139 } 0140 0141 uint16_t JSValue::toUInt16(ExecState *exec) const 0142 { 0143 return toUInt16(this, exec); 0144 } 0145 0146 uint16_t JSValue::toUInt16(const JSValue *value, ExecState *exec) 0147 { 0148 uint32_t i; 0149 if (getUInt32(value, i)) { 0150 return static_cast<uint16_t>(i); 0151 } 0152 0153 return KJS::toUInt16(const_cast<JSValue *>(value)->toNumber(value, exec)); 0154 } 0155 0156 float JSValue::toFloat(ExecState *exec) const 0157 { 0158 return toFloat(this, exec); 0159 } 0160 0161 float JSValue::toFloat(const JSValue *value, ExecState *exec) 0162 { 0163 return static_cast<float>(toNumber(value, exec)); 0164 } 0165 0166 bool JSCell::getNumber(double &numericValue) const 0167 { 0168 if (!isNumber()) { 0169 return false; 0170 } 0171 numericValue = static_cast<const NumberImp *>(this)->value(); 0172 return true; 0173 } 0174 0175 double JSCell::getNumber() const 0176 { 0177 return isNumber() ? static_cast<const NumberImp *>(this)->value() : NaN; 0178 } 0179 0180 bool JSCell::getString(UString &stringValue) const 0181 { 0182 if (!isString()) { 0183 return false; 0184 } 0185 stringValue = static_cast<const StringImp *>(this)->value(); 0186 return true; 0187 } 0188 0189 UString JSCell::getString() const 0190 { 0191 return isString() ? static_cast<const StringImp *>(this)->value() : UString(); 0192 } 0193 0194 JSObject *JSCell::getObject() 0195 { 0196 return isObject() ? static_cast<JSObject *>(this) : nullptr; 0197 } 0198 0199 const JSObject *JSCell::getObject() const 0200 { 0201 return isObject() ? static_cast<const JSObject *>(this) : nullptr; 0202 } 0203 0204 bool JSCell::implementsCall() const 0205 { 0206 return false; 0207 } 0208 0209 JSCell *jsString() 0210 { 0211 return new StringImp(); 0212 } 0213 0214 JSCell *jsString(const char *s) 0215 { 0216 return new StringImp(s, s ? strlen(s) : 0); 0217 } 0218 0219 JSCell *jsString(const char *s, int len) 0220 { 0221 return new StringImp(s, len); 0222 } 0223 0224 JSCell *jsString(const UString &s) 0225 { 0226 return s.isNull() ? new StringImp() : new StringImp(s); 0227 } 0228 0229 JSCell *jsOwnedString(const UString &s) 0230 { 0231 return s.isNull() ? new StringImp(UString::empty, StringImp::HasOtherOwner) : new StringImp(s, StringImp::HasOtherOwner); 0232 } 0233 0234 JSCell *jsString(ExecState *exec, const JSValue *value) 0235 { 0236 if (JSValue::isString(value)) { 0237 return jsString(static_cast<const StringImp *>(value)->value()); 0238 } 0239 return jsString(JSValue::toString(value, exec)); 0240 } 0241 0242 // This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine 0243 // it in a separate function to keep the normal case speedy. 0244 JSValue *jsNumberCell(double d) 0245 { 0246 return new NumberImp(d); 0247 } 0248 0249 JSValue *JSValue::getByIndex(ExecState *exec, unsigned propertyName) const 0250 { 0251 return getByIndex(this, exec, propertyName); 0252 } 0253 0254 JSValue *JSValue::getByIndex(const JSValue *value, ExecState *exec, unsigned propertyName) 0255 { 0256 switch (type(value)) { 0257 case StringType: { 0258 UString s = static_cast<const StringImp *>(value->asCell())->value(); 0259 if (propertyName < static_cast<unsigned>(s.size())) { 0260 return jsString(s.substr(propertyName, 1)); 0261 } 0262 // fall through 0263 } 0264 default: { 0265 JSObject *obj = toObject(value, exec); 0266 PropertySlot slot; 0267 if (obj->getPropertySlot(exec, propertyName, slot)) { 0268 return slot.getValue(exec, obj, propertyName); 0269 } 0270 0271 return jsUndefined(); 0272 } 0273 } 0274 } 0275 0276 } // namespace KJS