Changeset 35007 in webkit for trunk/JavaScriptCore/kjs/Error.cpp
- Timestamp:
- Jul 4, 2008, 10:35:09 PM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/Error.cpp
r35003 r35007 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2001 Harri Porten ([email protected]) … … 24 23 25 24 #include "config.h" 26 #include " JSObject.h"25 #include "Error.h" 27 26 28 #include " DatePrototype.h"27 #include "ConstructData.h" 29 28 #include "ErrorConstructor.h" 30 29 #include "JSGlobalObject.h" 30 #include "JSObject.h" 31 31 #include "NativeErrorConstructor.h" 32 #include "ObjectPrototype.h"33 #include "PropertyNameArray.h"34 #include "lookup.h"35 #include "nodes.h"36 #include "operations.h"37 #include <math.h>38 #include <profiler/Profiler.h>39 #include <wtf/Assertions.h>40 41 #define JAVASCRIPT_MARK_TRACING 042 32 43 33 namespace KJS { 44 45 // ------------------------------ JSObject ------------------------------------46 47 void JSObject::mark()48 {49 JSCell::mark();50 51 #if JAVASCRIPT_MARK_TRACING52 static int markStackDepth = 0;53 markStackDepth++;54 for (int i = 0; i < markStackDepth; i++)55 putchar('-');56 57 printf("%s (%p)\n", className().UTF8String().c_str(), this);58 #endif59 60 JSValue *proto = _proto;61 if (!proto->marked())62 proto->mark();63 64 _prop.mark();65 66 #if JAVASCRIPT_MARK_TRACING67 markStackDepth--;68 #endif69 }70 71 JSType JSObject::type() const72 {73 return ObjectType;74 }75 76 UString JSObject::className() const77 {78 const ClassInfo *ci = classInfo();79 if ( ci )80 return ci->className;81 return "Object";82 }83 84 bool JSObject::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)85 {86 return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);87 }88 89 static void throwSetterError(ExecState *exec)90 {91 throwError(exec, TypeError, "setting a property that has only a getter");92 }93 94 // ECMA 8.6.2.295 void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value)96 {97 ASSERT(value);98 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));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 chain120 JSValue* prototype;121 for (JSObject* obj = this; !obj->_prop.hasGetterSetterProperties(); obj = static_cast<JSObject*>(prototype)) {122 prototype = obj->_proto;123 if (prototype == jsNull()) {124 _prop.put(propertyName, value, 0, true);125 return;126 }127 }128 129 unsigned attributes;130 if (_prop.get(propertyName, attributes) && attributes & ReadOnly)131 return;132 133 for (JSObject* obj = this; ; obj = static_cast<JSObject*>(prototype)) {134 if (JSValue* gs = obj->_prop.get(propertyName, attributes)) {135 if (attributes & IsGetterSetter) {136 JSObject* setterFunc = static_cast<GetterSetter*>(gs)->setter();137 if (!setterFunc) {138 throwSetterError(exec);139 return;140 }141 142 CallData callData;143 CallType callType = setterFunc->getCallData(callData);144 ArgList args;145 args.append(value);146 call(exec, setterFunc, callType, callData, this, args);147 return;148 }149 150 // If there's an existing property on the object or one of its151 // prototypes it should be replaced, so break here.152 break;153 }154 155 prototype = obj->_proto;156 if (prototype == jsNull())157 break;158 }159 160 _prop.put(propertyName, value, 0, true);161 }162 163 void JSObject::put(ExecState* exec, unsigned propertyName, JSValue* value)164 {165 put(exec, Identifier::from(exec, propertyName), value);166 }167 168 void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)169 {170 putDirect(propertyName, value, attributes);171 }172 173 void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue* value, unsigned attributes)174 {175 putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);176 }177 178 bool JSObject::hasProperty(ExecState *exec, const Identifier &propertyName) const179 {180 PropertySlot slot;181 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);182 }183 184 bool JSObject::hasProperty(ExecState *exec, unsigned propertyName) const185 {186 PropertySlot slot;187 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);188 }189 190 // ECMA 8.6.2.5191 bool JSObject::deleteProperty(ExecState* exec, const Identifier &propertyName)192 {193 unsigned attributes;194 JSValue *v = _prop.get(propertyName, attributes);195 if (v) {196 if ((attributes & DontDelete))197 return false;198 _prop.remove(propertyName);199 if (attributes & IsGetterSetter)200 _prop.setHasGetterSetterProperties(_prop.containsGettersOrSetters());201 return true;202 }203 204 // Look in the static hashtable of properties205 const HashEntry* entry = findPropertyHashEntry(exec, propertyName);206 if (entry && entry->attributes & DontDelete)207 return false; // this builtin property can't be deleted208 // FIXME: Should the code here actually do some deletion?209 return true;210 }211 212 bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const213 {214 PropertySlot slot;215 return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);216 }217 218 bool JSObject::deleteProperty(ExecState *exec, unsigned propertyName)219 {220 return deleteProperty(exec, Identifier::from(exec, propertyName));221 }222 223 static ALWAYS_INLINE JSValue* callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)224 {225 JSValue* function = object->get(exec, propertyName);226 CallData callData;227 CallType callType = function->getCallData(callData);228 if (callType == CallTypeNone)229 return exec->exception();230 231 // Prevent "toString" and "valueOf" from observing execution if an exception232 // is pending.233 if (exec->hadException())234 return exec->exception();235 236 JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());237 ASSERT(result->type() != GetterSetterType);238 if (exec->hadException())239 return exec->exception();240 if (result->isObject())241 return 0;242 return result;243 }244 245 bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)246 {247 result = defaultValue(exec, NumberType);248 number = result->toNumber(exec);249 return !result->isString();250 }251 252 // ECMA 8.6.2.6253 JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const254 {255 // Must call toString first for Date objects.256 if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {257 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))258 return value;259 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))260 return value;261 } else {262 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))263 return value;264 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))265 return value;266 }267 268 ASSERT(!exec->hadException());269 270 return throwError(exec, TypeError, "No default value");271 }272 273 const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const274 {275 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {276 if (const HashTable* propHashTable = info->propHashTable(exec)) {277 if (const HashEntry* e = propHashTable->entry(exec, propertyName))278 return e;279 }280 }281 return 0;282 }283 284 void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)285 {286 JSValue *o = getDirect(propertyName);287 GetterSetter *gs;288 289 if (o && o->type() == GetterSetterType) {290 gs = static_cast<GetterSetter *>(o);291 } else {292 gs = new (exec) GetterSetter;293 putDirect(propertyName, gs, IsGetterSetter);294 }295 296 _prop.setHasGetterSetterProperties(true);297 gs->setGetter(getterFunc);298 }299 300 void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)301 {302 JSValue *o = getDirect(propertyName);303 GetterSetter *gs;304 305 if (o && o->type() == GetterSetterType) {306 gs = static_cast<GetterSetter *>(o);307 } else {308 gs = new (exec) GetterSetter;309 putDirect(propertyName, gs, IsGetterSetter);310 }311 312 _prop.setHasGetterSetterProperties(true);313 gs->setSetter(setterFunc);314 }315 316 JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName)317 {318 JSObject* obj = this;319 while (true) {320 JSValue* v = obj->getDirect(propertyName);321 if (v) {322 if (v->type() != GetterSetterType)323 return jsUndefined();324 JSObject* funcObj = static_cast<GetterSetter*>(v)->getter();325 if (!funcObj)326 return jsUndefined();327 return funcObj;328 }329 330 if (!obj->prototype() || !obj->prototype()->isObject())331 return jsUndefined();332 obj = static_cast<JSObject*>(obj->prototype());333 }334 }335 336 JSValue* JSObject::lookupSetter(ExecState*, const Identifier& propertyName)337 {338 JSObject* obj = this;339 while (true) {340 JSValue* v = obj->getDirect(propertyName);341 if (v) {342 if (v->type() != GetterSetterType)343 return jsUndefined();344 JSObject* funcObj = static_cast<GetterSetter*>(v)->setter();345 if (!funcObj)346 return jsUndefined();347 return funcObj;348 }349 350 if (!obj->prototype() || !obj->prototype()->isObject())351 return jsUndefined();352 obj = static_cast<JSObject*>(obj->prototype());353 }354 }355 356 bool JSObject::implementsHasInstance() const357 {358 return false;359 }360 361 bool JSObject::hasInstance(ExecState* exec, JSValue* value)362 {363 JSValue* proto = get(exec, exec->propertyNames().prototype);364 if (!proto->isObject()) {365 throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");366 return false;367 }368 369 if (!value->isObject())370 return false;371 372 JSObject* o = static_cast<JSObject*>(value);373 while ((o = o->prototype()->getObject())) {374 if (o == proto)375 return true;376 }377 return false;378 }379 380 bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const381 {382 unsigned attributes;383 384 if (!getPropertyAttributes(exec, propertyName, attributes))385 return false;386 else387 return !(attributes & DontEnum);388 }389 390 bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const391 {392 if (_prop.get(propertyName, attributes))393 return true;394 395 // Look in the static hashtable of properties396 const HashEntry* e = findPropertyHashEntry(exec, propertyName);397 if (e) {398 attributes = e->attributes;399 return true;400 }401 402 return false;403 }404 405 void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)406 {407 _prop.getEnumerablePropertyNames(propertyNames);408 409 // Add properties from the static hashtables of properties410 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {411 const HashTable* table = info->propHashTable(exec);412 if (!table)413 continue;414 table->initializeIfNeeded(exec);415 ASSERT(table->table);416 int hashSizeMask = table->hashSizeMask;417 const HashEntry* e = table->table;418 for (int i = 0; i <= hashSizeMask; ++i, ++e) {419 if (e->key && !(e->attributes & DontEnum))420 propertyNames.add(e->key);421 }422 }423 424 if (_proto->isObject())425 static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames);426 }427 428 bool JSObject::toBoolean(ExecState*) const429 {430 return true;431 }432 433 double JSObject::toNumber(ExecState *exec) const434 {435 JSValue *prim = toPrimitive(exec,NumberType);436 if (exec->hadException()) // should be picked up soon in nodes.cpp437 return 0.0;438 return prim->toNumber(exec);439 }440 441 UString JSObject::toString(ExecState* exec) const442 {443 JSValue* primitive = toPrimitive(exec, StringType);444 if (exec->hadException())445 return "";446 return primitive->toString(exec);447 }448 449 JSObject *JSObject::toObject(ExecState*) const450 {451 return const_cast<JSObject*>(this);452 }453 454 JSObject* JSObject::toThisObject(ExecState*) const455 {456 return const_cast<JSObject*>(this);457 }458 459 JSGlobalObject* JSObject::toGlobalObject(ExecState*) const460 {461 return 0;462 }463 464 void JSObject::removeDirect(const Identifier &propertyName)465 {466 _prop.remove(propertyName);467 }468 469 void JSObject::putDirectFunction(InternalFunction* func, int attr)470 {471 putDirect(func->functionName(), func, attr);472 }473 474 void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue** location)475 {476 if (JSObject* getterFunc = static_cast<GetterSetter*>(*location)->getter())477 slot.setGetterSlot(getterFunc);478 else479 slot.setUndefined();480 }481 482 // ------------------------------ Error ----------------------------------------483 34 484 35 JSObject* Error::create(ExecState* exec, ErrorType errtype, const UString& message, … … 571 122 } 572 123 573 JSObject* constructEmptyObject(ExecState* exec)574 {575 return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype());576 }577 578 124 } // namespace KJS
Note:
See TracChangeset
for help on using the changeset viewer.