fix logic
[personal-kdelibs.git] / kjs / internal.cpp
blob06b5f5e08c45cb59b5790020cb65c80160bee550
1 /*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
4 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
5 * Copyright (C) 2004 Apple Computer, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #include "internal.h"
25 #include <config.h>
27 #include "array_object.h"
28 #include "bool_object.h"
29 #include "collector.h"
30 #include "date_object.h"
31 #include "debugger.h"
32 #include "error_object.h"
33 #include "function_object.h"
34 #include "lexer.h"
35 #include "math_object.h"
36 #include "nodes.h"
37 #include "number_object.h"
38 #include "object.h"
39 #include "object_object.h"
40 #include "operations.h"
41 #include "regexp_object.h"
42 #include "string_object.h"
43 #include <assert.h>
44 #include <wtf/HashMap.h>
45 #include <wtf/HashSet.h>
46 #include <wtf/Vector.h>
47 #include <math.h>
48 #include <stdio.h>
50 namespace KJS {
52 #if PLATFORM(WIN_OS)
53 #define copysign _copysign
54 #endif
56 static const double D16 = 65536.0;
57 static const double D32 = 4294967296.0;
60 // ------------------------------ StringImp ------------------------------------
62 JSValue *StringImp::toPrimitive(ExecState *, JSType) const
64 return const_cast<StringImp *>(this);
67 bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
69 ASSERT_NOT_REACHED();
70 number = 0;
71 value = 0;
72 return true;
75 bool StringImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
77 value = this;
78 number = val.toDouble();
79 return false;
82 bool StringImp::toBoolean(ExecState *) const
84 return (val.size() > 0);
87 double StringImp::toNumber(ExecState *) const
89 return val.toDouble();
92 UString StringImp::toString(ExecState *) const
94 return val;
97 JSObject* StringImp::toObject(ExecState *exec) const
99 return new StringInstance(exec->lexicalInterpreter()->builtinStringPrototype(), const_cast<StringImp*>(this));
102 // ------------------------------ NumberImp ------------------------------------
104 JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
106 return const_cast<NumberImp *>(this);
109 bool NumberImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
111 number = val;
112 value = this;
113 return true;
116 bool NumberImp::toBoolean(ExecState *) const
118 return val < 0.0 || val > 0.0; // false for NaN
121 double NumberImp::toNumber(ExecState *) const
123 return val;
126 UString NumberImp::toString(ExecState *) const
128 if (val == 0.0) // +0.0 or -0.0
129 return "0";
130 return UString::from(val);
133 JSObject *NumberImp::toObject(ExecState *exec) const
135 List args;
136 args.append(const_cast<NumberImp*>(this));
137 return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
140 bool NumberImp::getUInt32(uint32_t& uint32) const
142 uint32 = static_cast<uint32_t>(val);
143 return uint32 == val;
146 bool NumberImp::getTruncatedInt32(int32_t& int32) const
148 if (!(val >= -2147483648.0 && val < 2147483648.0))
149 return false;
150 int32 = static_cast<int32_t>(val);
151 return true;
154 bool NumberImp::getTruncatedUInt32(uint32_t& uint32) const
156 if (!(val >= 0.0 && val < 4294967296.0))
157 return false;
158 uint32 = static_cast<uint32_t>(val);
159 return true;
162 // --------------------------- GetterSetterImp ---------------------------------
163 void GetterSetterImp::mark()
165 JSCell::mark();
167 if (getter && !getter->marked())
168 getter->mark();
169 if (setter && !setter->marked())
170 setter->mark();
173 JSValue *GetterSetterImp::toPrimitive(ExecState*, JSType) const
175 assert(false);
176 return jsNull();
179 bool GetterSetterImp::toBoolean(ExecState*) const
181 assert(false);
182 return false;
185 double GetterSetterImp::toNumber(ExecState *) const
187 assert(false);
188 return 0.0;
191 UString GetterSetterImp::toString(ExecState *) const
193 assert(false);
194 return UString::null();
197 JSObject *GetterSetterImp::toObject(ExecState *exec) const
199 assert(false);
200 return jsNull()->toObject(exec);
203 // ------------------------------ InternalFunctionImp --------------------------
205 const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
207 InternalFunctionImp::InternalFunctionImp()
211 InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
212 : JSObject(funcProto)
216 InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
217 : JSObject(funcProto)
218 , m_name(name)
222 bool InternalFunctionImp::implementsCall() const
224 return true;
227 bool InternalFunctionImp::implementsHasInstance() const
229 return true;
232 // ------------------------------ global functions -----------------------------
234 double roundValue(double d)
236 double ad = fabs(d);
237 if (ad == 0 || isNaN(d) || isInf(d))
238 return d;
239 return copysign(floor(ad), d);
242 int32_t toInt32(double d)
244 if (isNaN(d) || isInf(d))
245 return 0;
246 double d32 = fmod(roundValue(d), D32);
248 if (d32 >= D32 / 2)
249 d32 -= D32;
250 else if (d32 < -D32 / 2)
251 d32 += D32;
253 return static_cast<int32_t>(d32);
256 int32_t toInt32(double d, bool &ok)
258 ok = true;
259 if (isNaN(d) || isInf(d)) {
260 ok = false;
261 return 0;
263 return toInt32(d);
266 uint32_t toUInt32(double dd)
268 double d = roundValue(dd);
269 if (isNaN(d) || isInf(d))
270 return 0;
271 double d32 = fmod(d, D32);
273 if (d32 < 0)
274 d32 += D32;
276 return static_cast<uint32_t>(d32);
279 uint16_t toUInt16(double dd)
281 double d = roundValue(dd);
282 if (isNaN(d) || isInf(d))
283 return 0;
284 double d16 = fmod(d, D16);
286 if (d16 < 0)
287 d16 += D16;
289 return static_cast<uint16_t>(d16);
292 //#ifndef NDEBUG
293 void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
295 UString vString;
296 if (!o)
297 fprintf(stderr, "KJS: %s: (null)", s);
298 else {
299 JSValue *v = o;
301 unsigned int arrayLength = 0;
302 bool hadExcep = exec->hadException();
304 UString name;
305 switch (v->type()) {
306 case UnspecifiedType:
307 name = "Unspecified";
308 break;
309 case UndefinedType:
310 name = "Undefined";
311 break;
312 case NullType:
313 name = "Null";
314 break;
315 case BooleanType:
316 name = "Boolean";
317 break;
318 case StringType:
319 name = "String";
320 break;
321 case NumberType:
322 name = "Number";
323 break;
324 case ObjectType: {
325 JSObject* obj = static_cast<JSObject *>(v);
326 name = obj->className();
327 if (name.isNull())
328 name = "(unknown class)";
330 if ( obj->inherits(&ArrayInstance::info) )
331 arrayLength = obj->get(exec, exec->propertyNames().length)->toUInt32(exec);
332 vString = "[object " + name + "]";
333 break;
335 case GetterSetterType:
336 name = "GetterSetter";
337 break;
340 // Avoid calling toString on a huge array (e.g. 4 billion elements, in mozilla/js/js1_5/Array/array-001.js)
341 if ( arrayLength > 100 )
342 vString = UString( "[ Array with " ) + UString::from( arrayLength ) + " elements ]";
343 else if ( v->type() != ObjectType ) // Don't want to call a user toString function!
344 vString = v->toString(exec);
345 if ( !hadExcep )
346 exec->clearException();
348 if ( vString.size() > 350 )
349 vString = vString.substr( 0, 350 ) + "...";
351 // Can't use two UString::ascii() in the same fprintf call
352 CString tempString( vString.cstring() );
354 fprintf(stderr, "KJS: %s: %s : %s (%p)",
355 s, tempString.c_str(), name.ascii(), (void*)v);
357 if (lineno >= 0)
358 fprintf(stderr, ", line %d\n",lineno);
359 else
360 fprintf(stderr, "\n");
363 //#endif