Changeset 35830 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Aug 18, 2008, 9:39:04 PM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/GetterSetter.cpp
r35008 r35830 39 39 } 40 40 41 JSValue* GetterSetter::toPrimitive(ExecState*, JSType) const41 JSValue* GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const 42 42 { 43 43 ASSERT_NOT_REACHED(); … … 77 77 } 78 78 79 bool GetterSetter::isGetterSetter() const 80 { 81 return true; 82 } 83 79 84 } // namespace KJS -
trunk/JavaScriptCore/kjs/GetterSetter.h
r35022 r35830 40 40 } 41 41 42 JSType type() const { return GetterSetterType; }43 44 42 virtual void mark(); 45 43 … … 50 48 51 49 private: 52 virtual JSValue* toPrimitive(ExecState*, JSType preferred) const; 50 virtual bool isGetterSetter() const; 51 52 virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; 53 53 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); 54 54 virtual bool toBoolean(ExecState*) const; -
trunk/JavaScriptCore/kjs/JSCell.cpp
r34921 r35830 216 216 } 217 217 218 bool JSCell::isString() const 219 { 220 return false; 221 } 222 223 bool JSCell::isGetterSetter() const 224 { 225 return false; 226 } 227 228 bool JSCell::isObject() const 229 { 230 return false; 231 } 232 218 233 } // namespace KJS -
trunk/JavaScriptCore/kjs/JSCell.h
r35807 r35830 44 44 public: 45 45 // Querying the type. 46 virtual JSType type() const = 0;47 46 bool isNumber() const; 48 bool isString() const; 49 bool isObject() const; 50 bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits. 47 virtual bool isString() const; 48 virtual bool isGetterSetter() const; 49 virtual bool isObject() const; 50 virtual bool isObject(const ClassInfo*) const; 51 51 52 52 // Extracting the value. … … 67 67 68 68 // Basic conversions. 69 virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;69 virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; 70 70 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0; 71 71 virtual bool toBoolean(ExecState*) const = 0; … … 111 111 inline bool JSCell::isNumber() const 112 112 { 113 return type() == NumberType; 114 } 115 116 inline bool JSCell::isString() const 117 { 118 return type() == StringType; 119 } 120 121 inline bool JSCell::isObject() const 122 { 123 return type() == ObjectType; 113 return Heap::isNumber(const_cast<JSCell*>(this)); 124 114 } 125 115 … … 157 147 { 158 148 return !JSImmediate::isImmediate(this) && asCell()->isString(); 149 } 150 151 inline bool JSValue::isGetterSetter() const 152 { 153 return !JSImmediate::isImmediate(this) && asCell()->isGetterSetter(); 159 154 } 160 155 … … 234 229 } 235 230 236 inline JSType JSValue::type() const 237 { 238 return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type(); 239 } 240 241 inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const 231 inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const 242 232 { 243 233 return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType); -
trunk/JavaScriptCore/kjs/JSImmediate.h
r35782 r35830 1 1 /* 2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2006 Alexey Proskuryakov ([email protected]) 4 4 * … … 23 23 #define KJS_JS_IMMEDIATE_H 24 24 25 #include "JSType.h"26 25 #include <wtf/Assertions.h> 27 26 #include <wtf/AlwaysInline.h> … … 41 40 42 41 /* 43 * A JSValue* 42 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 44 43 * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging 45 44 * because allocator alignment guarantees they will be 00 in cell pointers. … … 83 82 84 83 class JSImmediate { 84 private: 85 85 static const uintptr_t TagMask = 0x3u; // primary tag is 2 bits long 86 static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates int , this dominates the following bit86 static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit 87 87 static const uintptr_t TagBitTypeOther = 0x2u; // second bit set indicates immediate other than an integer 88 88 … … 104 104 static ALWAYS_INLINE bool isImmediate(const JSValue* v) 105 105 { 106 return (reinterpret_cast<uintptr_t>(v) & TagMask);106 return reinterpret_cast<uintptr_t>(v) & TagMask; 107 107 } 108 108 109 109 static ALWAYS_INLINE bool isNumber(const JSValue* v) 110 110 { 111 return (reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger);111 return reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger; 112 112 } 113 113 … … 120 120 static ALWAYS_INLINE bool isBoolean(const JSValue* v) 121 121 { 122 return ( (reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool);122 return (reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool; 123 123 } 124 124 … … 126 126 { 127 127 // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. 128 return ( (reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull);128 return (reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull; 129 129 } 130 130 … … 148 148 static JSValue* from(double); 149 149 150 static ALWAYS_INLINE bool isEitherImmediate(const JSValue* v1, const JSValue* v2) 151 { 152 return (reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)) & TagMask; 153 } 154 150 155 static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2) 151 156 { 152 return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger);157 return reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger; 153 158 } 154 159 … … 214 219 static JSObject* toObject(const JSValue*, ExecState*); 215 220 static UString toString(const JSValue*); 216 static uint32_t toTruncatedUInt32(const JSValue*);217 static JSType type(const JSValue*);218 221 219 222 static bool getUInt32(const JSValue*, uint32_t&); … … 222 225 223 226 static int32_t getTruncatedInt32(const JSValue*); 227 static uint32_t getTruncatedUInt32(const JSValue*); 224 228 225 229 static JSValue* trueImmediate(); … … 233 237 234 238 private: 235 // Immediate values are restricted to a 30 bit signed value.236 239 static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift; 237 240 static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift; … … 270 273 static ALWAYS_INLINE bool boolValue(const JSValue* v) 271 274 { 272 return (rawValue(v) & ExtendedPayloadBitBoolValue) != 0;275 return rawValue(v) & ExtendedPayloadBitBoolValue; 273 276 } 274 277 … … 291 294 ASSERT(isImmediate(v)); 292 295 uintptr_t bits = rawValue(v); 293 return 294 (bits & TagBitTypeInteger) ? (bits != TagBitTypeInteger) :// !0 ints295 (bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue)); // bool true296 } 297 298 ALWAYS_INLINE uint32_t JSImmediate:: toTruncatedUInt32(const JSValue* v)296 return (bits & TagBitTypeInteger) 297 ? bits != TagBitTypeInteger // !0 ints 298 : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true 299 } 300 301 ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(const JSValue* v) 299 302 { 300 303 ASSERT(isNumber(v)); … … 377 380 378 381 // Check for data loss from conversion to int. 379 if ( (intVal != d)|| (!intVal && signbit(d)))382 if (intVal != d || (!intVal && signbit(d))) 380 383 return 0; 381 384 … … 418 421 } 419 422 420 ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v)421 {422 ASSERT(isImmediate(v));423 424 if (isNumber(v))425 return NumberType;426 if (isBoolean(v))427 return BooleanType;428 if (v != undefinedImmediate())429 return NullType;430 return UndefinedType;431 }432 433 423 ALWAYS_INLINE JSValue* jsUndefined() 434 424 { -
trunk/JavaScriptCore/kjs/JSNotAnObject.cpp
r35807 r35830 38 38 39 39 // JSValue methods 40 JSValue* JSNotAnObject::toPrimitive(ExecState* exec, JSType) const40 JSValue* JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const 41 41 { 42 42 UNUSED_PARAM(exec); -
trunk/JavaScriptCore/kjs/JSNotAnObject.h
r35245 r35830 58 58 private: 59 59 // JSValue methods 60 virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;60 virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; 61 61 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&); 62 62 virtual bool toBoolean(ExecState*) const; -
trunk/JavaScriptCore/kjs/JSNumberCell.cpp
r35027 r35830 24 24 #include "JSNumberCell.h" 25 25 26 #include "JSType.h"27 26 #include "NumberObject.h" 28 27 #include "ustring.h" … … 30 29 namespace KJS { 31 30 32 JSType JSNumberCell::type() const 33 { 34 return NumberType; 35 } 36 37 JSValue* JSNumberCell::toPrimitive(ExecState*, JSType) const 31 JSValue* JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const 38 32 { 39 33 return const_cast<JSNumberCell*>(this); -
trunk/JavaScriptCore/kjs/JSNumberCell.h
r35639 r35830 47 47 double value() const { return m_value; } 48 48 49 virtual JSType type() const; 50 51 virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const; 49 virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; 52 50 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); 53 51 virtual bool toBoolean(ExecState*) const; … … 59 57 virtual JSObject* toThisObject(ExecState*) const; 60 58 virtual JSValue* getJSNumber(); 61 int32_t fastToInt32() const; 62 uint32_t fastToUInt32() const; 59 60 int32_t toInt32() const; 61 uint32_t toUInt32() const; 63 62 64 63 void* operator new(size_t size, ExecState* exec) … … 149 148 } 150 149 151 inline int32_t JSNumberCell:: fastToInt32() const150 inline int32_t JSNumberCell::toInt32() const 152 151 { 153 152 if (m_value >= -2147483648.0 && m_value < 2147483648.0) … … 157 156 } 158 157 159 inline uint32_t JSNumberCell:: fastToUInt32() const158 inline uint32_t JSNumberCell::toUInt32() const 160 159 { 161 160 if (m_value >= 0.0 && m_value < 4294967296.0) -
trunk/JavaScriptCore/kjs/JSObject.cpp
r35807 r35830 68 68 } 69 69 70 JSType JSObject::type() const71 {72 return ObjectType;73 }74 75 70 UString JSObject::className() const 76 71 { … … 235 230 236 231 JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList()); 237 ASSERT( result->type() != GetterSetterType);232 ASSERT(!result->isGetterSetter()); 238 233 if (exec->hadException()) 239 234 return exec->exception(); … … 245 240 bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result) 246 241 { 247 result = defaultValue(exec, NumberType);242 result = defaultValue(exec, PreferNumber); 248 243 number = result->toNumber(exec); 249 244 return !result->isString(); … … 251 246 252 247 // ECMA 8.6.2.6 253 JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const248 JSValue* JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const 254 249 { 255 250 // Must call toString first for Date objects. 256 if ((hint == StringType) || (hint != NumberType&& m_prototype == exec->lexicalGlobalObject()->datePrototype())) {251 if ((hint == PreferString) || (hint != PreferNumber && m_prototype == exec->lexicalGlobalObject()->datePrototype())) { 257 252 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString)) 258 253 return value; … … 286 281 JSValue* object = getDirect(propertyName); 287 282 GetterSetter* getterSetter; 288 if (object && object-> type() == GetterSetterType)283 if (object && object->isGetterSetter()) 289 284 getterSetter = static_cast<GetterSetter*>(object); 290 285 else { … … 301 296 JSValue* object = getDirect(propertyName); 302 297 GetterSetter* getterSetter; 303 if (object && object-> type() == GetterSetterType)298 if (object && object->isGetterSetter()) 304 299 getterSetter = static_cast<GetterSetter*>(object); 305 300 else { … … 318 313 JSValue* value = object->getDirect(propertyName); 319 314 if (value) { 320 if ( value->type() != GetterSetterType)315 if (!value->isGetterSetter()) 321 316 return jsUndefined(); 322 317 JSObject* functionObject = static_cast<GetterSetter*>(value)->getter(); … … 338 333 JSValue* value = object->getDirect(propertyName); 339 334 if (value) { 340 if ( value->type() != GetterSetterType)335 if (!value->isGetterSetter()) 341 336 return jsUndefined(); 342 337 JSObject* functionObject = static_cast<GetterSetter*>(value)->setter(); … … 429 424 double JSObject::toNumber(ExecState* exec) const 430 425 { 431 JSValue* primitive = toPrimitive(exec, NumberType);426 JSValue* primitive = toPrimitive(exec, PreferNumber); 432 427 if (exec->hadException()) // should be picked up soon in nodes.cpp 433 428 return 0.0; … … 437 432 UString JSObject::toString(ExecState* exec) const 438 433 { 439 JSValue* primitive = toPrimitive(exec, StringType);434 JSValue* primitive = toPrimitive(exec, PreferString); 440 435 if (exec->hadException()) 441 436 return ""; … … 476 471 } 477 472 473 bool JSObject::isObject() const 474 { 475 return true; 476 } 477 478 478 JSObject* constructEmptyObject(ExecState* exec) 479 479 { -
trunk/JavaScriptCore/kjs/JSObject.h
r35807 r35830 29 29 #include "ExecState.h" 30 30 #include "JSNumberCell.h" 31 #include "JSType.h"32 31 #include "PropertyMap.h" 33 32 #include "PropertySlot.h" … … 68 67 69 68 virtual void mark(); 70 virtual JSType type() const; 71 72 bool inherits(const ClassInfo* classInfo) const { return isObject(classInfo); } // FIXME: Merge with isObject. 69 70 bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); } 73 71 74 72 JSValue* prototype() const; … … 101 99 virtual bool deleteProperty(ExecState*, unsigned propertyName); 102 100 103 virtual JSValue* defaultValue(ExecState*, JSType hint) const;101 virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const; 104 102 105 103 virtual bool implementsHasInstance() const; … … 108 106 virtual void getPropertyNames(ExecState*, PropertyNameArray&); 109 107 110 virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;108 virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; 111 109 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); 112 110 virtual bool toBoolean(ExecState*) const; … … 155 153 156 154 private: 155 virtual bool isObject() const; 156 157 157 const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; 158 158 JSValue* m_prototype; … … 258 258 { 259 259 if (JSValue** location = getDirectLocation(propertyName, slotIsWriteable)) { 260 if (m_propertyMap.hasGetterSetterProperties() && location[0]-> type() == GetterSetterType) {260 if (m_propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter()) { 261 261 slotIsWriteable = false; 262 262 fillGetterPropertySlot(slot, location); … … 282 282 { 283 283 if (JSValue** location = getDirectLocation(propertyName)) { 284 if (m_propertyMap.hasGetterSetterProperties() && location[0]-> type() == GetterSetterType)284 if (m_propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter()) 285 285 fillGetterPropertySlot(slot, location); 286 286 else … … 310 310 } 311 311 312 inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const312 inline JSValue* JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const 313 313 { 314 314 return defaultValue(exec, preferredType); -
trunk/JavaScriptCore/kjs/JSString.cpp
r35806 r35830 31 31 namespace KJS { 32 32 33 JSValue* JSString::toPrimitive(ExecState*, JSType) const33 JSValue* JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const 34 34 { 35 35 return const_cast<JSString*>(this); … … 110 110 } 111 111 112 bool JSString::isString() const 113 { 114 // FIXME: Change JSCell::isString to a non-virtual implementation like the one in Machine::isJSString. 115 return true; 116 } 117 112 118 JSString* jsString(ExecState* exec, const char* s) 113 119 { -
trunk/JavaScriptCore/kjs/JSString.h
r35806 r35830 62 62 63 63 private: 64 virtual JSType type() const { return StringType; }64 virtual bool isString() const; 65 65 66 virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;66 virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const; 67 67 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value); 68 68 virtual bool toBoolean(ExecState*) const; -
trunk/JavaScriptCore/kjs/JSValue.h
r35203 r35830 59 59 public: 60 60 // Querying the type. 61 JSType type() const;62 61 bool isUndefined() const; 63 62 bool isNull() const; … … 66 65 bool isNumber() const; 67 66 bool isString() const; 67 bool isGetterSetter() const; 68 68 bool isObject() const; 69 69 bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits. … … 89 89 90 90 // Basic conversions. 91 JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const; 91 enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; 92 JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; 92 93 bool getPrimitiveNumber(ExecState*, double& number, JSValue*&); 93 94 … … 188 189 inline bool JSValue::getBoolean() const 189 190 { 190 return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;191 return this == jsBoolean(true); 191 192 } 192 193 -
trunk/JavaScriptCore/kjs/collector.cpp
r35663 r35830 1024 1024 static const char* typeName(JSCell* val) 1025 1025 { 1026 const char* name = "???"; 1027 switch (val->type()) { 1028 case UnspecifiedType: 1029 break; 1030 case UndefinedType: 1031 name = "undefined"; 1032 break; 1033 case NullType: 1034 name = "null"; 1035 break; 1036 case BooleanType: 1037 name = "boolean"; 1038 break; 1039 case StringType: 1040 name = "string"; 1041 break; 1042 case NumberType: 1043 name = "number"; 1044 break; 1045 case ObjectType: { 1046 const ClassInfo* info = static_cast<JSObject*>(val)->classInfo(); 1047 name = info ? info->className : "Object"; 1048 break; 1049 } 1050 case GetterSetterType: 1051 name = "gettersetter"; 1052 break; 1053 } 1054 return name; 1026 if (val->isString()) 1027 return "string"; 1028 if (val->isNumber()) 1029 return "number"; 1030 if (val->isGetterSetter()) 1031 return "gettersetter"; 1032 ASSERT(val->isObject()); 1033 const ClassInfo* info = static_cast<JSObject*>(val)->classInfo(); 1034 return info ? info->className : "Object"; 1055 1035 } 1056 1036 -
trunk/JavaScriptCore/kjs/collector.h
r35807 r35830 108 108 109 109 JSGlobalData* globalData() const { return m_globalData; } 110 static bool fastIsNumber(JSCell*); 110 static bool isNumber(JSCell*); 111 111 112 private: 112 113 template <Heap::HeapType heapType> void* heapAllocate(size_t); … … 218 219 }; 219 220 220 inline bool Heap:: fastIsNumber(JSCell* cell)221 inline bool Heap::isNumber(JSCell* cell) 221 222 { 222 223 CollectorBlock* block = Heap::cellBlock(cell); -
trunk/JavaScriptCore/kjs/nodes.h
r35813 r35830 29 29 #include "Error.h" 30 30 #include "JSString.h" 31 #include "JSType.h" 31 32 #include "LabelStack.h" 32 33 #include "Opcode.h" -
trunk/JavaScriptCore/kjs/operations.cpp
r35027 r35830 37 37 38 38 // ECMA 11.9.3 39 bool equal(ExecState *exec, JSValue *v1, JSValue *v2)39 bool equal(ExecState* exec, JSValue* v1, JSValue* v2) 40 40 { 41 JSType t1 = v1->type(); 42 JSType t2 = v2->type(); 43 44 if (t1 != t2) { 45 if (t1 == UndefinedType) 46 t1 = NullType; 47 if (t2 == UndefinedType) 48 t2 = NullType; 49 50 if (t1 == BooleanType) 51 t1 = NumberType; 52 if (t2 == BooleanType) 53 t2 = NumberType; 54 55 if (t1 == NumberType && t2 == StringType) { 56 // use toNumber 57 } else if (t1 == StringType && t2 == NumberType) 58 t1 = NumberType; 59 // use toNumber 60 else { 61 if ((t1 == StringType || t1 == NumberType) && t2 == ObjectType) { 62 v2 = v2->toPrimitive(exec); 63 if (exec->hadException()) 64 return false; 65 return equal(exec, v1, v2); 66 } 67 if (t1 == NullType && t2 == ObjectType) 68 return static_cast<JSObject *>(v2)->masqueradeAsUndefined(); 69 if (t1 == ObjectType && (t2 == StringType || t2 == NumberType)) { 70 v1 = v1->toPrimitive(exec); 71 if (exec->hadException()) 72 return false; 73 return equal(exec, v1, v2); 74 } 75 if (t1 == ObjectType && t2 == NullType) 76 return static_cast<JSObject *>(v1)->masqueradeAsUndefined(); 77 if (t1 != t2) 78 return false; 79 } 41 startOver: 42 if (JSImmediate::areBothImmediateNumbers(v1, v2)) 43 return v1 == v2; 44 45 if (v1->isNumber() && v2->isNumber()) 46 return v1->uncheckedGetNumber() == v2->uncheckedGetNumber(); 47 48 bool s1 = v1->isString(); 49 bool s2 = v2->isString(); 50 if (s1 && s2) 51 return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value(); 52 53 if (v1->isUndefinedOrNull()) { 54 if (v2->isUndefinedOrNull()) 55 return true; 56 if (!v2->isObject()) 57 return false; 58 return static_cast<JSObject*>(v2)->masqueradeAsUndefined(); 80 59 } 81 82 if (t1 == UndefinedType || t1 == NullType) 83 return true; 84 85 if (t1 == NumberType) { 60 61 if (v2->isUndefinedOrNull()) { 62 if (!v1->isObject()) 63 return false; 64 return static_cast<JSObject*>(v1)->masqueradeAsUndefined(); 65 } 66 67 if (v1->isObject()) { 68 if (v2->isObject()) 69 return v1 == v2; 70 JSValue* p1 = v1->toPrimitive(exec); 71 if (exec->hadException()) 72 return false; 73 v1 = p1; 74 goto startOver; 75 } 76 77 if (v2->isObject()) { 78 JSValue* p2 = v2->toPrimitive(exec); 79 if (exec->hadException()) 80 return false; 81 v2 = p2; 82 goto startOver; 83 } 84 85 if (s1 || s2) { 86 86 double d1 = v1->toNumber(exec); 87 87 double d2 = v2->toNumber(exec); 88 88 return d1 == d2; 89 89 } 90 91 if (t1 == StringType) 92 return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value(); 93 94 if (t1 == BooleanType) 95 return v1->toBoolean(exec) == v2->toBoolean(exec); 96 97 // types are Object 90 91 if (v1->isBoolean()) { 92 if (v2->isNumber()) 93 return v1->getBoolean() == v2->uncheckedGetNumber(); 94 } else if (v2->isBoolean()) { 95 if (v1->isNumber()) 96 return v1->uncheckedGetNumber() == v2->getBoolean(); 97 } 98 98 99 return v1 == v2; 99 100 } … … 101 102 bool strictEqual(JSValue* v1, JSValue* v2) 102 103 { 103 JSType t1 = v1->type(); 104 JSType t2 = v2->type(); 105 106 if (t1 != t2) 107 return false; 104 if (JSImmediate::isEitherImmediate(v1, v2)) { 105 if (v1 == v2) 106 return true; 108 107 109 if (t1 == NumberType) 110 return v1->getNumber() == v2->getNumber(); 111 112 if (t1 == StringType) 113 return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value(); 114 115 return v1 == v2; // covers object, boolean, null, and undefined types 108 // The reason we can't just return false here is that 0 === -0, 109 // and while the former is an immediate number, the latter is not. 110 if (v1 == JSImmediate::from(0)) 111 return !JSImmediate::isImmediate(v2) 112 && static_cast<JSCell*>(v2)->isNumber() 113 && static_cast<JSNumberCell*>(v2)->value() == 0; 114 return v2 == JSImmediate::from(0) 115 && !JSImmediate::isImmediate(v1) 116 && static_cast<JSCell*>(v1)->isNumber() 117 && static_cast<JSNumberCell*>(v1)->value() == 0; 118 } 119 120 if (static_cast<JSCell*>(v1)->isNumber()) 121 return static_cast<JSCell*>(v2)->isNumber() 122 && static_cast<JSNumberCell*>(v1)->value() == static_cast<JSNumberCell*>(v2)->value(); 123 124 if (static_cast<JSCell*>(v1)->isString()) 125 return static_cast<JSCell*>(v2)->isString() 126 && static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value(); 127 128 return v1 == v2; 116 129 } 117 130
Note:
See TracChangeset
for help on using the changeset viewer.