blob: 224d9a508d335f00d5f2e4cd1b8ee81fd7645974 [file] [log] [blame]
#include "UserObjectImp.h"
const ClassInfo UserObjectImp::info = {"UserObject", 0, 0, 0};
class UserObjectPrototypeImp : public UserObjectImp {
public:
UserObjectPrototypeImp();
static UserObjectPrototypeImp* GlobalUserObjectPrototypeImp();
private:
static UserObjectPrototypeImp* sUserObjectPrototypeImp;
};
UserObjectPrototypeImp* UserObjectPrototypeImp::sUserObjectPrototypeImp = NULL;
UserObjectPrototypeImp::UserObjectPrototypeImp()
: UserObjectImp()
{
}
UserObjectPrototypeImp* UserObjectPrototypeImp::GlobalUserObjectPrototypeImp()
{
if (!sUserObjectPrototypeImp)
{
sUserObjectPrototypeImp = new UserObjectPrototypeImp();
static ProtectedValue protectPrototype = Value(sUserObjectPrototypeImp);
}
return sUserObjectPrototypeImp;
}
UserObjectImp::UserObjectImp(): ObjectImp(), fJSUserObject(NULL)
{
}
UserObjectImp::UserObjectImp(JSUserObject* userObject) :
ObjectImp(Object(UserObjectPrototypeImp::GlobalUserObjectPrototypeImp())),
fJSUserObject((JSUserObject*)userObject->Retain())
{
}
UserObjectImp::~UserObjectImp()
{
if (fJSUserObject)
{
fJSUserObject->Release();
}
}
const ClassInfo * UserObjectImp::classInfo() const
{
return &info;
}
bool UserObjectImp::implementsCall() const
{
return fJSUserObject ? fJSUserObject->ImplementsCall() : false;
}
Value UserObjectImp::call(ExecState *exec, Object &thisObj, const List &args)
{
Value result = Undefined();
JSUserObject* jsThisObj = KJSValueToJSObject(thisObj, exec);
if (jsThisObj)
{
CFIndex argCount = args.size();
CFArrayCallBacks arrayCallBacks;
JSTypeGetCFArrayCallBacks(&arrayCallBacks);
CFMutableArrayRef jsArgs = CFArrayCreateMutable(NULL, 0, &arrayCallBacks);
if (jsArgs)
{
for (CFIndex i = 0; i < argCount; i++)
{
JSUserObject* jsArg = KJSValueToJSObject(args[i], exec);
CFArrayAppendValue(jsArgs, (void*)jsArg);
jsArg->Release();
}
}
#if 0
JSUserObject* jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
#else
int lockCount = Interpreter::lockCount();
int i;
for (i = 0; i < lockCount; i++)
{
Interpreter::unlock();
}
JSUserObject* jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
for (i = 0; i < lockCount; i++)
{
Interpreter::lock();
}
#endif
if (jsResult)
{
result = JSObjectKJSValue(jsResult);
jsResult->Release();
}
ReleaseCFType(jsArgs);
jsThisObj->Release();
}
return result;
}
ReferenceList UserObjectImp::propList(ExecState *exec, bool recursive)
{
ReferenceList propList;
JSUserObject* ptr = GetJSUserObject();
if (ptr)
{
Object theObject = toObject(exec);
CFArrayRef propertyNames = ptr->CopyPropertyNames();
if (propertyNames)
{
CFIndex count = CFArrayGetCount(propertyNames);
CFIndex i;
for (i = 0; i < count; i++)
{
CFStringRef propertyName = (CFStringRef)CFArrayGetValueAtIndex(propertyNames, i);
propList.append(Reference(theObject, CFStringToIdentifier(propertyName)));
}
CFRelease(propertyNames);
}
}
return propList;
}
bool UserObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
{
Value prop = get(exec, propertyName);
if (prop.type() != UndefinedType)
{
return true;
}
return ObjectImp::hasProperty(exec, propertyName);
}
#if JAG_PINK_OR_LATER
Value UserObjectImp::get(ExecState *exec, const Identifier &propertyName) const
{
Value result = Undefined();
CFStringRef cfPropName = IdentifierToCFString(propertyName);
JSUserObject* jsResult = fJSUserObject->CopyProperty(cfPropName);
if (jsResult)
{
result = JSObjectKJSValue(jsResult);
jsResult->Release();
}
else
{
Value kjsValue = toPrimitive(exec);
if (kjsValue.type() != NullType && kjsValue.type() != UndefinedType)
{
Object kjsObject = kjsValue.toObject(exec);
Value kjsObjectProp = kjsObject.get(exec, propertyName);
result = kjsObjectProp;
}
}
ReleaseCFType(cfPropName);
return result;
}
void UserObjectImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
{
CFStringRef cfPropName = IdentifierToCFString(propertyName);
JSUserObject* jsValueObj = KJSValueToJSObject(value, exec);
fJSUserObject->SetProperty(cfPropName, jsValueObj);
if (jsValueObj) jsValueObj->Release();
ReleaseCFType(cfPropName);
}
#else //JAG_PINK_OR_LATER
Value UserObjectImp::get(ExecState* exec, const UString& propertyName) const
{
Value result = Undefined();
CFStringRef cfPropName = UStringToCFString(propertyName);
JSUserObject* jsResult = fJSUserObject->CopyProperty(cfPropName);
if (jsResult)
{
result = JSObjectKJSValue(jsResult);
jsResult->Release();
}
else
{
Value kjsValue = toPrimitive(exec);
if (kjsValue != Null() && kjsValue != Undefined())
{
Object kjsObject = kjsValue.toObject(exec);
Value kjsObjectProp = kjsObject.get(exec, propertyName);
result = kjsObjectProp;
}
}
ReleaseCFType(cfPropName);
return result;
}
void UserObjectImp::put(ExecState* exec, const UString& propertyName, const Value& value, int attr)
{
CFStringRef cfPropName = UStringToCFString(propertyName);
JSUserObject* jsValueObj = KJSValueToJSObject(value, exec);
fJSUserObject->SetProperty(cfPropName, jsValueObj);
if (jsValueObj) jsValueObj->Release();
ReleaseCFType(cfPropName);
}
#endif //JAG_PINK_OR_LATER
JSUserObject* UserObjectImp::GetJSUserObject() const
{
return fJSUserObject;
}
Value UserObjectImp::toPrimitive(ExecState *exec, Type preferredType) const
{
Value result = Undefined();
JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
if (cfValue)
{
CFTypeID cfType = CFGetTypeID(cfValue); // toPrimitive
if (cfValue == GetCFNull())
{
result = Null();
}
else if (cfType == CFBooleanGetTypeID())
{
if (cfValue == kCFBooleanTrue)
{
result = KJS::Boolean(true);
}
else
{
result = KJS::Boolean(false);
}
}
else if (cfType == CFStringGetTypeID())
{
result = KJS::String(CFStringToUString((CFStringRef)cfValue));
}
else if (cfType == CFNumberGetTypeID())
{
double d = 0.0;
CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
result = KJS::Number(d);
}
else if (cfType == CFURLGetTypeID())
{
CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
if (absURL)
{
result = KJS::String(CFStringToUString(CFURLGetString(absURL)));
ReleaseCFType(absURL);
}
}
ReleaseCFType(cfValue);
}
if (jsObjPtr) jsObjPtr->Release();
return result;
}
bool UserObjectImp::toBoolean(ExecState *exec) const
{
bool result = false;
JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
if (cfValue)
{
CFTypeID cfType = CFGetTypeID(cfValue); // toPrimitive
if (cfValue == GetCFNull())
{
//
}
else if (cfType == CFBooleanGetTypeID())
{
if (cfValue == kCFBooleanTrue)
{
result = true;
}
}
else if (cfType == CFStringGetTypeID())
{
if (CFStringGetLength((CFStringRef)cfValue))
{
result = true;
}
}
else if (cfType == CFNumberGetTypeID())
{
if (cfValue != kCFNumberNaN)
{
double d;
if (CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d))
{
if (d != 0)
{
result = true;
}
}
}
}
else if (cfType == CFArrayGetTypeID())
{
if (CFArrayGetCount((CFArrayRef)cfValue))
{
result = true;
}
}
else if (cfType == CFDictionaryGetTypeID())
{
if (CFDictionaryGetCount((CFDictionaryRef)cfValue))
{
result = true;
}
}
else if (cfType == CFSetGetTypeID())
{
if (CFSetGetCount((CFSetRef)cfValue))
{
result = true;
}
}
else if (cfType == CFURLGetTypeID())
{
CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
if (absURL)
{
CFStringRef cfStr = CFURLGetString(absURL);
if (cfStr && CFStringGetLength(cfStr))
{
result = true;
}
ReleaseCFType(absURL);
}
}
}
if (jsObjPtr) jsObjPtr->Release();
ReleaseCFType(cfValue);
return result;
}
double UserObjectImp::toNumber(ExecState *exec) const
{
double result = 0;
JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
if (cfValue)
{
CFTypeID cfType = CFGetTypeID(cfValue);
if (cfValue == GetCFNull())
{
//
}
else if (cfType == CFBooleanGetTypeID())
{
if (cfValue == kCFBooleanTrue)
{
result = 1;
}
}
else if (cfType == CFStringGetTypeID())
{
result = CFStringGetDoubleValue((CFStringRef)cfValue);
}
else if (cfType == CFNumberGetTypeID())
{
CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &result);
}
}
ReleaseCFType(cfValue);
if (jsObjPtr) jsObjPtr->Release();
return result;
}
UString UserObjectImp::toString(ExecState *exec) const
{
UString result;
JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : NULL;
if (cfValue)
{
CFTypeID cfType = CFGetTypeID(cfValue);
if (cfValue == GetCFNull())
{
//
}
else if (cfType == CFBooleanGetTypeID())
{
if (cfValue == kCFBooleanTrue)
{
result = "true";
}
else
{
result = "false";
}
}
else if (cfType == CFStringGetTypeID())
{
result = CFStringToUString((CFStringRef)cfValue);
}
else if (cfType == CFNumberGetTypeID())
{
if (cfValue == kCFNumberNaN)
{
result = "Nan";
}
else if (CFNumberCompare(kCFNumberPositiveInfinity, (CFNumberRef)cfValue, NULL) == 0)
{
result = "Infinity";
}
else if (CFNumberCompare(kCFNumberNegativeInfinity, (CFNumberRef)cfValue, NULL) == 0)
{
result = "-Infinity";
}
else
{
CFStringRef cfNumStr = NULL;
if (CFNumberIsFloatType((CFNumberRef)cfValue))
{
double d = 0;
CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
cfNumStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%f"), (float)d);
}
else
{
int i = 0;
CFNumberGetValue((CFNumberRef)cfValue, kCFNumberIntType, &i);
cfNumStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), (int)i);
}
if (cfNumStr)
{
result = CFStringToUString(cfNumStr);
ReleaseCFType(cfNumStr);
}
}
}
else if (cfType == CFArrayGetTypeID())
{
//
}
else if (cfType == CFDictionaryGetTypeID())
{
//
}
else if (cfType == CFSetGetTypeID())
{
//
}
else if (cfType == CFURLGetTypeID())
{
CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
if (absURL)
{
CFStringRef cfStr = CFURLGetString(absURL);
if (cfStr)
{
result = CFStringToUString(cfStr);
}
ReleaseCFType(absURL);
}
}
}
ReleaseCFType(cfValue);
if (jsObjPtr) jsObjPtr->Release();
return result;
}
void UserObjectImp::mark()
{
ObjectImp::mark(); // call parent to mark self
if (fJSUserObject)
{
fJSUserObject->Mark(); // mark child
}
}