--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/JavaScriptGlue/JSUtils.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSUtils.h"
+#include "JSBase.h"
+#include "JSObject.h"
+#include "JSRun.h"
+#include "UserObjectImp.h"
+#include "JSValueWrapper.h"
+#include "JSObject.h"
+#include <JavaScriptCore/PropertyNameArray.h>
+
+struct ObjectImpList {
+ JSObject* imp;
+ ObjectImpList* next;
+ CFTypeRef data;
+};
+
+static CFTypeRef KJSValueToCFTypeInternal(JSValue *inValue, ExecState *exec, ObjectImpList* inImps);
+
+
+//--------------------------------------------------------------------------
+// CFStringToUString
+//--------------------------------------------------------------------------
+
+UString CFStringToUString(CFStringRef inCFString)
+{
+ UString result;
+ if (inCFString) {
+ CFIndex len = CFStringGetLength(inCFString);
+ UniChar* buffer = (UniChar*)malloc(sizeof(UniChar) * len);
+ if (buffer)
+ {
+ CFStringGetCharacters(inCFString, CFRangeMake(0, len), buffer);
+ result = UString((const UChar *)buffer, len);
+ free(buffer);
+ }
+ }
+ return result;
+}
+
+
+//--------------------------------------------------------------------------
+// UStringToCFString
+//--------------------------------------------------------------------------
+// Caller is responsible for releasing the returned CFStringRef
+CFStringRef UStringToCFString(const UString& inUString)
+{
+ return CFStringCreateWithCharacters(0, (const UniChar*)inUString.data(), inUString.size());
+}
+
+
+//--------------------------------------------------------------------------
+// CFStringToIdentifier
+//--------------------------------------------------------------------------
+
+Identifier CFStringToIdentifier(CFStringRef inCFString)
+{
+ return Identifier(CFStringToUString(inCFString));
+}
+
+
+//--------------------------------------------------------------------------
+// IdentifierToCFString
+//--------------------------------------------------------------------------
+// Caller is responsible for releasing the returned CFStringRef
+CFStringRef IdentifierToCFString(const Identifier& inIdentifier)
+{
+ return UStringToCFString(inIdentifier.ustring());
+}
+
+
+//--------------------------------------------------------------------------
+// KJSValueToJSObject
+//--------------------------------------------------------------------------
+JSUserObject* KJSValueToJSObject(JSValue *inValue, ExecState *exec)
+{
+ JSUserObject* result = 0;
+
+ if (inValue->isObject(&UserObjectImp::info)) {
+ UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(inValue);
+ result = userObjectImp->GetJSUserObject();
+ if (result)
+ result->Retain();
+ } else {
+ JSValueWrapper* wrapperValue = new JSValueWrapper(inValue);
+ if (wrapperValue) {
+ JSObjectCallBacks callBacks;
+ JSValueWrapper::GetJSObectCallBacks(callBacks);
+ result = (JSUserObject*)JSObjectCreate(wrapperValue, &callBacks);
+ if (!result) {
+ delete wrapperValue;
+ }
+ }
+ }
+ return result;
+}
+
+//--------------------------------------------------------------------------
+// JSObjectKJSValue
+//--------------------------------------------------------------------------
+JSValue *JSObjectKJSValue(JSUserObject* ptr)
+{
+ JSLock lock;
+
+ JSValue *result = jsUndefined();
+ if (ptr)
+ {
+ bool handled = false;
+
+ switch (ptr->DataType())
+ {
+ case kJSUserObjectDataTypeJSValueWrapper:
+ {
+ JSValueWrapper* wrapper = (JSValueWrapper*)ptr->GetData();
+ if (wrapper)
+ {
+ result = wrapper->GetValue();
+ handled = true;
+ }
+ break;
+ }
+
+ case kJSUserObjectDataTypeCFType:
+ {
+ CFTypeRef cfType = (CFTypeRef*)ptr->GetData();
+ if (cfType)
+ {
+ CFTypeID typeID = CFGetTypeID(cfType);
+ if (typeID == CFStringGetTypeID())
+ {
+ result = jsString(CFStringToUString((CFStringRef)cfType));
+ handled = true;
+ }
+ else if (typeID == CFNumberGetTypeID())
+ {
+ double num;
+ CFNumberGetValue((CFNumberRef)cfType, kCFNumberDoubleType, &num);
+ result = jsNumber(num);
+ handled = true;
+ }
+ else if (typeID == CFBooleanGetTypeID())
+ {
+ result = jsBoolean(CFBooleanGetValue((CFBooleanRef)cfType));
+ handled = true;
+ }
+ else if (typeID == CFNullGetTypeID())
+ {
+ result = jsNull();
+ handled = true;
+ }
+ }
+ break;
+ }
+ }
+ if (!handled)
+ {
+ result = new UserObjectImp(ptr);
+ }
+ }
+ return result;
+}
+
+
+
+
+//--------------------------------------------------------------------------
+// KJSValueToCFTypeInternal
+//--------------------------------------------------------------------------
+// Caller is responsible for releasing the returned CFTypeRef
+CFTypeRef KJSValueToCFTypeInternal(JSValue *inValue, ExecState *exec, ObjectImpList* inImps)
+{
+ if (!inValue)
+ return 0;
+
+ CFTypeRef result = 0;
+
+ JSLock lock;
+
+ switch (inValue->type())
+ {
+ case BooleanType:
+ {
+ result = inValue->toBoolean(exec) ? kCFBooleanTrue : kCFBooleanFalse;
+ RetainCFType(result);
+ }
+ break;
+
+ case StringType:
+ {
+ UString uString = inValue->toString(exec);
+ result = UStringToCFString(uString);
+ }
+ break;
+
+ case NumberType:
+ {
+ 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);
+ }
+ }
+ break;
+
+ case ObjectType:
+ {
+ if (inValue->isObject(&UserObjectImp::info)) {
+ UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(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;
+ JSInterpreter* intrepreter = (JSInterpreter*)exec->dynamicInterpreter();
+ if (intrepreter && (intrepreter->Flags() & kJSFlagConvertAssociativeArray)) {
+ PropertyNameArray propNames;
+ object->getPropertyNames(exec, propNames);
+ PropertyNameArrayIterator iter = propNames.begin();
+ PropertyNameArrayIterator end = propNames.end();
+ while(iter != end && isArray)
+ {
+ Identifier propName = *iter;
+ UString ustr = propName.ustring();
+ const UniChar* uniChars = (const UniChar*)ustr.data();
+ int size = ustr.size();
+ 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, "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;
+ object->getPropertyNames(exec, propNames);
+ {
+ result = CFDictionaryCreateMutable(0,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (result)
+ {
+ PropertyNameArrayIterator iter = propNames.begin();
+ PropertyNameArrayIterator 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++;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case NullType:
+ case UndefinedType:
+ case UnspecifiedType:
+ result = RetainCFType(GetCFNull());
+ break;
+
+ default:
+ fprintf(stderr, "KJSValueToCFType: wrong value type %d\n", inValue->type());
+ break;
+ }
+
+ return result;
+}
+
+CFTypeRef KJSValueToCFType(JSValue *inValue, ExecState *exec)
+{
+ return KJSValueToCFTypeInternal(inValue, exec, 0);
+}
+
+CFTypeRef GetCFNull(void)
+{
+ static CFArrayRef sCFNull = CFArrayCreate(0, 0, 0, 0);
+ CFTypeRef result = JSGetCFNull();
+ if (!result)
+ {
+ result = sCFNull;
+ }
+ return result;
+}
+