source: webkit/trunk/JavaScriptCore/kjs/object.cpp@ 34424

Last change on this file since 34424 was 34355, checked in by Darin Adler, 17 years ago

JavaScriptCore:

2008-06-03 Darin Adler <Darin Adler>

Reviewed by Geoff.

Makes standalone SunSpider 1.025x as fast as before.

The getOwnPropertySlot virtual function now takes care of the toObject call
for get. Similarly, the put function (and later deleteProperty) does the
same for those operations. To do this, the virtual functions were moved from
the JSObject class to the JSCell class. Also, since the caller no longer knows
the identity of the "original object", which is used by JavaScript-function
based getters, changed the PropertySlot class so the original object is
already stored in the slot when getOwnPropertySlot is called, if the caller
intends to call getValue.

This affected the old interpreter code enough that the easiest thing for me
was to just delete it. While I am not certain the mysterious slowdown is not
still occurring, the net change is definitely a significant speedup.

  • VM/Machine.cpp: Moved the UNLIKELY macro into AlwaysInline.h. (KJS::resolve): Set up the originalObject in the PropertySlot before calling getPropertySlot. Also removed the originalObject argument from getValue. (KJS::resolve_skip): Ditto. (KJS::resolveBaseAndProperty): Ditto. (KJS::resolveBaseAndFunc): Ditto. (KJS::Machine::privateExecute): Removed the toObject calls from the get and put functions where possible, instead calling directly with JSValue and letting the JSValue and JSCell calls handle toObject. Same for toThisObject.
  • kjs/ExecState.h: Removed OldInterpreterExecState.
  • API/JSBase.cpp: Updated includes.
  • kjs/LocalStorageEntry.h: Removed contents. Later we can remove the file too.
  • kjs/array_instance.cpp: (KJS::ArrayInstance::lengthGetter): Removed originalObject argumet. (KJS::ArrayInstance::inlineGetOwnPropertySlot): Don't pass a base value to setValueSlot. Also use UNLIKELY around the "getting elements past the end of the array" code path; less common than successfully getting an element.
  • kjs/array_object.cpp: (KJS::getProperty): Initialize the PropertySlot with the original object. Don't pass the original object to the get function. (KJS::arrayProtoFuncFilter): Ditto. (KJS::arrayProtoFuncMap): Ditto. (KJS::arrayProtoFuncEvery): Ditto. (KJS::arrayProtoFuncForEach): Ditto. (KJS::arrayProtoFuncSome): Ditto.
  • kjs/function_object.cpp: (KJS::FunctionObjectImp::construct): Removed an obsolete comment.
  • kjs/grammar.y: Eliminated support for some of the node types that were used to optimize executing from the syntax tree.
  • kjs/internal.cpp: (KJS::StringImp::toThisObject): Added. Same as toObject. (KJS::NumberImp::toThisObject): Ditto. (KJS::GetterSetterImp::getOwnPropertySlot): Added. Not reached. (KJS::GetterSetterImp::put): Ditto. (KJS::GetterSetterImp::toThisObject): Ditto.
  • kjs/internal.h: Added toThisObject to NumberImp for speed.
  • kjs/lexer.cpp: (KJS::Lexer::shift): Changed shift to just do a single character, to unroll the loop and especially to make the one character case faster. (KJS::Lexer::setCode): Call shift multiple times instead of passing a number. (KJS::Lexer::lex): Ditto. (KJS::Lexer::matchPunctuator): Ditto. Also removed unneeded elses after returns. (KJS::Lexer::scanRegExp): Ditto.
  • kjs/lexer.h: Removed the count argument from shift.
  • kjs/math_object.cpp: (KJS::mathProtoFuncPow): Call jsNaN instead of jsNumber(NaN).
  • kjs/nodes.cpp: Removed some of the things needed only for the pre-SquirrelFish execution model. (KJS::ForNode::emitCode): Handle cases where some expressions are missing by not emitting any code at all. The old way was to emit code for "true", but this is an unnecessary remnant of the old way of doing things.
  • kjs/nodes.h: Removed some of the things needed only for the pre-SquirrelFish execution model.
  • kjs/object.cpp: (KJS::JSObject::fillGetterPropertySlot): Changed to only pass in the getter function. The old code passed in a base, but it was never used when actually getting the property; the toThisObject call was pointless. Also changed to not pass a base for setUndefined.
  • kjs/object.h: Added the new JSCell operations to GetterSetterImp. Never called. (KJS::JSObject::get): Initialize the object in the PropertySlot and don't pass it in getValue. (KJS::JSObject::getOwnPropertySlotForWrite): Removed the base argument in calls to setValueSlot. (KJS::JSObject::getOwnPropertySlot): Ditto. (KJS::JSValue::get): Added. Here because it calls through to JSObject. A version of JSObject::get that also handles the other types of JSValue by creating the appropriate wrapper. Saves the virtual call to toObject. (KJS::JSValue::put): Ditto. (KJS::JSValue::deleteProperty): Ditto.
  • kjs/property_slot.cpp: (KJS::PropertySlot::undefinedGetter): Removed the originalObject argument. (KJS::PropertySlot::ungettableGetter): Ditto. (KJS::PropertySlot::functionGetter): Ditto. Use the value in the base as the "this" object, which will be set to the original object by the new PropertySlot initialization code. Also call toThisObject. The old code did not do this, but needed to so we can properly handle the activation object like the other similar code paths.
  • kjs/property_slot.h: (KJS::PropertySlot::PropertySlot): Added a constructor that takes a base object. In debug builds, set the base to 0 if you don't pass one. (KJS::PropertySlot::getValue): Don't take or pass the originalObject. (KJS::PropertySlot::setValueSlot): Don't take a base object, and clear the base object in debug builds. (KJS::PropertySlot::setGetterSlot): Ditto. (KJS::PropertySlot::setUndefined): Ditto. (KJS::PropertySlot::setUngettable): Ditto. (KJS::PropertySlot::slotBase): Assert that a base object is present. This will fire if someone actually calls the get function without having passed in a base object and the getter needs it. (KJS::PropertySlot::setBase): Added. Used by the code that implements toObject so it can supply the original object after the fact. (KJS::PropertySlot::clearBase): Added. Clears the base, but is debug-only code because it's an error to fetch the base if you don't have a guarantee it was set.
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h: (KJS::JSCallbackObject::cachedValueGetter): (KJS::JSCallbackObject::staticValueGetter): (KJS::JSCallbackObject::staticFunctionGetter): (KJS::JSCallbackObject::callbackGetter):
  • kjs/JSActivation.cpp: (KJS::JSActivation::getOwnPropertySlot): (KJS::JSActivation::argumentsGetter):
  • kjs/JSActivation.h:
  • kjs/JSVariableObject.h: (KJS::JSVariableObject::symbolTableGet):
  • kjs/array_instance.h:
  • kjs/function.cpp: (KJS::FunctionImp::argumentsGetter): (KJS::FunctionImp::callerGetter): (KJS::FunctionImp::lengthGetter): (KJS::Arguments::mappedIndexGetter):
  • kjs/function.h:
  • kjs/lookup.h: (KJS::staticFunctionGetter): (KJS::staticValueGetter):
  • kjs/string_object.cpp: (KJS::StringInstance::lengthGetter): (KJS::StringInstance::indexGetter): (KJS::stringInstanceNumericPropertyGetter):
  • kjs/string_object.h: Removed originalObject arguments from getters. Don't pass base values to the various PropertySlot functions that no longer take them.
  • kjs/value.cpp: (KJS::JSCell::getOwnPropertySlot): Added. Calls toObject and then sets the slot. This function has to always return true, because the caller can't walk the prototype chain. Because of that, we do a getPropertySlot, not getOwnPropertySlot, which works for the caller. This is private, only called by getOwnPropertySlotInternal. (KJS::JSCell::put): Added. Calls toObject and then put. (KJS::JSCell::toThisObject): Added. Calls toObject.
  • kjs/value.h: Added get, put, and toThisObject to both JSValue and JSCell. These take care of the toObject operation without an additional virtual function call, and so make the common "already an object" case faster.
  • wtf/AlwaysInline.h: Moved the UNLIKELY macro here for now. Maybe we can find a better place later, or rename this header.

JavaScriptGlue:

2008-06-03 Darin Adler <Darin Adler>

  • UserObjectImp.cpp: (UserObjectImp::userObjectGetter): Removed originalObject argument.
  • UserObjectImp.h: Ditto.

WebCore:

2008-06-03 Justin Garcia <[email protected]>

Reviewed by John.

<rdar://problem/5763082> GMail: Hang when removing indent from nested list
<rdar://problem/5775449> In Gmail and GoogleDocs, a hang occurs when I attempt to apply a list style to a large selection of text
<rdar://problem/5937624> 9D32: Hang in Safari. Using 100% of processor

  • editing/InsertListCommand.cpp: (WebCore::InsertListCommand::modifyRange): doApply() may operate on and remove the last paragraph of the selection from the document if it's in the same list item as startOfCurrentParagraph. Return early to avoid an infinite loop and because there is no more work to be done. Added a FIXME (<rdar://problem/5983974>) about the incorrect endingSelection()s.
  • Property svn:eol-style set to native
File size: 17.1 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * Copyright (C) 1999-2001 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Eric Seidel ([email protected])
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "object.h"
27
28#include "date_object.h"
29#include "error_object.h"
30#include "nodes.h"
31#include "operations.h"
32#include "PropertyNameArray.h"
33#include <math.h>
34#include <profiler/Profiler.h>
35#include <wtf/Assertions.h>
36
37#define JAVASCRIPT_MARK_TRACING 0
38
39namespace KJS {
40
41// ------------------------------ JSObject ------------------------------------
42
43void JSObject::mark()
44{
45 JSCell::mark();
46
47#if JAVASCRIPT_MARK_TRACING
48 static int markStackDepth = 0;
49 markStackDepth++;
50 for (int i = 0; i < markStackDepth; i++)
51 putchar('-');
52
53 printf("%s (%p)\n", className().UTF8String().c_str(), this);
54#endif
55
56 JSValue *proto = _proto;
57 if (!proto->marked())
58 proto->mark();
59
60 _prop.mark();
61
62#if JAVASCRIPT_MARK_TRACING
63 markStackDepth--;
64#endif
65}
66
67JSType JSObject::type() const
68{
69 return ObjectType;
70}
71
72const ClassInfo *JSObject::classInfo() const
73{
74 return 0;
75}
76
77UString JSObject::className() const
78{
79 const ClassInfo *ci = classInfo();
80 if ( ci )
81 return ci->className;
82 return "Object";
83}
84
85bool JSObject::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
86{
87 return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
88}
89
90static void throwSetterError(ExecState *exec)
91{
92 throwError(exec, TypeError, "setting a property that has only a getter");
93}
94
95// ECMA 8.6.2.2
96void JSObject::put(ExecState* exec, const Identifier &propertyName, JSValue *value)
97{
98 ASSERT(value);
99
100 if (propertyName == exec->propertyNames().underscoreProto) {
101 JSObject* proto = value->getObject();
102
103 // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla
104 if (!proto && value != jsNull())
105 return;
106
107 while (proto) {
108 if (proto == this) {
109 throwError(exec, GeneralError, "cyclic __proto__ value");
110 return;
111 }
112 proto = proto->prototype() ? proto->prototype()->getObject() : 0;
113 }
114
115 setPrototype(value);
116 return;
117 }
118
119 // Check if there are any setters or getters in the prototype chain
120 JSObject *obj = this;
121 bool hasGettersOrSetters = false;
122 while (true) {
123 if (obj->_prop.hasGetterSetterProperties()) {
124 hasGettersOrSetters = true;
125 break;
126 }
127
128 if (obj->_proto == jsNull())
129 break;
130
131 obj = static_cast<JSObject *>(obj->_proto);
132 }
133
134 if (hasGettersOrSetters) {
135 unsigned attributes;
136 if (_prop.get(propertyName, attributes) && attributes & ReadOnly)
137 return;
138
139 obj = this;
140 while (true) {
141 if (JSValue *gs = obj->_prop.get(propertyName, attributes)) {
142 if (attributes & GetterSetter) {
143 JSObject *setterFunc = static_cast<GetterSetterImp *>(gs)->getSetter();
144
145 if (!setterFunc) {
146 throwSetterError(exec);
147 return;
148 }
149
150 List args;
151 args.append(value);
152
153 setterFunc->callAsFunction(exec, this->toThisObject(exec), args);
154 return;
155 } else {
156 // If there's an existing property on the object or one of its
157 // prototype it should be replaced, so we just break here.
158 break;
159 }
160 }
161
162 if (!obj->_proto->isObject())
163 break;
164
165 obj = static_cast<JSObject *>(obj->_proto);
166 }
167 }
168
169 _prop.put(propertyName, value, 0, true);
170}
171
172void JSObject::put(ExecState* exec, unsigned propertyName, JSValue* value)
173{
174 put(exec, Identifier::from(propertyName), value);
175}
176
177void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
178{
179 putDirect(propertyName, value, attributes);
180}
181
182void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue* value, unsigned attributes)
183{
184 putWithAttributes(exec, Identifier::from(propertyName), value, attributes);
185}
186
187bool JSObject::hasProperty(ExecState *exec, const Identifier &propertyName) const
188{
189 PropertySlot slot;
190 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
191}
192
193bool JSObject::hasProperty(ExecState *exec, unsigned propertyName) const
194{
195 PropertySlot slot;
196 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
197}
198
199// ECMA 8.6.2.5
200bool JSObject::deleteProperty(ExecState* exec, const Identifier &propertyName)
201{
202 unsigned attributes;
203 JSValue *v = _prop.get(propertyName, attributes);
204 if (v) {
205 if ((attributes & DontDelete))
206 return false;
207 _prop.remove(propertyName);
208 if (attributes & GetterSetter)
209 _prop.setHasGetterSetterProperties(_prop.containsGettersOrSetters());
210 return true;
211 }
212
213 // Look in the static hashtable of properties
214 const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
215 if (entry && entry->attributes & DontDelete)
216 return false; // this builtin property can't be deleted
217 // FIXME: Should the code here actually do some deletion?
218 return true;
219}
220
221bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
222{
223 PropertySlot slot;
224 return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
225}
226
227bool JSObject::deleteProperty(ExecState *exec, unsigned propertyName)
228{
229 return deleteProperty(exec, Identifier::from(propertyName));
230}
231
232static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObject *object, const Identifier &propertyName) {
233 JSValue* v = object->get(exec, propertyName);
234 if (v->isObject()) {
235 JSObject* o = static_cast<JSObject*>(v);
236 CallData data;
237 CallType callType = o->getCallData(data);
238 // spec says "not primitive type" but ...
239 if (callType != CallTypeNone) {
240 JSObject* thisObj = const_cast<JSObject*>(object);
241 JSValue* def = o->callAsFunction(exec, thisObj->toThisObject(exec), exec->emptyList());
242 JSType defType = def->type();
243 ASSERT(defType != GetterSetterType);
244 if (defType != ObjectType)
245 return def;
246 }
247 }
248 return NULL;
249}
250
251bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
252{
253 result = defaultValue(exec, NumberType);
254 number = result->toNumber(exec);
255 return !result->isString();
256}
257
258// ECMA 8.6.2.6
259JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
260{
261 // We need this check to guard against the case where this object is rhs of
262 // a binary expression where lhs threw an exception in its conversion to
263 // primitive
264 if (exec->hadException())
265 return exec->exception();
266 /* Prefer String for Date objects */
267 if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {
268 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
269 return v;
270 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().valueOf))
271 return v;
272 } else {
273 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().valueOf))
274 return v;
275 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
276 return v;
277 }
278
279 if (exec->hadException())
280 return exec->exception();
281
282 return throwError(exec, TypeError, "No default value");
283}
284
285const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const
286{
287 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
288 if (const HashTable* propHashTable = info->propHashTable(exec)) {
289 if (const HashEntry* e = propHashTable->entry(propertyName))
290 return e;
291 }
292 }
293 return 0;
294}
295
296void JSObject::defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc)
297{
298 JSValue *o = getDirect(propertyName);
299 GetterSetterImp *gs;
300
301 if (o && o->type() == GetterSetterType) {
302 gs = static_cast<GetterSetterImp *>(o);
303 } else {
304 gs = new GetterSetterImp;
305 putDirect(propertyName, gs, GetterSetter);
306 }
307
308 _prop.setHasGetterSetterProperties(true);
309 gs->setGetter(getterFunc);
310}
311
312void JSObject::defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc)
313{
314 JSValue *o = getDirect(propertyName);
315 GetterSetterImp *gs;
316
317 if (o && o->type() == GetterSetterType) {
318 gs = static_cast<GetterSetterImp *>(o);
319 } else {
320 gs = new GetterSetterImp;
321 putDirect(propertyName, gs, GetterSetter);
322 }
323
324 _prop.setHasGetterSetterProperties(true);
325 gs->setSetter(setterFunc);
326}
327
328JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
329{
330 JSObject* obj = this;
331 while (true) {
332 JSValue* v = obj->getDirect(propertyName);
333 if (v) {
334 if (v->type() != GetterSetterType)
335 return jsUndefined();
336 JSObject* funcObj = static_cast<GetterSetterImp*>(v)->getGetter();
337 if (!funcObj)
338 return jsUndefined();
339 return funcObj;
340 }
341
342 if (!obj->prototype() || !obj->prototype()->isObject())
343 return jsUndefined();
344 obj = static_cast<JSObject*>(obj->prototype());
345 }
346}
347
348JSValue* JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
349{
350 JSObject* obj = this;
351 while (true) {
352 JSValue* v = obj->getDirect(propertyName);
353 if (v) {
354 if (v->type() != GetterSetterType)
355 return jsUndefined();
356 JSObject* funcObj = static_cast<GetterSetterImp*>(v)->getSetter();
357 if (!funcObj)
358 return jsUndefined();
359 return funcObj;
360 }
361
362 if (!obj->prototype() || !obj->prototype()->isObject())
363 return jsUndefined();
364 obj = static_cast<JSObject*>(obj->prototype());
365 }
366}
367
368JSObject* JSObject::construct(ExecState*, const List& /*args*/)
369{
370 ASSERT(false);
371 return NULL;
372}
373
374JSObject* JSObject::construct(ExecState* exec, const List& args, const Identifier& /*functionName*/, const UString& /*sourceURL*/, int /*lineNumber*/)
375{
376 return construct(exec, args);
377}
378
379bool JSObject::implementsCall()
380{
381 CallData callData;
382 return getCallData(callData) != CallTypeNone;
383}
384
385JSValue *JSObject::callAsFunction(ExecState* /*exec*/, JSObject* /*thisObj*/, const List &/*args*/)
386{
387 ASSERT(false);
388 return NULL;
389}
390
391bool JSObject::implementsHasInstance() const
392{
393 return false;
394}
395
396bool JSObject::hasInstance(ExecState* exec, JSValue* value)
397{
398 JSValue* proto = get(exec, exec->propertyNames().prototype);
399 if (!proto->isObject()) {
400 throwError(exec, TypeError, "intanceof called on an object with an invalid prototype property.");
401 return false;
402 }
403
404 if (!value->isObject())
405 return false;
406
407 JSObject* o = static_cast<JSObject*>(value);
408 while ((o = o->prototype()->getObject())) {
409 if (o == proto)
410 return true;
411 }
412 return false;
413}
414
415bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
416{
417 unsigned attributes;
418
419 if (!getPropertyAttributes(exec, propertyName, attributes))
420 return false;
421 else
422 return !(attributes & DontEnum);
423}
424
425bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
426{
427 if (_prop.get(propertyName, attributes))
428 return true;
429
430 // Look in the static hashtable of properties
431 const HashEntry* e = findPropertyHashEntry(exec, propertyName);
432 if (e) {
433 attributes = e->attributes;
434 return true;
435 }
436
437 return false;
438}
439
440void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
441{
442 _prop.getEnumerablePropertyNames(propertyNames);
443
444 // Add properties from the static hashtables of properties
445 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
446 const HashTable* table = info->propHashTable(exec);
447 if (!table)
448 continue;
449 if (!table->table)
450 table->createTable();
451 ASSERT(table->table);
452 int hashSizeMask = table->hashSizeMask;
453 const HashEntry* e = table->table;
454 for (int i = 0; i <= hashSizeMask; ++i, ++e) {
455 if (e->key && !(e->attributes & DontEnum))
456 propertyNames.add(e->key);
457 }
458 }
459
460 if (_proto->isObject())
461 static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames);
462}
463
464bool JSObject::toBoolean(ExecState*) const
465{
466 return true;
467}
468
469double JSObject::toNumber(ExecState *exec) const
470{
471 JSValue *prim = toPrimitive(exec,NumberType);
472 if (exec->hadException()) // should be picked up soon in nodes.cpp
473 return 0.0;
474 return prim->toNumber(exec);
475}
476
477UString JSObject::toString(ExecState *exec) const
478{
479 JSValue *prim = toPrimitive(exec,StringType);
480 if (exec->hadException()) // should be picked up soon in nodes.cpp
481 return "";
482 return prim->toString(exec);
483}
484
485JSObject *JSObject::toObject(ExecState*) const
486{
487 return const_cast<JSObject*>(this);
488}
489
490JSObject* JSObject::toThisObject(ExecState*) const
491{
492 return const_cast<JSObject*>(this);
493}
494
495JSGlobalObject* JSObject::toGlobalObject(ExecState*) const
496{
497 return 0;
498}
499
500void JSObject::removeDirect(const Identifier &propertyName)
501{
502 _prop.remove(propertyName);
503}
504
505void JSObject::putDirectFunction(InternalFunctionImp* func, int attr)
506{
507 putDirect(func->functionName(), func, attr);
508}
509
510void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue **location)
511{
512 GetterSetterImp *gs = static_cast<GetterSetterImp *>(*location);
513 JSObject *getterFunc = gs->getGetter();
514 if (getterFunc)
515 slot.setGetterSlot(getterFunc);
516 else
517 slot.setUndefined();
518}
519
520// ------------------------------ Error ----------------------------------------
521
522const char * const errorNamesArr[] = {
523 I18N_NOOP("Error"), // GeneralError
524 I18N_NOOP("Evaluation error"), // EvalError
525 I18N_NOOP("Range error"), // RangeError
526 I18N_NOOP("Reference error"), // ReferenceError
527 I18N_NOOP("Syntax error"), // SyntaxError
528 I18N_NOOP("Type error"), // TypeError
529 I18N_NOOP("URI error"), // URIError
530};
531
532const char * const * const Error::errorNames = errorNamesArr;
533
534JSObject *Error::create(ExecState *exec, ErrorType errtype, const UString &message,
535 int lineno, int sourceId, const UString &sourceURL)
536{
537 JSObject *cons;
538 switch (errtype) {
539 case EvalError:
540 cons = exec->lexicalGlobalObject()->evalErrorConstructor();
541 break;
542 case RangeError:
543 cons = exec->lexicalGlobalObject()->rangeErrorConstructor();
544 break;
545 case ReferenceError:
546 cons = exec->lexicalGlobalObject()->referenceErrorConstructor();
547 break;
548 case SyntaxError:
549 cons = exec->lexicalGlobalObject()->syntaxErrorConstructor();
550 break;
551 case TypeError:
552 cons = exec->lexicalGlobalObject()->typeErrorConstructor();
553 break;
554 case URIError:
555 cons = exec->lexicalGlobalObject()->URIErrorConstructor();
556 break;
557 default:
558 cons = exec->lexicalGlobalObject()->errorConstructor();
559 break;
560 }
561
562 List args;
563 if (message.isEmpty())
564 args.append(jsString(errorNames[errtype]));
565 else
566 args.append(jsString(message));
567 JSObject *err = static_cast<JSObject *>(cons->construct(exec,args));
568
569 if (lineno != -1)
570 err->put(exec, "line", jsNumber(lineno));
571 if (sourceId != -1)
572 err->put(exec, "sourceId", jsNumber(sourceId));
573
574 if(!sourceURL.isNull())
575 err->put(exec, "sourceURL", jsString(sourceURL));
576
577 return err;
578}
579
580JSObject *Error::create(ExecState *exec, ErrorType type, const char *message)
581{
582 return create(exec, type, message, -1, -1, NULL);
583}
584
585JSObject *throwError(ExecState *exec, ErrorType type)
586{
587 JSObject *error = Error::create(exec, type, UString(), -1, -1, NULL);
588 exec->setException(error);
589 return error;
590}
591
592JSObject *throwError(ExecState *exec, ErrorType type, const UString &message)
593{
594 JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
595 exec->setException(error);
596 return error;
597}
598
599JSObject *throwError(ExecState *exec, ErrorType type, const char *message)
600{
601 JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
602 exec->setException(error);
603 return error;
604}
605
606JSObject *throwError(ExecState *exec, ErrorType type, const UString &message, int line, int sourceId, const UString &sourceURL)
607{
608 JSObject *error = Error::create(exec, type, message, line, sourceId, sourceURL);
609 exec->setException(error);
610 return error;
611}
612
613} // namespace KJS
Note: See TracBrowser for help on using the repository browser.