/*
    CFJSObjectSetProperty
*/
void CFJSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue)
{
    if (data && propertyName)
    {
        CFTypeRef cfValue = JSObjectCopyCFValue(jsValue);

        if (cfValue)
        {
            if (CFGetTypeID(data) == CFDictionaryGetTypeID())
            {
                CFDictionarySetValue((CFMutableDictionaryRef)data, propertyName, cfValue);
            }
            else if (CFGetTypeID(data) == CFArrayGetTypeID())
            {
                SInt32 index = CFStringGetIntValue(propertyName);
                CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
                if (index >= 0)
                {
                    for (; arrayCount < index; arrayCount++)
                    {
                        CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
                    }
                    CFArraySetValueAtIndex((CFMutableArrayRef)data, index, cfValue);
                }
            }
            CFRelease(cfValue);
        }
        else
        {
            if (CFGetTypeID(data) == CFDictionaryGetTypeID())
            {
                CFDictionaryRemoveValue((CFMutableDictionaryRef)data, propertyName);
            }
            else if (CFGetTypeID(data) == CFArrayGetTypeID())
            {
                SInt32 index = CFStringGetIntValue(propertyName);
                CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
                if (index >= 0)
                {
                    for (; arrayCount < index; arrayCount++)
                    {
                        CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
                    }
                    CFArraySetValueAtIndex((CFMutableArrayRef)data, index, GetCFNull());
                }
            }
        }
    }
}
double UserObjectImp::toNumber(ExecState *exec) const
{
    double result = 0;
    JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
    CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
    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;
}
JSValue *UserObjectImp::toPrimitive(ExecState *exec, JSType preferredType) const
{
    JSValue *result = jsUndefined();
    JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
    CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
    if (cfValue) {
        CFTypeID cfType = CFGetTypeID(cfValue);  // toPrimitive
        if (cfValue == GetCFNull()) {
            result = jsNull();
        }
        else if (cfType == CFBooleanGetTypeID()) {
            if (cfValue == kCFBooleanTrue) {
                result = jsBoolean(true);
            } else {
                result = jsBoolean(false);
            }
        } else if (cfType == CFStringGetTypeID()) {
            result = jsString(CFStringToUString((CFStringRef)cfValue));
        } else if (cfType == CFNumberGetTypeID()) {
            double d = 0.0;
            CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
            result = jsNumber(d);
        } else if (cfType == CFURLGetTypeID()) {
            CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
            if (absURL) {
                result = jsString(CFStringToUString(CFURLGetString(absURL)));
                ReleaseCFType(absURL);
            }
        }
        ReleaseCFType(cfValue);
    }
    if (jsObjPtr)
        jsObjPtr->Release();
    return result;
}
CFMutableArrayRef JSCreateCFArrayFromJSArray(CFArrayRef array)
{
    CFIndex count = array ? CFArrayGetCount(array) : 0;
    CFMutableArrayRef cfArray = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
    CFIndex i;

    for (i = 0; cfArray && i <  count; i++)
    {
        JSObjectRef jsValue = (JSObjectRef)CFArrayGetValueAtIndex(array, i);
        CFTypeRef cfvalue = JSObjectCopyCFValue(jsValue);
        if (cfvalue)
        {
            CFArrayAppendValue(cfArray, cfvalue);
            CFRelease(cfvalue);
        }
        else
        {
            CFArrayAppendValue(cfArray, GetCFNull());
        }
    }
    return cfArray;
}
CFMutableArrayRef JSCreateJSArrayFromCFArray(CFArrayRef array)
{
    CFIndex count = array ? CFArrayGetCount(array) : 0;
    CFArrayCallBacks arrayCallbacks;
    CFMutableArrayRef jsArray;
    CFIndex i;

    JSTypeGetCFArrayCallBacks(&arrayCallbacks);
    jsArray = CFArrayCreateMutable(0, 0, &arrayCallbacks);

    for (i = 0; array && i <  count; i++)
    {
        CFTypeRef cfValue = (CFTypeRef)CFArrayGetValueAtIndex(array, i);
        JSObjectRef jsValue = JSObjectCreateWithCFType(cfValue);

        if (!jsValue) jsValue = JSObjectCreateWithCFType(GetCFNull());
        if (jsValue)
        {
            CFArrayAppendValue(jsArray, jsValue);
            JSRelease(jsValue);
        }
    }
    return jsArray;
}
UString UserObjectImp::toString(ExecState *exec) const
{
    UString result;
    JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
    CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
    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, 0) == 0)
            {
                result = "Infinity";
            }
            else if (CFNumberCompare(kCFNumberNegativeInfinity, (CFNumberRef)cfValue, 0) == 0)
            {
                result = "-Infinity";
            }
            else
            {
                CFStringRef cfNumStr;
                double d = 0;
                CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
                if (CFNumberIsFloatType((CFNumberRef)cfValue))
                {
                    cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%f"), d);
                }
                else
                {
                    cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%.0f"), d);
                }
                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;
}
bool UserObjectImp::toBoolean(ExecState *exec) const
{
    bool result = false;
    JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
    CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
    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;
}
Beispiel #8
0
//--------------------------------------------------------------------------
// KJSValueToCFTypeInternal
//--------------------------------------------------------------------------
// Caller is responsible for releasing the returned CFTypeRef
CFTypeRef KJSValueToCFTypeInternal(JSValue inValue, ExecState *exec, ObjectImpList* inImps)
{
    if (!inValue)
        return 0;

    CFTypeRef result = 0;

    JSGlueAPIEntry entry;

        if (inValue.isBoolean())
            {
                result = inValue.toBoolean(exec) ? kCFBooleanTrue : kCFBooleanFalse;
                RetainCFType(result);
                return result;
            }

        if (inValue.isString())
            {
                UString uString = inValue.toString(exec);
                result = UStringToCFString(uString);
                return result;
            }

        if (inValue.isNumber())
            {
                double number1 = inValue.toNumber(exec);
                double number2 = (double)inValue.toInteger(exec);
                if (number1 ==  number2)
                {
                    int intValue = (int)number2;
                    result = CFNumberCreate(0, kCFNumberIntType, &intValue);
                }
                else
                {
                    result = CFNumberCreate(0, kCFNumberDoubleType, &number1);
                }
                return result;
            }

        if (inValue.isObject())
            {
                if (inValue.inherits(&UserObjectImp::info)) {
                    UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(asObject(inValue));
                    JSUserObject* ptr = userObjectImp->GetJSUserObject();
                    if (ptr)
                    {
                        result = ptr->CopyCFValue();
                    }
                }
                else
                {
                    JSObject *object = inValue.toObject(exec);
                    UInt8 isArray = false;

                    // if two objects reference each
                    JSObject* imp = object;
                    ObjectImpList* temp = inImps;
                    while (temp) {
                        if (imp == temp->imp) {
                            return CFRetain(GetCFNull());
                        }
                        temp = temp->next;
                    }

                    ObjectImpList imps;
                    imps.next = inImps;
                    imps.imp = imp;


//[...] HACK since we do not have access to the class info we use class name instead
#if 0
                    if (object->inherits(&ArrayInstanceImp::info))
#else
                    if (object->className() == "Array")
#endif
                    {
                        isArray = true;
                        JSGlueGlobalObject* globalObject = static_cast<JSGlueGlobalObject*>(exec->dynamicGlobalObject());
                        if (globalObject && (globalObject->Flags() & kJSFlagConvertAssociativeArray)) {
                            PropertyNameArray propNames(exec);
                            object->getPropertyNames(exec, propNames);
                            PropertyNameArray::const_iterator iter = propNames.begin();
                            PropertyNameArray::const_iterator end = propNames.end();
                            while(iter != end && isArray)
                            {
                                Identifier propName = *iter;
                                UString ustr = propName.ustring();
                                const UniChar* uniChars = (const UniChar*)ustr.characters();
                                int size = ustr.length();
                                while (size--) {
                                    if (uniChars[size] < '0' || uniChars[size] > '9') {
                                        isArray = false;
                                        break;
                                    }
                                }
                                iter++;
                            }
                        }
                    }

                    if (isArray)
                    {
                        // This is an KJS array
                        unsigned int length = object->get(exec, Identifier(exec, "length")).toUInt32(exec);
                        result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
                        if (result)
                        {
                            for (unsigned i = 0; i < length; i++)
                            {
                                CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, i), exec, &imps);
                                CFArrayAppendValue((CFMutableArrayRef)result, cfValue);
                                ReleaseCFType(cfValue);
                            }
                        }
                    }
                    else
                    {
                        // Not an array, just treat it like a dictionary which contains (property name, property value) pairs
                        PropertyNameArray propNames(exec);
                        object->getPropertyNames(exec, propNames);
                        {
                            result = CFDictionaryCreateMutable(0,
                                                               0,
                                                               &kCFTypeDictionaryKeyCallBacks,
                                                               &kCFTypeDictionaryValueCallBacks);
                            if (result)
                            {
                                PropertyNameArray::const_iterator iter = propNames.begin();
                                PropertyNameArray::const_iterator end = propNames.end();
                                while(iter != end)
                                {
                                    Identifier propName = *iter;
                                    if (object->hasProperty(exec, propName))
                                    {
                                        CFStringRef cfKey = IdentifierToCFString(propName);
                                        CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, propName), exec, &imps);
                                        if (cfKey && cfValue)
                                        {
                                            CFDictionaryAddValue((CFMutableDictionaryRef)result, cfKey, cfValue);
                                        }
                                        ReleaseCFType(cfKey);
                                        ReleaseCFType(cfValue);
                                    }
                                    iter++;
                                }
                            }
                        }
                    }
                }
                return result;
            }

    if (inValue.isUndefinedOrNull())
        {
            result = RetainCFType(GetCFNull());
            return result;
        }

    ASSERT_NOT_REACHED();
    return 0;
}