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

Last change on this file since 28923 was 28884, checked in by [email protected], 17 years ago

JavaScriptCore:

Reviewed by Oliver Hunt.


Optimized global access to global variables, using a symbol table.


SunSpider reports a 1.5% overall speedup, a 6.2% speedup on 3d-morph,
and a whopping 33.1% speedup on bitops-bitwise-and.

  • API/JSCallbackObjectFunctions.h: Replaced calls to JSObject:: with calls to Base::, since JSObject is not always our base class. This was always a bug, but the bug is even more apparent after some of my changes.

(KJS::::staticFunctionGetter): Replaced use of getDirect with call to
getOwnPropertySlot. Global declarations are no longer stored in the
property map, so a call to getDirect is insufficient for finding
override properties.

  • API/testapi.c:
  • API/testapi.js: Added test for the getDirect change mentioned above.
  • kjs/ExecState.cpp:
  • kjs/ExecState.h: Dialed back the optimization to store a direct pointer to the localStorage buffer. One ExecState can grow the global object's localStorage without another ExecState's knowledge, so ExecState can't store a direct pointer to the localStorage buffer unless/until we invent a way to update all the relevant ExecStates.
  • kjs/JSGlobalObject.cpp: Inserted the symbol table into get and put operations. (KJS::JSGlobalObject::reset): Reset the symbol table and local storage, too. Also, clear the property map here, removing the need for a separate call.
  • kjs/JSVariableObject.cpp:
  • kjs/JSVariableObject.h: Added support for saving localStorage and the symbol table to the back/forward cache, and restoring them.
  • kjs/function.cpp: (KJS::GlobalFuncImp::callAsFunction): Renamed progNode to evalNode because it's an EvalNode, not a ProgramNode.
  • kjs/lookup.h: (KJS::cacheGlobalObject): Replaced put with faster putDirect, since that's how the rest of lookup.h works. putDirect is safe here because cacheGlobalObject is only used for objects whose names are not valid identifiers.
  • kjs/nodes.cpp: The good stuff!

(KJS::EvalNode::processDeclarations): Replaced hasProperty with
the new hasOwnProperty, which is slightly faster.

  • kjs/object.h: Nixed clearProperties because clear() does this job now.
  • kjs/property_map.cpp:
  • kjs/property_map.h: More back/forward cache support.


  • wtf/Vector.h: (WTF::::grow): Added fast non-branching grow function. I used it in an earlier version of this patch, even though it's not used anymore.

JavaScriptGlue:

Build fix.

  • ForwardingHeaders/wtf/VectorTraits.h: Added.

WebCore:

Reviewed by Oliver Hunt.

Build support:

  • ForwardingHeaders/kjs/SymbolTable.h: Added.
  • ForwardingHeaders/wtf/VectorTraits.h: Added.
  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::JSDOMWindow::customGetOwnPropertySlot): Replaced use of getDirectLocation with getOwnPropertySlot. getDirectLocation is no longer valid, since global declarations are not stored in the property map.

(WebCore::JSDOMWindow::customPut): Replaced use of JSObject::put with
JSGlobalObject::put. JSObject::put is no longer valid, since global
declarations are not stored in the property map.

  • bindings/js/kjs_window.cpp: Replaced JSObject:: calls with Base:: calls, since JSObject is not our base class. This was always a bug, but the bug is even more apparent after some of my changes.

(KJS::Window::clear): Removed call to clearProperties because
JSGlobalObject::reset takes care of that now.

  • history/CachedPage.cpp:
  • history/CachedPage.h: Added support for saving a symbol table and localStorage to the page cache, and restoring it.

WebKit/mac:

Reviewed by Oliver Hunt.

Build fix.

  • ForwardingHeaders/kjs/SymbolTable.h: Added.
  • ForwardingHeaders/wtf/VectorTraits.h: Added.

LayoutTests:

Reviewed by Oliver Hunt.


Added some tests to verify some of the changes I made while optimizing
global access to global variables.

  • fast/dom/Window/resources/window-property-clearing-iframe0.html: Added.
  • fast/dom/Window/resources/window-property-clearing-iframe1.html: Added.
  • fast/dom/Window/window-property-clearing-expected.txt: Added.
  • fast/dom/Window/window-property-clearing.html: Added.
  • fast/dom/getter-on-window-object2-expected.txt: Added.
  • fast/dom/getter-on-window-object2.html: Added.

Checked in failing results for these const tests. The symbol table
optimization broke const. (We didn't know this before because our only
tests used global variables.)

  • fast/js/const-expected.txt:
  • fast/js/kde/const-expected.txt:
  • fast/js/resources/for-in-avoid-duplicates.js: Fixed a typo I noticed. Not related to this patch.
  • fast/dom/Window/window-property-shadowing.html: Changed this test to use "this" instead of "window". The fact that "window" worked before, despite an overriding / shadowing var declaration, was a bug.
  • Property svn:eol-style set to native
File size: 18.5 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
7 * Copyright (C) 2007 Eric Seidel ([email protected])
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "config.h"
27#include "object.h"
28
29#include "date_object.h"
30#include "error_object.h"
31#include "lookup.h"
32#include "nodes.h"
33#include "operations.h"
34#include "PropertyNameArray.h"
35#include <math.h>
36#include <wtf/Assertions.h>
37
38// maximum global call stack size. Protects against accidental or
39// malicious infinite recursions. Define to -1 if you want no limit.
40// In real-world testing it appears ok to bump the stack depth count to 500.
41// This of course is dependent on stack frame size.
42#define KJS_MAX_STACK 500
43
44#define JAVASCRIPT_CALL_TRACING 0
45#define JAVASCRIPT_MARK_TRACING 0
46
47#if JAVASCRIPT_CALL_TRACING
48static bool _traceJavaScript = false;
49
50extern "C" {
51 void setTraceJavaScript(bool f)
52 {
53 _traceJavaScript = f;
54 }
55
56 static bool traceJavaScript()
57 {
58 return _traceJavaScript;
59 }
60}
61#endif
62
63namespace KJS {
64
65// ------------------------------ Object ---------------------------------------
66
67JSValue *JSObject::call(ExecState *exec, JSObject *thisObj, const List &args)
68{
69 ASSERT(implementsCall());
70
71#if KJS_MAX_STACK > 0
72 static int depth = 0; // sum of all extant function calls
73
74#if JAVASCRIPT_CALL_TRACING
75 static bool tracing = false;
76 if (traceJavaScript() && !tracing) {
77 tracing = true;
78 for (int i = 0; i < depth; i++)
79 putchar (' ');
80 printf ("*** calling: %s\n", toString(exec).ascii());
81 for (int j = 0; j < args.size(); j++) {
82 for (int i = 0; i < depth; i++)
83 putchar (' ');
84 printf ("*** arg[%d] = %s\n", j, args[j]->toString(exec).ascii());
85 }
86 tracing = false;
87 }
88#endif
89
90 if (++depth > KJS_MAX_STACK) {
91 --depth;
92 return throwError(exec, RangeError, "Maximum call stack size exceeded.");
93 }
94#endif
95
96 JSValue *ret = callAsFunction(exec,thisObj,args);
97
98#if KJS_MAX_STACK > 0
99 --depth;
100#endif
101
102#if JAVASCRIPT_CALL_TRACING
103 if (traceJavaScript() && !tracing) {
104 tracing = true;
105 for (int i = 0; i < depth; i++)
106 putchar (' ');
107 printf ("*** returning: %s\n", ret->toString(exec).ascii());
108 tracing = false;
109 }
110#endif
111
112 return ret;
113}
114
115// ------------------------------ JSObject ------------------------------------
116
117void JSObject::mark()
118{
119 JSCell::mark();
120
121#if JAVASCRIPT_MARK_TRACING
122 static int markStackDepth = 0;
123 markStackDepth++;
124 for (int i = 0; i < markStackDepth; i++)
125 putchar('-');
126
127 printf("%s (%p)\n", className().UTF8String().c_str(), this);
128#endif
129
130 JSValue *proto = _proto;
131 if (!proto->marked())
132 proto->mark();
133
134 _prop.mark();
135
136#if JAVASCRIPT_MARK_TRACING
137 markStackDepth--;
138#endif
139}
140
141JSType JSObject::type() const
142{
143 return ObjectType;
144}
145
146const ClassInfo *JSObject::classInfo() const
147{
148 return 0;
149}
150
151UString JSObject::className() const
152{
153 const ClassInfo *ci = classInfo();
154 if ( ci )
155 return ci->className;
156 return "Object";
157}
158
159JSValue *JSObject::get(ExecState *exec, const Identifier &propertyName) const
160{
161 PropertySlot slot;
162
163 if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
164 return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
165
166 return jsUndefined();
167}
168
169JSValue *JSObject::get(ExecState *exec, unsigned propertyName) const
170{
171 PropertySlot slot;
172 if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
173 return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
174
175 return jsUndefined();
176}
177
178bool JSObject::getPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
179{
180 JSObject *imp = this;
181
182 while (true) {
183 if (imp->getOwnPropertySlot(exec, propertyName, slot))
184 return true;
185
186 JSValue *proto = imp->_proto;
187 if (!proto->isObject())
188 break;
189
190 imp = static_cast<JSObject *>(proto);
191 }
192
193 return false;
194}
195
196bool JSObject::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
197{
198 return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
199}
200
201static void throwSetterError(ExecState *exec)
202{
203 throwError(exec, TypeError, "setting a property that has only a getter");
204}
205
206// ECMA 8.6.2.2
207void JSObject::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
208{
209 ASSERT(value);
210
211 // non-standard netscape extension
212 if (propertyName == exec->propertyNames().underscoreProto) {
213 JSObject* proto = value->getObject();
214 while (proto) {
215 if (proto == this)
216 throwError(exec, GeneralError, "cyclic __proto__ value");
217 proto = proto->prototype() ? proto->prototype()->getObject() : 0;
218 }
219
220 setPrototype(value);
221 return;
222 }
223
224 /* TODO: check for write permissions directly w/o this call */
225 /* Doesn't look very easy with the PropertyMap API - David */
226 // putValue() is used for JS assignemnts. It passes no attribute.
227 // Assume that a C++ implementation knows what it is doing
228 // and let it override the canPut() check.
229 if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName)) {
230 return;
231 }
232
233 // Check if there are any setters or getters in the prototype chain
234 JSObject *obj = this;
235 bool hasGettersOrSetters = false;
236 while (true) {
237 if (obj->_prop.hasGetterSetterProperties()) {
238 hasGettersOrSetters = true;
239 break;
240 }
241
242 if (!obj->_proto->isObject())
243 break;
244
245 obj = static_cast<JSObject *>(obj->_proto);
246 }
247
248 if (hasGettersOrSetters) {
249 obj = this;
250 while (true) {
251 unsigned attributes;
252 if (JSValue *gs = obj->_prop.get(propertyName, attributes)) {
253 if (attributes & GetterSetter) {
254 JSObject *setterFunc = static_cast<GetterSetterImp *>(gs)->getSetter();
255
256 if (!setterFunc) {
257 throwSetterError(exec);
258 return;
259 }
260
261 List args;
262 args.append(value);
263
264 setterFunc->call(exec, this, args);
265 return;
266 } else {
267 // If there's an existing property on the object or one of its
268 // prototype it should be replaced, so we just break here.
269 break;
270 }
271 }
272
273 if (!obj->_proto->isObject())
274 break;
275
276 obj = static_cast<JSObject *>(obj->_proto);
277 }
278 }
279
280 _prop.put(propertyName,value,attr);
281}
282
283void JSObject::put(ExecState *exec, unsigned propertyName,
284 JSValue *value, int attr)
285{
286 put(exec, Identifier::from(propertyName), value, attr);
287}
288
289// ECMA 8.6.2.3
290bool JSObject::canPut(ExecState *, const Identifier &propertyName) const
291{
292 unsigned attributes;
293
294 // Don't look in the prototype here. We can always put an override
295 // in the object, even if the prototype has a ReadOnly property.
296
297 if (!getPropertyAttributes(propertyName, attributes))
298 return true;
299 else
300 return !(attributes & ReadOnly);
301}
302
303// ECMA 8.6.2.4
304bool JSObject::hasProperty(ExecState *exec, const Identifier &propertyName) const
305{
306 PropertySlot slot;
307 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
308}
309
310bool JSObject::hasProperty(ExecState *exec, unsigned propertyName) const
311{
312 PropertySlot slot;
313 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
314}
315
316// ECMA 8.6.2.5
317bool JSObject::deleteProperty(ExecState* /*exec*/, const Identifier &propertyName)
318{
319 unsigned attributes;
320 JSValue *v = _prop.get(propertyName, attributes);
321 if (v) {
322 if ((attributes & DontDelete))
323 return false;
324 _prop.remove(propertyName);
325 if (attributes & GetterSetter)
326 _prop.setHasGetterSetterProperties(_prop.containsGettersOrSetters());
327 return true;
328 }
329
330 // Look in the static hashtable of properties
331 const HashEntry* entry = findPropertyHashEntry(propertyName);
332 if (entry && entry->attr & DontDelete)
333 return false; // this builtin property can't be deleted
334 return true;
335}
336
337bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
338{
339 PropertySlot slot;
340 return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
341}
342
343bool JSObject::deleteProperty(ExecState *exec, unsigned propertyName)
344{
345 return deleteProperty(exec, Identifier::from(propertyName));
346}
347
348static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObject *object, const Identifier &propertyName) {
349 JSValue *v = object->get(exec, propertyName);
350 if (v->isObject()) {
351 JSObject *o = static_cast<JSObject*>(v);
352 if (o->implementsCall()) { // spec says "not primitive type" but ...
353 JSObject *thisObj = const_cast<JSObject*>(object);
354 JSValue *def = o->call(exec, thisObj, List::empty());
355 JSType defType = def->type();
356 ASSERT(defType != GetterSetterType);
357 if (defType != ObjectType)
358 return def;
359 }
360 }
361 return NULL;
362}
363
364bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
365{
366 result = defaultValue(exec, NumberType);
367 number = result->toNumber(exec);
368 return !result->isString();
369}
370
371// ECMA 8.6.2.6
372JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
373{
374 /* Prefer String for Date objects */
375 if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {
376 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
377 return v;
378 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().valueOf))
379 return v;
380 } else {
381 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().valueOf))
382 return v;
383 if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
384 return v;
385 }
386
387 if (exec->hadException())
388 return exec->exception();
389
390 return throwError(exec, TypeError, "No default value");
391}
392
393const HashEntry* JSObject::findPropertyHashEntry(const Identifier& propertyName) const
394{
395 for (const ClassInfo *info = classInfo(); info; info = info->parentClass) {
396 if (const HashTable *propHashTable = info->propHashTable) {
397 if (const HashEntry *e = Lookup::findEntry(propHashTable, propertyName))
398 return e;
399 }
400 }
401 return 0;
402}
403
404void JSObject::defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc)
405{
406 JSValue *o = getDirect(propertyName);
407 GetterSetterImp *gs;
408
409 if (o && o->type() == GetterSetterType) {
410 gs = static_cast<GetterSetterImp *>(o);
411 } else {
412 gs = new GetterSetterImp;
413 putDirect(propertyName, gs, GetterSetter);
414 }
415
416 _prop.setHasGetterSetterProperties(true);
417 gs->setGetter(getterFunc);
418}
419
420void JSObject::defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc)
421{
422 JSValue *o = getDirect(propertyName);
423 GetterSetterImp *gs;
424
425 if (o && o->type() == GetterSetterType) {
426 gs = static_cast<GetterSetterImp *>(o);
427 } else {
428 gs = new GetterSetterImp;
429 putDirect(propertyName, gs, GetterSetter);
430 }
431
432 _prop.setHasGetterSetterProperties(true);
433 gs->setSetter(setterFunc);
434}
435
436bool JSObject::implementsConstruct() const
437{
438 return false;
439}
440
441JSObject* JSObject::construct(ExecState*, const List& /*args*/)
442{
443 ASSERT(false);
444 return NULL;
445}
446
447JSObject* JSObject::construct(ExecState* exec, const List& args, const Identifier& /*functionName*/, const UString& /*sourceURL*/, int /*lineNumber*/)
448{
449 return construct(exec, args);
450}
451
452bool JSObject::implementsCall() const
453{
454 return false;
455}
456
457JSValue *JSObject::callAsFunction(ExecState* /*exec*/, JSObject* /*thisObj*/, const List &/*args*/)
458{
459 ASSERT(false);
460 return NULL;
461}
462
463bool JSObject::implementsHasInstance() const
464{
465 return false;
466}
467
468bool JSObject::hasInstance(ExecState* exec, JSValue* value)
469{
470 JSValue* proto = get(exec, exec->propertyNames().prototype);
471 if (!proto->isObject()) {
472 throwError(exec, TypeError, "intanceof called on an object with an invalid prototype property.");
473 return false;
474 }
475
476 if (!value->isObject())
477 return false;
478
479 JSObject* o = static_cast<JSObject*>(value);
480 while ((o = o->prototype()->getObject())) {
481 if (o == proto)
482 return true;
483 }
484 return false;
485}
486
487bool JSObject::propertyIsEnumerable(ExecState*, const Identifier& propertyName) const
488{
489 unsigned attributes;
490
491 if (!getPropertyAttributes(propertyName, attributes))
492 return false;
493 else
494 return !(attributes & DontEnum);
495}
496
497bool JSObject::getPropertyAttributes(const Identifier& propertyName, unsigned& attributes) const
498{
499 if (_prop.get(propertyName, attributes))
500 return true;
501
502 // Look in the static hashtable of properties
503 const HashEntry* e = findPropertyHashEntry(propertyName);
504 if (e) {
505 attributes = e->attr;
506 return true;
507 }
508
509 return false;
510}
511
512void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
513{
514 _prop.getEnumerablePropertyNames(propertyNames);
515
516 // Add properties from the static hashtable of properties
517 const ClassInfo *info = classInfo();
518 while (info) {
519 if (info->propHashTable) {
520 int size = info->propHashTable->size;
521 const HashEntry *e = info->propHashTable->entries;
522 for (int i = 0; i < size; ++i, ++e) {
523 if (e->s && !(e->attr & DontEnum))
524 propertyNames.add(e->s);
525 }
526 }
527 info = info->parentClass;
528 }
529 if (_proto->isObject())
530 static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames);
531}
532
533bool JSObject::toBoolean(ExecState*) const
534{
535 return true;
536}
537
538double JSObject::toNumber(ExecState *exec) const
539{
540 JSValue *prim = toPrimitive(exec,NumberType);
541 if (exec->hadException()) // should be picked up soon in nodes.cpp
542 return 0.0;
543 return prim->toNumber(exec);
544}
545
546UString JSObject::toString(ExecState *exec) const
547{
548 JSValue *prim = toPrimitive(exec,StringType);
549 if (exec->hadException()) // should be picked up soon in nodes.cpp
550 return "";
551 return prim->toString(exec);
552}
553
554JSObject *JSObject::toObject(ExecState*) const
555{
556 return const_cast<JSObject*>(this);
557}
558
559void JSObject::putDirect(const Identifier &propertyName, JSValue *value, int attr)
560{
561 _prop.put(propertyName, value, attr);
562}
563
564void JSObject::putDirect(const Identifier &propertyName, int value, int attr)
565{
566 _prop.put(propertyName, jsNumber(value), attr);
567}
568
569void JSObject::removeDirect(const Identifier &propertyName)
570{
571 _prop.remove(propertyName);
572}
573
574void JSObject::putDirectFunction(InternalFunctionImp* func, int attr)
575{
576 putDirect(func->functionName(), func, attr);
577}
578
579void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue **location)
580{
581 GetterSetterImp *gs = static_cast<GetterSetterImp *>(*location);
582 JSObject *getterFunc = gs->getGetter();
583 if (getterFunc)
584 slot.setGetterSlot(this, getterFunc);
585 else
586 slot.setUndefined(this);
587}
588
589// ------------------------------ Error ----------------------------------------
590
591const char * const errorNamesArr[] = {
592 I18N_NOOP("Error"), // GeneralError
593 I18N_NOOP("Evaluation error"), // EvalError
594 I18N_NOOP("Range error"), // RangeError
595 I18N_NOOP("Reference error"), // ReferenceError
596 I18N_NOOP("Syntax error"), // SyntaxError
597 I18N_NOOP("Type error"), // TypeError
598 I18N_NOOP("URI error"), // URIError
599};
600
601const char * const * const Error::errorNames = errorNamesArr;
602
603JSObject *Error::create(ExecState *exec, ErrorType errtype, const UString &message,
604 int lineno, int sourceId, const UString &sourceURL)
605{
606 JSObject *cons;
607 switch (errtype) {
608 case EvalError:
609 cons = exec->lexicalGlobalObject()->evalErrorConstructor();
610 break;
611 case RangeError:
612 cons = exec->lexicalGlobalObject()->rangeErrorConstructor();
613 break;
614 case ReferenceError:
615 cons = exec->lexicalGlobalObject()->referenceErrorConstructor();
616 break;
617 case SyntaxError:
618 cons = exec->lexicalGlobalObject()->syntaxErrorConstructor();
619 break;
620 case TypeError:
621 cons = exec->lexicalGlobalObject()->typeErrorConstructor();
622 break;
623 case URIError:
624 cons = exec->lexicalGlobalObject()->URIErrorConstructor();
625 break;
626 default:
627 cons = exec->lexicalGlobalObject()->errorConstructor();
628 break;
629 }
630
631 List args;
632 if (message.isEmpty())
633 args.append(jsString(errorNames[errtype]));
634 else
635 args.append(jsString(message));
636 JSObject *err = static_cast<JSObject *>(cons->construct(exec,args));
637
638 if (lineno != -1)
639 err->put(exec, "line", jsNumber(lineno));
640 if (sourceId != -1)
641 err->put(exec, "sourceId", jsNumber(sourceId));
642
643 if(!sourceURL.isNull())
644 err->put(exec, "sourceURL", jsString(sourceURL));
645
646 return err;
647
648/*
649#ifndef NDEBUG
650 const char *msg = err->get(messagePropertyName)->toString().value().ascii();
651 if (l >= 0)
652 fprintf(stderr, "KJS: %s at line %d. %s\n", estr, l, msg);
653 else
654 fprintf(stderr, "KJS: %s. %s\n", estr, msg);
655#endif
656
657 return err;
658*/
659}
660
661JSObject *Error::create(ExecState *exec, ErrorType type, const char *message)
662{
663 return create(exec, type, message, -1, -1, NULL);
664}
665
666JSObject *throwError(ExecState *exec, ErrorType type)
667{
668 JSObject *error = Error::create(exec, type, UString(), -1, -1, NULL);
669 exec->setException(error);
670 return error;
671}
672
673JSObject *throwError(ExecState *exec, ErrorType type, const UString &message)
674{
675 JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
676 exec->setException(error);
677 return error;
678}
679
680JSObject *throwError(ExecState *exec, ErrorType type, const char *message)
681{
682 JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
683 exec->setException(error);
684 return error;
685}
686
687JSObject *throwError(ExecState *exec, ErrorType type, const UString &message, int line, int sourceId, const UString &sourceURL)
688{
689 JSObject *error = Error::create(exec, type, message, line, sourceId, sourceURL);
690 exec->setException(error);
691 return error;
692}
693
694} // namespace KJS
Note: See TracBrowser for help on using the repository browser.