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.
27 #include "array_object.h"
28 #include "bool_object.h"
29 #include "collector.h"
30 #include "date_object.h"
32 #include "error_object.h"
33 #include "function_object.h"
35 #include "math_object.h"
37 #include "number_object.h"
39 #include "object_object.h"
40 #include "operations.h"
41 #include "regexp_object.h"
42 #include "string_object.h"
44 #include <wtf/HashMap.h>
45 #include <wtf/HashSet.h>
46 #include <wtf/Vector.h>
53 #define copysign _copysign
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
)
75 bool StringImp::getPrimitiveNumber(ExecState
*, double& number
, JSValue
*& value
)
78 number
= val
.toDouble();
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
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
)
116 bool NumberImp::toBoolean(ExecState
*) const
118 return val
< 0.0 || val
> 0.0; // false for NaN
121 double NumberImp::toNumber(ExecState
*) const
126 UString
NumberImp::toString(ExecState
*) const
128 if (val
== 0.0) // +0.0 or -0.0
130 return UString::from(val
);
133 JSObject
*NumberImp::toObject(ExecState
*exec
) const
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))
150 int32
= static_cast<int32_t>(val
);
154 bool NumberImp::getTruncatedUInt32(uint32_t& uint32
) const
156 if (!(val
>= 0.0 && val
< 4294967296.0))
158 uint32
= static_cast<uint32_t>(val
);
162 // --------------------------- GetterSetterImp ---------------------------------
163 void GetterSetterImp::mark()
167 if (getter
&& !getter
->marked())
169 if (setter
&& !setter
->marked())
173 JSValue
*GetterSetterImp::toPrimitive(ExecState
*, JSType
) const
179 bool GetterSetterImp::toBoolean(ExecState
*) const
185 double GetterSetterImp::toNumber(ExecState
*) const
191 UString
GetterSetterImp::toString(ExecState
*) const
194 return UString::null();
197 JSObject
*GetterSetterImp::toObject(ExecState
*exec
) const
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
)
222 bool InternalFunctionImp::implementsCall() const
227 bool InternalFunctionImp::implementsHasInstance() const
232 // ------------------------------ global functions -----------------------------
234 double roundValue(double d
)
237 if (ad
== 0 || isNaN(d
) || isInf(d
))
239 return copysign(floor(ad
), d
);
242 int32_t toInt32(double d
)
244 if (isNaN(d
) || isInf(d
))
246 double d32
= fmod(roundValue(d
), D32
);
250 else if (d32
< -D32
/ 2)
253 return static_cast<int32_t>(d32
);
256 int32_t toInt32(double d
, bool &ok
)
259 if (isNaN(d
) || isInf(d
)) {
266 uint32_t toUInt32(double dd
)
268 double d
= roundValue(dd
);
269 if (isNaN(d
) || isInf(d
))
271 double d32
= fmod(d
, 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
))
284 double d16
= fmod(d
, D16
);
289 return static_cast<uint16_t>(d16
);
293 void printInfo(ExecState
*exec
, const char *s
, JSValue
*o
, int lineno
)
297 fprintf(stderr
, "KJS: %s: (null)", s
);
301 unsigned int arrayLength
= 0;
302 bool hadExcep
= exec
->hadException();
306 case UnspecifiedType
:
307 name
= "Unspecified";
325 JSObject
* obj
= static_cast<JSObject
*>(v
);
326 name
= obj
->className();
328 name
= "(unknown class)";
330 if ( obj
->inherits(&ArrayInstance::info
) )
331 arrayLength
= obj
->get(exec
, exec
->propertyNames().length
)->toUInt32(exec
);
332 vString
= "[object " + name
+ "]";
335 case GetterSetterType
:
336 name
= "GetterSetter";
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
);
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
);
358 fprintf(stderr
, ", line %d\n",lineno
);
360 fprintf(stderr
, "\n");