Reviewed by Sam.
authorandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Mar 2008 19:43:29 +0000 (19:43 +0000)
committerandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Mar 2008 19:43:29 +0000 (19:43 +0000)
        Copy JSC bindings directory over to WebCore/bridge.

        * bridge: Copied from ../JavaScriptCore/bindings.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@30714 268f45cc-cd09-0410-ab3c-d52691b4dbfc

62 files changed:
WebCore/ChangeLog
WebCore/bridge/NP_jsobject.cpp [new file with mode: 0644]
WebCore/bridge/NP_jsobject.h [new file with mode: 0644]
WebCore/bridge/c/c_class.cpp [new file with mode: 0644]
WebCore/bridge/c/c_class.h [new file with mode: 0644]
WebCore/bridge/c/c_instance.cpp [new file with mode: 0644]
WebCore/bridge/c/c_instance.h [new file with mode: 0644]
WebCore/bridge/c/c_runtime.cpp [new file with mode: 0644]
WebCore/bridge/c/c_runtime.h [new file with mode: 0644]
WebCore/bridge/c/c_utility.cpp [new file with mode: 0644]
WebCore/bridge/c/c_utility.h [new file with mode: 0644]
WebCore/bridge/jni/jni_class.cpp [new file with mode: 0644]
WebCore/bridge/jni/jni_class.h [new file with mode: 0644]
WebCore/bridge/jni/jni_instance.cpp [new file with mode: 0644]
WebCore/bridge/jni/jni_instance.h [new file with mode: 0644]
WebCore/bridge/jni/jni_jsobject.cpp [new file with mode: 0644]
WebCore/bridge/jni/jni_jsobject.h [new file with mode: 0644]
WebCore/bridge/jni/jni_objc.mm [new file with mode: 0644]
WebCore/bridge/jni/jni_runtime.cpp [new file with mode: 0644]
WebCore/bridge/jni/jni_runtime.h [new file with mode: 0644]
WebCore/bridge/jni/jni_utility.cpp [new file with mode: 0644]
WebCore/bridge/jni/jni_utility.h [new file with mode: 0644]
WebCore/bridge/make_testbindings [new file with mode: 0755]
WebCore/bridge/npapi.h [new file with mode: 0644]
WebCore/bridge/npruntime.cpp [new file with mode: 0644]
WebCore/bridge/npruntime.h [new file with mode: 0644]
WebCore/bridge/npruntime_impl.h [new file with mode: 0644]
WebCore/bridge/npruntime_internal.h [new file with mode: 0644]
WebCore/bridge/npruntime_priv.h [new file with mode: 0644]
WebCore/bridge/objc/WebScriptObject.h [new file with mode: 0644]
WebCore/bridge/objc/objc_class.h [new file with mode: 0644]
WebCore/bridge/objc/objc_class.mm [new file with mode: 0644]
WebCore/bridge/objc/objc_header.h [new file with mode: 0644]
WebCore/bridge/objc/objc_instance.h [new file with mode: 0644]
WebCore/bridge/objc/objc_instance.mm [new file with mode: 0644]
WebCore/bridge/objc/objc_runtime.h [new file with mode: 0644]
WebCore/bridge/objc/objc_runtime.mm [new file with mode: 0644]
WebCore/bridge/objc/objc_utility.h [new file with mode: 0644]
WebCore/bridge/objc/objc_utility.mm [new file with mode: 0644]
WebCore/bridge/qt/qt_class.cpp [new file with mode: 0644]
WebCore/bridge/qt/qt_class.h [new file with mode: 0644]
WebCore/bridge/qt/qt_instance.cpp [new file with mode: 0644]
WebCore/bridge/qt/qt_instance.h [new file with mode: 0644]
WebCore/bridge/qt/qt_runtime.cpp [new file with mode: 0644]
WebCore/bridge/qt/qt_runtime.h [new file with mode: 0644]
WebCore/bridge/runtime.cpp [new file with mode: 0644]
WebCore/bridge/runtime.h [new file with mode: 0644]
WebCore/bridge/runtime_array.cpp [new file with mode: 0644]
WebCore/bridge/runtime_array.h [new file with mode: 0644]
WebCore/bridge/runtime_method.cpp [new file with mode: 0644]
WebCore/bridge/runtime_method.h [new file with mode: 0644]
WebCore/bridge/runtime_object.cpp [new file with mode: 0644]
WebCore/bridge/runtime_object.h [new file with mode: 0644]
WebCore/bridge/runtime_root.cpp [new file with mode: 0644]
WebCore/bridge/runtime_root.h [new file with mode: 0644]
WebCore/bridge/test.js [new file with mode: 0644]
WebCore/bridge/testC.js [new file with mode: 0644]
WebCore/bridge/testM.js [new file with mode: 0644]
WebCore/bridge/testbindings.cpp [new file with mode: 0644]
WebCore/bridge/testbindings.mm [new file with mode: 0644]
WebCore/bridge/testbindings.pro [new file with mode: 0644]
WebCore/bridge/testqtbindings.cpp [new file with mode: 0644]

index f3f2fa4..7e789f1 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-03  Anders Carlsson  <andersca@apple.com>
+
+        Reviewed by Sam.
+
+        Copy JSC bindings directory over to WebCore/bridge.
+
+        * bridge: Copied from ../JavaScriptCore/bindings.
+
 2008-03-03  Dan Bernstein  <mitz@apple.com>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/bridge/NP_jsobject.cpp b/WebCore/bridge/NP_jsobject.cpp
new file mode 100644 (file)
index 0000000..059b5df
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2004, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "NP_jsobject.h"
+
+#include "JSGlobalObject.h"
+#include "PropertyNameArray.h"
+#include "c_utility.h"
+#include "interpreter.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "object.h"
+#include "runtime_root.h"
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, List& aList)
+{
+    for (unsigned i = 0; i < argCount; i++)
+        aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
+}
+
+static NPObject* jsAllocate(NPP, NPClass*)
+{
+    return (NPObject*)malloc(sizeof(JavaScriptObject));
+}
+
+static void jsDeallocate(NPObject* npObj)
+{
+    JavaScriptObject* obj = (JavaScriptObject*)npObj;
+
+    if (obj->rootObject && obj->rootObject->isValid())
+        obj->rootObject->gcUnprotect(obj->imp);
+
+    if (obj->rootObject)
+        obj->rootObject->deref();
+
+    free(obj);
+}
+
+static NPClass javascriptClass = { 1, jsAllocate, jsDeallocate, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static NPClass noScriptClass = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+NPClass* NPScriptObjectClass = &javascriptClass;
+static NPClass* NPNoScriptObjectClass = &noScriptClass;
+
+NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject)
+{
+    JavaScriptObject* obj = (JavaScriptObject*)_NPN_CreateObject(npp, NPScriptObjectClass);
+
+    obj->rootObject = rootObject.releaseRef();
+
+    if (obj->rootObject)
+        obj->rootObject->gcProtect(imp);
+    obj->imp = imp;
+
+    return (NPObject*)obj;
+}
+
+NPObject *_NPN_CreateNoScriptObject(void)
+{
+    return _NPN_CreateObject(0, NPNoScriptObjectClass);
+}
+
+bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+        
+        VOID_TO_NPVARIANT(*result);
+        
+        // Lookup the function object.
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+        
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        JSLock lock;
+        
+        // Call the function object.
+        JSObject *funcImp = static_cast<JSObject*>(obj->imp);
+        if (!funcImp->implementsCall())
+            return false;
+        
+        List argList;
+        getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+        rootObject->globalObject()->startTimeoutCheck();
+        JSValue *resultV = funcImp->call (exec, funcImp, argList);
+        rootObject->globalObject()->stopTimeoutCheck();
+
+        // Convert and return the result of the function call.
+        convertValueToNPVariant(exec, resultV, result);
+        return true;        
+    }
+
+    if (o->_class->invokeDefault)
+        return o->_class->invokeDefault(o, args, argCount, result);    
+    VOID_TO_NPVARIANT(*result);
+    return true;
+}
+
+bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        PrivateIdentifier* i = (PrivateIdentifier*)methodName;
+        if (!i->isString)
+            return false;
+
+        // Special case the "eval" method.
+        if (methodName == _NPN_GetStringIdentifier("eval")) {
+            if (argCount != 1)
+                return false;
+            if (args[0].type != NPVariantType_String)
+                return false;
+            return _NPN_Evaluate(npp, o, (NPString *)&args[0].value.stringValue, result);
+        }
+
+        // Lookup the function object.
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        JSLock lock;
+        JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+        if (func->isNull()) {
+            NULL_TO_NPVARIANT(*result);
+            return false;
+        } 
+        if (func->isUndefined()) {
+            VOID_TO_NPVARIANT(*result);
+            return false;
+        }
+        // Call the function object.
+        JSObject *funcImp = static_cast<JSObject*>(func);
+        JSObject *thisObj = const_cast<JSObject*>(obj->imp);
+        List argList;
+        getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+        rootObject->globalObject()->startTimeoutCheck();
+        JSValue *resultV = funcImp->call (exec, thisObj, argList);
+        rootObject->globalObject()->stopTimeoutCheck();
+
+        // Convert and return the result of the function call.
+        convertValueToNPVariant(exec, resultV, result);
+        return true;
+    }
+
+    if (o->_class->invoke)
+        return o->_class->invoke(o, methodName, args, argCount, result);
+    
+    VOID_TO_NPVARIANT(*result);
+    return true;
+}
+
+bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        
+        JSLock lock;
+        NPUTF16* scriptString;
+        unsigned int UTF16Length;
+        convertNPStringToUTF16(s, &scriptString, &UTF16Length); // requires free() of returned memory
+        rootObject->globalObject()->startTimeoutCheck();
+        Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), UString(), 0, UString(reinterpret_cast<const UChar*>(scriptString), UTF16Length));
+        rootObject->globalObject()->stopTimeoutCheck();
+        ComplType type = completion.complType();
+        
+        JSValue* result;
+        if (type == Normal) {
+            result = completion.value();
+            if (!result)
+                result = jsUndefined();
+        } else
+            result = jsUndefined();
+
+        free(scriptString);
+
+        convertValueToNPVariant(exec, result, variant);
+    
+        return true;
+    }
+
+    VOID_TO_NPVARIANT(*variant);
+    return false;
+}
+
+bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+        
+        JSLock lock;
+        JSValue *result;
+        if (i->isString)
+            result = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+        else
+            result = obj->imp->get(exec, i->value.number);
+
+        convertValueToNPVariant(exec, result, variant);
+        return true;
+    }
+
+    if (o->_class->hasProperty && o->_class->getProperty) {
+        if (o->_class->hasProperty(o, propertyName))
+            return o->_class->getProperty(o, propertyName, variant);
+        return false;
+    }
+
+    VOID_TO_NPVARIANT(*variant);
+    return false;
+}
+
+bool _NPN_SetProperty(NPP, NPObject* o, NPIdentifier propertyName, const NPVariant* variant)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        JSLock lock;
+        PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+        if (i->isString)
+            obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant, rootObject));
+        else
+            obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant, rootObject));
+        return true;
+    }
+
+    if (o->_class->setProperty)
+        return o->_class->setProperty(o, propertyName, variant);
+
+    return false;
+}
+
+bool _NPN_RemoveProperty(NPP, NPObject* o, NPIdentifier propertyName)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+        if (i->isString) {
+            if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string)))
+                return false;
+        } else {
+            if (!obj->imp->hasProperty(exec, i->value.number))
+                return false;
+        }
+
+        JSLock lock;
+        if (i->isString)
+            obj->imp->deleteProperty(exec, identifierFromNPIdentifier(i->value.string));
+        else
+            obj->imp->deleteProperty(exec, i->value.number);
+        
+        return true;
+    }
+    return false;
+}
+
+bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+        JSLock lock;
+        if (i->isString)
+            return obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
+        return obj->imp->hasProperty(exec, i->value.number);
+    }
+
+    if (o->_class->hasProperty)
+        return o->_class->hasProperty(o, propertyName);
+
+    return false;
+}
+
+bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+
+        PrivateIdentifier* i = (PrivateIdentifier*)methodName;
+        if (!i->isString)
+            return false;
+
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        JSLock lock;
+        JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+        return !func->isUndefined();
+    }
+    
+    if (o->_class->hasMethod)
+        return o->_class->hasMethod(o, methodName);
+    
+    return false;
+}
+
+void _NPN_SetException(NPObject* o, const NPUTF8* message)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return;
+
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        JSLock lock;
+        throwError(exec, GeneralError, message);
+    }
+}
+
+bool _NPN_Enumerate(NPP, NPObject *o, NPIdentifier **identifier, uint32_t *count)
+{
+    if (o->_class == NPScriptObjectClass) {
+        JavaScriptObject* obj = (JavaScriptObject*)o; 
+        
+        RootObject* rootObject = obj->rootObject;
+        if (!rootObject || !rootObject->isValid())
+            return false;
+        
+        ExecState* exec = rootObject->globalObject()->globalExec();
+        JSLock lock;
+        PropertyNameArray propertyNames;
+
+        obj->imp->getPropertyNames(exec, propertyNames);
+        unsigned size = static_cast<unsigned>(propertyNames.size());
+        // FIXME: This should really call NPN_MemAlloc but that's in WebKit
+        NPIdentifier *identifiers = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier) * size));
+        
+        for (unsigned i = 0; i < size; i++)
+            identifiers[i] = _NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str());
+
+        *identifier = identifiers;
+        *count = size;
+        
+        return true;
+    }
+    
+    if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
+        return o->_class->enumerate(o, identifier, count);
+    
+    return false;
+}
+
+#endif
diff --git a/WebCore/bridge/NP_jsobject.h b/WebCore/bridge/NP_jsobject.h
new file mode 100644 (file)
index 0000000..dd9ccae
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef NP_JSOBJECT_H
+#define NP_JSOBJECT_H
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+#include <wtf/Forward.h>
+
+namespace KJS {
+    class JSObject;
+    namespace Bindings {
+        class RootObject;
+    }
+}
+
+extern NPClass* NPScriptObjectClass;
+
+struct JavaScriptObject
+{
+    NPObject object;
+    KJS::JSObject* imp;
+    KJS::Bindings::RootObject* rootObject;
+};
+
+NPObject* _NPN_CreateScriptObject(NPP npp, KJS::JSObject*, PassRefPtr<KJS::Bindings::RootObject> rootObject);
+NPObject* _NPN_CreateNoScriptObject(void);
+
+#endif
+#endif
diff --git a/WebCore/bridge/c/c_class.cpp b/WebCore/bridge/c/c_class.cpp
new file mode 100644 (file)
index 0000000..f0bb8da
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2003, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_class.h"
+
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "identifier.h"
+#include "npruntime_impl.h"
+
+namespace KJS { namespace Bindings {
+
+CClass::CClass(NPClass* aClass)
+{
+    _isa = aClass;
+}
+
+CClass::~CClass()
+{
+    JSLock lock;
+
+    deleteAllValues(_methods);
+    _methods.clear();
+
+    deleteAllValues(_fields);
+    _fields.clear();
+}
+
+typedef HashMap<NPClass*, CClass*> ClassesByIsAMap;
+static ClassesByIsAMap* classesByIsA = 0;
+
+CClass* CClass::classForIsA(NPClass* isa)
+{
+    if (!classesByIsA)
+        classesByIsA = new ClassesByIsAMap;
+
+    CClass* aClass = classesByIsA->get(isa);
+    if (!aClass) {
+        aClass = new CClass(isa);
+        classesByIsA->set(isa, aClass);
+    }
+
+    return aClass;
+}
+
+const char* CClass::name() const
+{
+    return "";
+}
+
+MethodList CClass::methodsNamed(const Identifier& identifier, Instance* instance) const
+{
+    MethodList methodList;
+
+    Method* method = _methods.get(identifier.ustring().rep());
+    if (method) {
+        methodList.append(method);
+        return methodList;
+    }
+
+    NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii());
+    const CInstance* inst = static_cast<const CInstance*>(instance);
+    NPObject* obj = inst->getObject();
+    if (_isa->hasMethod && _isa->hasMethod(obj, ident)){
+        Method* aMethod = new CMethod(ident); // deleted in the CClass destructor
+        {
+            JSLock lock;
+            _methods.set(identifier.ustring().rep(), aMethod);
+        }
+        methodList.append(aMethod);
+    }
+    
+    return methodList;
+}
+
+Field* CClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+    Field* aField = _fields.get(identifier.ustring().rep());
+    if (aField)
+        return aField;
+    
+    NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii());
+    const CInstance* inst = static_cast<const CInstance*>(instance);
+    NPObject* obj = inst->getObject();
+    if (_isa->hasProperty && _isa->hasProperty(obj, ident)){
+        aField = new CField(ident); // deleted in the CClass destructor
+        {
+            JSLock lock;
+            _fields.set(identifier.ustring().rep(), aField);
+        }
+    }
+    return aField;
+}
+
+} } // namespace KJS::Bindings
+
+#endif
diff --git a/WebCore/bridge/c/c_class.h b/WebCore/bridge/c/c_class.h
new file mode 100644 (file)
index 0000000..8134d5d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#ifndef BINDINGS_C_CLASS_H_
+#define BINDINGS_C_CLASS_H_
+
+#include "npruntime_internal.h"
+#include "runtime.h"
+#include <wtf/HashMap.h>
+
+namespace KJS {
+namespace Bindings {
+
+class CClass : public Class {
+protected:
+    CClass(NPClass*); // Use classForIsA to create a CClass.
+    
+public:
+    static CClass* classForIsA(NPClass*);
+    virtual ~CClass();
+
+    virtual const char* name() const;    
+    virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+    virtual Field* fieldNamed(const Identifier&, Instance*) const;
+
+private:
+    NPClass* _isa;
+    mutable MethodMap _methods;
+    mutable FieldMap _fields;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
+#endif
diff --git a/WebCore/bridge/c/c_instance.cpp b/WebCore/bridge/c/c_instance.cpp
new file mode 100644 (file)
index 0000000..3d04054
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2003, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_instance.h"
+
+#include "c_class.h"
+#include "c_runtime.h"
+#include "c_utility.h"
+#include "list.h"
+#include "npruntime_impl.h"
+#include "PropertyNameArray.h"
+#include "runtime_root.h"
+#include <wtf/Assertions.h>
+#include <wtf/StringExtras.h>
+#include <wtf/Vector.h>
+
+namespace KJS {
+namespace Bindings {
+
+CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
+    : Instance(rootObject)
+{
+    _object = _NPN_RetainObject(o);
+    _class = 0;
+}
+
+CInstance::~CInstance() 
+{
+    _NPN_ReleaseObject(_object);
+}
+
+Class *CInstance::getClass() const
+{
+    if (!_class)
+        _class = CClass::classForIsA(_object->_class);
+    return _class;
+}
+
+void CInstance::begin()
+{
+    // Do nothing.
+}
+
+void CInstance::end()
+{
+    // Do nothing.
+}
+
+bool CInstance::implementsCall() const
+{
+    return (_object->_class->invokeDefault != 0);
+}
+
+JSValue* CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const List& args)
+{
+    // Overloading methods are not allowed by NPObjects.  Should only be one
+    // name match for a particular method.
+    ASSERT(methodList.size() == 1);
+
+    CMethod* method = static_cast<CMethod*>(methodList[0]);
+
+    NPIdentifier ident = _NPN_GetStringIdentifier(method->name());
+    if (!_object->_class->hasMethod(_object, ident))
+        return jsUndefined();
+
+    unsigned count = args.size();
+    Vector<NPVariant, 128> cArgs(count);
+
+    unsigned i;
+    for (i = 0; i < count; i++)
+        convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
+
+    // Invoke the 'C' method.
+    NPVariant resultVariant;
+    VOID_TO_NPVARIANT(resultVariant);
+
+    {
+       JSLock::DropAllLocks dropAllLocks;
+        _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
+    }
+
+    for (i = 0; i < count; i++)
+        _NPN_ReleaseVariantValue(&cArgs[i]);
+
+    JSValue* resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
+    _NPN_ReleaseVariantValue(&resultVariant);
+    return resultValue;
+}
+
+
+JSValue* CInstance::invokeDefaultMethod(ExecState* exec, const List& args)
+{
+    if (!_object->_class->invokeDefault)
+        return jsUndefined();
+
+    unsigned count = args.size();
+    Vector<NPVariant, 128> cArgs(count);
+
+    unsigned i;
+    for (i = 0; i < count; i++)
+        convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
+
+    // Invoke the 'C' method.
+    NPVariant resultVariant;
+    VOID_TO_NPVARIANT(resultVariant);
+    {
+       JSLock::DropAllLocks dropAllLocks;
+        _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
+    }
+    
+    for (i = 0; i < count; i++)
+        _NPN_ReleaseVariantValue(&cArgs[i]);
+
+    JSValue* resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
+    _NPN_ReleaseVariantValue(&resultVariant);
+    return resultValue;
+}
+
+
+JSValue* CInstance::defaultValue(JSType hint) const
+{
+    if (hint == StringType)
+        return stringValue();
+    if (hint == NumberType)
+        return numberValue();
+   if (hint == BooleanType)
+        return booleanValue();
+    return valueOf();
+}
+
+JSValue* CInstance::stringValue() const
+{
+    char buf[1024];
+    snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
+    return jsString(buf);
+}
+
+JSValue* CInstance::numberValue() const
+{
+    // FIXME: Implement something sensible.
+    return jsNumber(0);
+}
+
+JSValue* CInstance::booleanValue() const
+{
+    // FIXME: Implement something sensible.
+    return jsBoolean(false);
+}
+
+JSValue* CInstance::valueOf() const 
+{
+    return stringValue();
+}
+
+void CInstance::getPropertyNames(ExecState*, PropertyNameArray& nameArray) 
+{
+    if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) ||
+        !_object->_class->enumerate)
+        return;
+
+    unsigned count;
+    NPIdentifier* identifiers;
+    
+    {
+        JSLock::DropAllLocks dropAllLocks;
+        if (!_object->_class->enumerate(_object, &identifiers, &count))
+            return;
+    }
+    
+    for (unsigned i = 0; i < count; i++) {
+        PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(identifiers[i]);
+        
+        if (identifier->isString)
+            nameArray.add(identifierFromNPIdentifier(identifier->value.string));
+        else
+            nameArray.add(Identifier::from(identifier->value.number));
+    }
+         
+    // FIXME: This should really call NPN_MemFree but that's in WebKit
+    free(identifiers);
+}
+
+}
+}
+
+#endif
diff --git a/WebCore/bridge/c/c_instance.h b/WebCore/bridge/c/c_instance.h
new file mode 100644 (file)
index 0000000..9991a18
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef BINDINGS_C_INSTANCE_H_
+#define BINDINGS_C_INSTANCE_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "runtime.h"
+#include <wtf/Noncopyable.h>
+
+typedef struct NPObject NPObject;
+
+namespace KJS {
+
+namespace Bindings {
+
+class CClass;
+
+class CInstance : public Instance {
+public:
+    CInstance (NPObject*, PassRefPtr<RootObject>);
+    ~CInstance ();
+    
+    virtual Class *getClass() const;
+    
+    virtual void begin();
+    virtual void end();
+    
+    virtual JSValue *valueOf() const;
+    virtual JSValue *defaultValue (JSType hint) const;
+
+    virtual bool implementsCall() const;
+    
+    virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
+    virtual JSValue *invokeDefaultMethod (ExecState *exec, const List &args);
+    virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+    JSValue *stringValue() const;
+    JSValue *numberValue() const;
+    JSValue *booleanValue() const;
+    
+    NPObject *getObject() const { return _object; }
+
+    virtual BindingLanguage getBindingLanguage() const { return CLanguage; }
+
+private:
+    mutable CClass *_class;
+    NPObject *_object;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
+#endif
diff --git a/WebCore/bridge/c/c_runtime.cpp b/WebCore/bridge/c/c_runtime.cpp
new file mode 100644 (file)
index 0000000..c5636cd
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_runtime.h"
+
+#include "c_instance.h"
+#include "c_utility.h"
+#include "npruntime_impl.h"
+
+namespace KJS {
+namespace Bindings {
+
+// ---------------------- CMethod ----------------------
+
+const char* CMethod::name() const
+{
+    PrivateIdentifier *i = (PrivateIdentifier *)_methodIdentifier;
+    return i->isString ? i->value.string : 0;
+}
+
+// ---------------------- CField ----------------------
+
+const char* CField::name() const
+{
+    PrivateIdentifier *i = (PrivateIdentifier *)_fieldIdentifier;
+    return i->isString ? i->value.string : 0;
+}
+
+JSValue* CField::valueFromInstance(ExecState* exec, const Instance* inst) const
+{
+    const CInstance* instance = static_cast<const CInstance*>(inst);
+    NPObject* obj = instance->getObject();
+    if (obj->_class->getProperty) {
+        NPVariant property;
+        VOID_TO_NPVARIANT(property);
+
+        bool result;
+        {
+           JSLock::DropAllLocks dropAllLocks;
+            result = obj->_class->getProperty(obj, _fieldIdentifier, &property);
+        }
+        if (result) {
+            JSValue* result = convertNPVariantToValue(exec, &property, instance->rootObject());
+            _NPN_ReleaseVariantValue(&property);
+            return result;
+        }
+    }
+    return jsUndefined();
+}
+
+void CField::setValueToInstance(ExecState *exec, const Instance *inst, JSValue *aValue) const
+{
+    const CInstance* instance = static_cast<const CInstance*>(inst);
+    NPObject* obj = instance->getObject();
+    if (obj->_class->setProperty) {
+        NPVariant variant;
+        convertValueToNPVariant(exec, aValue, &variant);
+
+        {
+           JSLock::DropAllLocks dropAllLocks;
+            obj->_class->setProperty(obj, _fieldIdentifier, &variant);
+        }
+
+        _NPN_ReleaseVariantValue(&variant);
+    }
+}
+
+} }
+
+#endif
diff --git a/WebCore/bridge/c/c_runtime.h b/WebCore/bridge/c/c_runtime.h
new file mode 100644 (file)
index 0000000..469008a
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef BINDINGS_C_RUNTIME_H_
+#define BINDINGS_C_RUNTIME_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+#include "runtime.h"
+
+namespace KJS {
+namespace Bindings {
+
+class CField : public Field {
+public:
+    CField(NPIdentifier ident) : _fieldIdentifier(ident) { }
+
+    virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
+    virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
+    virtual const char* name() const;
+
+private:
+    NPIdentifier _fieldIdentifier;
+};
+
+
+class CMethod : public Method
+{
+public:
+    CMethod(NPIdentifier ident) : _methodIdentifier(ident) { }
+
+    virtual const char* name() const;
+    virtual int numParameters() const { return 0; }
+
+private:
+    NPIdentifier _methodIdentifier;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
+#endif
diff --git a/WebCore/bridge/c/c_utility.cpp b/WebCore/bridge/c/c_utility.cpp
new file mode 100644 (file)
index 0000000..7e2a19f
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_utility.h"
+
+#include "NP_jsobject.h"
+#include "c_instance.h"
+#include "JSGlobalObject.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include "Platform.h"
+#include <wtf/Assertions.h>
+#include <wtf/unicode/UTF8.h>
+
+using namespace WTF::Unicode;
+
+namespace KJS { namespace Bindings {
+
+// Requires free() of returned UTF16Chars.
+static void convertUTF8ToUTF16WithLatin1Fallback(const NPUTF8* UTF8Chars, int UTF8Length, NPUTF16** UTF16Chars, unsigned int* UTF16Length)
+{
+    ASSERT(UTF8Chars || UTF8Length == 0);
+    ASSERT(UTF16Chars);
+    
+    if (UTF8Length == -1)
+        UTF8Length = static_cast<int>(strlen(UTF8Chars));
+
+    *UTF16Length = UTF8Length; 
+    *UTF16Chars = static_cast<NPUTF16*>(malloc(sizeof(NPUTF16) * (*UTF16Length)));
+    
+    const char* sourcestart = UTF8Chars;
+    const char* sourceend = sourcestart + UTF8Length;
+
+    ::UChar* targetstart = reinterpret_cast< ::UChar*>(*UTF16Chars);
+    ::UChar* targetend = targetstart + UTF8Length;
+    
+    ConversionResult result = convertUTF8ToUTF16(&sourcestart, sourceend, &targetstart, targetend);
+    
+    *UTF16Length = targetstart - reinterpret_cast< ::UChar*>(*UTF16Chars);
+
+    // Check to see if the conversion was successful
+    // Some plugins return invalid UTF-8 in NPVariantType_String, see <http://bugs.webkit.org/show_bug.cgi?id=5163>
+    // There is no "bad data" for latin1. It is unlikely that the plugin was really sending text in this encoding,
+    // but it should have used UTF-8, and now we are simply avoiding a crash.
+    if (result != conversionOK) {
+        *UTF16Length = UTF8Length;
+        
+        if (!*UTF16Chars)   // If the memory wasn't allocated, allocate it.
+            *UTF16Chars = (NPUTF16*)malloc(sizeof(NPUTF16) * (*UTF16Length));
+        for (unsigned i = 0; i < *UTF16Length; i++)
+            (*UTF16Chars)[i] = UTF8Chars[i] & 0xFF;
+    }
+}
+
+// Variant value must be released with NPReleaseVariantValue()
+void convertValueToNPVariant(ExecState *exec, JSValue *value, NPVariant *result)
+{
+    JSLock lock;
+    
+    JSType type = value->type();
+    
+    VOID_TO_NPVARIANT(*result);
+
+    if (type == StringType) {
+        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) {
+        DOUBLE_TO_NPVARIANT(value->toNumber(exec), *result);
+    } else if (type == BooleanType) {
+        BOOLEAN_TO_NPVARIANT(value->toBoolean(exec), *result);
+    } else if (type == UnspecifiedType) {
+        VOID_TO_NPVARIANT(*result);
+    } else if (type == NullType) {
+        NULL_TO_NPVARIANT(*result);
+    } else if (type == ObjectType) {
+        JSObject* object = static_cast<JSObject*>(value);
+        if (object->classInfo() == &RuntimeObjectImp::info) {
+            RuntimeObjectImp* imp = static_cast<RuntimeObjectImp *>(value);
+            CInstance* instance = static_cast<CInstance*>(imp->getInternalInstance());
+            if (instance) {
+                NPObject* obj = instance->getObject();
+                _NPN_RetainObject(obj);
+                OBJECT_TO_NPVARIANT(obj, *result);
+            }
+        } else {
+            JSGlobalObject* globalObject = exec->dynamicGlobalObject();
+
+            RootObject* rootObject = findRootObject(globalObject);
+            if (rootObject) {
+                NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject);
+                OBJECT_TO_NPVARIANT(npObject, *result);
+            }
+        }
+    }
+}
+
+JSValue *convertNPVariantToValue(ExecState*, const NPVariant* variant, RootObject* rootObject)
+{
+    JSLock lock;
+    
+    NPVariantType type = variant->type;
+
+    if (type == NPVariantType_Bool)
+        return jsBoolean(NPVARIANT_TO_BOOLEAN(*variant));
+    if (type == NPVariantType_Null)
+        return jsNull();
+    if (type == NPVariantType_Void)
+        return jsUndefined();
+    if (type == NPVariantType_Int32)
+        return jsNumber(NPVARIANT_TO_INT32(*variant));
+    if (type == NPVariantType_Double)
+        return jsNumber(NPVARIANT_TO_DOUBLE(*variant));
+    if (type == NPVariantType_String) {
+        NPUTF16 *stringValue;
+        unsigned int UTF16Length;
+        convertNPStringToUTF16(&variant->value.stringValue, &stringValue, &UTF16Length); // requires free() of returned memory
+        UString resultString((const UChar *)stringValue,UTF16Length);
+        free(stringValue);
+        return jsString(resultString);
+    }
+    if (type == NPVariantType_Object) {
+        NPObject *obj = variant->value.objectValue;
+        
+        if (obj->_class == NPScriptObjectClass)
+            // Get JSObject from NP_JavaScriptObject.
+            return ((JavaScriptObject *)obj)->imp;
+
+        // Wrap NPObject in a CInstance.
+        return Instance::createRuntimeObject(Instance::CLanguage, obj, rootObject);
+    }
+    
+    return jsUndefined();
+}
+
+// Requires free() of returned UTF16Chars.
+void convertNPStringToUTF16(const NPString *string, NPUTF16 **UTF16Chars, unsigned int *UTF16Length)
+{
+    convertUTF8ToUTF16WithLatin1Fallback(string->UTF8Characters, string->UTF8Length, UTF16Chars, UTF16Length);
+}
+
+Identifier identifierFromNPIdentifier(const NPUTF8* name)
+{
+    NPUTF16 *methodName;
+    unsigned UTF16Length;
+    convertUTF8ToUTF16WithLatin1Fallback(name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
+    Identifier identifier((const KJS::UChar*)methodName, UTF16Length);
+    free(methodName);
+    return identifier;
+}
+
+} }
+
+#endif
diff --git a/WebCore/bridge/c/c_utility.h b/WebCore/bridge/c/c_utility.h
new file mode 100644 (file)
index 0000000..18bc0d4
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef C_UTILITY_H_
+#define C_UTILITY_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+
+namespace KJS {
+
+class ExecState;
+class Identifier;
+class JSValue;
+
+namespace Bindings {
+
+class RootObject;
+    
+typedef uint16_t NPUTF16;
+
+enum NP_ValueType {
+    NP_NumberValueType,
+    NP_StringValueType,
+    NP_BooleanValueType,
+    NP_NullValueType,
+    NP_UndefinedValueType,
+    NP_ObjectValueType,
+    NP_InvalidValueType
+};
+
+void convertNPStringToUTF16(const NPString*, NPUTF16** UTF16Chars, unsigned int* UTF16Length);
+void convertValueToNPVariant(ExecState*, JSValue*, NPVariant* result);
+JSValue* convertNPVariantToValue(ExecState*, const NPVariant*, RootObject*);
+Identifier identifierFromNPIdentifier(const NPUTF8* name);
+
+struct PrivateIdentifier {
+    union {
+        const NPUTF8* string;
+        int32_t number;
+    } value;
+    bool isString;
+};
+
+} }
+
+#endif
+#endif
diff --git a/WebCore/bridge/jni/jni_class.cpp b/WebCore/bridge/jni/jni_class.cpp
new file mode 100644 (file)
index 0000000..72b1a73
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 <jni_class.h>
+
+#include "identifier.h"
+#include <jni_utility.h>
+#include <jni_runtime.h>
+
+using namespace KJS::Bindings;
+
+JavaClass::JavaClass(jobject anInstance)
+{
+    jobject aClass = callJNIObjectMethod(anInstance, "getClass", "()Ljava/lang/Class;");
+    
+    if (!aClass) {
+        fprintf(stderr, "%s:  unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance);
+        return;
+    }
+    
+    jstring className = (jstring)callJNIObjectMethod(aClass, "getName", "()Ljava/lang/String;");
+    const char *classNameC = getCharactersFromJString(className);
+    _name = strdup(classNameC);
+    releaseCharactersForJString(className, classNameC);
+
+    int i;
+    JNIEnv *env = getJNIEnv();
+    
+    // Get the fields
+    jarray fields = (jarray)callJNIObjectMethod(aClass, "getFields", "()[Ljava/lang/reflect/Field;");
+    int numFields = env->GetArrayLength(fields);    
+    for (i = 0; i < numFields; i++) {
+        jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i);
+        Field *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor
+        {
+            JSLock lock;
+            _fields.set(Identifier(aField->name()).ustring().rep(), aField);
+        }
+        env->DeleteLocalRef(aJField);
+    }
+    
+    // Get the methods
+    jarray methods = (jarray)callJNIObjectMethod(aClass, "getMethods", "()[Ljava/lang/reflect/Method;");
+    int numMethods = env->GetArrayLength(methods);
+    for (i = 0; i < numMethods; i++) {
+        jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i);
+        Method *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor
+        MethodList* methodList;
+        {
+            JSLock lock;
+
+            methodList = _methods.get(Identifier(aMethod->name()).ustring().rep());
+            if (!methodList) {
+                methodList = new MethodList();
+                _methods.set(Identifier(aMethod->name()).ustring().rep(), methodList);
+            }
+        }
+        methodList->append(aMethod);
+        env->DeleteLocalRef(aJMethod);
+    }    
+}
+
+JavaClass::~JavaClass() {
+    free((void *)_name);
+
+    JSLock lock;
+
+    deleteAllValues(_fields);
+    _fields.clear();
+
+    MethodListMap::const_iterator end = _methods.end();
+    for (MethodListMap::const_iterator it = _methods.begin(); it != end; ++it) {
+        const MethodList* methodList = it->second;
+        deleteAllValues(*methodList);
+        delete methodList;
+    }
+    _methods.clear();
+}
+
+MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+    MethodList *methodList = _methods.get(identifier.ustring().rep());
+    
+    if (methodList)
+        return *methodList;
+    return MethodList();
+}
+
+Field *JavaClass::fieldNamed(const Identifier& identifier, Instance*) const
+{
+    return _fields.get(identifier.ustring().rep());
+}
+
+bool JavaClass::isNumberClass() const
+{
+    return ((strcmp(_name, "java.lang.Byte") == 0 ||
+             strcmp(_name, "java.lang.Short") == 0 ||
+             strcmp(_name, "java.lang.Integer") == 0 ||
+             strcmp(_name, "java.lang.Long") == 0 ||
+             strcmp(_name, "java.lang.Float") == 0 ||
+             strcmp(_name, "java.lang.Double") == 0) );
+}
+
+bool JavaClass::isBooleanClass() const
+{
+    return strcmp(_name, "java.lang.Boolean") == 0;
+}
+
+bool JavaClass::isStringClass() const
+{
+    return strcmp(_name, "java.lang.String") == 0;
+}
diff --git a/WebCore/bridge/jni/jni_class.h b/WebCore/bridge/jni/jni_class.h
new file mode 100644 (file)
index 0000000..7c5dbcc
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef JNI_CLASS_H_
+#define JNI_CLASS_H_
+
+#include <jni_runtime.h>
+#include <wtf/HashMap.h>
+
+namespace KJS {
+
+namespace Bindings {
+
+class JavaClass : public Class {
+public:
+    JavaClass (jobject anInstance);
+    ~JavaClass ();
+
+    virtual const char *name() const { return _name; };
+    
+    virtual MethodList methodsNamed(const Identifier&, Instance* instance) const;    
+    virtual Field *fieldNamed(const Identifier&, Instance* instance) const;
+    
+    bool isNumberClass() const;
+    bool isBooleanClass() const;
+    bool isStringClass() const;
+    
+private:
+    JavaClass ();                                 // prevent default construction
+    
+    const char *_name;
+    FieldMap _fields;
+    MethodListMap _methods;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif // JNI_CLASS_H_
diff --git a/WebCore/bridge/jni/jni_instance.cpp b/WebCore/bridge/jni/jni_instance.cpp
new file mode 100644 (file)
index 0000000..d5d89aa
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "jni_class.h"
+#include "jni_instance.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+    fprintf (stderr, "%s:%d -- %s:  ", __FILE__, __LINE__, __FUNCTION__); \
+    fprintf(stderr, formatAndArgs); \
+}
+#endif
+using namespace KJS::Bindings;
+using namespace KJS;
+
+JavaInstance::JavaInstance (jobject instance, PassRefPtr<RootObject> rootObject)
+    : Instance(rootObject)
+{
+    _instance = new JObjectWrapper (instance);
+    _class = 0;
+}
+
+JavaInstance::~JavaInstance () 
+{
+    delete _class; 
+}
+
+#define NUM_LOCAL_REFS 64
+
+void JavaInstance::begin()
+{
+    getJNIEnv()->PushLocalFrame (NUM_LOCAL_REFS);
+}
+
+void JavaInstance::end()
+{
+    getJNIEnv()->PopLocalFrame (NULL);
+}
+
+Class *JavaInstance::getClass() const 
+{
+    if (_class == 0)
+        _class = new JavaClass (_instance->_instance);
+    return _class;
+}
+
+JSValue *JavaInstance::stringValue() const
+{
+    JSLock lock;
+    
+    jstring stringValue = (jstring)callJNIObjectMethod (_instance->_instance, "toString", "()Ljava/lang/String;");
+    JNIEnv *env = getJNIEnv();
+    const jchar *c = getUCharactersFromJStringInEnv(env, stringValue);
+    UString u((const UChar *)c, (int)env->GetStringLength(stringValue));
+    releaseUCharactersForJStringInEnv(env, stringValue, c);
+    return jsString(u);
+}
+
+JSValue *JavaInstance::numberValue() const
+{
+    jdouble doubleValue = callJNIDoubleMethod (_instance->_instance, "doubleValue", "()D");
+    return jsNumber(doubleValue);
+}
+
+JSValue *JavaInstance::booleanValue() const
+{
+    jboolean booleanValue = callJNIBooleanMethod (_instance->_instance, "booleanValue", "()Z");
+    return jsBoolean(booleanValue);
+}
+
+JSValue *JavaInstance::invokeMethod (ExecState *exec, const MethodList &methodList, const List &args)
+{
+    int i, count = args.size();
+    jvalue *jArgs;
+    JSValue *resultValue;
+    Method *method = 0;
+    size_t numMethods = methodList.size();
+    
+    // Try to find a good match for the overloaded method.  The 
+    // fundamental problem is that JavaScript doesn have the
+    // notion of method overloading and Java does.  We could 
+    // get a bit more sophisticated and attempt to does some
+    // type checking as we as checking the number of parameters.
+    Method *aMethod;
+    for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
+        aMethod = methodList[methodIndex];
+        if (aMethod->numParameters() == count) {
+            method = aMethod;
+            break;
+        }
+    }
+    if (method == 0) {
+        JS_LOG ("unable to find an appropiate method\n");
+        return jsUndefined();
+    }
+    
+    const JavaMethod *jMethod = static_cast<const JavaMethod*>(method);
+    JS_LOG ("call %s %s on %p\n", method->name(), jMethod->signature(), _instance->_instance);
+    
+    if (count > 0) {
+        jArgs = (jvalue *)malloc (count * sizeof(jvalue));
+    }
+    else
+        jArgs = 0;
+        
+    for (i = 0; i < count; i++) {
+        JavaParameter* aParameter = jMethod->parameterAt(i);
+        jArgs[i] = convertValueToJValue (exec, args.at(i), aParameter->getJNIType(), aParameter->type());
+        JS_LOG("arg[%d] = %s\n", i, args.at(i)->toString(exec).ascii());
+    }
+        
+    jvalue result;
+
+    // Try to use the JNI abstraction first, otherwise fall back to
+    // nornmal JNI.  The JNI dispatch abstraction allows the Java plugin
+    // to dispatch the call on the appropriate internal VM thread.
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return jsUndefined();
+
+    bool handled = false;
+    if (rootObject->nativeHandle()) {
+        jobject obj = _instance->_instance;
+        JSValue *exceptionDescription = NULL;
+        const char *callingURL = 0;  // FIXME, need to propagate calling URL to Java
+        handled = dispatchJNICall(rootObject->nativeHandle(), obj, jMethod->isStatic(), jMethod->JNIReturnType(), jMethod->methodID(obj), jArgs, result, callingURL, exceptionDescription);
+        if (exceptionDescription) {
+            throwError(exec, GeneralError, exceptionDescription->toString(exec));
+            free (jArgs);
+            return jsUndefined();
+        }
+    }
+    
+    // The following code can be conditionally removed once we have a Tiger update that
+    // contains the new Java plugin.  It is needed for builds prior to Tiger.
+    if (!handled) {    
+        jobject obj = _instance->_instance;
+        switch (jMethod->JNIReturnType()){
+            case void_type: {
+                callJNIVoidMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case object_type: {
+                result.l = callJNIObjectMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case boolean_type: {
+                result.z = callJNIBooleanMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case byte_type: {
+                result.b = callJNIByteMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case char_type: {
+                result.c = callJNICharMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case short_type: {
+                result.s = callJNIShortMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case int_type: {
+                result.i = callJNIIntMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case long_type: {
+                result.j = callJNILongMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case float_type: {
+                result.f = callJNIFloatMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+            
+            case double_type: {
+                result.d = callJNIDoubleMethodIDA (obj, jMethod->methodID(obj), jArgs);
+            }
+            break;
+
+            case invalid_type:
+            default: {
+            }
+            break;
+        }
+    }
+        
+    switch (jMethod->JNIReturnType()){
+        case void_type: {
+            resultValue = jsUndefined();
+        }
+        break;
+        
+        case object_type: {
+            if (result.l != 0) {
+                const char *arrayType = jMethod->returnType();
+                if (arrayType[0] == '[') {
+                    resultValue = JavaArray::convertJObjectToArray(exec, result.l, arrayType, rootObject);
+                }
+                else {
+                    resultValue = Instance::createRuntimeObject(Instance::JavaLanguage, result.l, rootObject);
+                }
+            }
+            else {
+                resultValue = jsUndefined();
+            }
+        }
+        break;
+        
+        case boolean_type: {
+            resultValue = jsBoolean(result.z);
+        }
+        break;
+        
+        case byte_type: {
+            resultValue = jsNumber(result.b);
+        }
+        break;
+        
+        case char_type: {
+            resultValue = jsNumber(result.c);
+        }
+        break;
+        
+        case short_type: {
+            resultValue = jsNumber(result.s);
+        }
+        break;
+        
+        case int_type: {
+            resultValue = jsNumber(result.i);
+        }
+        break;
+        
+        case long_type: {
+            resultValue = jsNumber(result.j);
+        }
+        break;
+        
+        case float_type: {
+            resultValue = jsNumber(result.f);
+        }
+        break;
+        
+        case double_type: {
+            resultValue = jsNumber(result.d);
+        }
+        break;
+
+        case invalid_type:
+        default: {
+            resultValue = jsUndefined();
+        }
+        break;
+    }
+
+    free (jArgs);
+
+    return resultValue;
+}
+
+JSValue *JavaInstance::defaultValue (JSType hint) const
+{
+    if (hint == StringType) {
+        return stringValue();
+    }
+    else if (hint == NumberType) {
+        return numberValue();
+    }
+    else if (hint == BooleanType) {
+        return booleanValue();
+    }
+    else if (hint == UnspecifiedType) {
+        JavaClass *aClass = static_cast<JavaClass*>(getClass());
+        if (aClass->isStringClass()) {
+            return stringValue();
+        }
+        else if (aClass->isNumberClass()) {
+            return numberValue();
+        }
+        else if (aClass->isBooleanClass()) {
+            return booleanValue();
+        }
+    }
+    
+    return valueOf();
+}
+
+JSValue *JavaInstance::valueOf() const 
+{
+    return stringValue();
+}
+
+JObjectWrapper::JObjectWrapper(jobject instance)
+: _refCount(0)
+{
+    assert (instance != 0);
+
+    // Cache the JNIEnv used to get the global ref for this java instanace.
+    // It'll be used to delete the reference.
+    _env = getJNIEnv();
+        
+    _instance = _env->NewGlobalRef (instance);
+    
+    JS_LOG ("new global ref %p for %p\n", _instance, instance);
+
+    if  (_instance == NULL) {
+        fprintf (stderr, "%s:  could not get GlobalRef for %p\n", __PRETTY_FUNCTION__, instance);
+    }
+}
+
+JObjectWrapper::~JObjectWrapper() {
+    JS_LOG ("deleting global ref %p\n", _instance);
+    _env->DeleteGlobalRef (_instance);
+}
diff --git a/WebCore/bridge/jni/jni_instance.h b/WebCore/bridge/jni/jni_instance.h
new file mode 100644 (file)
index 0000000..eb89e3f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+#ifndef _JNI_INSTANCE_H_
+#define _JNI_INSTANCE_H_
+
+#include "runtime.h"
+
+#include <JavaVM/jni.h>
+
+
+namespace KJS {
+
+namespace Bindings {
+
+class JavaClass;
+
+class JObjectWrapper
+{
+friend class RefPtr<JObjectWrapper>;
+friend class JavaArray;
+friend class JavaField;
+friend class JavaInstance;
+friend class JavaMethod;
+
+protected:
+    JObjectWrapper(jobject instance);    
+    ~JObjectWrapper();
+    
+    void ref() { _refCount++; }
+    void deref() 
+    { 
+        if (--_refCount == 0) 
+            delete this; 
+    }
+
+    jobject _instance;
+
+private:
+    JNIEnv *_env;
+    unsigned int _refCount;
+};
+
+class JavaInstance : public Instance
+{
+public:
+    JavaInstance(jobject instance, PassRefPtr<RootObject>);
+    ~JavaInstance();
+    
+    virtual Class *getClass() const;
+    
+    virtual void begin();
+    virtual void end();
+    
+    virtual JSValue *valueOf() const;
+    virtual JSValue *defaultValue (JSType hint) const;
+
+    virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
+
+    jobject javaInstance() const { return _instance->_instance; }
+    
+    JSValue *stringValue() const;
+    JSValue *numberValue() const;
+    JSValue *booleanValue() const;
+
+    virtual BindingLanguage getBindingLanguage() const { return JavaLanguage; }
+
+private:
+    RefPtr<JObjectWrapper> _instance;
+    mutable JavaClass *_class;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/jni/jni_jsobject.cpp b/WebCore/bridge/jni/jni_jsobject.cpp
new file mode 100644 (file)
index 0000000..347f24f
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "identifier.h"
+#include "internal.h"
+#include "interpreter.h"
+#include "jni_jsobject.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "JSGlobalObject.h"
+#include "list.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <wtf/Assertions.h>
+
+using namespace KJS::Bindings;
+using namespace KJS;
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+    fprintf (stderr, "%s(%p,%p):  ", __PRETTY_FUNCTION__, RootObject::runLoop(), CFRunLoopGetCurrent()); \
+    fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+#define UndefinedHandle 1
+
+static bool isJavaScriptThread()
+{
+    return (RootObject::runLoop() == CFRunLoopGetCurrent());
+}
+
+jvalue JavaJSObject::invoke (JSObjectCallContext *context)
+{
+    jvalue result;
+
+    bzero ((void *)&result, sizeof(jvalue));
+    
+    if (!isJavaScriptThread()) {        
+        // Send the call context to the thread that is allowed to
+        // call JavaScript.
+        RootObject::dispatchToJavaScriptThread(context);
+        result = context->result;
+    }
+    else {
+        jlong nativeHandle = context->nativeHandle;
+        if (nativeHandle == UndefinedHandle || nativeHandle == 0) {
+            return result;
+        }
+
+        if (context->type == CreateNative) {
+            result.j = JavaJSObject::createNative(nativeHandle);
+        }
+        else {
+            JSObject *imp = jlong_to_impptr(nativeHandle);
+            if (!findProtectingRootObject(imp)) {
+                fprintf (stderr, "%s:%d:  Attempt to access JavaScript from destroyed applet, type %d.\n", __FILE__, __LINE__, context->type);
+                return result;
+            }
+
+            switch (context->type){            
+                case Call: {
+                    result.l = JavaJSObject(nativeHandle).call(context->string, context->args);
+                    break;
+                }
+                
+                case Eval: {
+                    result.l = JavaJSObject(nativeHandle).eval(context->string);
+                    break;
+                }
+            
+                case GetMember: {
+                    result.l = JavaJSObject(nativeHandle).getMember(context->string);
+                    break;
+                }
+                
+                case SetMember: {
+                    JavaJSObject(nativeHandle).setMember(context->string, context->value);
+                    break;
+                }
+                
+                case RemoveMember: {
+                    JavaJSObject(nativeHandle).removeMember(context->string);
+                    break;
+                }
+            
+                case GetSlot: {
+                    result.l = JavaJSObject(nativeHandle).getSlot(context->index);
+                    break;
+                }
+                
+                case SetSlot: {
+                    JavaJSObject(nativeHandle).setSlot(context->index, context->value);
+                    break;
+                }
+            
+                case ToString: {
+                    result.l = (jobject) JavaJSObject(nativeHandle).toString();
+                    break;
+                }
+    
+                case Finalize: {
+                    JavaJSObject(nativeHandle).finalize();
+                    break;
+                }
+                
+                default: {
+                    fprintf (stderr, "%s:  invalid JavaScript call\n", __PRETTY_FUNCTION__);
+                }
+            }
+        }
+        context->result = result;
+    }
+
+    return result;
+}
+
+
+JavaJSObject::JavaJSObject(jlong nativeJSObject)
+{
+    _imp = jlong_to_impptr(nativeJSObject);
+    
+    ASSERT(_imp);
+    _rootObject = findProtectingRootObject(_imp);
+    ASSERT(_rootObject);
+}
+
+RootObject* JavaJSObject::rootObject() const
+{ 
+    return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; 
+}
+
+jobject JavaJSObject::call(jstring methodName, jobjectArray args) const
+{
+    JS_LOG ("methodName = %s\n", JavaString(methodName).UTF8String());
+
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return 0;
+    
+    // Lookup the function object.
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    JSLock lock;
+    
+    Identifier identifier(JavaString(methodName).ustring());
+    JSValue *func = _imp->get (exec, identifier);
+    if (func->isUndefinedOrNull())
+        return 0;
+
+    // Call the function object.
+    JSObject *funcImp = static_cast<JSObject*>(func);
+    JSObject *thisObj = const_cast<JSObject*>(_imp);
+    List argList;
+    getListFromJArray(args, argList);
+    rootObject->globalObject()->startTimeoutCheck();
+    JSValue *result = funcImp->call(exec, thisObj, argList);
+    rootObject->globalObject()->stopTimeoutCheck();
+
+    return convertValueToJObject(result);
+}
+
+jobject JavaJSObject::eval(jstring script) const
+{
+    JS_LOG ("script = %s\n", JavaString(script).UTF8String());
+    
+    JSObject *thisObj = const_cast<JSObject*>(_imp);
+    JSValue *result;
+    
+    JSLock lock;
+    
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return 0;
+
+    rootObject->globalObject()->startTimeoutCheck();
+    Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), UString(), 0, JavaString(script).ustring(),thisObj);
+    rootObject->globalObject()->stopTimeoutCheck();
+    ComplType type = completion.complType();
+    
+    if (type == Normal) {
+        result = completion.value();
+        if (!result)
+            result = jsUndefined();
+    } else
+        result = jsUndefined();
+    
+    return convertValueToJObject (result);
+}
+
+jobject JavaJSObject::getMember(jstring memberName) const
+{
+    JS_LOG ("(%p) memberName = %s\n", _imp, JavaString(memberName).UTF8String());
+
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return 0;
+
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    
+    JSLock lock;
+    JSValue *result = _imp->get (exec, Identifier (JavaString(memberName).ustring()));
+
+    return convertValueToJObject(result);
+}
+
+void JavaJSObject::setMember(jstring memberName, jobject value) const
+{
+    JS_LOG ("memberName = %s, value = %p\n", JavaString(memberName).UTF8String(), value);
+
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return;
+
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    JSLock lock;
+    _imp->put(exec, Identifier (JavaString(memberName).ustring()), convertJObjectToValue(value));
+}
+
+
+void JavaJSObject::removeMember(jstring memberName) const
+{
+    JS_LOG ("memberName = %s\n", JavaString(memberName).UTF8String());
+
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return;
+
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    JSLock lock;
+    _imp->deleteProperty(exec, Identifier (JavaString(memberName).ustring()));
+}
+
+
+jobject JavaJSObject::getSlot(jint index) const
+{
+#ifdef __LP64__
+    JS_LOG ("index = %d\n", index);
+#else
+    JS_LOG ("index = %ld\n", index);
+#endif
+
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return 0;
+
+    ExecState* exec = rootObject->globalObject()->globalExec();
+
+    JSLock lock;
+    JSValue *result = _imp->get (exec, (unsigned)index);
+
+    return convertValueToJObject(result);
+}
+
+
+void JavaJSObject::setSlot(jint index, jobject value) const
+{
+#ifdef __LP64__
+    JS_LOG ("index = %d, value = %p\n", index, value);
+#else
+    JS_LOG ("index = %ld, value = %p\n", index, value);
+#endif
+
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return;
+
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    JSLock lock;
+    _imp->put(exec, (unsigned)index, convertJObjectToValue(value));
+}
+
+
+jstring JavaJSObject::toString() const
+{
+    JS_LOG ("\n");
+    
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return 0;
+
+    JSLock lock;
+    JSObject *thisObj = const_cast<JSObject*>(_imp);
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    
+    return (jstring)convertValueToJValue (exec, thisObj, object_type, "java.lang.String").l;
+}
+
+void JavaJSObject::finalize() const
+{
+    if (RootObject* rootObject = this->rootObject())
+        rootObject->gcUnprotect(_imp);
+}
+
+// We're either creating a 'Root' object (via a call to JavaJSObject.getWindow()), or
+// another JavaJSObject.
+jlong JavaJSObject::createNative(jlong nativeHandle)
+{
+    JS_LOG ("nativeHandle = %d\n", (int)nativeHandle);
+
+    if (nativeHandle == UndefinedHandle)
+        return nativeHandle;
+
+    if (findProtectingRootObject(jlong_to_impptr(nativeHandle)))
+        return nativeHandle;
+
+    CreateRootObjectFunction createRootObject = RootObject::createRootObject();
+    if (!createRootObject)
+        return ptr_to_jlong(0);
+
+    RefPtr<RootObject> rootObject = createRootObject(jlong_to_ptr(nativeHandle));
+
+    // If rootObject is !NULL We must have been called via netscape.javascript.JavaJSObject.getWindow(),
+    // otherwise we are being called after creating a JavaJSObject in
+    // JavaJSObject::convertValueToJObject().
+    if (rootObject) {
+        JSObject* globalObject = rootObject->globalObject();
+        // We call gcProtect here to get the object into the root object's "protect set" which
+        // is used to test if a native handle is valid as well as getting the root object given the handle.
+        rootObject->gcProtect(globalObject);
+        return ptr_to_jlong(globalObject);
+    }
+    
+    return nativeHandle;
+}
+
+jobject JavaJSObject::convertValueToJObject (JSValue *value) const
+{
+    JSLock lock;
+    
+    RootObject* rootObject = this->rootObject();
+    if (!rootObject)
+        return 0;
+
+    ExecState* exec = rootObject->globalObject()->globalExec();
+    JNIEnv *env = getJNIEnv();
+    jobject result = 0;
+    
+    // See section 22.7 of 'JavaScript:  The Definitive Guide, 4th Edition',
+    // figure 22-5.
+    // number -> java.lang.Double
+    // string -> java.lang.String
+    // boolean -> java.lang.Boolean
+    // Java instance -> Java instance
+    // Everything else -> JavaJSObject
+    
+    JSType type = value->type();
+    if (type == NumberType) {
+        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) {
+        UString stringValue = value->toString(exec);
+        JNIEnv *env = getJNIEnv();
+        result = env->NewString ((const jchar *)stringValue.data(), stringValue.size());
+    }
+    else if (type == BooleanType) {
+        jclass JSObjectClass = env->FindClass ("java/lang/Boolean");
+        jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(Z)V");
+        if (constructorID != NULL) {
+            result = env->NewObject (JSObjectClass, constructorID, (jboolean)value->toBoolean(exec));
+        }
+    }
+    else {
+        // Create a JavaJSObject.
+        jlong nativeHandle;
+        
+        if (type == ObjectType){
+            JSObject *imp = static_cast<JSObject*>(value);
+            
+            // We either have a wrapper around a Java instance or a JavaScript
+            // object.  If we have a wrapper around a Java instance, return that
+            // instance, otherwise create a new Java JavaJSObject with the JSObject*
+            // as it's nativeHandle.
+            if (imp->classInfo() && strcmp(imp->classInfo()->className, "RuntimeObject") == 0) {
+                RuntimeObjectImp *runtimeImp = static_cast<RuntimeObjectImp*>(value);
+                JavaInstance *runtimeInstance = static_cast<JavaInstance *>(runtimeImp->getInternalInstance());
+                if (!runtimeInstance)
+                    return 0;
+                
+                return runtimeInstance->javaInstance();
+            }
+            else {
+                nativeHandle = ptr_to_jlong(imp);
+                rootObject->gcProtect(imp);
+            }
+        }
+        // All other types will result in an undefined object.
+        else {
+            nativeHandle = UndefinedHandle;
+        }
+        
+        // Now create the Java JavaJSObject.  Look for the JavaJSObject in it's new (Tiger)
+        // location and in the original Java 1.4.2 location.
+        jclass JSObjectClass;
+        
+        JSObjectClass = env->FindClass ("sun/plugin/javascript/webkit/JSObject");
+        if (!JSObjectClass) {
+            env->ExceptionDescribe();
+            env->ExceptionClear();
+            JSObjectClass = env->FindClass ("apple/applet/JSObject");
+        }
+            
+        jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(J)V");
+        if (constructorID != NULL) {
+            result = env->NewObject (JSObjectClass, constructorID, nativeHandle);
+        }
+    }
+    
+    return result;
+}
+
+JSValue *JavaJSObject::convertJObjectToValue (jobject theObject) const
+{
+    // Instances of netscape.javascript.JSObject get converted back to
+    // JavaScript objects.  All other objects are wrapped.  It's not
+    // possible to pass primitive types from the Java to JavaScript.
+    // See section 22.7 of 'JavaScript:  The Definitive Guide, 4th Edition',
+    // figure 22-4.
+    jobject classOfInstance = callJNIObjectMethod(theObject, "getClass", "()Ljava/lang/Class;");
+    jstring className = (jstring)callJNIObjectMethod(classOfInstance, "getName", "()Ljava/lang/String;");
+    
+    // Only the sun.plugin.javascript.webkit.JSObject has a member called nativeJSObject. This class is
+    // created above to wrap internal browser objects. The constructor of this class takes the native
+    // pointer and stores it in this object, so that it can be retrieved below.
+    if (strcmp(JavaString(className).UTF8String(), "sun.plugin.javascript.webkit.JSObject") == 0) {
+        // Pull the nativeJSObject value from the Java instance.  This is a
+        // pointer to the JSObject.
+        JNIEnv *env = getJNIEnv();
+        jfieldID fieldID = env->GetFieldID((jclass)classOfInstance, "nativeJSObject", "J");
+        if (fieldID == NULL) {
+            return jsUndefined();
+        }
+        jlong nativeHandle = env->GetLongField(theObject, fieldID);
+        if (nativeHandle == UndefinedHandle) {
+            return jsUndefined();
+        }
+        JSObject *imp = static_cast<JSObject*>(jlong_to_impptr(nativeHandle));
+        return imp;
+    }
+
+    JSLock lock;
+    JavaInstance* javaInstance = new JavaInstance(theObject, _rootObject);
+    return KJS::Bindings::Instance::createRuntimeObject(javaInstance);
+}
+
+void JavaJSObject::getListFromJArray(jobjectArray jArray, List& list) const
+{
+    JNIEnv *env = getJNIEnv();
+    int i, numObjects = jArray ? env->GetArrayLength (jArray) : 0;
+    
+    for (i = 0; i < numObjects; i++) {
+        jobject anObject = env->GetObjectArrayElement ((jobjectArray)jArray, i);
+        if (anObject) {
+            list.append(convertJObjectToValue(anObject));
+            env->DeleteLocalRef (anObject);
+        }
+        else {
+            env->ExceptionDescribe();
+            env->ExceptionClear();
+        }
+    }
+}
+
+extern "C" {
+
+jlong KJS_JSCreateNativeJSObject (JNIEnv*, jclass, jstring, jlong nativeHandle, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = CreateNative;
+    context.nativeHandle = nativeHandle;
+    return JavaJSObject::invoke (&context).j;
+}
+
+void KJS_JSObject_JSFinalize (JNIEnv*, jclass, jlong nativeHandle)
+{
+    JSObjectCallContext context;
+    context.type = Finalize;
+    context.nativeHandle = nativeHandle;
+    JavaJSObject::invoke (&context);
+}
+
+jobject KJS_JSObject_JSObjectCall (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring methodName, jobjectArray args, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = Call;
+    context.nativeHandle = nativeHandle;
+    context.string = methodName;
+    context.args = args;
+    return JavaJSObject::invoke (&context).l;
+}
+
+jobject KJS_JSObject_JSObjectEval (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jscript, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = Eval;
+    context.nativeHandle = nativeHandle;
+    context.string = jscript;
+    return JavaJSObject::invoke (&context).l;
+}
+
+jobject KJS_JSObject_JSObjectGetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = GetMember;
+    context.nativeHandle = nativeHandle;
+    context.string = jname;
+    return JavaJSObject::invoke (&context).l;
+}
+
+void KJS_JSObject_JSObjectSetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jobject value, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = SetMember;
+    context.nativeHandle = nativeHandle;
+    context.string = jname;
+    context.value = value;
+    JavaJSObject::invoke (&context);
+}
+
+void KJS_JSObject_JSObjectRemoveMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = RemoveMember;
+    context.nativeHandle = nativeHandle;
+    context.string = jname;
+    JavaJSObject::invoke (&context);
+}
+
+jobject KJS_JSObject_JSObjectGetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = GetSlot;
+    context.nativeHandle = nativeHandle;
+    context.index = jindex;
+    return JavaJSObject::invoke (&context).l;
+}
+
+void KJS_JSObject_JSObjectSetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jobject value, jboolean)
+{
+    JSObjectCallContext context;
+    context.type = SetSlot;
+    context.nativeHandle = nativeHandle;
+    context.index = jindex;
+    context.value = value;
+    JavaJSObject::invoke (&context);
+}
+
+jstring KJS_JSObject_JSObjectToString (JNIEnv*, jclass, jlong nativeHandle)
+{
+    JSObjectCallContext context;
+    context.type = ToString;
+    context.nativeHandle = nativeHandle;
+    return (jstring)JavaJSObject::invoke (&context).l;
+}
+
+}
diff --git a/WebCore/bridge/jni/jni_jsobject.h b/WebCore/bridge/jni/jni_jsobject.h
new file mode 100644 (file)
index 0000000..75f37a2
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
+#define JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <JavaVM/jni.h>
+#include <wtf/RefPtr.h>
+
+#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))
+#define jlong_to_impptr(a) (static_cast<KJS::JSObject*>(((void*)(uintptr_t)(a))))
+#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))
+
+namespace KJS {
+
+class List;
+class JSObject;
+class JSValue;
+
+namespace Bindings {
+
+class RootObject;
+
+enum JSObjectCallType {
+    CreateNative,
+    Call,
+    Eval,
+    GetMember,
+    SetMember,
+    RemoveMember,
+    GetSlot,
+    SetSlot,
+    ToString,
+    Finalize
+};
+
+struct JSObjectCallContext
+{
+    JSObjectCallType type;
+    jlong nativeHandle;
+    jstring string;
+    jobjectArray args;
+    jint index;
+    jobject value;
+    CFRunLoopRef originatingLoop;
+    jvalue result;
+};
+
+class JavaJSObject
+{
+public:
+    JavaJSObject(jlong nativeHandle);
+    
+    static jlong createNative(jlong nativeHandle);
+    jobject call(jstring methodName, jobjectArray args) const;
+    jobject eval(jstring script) const;
+    jobject getMember(jstring memberName) const;
+    void setMember(jstring memberName, jobject value) const;
+    void removeMember(jstring memberName) const;
+    jobject getSlot(jint index) const;
+    void setSlot(jint index, jobject value) const;
+    jstring toString() const;
+    void finalize() const;
+    
+    static jvalue invoke(JSObjectCallContext*);
+
+    jobject convertValueToJObject(JSValue*) const;
+    JSValue* convertJObjectToValue(jobject) const;
+    void getListFromJArray(jobjectArray, List&) const;
+    
+    RootObject* rootObject() const;
+    
+private:
+    RefPtr<RootObject> _rootObject;
+    JSObject* _imp;
+};
+
+
+} // namespace Bindings
+
+} // namespace KJS
+
+extern "C" {
+
+// The Java VM calls these functions to handle calls to methods in Java's JSObject class.
+jlong KJS_JSCreateNativeJSObject(JNIEnv*, jclass, jstring jurl, jlong nativeHandle, jboolean ctx);
+void KJS_JSObject_JSFinalize(JNIEnv*, jclass, jlong nativeJSObject);
+jobject KJS_JSObject_JSObjectCall(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring methodName, jobjectArray args, jboolean ctx);
+jobject KJS_JSObject_JSObjectEval(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jscript, jboolean ctx);
+jobject KJS_JSObject_JSObjectGetMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jboolean ctx);
+void KJS_JSObject_JSObjectSetMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jobject value, jboolean ctx);
+void KJS_JSObject_JSObjectRemoveMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jboolean ctx);
+jobject KJS_JSObject_JSObjectGetSlot(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jint jindex, jboolean ctx);
+void KJS_JSObject_JSObjectSetSlot(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jint jindex, jobject value, jboolean ctx);
+jstring KJS_JSObject_JSObjectToString(JNIEnv*, jclass, jlong nativeJSObject);
+
+}
+
+#endif
diff --git a/WebCore/bridge/jni/jni_objc.mm b/WebCore/bridge/jni/jni_objc.mm
new file mode 100644 (file)
index 0000000..43d2da0
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+#import <Foundation/Foundation.h>
+#import <JavaScriptCore/jni_utility.h>
+#import <JavaScriptCore/objc_utility.h>
+
+using namespace KJS::Bindings;
+
+@interface NSObject (WebScriptingPrivate)
+- (jvalue)webPlugInCallJava:(jobject)object method:(jmethodID)method returnType:(JNIType)returnType arguments:(jvalue*)args;
+- (jvalue)webPlugInCallJava:(jobject)object
+                   isStatic:(BOOL)isStatic
+                 returnType:(JNIType)returnType
+                     method:(jmethodID)method
+                  arguments:(jvalue*)args
+                 callingURL:(NSURL *)url
+       exceptionDescription:(NSString **)exceptionString;
+@end
+
+bool KJS::Bindings::dispatchJNICall (const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char*, JSValue *&exceptionDescription)
+{
+    id view = (id)targetAppletView;
+    
+    // As array_type is not known by the Mac JVM, change it to a compatible type.
+    if (returnType == array_type)
+        returnType = object_type;
+    
+    if ([view respondsToSelector:@selector(webPlugInCallJava:isStatic:returnType:method:arguments:callingURL:exceptionDescription:)]) {
+        NSString *_exceptionDescription = 0;
+
+        // Passing nil as the calling URL will cause the Java plugin to use the URL
+        // of the page that contains the applet. The execution restrictions 
+        // implemented in WebCore will guarantee that only appropriate JavaScript
+        // can reference the applet.
+        {
+           JSLock::DropAllLocks dropAllLocks;
+            result = [view webPlugInCallJava:obj isStatic:isStatic returnType:returnType method:methodID arguments:args callingURL:nil exceptionDescription:&_exceptionDescription];
+        }
+
+        if (_exceptionDescription != 0) {
+            exceptionDescription = convertNSStringToString(_exceptionDescription);
+        }
+        return true;
+    }
+    else if ([view respondsToSelector:@selector(webPlugInCallJava:method:returnType:arguments:)]) {
+       JSLock::DropAllLocks dropAllLocks;
+        result = [view webPlugInCallJava:obj method:methodID returnType:returnType arguments:args];
+        return true;
+    }
+
+    bzero (&result, sizeof(jvalue));
+    return false;
+}
diff --git a/WebCore/bridge/jni/jni_runtime.cpp b/WebCore/bridge/jni/jni_runtime.cpp
new file mode 100644 (file)
index 0000000..7d7cb31
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 <internal.h>
+#include <ustring.h>
+#include <value.h>
+
+#include <jni_utility.h>
+#include <jni_runtime.h>
+
+#include <runtime_array.h>
+#include <runtime_object.h>
+#include <runtime_root.h>
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+    fprintf (stderr, "%s:%d -- %s:  ", __FILE__, __LINE__, __FUNCTION__); \
+    fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+
+JavaParameter::JavaParameter (JNIEnv *env, jstring type)
+{
+    _type = JavaString (env, type);
+    _JNIType = JNITypeFromClassName (_type.UTF8String());
+}
+
+JavaField::JavaField (JNIEnv *env, jobject aField)
+{
+    // Get field type
+    jobject fieldType = callJNIObjectMethod (aField, "getType", "()Ljava/lang/Class;");
+    jstring fieldTypeName = (jstring)callJNIObjectMethod (fieldType, "getName", "()Ljava/lang/String;");
+    _type = JavaString(env, fieldTypeName);
+    _JNIType = JNITypeFromClassName (_type.UTF8String());
+
+    // Get field name
+    jstring fieldName = (jstring)callJNIObjectMethod (aField, "getName", "()Ljava/lang/String;");
+    _name = JavaString(env, fieldName);
+
+    _field = new JObjectWrapper(aField);
+}
+
+JSValue* JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
+{
+    if (type[0] != '[')
+        return jsUndefined();
+
+    return new RuntimeArray(exec, new JavaArray((jobject)anObject, type, rootObject));
+}
+
+jvalue JavaField::dispatchValueFromInstance(ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const
+{
+    jobject jinstance = instance->javaInstance();
+    jobject fieldJInstance = _field->_instance;
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+
+    bzero (&result, sizeof(jvalue));
+    jclass cls = env->GetObjectClass(fieldJInstance);
+    if ( cls != NULL ) {
+        jmethodID mid = env->GetMethodID(cls, name, sig);
+        if ( mid != NULL )
+        {
+            RootObject* rootObject = instance->rootObject();
+            if (rootObject && rootObject->nativeHandle()) {
+                JSValue *exceptionDescription = NULL;
+                jvalue args[1];
+                
+                args[0].l = jinstance;
+                dispatchJNICall(rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
+                if (exceptionDescription)
+                    throwError(exec, GeneralError, exceptionDescription->toString(exec));
+            }
+        }
+    }
+    return result;
+}
+
+JSValue *JavaField::valueFromInstance(ExecState *exec, const Instance *i) const 
+{
+    const JavaInstance *instance = static_cast<const JavaInstance *>(i);
+
+    JSValue *jsresult = jsUndefined();
+    
+    switch (_JNIType) {
+        case array_type:
+        case object_type: {
+            jvalue result = dispatchValueFromInstance (exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", object_type);
+            jobject anObject = result.l;
+
+            const char *arrayType = type();
+            if (arrayType[0] == '[') {
+                jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject());
+            }
+            else if (anObject != 0){
+                jsresult = Instance::createRuntimeObject(Instance::JavaLanguage, anObject, instance->rootObject());
+            }
+        }
+        break;
+            
+        case boolean_type:
+            jsresult = jsBoolean(dispatchValueFromInstance(exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", boolean_type).z);
+            break;
+            
+        case byte_type:
+        case char_type:
+        case short_type:
+        
+        case int_type: {
+            jint value;
+            jvalue result = dispatchValueFromInstance (exec, instance, "getInt", "(Ljava/lang/Object;)I", int_type);
+            value = result.i;
+            jsresult = jsNumber((int)value);
+        }
+        break;
+
+        case long_type:
+        case float_type:
+        case double_type: {
+            jdouble value;
+            jvalue result = dispatchValueFromInstance (exec, instance, "getDouble", "(Ljava/lang/Object;)D", double_type);
+            value = result.i;
+            jsresult = jsNumber((double)value);
+        }
+        break;
+        default:
+        break;
+    }
+
+    JS_LOG ("getting %s = %s\n", name(), jsresult->toString(exec).ascii());
+    
+    return jsresult;
+}
+
+void JavaField::dispatchSetValueToInstance(ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const
+{
+    jobject jinstance = instance->javaInstance();
+    jobject fieldJInstance = _field->_instance;
+    JNIEnv *env = getJNIEnv();
+
+    jclass cls = env->GetObjectClass(fieldJInstance);
+    if ( cls != NULL ) {
+        jmethodID mid = env->GetMethodID(cls, name, sig);
+        if ( mid != NULL )
+        {
+            RootObject* rootObject = instance->rootObject();
+            if (rootObject && rootObject->nativeHandle()) {
+                JSValue *exceptionDescription = NULL;
+                jvalue args[2];
+                jvalue result;
+                
+                args[0].l = jinstance;
+                args[1] = javaValue;
+                dispatchJNICall(rootObject->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
+                if (exceptionDescription)
+                    throwError(exec, GeneralError, exceptionDescription->toString(exec));
+            }
+        }
+    }
+}
+
+void JavaField::setValueToInstance(ExecState *exec, const Instance *i, JSValue *aValue) const
+{
+    const JavaInstance *instance = static_cast<const JavaInstance *>(i);
+    jvalue javaValue = convertValueToJValue (exec, aValue, _JNIType, type());
+
+    JS_LOG ("setting value %s to %s\n", name(), aValue->toString(exec).ascii());
+
+    switch (_JNIType) {
+        case array_type:
+        case object_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V");
+        }
+        break;
+            
+        case boolean_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V");
+        }
+        break;
+            
+        case byte_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V");
+        }
+        break;
+
+        case char_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V");
+        }
+        break;
+
+        case short_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V");
+        }
+        break;
+
+        case int_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V");
+        }
+        break;
+
+        case long_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V");
+        }
+        break;
+
+        case float_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V");
+        }
+        break;
+
+        case double_type: {
+            dispatchSetValueToInstance (exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V");
+        }
+        break;
+        default:
+        break;
+    }
+}
+
+JavaMethod::JavaMethod (JNIEnv *env, jobject aMethod)
+{
+    // Get return type
+    jobject returnType = callJNIObjectMethod (aMethod, "getReturnType", "()Ljava/lang/Class;");
+    jstring returnTypeName = (jstring)callJNIObjectMethod (returnType, "getName", "()Ljava/lang/String;");
+    _returnType =JavaString (env, returnTypeName);
+    _JNIReturnType = JNITypeFromClassName (_returnType.UTF8String());
+    env->DeleteLocalRef (returnType);
+    env->DeleteLocalRef (returnTypeName);
+
+    // Get method name
+    jstring methodName = (jstring)callJNIObjectMethod (aMethod, "getName", "()Ljava/lang/String;");
+    _name = JavaString (env, methodName);
+    env->DeleteLocalRef (methodName);
+
+    // Get parameters
+    jarray jparameters = (jarray)callJNIObjectMethod (aMethod, "getParameterTypes", "()[Ljava/lang/Class;");
+    _numParameters = env->GetArrayLength (jparameters);
+    _parameters = new JavaParameter[_numParameters];
+    
+    int i;
+    for (i = 0; i < _numParameters; i++) {
+        jobject aParameter = env->GetObjectArrayElement ((jobjectArray)jparameters, i);
+        jstring parameterName = (jstring)callJNIObjectMethod (aParameter, "getName", "()Ljava/lang/String;");
+        _parameters[i] = JavaParameter(env, parameterName);
+        env->DeleteLocalRef (aParameter);
+        env->DeleteLocalRef (parameterName);
+    }
+    env->DeleteLocalRef (jparameters);
+
+    // Created lazily.
+    _signature = 0;
+    _methodID = 0;
+    
+    jclass modifierClass = env->FindClass("java/lang/reflect/Modifier");
+    int modifiers = callJNIIntMethod (aMethod, "getModifiers", "()I");
+    _isStatic = (bool)callJNIStaticBooleanMethod (modifierClass, "isStatic", "(I)Z", modifiers);
+}
+
+JavaMethod::~JavaMethod() 
+{
+    if (_signature)
+        free(_signature);
+    delete [] _parameters;
+};
+
+// JNI method signatures use '/' between components of a class name, but
+// we get '.' between components from the reflection API.
+static void appendClassName(UString& aString, const char* className)
+{
+    ASSERT(JSLock::lockCount() > 0);
+    
+    char *result, *cp = strdup(className);
+    
+    result = cp;
+    while (*cp) {
+        if (*cp == '.')
+            *cp = '/';
+        cp++;
+    }
+        
+    aString.append(result);
+
+    free (result);
+}
+
+const char *JavaMethod::signature() const 
+{
+    if (!_signature) {
+        JSLock lock;
+
+        UString signatureBuilder("(");
+        for (int i = 0; i < _numParameters; i++) {
+            JavaParameter* aParameter = parameterAt(i);
+            JNIType _JNIType = aParameter->getJNIType();
+            if (_JNIType == array_type)
+                appendClassName(signatureBuilder, aParameter->type());
+            else {
+                signatureBuilder.append(signatureFromPrimitiveType(_JNIType));
+                if (_JNIType == object_type) {
+                    appendClassName(signatureBuilder, aParameter->type());
+                    signatureBuilder.append(";");
+                }
+            }
+        }
+        signatureBuilder.append(")");
+        
+        const char *returnType = _returnType.UTF8String();
+        if (_JNIReturnType == array_type) {
+            appendClassName(signatureBuilder, returnType);
+        } else {
+            signatureBuilder.append(signatureFromPrimitiveType(_JNIReturnType));
+            if (_JNIReturnType == object_type) {
+                appendClassName(signatureBuilder, returnType);
+                signatureBuilder.append(";");
+            }
+        }
+        
+        _signature = strdup(signatureBuilder.ascii());
+    }
+    
+    return _signature;
+}
+
+JNIType JavaMethod::JNIReturnType() const
+{
+    return _JNIReturnType;
+}
+
+jmethodID JavaMethod::methodID (jobject obj) const
+{
+    if (_methodID == 0) {
+        _methodID = getMethodID (obj, name(), signature());
+    }
+    return _methodID;
+}
+
+
+JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
+    : Array(rootObject)
+{
+    _array = new JObjectWrapper(array);
+    // Java array are fixed length, so we can cache length.
+    JNIEnv *env = getJNIEnv();
+    _length = env->GetArrayLength((jarray)_array->_instance);
+    _type = strdup(type);
+    _rootObject = rootObject;
+}
+
+JavaArray::~JavaArray () 
+{
+    free ((void *)_type);
+}
+
+RootObject* JavaArray::rootObject() const 
+{ 
+    return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
+}
+
+void JavaArray::setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const
+{
+    JNIEnv *env = getJNIEnv();
+    char *javaClassName = 0;
+    
+    JNIType arrayType = JNITypeFromPrimitiveType(_type[1]);
+    if (_type[1] == 'L'){
+        // The type of the array will be something like:
+        // "[Ljava.lang.string;".  This is guaranteed, so no need
+        // for extra sanity checks.
+        javaClassName = strdup(&_type[2]);
+        javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
+    }
+    jvalue aJValue = convertValueToJValue (exec, aValue, arrayType, javaClassName);
+    
+    switch (arrayType) {
+        case object_type: {
+            env->SetObjectArrayElement((jobjectArray)javaArray(), index, aJValue.l);
+            break;
+        }
+            
+        case boolean_type: {
+            env->SetBooleanArrayRegion((jbooleanArray)javaArray(), index, 1, &aJValue.z);
+            break;
+        }
+            
+        case byte_type: {
+            env->SetByteArrayRegion((jbyteArray)javaArray(), index, 1, &aJValue.b);
+            break;
+        }
+            
+        case char_type: {
+            env->SetCharArrayRegion((jcharArray)javaArray(), index, 1, &aJValue.c);
+            break;
+        }
+            
+        case short_type: {
+            env->SetShortArrayRegion((jshortArray)javaArray(), index, 1, &aJValue.s);
+            break;
+        }
+            
+        case int_type: {
+            env->SetIntArrayRegion((jintArray)javaArray(), index, 1, &aJValue.i);
+            break;
+        }
+            
+        case long_type: {
+            env->SetLongArrayRegion((jlongArray)javaArray(), index, 1, &aJValue.j);
+        }
+            
+        case float_type: {
+            env->SetFloatArrayRegion((jfloatArray)javaArray(), index, 1, &aJValue.f);
+            break;
+        }
+            
+        case double_type: {
+            env->SetDoubleArrayRegion((jdoubleArray)javaArray(), index, 1, &aJValue.d);
+            break;
+        }
+        default:
+        break;
+    }
+    
+    if (javaClassName)
+        free ((void *)javaClassName);
+}
+
+
+JSValue *JavaArray::valueAt(ExecState *exec, unsigned int index) const
+{
+    JNIEnv *env = getJNIEnv();
+    JNIType arrayType = JNITypeFromPrimitiveType(_type[1]);
+    switch (arrayType) {
+        case object_type: {
+            jobjectArray objectArray = (jobjectArray)javaArray();
+            jobject anObject;
+            anObject = env->GetObjectArrayElement(objectArray, index);
+
+            // No object?
+            if (!anObject) {
+                return jsNull();
+            }
+            
+            // Nested array?
+            if (_type[1] == '[') {
+                return JavaArray::convertJObjectToArray(exec, anObject, _type+1, rootObject());
+            }
+            // or array of other object type?
+            return Instance::createRuntimeObject(Instance::JavaLanguage, anObject, rootObject());
+        }
+            
+        case boolean_type: {
+            jbooleanArray booleanArray = (jbooleanArray)javaArray();
+            jboolean aBoolean;
+            env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
+            return jsBoolean(aBoolean);
+        }
+            
+        case byte_type: {
+            jbyteArray byteArray = (jbyteArray)javaArray();
+            jbyte aByte;
+            env->GetByteArrayRegion(byteArray, index, 1, &aByte);
+            return jsNumber(aByte);
+        }
+            
+        case char_type: {
+            jcharArray charArray = (jcharArray)javaArray();
+            jchar aChar;
+            env->GetCharArrayRegion(charArray, index, 1, &aChar);
+            return jsNumber(aChar);
+            break;
+        }
+            
+        case short_type: {
+            jshortArray shortArray = (jshortArray)javaArray();
+            jshort aShort;
+            env->GetShortArrayRegion(shortArray, index, 1, &aShort);
+            return jsNumber(aShort);
+        }
+            
+        case int_type: {
+            jintArray intArray = (jintArray)javaArray();
+            jint anInt;
+            env->GetIntArrayRegion(intArray, index, 1, &anInt);
+            return jsNumber(anInt);
+        }
+            
+        case long_type: {
+            jlongArray longArray = (jlongArray)javaArray();
+            jlong aLong;
+            env->GetLongArrayRegion(longArray, index, 1, &aLong);
+            return jsNumber(aLong);
+        }
+            
+        case float_type: {
+            jfloatArray floatArray = (jfloatArray)javaArray();
+            jfloat aFloat;
+            env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
+            return jsNumber(aFloat);
+        }
+            
+        case double_type: {
+            jdoubleArray doubleArray = (jdoubleArray)javaArray();
+            jdouble aDouble;
+            env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
+            return jsNumber(aDouble);
+        }
+        default:
+        break;
+    }
+    return jsUndefined();
+}
+
+unsigned int JavaArray::getLength() const
+{
+    return _length;
+}
+
+
diff --git a/WebCore/bridge/jni/jni_runtime.h b/WebCore/bridge/jni/jni_runtime.h
new file mode 100644 (file)
index 0000000..9ea1371
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+#ifndef _JNI_RUNTIME_H_
+#define _JNI_RUNTIME_H_
+
+#include <jni_utility.h>
+#include <jni_instance.h>
+
+
+namespace KJS
+{
+
+namespace Bindings
+{
+
+typedef const char* RuntimeType;
+
+class JavaString
+{
+public:
+    JavaString()
+    {
+        JSLock lock;
+        _rep = UString().rep();
+    }
+
+    void _commonInit (JNIEnv *e, jstring s)
+    {
+        int _size = e->GetStringLength (s);
+        const jchar *uc = getUCharactersFromJStringInEnv (e, s);
+        {
+            JSLock lock;
+            _rep = UString((UChar *)uc,_size).rep();
+        }
+        releaseUCharactersForJStringInEnv (e, s, uc);
+    }
+    
+    JavaString (JNIEnv *e, jstring s) {
+        _commonInit (e, s);
+    }
+    
+    JavaString (jstring s) {
+        _commonInit (getJNIEnv(), s);
+    }
+    
+    ~JavaString()
+    {
+        JSLock lock;
+        _rep = 0;
+    }
+    
+    const char *UTF8String() const { 
+        if (_utf8String.c_str() == 0) {
+            JSLock lock;
+            _utf8String = UString(_rep).UTF8String();
+        }
+        return _utf8String.c_str();
+    }
+    const jchar *uchars() const { return (const jchar *)_rep->data(); }
+    int length() const { return _rep->size(); }
+    UString ustring() const { return UString(_rep); }
+
+private:
+    RefPtr<UString::Rep> _rep;
+    mutable CString _utf8String;
+};
+
+class JavaParameter
+{
+public:
+    JavaParameter () : _JNIType(invalid_type) {};
+    JavaParameter (JNIEnv *env, jstring type);
+    virtual ~JavaParameter() { }
+
+    RuntimeType type() const { return _type.UTF8String(); }
+    JNIType getJNIType() const { return _JNIType; }
+    
+private:
+    JavaString _type;
+    JNIType _JNIType;
+};
+
+
+class JavaField : public Field
+{
+public:
+    JavaField (JNIEnv *env, jobject aField);
+
+    virtual JSValue *valueFromInstance(ExecState *exec, const Instance *instance) const;
+    virtual void setValueToInstance(ExecState *exec, const Instance *instance, JSValue *aValue) const;
+    
+    virtual const char *name() const { return _name.UTF8String(); }
+    virtual RuntimeType type() const { return _type.UTF8String(); }
+
+    JNIType getJNIType() const { return _JNIType; }
+    
+private:
+    void dispatchSetValueToInstance(ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const;
+    jvalue dispatchValueFromInstance(ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const;
+
+    JavaString _name;
+    JavaString _type;
+    JNIType _JNIType;
+    RefPtr<JObjectWrapper> _field;
+};
+
+
+class JavaMethod : public Method
+{
+public:
+    JavaMethod(JNIEnv* env, jobject aMethod);
+    ~JavaMethod();
+
+    virtual const char *name() const { return _name.UTF8String(); };
+    RuntimeType returnType() const { return _returnType.UTF8String(); };
+    JavaParameter* parameterAt(int i) const { return &_parameters[i]; };
+    int numParameters() const { return _numParameters; };
+    
+    const char *signature() const;
+    JNIType JNIReturnType() const;
+
+    jmethodID methodID (jobject obj) const;
+    
+    bool isStatic() const { return _isStatic; }
+
+private:
+    JavaParameter* _parameters;
+    int _numParameters;
+    JavaString _name;
+    mutable char* _signature;
+    JavaString _returnType;
+    JNIType _JNIReturnType;
+    mutable jmethodID _methodID;
+    bool _isStatic;
+};
+
+class JavaArray : public Array
+{
+public:
+    JavaArray(jobject array, const char* type, PassRefPtr<RootObject>);
+    virtual ~JavaArray();
+
+    RootObject* rootObject() const;
+
+    virtual void setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const;
+    virtual JSValue *valueAt(ExecState *exec, unsigned int index) const;
+    virtual unsigned int getLength() const;
+    
+    jobject javaArray() const { return _array->_instance; }
+
+    static JSValue* convertJObjectToArray (ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject>);
+
+private:
+    RefPtr<JObjectWrapper> _array;
+    unsigned int _length;
+    const char *_type;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/jni/jni_utility.cpp b/WebCore/bridge/jni/jni_utility.cpp
new file mode 100644 (file)
index 0000000..8a8c656
--- /dev/null
@@ -0,0 +1,987 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "jni_utility.h"
+
+#include "list.h"
+#include "jni_runtime.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <dlfcn.h>
+
+namespace KJS {
+
+namespace Bindings {
+
+static jint KJS_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs)
+{
+    static void* javaVMFramework = 0;
+    if (!javaVMFramework)
+        javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY);
+    if (!javaVMFramework)
+        return JNI_ERR;
+
+    static jint(*functionPointer)(JavaVM**, jsize, jsize *) = 0;
+    if (!functionPointer)
+        functionPointer = (jint(*)(JavaVM**, jsize, jsize *))dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs");
+    if (!functionPointer)
+        return JNI_ERR;
+    return functionPointer(vmBuf, bufLen, nVMs);
+}
+
+static JavaVM *jvm = 0;
+
+// Provide the ability for an outside component to specify the JavaVM to use
+// If the jvm value is set, the getJavaVM function below will just return. 
+// In getJNIEnv(), if AttachCurrentThread is called to a VM that is already
+// attached, the result is a no-op.
+void setJavaVM(JavaVM *javaVM)
+{
+    jvm = javaVM;
+}
+
+JavaVM *getJavaVM()
+{
+    if (jvm)
+        return jvm;
+
+    JavaVM *jvmArray[1];
+    jsize bufLen = 1;
+    jsize nJVMs = 0;
+    jint jniError = 0;
+
+    // Assumes JVM is already running ..., one per process
+    jniError = KJS_GetCreatedJavaVMs(jvmArray, bufLen, &nJVMs);
+    if ( jniError == JNI_OK && nJVMs > 0 ) {
+        jvm = jvmArray[0];
+    }
+    else 
+        fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
+        
+    return jvm;
+}
+
+JNIEnv* getJNIEnv()
+{
+    union {
+        JNIEnv* env;
+        void* dummy;
+    } u;
+    jint jniError = 0;
+
+    jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL);
+    if (jniError == JNI_OK)
+        return u.env;
+    else
+        fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
+    return NULL;
+}
+
+static jvalue callJNIMethod (JNIType type, jobject obj, const char *name, const char *sig, va_list args)
+{
+    JavaVM *jvm = getJavaVM();
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+
+    bzero (&result, sizeof(jvalue));
+    if ( obj != NULL && jvm != NULL && env != NULL) {
+        jclass cls = env->GetObjectClass(obj);
+        if ( cls != NULL ) {
+            jmethodID mid = env->GetMethodID(cls, name, sig);
+            if ( mid != NULL )
+            {
+                switch (type) {
+                case void_type:
+                    env->functions->CallVoidMethodV(env, obj, mid, args);
+                    break;
+                case array_type:
+                case object_type:
+                    result.l = env->functions->CallObjectMethodV(env, obj, mid, args);
+                    break;
+                case boolean_type:
+                    result.z = env->functions->CallBooleanMethodV(env, obj, mid, args);
+                    break;
+                case byte_type:
+                    result.b = env->functions->CallByteMethodV(env, obj, mid, args);
+                    break;
+                case char_type:
+                    result.c = env->functions->CallCharMethodV(env, obj, mid, args);
+                    break;
+                case short_type:
+                    result.s = env->functions->CallShortMethodV(env, obj, mid, args);
+                    break;
+                case int_type:
+                    result.i = env->functions->CallIntMethodV(env, obj, mid, args);
+                    break;
+                case long_type:
+                    result.j = env->functions->CallLongMethodV(env, obj, mid, args);
+                    break;
+                case float_type:
+                    result.f = env->functions->CallFloatMethodV(env, obj, mid, args);
+                    break;
+                case double_type:
+                    result.d = env->functions->CallDoubleMethodV(env, obj, mid, args);
+                    break;
+                default:
+                    fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+                }
+            }
+            else
+            {
+                fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj);
+                env->ExceptionDescribe();
+                env->ExceptionClear();
+                fprintf (stderr, "\n");
+            }
+
+            env->DeleteLocalRef(cls);
+        }
+        else {
+            fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj);
+        }
+    }
+
+    return result;
+}
+
+static jvalue callJNIStaticMethod (JNIType type, jclass cls, const char *name, const char *sig, va_list args)
+{
+    JavaVM *jvm = getJavaVM();
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+
+    bzero (&result, sizeof(jvalue));
+    if ( cls != NULL && jvm != NULL && env != NULL) {
+        jmethodID mid = env->GetStaticMethodID(cls, name, sig);
+        if ( mid != NULL )
+        {
+            switch (type) {
+            case void_type:
+                env->functions->CallStaticVoidMethodV(env, cls, mid, args);
+                break;
+            case array_type:
+            case object_type:
+                result.l = env->functions->CallStaticObjectMethodV(env, cls, mid, args);
+                break;
+            case boolean_type:
+                result.z = env->functions->CallStaticBooleanMethodV(env, cls, mid, args);
+                break;
+            case byte_type:
+                result.b = env->functions->CallStaticByteMethodV(env, cls, mid, args);
+                break;
+            case char_type:
+                result.c = env->functions->CallStaticCharMethodV(env, cls, mid, args);
+                break;
+            case short_type:
+                result.s = env->functions->CallStaticShortMethodV(env, cls, mid, args);
+                break;
+            case int_type:
+                result.i = env->functions->CallStaticIntMethodV(env, cls, mid, args);
+                break;
+            case long_type:
+                result.j = env->functions->CallStaticLongMethodV(env, cls, mid, args);
+                break;
+            case float_type:
+                result.f = env->functions->CallStaticFloatMethodV(env, cls, mid, args);
+                break;
+            case double_type:
+                result.d = env->functions->CallStaticDoubleMethodV(env, cls, mid, args);
+                break;
+            default:
+                fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+            }
+        }
+        else
+        {
+            fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, cls);
+            env->ExceptionDescribe();
+            env->ExceptionClear();
+            fprintf (stderr, "\n");
+        }
+    }
+
+    return result;
+}
+
+static jvalue callJNIMethodIDA (JNIType type, jobject obj, jmethodID mid, jvalue *args)
+{
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+    
+    bzero (&result, sizeof(jvalue));
+    if ( obj != NULL && mid != NULL )
+    {
+        switch (type) {
+        case void_type:
+            env->functions->CallVoidMethodA(env, obj, mid, args);
+            break;
+        case array_type:
+        case object_type:
+            result.l = env->functions->CallObjectMethodA(env, obj, mid, args);
+            break;
+        case boolean_type:
+            result.z = env->functions->CallBooleanMethodA(env, obj, mid, args);
+            break;
+        case byte_type:
+            result.b = env->functions->CallByteMethodA(env, obj, mid, args);
+            break;
+        case char_type:
+            result.c = env->functions->CallCharMethodA(env, obj, mid, args);
+            break;
+        case short_type:
+            result.s = env->functions->CallShortMethodA(env, obj, mid, args);
+            break;
+        case int_type:
+            result.i = env->functions->CallIntMethodA(env, obj, mid, args);
+            break;
+        case long_type:
+            result.j = env->functions->CallLongMethodA(env, obj, mid, args);
+            break;
+        case float_type:
+            result.f = env->functions->CallFloatMethodA(env, obj, mid, args);
+            break;
+        case double_type:
+            result.d = env->functions->CallDoubleMethodA(env, obj, mid, args);
+            break;
+        default:
+            fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+        }
+    }
+
+    return result;
+}
+
+static jvalue callJNIMethodA (JNIType type, jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    JavaVM *jvm = getJavaVM();
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+    
+    bzero (&result, sizeof(jvalue));
+    if ( obj != NULL && jvm != NULL && env != NULL) {
+        jclass cls = env->GetObjectClass(obj);
+        if ( cls != NULL ) {
+            jmethodID mid = env->GetMethodID(cls, name, sig);
+            if ( mid != NULL ) {
+                result = callJNIMethodIDA (type, obj, mid, args);
+            }
+            else {
+                fprintf(stderr, "%s: Could not find method: %s\n", __PRETTY_FUNCTION__, name);
+                env->ExceptionDescribe();
+                env->ExceptionClear();
+                fprintf (stderr, "\n");
+            }
+
+            env->DeleteLocalRef(cls);
+        }
+        else {
+            fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
+        }
+    }
+
+    return result;
+}
+
+jmethodID getMethodID (jobject obj, const char *name, const char *sig)
+{
+    JNIEnv *env = getJNIEnv();
+    jmethodID mid = 0;
+        
+    if ( env != NULL) {
+    jclass cls = env->GetObjectClass(obj);
+    if ( cls != NULL ) {
+            mid = env->GetMethodID(cls, name, sig);
+            if (!mid) {
+                env->ExceptionClear();
+                mid = env->GetStaticMethodID(cls, name, sig);
+                if (!mid) {
+                    env->ExceptionClear();
+                }
+            }
+        }
+        env->DeleteLocalRef(cls);
+    }
+    return mid;
+}
+
+
+#define CALL_JNI_METHOD(function_type,obj,name,sig) \
+    va_list args;\
+    va_start (args, sig);\
+    \
+    jvalue result = callJNIMethod(function_type, obj, name, sig, args);\
+    \
+    va_end (args);
+
+#define CALL_JNI_STATIC_METHOD(function_type,cls,name,sig) \
+    va_list args;\
+    va_start (args, sig);\
+    \
+    jvalue result = callJNIStaticMethod(function_type, cls, name, sig, args);\
+    \
+    va_end (args);
+
+void callJNIVoidMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (void_type, obj, name, sig);
+}
+
+jobject callJNIObjectMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (object_type, obj, name, sig);
+    return result.l;
+}
+
+jboolean callJNIBooleanMethod( jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (boolean_type, obj, name, sig);
+    return result.z;
+}
+
+jboolean callJNIStaticBooleanMethod (jclass cls, const char *name, const char *sig, ... )
+{
+    CALL_JNI_STATIC_METHOD (boolean_type, cls, name, sig);
+    return result.z;
+}
+
+jbyte callJNIByteMethod( jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (byte_type, obj, name, sig);
+    return result.b;
+}
+
+jchar callJNICharMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (char_type, obj, name, sig);
+    return result.c;
+}
+
+jshort callJNIShortMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (short_type, obj, name, sig);
+    return result.s;
+}
+
+jint callJNIIntMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (int_type, obj, name, sig);
+    return result.i;
+}
+
+jlong callJNILongMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (long_type, obj, name, sig);
+    return result.j;
+}
+
+jfloat callJNIFloatMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (float_type, obj, name, sig);
+    return result.f;
+}
+
+jdouble callJNIDoubleMethod (jobject obj, const char *name, const char *sig, ... )
+{
+    CALL_JNI_METHOD (double_type, obj, name, sig);
+    return result.d;
+}
+
+void callJNIVoidMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (void_type, obj, name, sig, args);
+}
+
+jobject callJNIObjectMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (object_type, obj, name, sig, args);
+    return result.l;
+}
+
+jbyte callJNIByteMethodA ( jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (byte_type, obj, name, sig, args);
+    return result.b;
+}
+
+jchar callJNICharMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (char_type, obj, name, sig, args);
+    return result.c;
+}
+
+jshort callJNIShortMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (short_type, obj, name, sig, args);
+    return result.s;
+}
+
+jint callJNIIntMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (int_type, obj, name, sig, args);
+    return result.i;
+}
+
+jlong callJNILongMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (long_type, obj, name, sig, args);
+    return result.j;
+}
+
+jfloat callJNIFloatMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA  (float_type, obj, name, sig, args);
+    return result.f;
+}
+
+jdouble callJNIDoubleMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (double_type, obj, name, sig, args);
+    return result.d;
+}
+
+jboolean callJNIBooleanMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+    jvalue result = callJNIMethodA (boolean_type, obj, name, sig, args);
+    return result.z;
+}
+
+void callJNIVoidMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (void_type, obj, methodID, args);
+}
+
+jobject callJNIObjectMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (object_type, obj, methodID, args);
+    return result.l;
+}
+
+jbyte callJNIByteMethodIDA ( jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (byte_type, obj, methodID, args);
+    return result.b;
+}
+
+jchar callJNICharMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (char_type, obj, methodID, args);
+    return result.c;
+}
+
+jshort callJNIShortMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (short_type, obj, methodID, args);
+    return result.s;
+}
+
+jint callJNIIntMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (int_type, obj, methodID, args);
+    return result.i;
+}
+
+jlong callJNILongMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (long_type, obj, methodID, args);
+    return result.j;
+}
+
+jfloat callJNIFloatMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA  (float_type, obj, methodID, args);
+    return result.f;
+}
+
+jdouble callJNIDoubleMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (double_type, obj, methodID, args);
+    return result.d;
+}
+
+jboolean callJNIBooleanMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+    jvalue result = callJNIMethodIDA (boolean_type, obj, methodID, args);
+    return result.z;
+}
+
+const char *getCharactersFromJString (jstring aJString)
+{
+    return getCharactersFromJStringInEnv (getJNIEnv(), aJString);
+}
+
+void releaseCharactersForJString (jstring aJString, const char *s)
+{
+    releaseCharactersForJStringInEnv (getJNIEnv(), aJString, s);
+}
+
+const char *getCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
+{
+    jboolean isCopy;
+    const char *s = env->GetStringUTFChars((jstring)aJString, &isCopy);
+    if (!s) {
+        env->ExceptionDescribe();
+        env->ExceptionClear();
+                fprintf (stderr, "\n");
+    }
+    return s;
+}
+
+void releaseCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const char *s)
+{
+    env->ReleaseStringUTFChars (aJString, s);
+}
+
+const jchar *getUCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
+{
+    jboolean isCopy;
+    const jchar *s = env->GetStringChars((jstring)aJString, &isCopy);
+    if (!s) {
+        env->ExceptionDescribe();
+        env->ExceptionClear();
+                fprintf (stderr, "\n");
+    }
+    return s;
+}
+
+void releaseUCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const jchar *s)
+{
+    env->ReleaseStringChars (aJString, s);
+}
+
+JNIType JNITypeFromClassName(const char *name)
+{
+    JNIType type;
+    
+    if (strcmp("byte",name) == 0)
+        type = byte_type;
+    else if (strcmp("short",name) == 0)
+        type = short_type;
+    else if (strcmp("int",name) == 0)
+        type = int_type;
+    else if (strcmp("long",name) == 0)
+        type = long_type;
+    else if (strcmp("float",name) == 0)
+        type = float_type;
+    else if (strcmp("double",name) == 0)
+        type = double_type;
+    else if (strcmp("char",name) == 0)
+        type = char_type;
+    else if (strcmp("boolean",name) == 0)
+        type = boolean_type;
+    else if (strcmp("void",name) == 0)
+        type = void_type;
+    else if ('[' == name[0]) 
+        type = array_type;
+    else
+        type = object_type;
+        
+    return type;
+}
+
+const char *signatureFromPrimitiveType(JNIType type)
+{
+    switch (type){
+        case void_type: 
+            return "V";
+        
+        case array_type:
+            return "[";
+        
+        case object_type:
+            return "L";
+        
+        case boolean_type:
+            return "Z";
+        
+        case byte_type:
+            return "B";
+            
+        case char_type:
+            return "C";
+        
+        case short_type:
+            return "S";
+        
+        case int_type:
+            return "I";
+        
+        case long_type:
+            return "J";
+        
+        case float_type:
+            return "F";
+        
+        case double_type:
+            return "D";
+
+        case invalid_type:
+        default:
+        break;
+    }
+    return "";
+}
+
+JNIType JNITypeFromPrimitiveType(char type)
+{
+    switch (type){
+        case 'V': 
+            return void_type;
+        
+        case 'L':
+            return object_type;
+            
+        case '[':
+            return array_type;
+        
+        case 'Z':
+            return boolean_type;
+        
+        case 'B':
+            return byte_type;
+            
+        case 'C':
+            return char_type;
+        
+        case 'S':
+            return short_type;
+        
+        case 'I':
+            return int_type;
+        
+        case 'J':
+            return long_type;
+        
+        case 'F':
+            return float_type;
+        
+        case 'D':
+            return double_type;
+
+        default:
+        break;
+    }
+    return invalid_type;
+}
+
+jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *signature)
+{
+    JavaVM *jvm = getJavaVM();
+    JNIEnv *env = getJNIEnv();
+    jvalue result;
+
+    bzero (&result, sizeof(jvalue));
+    if ( obj != NULL && jvm != NULL && env != NULL) {
+        jclass cls = env->GetObjectClass(obj);
+        if ( cls != NULL ) {
+            jfieldID field = env->GetFieldID(cls, name, signature);
+            if ( field != NULL ) {
+                switch (type) {
+                case array_type:
+                case object_type:
+                    result.l = env->functions->GetObjectField(env, obj, field);
+                    break;
+                case boolean_type:
+                    result.z = env->functions->GetBooleanField(env, obj, field);
+                    break;
+                case byte_type:
+                    result.b = env->functions->GetByteField(env, obj, field);
+                    break;
+                case char_type:
+                    result.c = env->functions->GetCharField(env, obj, field);
+                    break;
+                case short_type:
+                    result.s = env->functions->GetShortField(env, obj, field);
+                    break;
+                case int_type:
+                    result.i = env->functions->GetIntField(env, obj, field);
+                    break;
+                case long_type:
+                    result.j = env->functions->GetLongField(env, obj, field);
+                    break;
+                case float_type:
+                    result.f = env->functions->GetFloatField(env, obj, field);
+                    break;
+                case double_type:
+                    result.d = env->functions->GetDoubleField(env, obj, field);
+                    break;
+                default:
+                    fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+                }
+            }
+            else
+            {
+                fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name);
+                env->ExceptionDescribe();
+                env->ExceptionClear();
+                fprintf (stderr, "\n");
+            }
+
+            env->DeleteLocalRef(cls);
+        }
+        else {
+            fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
+        }
+    }
+
+    return result;
+}
+
+static jobject convertArrayInstanceToJavaArray(ExecState *exec, JSValue *value, const char *javaClassName) {
+
+    ASSERT(JSLock::lockCount() > 0);
+    
+    JNIEnv *env = getJNIEnv();
+    // As JS Arrays can contain a mixture of objects, assume we can convert to
+    // the requested Java Array type requested, unless the array type is some object array
+    // other than a string.
+    ArrayInstance *jsArray = static_cast<ArrayInstance *>(value);
+    unsigned length = jsArray->getLength();
+    jobjectArray jarray = 0;
+    
+    // Build the correct array type
+    switch (JNITypeFromPrimitiveType(javaClassName[1])) { 
+        case object_type: {
+        // Only support string object types
+        if (0 == strcmp("[Ljava.lang.String;", javaClassName)) {
+            jarray = (jobjectArray)env->NewObjectArray(length,
+                env->FindClass("java/lang/String"),
+                env->NewStringUTF(""));
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                UString stringValue = item->toString(exec);
+                env->SetObjectArrayElement(jarray,i,
+                    env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size()));
+                }
+            }
+            break;
+        }
+        
+        case boolean_type: {
+            jarray = (jobjectArray)env->NewBooleanArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jboolean value = (jboolean)item->toNumber(exec);
+                env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+        
+        case byte_type: {
+            jarray = (jobjectArray)env->NewByteArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jbyte value = (jbyte)item->toNumber(exec);
+                env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+
+        case char_type: {
+            jarray = (jobjectArray)env->NewCharArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                UString stringValue = item->toString(exec);
+                jchar value = 0;
+                if (stringValue.size() > 0)
+                    value = ((const jchar*)stringValue.data())[0];
+                env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+
+        case short_type: {
+            jarray = (jobjectArray)env->NewShortArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jshort value = (jshort)item->toNumber(exec);
+                env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+
+        case int_type: {
+            jarray = (jobjectArray)env->NewIntArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jint value = (jint)item->toNumber(exec);
+                env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+
+        case long_type: {
+            jarray = (jobjectArray)env->NewLongArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jlong value = (jlong)item->toNumber(exec);
+                env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+
+        case float_type: {
+            jarray = (jobjectArray)env->NewFloatArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jfloat value = (jfloat)item->toNumber(exec);
+                env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+    
+        case double_type: {
+            jarray = (jobjectArray)env->NewDoubleArray(length);
+            for(unsigned i = 0; i < length; i++) {
+                JSValue* item = jsArray->getItem(i);
+                jdouble value = (jdouble)item->toNumber(exec);
+                env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value);
+            }
+            break;
+        }
+        
+        case array_type: // don't handle embedded arrays
+        case void_type: // Don't expect arrays of void objects
+        case invalid_type: // Array of unknown objects
+            break;
+    }
+    
+    // if it was not one of the cases handled, then null is returned
+    return jarray;
+}
+
+
+jvalue convertValueToJValue (ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName)
+{
+    JSLock lock;
+    
+    jvalue result;
+   
+    switch (_JNIType){
+        case array_type:
+        case object_type: {
+            result.l = (jobject)0;
+            
+            // First see if we have a Java instance.
+            if (value->isObject()){
+                JSObject *objectImp = static_cast<JSObject*>(value);
+                if (objectImp->classInfo() == &RuntimeObjectImp::info) {
+                    RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value);
+                    JavaInstance *instance = static_cast<JavaInstance*>(imp->getInternalInstance());
+                    if (instance)
+                        result.l = instance->javaInstance();
+                }
+                else if (objectImp->classInfo() == &RuntimeArray::info) {
+                // Input is a JavaScript Array that was originally created from a Java Array
+                    RuntimeArray *imp = static_cast<RuntimeArray *>(value);
+                    JavaArray *array = static_cast<JavaArray*>(imp->getConcreteArray());
+                    result.l = array->javaArray();
+                } 
+                else if (objectImp->classInfo() == &ArrayInstance::info) {
+                    // Input is a Javascript Array. We need to create it to a Java Array.
+                    result.l = convertArrayInstanceToJavaArray(exec, value, javaClassName);
+                }
+            }
+            
+            // Now convert value to a string if the target type is a java.lang.string, and we're not
+            // converting from a Null.
+            if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) {
+#ifdef CONVERT_NULL_TO_EMPTY_STRING
+                if (value->isNull()) {
+                    JNIEnv *env = getJNIEnv();
+                    jchar buf[2];
+                    jobject javaString = env->functions->NewString (env, buf, 0);
+                    result.l = javaString;
+                }
+                else 
+#else
+                if (!value->isNull())
+#endif
+                {
+                    UString stringValue = value->toString(exec);
+                    JNIEnv *env = getJNIEnv();
+                    jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size());
+                    result.l = javaString;
+                }
+            } else if (result.l == 0) 
+                bzero (&result, sizeof(jvalue)); // Handle it the same as a void case
+        }
+        break;
+        
+        case boolean_type: {
+            result.z = (jboolean)value->toNumber(exec);
+        }
+        break;
+            
+        case byte_type: {
+            result.b = (jbyte)value->toNumber(exec);
+        }
+        break;
+        
+        case char_type: {
+            result.c = (jchar)value->toNumber(exec);
+        }
+        break;
+
+        case short_type: {
+            result.s = (jshort)value->toNumber(exec);
+        }
+        break;
+
+        case int_type: {
+            result.i = (jint)value->toNumber(exec);
+        }
+        break;
+
+        case long_type: {
+            result.j = (jlong)value->toNumber(exec);
+        }
+        break;
+
+        case float_type: {
+            result.f = (jfloat)value->toNumber(exec);
+        }
+        break;
+
+        case double_type: {
+            result.d = (jdouble)value->toNumber(exec);
+        }
+        break;
+            
+        break;
+
+        case invalid_type:
+        default:
+        case void_type: {
+            bzero (&result, sizeof(jvalue));
+        }
+        break;
+    }
+    return result;
+}
+
+}  // end of namespace Bindings
+
+} // end of namespace KJS
diff --git a/WebCore/bridge/jni/jni_utility.h b/WebCore/bridge/jni/jni_utility.h
new file mode 100644 (file)
index 0000000..69aa739
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+#ifndef _JNI_UTILITY_H_
+#define _JNI_UTILITY_H_
+
+#include <list.h>
+
+#include <JavaVM/jni.h>
+
+// The order of these items can not be modified as they are tightly
+// bound with the JVM on Mac OSX. If new types need to be added, they
+// should be added to the end. It is used in jni_obc.mm when calling
+// through to the JVM. Newly added items need to be made compatible
+// in that file.
+typedef enum {
+    invalid_type = 0,
+    void_type,
+    object_type,
+    boolean_type,
+    byte_type,
+    char_type,
+    short_type,
+    int_type,
+    long_type,
+    float_type,
+    double_type,
+    array_type
+} JNIType;
+
+namespace KJS {
+
+namespace Bindings {
+
+class JavaParameter;
+
+const char *getCharactersFromJString(jstring aJString);
+void releaseCharactersForJString(jstring aJString, const char *s);
+
+const char *getCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
+void releaseCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const char *s);
+const jchar *getUCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
+void releaseUCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const jchar *s);
+
+JNIType JNITypeFromClassName(const char *name);
+JNIType JNITypeFromPrimitiveType(char type);
+const char *signatureFromPrimitiveType(JNIType type);
+
+jvalue convertValueToJValue(ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName);
+
+jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature);
+
+jmethodID getMethodID(jobject obj, const char *name, const char *sig);
+
+jobject callJNIObjectMethod(jobject obj, const char *name, const char *sig, ... );
+void callJNIVoidMethod(jobject obj, const char *name, const char *sig, ... );
+jboolean callJNIBooleanMethod(jobject obj, const char *name, const char *sig, ... );
+jboolean callJNIStaticBooleanMethod(jclass cls, const char *name, const char *sig, ... );
+jbyte callJNIByteMethod(jobject obj, const char *name, const char *sig, ... );
+jchar callJNICharMethod(jobject obj, const char *name, const char *sig, ... );
+jshort callJNIShortMethod(jobject obj, const char *name, const char *sig, ... );
+jint callJNIIntMethod(jobject obj, const char *name, const char *sig, ... );
+jlong callJNILongMethod(jobject obj, const char *name, const char *sig, ... );
+jfloat callJNIFloatMethod(jobject obj, const char *name, const char *sig, ... );
+jdouble callJNIDoubleMethod(jobject obj, const char *name, const char *sig, ... );
+
+jobject callJNIObjectMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+void callJNIVoidMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jboolean callJNIBooleanMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jbyte callJNIByteMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jchar callJNICharMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jshort callJNIShortMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jint callJNIIntMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jlong callJNILongMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jfloat callJNIFloatMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jdouble callJNIDoubleMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+
+jobject callJNIObjectMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+void callJNIVoidMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jboolean callJNIBooleanMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jbyte callJNIByteMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jchar callJNICharMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jshort callJNIShortMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jint callJNIIntMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jlong callJNILongMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jfloat callJNIFloatMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jdouble callJNIDoubleMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+
+JavaVM *getJavaVM();
+void    setJavaVM(JavaVM *javaVM);
+JNIEnv *getJNIEnv();
+
+bool dispatchJNICall(const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char *callingURL, JSValue *&exceptionDescription);
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif // _JNI_UTILITY_H_
diff --git a/WebCore/bridge/make_testbindings b/WebCore/bridge/make_testbindings
new file mode 100755 (executable)
index 0000000..1f528fe
--- /dev/null
@@ -0,0 +1,2 @@
+cc -g -o testbindingsM testbindings.mm -I../kjs -F$SYMROOTS -framework JavaScriptCore -framework Foundation -lstdc++
+cc -g -o testbindingsC testbindings.cpp -I../kjs -F$SYMROOTS -framework JavaScriptCore -framework Foundation -lstdc++
diff --git a/WebCore/bridge/npapi.h b/WebCore/bridge/npapi.h
new file mode 100644 (file)
index 0000000..ba8b6c7
--- /dev/null
@@ -0,0 +1,714 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+ /*
+  *  Netscape client plug-in API spec
+  */
+
+#ifndef _NPAPI_H_
+#define _NPAPI_H_
+
+#ifdef INCLUDE_JAVA
+#include "jri.h"                /* Java Runtime Interface */
+#else
+#define jref    void *
+#define JRIEnv  void
+#endif
+
+#ifdef _WIN32
+#    ifndef XP_WIN
+#        define XP_WIN 1
+#    endif /* XP_WIN */
+#endif /* _WIN32 */
+
+#ifdef __MWERKS__
+#    define _declspec __declspec
+#    ifdef macintosh
+#        ifndef XP_MAC
+#            define XP_MAC 1
+#        endif /* XP_MAC */
+#    endif /* macintosh */
+#    ifdef __INTEL__
+#        undef NULL
+#        ifndef XP_WIN
+#            define XP_WIN 1
+#        endif /* __INTEL__ */
+#    endif /* XP_PC */
+#endif /* __MWERKS__ */
+
+#if defined(__APPLE_CC__) && !defined(__MACOS_CLASSIC__) && !defined(XP_UNIX)
+#   define XP_MACOSX
+#endif
+
+#ifdef XP_MAC
+    #include <Quickdraw.h>
+    #include <Events.h>
+#endif
+
+#ifdef XP_MACOSX
+    #include <Carbon/Carbon.h>
+    #include <ApplicationServices/ApplicationServices.h>
+    #include <OpenGL/OpenGL.h>
+#endif
+
+#ifdef XP_UNIX
+    #include <X11/Xlib.h>
+    #include <X11/Xutil.h>
+    #include <stdio.h>
+#endif
+
+#ifdef XP_WIN
+    #include <windows.h>
+#endif
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#error 64-bit Netscape plug-ins are not supported on Mac OS X
+#endif
+
+/*----------------------------------------------------------------------*/
+/*             Plugin Version Constants                                 */
+/*----------------------------------------------------------------------*/
+
+#define NP_VERSION_MAJOR 0
+#define NP_VERSION_MINOR 18
+
+
+
+/*----------------------------------------------------------------------*/
+/*             Definition of Basic Types                                */
+/*----------------------------------------------------------------------*/
+
+#ifndef _UINT16
+#define _UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef _UINT32
+#define _UINT32
+#ifdef __LP64__
+typedef unsigned int uint32;
+#else /* __LP64__ */
+typedef unsigned long uint32;
+#endif /* __LP64__ */
+#endif
+
+#ifndef _INT16
+#define _INT16
+typedef short int16;
+#endif
+
+#ifndef _INT32
+#define _INT32
+#ifdef __LP64__
+typedef int int32;
+#else /* __LP64__ */
+typedef long int32;
+#endif /* __LP64__ */
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef NULL
+#define NULL (0L)
+#endif
+
+typedef unsigned char    NPBool;
+typedef int16            NPError;
+typedef int16            NPReason;
+typedef char*            NPMIMEType;
+
+
+
+/*----------------------------------------------------------------------*/
+/*             Structures and definitions             */
+/*----------------------------------------------------------------------*/
+
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=mac68k
+#endif
+#endif /* __LP64__ */
+
+/*
+ *  NPP is a plug-in's opaque instance handle
+ */
+typedef struct _NPP
+{
+    void*    pdata;            /* plug-in private data */
+    void*    ndata;            /* netscape private data */
+} NPP_t;
+
+typedef NPP_t*    NPP;
+
+
+typedef struct _NPStream
+{
+    void*        pdata;        /* plug-in private data */
+    void*        ndata;        /* netscape private data */
+    const char*  url;
+    uint32       end;
+    uint32       lastmodified;
+    void*        notifyData;
+    const char*  headers;      /* Response headers from host.
+                                * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
+                                * Used for HTTP only; NULL for non-HTTP.
+                                * Available from NPP_NewStream onwards.
+                                * Plugin should copy this data before storing it.
+                                * Includes HTTP status line and all headers,
+                                * preferably verbatim as received from server,
+                                * headers formatted as in HTTP ("Header: Value"),
+                                * and newlines (\n, NOT \r\n) separating lines.
+                                * Terminated by \n\0 (NOT \n\n\0). */
+} NPStream;
+
+
+typedef struct _NPByteRange
+{
+    int32      offset;         /* negative offset means from the end */
+    uint32     length;
+    struct _NPByteRange* next;
+} NPByteRange;
+
+
+typedef struct _NPSavedData
+{
+    int32    len;
+    void*    buf;
+} NPSavedData;
+
+
+typedef struct _NPRect
+{
+    uint16    top;
+    uint16    left;
+    uint16    bottom;
+    uint16    right;
+} NPRect;
+
+
+#ifdef XP_UNIX
+/*
+ * Unix specific structures and definitions
+ */
+
+/*
+ * Callback Structures.
+ *
+ * These are used to pass additional platform specific information.
+ */
+enum {
+    NP_SETWINDOW = 1,
+    NP_PRINT
+};
+
+typedef struct
+{
+    int32        type;
+} NPAnyCallbackStruct;
+
+typedef struct
+{
+    int32           type;
+    Display*        display;
+    Visual*         visual;
+    Colormap        colormap;
+    unsigned int    depth;
+} NPSetWindowCallbackStruct;
+
+typedef struct
+{
+    int32            type;
+    FILE*            fp;
+} NPPrintCallbackStruct;
+
+#endif /* XP_UNIX */
+
+/*
+ *   The following masks are applied on certain platforms to NPNV and 
+ *   NPPV selectors that pass around pointers to COM interfaces. Newer 
+ *   compilers on some platforms may generate vtables that are not 
+ *   compatible with older compilers. To prevent older plugins from 
+ *   not understanding a new browser's ABI, these masks change the 
+ *   values of those selectors on those platforms. To remain backwards
+ *   compatible with differenet versions of the browser, plugins can 
+ *   use these masks to dynamically determine and use the correct C++
+ *   ABI that the browser is expecting. This does not apply to Windows 
+ *   as Microsoft's COM ABI will likely not change.
+ */
+
+#define NP_ABI_GCC3_MASK  0x10000000
+/*
+ *   gcc 3.x generated vtables on UNIX and OSX are incompatible with 
+ *   previous compilers.
+ */
+#if (defined (XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
+#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_GCC3 0
+#endif
+
+#define NP_ABI_MACHO_MASK 0x01000000
+/*
+ *   On OSX, the Mach-O executable format is significantly
+ *   different than CFM. In addition to having a different
+ *   C++ ABI, it also has has different C calling convention.
+ *   You must use glue code when calling between CFM and
+ *   Mach-O C functions. 
+ */
+#if (defined(TARGET_RT_MAC_MACHO))
+#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_MACHO 0
+#endif
+
+
+#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
+
+/*
+ * List of variable names for which NPP_GetValue shall be implemented
+ */
+typedef enum {
+    NPPVpluginNameString = 1,
+    NPPVpluginDescriptionString,
+    NPPVpluginWindowBool,
+    NPPVpluginTransparentBool,
+
+    NPPVjavaClass,                /* Not implemented in WebKit */
+    NPPVpluginWindowSize,         /* Not implemented in WebKit */
+    NPPVpluginTimerInterval,      /* Not implemented in WebKit */
+
+    NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), /* Not implemented in WebKit */
+    NPPVpluginScriptableIID = 11, /* Not implemented in WebKit */
+
+    /* 12 and over are available on Mozilla builds starting with 0.9.9 */
+    NPPVjavascriptPushCallerBool = 12,  /* Not implemented in WebKit */
+    NPPVpluginKeepLibraryInMemory = 13, /* Not implemented in WebKit */
+    NPPVpluginNeedsXEmbed         = 14, /* Not implemented in WebKit */
+
+    /* Get the NPObject for scripting the plugin. */
+    NPPVpluginScriptableNPObject  = 15,
+
+    /* Get the plugin value (as \0-terminated UTF-8 string data) for
+     * form submission if the plugin is part of a form. Use
+     * NPN_MemAlloc() to allocate memory for the string data.
+     */
+    NPPVformValue = 16,    /* Not implemented in WebKit */
+#ifdef XP_MACOSX
+    /* Used for negotiating drawing models */
+    NPPVpluginDrawingModel = 1000
+#endif
+} NPPVariable;
+
+/*
+ * List of variable names for which NPN_GetValue is implemented by Mozilla
+ */
+typedef enum {
+    NPNVxDisplay = 1,
+    NPNVxtAppContext,
+    NPNVnetscapeWindow,
+    NPNVjavascriptEnabledBool,
+    NPNVasdEnabledBool,
+    NPNVisOfflineBool,
+
+    /* 10 and over are available on Mozilla builds starting with 0.9.4 */
+    NPNVserviceManager = (10 | NP_ABI_MASK),  /* Not implemented in WebKit */
+    NPNVDOMElement     = (11 | NP_ABI_MASK),  /* Not implemented in WebKit */
+    NPNVDOMWindow      = (12 | NP_ABI_MASK),  /* Not implemented in WebKit */
+    NPNVToolkit        = (13 | NP_ABI_MASK),  /* Not implemented in WebKit */
+    NPNVSupportsXEmbedBool = 14,              /* Not implemented in WebKit */
+
+    /* Get the NPObject wrapper for the browser window. */
+    NPNVWindowNPObject = 15,
+
+    /* Get the NPObject wrapper for the plugins DOM element. */
+    NPNVPluginElementNPObject
+
+#ifdef XP_MACOSX
+    , NPNVpluginDrawingModel = 1000 /* The NPDrawingModel specified by the plugin */
+
+#ifndef NP_NO_QUICKDRAW
+    , NPNVsupportsQuickDrawBool = 2000 /* TRUE if the browser supports the QuickDraw drawing model */
+#endif
+    , NPNVsupportsCoreGraphicsBool = 2001 /* TRUE if the browser supports the CoreGraphics drawing model */
+    , NPNVsupportsOpenGLBool = 2002 /* TRUE if the browser supports the OpenGL drawing model (CGL on Mac) */
+#endif /* XP_MACOSX */
+} NPNVariable;
+
+/*
+ * The type of a NPWindow - it specifies the type of the data structure
+ * returned in the window field.
+ */
+typedef enum {
+    NPWindowTypeWindow = 1,
+    NPWindowTypeDrawable
+} NPWindowType;
+
+#ifdef XP_MACOSX
+
+/*
+ * The drawing model for a Mac OS X plugin.  These are the possible values for the NPNVpluginDrawingModel variable.
+ */
+typedef enum {
+#ifndef NP_NO_QUICKDRAW
+    NPDrawingModelQuickDraw = 0,
+#endif
+    NPDrawingModelCoreGraphics = 1,
+    NPDrawingModelOpenGL = 2
+} NPDrawingModel;
+
+#endif
+
+typedef struct _NPWindow
+{
+    void*    window;     /* Platform specific window handle */
+    int32    x;            /* Position of top left corner relative */
+    int32    y;            /*    to a netscape page.                    */
+    uint32    width;        /* Maximum window size */
+    uint32    height;
+    NPRect    clipRect;    /* Clipping rectangle in port coordinates */
+                        /* Used by MAC only.              */
+#ifdef XP_UNIX
+    void *    ws_info;    /* Platform-dependent additonal data */
+#endif /* XP_UNIX */
+    NPWindowType type;    /* Is this a window or a drawable? */
+} NPWindow;
+
+
+typedef struct _NPFullPrint
+{
+    NPBool    pluginPrinted;    /* Set TRUE if plugin handled fullscreen */
+                            /*    printing                             */
+    NPBool    printOne;        /* TRUE if plugin should print one copy  */
+                            /*    to default printer                     */
+    void*    platformPrint;    /* Platform-specific printing info */
+} NPFullPrint;
+
+typedef struct _NPEmbedPrint
+{
+    NPWindow    window;
+    void*    platformPrint;    /* Platform-specific printing info */
+} NPEmbedPrint;
+
+typedef struct _NPPrint
+{
+    uint16    mode;                        /* NP_FULL or NP_EMBED */
+    union
+    {
+        NPFullPrint     fullPrint;        /* if mode is NP_FULL */
+        NPEmbedPrint    embedPrint;        /* if mode is NP_EMBED */
+    } print;
+} NPPrint;
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+typedef EventRecord    NPEvent;
+#elif defined(XP_WIN)
+typedef struct _NPEvent
+{
+    uint16   event;
+    uint32   wParam;
+    uint32   lParam;
+} NPEvent;
+#elif defined (XP_UNIX)
+typedef XEvent NPEvent;
+#else
+typedef void*            NPEvent;
+#endif /* XP_MAC */
+
+#if defined(XP_MAC)
+typedef RgnHandle NPRegion;
+#elif defined(XP_MACOSX)
+/* 
+ * NPRegion's type depends on the drawing model specified by the plugin (see NPNVpluginDrawingModel).
+ * NPQDRegion represents a QuickDraw RgnHandle and is used with the QuickDraw drawing model.
+ * NPCGRegion repesents a graphical region when using any other drawing model.
+ */
+typedef void *NPRegion;
+#ifndef NP_NO_QUICKDRAW
+typedef RgnHandle NPQDRegion;
+#endif
+typedef CGPathRef NPCGRegion;
+#elif defined(XP_WIN)
+typedef HRGN NPRegion;
+#elif defined(XP_UNIX)
+typedef Region NPRegion;
+#else
+typedef void *NPRegion;
+#endif /* XP_MAC */
+
+#ifdef XP_MACOSX
+
+/* 
+ * NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
+ * as its drawing model.
+ */
+
+typedef struct NP_CGContext
+{
+    CGContextRef context;
+    WindowRef window;
+} NP_CGContext;
+
+/* 
+ * NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
+ * drawing model.
+ */
+
+typedef struct NP_GLContext
+{
+    CGLContextObj context;
+    WindowRef window;
+} NP_GLContext;
+
+#endif /* XP_MACOSX */
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+
+/*
+ *  Mac-specific structures and definitions.
+ */
+
+#ifndef NP_NO_QUICKDRAW
+
+/* 
+ * NP_Port is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelQuickDraw as its
+ * drawing model, or the plugin does not specify a drawing model.
+ *
+ * It is not recommended that new plugins use NPDrawingModelQuickDraw or NP_Port, as QuickDraw has been
+ * deprecated in Mac OS X 10.5.  CoreGraphics is the preferred drawing API.
+ *
+ * NP_Port is not available in 64-bit.
+ */
+typedef struct NP_Port
+{
+    CGrafPtr     port;        /* Grafport */
+    int32        portx;        /* position inside the topmost window */
+    int32        porty;
+} NP_Port;
+
+#endif /* NP_NO_QUICKDRAW */
+
+/*
+ *  Non-standard event types that can be passed to HandleEvent
+ */
+#define getFocusEvent        (osEvt + 16)
+#define loseFocusEvent        (osEvt + 17)
+#define adjustCursorEvent   (osEvt + 18)
+
+#endif /* XP_MAC */
+
+
+/*
+ * Values for mode passed to NPP_New:
+ */
+#define NP_EMBED        1
+#define NP_FULL         2
+
+/*
+ * Values for stream type passed to NPP_NewStream:
+ */
+#define NP_NORMAL        1
+#define NP_SEEK         2
+#define NP_ASFILE        3
+#define NP_ASFILEONLY        4
+
+#define NP_MAXREADY    (((unsigned)(~0)<<1)>>1)
+
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=reset
+#endif
+#endif /* __LP64__ */
+
+
+/*----------------------------------------------------------------------*/
+/*             Error and Reason Code definitions            */
+/*----------------------------------------------------------------------*/
+
+/*
+ *    Values of type NPError:
+ */
+#define NPERR_BASE                            0
+#define NPERR_NO_ERROR                        (NPERR_BASE + 0)
+#define NPERR_GENERIC_ERROR                    (NPERR_BASE + 1)
+#define NPERR_INVALID_INSTANCE_ERROR        (NPERR_BASE + 2)
+#define NPERR_INVALID_FUNCTABLE_ERROR        (NPERR_BASE + 3)
+#define NPERR_MODULE_LOAD_FAILED_ERROR        (NPERR_BASE + 4)
+#define NPERR_OUT_OF_MEMORY_ERROR            (NPERR_BASE + 5)
+#define NPERR_INVALID_PLUGIN_ERROR            (NPERR_BASE + 6)
+#define NPERR_INVALID_PLUGIN_DIR_ERROR        (NPERR_BASE + 7)
+#define NPERR_INCOMPATIBLE_VERSION_ERROR    (NPERR_BASE + 8)
+#define NPERR_INVALID_PARAM                (NPERR_BASE + 9)
+#define NPERR_INVALID_URL                    (NPERR_BASE + 10)
+#define NPERR_FILE_NOT_FOUND                (NPERR_BASE + 11)
+#define NPERR_NO_DATA                        (NPERR_BASE + 12)
+#define NPERR_STREAM_NOT_SEEKABLE            (NPERR_BASE + 13)
+
+/*
+ *    Values of type NPReason:
+ */
+#define NPRES_BASE                0
+#define NPRES_DONE                    (NPRES_BASE + 0)
+#define NPRES_NETWORK_ERR            (NPRES_BASE + 1)
+#define NPRES_USER_BREAK            (NPRES_BASE + 2)
+
+/*
+ *      Don't use these obsolete error codes any more.
+ */
+#define NP_NOERR  NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
+#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
+#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
+
+/*
+ * Version feature information
+ */
+#define NPVERS_HAS_STREAMOUTPUT     8
+#define NPVERS_HAS_NOTIFICATION     9
+#define NPVERS_HAS_LIVECONNECT        9
+#define NPVERS_WIN16_HAS_LIVECONNECT    9
+#define NPVERS_68K_HAS_LIVECONNECT    11
+#define NPVERS_HAS_WINDOWLESS       11
+#define NPVERS_HAS_XPCONNECT_SCRIPTING    13  /* Not implemented in WebKit */
+#define NPVERS_HAS_NPRUNTIME_SCRIPTING    14
+#define NPVERS_HAS_FORM_VALUES            15  /* Not implemented in WebKit; see bug 13061 */
+#define NPVERS_HAS_POPUPS_ENABLED_STATE   16  /* Not implemented in WebKit */
+#define NPVERS_HAS_RESPONSE_HEADERS       17
+#define NPVERS_HAS_NPOBJECT_ENUM          18
+
+
+/*----------------------------------------------------------------------*/
+/*             Function Prototypes                */
+/*----------------------------------------------------------------------*/
+
+#if defined(_WINDOWS) && !defined(WIN32)
+#define NP_LOADDS  _loadds
+#else
+#define NP_LOADDS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * NPP_* functions are provided by the plugin and called by the navigator.
+ */
+
+#ifdef XP_UNIX
+char*                    NPP_GetMIMEDescription(void);
+#endif /* XP_UNIX */
+
+NPError     NPP_Initialize(void);
+void        NPP_Shutdown(void);
+NPError     NP_LOADDS    NPP_New(NPMIMEType pluginType, NPP instance,
+                                uint16 mode, int16 argc, char* argn[],
+                                char* argv[], NPSavedData* saved);
+NPError     NP_LOADDS    NPP_Destroy(NPP instance, NPSavedData** save);
+NPError     NP_LOADDS    NPP_SetWindow(NPP instance, NPWindow* window);
+NPError     NP_LOADDS    NPP_NewStream(NPP instance, NPMIMEType type,
+                                      NPStream* stream, NPBool seekable,
+                                      uint16* stype);
+NPError     NP_LOADDS    NPP_DestroyStream(NPP instance, NPStream* stream,
+                                          NPReason reason);
+int32        NP_LOADDS    NPP_WriteReady(NPP instance, NPStream* stream);
+int32        NP_LOADDS    NPP_Write(NPP instance, NPStream* stream, int32 offset,
+                                  int32 len, void* buffer);
+void        NP_LOADDS    NPP_StreamAsFile(NPP instance, NPStream* stream,
+                                         const char* fname);
+void        NP_LOADDS    NPP_Print(NPP instance, NPPrint* platformPrint);
+int16            NPP_HandleEvent(NPP instance, void* event);
+void        NP_LOADDS    NPP_URLNotify(NPP instance, const char* url,
+                                      NPReason reason, void* notifyData);
+jref        NP_LOADDS            NPP_GetJavaClass(void);
+NPError     NPP_GetValue(NPP instance, NPPVariable variable,
+                                     void *value);
+NPError     NPP_SetValue(NPP instance, NPNVariable variable,
+                                     void *value);
+
+/*
+ * NPN_* functions are provided by the navigator and called by the plugin.
+ */
+
+void        NPN_Version(int* plugin_major, int* plugin_minor,
+                            int* netscape_major, int* netscape_minor);
+NPError     NPN_GetURLNotify(NPP instance, const char* url,
+                                 const char* target, void* notifyData);
+NPError     NPN_GetURL(NPP instance, const char* url,
+                           const char* target);
+NPError     NPN_PostURLNotify(NPP instance, const char* url,
+                                  const char* target, uint32 len,
+                                  const char* buf, NPBool file,
+                                  void* notifyData);
+NPError     NPN_PostURL(NPP instance, const char* url,
+                            const char* target, uint32 len,
+                            const char* buf, NPBool file);
+NPError     NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
+NPError     NPN_NewStream(NPP instance, NPMIMEType type,
+                              const char* target, NPStream** stream);
+int32        NPN_Write(NPP instance, NPStream* stream, int32 len,
+                          void* buffer);
+NPError     NPN_DestroyStream(NPP instance, NPStream* stream,
+                                  NPReason reason);
+void        NPN_Status(NPP instance, const char* message);
+const char*    NPN_UserAgent(NPP instance);
+void*        NPN_MemAlloc(uint32 size);
+void        NPN_MemFree(void* ptr);
+uint32        NPN_MemFlush(uint32 size);
+void        NPN_ReloadPlugins(NPBool reloadPages);
+JRIEnv*     NPN_GetJavaEnv(void);
+jref        NPN_GetJavaPeer(NPP instance);
+NPError     NPN_GetValue(NPP instance, NPNVariable variable,
+                             void *value);
+NPError     NPN_SetValue(NPP instance, NPPVariable variable,
+                             void *value);
+void        NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
+void        NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
+void        NPN_ForceRedraw(NPP instance);
+void        NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
+void        NPN_PopPopupsEnabledState(NPP instance);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* _NPAPI_H_ */
diff --git a/WebCore/bridge/npruntime.cpp b/WebCore/bridge/npruntime.cpp
new file mode 100644 (file)
index 0000000..ea7ea63
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2004, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+
+#include "JSLock.h"
+#include "c_utility.h"
+#include "identifier.h"
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+
+using namespace KJS::Bindings;
+
+typedef HashMap<RefPtr<KJS::UString::Rep>, PrivateIdentifier*> StringIdentifierMap;
+
+static StringIdentifierMap* getStringIdentifierMap()
+{
+    static StringIdentifierMap* stringIdentifierMap = 0;
+    if (!stringIdentifierMap)
+        stringIdentifierMap = new StringIdentifierMap;
+    return stringIdentifierMap;
+}
+
+typedef HashMap<int, PrivateIdentifier*> IntIdentifierMap;
+
+static IntIdentifierMap* getIntIdentifierMap()
+{
+    static IntIdentifierMap* intIdentifierMap = 0;
+    if (!intIdentifierMap)
+        intIdentifierMap = new IntIdentifierMap;
+    return intIdentifierMap;
+}
+
+NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
+{
+    ASSERT(name);
+    
+    if (name) {
+        PrivateIdentifier* identifier = 0;
+        
+        KJS::JSLock lock;
+        
+        identifier = getStringIdentifierMap()->get(identifierFromNPIdentifier(name).ustring().rep());
+        if (identifier == 0) {
+            identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
+            // We never release identifier names, so this dictionary will grow, as will
+            // the memory for the identifier name strings.
+            identifier->isString = true;
+            identifier->value.string = strdup(name);
+
+            getStringIdentifierMap()->set(identifierFromNPIdentifier(name).ustring().rep(), identifier);
+        }
+        return (NPIdentifier)identifier;
+    }
+    
+    return 0;
+}
+
+void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
+{
+    ASSERT(names);
+    ASSERT(identifiers);
+    
+    if (names && identifiers)
+        for (int i = 0; i < nameCount; i++)
+            identifiers[i] = _NPN_GetStringIdentifier(names[i]);
+}
+
+NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
+{
+    PrivateIdentifier* identifier;
+
+    if (intid == 0 || intid == -1) {
+        static PrivateIdentifier* negativeOneAndZeroIdentifiers[2];
+
+        identifier = negativeOneAndZeroIdentifiers[intid + 1];
+        if (!identifier) {
+            identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
+            identifier->isString = false;
+            identifier->value.number = intid;
+
+            negativeOneAndZeroIdentifiers[intid + 1] = identifier;
+        }
+    } else {
+        identifier = getIntIdentifierMap()->get(intid);
+        if (!identifier) {
+            identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
+            // We never release identifier names, so this dictionary will grow.
+            identifier->isString = false;
+            identifier->value.number = intid;
+
+            getIntIdentifierMap()->set(intid, identifier);
+        }
+    }
+    return (NPIdentifier)identifier;
+}
+
+bool _NPN_IdentifierIsString(NPIdentifier identifier)
+{
+    PrivateIdentifier* i = (PrivateIdentifier*)identifier;
+    return i->isString;
+}
+
+NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier)
+{
+    PrivateIdentifier* i = (PrivateIdentifier*)identifier;
+    if (!i->isString || !i->value.string)
+        return NULL;
+        
+    return (NPUTF8 *)strdup(i->value.string);
+}
+
+int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
+{
+    PrivateIdentifier* i = (PrivateIdentifier*)identifier;
+    if (!i->isString)
+        return 0;
+    return i->value.number;
+}
+
+void NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
+{
+    variant->type = NPVariantType_String;
+    variant->value.stringValue.UTF8Length = value->UTF8Length;
+    variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
+    memcpy((void*)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
+}
+
+void _NPN_ReleaseVariantValue(NPVariant* variant)
+{
+    ASSERT(variant);
+
+    if (variant->type == NPVariantType_Object) {
+        _NPN_ReleaseObject(variant->value.objectValue);
+        variant->value.objectValue = 0;
+    } else if (variant->type == NPVariantType_String) {
+        free((void*)variant->value.stringValue.UTF8Characters);
+        variant->value.stringValue.UTF8Characters = 0;
+        variant->value.stringValue.UTF8Length = 0;
+    }
+
+    variant->type = NPVariantType_Void;
+}
+
+NPObject *_NPN_CreateObject(NPP npp, NPClass* aClass)
+{
+    ASSERT(aClass);
+
+    if (aClass) {
+        NPObject* obj;
+        if (aClass->allocate != NULL)
+            obj = aClass->allocate(npp, aClass);
+        else
+            obj = (NPObject*)malloc(sizeof(NPObject));
+
+        obj->_class = aClass;
+        obj->referenceCount = 1;
+
+        return obj;
+    }
+
+    return 0;
+}
+
+NPObject* _NPN_RetainObject(NPObject* obj)
+{
+    ASSERT(obj);
+
+    if (obj)
+        obj->referenceCount++;
+
+    return obj;
+}
+
+void _NPN_ReleaseObject(NPObject* obj)
+{
+    ASSERT(obj);
+    ASSERT(obj->referenceCount >= 1);
+
+    if (obj && obj->referenceCount >= 1) {
+        if (--obj->referenceCount == 0)
+            _NPN_DeallocateObject(obj);
+    }
+}
+
+void _NPN_DeallocateObject(NPObject *obj)
+{
+    ASSERT(obj);
+
+    if (obj) {
+        if (obj->_class->deallocate)
+            obj->_class->deallocate(obj);
+        else
+            free(obj);
+    }
+}
+
+#endif
diff --git a/WebCore/bridge/npruntime.h b/WebCore/bridge/npruntime.h
new file mode 100644 (file)
index 0000000..fd1c192
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2004, Apple Computer, Inc. and The Mozilla Foundation. 
+ * 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 names of Apple Computer, Inc. ("Apple") or The Mozilla
+ * Foundation ("Mozilla") nor the names of their contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR 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, MOZILLA OR
+ * THEIR 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.
+ *
+ * Revision 1 (March 4, 2004):
+ * Initial proposal.
+ *
+ * Revision 2 (March 10, 2004):
+ * All calls into script were made asynchronous.  Results are
+ * provided via the NPScriptResultFunctionPtr callback.
+ *
+ * Revision 3 (March 10, 2004):
+ * Corrected comments to not refer to class retain/release FunctionPtrs.
+ *
+ * Revision 4 (March 11, 2004):
+ * Added additional convenience NPN_SetExceptionWithUTF8().
+ * Changed NPHasPropertyFunctionPtr and NPHasMethodFunctionPtr to take NPClass
+ * pointers instead of NPObject pointers.
+ * Added NPIsValidIdentifier().
+ *
+ * Revision 5 (March 17, 2004):
+ * Added context parameter to result callbacks from ScriptObject functions.
+ *
+ * Revision 6 (March 29, 2004):
+ * Renamed functions implemented by user agent to NPN_*.  Removed _ from
+ * type names.
+ * Renamed "JavaScript" types to "Script".
+ *
+ * Revision 7 (April 21, 2004):
+ * NPIdentifier becomes a void*, was int32_t
+ * Remove NP_IsValidIdentifier, renamed NP_IdentifierFromUTF8 to NP_GetIdentifier
+ * Added NPVariant and modified functions to use this new type.
+ *
+ * Revision 8 (July 9, 2004):
+ * Updated to joint Apple-Mozilla license.
+ *
+ * Revision 9 (August 12, 2004):
+ * Changed NPVariantType enum values to form PVariantType_XXX
+ * Added NPP arguments to NPObject functions.
+ * Replaced NPVariant functions with macros.
+ */
+#ifndef _NP_RUNTIME_H_
+#define _NP_RUNTIME_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "npapi.h"
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#error 64-bit Netscape plug-ins are not supported on Mac OS X
+#endif
+
+/*
+    This API is used to facilitate binding code written in C to script
+    objects.  The API in this header does not assume the presence of a
+    user agent.  That is, it can be used to bind C code to scripting
+    environments outside of the context of a user agent.
+    
+    However, the normal use of the this API is in the context of a
+    scripting environment running in a browser or other user agent.
+    In particular it is used to support the extended Netscape
+    script-ability API for plugins (NP-SAP).  NP-SAP is an extension
+    of the Netscape plugin API.  As such we have adopted the use of
+    the "NP" prefix for this API.
+
+    The following NP{N|P}Variables were added to the Netscape plugin
+    API (in npapi.h):
+
+    NPNVWindowNPObject
+    NPNVPluginElementNPObject
+    NPPVpluginScriptableNPObject
+
+    These variables are exposed through NPN_GetValue() and
+    NPP_GetValue() (respectively) and are used to establish the
+    initial binding between the user agent and native code.  The DOM
+    objects in the user agent can be examined and manipulated using
+    the NPN_ functions that operate on NPObjects described in this
+    header.
+
+    To the extent possible the assumptions about the scripting
+    language used by the scripting environment have been minimized.
+*/
+
+
+/*
+    Objects (non-primitive data) passed between 'C' and script is
+    always wrapped in an NPObject.  The 'interface' of an NPObject is
+    described by an NPClass.
+*/
+typedef struct NPObject NPObject;
+typedef struct NPClass NPClass;
+
+typedef char NPUTF8;
+typedef struct _NPString {
+    const NPUTF8 *UTF8Characters;
+    uint32_t UTF8Length;
+} NPString;
+  
+typedef enum {
+    NPVariantType_Void,
+    NPVariantType_Null,
+    NPVariantType_Bool,
+    NPVariantType_Int32,
+    NPVariantType_Double,
+    NPVariantType_String,
+    NPVariantType_Object
+} NPVariantType;
+
+typedef struct _NPVariant {
+    NPVariantType type;
+    union {
+        bool boolValue;
+        int32_t intValue;
+        double doubleValue;
+        NPString stringValue;
+        NPObject *objectValue;
+    } value;
+} NPVariant;
+
+/*
+    NPN_ReleaseVariantValue is called on all 'out' parameters references.
+    Specifically it is called on variants that are resultant out parameters
+    in NPGetPropertyFunctionPtr and NPInvokeFunctionPtr.  Resultant variants
+    from these two functions should be initialized using the
+    NPN_InitializeVariantXXX() functions.
+    
+    After calling NPReleaseVariantValue, the type of the variant will
+    be set to NPVariantUndefinedType.
+*/
+void NPN_ReleaseVariantValue (NPVariant *variant);
+
+#define NPVARIANT_IS_VOID(_v)    ((_v).type == NPVariantType_Void)
+#define NPVARIANT_IS_NULL(_v)    ((_v).type == NPVariantType_Null)
+#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
+#define NPVARIANT_IS_INT32(_v)   ((_v).type == NPVariantType_Int32)
+#define NPVARIANT_IS_DOUBLE(_v)  ((_v).type == NPVariantType_Double)
+#define NPVARIANT_IS_STRING(_v)  ((_v).type == NPVariantType_String)
+#define NPVARIANT_IS_OBJECT(_v)  ((_v).type == NPVariantType_Object)
+
+#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
+#define NPVARIANT_TO_INT32(_v)   ((_v).value.intValue)
+#define NPVARIANT_TO_DOUBLE(_v)  ((_v).value.doubleValue)
+#define NPVARIANT_TO_STRING(_v)  ((_v).value.stringValue)
+#define NPVARIANT_TO_OBJECT(_v)  ((_v).value.objectValue)
+
+#define NP_BEGIN_MACRO  do {
+#define NP_END_MACRO    } while (0)
+
+#define VOID_TO_NPVARIANT(_v)                NP_BEGIN_MACRO (_v).type = NPVariantType_Void; (_v).value.objectValue = NULL; NP_END_MACRO
+#define NULL_TO_NPVARIANT(_v)                NP_BEGIN_MACRO (_v).type = NPVariantType_Null; (_v).value.objectValue = NULL; NP_END_MACRO
+#define BOOLEAN_TO_NPVARIANT(_val, _v)       NP_BEGIN_MACRO (_v).type = NPVariantType_Bool; (_v).value.boolValue = !!(_val); NP_END_MACRO
+#define INT32_TO_NPVARIANT(_val, _v)         NP_BEGIN_MACRO (_v).type = NPVariantType_Int32; (_v).value.intValue = _val; NP_END_MACRO
+#define DOUBLE_TO_NPVARIANT(_val, _v)        NP_BEGIN_MACRO (_v).type = NPVariantType_Double; (_v).value.doubleValue = _val; NP_END_MACRO
+#define STRINGZ_TO_NPVARIANT(_val, _v)       NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString str = { _val, strlen(_val) }; (_v).value.stringValue = str; NP_END_MACRO
+#define STRINGN_TO_NPVARIANT(_val, _len, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString str = { _val, _len }; (_v).value.stringValue = str; NP_END_MACRO
+#define OBJECT_TO_NPVARIANT(_val, _v)        NP_BEGIN_MACRO (_v).type = NPVariantType_Object; (_v).value.objectValue = _val; NP_END_MACRO
+
+/*
+        Type mappings (JavaScript types have been used for illustration
+    purposes):
+
+        JavaScript       to             C (NPVariant with type:)
+        undefined                       NPVariantType_Void
+        null                            NPVariantType_Null
+        Boolean                         NPVariantType_Bool
+        Number                          NPVariantType_Double or NPVariantType_Int32
+        String                          NPVariantType_String
+        Object                          NPVariantType_Object
+
+        C (NPVariant with type:)   to   JavaScript
+        NPVariantType_Void              undefined
+        NPVariantType_Null              null
+        NPVariantType_Bool              Boolean 
+        NPVariantType_Int32             Number
+        NPVariantType_Double            Number
+        NPVariantType_String            String
+        NPVariantType_Object            Object
+*/
+
+typedef void *NPIdentifier;
+
+/*
+    NPObjects have methods and properties.  Methods and properties are
+    identified with NPIdentifiers.  These identifiers may be reflected
+    in script.  NPIdentifiers can be either strings or integers, IOW,
+    methods and properties can be identified by either strings or
+    integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
+    compared using ==.  In case of any errors, the requested
+    NPIdentifier(s) will be NULL.
+*/
+NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
+void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+NPIdentifier NPN_GetIntIdentifier(int32_t intid);
+bool NPN_IdentifierIsString(NPIdentifier identifier);
+
+/*
+    The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
+*/
+NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
+
+/*
+    Get the integer represented by identifier. If identifier is not an
+    integer identifier, the behaviour is undefined.
+*/
+int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
+
+/*
+    NPObject behavior is implemented using the following set of
+    callback functions.
+
+    The NPVariant *result argument of these functions (where
+    applicable) should be released using NPN_ReleaseVariantValue().
+*/
+typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
+typedef void (*NPDeallocateFunctionPtr)(NPObject *obj);
+typedef void (*NPInvalidateFunctionPtr)(NPObject *obj);
+typedef bool (*NPHasMethodFunctionPtr)(NPObject *obj, NPIdentifier name);
+typedef bool (*NPInvokeFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
+typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+typedef bool (*NPHasPropertyFunctionPtr)(NPObject *obj, NPIdentifier name);
+typedef bool (*NPGetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, NPVariant *result);
+typedef bool (*NPSetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *value);
+typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
+typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, uint32_t *count);
+
+/*
+    NPObjects returned by create have a reference count of one.  It is the caller's responsibility
+    to release the returned object.
+
+    NPInvokeFunctionPtr function may return false to indicate a the method could not be invoked.
+    
+    NPGetPropertyFunctionPtr and NPSetPropertyFunctionPtr may return false to indicate a property doesn't
+    exist.
+    
+    NPInvalidateFunctionPtr is called by the scripting environment when the native code is
+    shutdown.  Any attempt to message a NPObject instance after the invalidate
+    callback has been called will result in undefined behavior, even if the
+    native code is still retaining those NPObject instances.
+    (The runtime will typically return immediately, with 0 or NULL, from an attempt to
+    dispatch to a NPObject, but this behavior should not be depended upon.)
+    
+    The NPEnumerationFunctionPtr function may pass an array of                  
+    NPIdentifiers back to the caller. The callee allocs the memory of           
+    the array using NPN_MemAlloc(), and it's the caller's responsibility        
+    to release it using NPN_MemFree().           
+*/
+struct NPClass
+{
+    uint32_t structVersion;
+    NPAllocateFunctionPtr allocate;
+    NPDeallocateFunctionPtr deallocate;
+    NPInvalidateFunctionPtr invalidate;
+    NPHasMethodFunctionPtr hasMethod;
+    NPInvokeFunctionPtr invoke;
+    NPInvokeDefaultFunctionPtr invokeDefault;
+    NPHasPropertyFunctionPtr hasProperty;
+    NPGetPropertyFunctionPtr getProperty;
+    NPSetPropertyFunctionPtr setProperty;
+    NPRemovePropertyFunctionPtr removeProperty;
+    NPEnumerationFunctionPtr enumerate;
+};
+
+#define NP_CLASS_STRUCT_VERSION      2
+#define NP_CLASS_STRUCT_VERSION_ENUM 2                           
+#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass)   \
+    ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
+
+struct NPObject {
+    NPClass *_class;
+    uint32_t referenceCount;
+    // Additional space may be allocated here by types of NPObjects
+};
+
+/*
+    If the class has an allocate function, NPN_CreateObject invokes that function,
+    otherwise a NPObject is allocated and returned.  If a class has an allocate
+    function it is the responsibility of that implementation to set the initial retain
+    count to 1.
+*/
+NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
+
+/*
+    Increment the NPObject's reference count.
+*/
+NPObject *NPN_RetainObject (NPObject *obj);
+
+/*
+    Decremented the NPObject's reference count.  If the reference
+    count goes to zero, the class's destroy function is invoke if
+    specified, otherwise the object is freed directly.
+*/
+void NPN_ReleaseObject (NPObject *obj);
+
+/*
+    Functions to access script objects represented by NPObject.
+
+    Calls to script objects are synchronous.  If a function returns a
+    value, it will be supplied via the result NPVariant
+    argument. Successful calls will return true, false will be
+    returned in case of an error.
+    
+    Calls made from plugin code to script must be made from the thread
+    on which the plugin was initialized.
+*/
+bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
+bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
+bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
+bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
+bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+
+/*
+    NPN_SetException may be called to trigger a script exception upon return
+    from entry points into NPObjects.
+*/
+void NPN_SetException (NPObject *obj, const NPUTF8 *message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/WebCore/bridge/npruntime_impl.h b/WebCore/bridge/npruntime_impl.h
new file mode 100644 (file)
index 0000000..84e63ce
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef _NP_RUNTIME_IMPL_H_
+#define _NP_RUNTIME_IMPL_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void _NPN_ReleaseVariantValue(NPVariant *variant);
+extern NPIdentifier _NPN_GetStringIdentifier(const NPUTF8 *name);
+extern void _NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+extern NPIdentifier _NPN_GetIntIdentifier(int32_t intid);
+extern bool _NPN_IdentifierIsString(NPIdentifier identifier);
+extern NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier);
+extern int32_t _NPN_IntFromIdentifier(NPIdentifier identifier);    
+extern NPObject *_NPN_CreateObject(NPP npp, NPClass *aClass);
+extern NPObject *_NPN_RetainObject(NPObject *obj);
+extern void _NPN_ReleaseObject(NPObject *obj);
+extern void _NPN_DeallocateObject(NPObject *obj);
+extern bool _NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
+extern bool _NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+extern bool _NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
+extern bool _NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
+extern bool _NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
+extern bool _NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+extern bool _NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+extern bool _NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
+extern void _NPN_SetException(NPObject *obj, const NPUTF8 *message);
+extern bool _NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif
+#endif
diff --git a/WebCore/bridge/npruntime_internal.h b/WebCore/bridge/npruntime_internal.h
new file mode 100644 (file)
index 0000000..f5357cd
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 Collabora, Ltd.  All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This is a internal include header for npapi.h
+ *
+ * Some of the #defines which are in X11 headers conflict with type and enum
+ * names in JavaScriptCore and WebCore
+ * This header #undefs those defines to fix the conflicts
+ * If you need to include npapi.h or npruntime.h when building on X11,
+ * include this file instead of the actual npapi.h or npruntime.h
+ */
+
+#include "npruntime.h"
+
+#ifdef XP_UNIX
+    #include <X11/Xresource.h>
+
+    #undef None
+    #undef Above
+    #undef Below
+    #undef Auto
+    #undef Complex
+    #undef Status
+#endif
diff --git a/WebCore/bridge/npruntime_priv.h b/WebCore/bridge/npruntime_priv.h
new file mode 100644 (file)
index 0000000..b19b16a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003, 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef NP_RUNTIME_PRIV_H_
+#define NP_RUNTIME_PRIV_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+
+/*
+    NPN_InitializeVariantWithStringCopy() will copy string data.  The string data
+    will be deallocated by calls to NPReleaseVariantValue().
+*/
+void NPN_InitializeVariantWithStringCopy(NPVariant*, const NPString*);
+
+#endif
+#endif
+
diff --git a/WebCore/bridge/objc/WebScriptObject.h b/WebCore/bridge/objc/WebScriptObject.h
new file mode 100644 (file)
index 0000000..14d77d7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#import <Foundation/Foundation.h>
+
+#include "internal.h"
+#include "runtime_root.h"
+
+@class WebUndefined;
+
+@protocol WebScriptObject
++ (NSString *)webScriptNameForSelector:(SEL)aSelector;
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
++ (NSString *)webScriptNameForKey:(const char *)name;
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
+
++ (id)_convertValueToObjcValue:(KJS::JSValue *)value originRootObject:(KJS::Bindings::RootObject*)originRootObject rootObject:(KJS::Bindings::RootObject*)rootObject;
+- _initWithJSObject:(KJS::JSObject*)imp originRootObject:(PassRefPtr<KJS::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<KJS::Bindings::RootObject>)rootObject;
+- (KJS::JSObject *)_imp;
+@end
+
+@protocol WebUndefined
++ (WebUndefined *)undefined;
+@end
diff --git a/WebCore/bridge/objc/objc_class.h b/WebCore/bridge/objc/objc_class.h
new file mode 100644 (file)
index 0000000..3faee18
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef KJS_BINDINGS_OBJC_CLASS_H
+#define KJS_BINDINGS_OBJC_CLASS_H
+
+#include <JavaScriptCore/objc_runtime.h>
+
+namespace KJS {
+namespace Bindings {
+
+class ObjcClass : public Class
+{
+protected:
+    ObjcClass (ClassStructPtr aClass); // Use classForIsA to create an ObjcClass.
+    
+public:
+    // Return the cached ObjC of the specified name.
+    static ObjcClass *classForIsA(ClassStructPtr);
+    
+    virtual const char *name() const;
+    
+    virtual MethodList methodsNamed(const Identifier&, Instance *instance) const;
+    virtual Field *fieldNamed(const Identifier&, Instance *instance) const;
+
+    virtual JSValue *fallbackObject(ExecState *exec, Instance *instance, const Identifier &propertyName);
+    
+    ClassStructPtr isa() { return _isa; }
+    
+private:
+    ClassStructPtr _isa;
+    RetainPtr<CFMutableDictionaryRef> _methods;
+    RetainPtr<CFMutableDictionaryRef> _fields;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/objc/objc_class.mm b/WebCore/bridge/objc/objc_class.mm
new file mode 100644 (file)
index 0000000..e3a72f7
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "objc_class.h"
+
+#include "objc_instance.h"
+#include "WebScriptObject.h"
+
+namespace KJS {
+namespace Bindings {
+    
+static void deleteMethod(CFAllocatorRef, const void* value)
+{
+    delete static_cast<const Method*>(value);
+}
+    
+static void deleteField(CFAllocatorRef, const void* value)
+{
+    delete static_cast<const Field*>(value);
+}
+
+const CFDictionaryValueCallBacks MethodDictionaryValueCallBacks = { 0, 0, &deleteMethod, 0 , 0 };
+const CFDictionaryValueCallBacks FieldDictionaryValueCallBacks = { 0, 0, &deleteField, 0 , 0 };    
+    
+ObjcClass::ObjcClass(ClassStructPtr aClass)
+    : _isa(aClass)
+    , _methods(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &MethodDictionaryValueCallBacks))
+    , _fields(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &FieldDictionaryValueCallBacks))
+{
+}
+
+static CFMutableDictionaryRef classesByIsA = 0;
+
+static void _createClassesByIsAIfNecessary()
+{
+    if (!classesByIsA)
+        classesByIsA = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+}
+
+ObjcClass* ObjcClass::classForIsA(ClassStructPtr isa)
+{
+    _createClassesByIsAIfNecessary();
+
+    ObjcClass* aClass = (ObjcClass*)CFDictionaryGetValue(classesByIsA, isa);
+    if (!aClass) {
+        aClass = new ObjcClass(isa);
+        CFDictionaryAddValue(classesByIsA, isa, aClass);
+    }
+
+    return aClass;
+}
+
+const char* ObjcClass::name() const
+{
+    return object_getClassName(_isa);
+}
+
+MethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+    MethodList methodList;
+    char fixedSizeBuffer[1024];
+    char* buffer = fixedSizeBuffer;
+    const char* JSName = identifier.ascii();
+    if (!convertJSMethodNameToObjc(JSName, buffer, sizeof(fixedSizeBuffer))) {
+        int length = strlen(JSName) + 1;
+        buffer = new char[length];
+        if (!buffer || !convertJSMethodNameToObjc(JSName, buffer, length))
+            return methodList;
+    }
+
+    
+    RetainPtr<CFStringRef> methodName(AdoptCF, CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII));
+    Method* method = (Method*)CFDictionaryGetValue(_methods.get(), methodName.get());
+    if (method) {
+        methodList.append(method);
+        return methodList;
+    }
+
+    ClassStructPtr thisClass = _isa;
+    while (thisClass && methodList.isEmpty()) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+        unsigned numMethodsInClass = 0;
+        MethodStructPtr* objcMethodList = class_copyMethodList(thisClass, &numMethodsInClass);
+#else
+        void* iterator = 0;
+        struct objc_method_list* objcMethodList;
+        while ((objcMethodList = class_nextMethodList(thisClass, &iterator))) {
+            unsigned numMethodsInClass = objcMethodList->method_count;
+#endif
+            for (unsigned i = 0; i < numMethodsInClass; i++) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+                MethodStructPtr objcMethod = objcMethodList[i];
+                SEL objcMethodSelector = method_getName(objcMethod);
+#else
+                struct objc_method* objcMethod = &objcMethodList->method_list[i];
+                SEL objcMethodSelector = objcMethod->method_name;
+#endif
+                const char* objcMethodSelectorName = sel_getName(objcMethodSelector);
+                NSString* mappedName = nil;
+
+                // See if the class wants to exclude the selector from visibility in JavaScript.
+                if ([thisClass respondsToSelector:@selector(isSelectorExcludedFromWebScript:)])
+                    if ([thisClass isSelectorExcludedFromWebScript:objcMethodSelector])
+                        continue;
+
+                // See if the class want to provide a different name for the selector in JavaScript.
+                // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+                // of the class.
+                if ([thisClass respondsToSelector:@selector(webScriptNameForSelector:)])
+                    mappedName = [thisClass webScriptNameForSelector:objcMethodSelector];
+
+                if ((mappedName && [mappedName isEqual:(NSString*)methodName.get()]) || strcmp(objcMethodSelectorName, buffer) == 0) {
+                    Method* aMethod = new ObjcMethod(thisClass, objcMethodSelectorName); // deleted when the dictionary is destroyed
+                    CFDictionaryAddValue(_methods.get(), methodName.get(), aMethod);
+                    methodList.append(aMethod);
+                    break;
+                }
+            }
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+            thisClass = class_getSuperclass(thisClass);
+            free(objcMethodList);
+#else
+        }
+        thisClass = thisClass->super_class;
+#endif
+    }
+
+    if (buffer != fixedSizeBuffer)
+        delete [] buffer;
+
+    return methodList;
+}
+
+Field* ObjcClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+    ClassStructPtr thisClass = _isa;
+
+    const char* name = identifier.ascii();
+    RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII));
+    Field* aField = (Field*)CFDictionaryGetValue(_fields.get(), fieldName.get());
+    if (aField)
+        return aField;
+
+    id targetObject = (static_cast<ObjcInstance*>(instance))->getObject();
+    id attributes = [targetObject attributeKeys];
+    if (attributes) {
+        // Class overrides attributeKeys, use that array of key names.
+        unsigned count = [attributes count];
+        for (unsigned i = 0; i < count; i++) {
+            NSString* keyName = [attributes objectAtIndex:i];
+            const char* UTF8KeyName = [keyName UTF8String]; // ObjC actually only supports ASCII names.
+
+            // See if the class wants to exclude the selector from visibility in JavaScript.
+            if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
+                if ([thisClass isKeyExcludedFromWebScript:UTF8KeyName])
+                    continue;
+
+            // See if the class want to provide a different name for the selector in JavaScript.
+            // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+            // of the class.
+            NSString* mappedName = nil;
+            if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
+                mappedName = [thisClass webScriptNameForKey:UTF8KeyName];
+
+            if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || [keyName isEqual:(NSString*)fieldName.get()]) {
+                aField = new ObjcField((CFStringRef)keyName); // deleted when the dictionary is destroyed
+                CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
+                break;
+            }
+        }
+    } else {
+        // Class doesn't override attributeKeys, so fall back on class runtime
+        // introspection.
+
+        while (thisClass) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+            unsigned numFieldsInClass = 0;
+            IvarStructPtr* ivarsInClass = class_copyIvarList(thisClass, &numFieldsInClass);
+#else
+            struct objc_ivar_list* fieldsInClass = thisClass->ivars;
+            if (fieldsInClass) {
+                unsigned numFieldsInClass = fieldsInClass->ivar_count;
+#endif
+                for (unsigned i = 0; i < numFieldsInClass; i++) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+                    IvarStructPtr objcIVar = ivarsInClass[i];
+                    const char* objcIvarName = ivar_getName(objcIVar);
+#else
+                    IvarStructPtr objcIVar = &fieldsInClass->ivar_list[i];
+                    const char* objcIvarName = objcIVar->ivar_name;
+#endif
+                    NSString* mappedName = 0;
+
+                    // See if the class wants to exclude the selector from visibility in JavaScript.
+                    if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
+                        if ([thisClass isKeyExcludedFromWebScript:objcIvarName])
+                            continue;
+
+                    // See if the class want to provide a different name for the selector in JavaScript.
+                    // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+                    // of the class.
+                    if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
+                        mappedName = [thisClass webScriptNameForKey:objcIvarName];
+
+                    if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || strcmp(objcIvarName, name) == 0) {
+                        aField = new ObjcField(objcIVar); // deleted when the dictionary is destroyed
+                        CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
+                        break;
+                    }
+                }
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+            thisClass = class_getSuperclass(thisClass);
+            free(ivarsInClass);
+#else
+            }
+            thisClass = thisClass->super_class;
+#endif
+        }
+    }
+
+    return aField;
+}
+
+JSValue* ObjcClass::fallbackObject(ExecState*, Instance* instance, const Identifier &propertyName)
+{
+    ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
+    id targetObject = objcInstance->getObject();
+    
+    if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+        return jsUndefined();
+    return new ObjcFallbackObjectImp(objcInstance, propertyName);
+}
+
+}
+}
diff --git a/WebCore/bridge/objc/objc_header.h b/WebCore/bridge/objc/objc_header.h
new file mode 100644 (file)
index 0000000..07954a1
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef KJS_BINDINGS_OBJC_HEADER_H
+#define KJS_BINDINGS_OBJC_HEADER_H
+
+#ifdef __OBJC__
+
+#include <objc/objc.h>
+#include <objc/objc-class.h>
+#include <objc/objc-runtime.h>
+
+typedef Class ClassStructPtr;
+typedef id ObjectStructPtr;
+typedef Method MethodStructPtr;
+typedef Ivar IvarStructPtr;
+
+@class NSMethodSignature;
+
+#else
+
+typedef struct objc_class* ClassStructPtr;
+typedef struct objc_object* ObjectStructPtr;
+typedef struct objc_method* MethodStructPtr;
+typedef struct objc_ivar* IvarStructPtr;
+
+class NSMethodSignature;
+
+#endif
+
+#endif
diff --git a/WebCore/bridge/objc/objc_instance.h b/WebCore/bridge/objc/objc_instance.h
new file mode 100644 (file)
index 0000000..2233791
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef BINDINGS_OBJC_INSTANCE_H_
+#define BINDINGS_OBJC_INSTANCE_H_
+
+#include <JavaScriptCore/objc_class.h>
+#include <JavaScriptCore/objc_utility.h>
+
+namespace KJS {
+
+namespace Bindings {
+
+class ObjcClass;
+
+class ObjcInstance : public Instance {
+public:
+    ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject>);
+        
+    ~ObjcInstance();
+    
+    virtual Class *getClass() const;
+    
+    virtual void begin();
+    virtual void end();
+    
+    virtual JSValue *valueOf() const;
+    virtual JSValue *defaultValue(JSType hint) const;
+
+    virtual bool implementsCall() const;
+    
+    virtual JSValue *invokeMethod(ExecState *exec, const MethodList &method, const List &args);
+    virtual JSValue *invokeDefaultMethod(ExecState *exec, const List &args);
+
+    virtual bool supportsSetValueOfUndefinedField();
+    virtual void setValueOfUndefinedField(ExecState *exec, const Identifier &property, JSValue *aValue);
+    
+    virtual JSValue *getValueOfUndefinedField(ExecState *exec, const Identifier &property, JSType hint) const;
+
+    ObjectStructPtr getObject() const { return _instance.get(); }
+    
+    JSValue *stringValue() const;
+    JSValue *numberValue() const;
+    JSValue *booleanValue() const;
+
+    virtual BindingLanguage getBindingLanguage() const { return ObjectiveCLanguage; }
+
+private:
+    RetainPtr<ObjectStructPtr> _instance;
+    mutable ObjcClass *_class;
+    ObjectStructPtr _pool;
+    int _beginCount;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif // BINDINGS_OBJC_INSTANCE_H_
diff --git a/WebCore/bridge/objc/objc_instance.mm b/WebCore/bridge/objc/objc_instance.mm
new file mode 100644 (file)
index 0000000..57ebfe8
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#import "config.h"
+#import "objc_instance.h"
+
+#import "WebScriptObject.h"
+#include <wtf/Assertions.h>
+
+#ifdef NDEBUG
+#define OBJC_LOG(formatAndArgs...) ((void)0)
+#else
+#define OBJC_LOG(formatAndArgs...) { \
+    fprintf (stderr, "%s:%d -- %s:  ", __FILE__, __LINE__, __FUNCTION__); \
+    fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+using namespace KJS::Bindings;
+using namespace KJS;
+
+ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject) 
+    : Instance(rootObject)
+    , _instance(instance)
+    , _class(0)
+    , _pool(0)
+    , _beginCount(0)
+{
+}
+
+ObjcInstance::~ObjcInstance() 
+{
+    begin(); // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
+    if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
+        [_instance.get() performSelector:@selector(finalizeForWebScript)];
+    _instance = 0;
+    end();
+}
+
+void ObjcInstance::begin()
+{
+    if (!_pool)
+        _pool = [[NSAutoreleasePool alloc] init];
+    _beginCount++;
+}
+
+void ObjcInstance::end()
+{
+    _beginCount--;
+    ASSERT(_beginCount >= 0);
+    if (!_beginCount) {
+        [_pool drain];
+        _pool = 0;
+    }
+}
+
+Bindings::Class* ObjcInstance::getClass() const 
+{
+    if (!_instance)
+        return 0;
+    if (!_class)
+        _class = ObjcClass::classForIsA(_instance->isa);
+    return static_cast<Bindings::Class*>(_class);
+}
+
+bool ObjcInstance::implementsCall() const
+{
+    return [_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)];
+}
+
+JSValue* ObjcInstance::invokeMethod(ExecState* exec, const MethodList &methodList, const List &args)
+{
+    JSValue* result = jsUndefined();
+    
+   JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+    // Overloading methods is not allowed in ObjectiveC.  Should only be one
+    // name match for a particular method.
+    ASSERT(methodList.size() == 1);
+
+@try {
+    ObjcMethod* method = 0;
+    method = static_cast<ObjcMethod*>(methodList[0]);
+    NSMethodSignature* signature = method->getMethodSignature();
+    NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+    [invocation setSelector:sel_registerName(method->name())];
+#else
+    [invocation setSelector:(SEL)method->name()];
+#endif
+    [invocation setTarget:_instance.get()];
+
+    if (method->isFallbackMethod()) {
+        if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
+            NSLog(@"Incorrect signature for invokeUndefinedMethodFromWebScript:withArguments: -- return type must be object.");
+            return result;
+        }
+
+        // Invoke invokeUndefinedMethodFromWebScript:withArguments:, pass JavaScript function
+        // name as first (actually at 2) argument and array of args as second.
+        NSString* jsName = (NSString* )method->javaScriptName();
+        [invocation setArgument:&jsName atIndex:2];
+
+        NSMutableArray* objcArgs = [NSMutableArray array];
+        int count = args.size();
+        for (int i = 0; i < count; i++) {
+            ObjcValue value = convertValueToObjcValue(exec, args.at(i), ObjcObjectType);
+            [objcArgs addObject:value.objectValue];
+        }
+        [invocation setArgument:&objcArgs atIndex:3];
+    } else {
+        unsigned count = [signature numberOfArguments];
+        for (unsigned i = 2; i < count ; i++) {
+            const char* type = [signature getArgumentTypeAtIndex:i];
+            ObjcValueType objcValueType = objcValueTypeForType(type);
+
+            // Must have a valid argument type.  This method signature should have
+            // been filtered already to ensure that it has acceptable argument
+            // types.
+            ASSERT(objcValueType != ObjcInvalidType && objcValueType != ObjcVoidType);
+
+            ObjcValue value = convertValueToObjcValue(exec, args.at(i-2), objcValueType);
+
+            switch (objcValueType) {
+                case ObjcObjectType:
+                    [invocation setArgument:&value.objectValue atIndex:i];
+                    break;
+                case ObjcCharType:
+                case ObjcUnsignedCharType:
+                    [invocation setArgument:&value.charValue atIndex:i];
+                    break;
+                case ObjcShortType:
+                case ObjcUnsignedShortType:
+                    [invocation setArgument:&value.shortValue atIndex:i];
+                    break;
+                case ObjcIntType:
+                case ObjcUnsignedIntType:
+                    [invocation setArgument:&value.intValue atIndex:i];
+                    break;
+                case ObjcLongType:
+                case ObjcUnsignedLongType:
+                    [invocation setArgument:&value.longValue atIndex:i];
+                    break;
+                case ObjcLongLongType:
+                case ObjcUnsignedLongLongType:
+                    [invocation setArgument:&value.longLongValue atIndex:i];
+                    break;
+                case ObjcFloatType:
+                    [invocation setArgument:&value.floatValue atIndex:i];
+                    break;
+                case ObjcDoubleType:
+                    [invocation setArgument:&value.doubleValue atIndex:i];
+                    break;
+                default:
+                    // Should never get here.  Argument types are filtered (and
+                    // the assert above should have fired in the impossible case
+                    // of an invalid type anyway).
+                    fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)objcValueType);
+                    ASSERT(false);
+            }
+        }
+    }
+
+    [invocation invoke];
+
+    // Get the return value type.
+    const char* type = [signature methodReturnType];
+    ObjcValueType objcValueType = objcValueTypeForType(type);
+
+    // Must have a valid return type.  This method signature should have
+    // been filtered already to ensure that it have an acceptable return
+    // type.
+    ASSERT(objcValueType != ObjcInvalidType);
+
+    // Get the return value and convert it to a JavaScript value. Length
+    // of return value will never exceed the size of largest scalar
+    // or a pointer.
+    char buffer[1024];
+    ASSERT([signature methodReturnLength] < 1024);
+
+    if (*type != 'v') {
+        [invocation getReturnValue:buffer];
+        result = convertObjcValueToValue(exec, buffer, objcValueType, _rootObject.get());
+    }
+} @catch(NSException* localException) {
+}
+    return result;
+}
+
+JSValue* ObjcInstance::invokeDefaultMethod(ExecState* exec, const List &args)
+{
+    JSValue* result = jsUndefined();
+
+   JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+@try {
+    if (![_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)])
+        return result;
+
+    NSMethodSignature* signature = [_instance.get() methodSignatureForSelector:@selector(invokeDefaultMethodWithArguments:)];
+    NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+    [invocation setSelector:@selector(invokeDefaultMethodWithArguments:)];
+    [invocation setTarget:_instance.get()];
+
+    if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
+        NSLog(@"Incorrect signature for invokeDefaultMethodWithArguments: -- return type must be object.");
+        return result;
+    }
+
+    NSMutableArray* objcArgs = [NSMutableArray array];
+    unsigned count = args.size();
+    for (unsigned i = 0; i < count; i++) {
+        ObjcValue value = convertValueToObjcValue(exec, args.at(i), ObjcObjectType);
+        [objcArgs addObject:value.objectValue];
+    }
+    [invocation setArgument:&objcArgs atIndex:2];
+
+    [invocation invoke];
+
+    // Get the return value type, should always be "@" because of
+    // check above.
+    const char* type = [signature methodReturnType];
+    ObjcValueType objcValueType = objcValueTypeForType(type);
+
+    // Get the return value and convert it to a JavaScript value. Length
+    // of return value will never exceed the size of a pointer, so we're
+    // OK with 32 here.
+    char buffer[32];
+    [invocation getReturnValue:buffer];
+    result = convertObjcValueToValue(exec, buffer, objcValueType, _rootObject.get());
+} @catch(NSException* localException) {
+}
+
+    return result;
+}
+
+bool ObjcInstance::supportsSetValueOfUndefinedField()
+{
+    id targetObject = getObject();
+    if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)])
+        return true;
+    return false;
+}
+
+void ObjcInstance::setValueOfUndefinedField(ExecState* exec, const Identifier &property, JSValue* aValue)
+{
+    id targetObject = getObject();
+
+   JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+    // This check is not really necessary because NSObject implements
+    // setValue:forUndefinedKey:, and unfortnately the default implementation
+    // throws an exception.
+    if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)]){
+        ObjcValue objcValue = convertValueToObjcValue(exec, aValue, ObjcObjectType);
+
+        @try {
+            [targetObject setValue:objcValue.objectValue forUndefinedKey:[NSString stringWithCString:property.ascii() encoding:NSASCIIStringEncoding]];
+        } @catch(NSException* localException) {
+            // Do nothing.  Class did not override valueForUndefinedKey:.
+        }
+    }
+}
+
+JSValue* ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property, JSType) const
+{
+    JSValue* result = jsUndefined();
+    
+    id targetObject = getObject();
+
+   JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+    // This check is not really necessary because NSObject implements
+    // valueForUndefinedKey:, and unfortnately the default implementation
+    // throws an exception.
+    if ([targetObject respondsToSelector:@selector(valueForUndefinedKey:)]){
+        @try {
+            id objcValue = [targetObject valueForUndefinedKey:[NSString stringWithCString:property.ascii() encoding:NSASCIIStringEncoding]];
+            result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, _rootObject.get());
+        } @catch(NSException* localException) {
+            // Do nothing.  Class did not override valueForUndefinedKey:.
+        }
+    }
+
+    return result;
+}
+
+JSValue* ObjcInstance::defaultValue(JSType hint) const
+{
+    switch (hint) {
+    case StringType:
+        return stringValue();
+    case NumberType:
+        return numberValue();
+    case BooleanType:
+        return booleanValue();
+    case UnspecifiedType:
+        if ([_instance.get() isKindOfClass:[NSString class]])
+            return stringValue();
+        if ([_instance.get() isKindOfClass:[NSNumber class]])
+            return numberValue();
+    default:
+        return valueOf();
+    }
+}
+
+JSValue* ObjcInstance::stringValue() const
+{
+    return convertNSStringToString([getObject() description]);
+}
+
+JSValue* ObjcInstance::numberValue() const
+{
+    // FIXME:  Implement something sensible
+    return jsNumber(0);
+}
+
+JSValue* ObjcInstance::booleanValue() const
+{
+    // FIXME:  Implement something sensible
+    return jsBoolean(false);
+}
+
+JSValue* ObjcInstance::valueOf() const 
+{
+    return stringValue();
+}
diff --git a/WebCore/bridge/objc/objc_runtime.h b/WebCore/bridge/objc/objc_runtime.h
new file mode 100644 (file)
index 0000000..74bc49e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef KJS_BINDINGS_OBJC_RUNTIME_H
+#define KJS_BINDINGS_OBJC_RUNTIME_H
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <JavaScriptCore/objc_header.h>
+#include <JavaScriptCore/object.h>
+#include <JavaScriptCore/runtime.h>
+
+#include <wtf/RetainPtr.h>
+
+namespace KJS {
+namespace Bindings {
+
+extern ClassStructPtr webScriptObjectClass();
+extern ClassStructPtr webUndefinedClass();
+
+class ObjcInstance;
+
+class ObjcField : public Field
+{
+public:
+    ObjcField(IvarStructPtr ivar);
+    ObjcField(CFStringRef name);
+    
+    virtual JSValue *valueFromInstance(ExecState *exec, const Instance *instance) const;
+    virtual void setValueToInstance(ExecState *exec, const Instance *instance, JSValue *aValue) const;
+    
+    virtual const char *name() const;
+        
+private:
+    IvarStructPtr _ivar;
+    RetainPtr<CFStringRef> _name;
+};
+
+class ObjcMethod : public Method
+{
+public:
+    ObjcMethod() : _objcClass(0), _selector(0), _javaScriptName(0) {}
+    ObjcMethod(ClassStructPtr aClass, const char *_selector);
+
+    virtual const char *name() const;
+
+    virtual int numParameters() const;
+
+    NSMethodSignature *getMethodSignature() const;
+    
+    bool isFallbackMethod() const { return strcmp(_selector, "invokeUndefinedMethodFromWebScript:withArguments:") == 0; }
+    void setJavaScriptName(CFStringRef n) { _javaScriptName = n; }
+    CFStringRef javaScriptName() const { return _javaScriptName.get(); }
+    
+private:
+    ClassStructPtr _objcClass;
+    const char *_selector;
+    RetainPtr<CFStringRef> _javaScriptName;
+};
+
+class ObjcArray : public Array
+{
+public:
+    ObjcArray(ObjectStructPtr, PassRefPtr<RootObject>);
+
+    virtual void setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const;
+    virtual JSValue *valueAt(ExecState *exec, unsigned int index) const;
+    virtual unsigned int getLength() const;
+    
+    ObjectStructPtr getObjcArray() const { return _array.get(); }
+
+    static JSValue *convertObjcArrayToArray(ExecState *exec, ObjectStructPtr anObject);
+
+private:
+    RetainPtr<ObjectStructPtr> _array;
+};
+
+class ObjcFallbackObjectImp : public JSObject {
+public:
+    ObjcFallbackObjectImp(ObjcInstance *i, const Identifier propertyName);
+
+    const ClassInfo *classInfo() const { return &info; }
+
+    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+    virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
+    virtual bool implementsCall() const;
+    virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+    virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+    virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
+
+    virtual JSType type() const;
+    virtual bool toBoolean(ExecState *exec) const;
+
+private:
+    ObjcFallbackObjectImp(); // prevent default construction
+    
+    static const ClassInfo info;
+
+    RefPtr<ObjcInstance> _instance;
+    Identifier _item;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/objc/objc_runtime.mm b/WebCore/bridge/objc/objc_runtime.mm
new file mode 100644 (file)
index 0000000..14877b4
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "objc_runtime.h"
+
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.h"
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+extern ClassStructPtr KJS::Bindings::webScriptObjectClass()
+{
+    static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");
+    return webScriptObjectClass;
+}
+
+extern ClassStructPtr KJS::Bindings::webUndefinedClass()
+{
+    static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");
+    return webUndefinedClass;
+}
+
+// ---------------------- ObjcMethod ----------------------
+
+ObjcMethod::ObjcMethod(ClassStructPtr aClass, const char* name)
+{
+    _objcClass = aClass;
+    _selector = name;   // Assume ObjC runtime keeps these around forever.
+    _javaScriptName = 0;
+}
+
+const char* ObjcMethod::name() const
+{
+    return _selector;
+}
+
+int ObjcMethod::numParameters() const
+{
+    return [getMethodSignature() numberOfArguments] - 2;
+}
+
+NSMethodSignature* ObjcMethod::getMethodSignature() const
+{
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+    return [_objcClass instanceMethodSignatureForSelector:sel_registerName(_selector)];
+#else
+    return [_objcClass instanceMethodSignatureForSelector:(SEL)_selector];
+#endif
+}
+
+// ---------------------- ObjcField ----------------------
+
+ObjcField::ObjcField(Ivar ivar) 
+{
+    _ivar = ivar;    // Assume ObjectiveC runtime will keep this alive forever
+    _name = 0;
+}
+
+ObjcField::ObjcField(CFStringRef name) 
+{
+    _ivar = 0;
+    _name = (CFStringRef)CFRetain(name);
+}
+
+const char* ObjcField::name() const 
+{
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+    if (_ivar)
+        return ivar_getName(_ivar);
+#else
+    if (_ivar)
+        return _ivar->ivar_name;
+#endif
+    return [(NSString*)_name.get() UTF8String];
+}
+
+JSValue* ObjcField::valueFromInstance(ExecState* exec, const Instance* instance) const
+{
+    JSValue* result = jsUndefined();
+    
+    id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+
+   JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+    @try {
+        NSString* key = [NSString stringWithCString:name() encoding:NSASCIIStringEncoding];
+        if (id objcValue = [targetObject valueForKey:key])
+            result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, instance->rootObject());
+    } @catch(NSException* localException) {
+        JSLock::lock();
+        throwError(exec, GeneralError, [localException reason]);
+        JSLock::unlock();
+    }
+
+    return result;
+}
+
+static id convertValueToObjcObject(ExecState* exec, JSValue* value)
+{
+    RefPtr<RootObject> rootObject = findRootObject(exec->dynamicGlobalObject());
+    if (!rootObject)
+        return nil;
+    return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject.get() rootObject:rootObject.get()];
+}
+
+void ObjcField::setValueToInstance(ExecState* exec, const Instance* instance, JSValue* aValue) const
+{
+    id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+    id value = convertValueToObjcObject(exec, aValue);
+
+   JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+    @try {
+        NSString* key = [NSString stringWithCString:name() encoding:NSASCIIStringEncoding];
+        [targetObject setValue:value forKey:key];
+    } @catch(NSException* localException) {
+        JSLock::lock();
+        throwError(exec, GeneralError, [localException reason]);
+        JSLock::unlock();
+    }
+}
+
+// ---------------------- ObjcArray ----------------------
+
+ObjcArray::ObjcArray(ObjectStructPtr a, PassRefPtr<RootObject> rootObject)
+    : Array(rootObject)
+    , _array(a)
+{
+}
+
+void ObjcArray::setValueAt(ExecState* exec, unsigned int index, JSValue* aValue) const
+{
+    if (![_array.get() respondsToSelector:@selector(insertObject:atIndex:)]) {
+        throwError(exec, TypeError, "Array is not mutable.");
+        return;
+    }
+
+    if (index > [_array.get() count]) {
+        throwError(exec, RangeError, "Index exceeds array size.");
+        return;
+    }
+    
+    // Always try to convert the value to an ObjC object, so it can be placed in the
+    // array.
+    ObjcValue oValue = convertValueToObjcValue (exec, aValue, ObjcObjectType);
+
+    @try {
+        [_array.get() insertObject:oValue.objectValue atIndex:index];
+    } @catch(NSException* localException) {
+        throwError(exec, GeneralError, "Objective-C exception.");
+    }
+}
+
+JSValue* ObjcArray::valueAt(ExecState* exec, unsigned int index) const
+{
+    if (index > [_array.get() count])
+        return throwError(exec, RangeError, "Index exceeds array size.");
+    @try {
+        id obj = [_array.get() objectAtIndex:index];
+        if (obj)
+            return convertObjcValueToValue (exec, &obj, ObjcObjectType, _rootObject.get());
+    } @catch(NSException* localException) {
+        return throwError(exec, GeneralError, "Objective-C exception.");
+    }
+    return jsUndefined();
+}
+
+unsigned int ObjcArray::getLength() const
+{
+    return [_array.get() count];
+}
+
+const ClassInfo ObjcFallbackObjectImp::info = { "ObjcFallbackObject", 0, 0 };
+
+ObjcFallbackObjectImp::ObjcFallbackObjectImp(ObjcInstance* i, const KJS::Identifier propertyName)
+: _instance(i)
+, _item(propertyName)
+{
+}
+
+bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot& slot)
+{
+    // keep the prototype from getting called instead of just returning false
+    slot.setUndefined(this);
+    return true;
+}
+
+void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue*)
+{
+}
+
+JSType ObjcFallbackObjectImp::type() const
+{
+    id targetObject = _instance->getObject();
+    
+    if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+        return ObjectType;
+    
+    return UndefinedType;
+}
+
+bool ObjcFallbackObjectImp::implementsCall() const
+{
+    id targetObject = _instance->getObject();
+    
+    if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+        return true;
+    
+    return false;
+}
+
+JSValue* ObjcFallbackObjectImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
+{
+    if (thisObj->classInfo() != &KJS::RuntimeObjectImp::info)
+        return throwError(exec, TypeError);
+
+    JSValue* result = jsUndefined();
+
+    RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(thisObj);
+    Instance* instance = imp->getInternalInstance();
+
+    if (!instance)
+        return RuntimeObjectImp::throwInvalidAccessError(exec);
+    
+    instance->begin();
+
+    ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
+    id targetObject = objcInstance->getObject();
+    
+    if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
+        MethodList methodList;
+        ObjcClass* objcClass = static_cast<ObjcClass*>(instance->getClass());
+        ObjcMethod* fallbackMethod = new ObjcMethod (objcClass->isa(), sel_getName(@selector(invokeUndefinedMethodFromWebScript:withArguments:)));
+        fallbackMethod->setJavaScriptName((CFStringRef)[NSString stringWithCString:_item.ascii() encoding:NSASCIIStringEncoding]);
+        methodList.append(fallbackMethod);
+        result = instance->invokeMethod(exec, methodList, args);
+        delete fallbackMethod;
+    }
+            
+    instance->end();
+
+    return result;
+}
+
+bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+    return false;
+}
+
+JSValue* ObjcFallbackObjectImp::defaultValue(ExecState* exec, JSType hint) const
+{
+    return _instance->getValueOfUndefinedField(exec, _item, hint);
+}
+
+bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
+{
+    id targetObject = _instance->getObject();
+    
+    if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+        return true;
+    
+    return false;
+}
diff --git a/WebCore/bridge/objc/objc_utility.h b/WebCore/bridge/objc/objc_utility.h
new file mode 100644 (file)
index 0000000..e674fcc
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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. 
+ */
+
+#ifndef KJS_BINDINGS_OBJC_UTILITY_H
+#define KJS_BINDINGS_OBJC_UTILITY_H
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "object.h"
+#include "objc_header.h"
+
+#ifdef __OBJC__
+@class NSString;
+#else
+class NSString;
+#endif
+
+namespace KJS {
+namespace Bindings {
+
+typedef union {
+    ObjectStructPtr objectValue;
+    bool booleanValue;
+    char charValue;
+    short shortValue;
+    int intValue;
+    long longValue;
+    long long longLongValue;
+    float floatValue;
+    double doubleValue;
+} ObjcValue;
+
+typedef enum {
+    ObjcVoidType,
+    ObjcObjectType,
+    ObjcCharType,
+    ObjcUnsignedCharType,
+    ObjcShortType,
+    ObjcUnsignedShortType,
+    ObjcIntType,
+    ObjcUnsignedIntType,
+    ObjcLongType,
+    ObjcUnsignedLongType,
+    ObjcLongLongType,
+    ObjcUnsignedLongLongType,
+    ObjcFloatType,
+    ObjcDoubleType,
+    ObjcInvalidType
+} ObjcValueType;
+
+class RootObject;
+
+ObjcValue convertValueToObjcValue(ExecState *exec, JSValue *value, ObjcValueType type);
+JSValue *convertNSStringToString(NSString *nsstring);
+JSValue *convertObjcValueToValue(ExecState *exec, void *buffer, ObjcValueType type, RootObject*);
+ObjcValueType objcValueTypeForType(const char *type);
+
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize);
+
+JSObject *throwError(ExecState *, ErrorType, NSString *message);
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/objc/objc_utility.mm b/WebCore/bridge/objc/objc_utility.mm
new file mode 100644 (file)
index 0000000..62a0ad0
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "objc_utility.h"
+
+#include "objc_instance.h"
+#include "JSGlobalObject.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.h"
+#include <wtf/Assertions.h>
+
+#if !defined(_C_LNG_LNG)
+#define _C_LNG_LNG 'q'
+#endif
+
+#if !defined(_C_ULNG_LNG)
+#define _C_ULNG_LNG 'Q'
+#endif
+
+#if !defined(_C_CONST)
+#define _C_CONST 'r'
+#endif
+
+#if !defined(_C_BYCOPY)
+#define _C_BYCOPY 'O'
+#endif
+
+#if !defined(_C_BYREF)
+#define _C_BYREF 'R'
+#endif
+
+#if !defined(_C_ONEWAY)
+#define _C_ONEWAY 'V'
+#endif
+
+#if !defined(_C_GCINVISIBLE)
+#define _C_GCINVISIBLE '!'
+#endif
+
+namespace KJS {
+namespace Bindings {
+
+/*
+    By default, a JavaScript method name is produced by concatenating the 
+    components of an ObjectiveC method name, replacing ':' with '_', and 
+    escaping '_' and '$' with a leading '$', such that '_' becomes "$_" and 
+    '$' becomes "$$". For example:
+
+    ObjectiveC name         Default JavaScript name
+        moveTo::                moveTo__
+        moveTo_                 moveTo$_
+        moveTo$_                moveTo$$$_
+
+    This function performs the inverse of that operation.
+    @result Fills 'buffer' with the ObjectiveC method name that corresponds to 'JSName'. 
+            Returns true for success, false for failure. (Failure occurs when 'buffer' 
+            is not big enough to hold the result.)
+*/
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize)
+{
+    ASSERT(JSName && buffer);
+    
+    const char *sp = JSName; // source pointer
+    char *dp = buffer; // destination pointer
+        
+    char *end = buffer + bufferSize;
+    while (dp < end) {
+        if (*sp == '$') {
+            ++sp;
+            *dp = *sp;
+        } else if (*sp == '_')
+            *dp = ':';
+        else
+            *dp = *sp;
+
+        // If a future coder puts funny ++ operators above, we might write off the end 
+        // of the buffer in the middle of this loop. Let's make sure to check for that.
+        ASSERT(dp < end);
+        
+        if (*sp == 0) { // We finished converting JSName
+            ASSERT(strlen(JSName) < bufferSize);
+            return true;
+        }
+        
+        ++sp; 
+        ++dp;
+    }
+
+    return false; // We ran out of buffer before converting JSName
+}
+
+/*
+
+    JavaScript to   ObjC
+    Number          coerced to char, short, int, long, float, double, or NSNumber, as appropriate
+    String          NSString
+    wrapper         id
+    Object          WebScriptObject
+    null            NSNull
+    [], other       exception
+
+*/
+ObjcValue convertValueToObjcValue(ExecState *exec, JSValue *value, ObjcValueType type)
+{
+    ObjcValue result;
+    double d = 0;
+
+    if (value->isNumber() || value->isString() || value->isBoolean())
+        d = value->toNumber(exec);
+
+    switch (type) {
+        case ObjcObjectType: {
+            JSLock lock;
+            
+            JSGlobalObject *originGlobalObject = exec->dynamicGlobalObject();
+            RootObject* originRootObject = findRootObject(originGlobalObject);
+
+            JSGlobalObject* globalObject = 0;
+            if (value->isObject() && static_cast<JSObject*>(value)->isGlobalObject())
+                globalObject = static_cast<JSGlobalObject*>(value);
+
+            if (!globalObject)
+                globalObject = originGlobalObject;
+                
+            RootObject* rootObject = findRootObject(globalObject);
+            result.objectValue =  rootObject
+                ? [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:originRootObject rootObject:rootObject]
+                : nil;
+        }
+        break;
+
+        case ObjcCharType:
+        case ObjcUnsignedCharType:
+            result.charValue = (char)d;
+            break;
+        case ObjcShortType:
+        case ObjcUnsignedShortType:
+            result.shortValue = (short)d;
+            break;
+        case ObjcIntType:
+        case ObjcUnsignedIntType:
+            result.intValue = (int)d;
+            break;
+        case ObjcLongType:
+        case ObjcUnsignedLongType:
+            result.longValue = (long)d;
+            break;
+        case ObjcLongLongType:
+        case ObjcUnsignedLongLongType:
+            result.longLongValue = (long long)d;
+            break;
+        case ObjcFloatType:
+            result.floatValue = (float)d;
+            break;
+        case ObjcDoubleType:
+            result.doubleValue = (double)d;
+            break;
+        case ObjcVoidType:
+            bzero(&result, sizeof(ObjcValue));
+            break;
+
+        case ObjcInvalidType:
+        default:
+            // FIXME: throw an exception?
+            break;
+    }
+
+    return result;
+}
+
+JSValue *convertNSStringToString(NSString *nsstring)
+{
+    JSLock lock;
+    
+    unichar *chars;
+    unsigned int length = [nsstring length];
+    chars = (unichar *)malloc(sizeof(unichar)*length);
+    [nsstring getCharacters:chars];
+    UString u((const UChar*)chars, length);
+    JSValue *aValue = jsString(u);
+    free((void *)chars);
+    return aValue;
+}
+
+/*
+    ObjC      to    JavaScript
+    ----            ----------
+    char            number
+    short           number
+    int             number
+    long            number
+    float           number
+    double          number
+    NSNumber        boolean or number
+    NSString        string
+    NSArray         array
+    NSNull          null
+    WebScriptObject underlying JavaScript object
+    WebUndefined    undefined
+    id              object wrapper
+    other           should not happen
+*/
+JSValue* convertObjcValueToValue(ExecState* exec, void* buffer, ObjcValueType type, RootObject* rootObject)
+{
+    JSLock lock;
+    
+    switch (type) {
+        case ObjcObjectType: {
+            id obj = *(id*)buffer;
+            if ([obj isKindOfClass:[NSString class]])
+                return convertNSStringToString((NSString *)obj);
+            if ([obj isKindOfClass:webUndefinedClass()])
+                return jsUndefined();
+            if ((CFBooleanRef)obj == kCFBooleanTrue)
+                return jsBoolean(true);
+            if ((CFBooleanRef)obj == kCFBooleanFalse)
+                return jsBoolean(false);
+            if ([obj isKindOfClass:[NSNumber class]])
+                return jsNumber([obj doubleValue]);
+            if ([obj isKindOfClass:[NSArray class]])
+                return new RuntimeArray(exec, new ObjcArray(obj, rootObject));
+            if ([obj isKindOfClass:webScriptObjectClass()]) {
+                JSObject* imp = [obj _imp];
+                return imp ? imp : jsUndefined();
+            }
+            if ([obj isKindOfClass:[NSNull class]])
+                return jsNull();
+            if (obj == 0)
+                return jsUndefined();
+            return Instance::createRuntimeObject(Instance::ObjectiveCLanguage, obj, rootObject);
+        }
+        case ObjcCharType:
+            return jsNumber(*(char *)buffer);
+        case ObjcUnsignedCharType:
+            return jsNumber(*(unsigned char *)buffer);
+        case ObjcShortType:
+            return jsNumber(*(short *)buffer);
+        case ObjcUnsignedShortType:
+            return jsNumber(*(unsigned short *)buffer);
+        case ObjcIntType:
+            return jsNumber(*(int *)buffer);
+        case ObjcUnsignedIntType:
+            return jsNumber(*(unsigned int *)buffer);
+        case ObjcLongType:
+            return jsNumber(*(long *)buffer);
+        case ObjcUnsignedLongType:
+            return jsNumber(*(unsigned long *)buffer);
+        case ObjcLongLongType:
+            return jsNumber(*(long long *)buffer);
+        case ObjcUnsignedLongLongType:
+            return jsNumber(*(unsigned long long *)buffer);
+        case ObjcFloatType:
+            return jsNumber(*(float *)buffer);
+        case ObjcDoubleType:
+            return jsNumber(*(double *)buffer);
+        default:
+            // Should never get here. Argument types are filtered.
+            fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+            ASSERT(false);
+    }
+    
+    return 0;
+}
+
+ObjcValueType objcValueTypeForType(const char *type)
+{
+    int typeLength = strlen(type);
+    ObjcValueType objcValueType = ObjcInvalidType;
+
+    for (int i = 0; i < typeLength; ++i) {
+        char typeChar = type[i];
+        switch (typeChar) {
+            case _C_CONST:
+            case _C_BYCOPY:
+            case _C_BYREF:
+            case _C_ONEWAY:
+            case _C_GCINVISIBLE:
+                // skip these type modifiers
+                break;
+            case _C_ID:
+                objcValueType = ObjcObjectType;
+                break;
+            case _C_CHR:
+                objcValueType = ObjcCharType;
+                break;
+            case _C_UCHR:
+                objcValueType = ObjcUnsignedCharType;
+                break;
+            case _C_SHT:
+                objcValueType = ObjcShortType;
+                break;
+            case _C_USHT:
+                objcValueType = ObjcUnsignedShortType;
+                break;
+            case _C_INT:
+                objcValueType = ObjcIntType;
+                break;
+            case _C_UINT:
+                objcValueType = ObjcUnsignedIntType;
+                break;
+            case _C_LNG:
+                objcValueType = ObjcLongType;
+                break;
+            case _C_ULNG:
+                objcValueType = ObjcUnsignedLongType;
+                break;
+            case _C_LNG_LNG:
+                objcValueType = ObjcLongLongType;
+                break;
+            case _C_ULNG_LNG:
+                objcValueType = ObjcUnsignedLongLongType;
+                break;
+            case _C_FLT:
+                objcValueType = ObjcFloatType;
+                break;
+            case _C_DBL:
+                objcValueType = ObjcDoubleType;
+                break;
+            case _C_VOID:
+                objcValueType = ObjcVoidType;
+                break;
+            default:
+                // Unhandled type. We don't handle C structs, unions, etc.
+                // FIXME: throw an exception?
+                ASSERT(false);
+        }
+
+        if (objcValueType != ObjcInvalidType)
+            break;
+    }
+
+    return objcValueType;
+}
+
+JSObject *throwError(ExecState *exec, ErrorType type, NSString *message)
+{
+    ASSERT(message);
+    size_t length = [message length];
+    unichar *buffer = new unichar[length];
+    [message getCharacters:buffer];
+    JSObject *error = throwError(exec, type, UString(reinterpret_cast<UChar *>(buffer), length));
+    delete [] buffer;
+    return error;
+}
+
+}
+}
diff --git a/WebCore/bridge/qt/qt_class.cpp b/WebCore/bridge/qt/qt_class.cpp
new file mode 100644 (file)
index 0000000..59730b8
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "identifier.h"
+
+#include "qt_class.h"
+#include "qt_instance.h"
+#include "qt_runtime.h"
+
+#include <qmetaobject.h>
+#include <qdebug.h>
+
+namespace KJS {
+namespace Bindings {
+
+QtClass::QtClass(const QMetaObject* mo)
+    : m_metaObject(mo)
+{
+}
+
+QtClass::~QtClass()
+{
+}
+
+typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
+static ClassesByMetaObject* classesByMetaObject = 0;
+
+QtClass* QtClass::classForObject(QObject* o)
+{
+    if (!classesByMetaObject)
+        classesByMetaObject = new ClassesByMetaObject;
+
+    const QMetaObject* mo = o->metaObject();
+    QtClass* aClass = classesByMetaObject->get(mo);
+    if (!aClass) {
+        aClass = new QtClass(mo);
+        classesByMetaObject->set(mo, aClass);
+    }
+
+    return aClass;
+}
+
+const char* QtClass::name() const
+{
+    return m_metaObject->className();
+}
+
+// We use this to get at signals (so we can return a proper function object,
+// and not get wrapped in RuntimeMethod).  Also, use this for methods,
+// so we can cache the JSValue* and return the same JSValue for the same
+// identifier...
+//
+// Unfortunately... we need to gcProtect our JSValues, since we don't have
+// access to an actual JS class that can mark() our JSValues.
+//
+JSValue* QtClass::fallbackObject(ExecState *exec, Instance *inst, const Identifier &identifier)
+{
+    QtInstance* qtinst = static_cast<QtInstance*>(inst);
+
+    QByteArray name(identifier.ascii());
+
+    // First see if we have a cache hit
+    JSValue* val = qtinst->m_methods.value(name);
+    if (val)
+        return val;
+
+    // Nope, create an entry
+    QByteArray normal = QMetaObject::normalizedSignature(name.constData());
+
+    // See if there is an exact match
+    int index = -1;
+    if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
+        QMetaMethod m = m_metaObject->method(index);
+        if (m.access() != QMetaMethod::Private) {
+            JSValue *val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+            gcProtect(val);
+            qtinst->m_methods.insert(name, val);
+            return val;
+        }
+    }
+
+    // Nope.. try a basename match
+    int count = m_metaObject->methodCount();
+    for (index = count - 1; index >= 0; --index) {
+        const QMetaMethod m = m_metaObject->method(index);
+        if (m.access() == QMetaMethod::Private)
+            continue;
+
+        QByteArray signature = m.signature();
+        signature.truncate(signature.indexOf('('));
+
+        if (normal == signature) {
+            JSValue* val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+            gcProtect(val);
+            qtinst->m_methods.insert(name, val);
+            return val;
+        }
+    }
+
+    return jsUndefined();
+}
+
+// This functionality is handled by the fallback case above...
+MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
+{
+    return MethodList();
+}
+
+// ### we may end up with a different search order than QtScript by not
+// folding this code into the fallbackMethod above, but Fields propagate out
+// of the binding code
+Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+    // Check static properties first
+    QtInstance* qtinst = static_cast<QtInstance*>(instance);
+
+    QObject* obj = qtinst->getObject();
+    UString ustring = identifier.ustring();
+    QString objName(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
+    QByteArray ba = objName.toAscii();
+
+    // First check for a cached field
+    QtField* f = qtinst->m_fields.value(objName);
+
+    if (obj) {
+        if (f) {
+            // We only cache real metaproperties, but we do store the
+            // other types so we can delete them later
+            if (f->fieldType() == QtField::MetaProperty)
+                return f;
+            else if (f->fieldType() == QtField::DynamicProperty) {
+                if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
+                    return f;
+                else {
+                    // Dynamic property that disappeared
+                    qtinst->m_fields.remove(objName);
+                    delete f;
+                }
+            } else {
+                QList<QObject*> children = obj->children();
+                for (int index = 0; index < children.count(); ++index) {
+                    QObject *child = children.at(index);
+                    if (child->objectName() == objName)
+                        return f;
+                }
+
+                // Didn't find it, delete it from the cache
+                qtinst->m_fields.remove(objName);
+                delete f;
+            }
+        }
+
+        int index = m_metaObject->indexOfProperty(identifier.ascii());
+        if (index >= 0) {
+            QMetaProperty prop = m_metaObject->property(index);
+
+            if (prop.isScriptable(obj)) {
+                f = new QtField(prop);
+                qtinst->m_fields.insert(objName, f);
+                return f;
+            }
+        }
+
+        // Dynamic properties
+        index = obj->dynamicPropertyNames().indexOf(ba);
+        if (index >= 0) {
+            f = new QtField(ba);
+            qtinst->m_fields.insert(objName, f);
+            return f;
+        }
+
+        // Child objects
+
+        QList<QObject*> children = obj->children();
+        for (index = 0; index < children.count(); ++index) {
+            QObject *child = children.at(index);
+            if (child->objectName() == objName) {
+                f = new QtField(child);
+                qtinst->m_fields.insert(objName, f);
+                return f;
+            }
+        }
+
+        // Nothing named this
+        return 0;
+    } else {
+        QByteArray ba(identifier.ascii());
+        // For compatibility with qtscript, cached methods don't cause
+        // errors until they are accessed, so don't blindly create an error
+        // here.
+        if (qtinst->m_methods.contains(ba))
+            return 0;
+
+        // deleted qobject, but can't throw an error from here (no exec)
+        // create a fake QtField that will throw upon access
+        if (!f) {
+            f = new QtField(ba);
+            qtinst->m_fields.insert(objName, f);
+        }
+        return f;
+    }
+}
+
+}
+}
+
diff --git a/WebCore/bridge/qt/qt_class.h b/WebCore/bridge/qt/qt_class.h
new file mode 100644 (file)
index 0000000..c3e59ec
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef BINDINGS_QT_CLASS_H_
+#define BINDINGS_QT_CLASS_H_
+
+#include "runtime.h"
+class QObject;
+class QMetaObject;
+
+namespace KJS {
+namespace Bindings {
+
+
+class QtClass : public Class {
+protected:
+    QtClass(const QMetaObject*);
+
+public:
+    static QtClass* classForObject(QObject*);
+    virtual ~QtClass();
+
+    virtual const char* name() const;
+    virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+    virtual Field* fieldNamed(const Identifier&, Instance*) const;
+
+    virtual JSValue* fallbackObject(ExecState*, Instance*, const Identifier&);
+
+private:
+    QtClass(const QtClass&); // prohibit copying
+    QtClass& operator=(const QtClass&); // prohibit assignment
+
+    const QMetaObject* m_metaObject;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/qt/qt_instance.cpp b/WebCore/bridge/qt/qt_instance.cpp
new file mode 100644 (file)
index 0000000..0197b84
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "qt_instance.h"
+
+#include "JSGlobalObject.h"
+#include "list.h"
+#include "qt_class.h"
+#include "qt_runtime.h"
+#include "PropertyNameArray.h"
+#include "runtime_object.h"
+#include "object_object.h"
+
+#include <qmetaobject.h>
+#include <qdebug.h>
+#include <qmetatype.h>
+#include <qhash.h>
+
+namespace KJS {
+namespace Bindings {
+
+// Cache QtInstances
+typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
+static QObjectInstanceMap cachedInstances;
+
+// Cache JSObjects
+typedef QHash<QtInstance*, JSObject*> InstanceJSObjectMap;
+static InstanceJSObjectMap cachedObjects;
+
+// Derived RuntimeObject
+class QtRuntimeObjectImp : public RuntimeObjectImp {
+    public:
+        QtRuntimeObjectImp(Instance*);
+        ~QtRuntimeObjectImp();
+        virtual void invalidate();
+
+        // Additions
+        virtual bool implementsConstruct() const {return implementsCall();}
+        virtual JSObject* construct(ExecState* exec, const List& args);
+    protected:
+        void removeFromCache();
+};
+
+QtRuntimeObjectImp::QtRuntimeObjectImp(Instance* instance)
+    : RuntimeObjectImp(instance)
+{
+}
+
+QtRuntimeObjectImp::~QtRuntimeObjectImp()
+{
+    removeFromCache();
+}
+
+void QtRuntimeObjectImp::invalidate()
+{
+    removeFromCache();
+    RuntimeObjectImp::invalidate();
+}
+
+void QtRuntimeObjectImp::removeFromCache()
+{
+    JSLock lock;
+    QtInstance* key = cachedObjects.key(this);
+    if (key)
+        cachedObjects.remove(key);
+}
+
+JSObject* QtRuntimeObjectImp::construct(ExecState* exec, const List& args)
+{
+    // ECMA 15.2.2.1 (?)
+    JSValue *val = callAsFunction(exec, this, args);
+
+    if (!val || val->type() == NullType || val->type() == UndefinedType)
+        return new JSObject(exec->lexicalGlobalObject()->objectPrototype());
+    else
+        return val->toObject(exec);
+}
+
+// QtInstance
+QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+    : Instance(rootObject)
+    , m_class(0)
+    , m_object(o)
+    , m_hashkey(o)
+    , m_defaultMethod(0)
+    , m_defaultMethodIndex(-2)
+{
+}
+
+QtInstance::~QtInstance()
+{
+    JSLock lock;
+
+    cachedObjects.remove(this);
+    cachedInstances.remove(m_hashkey);
+
+    // clean up (unprotect from gc) the JSValues we've created
+    foreach(JSValue* val, m_methods.values()) {
+        gcUnprotect(val);
+    }
+    m_methods.clear();
+
+    foreach(QtField* f, m_fields.values()) {
+        delete f;
+    }
+    m_fields.clear();
+
+    if (m_defaultMethod)
+        gcUnprotect(m_defaultMethod);
+}
+
+QtInstance* QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+{
+    JSLock lock;
+
+    foreach(QtInstance* instance, cachedInstances.values(o)) {
+        if (instance->rootObject() == rootObject)
+            return instance;
+    }
+
+    QtInstance* ret = new QtInstance(o, rootObject);
+    cachedInstances.insert(o, ret);
+
+    return ret;
+}
+
+JSObject* QtInstance::getRuntimeObject(QtInstance* instance)
+{
+    JSLock lock;
+    JSObject* ret = cachedObjects.value(instance);
+    if (!ret) {
+        ret = new QtRuntimeObjectImp(instance);
+        cachedObjects.insert(instance, ret);
+    }
+    return ret;
+}
+
+Class* QtInstance::getClass() const
+{
+    if (!m_class)
+        m_class = QtClass::classForObject(m_object);
+    return m_class;
+}
+
+void QtInstance::begin()
+{
+    // Do nothing.
+}
+
+void QtInstance::end()
+{
+    // Do nothing.
+}
+
+void QtInstance::getPropertyNames(ExecState* , PropertyNameArray& array)
+{
+    // This is the enumerable properties, so put:
+    // properties
+    // dynamic properties
+    // slots
+    QObject* obj = getObject();
+    if (obj) {
+        const QMetaObject* meta = obj->metaObject();
+
+        int i;
+        for (i=0; i < meta->propertyCount(); i++) {
+            QMetaProperty prop = meta->property(i);
+            if (prop.isScriptable()) {
+                array.add(Identifier(prop.name()));
+            }
+        }
+
+        QList<QByteArray> dynProps = obj->dynamicPropertyNames();
+        foreach(QByteArray ba, dynProps) {
+            array.add(Identifier(ba.constData()));
+        }
+
+        for (i=0; i < meta->methodCount(); i++) {
+            QMetaMethod method = meta->method(i);
+            if (method.access() != QMetaMethod::Private) {
+                array.add(Identifier(method.signature()));
+            }
+        }
+    }
+}
+
+JSValue* QtInstance::invokeMethod(ExecState*, const MethodList&, const List&)
+{
+    // Implemented via fallbackMethod & QtRuntimeMetaMethod::callAsFunction
+    return jsUndefined();
+}
+
+bool QtInstance::implementsCall() const
+{
+    // See if we have qscript_call
+    if (m_defaultMethodIndex == -2) {
+        if (m_object) {
+            const QMetaObject* meta = m_object->metaObject();
+            int count = meta->methodCount();
+            const QByteArray defsig("qscript_call");
+            for (int index = count - 1; index >= 0; --index) {
+                const QMetaMethod m = meta->method(index);
+
+                QByteArray signature = m.signature();
+                signature.truncate(signature.indexOf('('));
+
+                if (defsig == signature) {
+                    m_defaultMethodIndex = index;
+                    break;
+                }
+            }
+        }
+
+        if (m_defaultMethodIndex == -2) // Not checked
+            m_defaultMethodIndex = -1; // No qscript_call
+    }
+
+    // typeof object that implements call == function
+    return (m_defaultMethodIndex >= 0);
+}
+
+JSValue* QtInstance::invokeDefaultMethod(ExecState* exec, const List& args)
+{
+    // QtScript tries to invoke a meta method qscript_call
+    if (!getObject())
+        return throwError(exec, GeneralError, "cannot call function of deleted QObject");
+
+    // implementsCall will update our default method cache, if possible
+    if (implementsCall()) {
+        if (!m_defaultMethod) {
+            m_defaultMethod = new QtRuntimeMetaMethod(exec, Identifier("[[Call]]"),this, m_defaultMethodIndex, QByteArray("qscript_call"), true);
+            gcProtect(m_defaultMethod);
+        }
+
+        return m_defaultMethod->callAsFunction(exec, 0, args); // Luckily QtRuntimeMetaMethod ignores the obj parameter
+    } else
+        return throwError(exec, TypeError, "not a function");
+}
+
+JSValue* QtInstance::defaultValue(JSType hint) const
+{
+    if (hint == StringType)
+        return stringValue();
+    if (hint == NumberType)
+        return numberValue();
+    if (hint == BooleanType)
+        return booleanValue();
+    return valueOf();
+}
+
+JSValue* QtInstance::stringValue() const
+{
+    // Hmm.. see if there is a toString defined
+    QByteArray buf;
+    bool useDefault = true;
+    getClass();
+    QObject* obj = getObject();
+    if (m_class && obj) {
+        // Cheat and don't use the full name resolution
+        int index = obj->metaObject()->indexOfMethod("toString()");
+        if (index >= 0) {
+            QMetaMethod m = obj->metaObject()->method(index);
+            // Check to see how much we can call it
+            if (m.access() != QMetaMethod::Private
+                && m.methodType() != QMetaMethod::Signal
+                && m.parameterTypes().count() == 0) {
+                const char* retsig = m.typeName();
+                if (retsig && *retsig) {
+                    QVariant ret(QMetaType::type(retsig), (void*)0);
+                    void * qargs[1];
+                    qargs[0] = ret.data();
+
+                    if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, index, qargs) < 0) {
+                        if (ret.isValid() && ret.canConvert(QVariant::String)) {
+                            buf = ret.toString().toLatin1().constData(); // ### Latin 1? Ascii?
+                            useDefault = false;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (useDefault) {
+        const QMetaObject* meta = obj ? obj->metaObject() : &QObject::staticMetaObject;
+        QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed");
+        QString str = QString::fromUtf8("%0(name = \"%1\")")
+                      .arg(QLatin1String(meta->className())).arg(name);
+
+        buf = str.toLatin1();
+    }
+    return jsString(buf.constData());
+}
+
+JSValue* QtInstance::numberValue() const
+{
+    return jsNumber(0);
+}
+
+JSValue* QtInstance::booleanValue() const
+{
+    // ECMA 9.2
+    return jsBoolean(true);
+}
+
+JSValue* QtInstance::valueOf() const
+{
+    return stringValue();
+}
+
+// In qt_runtime.cpp
+JSValue* convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance);
+
+const char* QtField::name() const
+{
+    if (m_type == MetaProperty)
+        return m_property.name();
+    else if (m_type == ChildObject && m_childObject)
+        return m_childObject->objectName().toLatin1();
+    else if (m_type == DynamicProperty)
+        return m_dynamicProperty.constData();
+    return ""; // deleted child object
+}
+
+JSValue* QtField::valueFromInstance(ExecState* exec, const Instance* inst) const
+{
+    const QtInstance* instance = static_cast<const QtInstance*>(inst);
+    QObject* obj = instance->getObject();
+
+    if (obj) {
+        QVariant val;
+        if (m_type == MetaProperty) {
+            if (m_property.isReadable())
+                val = m_property.read(obj);
+            else
+                return jsUndefined();
+        } else if (m_type == ChildObject)
+            val = QVariant::fromValue((QObject*) m_childObject);
+        else if (m_type == DynamicProperty)
+            val = obj->property(m_dynamicProperty);
+
+        return convertQVariantToValue(exec, inst->rootObject(), val);
+    } else {
+        QString msg = QString("cannot access member `%1' of deleted QObject").arg(name());
+        return throwError(exec, GeneralError, msg.toLatin1().constData());
+    }
+}
+
+void QtField::setValueToInstance(ExecState* exec, const Instance* inst, JSValue* aValue) const
+{
+    if (m_type == ChildObject) // QtScript doesn't allow setting to a named child
+        return;
+
+    const QtInstance* instance = static_cast<const QtInstance*>(inst);
+    QObject* obj = instance->getObject();
+    if (obj) {
+        QMetaType::Type argtype = QMetaType::Void;
+        if (m_type == MetaProperty)
+            argtype = (QMetaType::Type) QMetaType::type(m_property.typeName());
+
+        // dynamic properties just get any QVariant
+        QVariant val = convertValueToQVariant(exec, aValue, argtype, 0);
+        if (m_type == MetaProperty) {
+            if (m_property.isWritable())
+                m_property.write(obj, val);
+        } else if (m_type == DynamicProperty)
+            obj->setProperty(m_dynamicProperty.constData(), val);
+    } else {
+        QString msg = QString("cannot access member `%1' of deleted QObject").arg(name());
+        throwError(exec, GeneralError, msg.toLatin1().constData());
+    }
+}
+
+
+}
+}
diff --git a/WebCore/bridge/qt/qt_instance.h b/WebCore/bridge/qt/qt_instance.h
new file mode 100644 (file)
index 0000000..2304ac5
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef BINDINGS_QT_INSTANCE_H_
+#define BINDINGS_QT_INSTANCE_H_
+
+#include "runtime.h"
+#include "runtime_root.h"
+#include <qpointer.h>
+#include <qhash.h>
+
+class QObject;
+
+namespace KJS {
+
+namespace Bindings {
+
+class QtClass;
+class QtField;
+class QtRuntimeMetaMethod;
+
+class QtInstance : public Instance
+{
+public:
+    ~QtInstance ();
+
+    virtual Class* getClass() const;
+
+    virtual void begin();
+    virtual void end();
+
+    virtual JSValue* valueOf() const;
+    virtual JSValue* defaultValue (JSType hint) const;
+
+    virtual bool implementsCall() const;
+
+    virtual JSValue* invokeMethod (ExecState *exec, const MethodList &method, const List &args);
+    virtual JSValue* invokeDefaultMethod (ExecState *exec, const List &args);
+
+    virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+    virtual BindingLanguage getBindingLanguage() const { return QtLanguage; }
+
+    JSValue* stringValue() const;
+    JSValue* numberValue() const;
+    JSValue* booleanValue() const;
+
+    QObject* getObject() const { return m_object; }
+
+    static QtInstance* getQtInstance(QObject*, PassRefPtr<RootObject>);
+    static JSObject* getRuntimeObject(QtInstance*);
+
+private:
+    friend class QtClass;
+    QtInstance(QObject*, PassRefPtr<RootObject>); // Factory produced only..
+    mutable QtClass* m_class;
+    QPointer<QObject> m_object;
+    QObject* m_hashkey;
+    mutable QHash<QByteArray,JSValue*> m_methods;
+    mutable QHash<QString,QtField*> m_fields;
+    mutable QtRuntimeMetaMethod* m_defaultMethod;
+    mutable int m_defaultMethodIndex;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/WebCore/bridge/qt/qt_runtime.cpp b/WebCore/bridge/qt/qt_runtime.cpp
new file mode 100644 (file)
index 0000000..113f0c5
--- /dev/null
@@ -0,0 +1,1590 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "qt_runtime.h"
+#include "qt_instance.h"
+#include "object.h"
+#include "array_instance.h"
+#include "date_object.h"
+#include "DateMath.h"
+#include "regexp_object.h"
+#include <runtime_object.h>
+#include <runtime_array.h>
+#include <function.h>
+#include "PropertyNameArray.h"
+#include "qmetatype.h"
+#include "qmetaobject.h"
+#include "qobject.h"
+#include "qstringlist.h"
+#include "qdebug.h"
+#include "qvarlengtharray.h"
+#include "qdatetime.h"
+#include <limits.h>
+
+// QtScript has these
+Q_DECLARE_METATYPE(QObjectList);
+Q_DECLARE_METATYPE(QList<int>);
+Q_DECLARE_METATYPE(QVariant);
+
+
+namespace KJS {
+namespace Bindings {
+
+// Debugging
+//#define QTWK_RUNTIME_CONVERSION_DEBUG
+//#define QTWK_RUNTIME_MATCH_DEBUG
+
+class QWKNoDebug
+{
+public:
+    inline QWKNoDebug(){}
+    inline ~QWKNoDebug(){}
+
+    template<typename T>
+    inline QWKNoDebug &operator<<(const T &) { return *this; }
+};
+
+#ifdef QTWK_RUNTIME_CONVERSION_DEBUG
+#define qConvDebug() qDebug()
+#else
+#define qConvDebug() QWKNoDebug()
+#endif
+
+#ifdef QTWK_RUNTIME_MATCH_DEBUG
+#define qMatchDebug() qDebug()
+#else
+#define qMatchDebug() QWKNoDebug()
+#endif
+
+typedef enum {
+    Variant,
+    Number,
+    Boolean,
+    String,
+    Date,
+    RegExp,
+    Array,
+    QObj,
+    Object,
+    Null
+} JSRealType;
+
+static JSRealType valueRealType(ExecState* exec, JSValue* val)
+{
+    if (val->isNumber())
+        return Number;
+    else if (val->isString())
+        return String;
+    else if (val->isBoolean())
+        return Boolean;
+    else if (val->isNull())
+        return Null;
+    else if (val->isObject()) {
+        JSObject *object = val->toObject(exec);
+        if (object->inherits(&ArrayInstance::info))
+            return Array;
+        else if (object->inherits(&DateInstance::info))
+            return Date;
+        else if (object->inherits(&RegExpImp::info))
+            return RegExp;
+        else if (object->inherits(&RuntimeObjectImp::info))
+            return QObj;
+        return Object;
+    }
+
+    return String; // I don't know.
+}
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance)
+{
+    // check magic pointer values before dereferencing value
+    if (value == jsNaN() || value == jsUndefined()) {
+        if (distance)
+            *distance = -1;
+        return QVariant();
+    }
+
+    JSLock lock;
+    JSRealType type = valueRealType(exec, value);
+    if (hint == QMetaType::Void) {
+        switch(type) {
+            case Number:
+                hint = QMetaType::Double;
+                break;
+            case Boolean:
+                hint = QMetaType::Bool;
+                break;
+            case String:
+            default:
+                hint = QMetaType::QString;
+                break;
+            case Date:
+                hint = QMetaType::QDateTime;
+                break;
+            case RegExp:
+                hint = QMetaType::QRegExp;
+                break;
+            case QObj:
+                hint = QMetaType::QObjectStar;
+                break;
+            case Array:
+                hint = QMetaType::QVariantList;
+                break;
+        }
+    }
+
+    if (value == jsNull() 
+        && hint != QMetaType::QObjectStar
+        && hint != QMetaType::VoidStar) {
+        if (distance)
+            *distance = -1;
+        return QVariant();
+    }
+
+    QVariant ret;
+    int dist = -1;
+    switch (hint) {
+        case QMetaType::Bool:
+            ret = QVariant(value->toBoolean(exec));
+            if (type == Boolean)
+                dist = 0;
+            else
+                dist = 10;
+            break;
+
+        case QMetaType::Int:
+        case QMetaType::UInt:
+        case QMetaType::Long:
+        case QMetaType::ULong:
+        case QMetaType::LongLong:
+        case QMetaType::ULongLong:
+        case QMetaType::Short:
+        case QMetaType::UShort:
+        case QMetaType::Float:
+        case QMetaType::Double:
+            ret = QVariant(value->toNumber(exec));
+            ret.convert((QVariant::Type)hint);
+            if (type == Number) {
+                switch (hint) {
+                case QMetaType::Double:
+                    dist = 0;
+                    break;
+                case QMetaType::Float:
+                    dist = 1;
+                    break;
+                case QMetaType::LongLong:
+                case QMetaType::ULongLong:
+                    dist = 2;
+                    break;
+                case QMetaType::Long:
+                case QMetaType::ULong:
+                    dist = 3;
+                    break;
+                case QMetaType::Int:
+                case QMetaType::UInt:
+                    dist = 4;
+                    break;
+                case QMetaType::Short:
+                case QMetaType::UShort:
+                    dist = 5;
+                    break;
+                    break;
+                default:
+                    dist = 10;
+                    break;
+                }
+            } else {
+                dist = 10;
+            }
+            break;
+
+        case QMetaType::QChar:
+            if (type == Number || type == Boolean) {
+                ret = QVariant(QChar((ushort)value->toNumber(exec)));
+                if (type == Boolean)
+                    dist = 3;
+                else
+                    dist = 6;
+            } else {
+                UString str = value->toString(exec);
+                ret = QVariant(QChar(str.size() ? *(const ushort*)str.rep()->data() : 0));
+                if (type == String)
+                    dist = 3;
+                else
+                    dist = 10;
+            }
+            break;
+
+        case QMetaType::QString: {
+            UString ustring = value->toString(exec);
+            ret = QVariant(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
+            if (type == String)
+                dist = 0;
+            else
+                dist = 10;
+            break;
+        }
+
+        case QMetaType::QVariantMap: 
+            if (type == Object || type == Array) {
+                // Enumerate the contents of the object
+                JSObject* object = value->toObject(exec);
+
+                PropertyNameArray properties;
+                object->getPropertyNames(exec, properties);
+                PropertyNameArray::const_iterator it = properties.begin();
+
+                QVariantMap result;
+                int objdist = 0;
+                while(it != properties.end()) {
+                    if (object->propertyIsEnumerable(exec, *it)) {
+                        JSValue* val = object->get(exec, *it);
+                        QVariant v = convertValueToQVariant(exec, val, QMetaType::Void, &objdist);
+                        if (objdist >= 0) {
+                            UString ustring = (*it).ustring();
+                            QString id = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+                            result.insert(id, v);
+                        }
+                    }
+                    ++it;
+                }
+                dist = 1;
+                ret = QVariant(result);
+            }
+            break;
+
+        case QMetaType::QVariantList:
+            if (type == Array) {
+                JSObject* object = value->toObject(exec);
+                ArrayInstance* array = static_cast<ArrayInstance*>(object);
+
+                QVariantList result;
+                int len = array->getLength();
+                int objdist = 0;
+                for (int i = 0; i < len; ++i) {
+                    JSValue *val = array->getItem(i);
+                    result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist));
+                    if (objdist == -1)
+                        break; // Failed converting a list entry, so fail the array
+                }
+                if (objdist != -1) {
+                    dist = 5;
+                    ret = QVariant(result);
+                }
+            } else {
+                // Make a single length array
+                QVariantList result;
+                int objdist;
+                result.append(convertValueToQVariant(exec, value, QMetaType::Void, &objdist));
+                if (objdist != -1) {
+                    ret = QVariant(result);
+                    dist = 10;
+                }
+            }
+            break;
+
+        case QMetaType::QStringList: {
+            if (type == Array) {
+                JSObject* object = value->toObject(exec);
+                ArrayInstance* array = static_cast<ArrayInstance*>(object);
+
+                QStringList result;
+                int len = array->getLength();
+                for (int i = 0; i < len; ++i) {
+                    JSValue* val = array->getItem(i);
+                    UString ustring = val->toString(exec);
+                    QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+                    result.append(qstring);
+                }
+                dist = 5;
+                ret = QVariant(result);
+            } else {
+                // Make a single length array
+                UString ustring = value->toString(exec);
+                QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+                QStringList result;
+                result.append(qstring);
+                ret = QVariant(result);
+                dist = 10;
+            }
+            break;
+        }
+
+        case QMetaType::QByteArray: {
+            UString ustring = value->toString(exec);
+            ret = QVariant(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()).toLatin1());
+            if (type == String)
+                dist = 5;
+            else
+                dist = 10;
+            break;
+        }
+
+        case QMetaType::QDateTime:
+        case QMetaType::QDate:
+        case QMetaType::QTime:
+            if (type == Date) {
+                JSObject* object = value->toObject(exec);
+                DateInstance* date = static_cast<DateInstance*>(object);
+                GregorianDateTime gdt;
+                date->getUTCTime(gdt);
+                if (hint == QMetaType::QDateTime) {
+                    ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
+                    dist = 0;
+                } else if (hint == QMetaType::QDate) {
+                    ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
+                    dist = 1;
+                } else {
+                    ret = QTime(gdt.hour + 1900, gdt.minute, gdt.second);
+                    dist = 2;
+                }
+            } else if (type == Number) {
+                double b = value->toNumber(exec);
+                GregorianDateTime gdt;
+                msToGregorianDateTime(b, true, gdt);
+                if (hint == QMetaType::QDateTime) {
+                    ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
+                    dist = 6;
+                } else if (hint == QMetaType::QDate) {
+                    ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
+                    dist = 8;
+                } else {
+                    ret = QTime(gdt.hour, gdt.minute, gdt.second);
+                    dist = 10;
+                }
+            } else if (type == String) {
+                UString ustring = value->toString(exec);
+                QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+                if (hint == QMetaType::QDateTime) {
+                    QDateTime dt = QDateTime::fromString(qstring, Qt::ISODate);
+                    if (!dt.isValid())
+                        dt = QDateTime::fromString(qstring, Qt::TextDate);
+                    if (!dt.isValid())
+                        dt = QDateTime::fromString(qstring, Qt::SystemLocaleDate);
+                    if (!dt.isValid())
+                        dt = QDateTime::fromString(qstring, Qt::LocaleDate);
+                    if (dt.isValid()) {
+                        ret = dt;
+                        dist = 2;
+                    }
+                } else if (hint == QMetaType::QDate) {
+                    QDate dt = QDate::fromString(qstring, Qt::ISODate);
+                    if (!dt.isValid())
+                        dt = QDate::fromString(qstring, Qt::TextDate);
+                    if (!dt.isValid())
+                        dt = QDate::fromString(qstring, Qt::SystemLocaleDate);
+                    if (!dt.isValid())
+                        dt = QDate::fromString(qstring, Qt::LocaleDate);
+                    if (dt.isValid()) {
+                        ret = dt;
+                        dist = 3;
+                    }
+                } else {
+                    QTime dt = QTime::fromString(qstring, Qt::ISODate);
+                    if (!dt.isValid())
+                        dt = QTime::fromString(qstring, Qt::TextDate);
+                    if (!dt.isValid())
+                        dt = QTime::fromString(qstring, Qt::SystemLocaleDate);
+                    if (!dt.isValid())
+                        dt = QTime::fromString(qstring, Qt::LocaleDate);
+                    if (dt.isValid()) {
+                        ret = dt;
+                        dist = 3;
+                    }
+                }
+            }
+            break;
+
+        case QMetaType::QRegExp:
+            if (type == RegExp) {
+/*                JSObject *object = value->toObject(exec);
+                RegExpImp *re = static_cast<RegExpImp*>(object);
+*/
+                // Attempt to convert.. a bit risky
+                UString ustring = value->toString(exec);
+                QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+                // this is of the form '/xxxxxx/i'
+                int firstSlash = qstring.indexOf('/');
+                int lastSlash = qstring.lastIndexOf('/');
+                if (firstSlash >=0 && lastSlash > firstSlash) {
+                    QRegExp realRe;
+
+                    realRe.setPattern(qstring.mid(firstSlash + 1, lastSlash - firstSlash - 1));
+
+                    if (qstring.mid(lastSlash + 1).contains('i'))
+                        realRe.setCaseSensitivity(Qt::CaseInsensitive);
+
+                    ret = qVariantFromValue(realRe);
+                    dist = 0;
+                } else {
+                    qConvDebug() << "couldn't parse a JS regexp";
+                }
+            } else if (type == String) {
+                UString ustring = value->toString(exec);
+                QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+                QRegExp re(qstring);
+                if (re.isValid()) {
+                    ret = qVariantFromValue(re);
+                    dist = 10;
+                }
+            }
+            break;
+
+        case QMetaType::QObjectStar:
+            if (type == QObj) {
+                JSObject* object = value->toObject(exec);
+                QtInstance* qtinst = static_cast<QtInstance*>(Instance::getInstance(object, Instance::QtLanguage));
+                if (qtinst) {
+                    if (qtinst->getObject()) {
+                        qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
+                        ret = qVariantFromValue(qtinst->getObject());
+                        qConvDebug() << ret;
+                        dist = 0;
+                    } else {
+                        qConvDebug() << "can't convert deleted qobject";
+                    }
+                } else {
+                    qConvDebug() << "wasn't a qtinstance";
+                }
+            } else if (type == Null) {
+                QObject* nullobj = 0;
+                ret = qVariantFromValue(nullobj);
+                dist = 0;
+            } else {
+                qConvDebug() << "previous type was not an object:" << type;
+            }
+            break;
+
+        case QMetaType::VoidStar:
+            if (type == QObj) {
+                JSObject* object = value->toObject(exec);
+                QtInstance* qtinst = static_cast<QtInstance*>(Instance::getInstance(object, Instance::QtLanguage));
+                if (qtinst) {
+                    if (qtinst->getObject()) {
+                        qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
+                        ret = qVariantFromValue((void *)qtinst->getObject());
+                        qConvDebug() << ret;
+                        dist = 0;
+                    } else {
+                        qConvDebug() << "can't convert deleted qobject";
+                    }
+                } else {
+                    qConvDebug() << "wasn't a qtinstance";
+                }
+            } else if (type == Null) {
+                ret = qVariantFromValue((void*)0);
+                dist = 0;
+            } else if (type == Number) {
+                // I don't think that converting a double to a pointer is a wise
+                // move.  Except maybe 0.
+                qConvDebug() << "got number for void * - not converting, seems unsafe:" << value->toNumber(exec);
+            } else {
+                qConvDebug() << "void* - unhandled type" << type;
+            }
+            break;
+
+        default:
+            // Non const type ids
+            if (hint == (QMetaType::Type) qMetaTypeId<QObjectList>())
+            {
+                if (type == Array) {
+                    JSObject* object = value->toObject(exec);
+                    ArrayInstance* array = static_cast<ArrayInstance *>(object);
+
+                    QObjectList result;
+                    int len = array->getLength();
+                    for (int i = 0; i < len; ++i) {
+                        JSValue *val = array->getItem(i);
+                        int itemdist = -1;
+                        QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist);
+                        if (itemdist >= 0)
+                            result.append(item.value<QObject*>());
+                        else
+                            break;
+                    }
+                    // If we didn't fail conversion
+                    if (result.count() == len) {
+                        dist = 5;
+                        ret = QVariant::fromValue(result);
+                    } else {
+                        qConvDebug() << "type conversion failed (wanted" << len << ", got " << result.count() << ")";
+                    }
+                } else {
+                    // Make a single length array
+                    QObjectList result;
+                    int itemdist = -1;
+                    QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist);
+                    if (itemdist >= 0) {
+                        result.append(item.value<QObject*>());
+                        dist = 10;
+                        ret = QVariant::fromValue(result);
+                    }
+                }
+                break;
+            } else if (hint == (QMetaType::Type) qMetaTypeId<QList<int> >()) {
+                if (type == Array) {
+                    JSObject* object = value->toObject(exec);
+                    ArrayInstance* array = static_cast<ArrayInstance *>(object);
+
+                    QList<int> result;
+                    int len = array->getLength();
+                    for (int i = 0; i < len; ++i) {
+                        JSValue* val = array->getItem(i);
+                        int itemdist = -1;
+                        QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist);
+                        if (itemdist >= 0)
+                            result.append(item.value<int>());
+                        else
+                            break;
+                    }
+                    // If we didn't fail conversion
+                    if (result.count() == len) {
+                        dist = 5;
+                        ret = QVariant::fromValue(result);
+                    } else {
+                        qConvDebug() << "type conversion failed (wanted" << len << ", got " << result.count() << ")";
+                    }
+                } else {
+                    // Make a single length array
+                    QList<int> result;
+                    int itemdist = -1;
+                    QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist);
+                    if (itemdist >= 0) {
+                        result.append(item.value<int>());
+                        dist = 10;
+                        ret = QVariant::fromValue(result);
+                    }
+                }
+                break;
+            } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) {
+                // Well.. we can do anything... just recurse with the autodetect flag
+                ret = convertValueToQVariant(exec, value, QMetaType::Void, distance);
+                dist = 10;
+                break;
+            }
+
+            dist = 10;
+            break;
+    }
+
+    if (!ret.isValid())
+        dist = -1;
+    if (distance)
+        *distance = dist;
+
+    return ret;
+}
+
+JSValue* convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
+{
+    // Variants with QObject * can be isNull but not a null pointer
+    // An empty QString variant is also null
+    QMetaType::Type type = (QMetaType::Type) variant.userType();
+    if (variant.isNull() &&
+        type != QMetaType::QObjectStar &&
+        type != QMetaType::VoidStar &&
+        type != QMetaType::QWidgetStar &&
+        type != QMetaType::QString) {
+        return jsNull();
+    }
+
+    JSLock lock;
+
+    if (type == QMetaType::Bool)
+        return jsBoolean(variant.toBool());
+
+    if (type == QMetaType::Int ||
+        type == QMetaType::UInt ||
+        type == QMetaType::Long ||
+        type == QMetaType::ULong ||
+        type == QMetaType::LongLong ||
+        type == QMetaType::ULongLong ||
+        type == QMetaType::Short ||
+        type == QMetaType::UShort ||
+        type == QMetaType::Float ||
+        type == QMetaType::Double)
+        return jsNumber(variant.toDouble());
+
+    if (type == QMetaType::QRegExp) {
+        QRegExp re = variant.value<QRegExp>();
+
+        if (re.isValid()) {
+            RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalGlobalObject()->regExpConstructor());
+            List args;
+            UString uflags;
+
+            if (re.caseSensitivity() == Qt::CaseInsensitive)
+                uflags = "i"; // ### Can't do g or m
+            UString ustring((KJS::UChar*)re.pattern().utf16(), re.pattern().length());
+            args.append(jsString(ustring));
+            args.append(jsString(uflags));
+            return regExpObj->construct(exec, args);
+        }
+    }
+
+    if (type == QMetaType::QDateTime ||
+        type == QMetaType::QDate ||
+        type == QMetaType::QTime) {
+        DateObjectImp *dateObj = static_cast<DateObjectImp*>(exec->lexicalGlobalObject()->dateConstructor());
+        List args;
+
+        QDate date = QDate::currentDate();
+        QTime time(0,0,0); // midnight
+
+        if (type == QMetaType::QDate)
+            date = variant.value<QDate>();
+        else if (type == QMetaType::QTime)
+            time = variant.value<QTime>();
+        else {
+            QDateTime dt = variant.value<QDateTime>().toLocalTime();
+            date = dt.date();
+            time = dt.time();
+        }
+
+        // Dates specified this way are in local time (we convert DateTimes above)
+        args.append(jsNumber(date.year()));
+        args.append(jsNumber(date.month() - 1));
+        args.append(jsNumber(date.day()));
+        args.append(jsNumber(time.hour()));
+        args.append(jsNumber(time.minute()));
+        args.append(jsNumber(time.second()));
+        args.append(jsNumber(time.msec()));
+        return dateObj->construct(exec, args);
+    }
+
+    if (type == QMetaType::QByteArray) {
+        QByteArray ba = variant.value<QByteArray>();
+        UString ustring(ba.constData());
+        return jsString(ustring);
+    }
+
+    if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
+        QObject* obj = variant.value<QObject*>();
+        return Instance::createRuntimeObject(Instance::QtLanguage, obj, root);
+    }
+
+    if (type == QMetaType::QVariantMap) {
+        // create a new object, and stuff properties into it
+        JSObject* ret = new JSObject(exec->lexicalGlobalObject()->objectPrototype());
+        QVariantMap map = variant.value<QVariantMap>();
+        QVariantMap::const_iterator i = map.constBegin();
+        while (i != map.constEnd()) {
+            QString s = i.key();
+            JSValue* val = convertQVariantToValue(exec, root, i.value());
+            if (val)
+                ret->put(exec, Identifier((const UChar *)s.constData(), s.length()), val);
+            // ### error case?
+            ++i;
+        }
+
+        return ret;
+    }
+
+    // List types
+    if (type == QMetaType::QVariantList) {
+        QVariantList vl = variant.toList();
+        return new RuntimeArray(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
+    } else if (type == QMetaType::QStringList) {
+        QStringList sl = variant.value<QStringList>();
+        return new RuntimeArray(exec, new QtArray<QString>(sl, QMetaType::QString, root));
+    } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
+        QObjectList ol= variant.value<QObjectList>();
+        return new RuntimeArray(exec, new QtArray<QObject*>(ol, QMetaType::QObjectStar, root));
+    } else if (type == (QMetaType::Type)qMetaTypeId<QList<int> >()) {
+        QList<int> il= variant.value<QList<int> >();
+        return new RuntimeArray(exec, new QtArray<int>(il, QMetaType::Int, root));
+    }
+
+    if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
+        QVariant real = variant.value<QVariant>();
+        qConvDebug() << "real variant is:" << real;
+        return convertQVariantToValue(exec, root, real);
+    }
+
+    qConvDebug() << "fallback path for" << variant << variant.userType();
+
+    QString string = variant.toString();
+    UString ustring((KJS::UChar*)string.utf16(), string.length());
+    return jsString(ustring);
+}
+
+// ===============
+
+// Qt-like macros
+#define QW_D(Class) Class##Data* d = d_func()
+#define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()
+
+QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState *exec, const Identifier &ident, PassRefPtr<QtInstance> inst)
+    : InternalFunctionImp (static_cast<FunctionPrototype*>(exec->lexicalGlobalObject()->functionPrototype()), ident)
+    , d_ptr(dd)
+{
+    QW_D(QtRuntimeMethod);
+    d->m_instance =&nbs