• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kjs
 

kjs

  • kjs
object.cpp
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
5 * Copyright (C) 2003 Apple Computer, Inc.
6 *
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.
11 *
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.
16 *
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.
21 *
22 */
23
24#include "value.h"
25#include "object.h"
26#include "types.h"
27#include "interpreter.h"
28#include "lookup.h"
29#include "reference_list.h"
30
31#include <assert.h>
32#include <math.h>
33#include <stdio.h>
34
35#include "internal.h"
36#include "collector.h"
37#include "operations.h"
38#include "error_object.h"
39#include "nodes.h"
40
41using namespace KJS;
42
43// ------------------------------ Object ---------------------------------------
44
45Object Object::dynamicCast(const Value &v)
46{
47 if (!v.isValid() || v.type() != ObjectType)
48 return Object(0);
49
50 return Object(static_cast<ObjectImp*>(v.imp()));
51}
52
53Value Object::call(ExecState *exec, Object &thisObj, const List &args)
54{
55#if KJS_MAX_STACK > 0
56 static int depth = 0; // sum of all concurrent interpreters
57 if (++depth > KJS_MAX_STACK) {
58#ifndef NDEBUG
59 fprintf(stderr, "Exceeded maximum function call depth\n");
60#endif
61 int saveDepth = depth - 1;
62 Object err = Error::create(exec, RangeError,
63 "Exceeded maximum function call depth.");
64 depth = depth - 10; //Give some room for the debugger to operate,
65 //so if it tries to examine things we don't get here again
66 exec->setException(err);
67 depth = saveDepth;
68 return err;
69 }
70#endif
71
72 Value ret = static_cast<ObjectImp*>(rep)->call(exec,thisObj,args);
73
74#if KJS_MAX_STACK > 0
75 --depth;
76#endif
77
78 return ret;
79}
80
81// ------------------------------ ObjectImp ------------------------------------
82
83ObjectImp::ObjectImp(const Object &proto)
84 : _proto(static_cast<ObjectImp*>(proto.imp())), _internalValue(0L)
85{
86 //fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
87}
88
89ObjectImp::ObjectImp(ObjectImp *proto)
90 : _proto(proto), _internalValue(0L)
91{
92}
93
94ObjectImp::ObjectImp()
95{
96 //fprintf(stderr,"ObjectImp::ObjectImp %p\n",(void*)this);
97 _proto = NullImp::staticNull;
98 _internalValue = 0L;
99}
100
101ObjectImp::~ObjectImp()
102{
103 //fprintf(stderr,"ObjectImp::~ObjectImp %p\n",(void*)this);
104}
105
106void ObjectImp::mark()
107{
108 //fprintf(stderr,"ObjectImp::mark() %p\n",(void*)this);
109 ValueImp::mark();
110
111 if (_proto && !_proto->marked())
112 _proto->mark();
113
114 _prop.mark();
115
116 if (_internalValue && !_internalValue->marked())
117 _internalValue->mark();
118
119 _scope.mark();
120}
121
122const ClassInfo *ObjectImp::classInfo() const
123{
124 return 0;
125}
126
127bool ObjectImp::inherits(const ClassInfo *info) const
128{
129 if (!info)
130 return false;
131
132 const ClassInfo *ci = classInfo();
133 if (!ci)
134 return false;
135
136 while (ci && ci != info)
137 ci = ci->parentClass;
138
139 return (ci == info);
140}
141
142Type ObjectImp::type() const
143{
144 return ObjectType;
145}
146
147Value ObjectImp::prototype() const
148{
149 return Value(_proto);
150}
151
152void ObjectImp::setPrototype(const Value &proto)
153{
154 _proto = proto.imp();
155}
156
157UString ObjectImp::className() const
158{
159 const ClassInfo *ci = classInfo();
160 if ( ci )
161 return ci->className;
162 return "Object";
163}
164
165Value ObjectImp::get(ExecState *exec, const Identifier &propertyName) const
166{
167 ValueImp *imp = getDirect(propertyName);
168 if (imp)
169 return Value(imp);
170
171 Object proto = Object::dynamicCast(prototype());
172
173 // non-standard netscape extension
174 if (propertyName == specialPrototypePropertyName) {
175 if (!proto.isValid())
176 return Null();
177 else
178 return Value(proto);
179 }
180
181 if (!proto.isValid())
182 return Undefined();
183
184 return proto.get(exec,propertyName);
185}
186
187Value ObjectImp::getPropertyByIndex(ExecState *exec,
188 unsigned propertyName) const
189{
190 return get(exec, Identifier::from(propertyName));
191}
192
193// ECMA 8.6.2.2
194void ObjectImp::put(ExecState *exec, const Identifier &propertyName,
195 const Value &value, int attr)
196{
197 assert(value.isValid());
198
199 // non-standard netscape extension
200 if (propertyName == specialPrototypePropertyName) {
201 setPrototype(value);
202 return;
203 }
204
205 /* TODO: check for write permissions directly w/o this call */
206 /* Doesn't look very easy with the PropertyMap API - David */
207 // putValue() is used for JS assignemnts. It passes no attribute.
208 // Assume that a C++ implementation knows what it is doing
209 // and let it override the canPut() check.
210 if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName)) {
211#ifdef KJS_VERBOSE
212 fprintf( stderr, "[kjs-object] WARNING: canPut %s said NO\n", propertyName.ascii() );
213#endif
214 return;
215 }
216
217 _prop.put(propertyName,value.imp(),attr);
218}
219
220// delme
221void ObjectImp::putPropertyByIndex(ExecState *exec, unsigned propertyName,
222 const Value &value, int attr)
223{
224 put(exec, Identifier::from(propertyName), value, attr);
225}
226
227// ECMA 8.6.2.3
228bool ObjectImp::canPut(ExecState *, const Identifier &propertyName) const
229{
230 int attributes;
231 ValueImp *v = _prop.get(propertyName, attributes);
232 if (v)
233 return!(attributes & ReadOnly);
234
235 // Look in the static hashtable of properties
236 const HashEntry* e = findPropertyHashEntry(propertyName);
237 if (e)
238 return !(e->attr & ReadOnly);
239
240 // Don't look in the prototype here. We can always put an override
241 // in the object, even if the prototype has a ReadOnly property.
242 return true;
243}
244
245// ECMA 8.6.2.4
246bool ObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
247{
248 if (_prop.get(propertyName))
249 return true;
250
251 // Look in the static hashtable of properties
252 if (findPropertyHashEntry(propertyName))
253 return true;
254
255 // non-standard netscape extension
256 if (propertyName == specialPrototypePropertyName)
257 return true;
258
259 // Look in the prototype
260 Object proto = Object::dynamicCast(prototype());
261 return proto.isValid() && proto.hasProperty(exec,propertyName);
262}
263
264bool ObjectImp::hasPropertyByIndex(ExecState *exec, unsigned propertyName) const
265{
266 return hasProperty(exec, Identifier::from(propertyName));
267}
268
269// ECMA 8.6.2.5
270bool ObjectImp::deleteProperty(ExecState * /*exec*/, const Identifier &propertyName)
271{
272 int attributes;
273 ValueImp *v = _prop.get(propertyName, attributes);
274 if (v) {
275 if ((attributes & DontDelete))
276 return false;
277 _prop.remove(propertyName);
278 return true;
279 }
280
281 // Look in the static hashtable of properties
282 const HashEntry* entry = findPropertyHashEntry(propertyName);
283 if (entry && entry->attr & DontDelete)
284 return false; // this builtin property can't be deleted
285 return true;
286}
287
288bool ObjectImp::deletePropertyByIndex(ExecState *exec, unsigned propertyName)
289{
290 return deleteProperty(exec, Identifier::from(propertyName));
291}
292
293void ObjectImp::deleteAllProperties( ExecState * )
294{
295 _prop.clear();
296}
297
298// ECMA 8.6.2.6
299Value ObjectImp::defaultValue(ExecState *exec, Type hint) const
300{
301 if (hint != StringType && hint != NumberType) {
302 /* Prefer String for Date objects */
303 if (_proto == exec->lexicalInterpreter()->builtinDatePrototype().imp())
304 hint = StringType;
305 else
306 hint = NumberType;
307 }
308
309 Value v;
310 if (hint == StringType)
311 v = get(exec,toStringPropertyName);
312 else
313 v = get(exec,valueOfPropertyName);
314
315 if (v.type() == ObjectType) {
316 Object o = Object(static_cast<ObjectImp*>(v.imp()));
317 if (o.implementsCall()) { // spec says "not primitive type" but ...
318 Object thisObj = Object(const_cast<ObjectImp*>(this));
319 Value def = o.call(exec,thisObj,List::empty());
320 Type defType = def.type();
321 if (defType == UnspecifiedType || defType == UndefinedType ||
322 defType == NullType || defType == BooleanType ||
323 defType == StringType || defType == NumberType) {
324 return def;
325 }
326 }
327 }
328
329 if (hint == StringType)
330 v = get(exec,valueOfPropertyName);
331 else
332 v = get(exec,toStringPropertyName);
333
334 if (v.type() == ObjectType) {
335 Object o = Object(static_cast<ObjectImp*>(v.imp()));
336 if (o.implementsCall()) { // spec says "not primitive type" but ...
337 Object thisObj = Object(const_cast<ObjectImp*>(this));
338 Value def = o.call(exec,thisObj,List::empty());
339 Type defType = def.type();
340 if (defType == UnspecifiedType || defType == UndefinedType ||
341 defType == NullType || defType == BooleanType ||
342 defType == StringType || defType == NumberType) {
343 return def;
344 }
345 }
346 }
347
348 Object err = Error::create(exec, TypeError, I18N_NOOP("No default value"));
349 exec->setException(err);
350 return err;
351}
352
353const HashEntry* ObjectImp::findPropertyHashEntry( const Identifier& propertyName ) const
354{
355 const ClassInfo *info = classInfo();
356 while (info) {
357 if (info->propHashTable) {
358 const HashEntry *e = Lookup::findEntry(info->propHashTable, propertyName);
359 if (e)
360 return e;
361 }
362 info = info->parentClass;
363 }
364 return 0L;
365}
366
367bool ObjectImp::implementsConstruct() const
368{
369 return false;
370}
371
372Object ObjectImp::construct(ExecState* /*exec*/, const List &/*args*/)
373{
374 assert(false);
375 return Object(0);
376}
377
378bool ObjectImp::implementsCall() const
379{
380 return false;
381}
382
383Value ObjectImp::call(ExecState* /*exec*/, Object &/*thisObj*/, const List &/*args*/)
384{
385 assert(false);
386 return Object(0);
387}
388
389bool ObjectImp::implementsHasInstance() const
390{
391 return false;
392}
393
394Boolean ObjectImp::hasInstance(ExecState* /*exec*/, const Value &/*value*/)
395{
396 assert(false);
397 return Boolean(false);
398}
399
400ReferenceList ObjectImp::propList(ExecState *exec, bool recursive)
401{
402 ReferenceList list;
403 if (_proto && _proto->dispatchType() == ObjectType && recursive)
404 list = static_cast<ObjectImp*>(_proto)->propList(exec,recursive);
405
406 _prop.addEnumerablesToReferenceList(list, Object(this));
407
408 // Add properties from the static hashtable of properties
409 const ClassInfo *info = classInfo();
410 while (info) {
411 if (info->propHashTable) {
412 int size = info->propHashTable->size;
413 const HashEntry *e = info->propHashTable->entries;
414 for (int i = 0; i < size; ++i, ++e) {
415 if ( e->soffset && !(e->attr & DontEnum) )
416 list.append(Reference(this, &info->propHashTable->sbase[e->soffset]));
417 }
418 }
419 info = info->parentClass;
420 }
421
422 return list;
423}
424
425Value ObjectImp::internalValue() const
426{
427 return Value(_internalValue);
428}
429
430void ObjectImp::setInternalValue(const Value &v)
431{
432 _internalValue = v.imp();
433}
434
435void ObjectImp::setInternalValue(ValueImp *v)
436{
437 v->setGcAllowed();
438 _internalValue = v;
439}
440
441Value ObjectImp::toPrimitive(ExecState *exec, Type preferredType) const
442{
443 return defaultValue(exec,preferredType);
444}
445
446bool ObjectImp::toBoolean(ExecState* /*exec*/) const
447{
448 return true;
449}
450
451double ObjectImp::toNumber(ExecState *exec) const
452{
453 Value prim = toPrimitive(exec,NumberType);
454 if (exec->hadException()) // should be picked up soon in nodes.cpp
455 return 0.0;
456 return prim.toNumber(exec);
457}
458
459UString ObjectImp::toString(ExecState *exec) const
460{
461 Value prim = toPrimitive(exec,StringType);
462 if (exec->hadException()) // should be picked up soon in nodes.cpp
463 return "";
464 return prim.toString(exec);
465}
466
467Object ObjectImp::toObject(ExecState * /*exec*/) const
468{
469 return Object(const_cast<ObjectImp*>(this));
470}
471
472void ObjectImp::putDirect(const Identifier &propertyName, ValueImp *value, int attr)
473{
474 value->setGcAllowed();
475 _prop.put(propertyName, value, attr);
476}
477
478void ObjectImp::putDirect(const Identifier &propertyName, int value, int attr)
479{
480 _prop.put(propertyName, NumberImp::create(value), attr);
481}
482
483void ObjectImp::setFunctionName(const Identifier &propertyName)
484{
485 if (inherits(&InternalFunctionImp::info))
486 static_cast<InternalFunctionImp*>(this)->setName(propertyName);
487}
488
489// ------------------------------ Error ----------------------------------------
490
491const char * const errorNamesArr[] = {
492 I18N_NOOP("Error"), // GeneralError
493 I18N_NOOP("Evaluation error"), // EvalError
494 I18N_NOOP("Range error"), // RangeError
495 I18N_NOOP("Reference error"), // ReferenceError
496 I18N_NOOP("Syntax error"), // SyntaxError
497 I18N_NOOP("Type error"), // TypeError
498 I18N_NOOP("URI error"), // URIError
499};
500
501const char * const * const Error::errorNames = errorNamesArr;
502
503Object Error::create(ExecState *exec, ErrorType errtype, const char *message,
504 int lineno, int sourceId)
505{
506#ifdef KJS_VERBOSE
507 // message could be 0L. Don't enable this on Solaris ;)
508 fprintf(stderr, "WARNING: KJS %s: %s\n", errorNames[errtype], message);
509#endif
510
511 Object cons;
512
513 switch (errtype) {
514 case EvalError:
515 cons = exec->lexicalInterpreter()->builtinEvalError();
516 break;
517 case RangeError:
518 cons = exec->lexicalInterpreter()->builtinRangeError();
519 break;
520 case ReferenceError:
521 cons = exec->lexicalInterpreter()->builtinReferenceError();
522 break;
523 case SyntaxError:
524 cons = exec->lexicalInterpreter()->builtinSyntaxError();
525 break;
526 case TypeError:
527 cons = exec->lexicalInterpreter()->builtinTypeError();
528 break;
529 case URIError:
530 cons = exec->lexicalInterpreter()->builtinURIError();
531 break;
532 default:
533 cons = exec->lexicalInterpreter()->builtinError();
534 break;
535 }
536
537 if (!message)
538 message = errorNames[errtype];
539 List args;
540 args.append(String(message));
541 Object err = Object::dynamicCast(cons.construct(exec,args));
542
543 if (lineno != -1)
544 err.put(exec, "line", Number(lineno));
545 if (sourceId != -1)
546 err.put(exec, "sourceId", Number(sourceId));
547
548 return err;
549
550/*
551#ifndef NDEBUG
552 const char *msg = err.get(messagePropertyName).toString().value().ascii();
553 if (l >= 0)
554 fprintf(stderr, "KJS: %s at line %d. %s\n", estr, l, msg);
555 else
556 fprintf(stderr, "KJS: %s. %s\n", estr, msg);
557#endif
558
559 return err;
560*/
561}
562
KJS::Boolean
Represents an primitive Boolean value.
Definition: value.h:316
KJS::Error::create
static Object create(ExecState *exec, ErrorType errtype=GeneralError, const char *message=0, int lineno=-1, int sourceId=-1)
Factory method for error objects.
Definition: object.cpp:503
KJS::Error::errorNames
static const char *const *const errorNames
Array of error names corresponding to ErrorType.
Definition: object.h:644
KJS::ExecState
Represents the current state of script execution.
Definition: interpreter.h:438
KJS::ExecState::lexicalInterpreter
Interpreter * lexicalInterpreter() const
Returns the interpreter associated with the current scope's global object.
Definition: interpreter.cpp:394
KJS::Identifier
Represents an Identifier for a Javascript object.
Definition: identifier.h:32
KJS::Identifier::ascii
const char * ascii() const
Char * of the identifier's string.
Definition: identifier.h:71
KJS::InternalFunctionImp
Base class for all function objects.
Definition: function.h:40
KJS::Interpreter::builtinError
Object builtinError() const
Returns the builtin "Error" object.
Definition: interpreter.cpp:213
KJS::Interpreter::builtinDatePrototype
Object builtinDatePrototype() const
Returns the builtin "Date.prototype" object.
Definition: interpreter.cpp:248
KJS::Interpreter::builtinEvalError
Object builtinEvalError() const
The initial value of "Error" global property.
Definition: interpreter.cpp:263
KJS::List
Native list type.
Definition: list.h:48
KJS::List::append
void append(const Value &val)
Append an object to the end of the list.
Definition: list.h:66
KJS::List::empty
static const List & empty()
Returns a pointer to a static instance of an empty list.
Definition: list.cpp:322
KJS::Lookup::findEntry
static const HashEntry * findEntry(const struct HashTable *table, const Identifier &s)
Find an entry in the table, and return the entry This variant gives access to the other attributes of...
Definition: lookup.cpp:71
KJS::Null
Represents an primitive Null value.
Definition: value.h:294
KJS::Number
Represents an primitive Number value.
Definition: value.h:367
KJS::Object
Represents an Object.
Definition: object.h:81
KJS::Object::implementsCall
bool implementsCall() const
Whether or not the object implements the call() method.
Definition: object.h:699
KJS::Object::construct
Object construct(ExecState *exec, const List &args)
Creates a new object based on this object.
Definition: object.h:696
KJS::Object::put
void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr=None)
Sets the specified property.
Definition: object.h:669
KJS::Object::call
Value call(ExecState *exec, Object &thisObj, const List &args)
Calls this object as if it is a function.
Definition: object.cpp:53
KJS::Object::dynamicCast
static Object dynamicCast(const Value &v)
Converts a Value into an Object.
Definition: object.cpp:45
KJS::Object::hasProperty
bool hasProperty(ExecState *exec, const Identifier &propertyName) const
Checks to see whether the object (or any object in it's prototype chain) has a property with the spec...
Definition: object.h:678
KJS::Object::get
Value get(ExecState *exec, const Identifier &propertyName) const
Retrieves the specified property from the object.
Definition: object.h:663
KJS::ReferenceList
A list of Reference objects.
Definition: reference_list.h:53
KJS::Reference
Defines a Javascript reference.
Definition: reference.h:34
KJS::String
Represents an primitive String value.
Definition: value.h:340
KJS::UString
Unicode string class.
Definition: ustring.h:189
KJS::Undefined
Represents an primitive Undefined value.
Definition: value.h:269
KJS::ValueImp
ValueImp is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects i...
Definition: value.h:78
KJS::Value
Value objects are act as wrappers ("smart pointers") around ValueImp objects and their descendents.
Definition: value.h:167
KJS::Value::toString
UString toString(ExecState *exec) const
Performs the ToString type conversion operation on this value (ECMA 9.8)
Definition: value.h:246
KJS::Value::isValid
bool isValid() const
Returns whether or not this is a valid value.
Definition: value.h:181
KJS::Value::type
Type type() const
Returns the type of value.
Definition: value.h:195
KJS::Value::toNumber
double toNumber(ExecState *exec) const
Performs the ToNumber type conversion operation on this value (ECMA 9.3)
Definition: value.h:221
KJS::ClassInfo
Class Information.
Definition: object.h:58
KJS::ClassInfo::className
const char * className
A string denoting the class name.
Definition: object.h:62
KJS::ClassInfo::propHashTable
const HashTable * propHashTable
Static hash-table of properties.
Definition: object.h:71
KJS::ClassInfo::parentClass
const ClassInfo * parentClass
Pointer to the class information of the base class.
Definition: object.h:67
KJS::HashEntry
An entry in a hash table.
Definition: lookup.h:36
KJS::HashEntry::attr
unsigned char attr
attr is a set for flags (e.g.
Definition: lookup.h:48
KJS::HashEntry::soffset
unsigned short soffset
s is the offset to the string key (e.g.
Definition: lookup.h:40
KJS::HashTable::sbase
const char *const sbase
pointer to the string table.
Definition: lookup.h:95
KJS::HashTable::entries
const HashEntry *const entries
pointer to the array of entries Mind that some entries in the array are null (0,0,...
Definition: lookup.h:86
KJS::HashTable::size
int size
size is the total number of entries in the hashtable, including the null entries, i....
Definition: lookup.h:81

kjs

Skip menu "kjs"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kjs

Skip menu "kjs"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kjs by doxygen 1.9.4
This website is maintained by Timothy Pearson.