2008-08-12 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- eliminate JSValue::type()
This will make it slightly easier to change the JSImmediate design without
having to touch so many call sites.
SunSpider says this change is a wash (looked like a slight speedup, but not
statistically significant).
* API/JSStringRef.cpp: Removed include of JSType.h.
* API/JSValueRef.cpp: Removed include of JSType.h.
(JSValueGetType): Replaced use of JSValue::type() with
JSValue::is functions.
* JavaScriptCore.exp: Updated.
* VM/JSPropertyNameIterator.cpp: Removed type() implementation.
(KJS::JSPropertyNameIterator::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
* VM/JSPropertyNameIterator.h: Ditto.
* VM/Machine.cpp:
(KJS::fastIsNumber): Updated for name change.
(KJS::fastToInt32): Ditto.
(KJS::fastToUInt32): Ditto.
(KJS::jsAddSlowCase): Updated toPrimitive caller for change from
JSType to PreferredPrimitiveType.
(KJS::jsAdd): Replaced calls to JSValue::type() with calls to
JSValue::isString().
(KJS::jsTypeStringForValue): Replaced calls to JSValue::type()
with multiple calls to JSValue::is -- we could make this a
virtual function instead if we want to have faster performance.
(KJS::Machine::privateExecute): Renamed JSImmediate::toTruncatedUInt32
to JSImmediate::getTruncatedUInt32 for consistency with other functions.
Changed two calls of JSValue::type() to JSValue::isString().
* kjs/GetterSetter.cpp:
(KJS::GetterSetter::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
(KJS::GetterSetter::isGetterSetter): Added.
* kjs/GetterSetter.h:
* kjs/JSCell.cpp:
(KJS::JSCell::isString): Added.
(KJS::JSCell::isGetterSetter): Added.
(KJS::JSCell::isObject): Added.
* kjs/JSCell.h: Eliminated type function. Added isGetterSetter.
Made isString and isObject virtual. Changed toPrimitive to take
PreferredPrimitiveType argument instead of JSType.
(KJS::JSCell::isNumber): Use Heap::isNumber for faster performance.
(KJS::JSValue::isGetterSetter): Added.
(KJS::JSValue::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
* kjs/JSImmediate.h: Removed JSValue::type() and replaced
JSValue::toTruncatedUInt32 with JSValue::getTruncatedUInt32.
(KJS::JSImmediate::isEitherImmediate): Added.
* kjs/JSNotAnObject.cpp:
(KJS::JSNotAnObject::toPrimitive): Changed to take
PreferredPrimitiveType argument instead of JSType.
* kjs/JSNotAnObject.h: Ditto.
* kjs/JSNumberCell.cpp:
(KJS::JSNumberCell::toPrimitive): Ditto.
* kjs/JSNumberCell.h:
(KJS::JSNumberCell::toInt32): Renamed from fastToInt32. There's no
other "slow" version of this once you have a JSNumberCell, so there's
no need for "fast" in the name. It's a feature that this hides the
base class toInt32, which does the same job less efficiently (and has
an additional ExecState argument).
(KJS::JSNumberCell::toUInt32): Ditto.
* kjs/JSObject.cpp:
(KJS::callDefaultValueFunction): Use isGetterSetter instead of type.
(KJS::JSObject::getPrimitiveNumber): Use PreferredPrimitiveType.
(KJS::JSObject::defaultValue): Ditto.
(KJS::JSObject::defineGetter): Use isGetterSetter.
(KJS::JSObject::defineSetter): Ditto.
(KJS::JSObject::lookupGetter): Ditto.
(KJS::JSObject::lookupSetter): Ditto.
(KJS::JSObject::toNumber): Use PreferredPrimitiveType.
(KJS::JSObject::toString): Ditto.
(KJS::JSObject::isObject): Added.
* kjs/JSObject.h:
(KJS::JSObject::inherits): Call the isObject from JSCell; it's now
hidden by our override of isObject.
(KJS::JSObject::getOwnPropertySlotForWrite): Use isGetterSetter
instead of type.
(KJS::JSObject::getOwnPropertySlot): Ditto.
(KJS::JSObject::toPrimitive): Use PreferredPrimitiveType.
* kjs/JSString.cpp:
(KJS::JSString::toPrimitive): Use PreferredPrimitiveType.
(KJS::JSString::isString): Added.
* kjs/JSString.h: Ditto.
* kjs/JSValue.h: Removed type(), added isGetterSetter(). Added
PreferredPrimitiveType enum and used it as the argument for the
toPrimitive function.
(KJS::JSValue::getBoolean): Simplified a bit an removed a branch.
* kjs/collector.cpp:
(KJS::typeName): Changed to use JSCell::is functions instead of
calling JSCell::type.
* kjs/collector.h:
(KJS::Heap::isNumber): Renamed from fastIsNumber.
* kjs/nodes.h: Added now-needed include of JSType, since the type
is used here to record types of values in the tree.
* kjs/operations.cpp:
(KJS::equal): Rewrote to no longer depend on type().
(KJS::strictEqual): Ditto.
JavaScriptGlue:
2008-08-12 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- eliminate JSValue::type()
* JSUtils.cpp:
(KJSValueToCFTypeInternal): Replaced uses of JSValue::type() with
JSValue::is functions.
* UserObjectImp.cpp:
(UserObjectImp::getOwnPropertySlot): Ditto.
(UserObjectImp::toPrimitive): Take PreferredPrimitiveType argument
instead of JSType argument.
* UserObjectImp.h: Ditto.
WebCore:
2008-08-12 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- eliminate JSValue::type()
* bridge/c/c_instance.cpp:
(KJS::Bindings::CInstance::defaultValue): Take PreferredPrimitiveType
argument instead of JSType argument. Removed unneeded code to handle
boolean, since that's never passed.
* bridge/c/c_instance.h: Ditto.
* bridge/c/c_utility.cpp:
(KJS::Bindings::convertValueToNPVariant): Use JSValue::is functions
instead of JSValue::type(). Removed unneeded code to handle
"unspecified".
* bridge/jni/jni_instance.cpp:
(JavaInstance::defaultValue): Take PreferredPrimitiveType argument
instead of JSType argument. Removed unneeded code to handle boolean.
* bridge/jni/jni_instance.h: Ditto.
* bridge/jni/jni_jsobject.mm:
(JavaJSObject::convertValueToJObject): Use JSValue::is functions
instead of JSValue::type().
* bridge/objc/objc_instance.h: Take PreferredPrimitiveType argument
instead of JSType argument. Removed unused argument.
* bridge/objc/objc_instance.mm:
(ObjcInstance::getValueOfUndefinedField): Removed unused argument.
(ObjcInstance::defaultValue): Take PreferredPrimitiveType argument
instead of JSType argument. Removed unneeded code to handle boolean
and another dead code path for unknown types.
* bridge/objc/objc_runtime.h: Take PreferredPrimitiveType argument
instead of JSType argument. Removed override of type() that caused
the fallback object to return "UndefinedType" when there is no
invokeUndefinedMethodFromWebScript:withArguments: method defined.
That didn't accomplish much, since most checks for undefined don't
ever call type().
* bridge/objc/objc_runtime.mm:
(ObjcFallbackObjectImp::defaultValue): Ditto.
* bridge/qt/qt_instance.cpp:
(KJS::Bindings::QtInstance::defaultValue): Take PreferredPrimitiveType
argument instead of JSType argument. Removed unneeded code to handle
boolean.
* bridge/qt/qt_instance.h: Ditto.
* bridge/runtime.h:
(KJS::Bindings::Instance::getValueOfUndefinedField): Removed
unsed argument.
* bridge/runtime_object.cpp:
(RuntimeObjectImp::defaultValue): Take PreferredPrimitiveType
argument instead of JSType argument.
* bridge/runtime_object.h: Ditto.
WebKit/mac:
2008-08-12 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- eliminate JSValue::type()
* WebView/WebView.mm:
(aeDescFromJSValue): Rewrite to use the JSValue::is functions instead
of a switch on JSValue::type().
LayoutTests:
2008-08-12 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- added a test since I had to rewrite the == and === operators
* fast/js/equality-expected.txt: Added.
* fast/js/equality.html: Added.
* fast/js/resources/equality.js: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@35830
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
#include "APICast.h"
#include "JSCallbackObject.h"
-#include <kjs/JSType.h>
#include <kjs/JSGlobalObject.h>
#include <kjs/JSString.h>
#include <kjs/operations.h>
JSType JSValueGetType(JSContextRef, JSValueRef value)
{
KJS::JSValue* jsValue = toJS(value);
- switch (jsValue->type()) {
- case KJS::UndefinedType:
- return kJSTypeUndefined;
- case KJS::NullType:
- return kJSTypeNull;
- case KJS::BooleanType:
- return kJSTypeBoolean;
- case KJS::NumberType:
- return kJSTypeNumber;
- case KJS::StringType:
- return kJSTypeString;
- case KJS::ObjectType:
- return kJSTypeObject;
- default:
- ASSERT(!"JSValueGetType: unknown type code.\n");
- return kJSTypeUndefined;
- }
+ if (jsValue->isUndefined())
+ return kJSTypeUndefined;
+ if (jsValue->isNull())
+ return kJSTypeNull;
+ if (jsValue->isBoolean())
+ return kJSTypeBoolean;
+ if (jsValue->isNumber())
+ return kJSTypeNumber;
+ if (jsValue->isString())
+ return kJSTypeString;
+ ASSERT(jsValue->isObject());
+ return kJSTypeObject;
}
using namespace KJS; // placed here to avoid conflict between KJS::JSType and JSType, above.
+2008-08-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - eliminate JSValue::type()
+
+ This will make it slightly easier to change the JSImmediate design without
+ having to touch so many call sites.
+
+ SunSpider says this change is a wash (looked like a slight speedup, but not
+ statistically significant).
+
+ * API/JSStringRef.cpp: Removed include of JSType.h.
+ * API/JSValueRef.cpp: Removed include of JSType.h.
+ (JSValueGetType): Replaced use of JSValue::type() with
+ JSValue::is functions.
+
+ * JavaScriptCore.exp: Updated.
+
+ * VM/JSPropertyNameIterator.cpp: Removed type() implementation.
+ (KJS::JSPropertyNameIterator::toPrimitive): Changed to take
+ PreferredPrimitiveType argument instead of JSType.
+ * VM/JSPropertyNameIterator.h: Ditto.
+
+ * VM/Machine.cpp:
+ (KJS::fastIsNumber): Updated for name change.
+ (KJS::fastToInt32): Ditto.
+ (KJS::fastToUInt32): Ditto.
+ (KJS::jsAddSlowCase): Updated toPrimitive caller for change from
+ JSType to PreferredPrimitiveType.
+ (KJS::jsAdd): Replaced calls to JSValue::type() with calls to
+ JSValue::isString().
+ (KJS::jsTypeStringForValue): Replaced calls to JSValue::type()
+ with multiple calls to JSValue::is -- we could make this a
+ virtual function instead if we want to have faster performance.
+ (KJS::Machine::privateExecute): Renamed JSImmediate::toTruncatedUInt32
+ to JSImmediate::getTruncatedUInt32 for consistency with other functions.
+ Changed two calls of JSValue::type() to JSValue::isString().
+
+ * kjs/GetterSetter.cpp:
+ (KJS::GetterSetter::toPrimitive): Changed to take
+ PreferredPrimitiveType argument instead of JSType.
+ (KJS::GetterSetter::isGetterSetter): Added.
+ * kjs/GetterSetter.h:
+
+ * kjs/JSCell.cpp:
+ (KJS::JSCell::isString): Added.
+ (KJS::JSCell::isGetterSetter): Added.
+ (KJS::JSCell::isObject): Added.
+
+ * kjs/JSCell.h: Eliminated type function. Added isGetterSetter.
+ Made isString and isObject virtual. Changed toPrimitive to take
+ PreferredPrimitiveType argument instead of JSType.
+ (KJS::JSCell::isNumber): Use Heap::isNumber for faster performance.
+ (KJS::JSValue::isGetterSetter): Added.
+ (KJS::JSValue::toPrimitive): Changed to take
+ PreferredPrimitiveType argument instead of JSType.
+
+ * kjs/JSImmediate.h: Removed JSValue::type() and replaced
+ JSValue::toTruncatedUInt32 with JSValue::getTruncatedUInt32.
+ (KJS::JSImmediate::isEitherImmediate): Added.
+
+ * kjs/JSNotAnObject.cpp:
+ (KJS::JSNotAnObject::toPrimitive): Changed to take
+ PreferredPrimitiveType argument instead of JSType.
+ * kjs/JSNotAnObject.h: Ditto.
+ * kjs/JSNumberCell.cpp:
+ (KJS::JSNumberCell::toPrimitive): Ditto.
+ * kjs/JSNumberCell.h:
+ (KJS::JSNumberCell::toInt32): Renamed from fastToInt32. There's no
+ other "slow" version of this once you have a JSNumberCell, so there's
+ no need for "fast" in the name. It's a feature that this hides the
+ base class toInt32, which does the same job less efficiently (and has
+ an additional ExecState argument).
+ (KJS::JSNumberCell::toUInt32): Ditto.
+
+ * kjs/JSObject.cpp:
+ (KJS::callDefaultValueFunction): Use isGetterSetter instead of type.
+ (KJS::JSObject::getPrimitiveNumber): Use PreferredPrimitiveType.
+ (KJS::JSObject::defaultValue): Ditto.
+ (KJS::JSObject::defineGetter): Use isGetterSetter.
+ (KJS::JSObject::defineSetter): Ditto.
+ (KJS::JSObject::lookupGetter): Ditto.
+ (KJS::JSObject::lookupSetter): Ditto.
+ (KJS::JSObject::toNumber): Use PreferredPrimitiveType.
+ (KJS::JSObject::toString): Ditto.
+ (KJS::JSObject::isObject): Added.
+
+ * kjs/JSObject.h:
+ (KJS::JSObject::inherits): Call the isObject from JSCell; it's now
+ hidden by our override of isObject.
+ (KJS::JSObject::getOwnPropertySlotForWrite): Use isGetterSetter
+ instead of type.
+ (KJS::JSObject::getOwnPropertySlot): Ditto.
+ (KJS::JSObject::toPrimitive): Use PreferredPrimitiveType.
+
+ * kjs/JSString.cpp:
+ (KJS::JSString::toPrimitive): Use PreferredPrimitiveType.
+ (KJS::JSString::isString): Added.
+ * kjs/JSString.h: Ditto.
+
+ * kjs/JSValue.h: Removed type(), added isGetterSetter(). Added
+ PreferredPrimitiveType enum and used it as the argument for the
+ toPrimitive function.
+ (KJS::JSValue::getBoolean): Simplified a bit an removed a branch.
+
+ * kjs/collector.cpp:
+ (KJS::typeName): Changed to use JSCell::is functions instead of
+ calling JSCell::type.
+
+ * kjs/collector.h:
+ (KJS::Heap::isNumber): Renamed from fastIsNumber.
+
+ * kjs/nodes.h: Added now-needed include of JSType, since the type
+ is used here to record types of values in the tree.
+
+ * kjs/operations.cpp:
+ (KJS::equal): Rewrote to no longer depend on type().
+ (KJS::strictEqual): Ditto.
+
2008-08-18 Kevin McCullough <kmccullough@apple.com>
Reviewed by Tim.
__ZNK3KJS4Node8toStringEv
__ZNK3KJS6JSCell12toThisObjectEPNS_9ExecStateE
__ZNK3KJS6JSCell12toThisStringEPNS_9ExecStateE
+__ZNK3KJS6JSCell14isGetterSetterEv
__ZNK3KJS6JSCell17getTruncatedInt32ERi
__ZNK3KJS6JSCell18getTruncatedUInt32ERj
+__ZNK3KJS6JSCell8isObjectEv
+__ZNK3KJS6JSCell8isStringEv
__ZNK3KJS6JSCell9classInfoEv
__ZNK3KJS6JSCell9getNumberEv
__ZNK3KJS6JSCell9getStringERNS_7UStringE
__ZNK3KJS7UString8toUInt32EPbb
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateEj
-__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
+__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_7JSValue22PreferredPrimitiveTypeE
__ZNK3KJS8JSObject12toThisObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject14toGlobalObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
__ZNK3KJS8JSObject21implementsHasInstanceEv
-__ZNK3KJS8JSObject4typeEv
+__ZNK3KJS8JSObject8isObjectEv
__ZNK3KJS8JSObject8toNumberEPNS_9ExecStateE
__ZNK3KJS8JSObject8toObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject8toStringEPNS_9ExecStateE
invalidate();
}
-JSType JSPropertyNameIterator::type() const
-{
- return UnspecifiedType;
-}
-
-JSValue* JSPropertyNameIterator::toPrimitive(ExecState*, JSType) const
+JSValue* JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return 0;
virtual ~JSPropertyNameIterator();
- virtual JSType type() const;
- virtual JSValue* toPrimitive(ExecState*, JSType) const;
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double&, JSValue*&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
return scopeDepth;
}
-static bool fastIsNumber(JSValue* value, double& arg) {
+// FIXME: This operation should be called "getNumber", not "isNumber" (as it is in JSValue.h).
+// FIXME: There's no need to have a "slow" version of this. All versions should be fast.
+static bool fastIsNumber(JSValue* value, double& arg)
+{
if (JSImmediate::isNumber(value))
arg = JSImmediate::getTruncatedInt32(value);
- else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
+ else if (Heap::isNumber(static_cast<JSCell*>(value)))
arg = static_cast<JSNumberCell*>(value)->value();
else
return false;
return true;
}
-static bool fastToInt32(JSValue* value, int32_t& arg) {
+// FIXME: Why doesn't JSValue::toInt32 have the Heap::isNumber optimization?
+static bool fastToInt32(JSValue* value, int32_t& arg)
+{
if (JSImmediate::isNumber(value))
arg = JSImmediate::getTruncatedInt32(value);
- else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
- arg = static_cast<JSNumberCell*>(value)->fastToInt32();
+ else if (Heap::isNumber(static_cast<JSCell*>(value)))
+ arg = static_cast<JSNumberCell*>(value)->toInt32();
else
return false;
return true;
}
-static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg) {
+static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg)
+{
if (JSImmediate::isNumber(value)) {
if (JSImmediate::getTruncatedUInt32(value, arg))
return true;
bool scratch;
arg = JSValue::toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
return true;
- } else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
- arg = static_cast<JSNumberCell*>(value)->fastToUInt32();
+ } else if (Heap::isNumber(static_cast<JSCell*>(value)))
+ arg = static_cast<JSNumberCell*>(value)->toUInt32();
else
return false;
return true;
static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
{
// exception for the Date exception in defaultValue()
- JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
- JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
+ JSValue* p1 = v1->toPrimitive(exec);
+ JSValue* p2 = v2->toPrimitive(exec);
if (p1->isString() || p2->isString()) {
UString value = p1->toString(exec) + p2->toString(exec);
{
double left;
double right;
-
if (fastIsNumber(v1, left) && fastIsNumber(v2, right))
return jsNumber(exec, left + right);
- JSType t1 = v1->type();
- JSType t2 = v2->type();
- const unsigned bothTypes = (t1 << 3) | t2;
- ASSERT(bothTypes != ((NumberType << 3) | NumberType));
- if (bothTypes == ((StringType << 3) | StringType)) {
+ if (v1->isString() && v2->isString()) {
UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
if (value.isNull())
return throwOutOfMemoryError(exec);
static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
{
- switch (v->type()) {
- case UndefinedType:
+ if (v->isUndefined())
+ return jsString(exec, "undefined");
+ if (v->isBoolean())
+ return jsString(exec, "boolean");
+ if (v->isNumber())
+ return jsString(exec, "number");
+ if (v->isString())
+ return jsString(exec, "string");
+ if (v->isObject()) {
+ // Return "undefined" for objects that should be treated
+ // as null when doing comparisons.
+ if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
return jsString(exec, "undefined");
- case NullType:
- return jsString(exec, "object");
- case BooleanType:
- return jsString(exec, "boolean");
- case NumberType:
- return jsString(exec, "number");
- case StringType:
- return jsString(exec, "string");
- default:
- if (v->isObject()) {
- // Return "undefined" for objects that should be treated
- // as null when doing comparisons.
- if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
- return jsString(exec, "undefined");
- CallData callData;
- if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
- return jsString(exec, "function");
- }
-
- return jsString(exec, "object");
+ CallData callData;
+ if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
+ return jsString(exec, "function");
}
+ return jsString(exec, "object");
}
static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
int32_t left;
uint32_t right;
if (JSImmediate::areBothImmediateNumbers(val, shift))
- r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
+ r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
else if (fastToInt32(val, left) && fastToUInt32(shift, right))
r[dst] = jsNumber(exec, left << (right & 0x1f));
else {
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
- if (scrutinee->type() != StringType)
+ if (!scrutinee->isString())
vPC += defaultOffset;
else {
UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
- if (scrutinee->type() != StringType)
+ if (!scrutinee->isString())
vPC += defaultOffset;
else
vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
m_setter->mark();
}
-JSValue* GetterSetter::toPrimitive(ExecState*, JSType) const
+JSValue* GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
ASSERT_NOT_REACHED();
return jsNull();
return jsNull()->toObject(exec);
}
+bool GetterSetter::isGetterSetter() const
+{
+ return true;
+}
+
} // namespace KJS
{
}
- JSType type() const { return GetterSetterType; }
-
virtual void mark();
JSObject* getter() const { return m_getter; }
void setSetter(JSObject* setter) { m_setter = setter; }
private:
- virtual JSValue* toPrimitive(ExecState*, JSType preferred) const;
+ virtual bool isGetterSetter() const;
+
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
return 0;
}
+bool JSCell::isString() const
+{
+ return false;
+}
+
+bool JSCell::isGetterSetter() const
+{
+ return false;
+}
+
+bool JSCell::isObject() const
+{
+ return false;
+}
+
} // namespace KJS
public:
// Querying the type.
- virtual JSType type() const = 0;
bool isNumber() const;
- bool isString() const;
- bool isObject() const;
- bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
+ virtual bool isString() const;
+ virtual bool isGetterSetter() const;
+ virtual bool isObject() const;
+ virtual bool isObject(const ClassInfo*) const;
// Extracting the value.
bool getNumber(double&) const;
virtual bool getTruncatedUInt32(uint32_t&) const;
// Basic conversions.
- virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const = 0;
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
virtual bool toBoolean(ExecState*) const = 0;
virtual double toNumber(ExecState*) const = 0;
inline bool JSCell::isNumber() const
{
- return type() == NumberType;
- }
-
- inline bool JSCell::isString() const
- {
- return type() == StringType;
- }
-
- inline bool JSCell::isObject() const
- {
- return type() == ObjectType;
+ return Heap::isNumber(const_cast<JSCell*>(this));
}
inline bool JSCell::marked() const
return !JSImmediate::isImmediate(this) && asCell()->isString();
}
+ inline bool JSValue::isGetterSetter() const
+ {
+ return !JSImmediate::isImmediate(this) && asCell()->isGetterSetter();
+ }
+
inline bool JSValue::isObject() const
{
return !JSImmediate::isImmediate(this) && asCell()->isObject();
return JSImmediate::isImmediate(this) || asCell()->marked();
}
- inline JSType JSValue::type() const
- {
- return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
- }
-
- inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
+ inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
}
/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
*
* This library is free software; you can redistribute it and/or
#ifndef KJS_JS_IMMEDIATE_H
#define KJS_JS_IMMEDIATE_H
-#include "JSType.h"
#include <wtf/Assertions.h>
#include <wtf/AlwaysInline.h>
#include <wtf/MathExtras.h>
class UString;
/*
- * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
+ * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
* value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
* because allocator alignment guarantees they will be 00 in cell pointers.
*
*/
class JSImmediate {
+ private:
static const uintptr_t TagMask = 0x3u; // primary tag is 2 bits long
- static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates int, this dominates the following bit
+ static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit
static const uintptr_t TagBitTypeOther = 0x2u; // second bit set indicates immediate other than an integer
static const uintptr_t ExtendedTagMask = 0xCu; // extended tag holds a further two bits
public:
static ALWAYS_INLINE bool isImmediate(const JSValue* v)
{
- return (reinterpret_cast<uintptr_t>(v) & TagMask);
+ return reinterpret_cast<uintptr_t>(v) & TagMask;
}
static ALWAYS_INLINE bool isNumber(const JSValue* v)
{
- return (reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger);
+ return reinterpret_cast<uintptr_t>(v) & TagBitTypeInteger;
}
static ALWAYS_INLINE bool isPositiveNumber(const JSValue* v)
static ALWAYS_INLINE bool isBoolean(const JSValue* v)
{
- return ((reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool);
+ return (reinterpret_cast<uintptr_t>(v) & FullTagTypeMask) == FullTagTypeBool;
}
static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
{
// Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
- return ((reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull);
+ return (reinterpret_cast<uintptr_t>(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
}
static bool isNegative(const JSValue* v)
static JSValue* from(unsigned long long);
static JSValue* from(double);
+ static ALWAYS_INLINE bool isEitherImmediate(const JSValue* v1, const JSValue* v2)
+ {
+ return (reinterpret_cast<uintptr_t>(v1) | reinterpret_cast<uintptr_t>(v2)) & TagMask;
+ }
+
static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
{
- return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger);
+ return reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagBitTypeInteger;
}
static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
static bool toBoolean(const JSValue*);
static JSObject* toObject(const JSValue*, ExecState*);
static UString toString(const JSValue*);
- static uint32_t toTruncatedUInt32(const JSValue*);
- static JSType type(const JSValue*);
static bool getUInt32(const JSValue*, uint32_t&);
static bool getTruncatedInt32(const JSValue*, int32_t&);
static bool getTruncatedUInt32(const JSValue*, uint32_t&);
static int32_t getTruncatedInt32(const JSValue*);
+ static uint32_t getTruncatedUInt32(const JSValue*);
static JSValue* trueImmediate();
static JSValue* falseImmediate();
static JSObject* prototype(const JSValue*, ExecState*);
private:
- // Immediate values are restricted to a 30 bit signed value.
static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
static const unsigned maxImmediateUInt = maxImmediateInt;
static ALWAYS_INLINE bool boolValue(const JSValue* v)
{
- return (rawValue(v) & ExtendedPayloadBitBoolValue) != 0;
+ return rawValue(v) & ExtendedPayloadBitBoolValue;
}
static ALWAYS_INLINE uintptr_t rawValue(const JSValue* v)
{
ASSERT(isImmediate(v));
uintptr_t bits = rawValue(v);
- return
- (bits & TagBitTypeInteger) ? (bits != TagBitTypeInteger) : // !0 ints
- (bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue)); // bool true
+ return (bits & TagBitTypeInteger)
+ ? bits != TagBitTypeInteger // !0 ints
+ : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true
}
- ALWAYS_INLINE uint32_t JSImmediate::toTruncatedUInt32(const JSValue* v)
+ ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(const JSValue* v)
{
ASSERT(isNumber(v));
return intValue(v);
return 0;
// Check for data loss from conversion to int.
- if ((intVal != d) || (!intVal && signbit(d)))
+ if (intVal != d || (!intVal && signbit(d)))
return 0;
return makeInt(intVal);
return getUInt32(v, i);
}
- ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v)
- {
- ASSERT(isImmediate(v));
-
- if (isNumber(v))
- return NumberType;
- if (isBoolean(v))
- return BooleanType;
- if (v != undefinedImmediate())
- return NullType;
- return UndefinedType;
- }
-
ALWAYS_INLINE JSValue* jsUndefined()
{
return JSImmediate::undefinedImmediate();
ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
// JSValue methods
-JSValue* JSNotAnObject::toPrimitive(ExecState* exec, JSType) const
+JSValue* JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
{
UNUSED_PARAM(exec);
ASSERT(exec->hadException() && exec->exception() == m_exception);
private:
// JSValue methods
- virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
#include "config.h"
#include "JSNumberCell.h"
-#include "JSType.h"
#include "NumberObject.h"
#include "ustring.h"
namespace KJS {
-JSType JSNumberCell::type() const
-{
- return NumberType;
-}
-
-JSValue* JSNumberCell::toPrimitive(ExecState*, JSType) const
+JSValue* JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
return const_cast<JSNumberCell*>(this);
}
public:
double value() const { return m_value; }
- virtual JSType type() const;
-
- virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toThisString(ExecState*) const;
virtual JSObject* toThisObject(ExecState*) const;
virtual JSValue* getJSNumber();
- int32_t fastToInt32() const;
- uint32_t fastToUInt32() const;
+
+ int32_t toInt32() const;
+ uint32_t toUInt32() const;
void* operator new(size_t size, ExecState* exec)
{
return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : static_cast<const JSNumberCell*>(this)->value();
}
- inline int32_t JSNumberCell::fastToInt32() const
+ inline int32_t JSNumberCell::toInt32() const
{
if (m_value >= -2147483648.0 && m_value < 2147483648.0)
return static_cast<int32_t>(m_value);
return JSValue::toInt32SlowCase(m_value, scratch);
}
- inline uint32_t JSNumberCell::fastToUInt32() const
+ inline uint32_t JSNumberCell::toUInt32() const
{
if (m_value >= 0.0 && m_value < 4294967296.0)
return static_cast<uint32_t>(m_value);
#endif
}
-JSType JSObject::type() const
-{
- return ObjectType;
-}
-
UString JSObject::className() const
{
const ClassInfo* info = classInfo();
return exec->exception();
JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
- ASSERT(result->type() != GetterSetterType);
+ ASSERT(!result->isGetterSetter());
if (exec->hadException())
return exec->exception();
if (result->isObject())
bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
{
- result = defaultValue(exec, NumberType);
+ result = defaultValue(exec, PreferNumber);
number = result->toNumber(exec);
return !result->isString();
}
// ECMA 8.6.2.6
-JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
+JSValue* JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
// Must call toString first for Date objects.
- if ((hint == StringType) || (hint != NumberType && m_prototype == exec->lexicalGlobalObject()->datePrototype())) {
+ if ((hint == PreferString) || (hint != PreferNumber && m_prototype == exec->lexicalGlobalObject()->datePrototype())) {
if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
return value;
if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))
{
JSValue* object = getDirect(propertyName);
GetterSetter* getterSetter;
- if (object && object->type() == GetterSetterType)
+ if (object && object->isGetterSetter())
getterSetter = static_cast<GetterSetter*>(object);
else {
getterSetter = new (exec) GetterSetter;
{
JSValue* object = getDirect(propertyName);
GetterSetter* getterSetter;
- if (object && object->type() == GetterSetterType)
+ if (object && object->isGetterSetter())
getterSetter = static_cast<GetterSetter*>(object);
else {
getterSetter = new (exec) GetterSetter;
while (true) {
JSValue* value = object->getDirect(propertyName);
if (value) {
- if (value->type() != GetterSetterType)
+ if (!value->isGetterSetter())
return jsUndefined();
JSObject* functionObject = static_cast<GetterSetter*>(value)->getter();
if (!functionObject)
while (true) {
JSValue* value = object->getDirect(propertyName);
if (value) {
- if (value->type() != GetterSetterType)
+ if (!value->isGetterSetter())
return jsUndefined();
JSObject* functionObject = static_cast<GetterSetter*>(value)->setter();
if (!functionObject)
double JSObject::toNumber(ExecState* exec) const
{
- JSValue* primitive = toPrimitive(exec, NumberType);
+ JSValue* primitive = toPrimitive(exec, PreferNumber);
if (exec->hadException()) // should be picked up soon in nodes.cpp
return 0.0;
return primitive->toNumber(exec);
UString JSObject::toString(ExecState* exec) const
{
- JSValue* primitive = toPrimitive(exec, StringType);
+ JSValue* primitive = toPrimitive(exec, PreferString);
if (exec->hadException())
return "";
return primitive->toString(exec);
slot.setUndefined();
}
+bool JSObject::isObject() const
+{
+ return true;
+}
+
JSObject* constructEmptyObject(ExecState* exec)
{
return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype());
#include "CommonIdentifiers.h"
#include "ExecState.h"
#include "JSNumberCell.h"
-#include "JSType.h"
#include "PropertyMap.h"
#include "PropertySlot.h"
#include "ScopeChain.h"
JSObject();
virtual void mark();
- virtual JSType type() const;
- bool inherits(const ClassInfo* classInfo) const { return isObject(classInfo); } // FIXME: Merge with isObject.
+ bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
JSValue* prototype() const;
void setPrototype(JSValue* prototype);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
- virtual JSValue* defaultValue(ExecState*, JSType hint) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
virtual bool implementsHasInstance() const;
virtual bool hasInstance(ExecState*, JSValue*);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
- virtual JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
private:
+ virtual bool isObject() const;
+
const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
JSValue* m_prototype;
};
ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
{
if (JSValue** location = getDirectLocation(propertyName, slotIsWriteable)) {
- if (m_propertyMap.hasGetterSetterProperties() && location[0]->type() == GetterSetterType) {
+ if (m_propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter()) {
slotIsWriteable = false;
fillGetterPropertySlot(slot, location);
} else
ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
if (JSValue** location = getDirectLocation(propertyName)) {
- if (m_propertyMap.hasGetterSetterProperties() && location[0]->type() == GetterSetterType)
+ if (m_propertyMap.hasGetterSetterProperties() && location[0]->isGetterSetter())
fillGetterPropertySlot(slot, location);
else
slot.setValueSlot(location);
m_propertyMap.put(propertyName, jsNumber(exec, value), attr);
}
-inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const
+inline JSValue* JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
return defaultValue(exec, preferredType);
}
namespace KJS {
-JSValue* JSString::toPrimitive(ExecState*, JSType) const
+JSValue* JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
{
return const_cast<JSString*>(this);
}
return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}
+bool JSString::isString() const
+{
+ // FIXME: Change JSCell::isString to a non-virtual implementation like the one in Machine::isJSString.
+ return true;
+}
+
JSString* jsString(ExecState* exec, const char* s)
{
return new (exec) JSString(s ? s : "");
}
private:
- virtual JSType type() const { return StringType; }
+ virtual bool isString() const;
- virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
public:
// Querying the type.
- JSType type() const;
bool isUndefined() const;
bool isNull() const;
bool isUndefinedOrNull() const;
bool isBoolean() const;
bool isNumber() const;
bool isString() const;
+ bool isGetterSetter() const;
bool isObject() const;
bool isObject(const ClassInfo*) const; // FIXME: Merge with inherits.
bool getTruncatedUInt32(uint32_t&) const;
// Basic conversions.
- JSValue* toPrimitive(ExecState*, JSType preferredType = UnspecifiedType) const;
+ enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
+ JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
bool toBoolean(ExecState*) const;
inline bool JSValue::getBoolean() const
{
- return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
+ return this == jsBoolean(true);
}
ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
static const char* typeName(JSCell* val)
{
- const char* name = "???";
- switch (val->type()) {
- case UnspecifiedType:
- break;
- case UndefinedType:
- name = "undefined";
- break;
- case NullType:
- name = "null";
- break;
- case BooleanType:
- name = "boolean";
- break;
- case StringType:
- name = "string";
- break;
- case NumberType:
- name = "number";
- break;
- case ObjectType: {
- const ClassInfo* info = static_cast<JSObject*>(val)->classInfo();
- name = info ? info->className : "Object";
- break;
- }
- case GetterSetterType:
- name = "gettersetter";
- break;
- }
- return name;
+ if (val->isString())
+ return "string";
+ if (val->isNumber())
+ return "number";
+ if (val->isGetterSetter())
+ return "gettersetter";
+ ASSERT(val->isObject());
+ const ClassInfo* info = static_cast<JSObject*>(val)->classInfo();
+ return info ? info->className : "Object";
}
HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; }
JSGlobalData* globalData() const { return m_globalData; }
- static bool fastIsNumber(JSCell*);
+ static bool isNumber(JSCell*);
+
private:
template <Heap::HeapType heapType> void* heapAllocate(size_t);
template <Heap::HeapType heapType> size_t sweep();
Heap::HeapType type;
};
- inline bool Heap::fastIsNumber(JSCell* cell)
+ inline bool Heap::isNumber(JSCell* cell)
{
CollectorBlock* block = Heap::cellBlock(cell);
return block && block->type == NumberHeap;
#include "Error.h"
#include "JSString.h"
+#include "JSType.h"
#include "LabelStack.h"
#include "Opcode.h"
#include "RegisterID.h"
namespace KJS {
// ECMA 11.9.3
-bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
+bool equal(ExecState* exec, JSValue* v1, JSValue* v2)
{
- JSType t1 = v1->type();
- JSType t2 = v2->type();
-
- if (t1 != t2) {
- if (t1 == UndefinedType)
- t1 = NullType;
- if (t2 == UndefinedType)
- t2 = NullType;
-
- if (t1 == BooleanType)
- t1 = NumberType;
- if (t2 == BooleanType)
- t2 = NumberType;
-
- if (t1 == NumberType && t2 == StringType) {
- // use toNumber
- } else if (t1 == StringType && t2 == NumberType)
- t1 = NumberType;
- // use toNumber
- else {
- if ((t1 == StringType || t1 == NumberType) && t2 == ObjectType) {
- v2 = v2->toPrimitive(exec);
- if (exec->hadException())
- return false;
- return equal(exec, v1, v2);
- }
- if (t1 == NullType && t2 == ObjectType)
- return static_cast<JSObject *>(v2)->masqueradeAsUndefined();
- if (t1 == ObjectType && (t2 == StringType || t2 == NumberType)) {
- v1 = v1->toPrimitive(exec);
- if (exec->hadException())
- return false;
- return equal(exec, v1, v2);
- }
- if (t1 == ObjectType && t2 == NullType)
- return static_cast<JSObject *>(v1)->masqueradeAsUndefined();
- if (t1 != t2)
- return false;
- }
+startOver:
+ if (JSImmediate::areBothImmediateNumbers(v1, v2))
+ return v1 == v2;
+
+ if (v1->isNumber() && v2->isNumber())
+ return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
+
+ bool s1 = v1->isString();
+ bool s2 = v2->isString();
+ if (s1 && s2)
+ return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
+
+ if (v1->isUndefinedOrNull()) {
+ if (v2->isUndefinedOrNull())
+ return true;
+ if (!v2->isObject())
+ return false;
+ return static_cast<JSObject*>(v2)->masqueradeAsUndefined();
+ }
+
+ if (v2->isUndefinedOrNull()) {
+ if (!v1->isObject())
+ return false;
+ return static_cast<JSObject*>(v1)->masqueradeAsUndefined();
}
-
- if (t1 == UndefinedType || t1 == NullType)
- return true;
-
- if (t1 == NumberType) {
+
+ if (v1->isObject()) {
+ if (v2->isObject())
+ return v1 == v2;
+ JSValue* p1 = v1->toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v1 = p1;
+ goto startOver;
+ }
+
+ if (v2->isObject()) {
+ JSValue* p2 = v2->toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v2 = p2;
+ goto startOver;
+ }
+
+ if (s1 || s2) {
double d1 = v1->toNumber(exec);
double d2 = v2->toNumber(exec);
return d1 == d2;
}
-
- if (t1 == StringType)
- return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
-
- if (t1 == BooleanType)
- return v1->toBoolean(exec) == v2->toBoolean(exec);
-
- // types are Object
+
+ if (v1->isBoolean()) {
+ if (v2->isNumber())
+ return v1->getBoolean() == v2->uncheckedGetNumber();
+ } else if (v2->isBoolean()) {
+ if (v1->isNumber())
+ return v1->uncheckedGetNumber() == v2->getBoolean();
+ }
+
return v1 == v2;
}
bool strictEqual(JSValue* v1, JSValue* v2)
{
- JSType t1 = v1->type();
- JSType t2 = v2->type();
-
- if (t1 != t2)
- return false;
-
- if (t1 == NumberType)
- return v1->getNumber() == v2->getNumber();
-
- if (t1 == StringType)
- return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
-
- return v1 == v2; // covers object, boolean, null, and undefined types
+ if (JSImmediate::isEitherImmediate(v1, v2)) {
+ if (v1 == v2)
+ return true;
+
+ // The reason we can't just return false here is that 0 === -0,
+ // and while the former is an immediate number, the latter is not.
+ if (v1 == JSImmediate::from(0))
+ return !JSImmediate::isImmediate(v2)
+ && static_cast<JSCell*>(v2)->isNumber()
+ && static_cast<JSNumberCell*>(v2)->value() == 0;
+ return v2 == JSImmediate::from(0)
+ && !JSImmediate::isImmediate(v1)
+ && static_cast<JSCell*>(v1)->isNumber()
+ && static_cast<JSNumberCell*>(v1)->value() == 0;
+ }
+
+ if (static_cast<JSCell*>(v1)->isNumber())
+ return static_cast<JSCell*>(v2)->isNumber()
+ && static_cast<JSNumberCell*>(v1)->value() == static_cast<JSNumberCell*>(v2)->value();
+
+ if (static_cast<JSCell*>(v1)->isString())
+ return static_cast<JSCell*>(v2)->isString()
+ && static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
+
+ return v1 == v2;
}
JSValue* throwOutOfMemoryError(ExecState* exec)
+2008-08-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - eliminate JSValue::type()
+
+ * JSUtils.cpp:
+ (KJSValueToCFTypeInternal): Replaced uses of JSValue::type() with
+ JSValue::is functions.
+ * UserObjectImp.cpp:
+ (UserObjectImp::getOwnPropertySlot): Ditto.
+ (UserObjectImp::toPrimitive): Take PreferredPrimitiveType argument
+ instead of JSType argument.
+ * UserObjectImp.h: Ditto.
+
2008-08-17 Geoffrey Garen <ggaren@apple.com>
Reviewed by Cameron Zwarich.
CFTypeRef result = 0;
- switch (inValue->type())
- {
- case BooleanType:
+ if (inValue->isBoolean())
{
result = inValue->toBoolean(exec) ? kCFBooleanTrue : kCFBooleanFalse;
RetainCFType(result);
+ return result;
}
- break;
- case StringType:
+ if (inValue->isString())
{
UString uString = inValue->toString(exec);
result = UStringToCFString(uString);
+ return result;
}
- break;
- case NumberType:
+ if (inValue->isNumber())
{
double number1 = inValue->toNumber(exec);
double number2 = (double)inValue->toInteger(exec);
{
result = CFNumberCreate(0, kCFNumberDoubleType, &number1);
}
+ return result;
}
- break;
- case ObjectType:
+ if (inValue->isObject())
{
if (inValue->isObject(&UserObjectImp::info)) {
UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(inValue);
}
}
}
+ return result;
}
- break;
- case NullType:
- case UndefinedType:
- case UnspecifiedType:
+ if (inValue->isUndefinedOrNull())
+ {
result = RetainCFType(GetCFNull());
- break;
-
- default:
- fprintf(stderr, "KJSValueToCFType: wrong value type %d\n", inValue->type());
- break;
- }
+ return result;
+ }
- return result;
+ ASSERT_NOT_REACHED();
+ return 0;
}
CFTypeRef KJSValueToCFType(JSValue *inValue, ExecState *exec)
return true;
} else {
JSValue *kjsValue = toPrimitive(exec);
- if (kjsValue->type() != NullType && kjsValue->type() != UndefinedType) {
+ if (!kjsValue->isUndefinedOrNull()) {
JSObject *kjsObject = kjsValue->toObject(exec);
if (kjsObject->getPropertySlot(exec, propertyName, slot))
return true;
return fJSUserObject;
}
-JSValue *UserObjectImp::toPrimitive(ExecState *exec, JSType preferredType) const
+JSValue *UserObjectImp::toPrimitive(ExecState *exec, PreferredPrimitiveType) const
{
JSValue *result = jsUndefined();
JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
- JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
+ JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
virtual bool toBoolean(ExecState *exec) const;
virtual double toNumber(ExecState *exec) const;
virtual UString toString(ExecState *exec) const;
+2008-08-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - added a test since I had to rewrite the == and === operators
+
+ * fast/js/equality-expected.txt: Added.
+ * fast/js/equality.html: Added.
+ * fast/js/resources/equality.js: Added.
+
2008-08-18 Dan Bernstein <mitz@apple.com>
Reviewed by Dave Hyatt.
--- /dev/null
+Test for equality of many combinations types.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS 0 == 0 is true
+PASS 0 == 1 is false
+PASS 0 == 0.1 is false
+PASS 0 == -0 is true
+PASS 0 == "0" is true
+PASS 0 == "1" is false
+PASS 0 == "0.1" is false
+PASS 0 == "-0" is true
+PASS 0 == null is false
+PASS 0 == undefined is false
+PASS 0 == false is true
+PASS 0 == true is false
+PASS 0 == new String("0") is true
+PASS 0 == new Object is false
+PASS 1 == 0 is false
+PASS 1 == 1 is true
+PASS 1 == 0.1 is false
+PASS 1 == -0 is false
+PASS 1 == "0" is false
+PASS 1 == "1" is true
+PASS 1 == "0.1" is false
+PASS 1 == "-0" is false
+PASS 1 == null is false
+PASS 1 == undefined is false
+PASS 1 == false is false
+PASS 1 == true is true
+PASS 1 == new String("0") is false
+PASS 1 == new Object is false
+PASS 0.1 == 0 is false
+PASS 0.1 == 1 is false
+PASS 0.1 == 0.1 is true
+PASS 0.1 == -0 is false
+PASS 0.1 == "0" is false
+PASS 0.1 == "1" is false
+PASS 0.1 == "0.1" is true
+PASS 0.1 == "-0" is false
+PASS 0.1 == null is false
+PASS 0.1 == undefined is false
+PASS 0.1 == false is false
+PASS 0.1 == true is false
+PASS 0.1 == new String("0") is false
+PASS 0.1 == new Object is false
+PASS -0 == 0 is true
+PASS -0 == 1 is false
+PASS -0 == 0.1 is false
+PASS -0 == -0 is true
+PASS -0 == "0" is true
+PASS -0 == "1" is false
+PASS -0 == "0.1" is false
+PASS -0 == "-0" is true
+PASS -0 == null is false
+PASS -0 == undefined is false
+PASS -0 == false is true
+PASS -0 == true is false
+PASS -0 == new String("0") is true
+PASS -0 == new Object is false
+PASS "0" == 0 is true
+PASS "0" == 1 is false
+PASS "0" == 0.1 is false
+PASS "0" == -0 is true
+PASS "0" == "0" is true
+PASS "0" == "1" is false
+PASS "0" == "0.1" is false
+PASS "0" == "-0" is false
+PASS "0" == null is false
+PASS "0" == undefined is false
+PASS "0" == false is true
+PASS "0" == true is false
+PASS "0" == new String("0") is true
+PASS "0" == new Object is false
+PASS "1" == 0 is false
+PASS "1" == 1 is true
+PASS "1" == 0.1 is false
+PASS "1" == -0 is false
+PASS "1" == "0" is false
+PASS "1" == "1" is true
+PASS "1" == "0.1" is false
+PASS "1" == "-0" is false
+PASS "1" == null is false
+PASS "1" == undefined is false
+PASS "1" == false is false
+PASS "1" == true is true
+PASS "1" == new String("0") is false
+PASS "1" == new Object is false
+PASS "0.1" == 0 is false
+PASS "0.1" == 1 is false
+PASS "0.1" == 0.1 is true
+PASS "0.1" == -0 is false
+PASS "0.1" == "0" is false
+PASS "0.1" == "1" is false
+PASS "0.1" == "0.1" is true
+PASS "0.1" == "-0" is false
+PASS "0.1" == null is false
+PASS "0.1" == undefined is false
+PASS "0.1" == false is false
+PASS "0.1" == true is false
+PASS "0.1" == new String("0") is false
+PASS "0.1" == new Object is false
+PASS "-0" == 0 is true
+PASS "-0" == 1 is false
+PASS "-0" == 0.1 is false
+PASS "-0" == -0 is true
+PASS "-0" == "0" is false
+PASS "-0" == "1" is false
+PASS "-0" == "0.1" is false
+PASS "-0" == "-0" is true
+PASS "-0" == null is false
+PASS "-0" == undefined is false
+PASS "-0" == false is true
+PASS "-0" == true is false
+PASS "-0" == new String("0") is false
+PASS "-0" == new Object is false
+PASS null == 0 is false
+PASS null == 1 is false
+PASS null == 0.1 is false
+PASS null == -0 is false
+PASS null == "0" is false
+PASS null == "1" is false
+PASS null == "0.1" is false
+PASS null == "-0" is false
+PASS null == null is true
+PASS null == undefined is true
+PASS null == false is false
+PASS null == true is false
+PASS null == new String("0") is false
+PASS null == new Object is false
+PASS undefined == 0 is false
+PASS undefined == 1 is false
+PASS undefined == 0.1 is false
+PASS undefined == -0 is false
+PASS undefined == "0" is false
+PASS undefined == "1" is false
+PASS undefined == "0.1" is false
+PASS undefined == "-0" is false
+PASS undefined == null is true
+PASS undefined == undefined is true
+PASS undefined == false is false
+PASS undefined == true is false
+PASS undefined == new String("0") is false
+PASS undefined == new Object is false
+PASS false == 0 is true
+PASS false == 1 is false
+PASS false == 0.1 is false
+PASS false == -0 is true
+PASS false == "0" is true
+PASS false == "1" is false
+PASS false == "0.1" is false
+PASS false == "-0" is true
+PASS false == null is false
+PASS false == undefined is false
+PASS false == false is true
+PASS false == true is false
+PASS false == new String("0") is true
+PASS false == new Object is false
+PASS true == 0 is false
+PASS true == 1 is true
+PASS true == 0.1 is false
+PASS true == -0 is false
+PASS true == "0" is false
+PASS true == "1" is true
+PASS true == "0.1" is false
+PASS true == "-0" is false
+PASS true == null is false
+PASS true == undefined is false
+PASS true == false is false
+PASS true == true is true
+PASS true == new String("0") is false
+PASS true == new Object is false
+PASS new String("0") == 0 is true
+PASS new String("0") == 1 is false
+PASS new String("0") == 0.1 is false
+PASS new String("0") == -0 is true
+PASS new String("0") == "0" is true
+PASS new String("0") == "1" is false
+PASS new String("0") == "0.1" is false
+PASS new String("0") == "-0" is false
+PASS new String("0") == null is false
+PASS new String("0") == undefined is false
+PASS new String("0") == false is true
+PASS new String("0") == true is false
+PASS new String("0") == new String("0") is false
+PASS new String("0") == new Object is false
+PASS new Object == 0 is false
+PASS new Object == 1 is false
+PASS new Object == 0.1 is false
+PASS new Object == -0 is false
+PASS new Object == "0" is false
+PASS new Object == "1" is false
+PASS new Object == "0.1" is false
+PASS new Object == "-0" is false
+PASS new Object == null is false
+PASS new Object == undefined is false
+PASS new Object == false is false
+PASS new Object == true is false
+PASS new Object == new String("0") is false
+PASS new Object == new Object is false
+PASS 0 === 0 is true
+PASS 0 === 1 is false
+PASS 0 === 0.1 is false
+PASS 0 === -0 is true
+PASS 0 === "0" is false
+PASS 0 === "1" is false
+PASS 0 === "0.1" is false
+PASS 0 === "-0" is false
+PASS 0 === null is false
+PASS 0 === undefined is false
+PASS 0 === false is false
+PASS 0 === true is false
+PASS 0 === new String("0") is false
+PASS 0 === new Object is false
+PASS 1 === 0 is false
+PASS 1 === 1 is true
+PASS 1 === 0.1 is false
+PASS 1 === -0 is false
+PASS 1 === "0" is false
+PASS 1 === "1" is false
+PASS 1 === "0.1" is false
+PASS 1 === "-0" is false
+PASS 1 === null is false
+PASS 1 === undefined is false
+PASS 1 === false is false
+PASS 1 === true is false
+PASS 1 === new String("0") is false
+PASS 1 === new Object is false
+PASS 0.1 === 0 is false
+PASS 0.1 === 1 is false
+PASS 0.1 === 0.1 is true
+PASS 0.1 === -0 is false
+PASS 0.1 === "0" is false
+PASS 0.1 === "1" is false
+PASS 0.1 === "0.1" is false
+PASS 0.1 === "-0" is false
+PASS 0.1 === null is false
+PASS 0.1 === undefined is false
+PASS 0.1 === false is false
+PASS 0.1 === true is false
+PASS 0.1 === new String("0") is false
+PASS 0.1 === new Object is false
+PASS -0 === 0 is true
+PASS -0 === 1 is false
+PASS -0 === 0.1 is false
+PASS -0 === -0 is true
+PASS -0 === "0" is false
+PASS -0 === "1" is false
+PASS -0 === "0.1" is false
+PASS -0 === "-0" is false
+PASS -0 === null is false
+PASS -0 === undefined is false
+PASS -0 === false is false
+PASS -0 === true is false
+PASS -0 === new String("0") is false
+PASS -0 === new Object is false
+PASS "0" === 0 is false
+PASS "0" === 1 is false
+PASS "0" === 0.1 is false
+PASS "0" === -0 is false
+PASS "0" === "0" is true
+PASS "0" === "1" is false
+PASS "0" === "0.1" is false
+PASS "0" === "-0" is false
+PASS "0" === null is false
+PASS "0" === undefined is false
+PASS "0" === false is false
+PASS "0" === true is false
+PASS "0" === new String("0") is false
+PASS "0" === new Object is false
+PASS "1" === 0 is false
+PASS "1" === 1 is false
+PASS "1" === 0.1 is false
+PASS "1" === -0 is false
+PASS "1" === "0" is false
+PASS "1" === "1" is true
+PASS "1" === "0.1" is false
+PASS "1" === "-0" is false
+PASS "1" === null is false
+PASS "1" === undefined is false
+PASS "1" === false is false
+PASS "1" === true is false
+PASS "1" === new String("0") is false
+PASS "1" === new Object is false
+PASS "0.1" === 0 is false
+PASS "0.1" === 1 is false
+PASS "0.1" === 0.1 is false
+PASS "0.1" === -0 is false
+PASS "0.1" === "0" is false
+PASS "0.1" === "1" is false
+PASS "0.1" === "0.1" is true
+PASS "0.1" === "-0" is false
+PASS "0.1" === null is false
+PASS "0.1" === undefined is false
+PASS "0.1" === false is false
+PASS "0.1" === true is false
+PASS "0.1" === new String("0") is false
+PASS "0.1" === new Object is false
+PASS "-0" === 0 is false
+PASS "-0" === 1 is false
+PASS "-0" === 0.1 is false
+PASS "-0" === -0 is false
+PASS "-0" === "0" is false
+PASS "-0" === "1" is false
+PASS "-0" === "0.1" is false
+PASS "-0" === "-0" is true
+PASS "-0" === null is false
+PASS "-0" === undefined is false
+PASS "-0" === false is false
+PASS "-0" === true is false
+PASS "-0" === new String("0") is false
+PASS "-0" === new Object is false
+PASS null === 0 is false
+PASS null === 1 is false
+PASS null === 0.1 is false
+PASS null === -0 is false
+PASS null === "0" is false
+PASS null === "1" is false
+PASS null === "0.1" is false
+PASS null === "-0" is false
+PASS null === null is true
+PASS null === undefined is false
+PASS null === false is false
+PASS null === true is false
+PASS null === new String("0") is false
+PASS null === new Object is false
+PASS undefined === 0 is false
+PASS undefined === 1 is false
+PASS undefined === 0.1 is false
+PASS undefined === -0 is false
+PASS undefined === "0" is false
+PASS undefined === "1" is false
+PASS undefined === "0.1" is false
+PASS undefined === "-0" is false
+PASS undefined === null is false
+PASS undefined === undefined is true
+PASS undefined === false is false
+PASS undefined === true is false
+PASS undefined === new String("0") is false
+PASS undefined === new Object is false
+PASS false === 0 is false
+PASS false === 1 is false
+PASS false === 0.1 is false
+PASS false === -0 is false
+PASS false === "0" is false
+PASS false === "1" is false
+PASS false === "0.1" is false
+PASS false === "-0" is false
+PASS false === null is false
+PASS false === undefined is false
+PASS false === false is true
+PASS false === true is false
+PASS false === new String("0") is false
+PASS false === new Object is false
+PASS true === 0 is false
+PASS true === 1 is false
+PASS true === 0.1 is false
+PASS true === -0 is false
+PASS true === "0" is false
+PASS true === "1" is false
+PASS true === "0.1" is false
+PASS true === "-0" is false
+PASS true === null is false
+PASS true === undefined is false
+PASS true === false is false
+PASS true === true is true
+PASS true === new String("0") is false
+PASS true === new Object is false
+PASS new String("0") === 0 is false
+PASS new String("0") === 1 is false
+PASS new String("0") === 0.1 is false
+PASS new String("0") === -0 is false
+PASS new String("0") === "0" is false
+PASS new String("0") === "1" is false
+PASS new String("0") === "0.1" is false
+PASS new String("0") === "-0" is false
+PASS new String("0") === null is false
+PASS new String("0") === undefined is false
+PASS new String("0") === false is false
+PASS new String("0") === true is false
+PASS new String("0") === new String("0") is false
+PASS new String("0") === new Object is false
+PASS new Object === 0 is false
+PASS new Object === 1 is false
+PASS new Object === 0.1 is false
+PASS new Object === -0 is false
+PASS new Object === "0" is false
+PASS new Object === "1" is false
+PASS new Object === "0.1" is false
+PASS new Object === "-0" is false
+PASS new Object === null is false
+PASS new Object === undefined is false
+PASS new Object === false is false
+PASS new Object === true is false
+PASS new Object === new String("0") is false
+PASS new Object === new Object is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/equality.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+description(
+'Test for equality of many combinations types.'
+);
+
+var values = [ '0', '1', '0.1', '-0', '"0"', '"1"', '"0.1"', '"-0"', 'null', 'undefined', 'false', 'true', 'new String("0")', 'new Object' ];
+
+var exceptions = [
+ '"-0" == false',
+ '"0" == false',
+ '"0" == new String("0")',
+ '"1" == true',
+ '-0 == "-0"',
+ '-0 == "0"',
+ '-0 == false',
+ '-0 == new String("0")',
+ '0 == "-0"',
+ '0 == "0"',
+ '0 == -0',
+ '0 == false',
+ '0 == new String("0")',
+ '0 === -0',
+ '0.1 == "0.1"',
+ '1 == "1"',
+ '1 == true',
+ 'new Object == new Object',
+ 'new Object === new Object',
+ 'new String("0") == false',
+ 'new String("0") == new String("0")',
+ 'new String("0") === new String("0")',
+ 'null == undefined',
+];
+
+var exceptionMap = new Object;
+
+var i, j;
+
+for (i = 0; i < exceptions.length; ++i)
+ exceptionMap[exceptions[i]] = 1;
+
+for (i = 0; i < values.length; ++i) {
+ for (j = 0; j < values.length; ++j) {
+ var expression = values[i] + " == " + values[j];
+ var reversed = values[j] + " == " + values[i];
+ shouldBe(expression, ((i == j) ^ (exceptionMap[expression] || exceptionMap[reversed])) ? "true" : "false");
+ }
+}
+
+for (i = 0; i < values.length; ++i) {
+ for (j = 0; j < values.length; ++j) {
+ var expression = values[i] + " === " + values[j];
+ var reversed = values[j] + " === " + values[i];
+ shouldBe(expression, ((i == j) ^ (exceptionMap[expression] || exceptionMap[reversed])) ? "true" : "false");
+ }
+}
+
+var successfullyParsed = true;
+2008-08-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - eliminate JSValue::type()
+
+ * bridge/c/c_instance.cpp:
+ (KJS::Bindings::CInstance::defaultValue): Take PreferredPrimitiveType
+ argument instead of JSType argument. Removed unneeded code to handle
+ boolean, since that's never passed.
+ * bridge/c/c_instance.h: Ditto.
+
+ * bridge/c/c_utility.cpp:
+ (KJS::Bindings::convertValueToNPVariant): Use JSValue::is functions
+ instead of JSValue::type(). Removed unneeded code to handle
+ "unspecified".
+
+ * bridge/jni/jni_instance.cpp:
+ (JavaInstance::defaultValue): Take PreferredPrimitiveType argument
+ instead of JSType argument. Removed unneeded code to handle boolean.
+ * bridge/jni/jni_instance.h: Ditto.
+
+ * bridge/jni/jni_jsobject.mm:
+ (JavaJSObject::convertValueToJObject): Use JSValue::is functions
+ instead of JSValue::type().
+
+ * bridge/objc/objc_instance.h: Take PreferredPrimitiveType argument
+ instead of JSType argument. Removed unused argument.
+ * bridge/objc/objc_instance.mm:
+ (ObjcInstance::getValueOfUndefinedField): Removed unused argument.
+ (ObjcInstance::defaultValue): Take PreferredPrimitiveType argument
+ instead of JSType argument. Removed unneeded code to handle boolean
+ and another dead code path for unknown types.
+
+ * bridge/objc/objc_runtime.h: Take PreferredPrimitiveType argument
+ instead of JSType argument. Removed override of type() that caused
+ the fallback object to return "UndefinedType" when there is no
+ invokeUndefinedMethodFromWebScript:withArguments: method defined.
+ That didn't accomplish much, since most checks for undefined don't
+ ever call type().
+ * bridge/objc/objc_runtime.mm:
+ (ObjcFallbackObjectImp::defaultValue): Ditto.
+
+ * bridge/qt/qt_instance.cpp:
+ (KJS::Bindings::QtInstance::defaultValue): Take PreferredPrimitiveType
+ argument instead of JSType argument. Removed unneeded code to handle
+ boolean.
+ * bridge/qt/qt_instance.h: Ditto.
+
+ * bridge/runtime.h:
+ (KJS::Bindings::Instance::getValueOfUndefinedField): Removed
+ unsed argument.
+ * bridge/runtime_object.cpp:
+ (RuntimeObjectImp::defaultValue): Take PreferredPrimitiveType
+ argument instead of JSType argument.
+ * bridge/runtime_object.h: Ditto.
+
2008-08-18 Maxime Britto <britto@apple.com>
Reviewed by Adele.
}
-JSValue* CInstance::defaultValue(ExecState* exec, JSType hint) const
+JSValue* CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
- if (hint == StringType)
+ if (hint == JSValue::PreferString)
return stringValue(exec);
- if (hint == NumberType)
+ if (hint == JSValue::PreferNumber)
return numberValue(exec);
- if (hint == BooleanType)
- return booleanValue();
return valueOf(exec);
}
virtual Class *getClass() const;
virtual JSValue* valueOf(ExecState*) const;
- virtual JSValue* defaultValue(ExecState*, JSType hint) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const ArgList &args);
virtual bool supportsInvokeDefaultMethod() const;
// Variant value must be released with NPReleaseVariantValue()
void convertValueToNPVariant(ExecState* exec, JSValue* value, NPVariant* result)
-{
- JSType type = value->type();
-
+{
VOID_TO_NPVARIANT(*result);
- if (type == StringType) {
+ if (value->isString()) {
UString ustring = value->toString(exec);
CString cstring = ustring.UTF8String();
NPString string = { (const NPUTF8*)cstring.c_str(), static_cast<uint32_t>(cstring.size()) };
NPN_InitializeVariantWithStringCopy(result, &string);
- } else if (type == NumberType) {
+ } else if (value->isNumber()) {
DOUBLE_TO_NPVARIANT(value->toNumber(exec), *result);
- } else if (type == BooleanType) {
+ } else if (value->isBoolean()) {
BOOLEAN_TO_NPVARIANT(value->toBoolean(exec), *result);
- } else if (type == UnspecifiedType) {
- VOID_TO_NPVARIANT(*result);
- } else if (type == NullType) {
+ } else if (value->isNull()) {
NULL_TO_NPVARIANT(*result);
- } else if (type == ObjectType) {
+ } else if (value->isObject()) {
JSObject* object = static_cast<JSObject*>(value);
if (object->classInfo() == &RuntimeObjectImp::s_info) {
RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(value);
/*
- * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
return resultValue;
}
-JSValue* JavaInstance::defaultValue(ExecState* exec, JSType hint) const
+JSValue* JavaInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
- if (hint == StringType)
+ if (hint == JSValue::PreferString)
return stringValue(exec);
- if (hint == NumberType)
+ if (hint == JSValue::PreferNumber)
return numberValue(exec);
- if (hint == BooleanType)
+ JavaClass *aClass = static_cast<JavaClass*>(getClass());
+ if (aClass->isStringClass())
+ return stringValue(exec);
+ if (aClass->isNumberClass())
+ return numberValue(exec);
+ if (aClass->isBooleanClass())
return booleanValue();
- if (hint == UnspecifiedType) {
- JavaClass *aClass = static_cast<JavaClass*>(getClass());
- if (aClass->isStringClass())
- return stringValue(exec);
- if (aClass->isNumberClass())
- return numberValue(exec);
- if (aClass->isBooleanClass())
- return booleanValue();
- }
-
return valueOf(exec);
}
virtual Class *getClass() const;
virtual JSValue* valueOf(ExecState*) const;
- virtual JSValue* defaultValue(ExecState*, JSType hint) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
virtual JSValue* invokeMethod(ExecState* exec, const MethodList& method, const ArgList& args);
// Java instance -> Java instance
// Everything else -> JavaJSObject
- JSType type = value->type();
- if (type == NumberType) {
+ if (value->isNumber()) {
jclass JSObjectClass = env->FindClass ("java/lang/Double");
jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(D)V");
if (constructorID != NULL) {
result = env->NewObject (JSObjectClass, constructorID, (jdouble)value->toNumber(exec));
}
- }
- else if (type == StringType) {
+ } else if (value->isString()) {
UString stringValue = value->toString(exec);
JNIEnv *env = getJNIEnv();
result = env->NewString ((const jchar *)stringValue.data(), stringValue.size());
- }
- else if (type == BooleanType) {
+ } else if (value->isBoolean()) {
jclass JSObjectClass = env->FindClass ("java/lang/Boolean");
jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(Z)V");
if (constructorID != NULL) {
// Create a JavaJSObject.
jlong nativeHandle;
- if (type == ObjectType){
+ if (value->isObject()) {
JSObject *imp = static_cast<JSObject*>(value);
// We either have a wrapper around a Java instance or a JavaScript
virtual Class *getClass() const;
virtual JSValue* valueOf(ExecState*) const;
- virtual JSValue* defaultValue(ExecState*, JSType hint) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
virtual JSValue *invokeMethod(ExecState *exec, const MethodList &method, const ArgList &args);
virtual bool supportsInvokeDefaultMethod() const;
virtual bool supportsSetValueOfUndefinedField();
virtual void setValueOfUndefinedField(ExecState *exec, const Identifier &property, JSValue *aValue);
- virtual JSValue *getValueOfUndefinedField(ExecState *exec, const Identifier &property, JSType hint) const;
+ virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier& property) const;
ObjectStructPtr getObject() const { return _instance.get(); }
}
}
-JSValue* ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property, JSType) const
+JSValue* ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property) const
{
JSValue* result = jsUndefined();
return result;
}
-JSValue* ObjcInstance::defaultValue(ExecState* exec, JSType hint) const
+JSValue* ObjcInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
- switch (hint) {
- case StringType:
+ if (hint == JSValue::PreferString)
return stringValue(exec);
- case NumberType:
+ if (hint == JSValue::PreferNumber)
return numberValue(exec);
- case BooleanType:
- return booleanValue();
- case UnspecifiedType:
- if ([_instance.get() isKindOfClass:[NSString class]])
- return stringValue(exec);
- if ([_instance.get() isKindOfClass:[NSNumber class]])
- return numberValue(exec);
- default:
- return valueOf(exec);
- }
+ if ([_instance.get() isKindOfClass:[NSString class]])
+ return stringValue(exec);
+ if ([_instance.get() isKindOfClass:[NSNumber class]])
+ return numberValue(exec);
+ return valueOf(exec);
}
JSValue* ObjcInstance::stringValue(ExecState* exec) const
virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
virtual CallType getCallData(CallData&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
- virtual JSValue* defaultValue(ExecState*, JSType hint) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
- virtual JSType type() const;
virtual bool toBoolean(ExecState*) const;
virtual const ClassInfo* classInfo() const { return &info; }
{
}
-JSType ObjcFallbackObjectImp::type() const
-{
- id targetObject = _instance->getObject();
-
- if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
- return ObjectType;
-
- return UndefinedType;
-}
-
static JSValue* callObjCFallbackObject(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)
{
if (!thisValue->isObject(&RuntimeObjectImp::s_info))
return false;
}
-JSValue* ObjcFallbackObjectImp::defaultValue(ExecState* exec, JSType hint) const
+JSValue* ObjcFallbackObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType) const
{
- return _instance->getValueOfUndefinedField(exec, _item, hint);
+ return _instance->getValueOfUndefinedField(exec, _item);
}
bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
return throwError(exec, TypeError, "not a function");
}
-JSValue* QtInstance::defaultValue(ExecState* exec, JSType hint) const
+JSValue* QtInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
- if (hint == StringType)
+ if (hint == PreferString)
return stringValue(exec);
- if (hint == NumberType)
+ if (hint == PreferNumber)
return numberValue(exec);
- if (hint == BooleanType)
- return booleanValue();
return valueOf(exec);
}
virtual void end();
virtual JSValue* valueOf(ExecState* exec) const;
- virtual JSValue* defaultValue(ExecState* exec, JSType hint) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
virtual CallType getCallData(CallData&);
virtual Class *getClass() const = 0;
virtual JSValue* getValueOfField(ExecState*, const Field*) const;
- virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier&, JSType) const { return jsUndefined(); }
+ virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier&) const { return jsUndefined(); }
virtual void setValueOfField(ExecState*, const Field*, JSValue*) const;
virtual bool supportsSetValueOfUndefinedField() { return false; }
virtual void setValueOfUndefinedField(ExecState*, const Identifier&, JSValue*) {}
virtual void getPropertyNames(ExecState*, PropertyNameArray&) { }
- virtual JSValue* defaultValue(ExecState*, JSType hint) const = 0;
+ typedef JSValue::PreferredPrimitiveType PreferredPrimitiveType;
+ virtual JSValue* defaultValue(ExecState*, JSValue::PreferredPrimitiveType) const = 0;
virtual JSValue* valueOf(ExecState* exec) const { return jsString(exec, getClass()->name()); }
return false;
}
-JSValue* RuntimeObjectImp::defaultValue(ExecState* exec, JSType hint) const
+JSValue* RuntimeObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
{
if (!instance)
return throwInvalidAccessError(exec);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
virtual bool deleteProperty(ExecState* , const Identifier& propertyName);
- virtual JSValue* defaultValue(ExecState*, JSType hint) const;
- virtual KJS::CallType getCallData(KJS::CallData&);
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+ virtual CallType getCallData(CallData&);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
virtual void invalidate();
+2008-08-12 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoff.
+
+ - eliminate JSValue::type()
+
+ * WebView/WebView.mm:
+ (aeDescFromJSValue): Rewrite to use the JSValue::is functions instead
+ of a switch on JSValue::type().
+
2008-08-17 Geoffrey Garen <ggaren@apple.com>
Reviewed by Cameron Zwarich.
static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
{
NSAppleEventDescriptor* aeDesc = 0;
- switch (jsValue->type()) {
- case BooleanType:
- aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
- break;
- case StringType:
- aeDesc = [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
- break;
- case NumberType: {
- double value = jsValue->getNumber();
- int intValue = (int)value;
- if (value == intValue)
- aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
- else
- aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
- break;
- }
- case ObjectType: {
- JSObject* object = jsValue->getObject();
- if (object->inherits(&DateInstance::info)) {
- DateInstance* date = static_cast<DateInstance*>(object);
- double ms = 0;
- int tzOffset = 0;
- if (date->getTime(ms, tzOffset)) {
- CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
- LongDateTime ldt;
- if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
- aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
- }
- }
- else if (object->inherits(&JSArray::info)) {
- static HashSet<JSObject*> visitedElems;
- if (!visitedElems.contains(object)) {
- visitedElems.add(object);
-
- JSArray* array = static_cast<JSArray*>(object);
- aeDesc = [NSAppleEventDescriptor listDescriptor];
- unsigned numItems = array->length();
- for (unsigned i = 0; i < numItems; ++i)
- [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
-
- visitedElems.remove(object);
- }
+ if (jsValue->isBoolean())
+ return [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
+ if (jsValue->isString())
+ return [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
+ if (jsValue->isNumber()) {
+ double value = jsValue->getNumber();
+ int intValue = value;
+ if (value == intValue)
+ return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
+ return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
+ }
+ if (jsValue->isObject()) {
+ JSObject* object = jsValue->getObject();
+ if (object->inherits(&DateInstance::info)) {
+ DateInstance* date = static_cast<DateInstance*>(object);
+ double ms = 0;
+ int tzOffset = 0;
+ if (date->getTime(ms, tzOffset)) {
+ CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
+ LongDateTime ldt;
+ if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
+ return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
}
- if (!aeDesc) {
- JSValue* primitive = object->toPrimitive(exec);
- if (exec->hadException()) {
- exec->clearException();
- return [NSAppleEventDescriptor nullDescriptor];
- }
- return aeDescFromJSValue(exec, primitive);
+ }
+ else if (object->inherits(&JSArray::info)) {
+ static HashSet<JSObject*> visitedElems;
+ if (!visitedElems.contains(object)) {
+ visitedElems.add(object);
+
+ JSArray* array = static_cast<JSArray*>(object);
+ aeDesc = [NSAppleEventDescriptor listDescriptor];
+ unsigned numItems = array->length();
+ for (unsigned i = 0; i < numItems; ++i)
+ [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->get(exec, i)) atIndex:0];
+
+ visitedElems.remove(object);
+ return aeDesc;
}
- break;
}
- case UndefinedType:
- aeDesc = [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
- break;
- default:
- LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
- // no break;
- case UnspecifiedType:
- case NullType:
- case GetterSetterType:
- aeDesc = [NSAppleEventDescriptor nullDescriptor];
- break;
+ JSValue* primitive = object->toPrimitive(exec);
+ if (exec->hadException()) {
+ exec->clearException();
+ return [NSAppleEventDescriptor nullDescriptor];
+ }
+ return aeDescFromJSValue(exec, primitive);
}
-
- return aeDesc;
+ if (jsValue->isUndefined())
+ return [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
+ ASSERT(jsValue->isNull());
+ return [NSAppleEventDescriptor nullDescriptor];
}
- (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script