summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/bridge
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/bridge
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/bridge')
-rw-r--r--Source/WebCore/bridge/Bridge.h48
-rw-r--r--Source/WebCore/bridge/IdentifierRep.cpp112
-rw-r--r--Source/WebCore/bridge/IdentifierRep.h76
-rw-r--r--Source/WebCore/bridge/NP_jsobject.cpp533
-rw-r--r--Source/WebCore/bridge/NP_jsobject.h55
-rw-r--r--Source/WebCore/bridge/c/CRuntimeObject.cpp56
-rw-r--r--Source/WebCore/bridge/c/CRuntimeObject.h55
-rw-r--r--Source/WebCore/bridge/c/c_class.cpp120
-rw-r--r--Source/WebCore/bridge/c/c_class.h60
-rw-r--r--Source/WebCore/bridge/c/c_instance.cpp318
-rw-r--r--Source/WebCore/bridge/c/c_instance.h93
-rw-r--r--Source/WebCore/bridge/c/c_runtime.cpp83
-rw-r--r--Source/WebCore/bridge/c/c_runtime.h68
-rw-r--r--Source/WebCore/bridge/c/c_utility.cpp158
-rw-r--r--Source/WebCore/bridge/c/c_utility.h55
-rw-r--r--Source/WebCore/bridge/jni/JNIBridge.cpp178
-rw-r--r--Source/WebCore/bridge/jni/JNIBridge.h123
-rw-r--r--Source/WebCore/bridge/jni/JNIUtility.cpp343
-rw-r--r--Source/WebCore/bridge/jni/JNIUtility.h275
-rw-r--r--Source/WebCore/bridge/jni/jni_jsobject.h133
-rw-r--r--Source/WebCore/bridge/jni/jni_jsobject.mm705
-rw-r--r--Source/WebCore/bridge/jni/jni_objc.mm84
-rw-r--r--Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp445
-rw-r--r--Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.h89
-rw-r--r--Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp318
-rw-r--r--Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h53
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaClassJSC.cpp150
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaClassJSC.h62
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp384
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.h112
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.cpp53
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.h52
-rw-r--r--Source/WebCore/bridge/jni/jsc/JavaStringJSC.h84
-rw-r--r--Source/WebCore/bridge/jni/v8/JNIBridgeV8.cpp44
-rw-r--r--Source/WebCore/bridge/jni/v8/JNIBridgeV8.h56
-rw-r--r--Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp481
-rw-r--r--Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h49
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaClassV8.cpp103
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaClassV8.h60
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaInstanceV8.cpp173
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaInstanceV8.h100
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp176
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaNPObjectV8.h56
-rw-r--r--Source/WebCore/bridge/jni/v8/JavaStringV8.h61
-rw-r--r--Source/WebCore/bridge/jsc/BridgeJSC.cpp127
-rw-r--r--Source/WebCore/bridge/jsc/BridgeJSC.h153
-rwxr-xr-xSource/WebCore/bridge/make_testbindings2
-rw-r--r--Source/WebCore/bridge/npapi.h897
-rw-r--r--Source/WebCore/bridge/npruntime.cpp164
-rw-r--r--Source/WebCore/bridge/npruntime.h393
-rw-r--r--Source/WebCore/bridge/npruntime_impl.h66
-rw-r--r--Source/WebCore/bridge/npruntime_internal.h53
-rw-r--r--Source/WebCore/bridge/npruntime_priv.h41
-rw-r--r--Source/WebCore/bridge/nptypes.h214
-rw-r--r--Source/WebCore/bridge/objc/ObjCRuntimeObject.h52
-rw-r--r--Source/WebCore/bridge/objc/ObjCRuntimeObject.mm52
-rw-r--r--Source/WebCore/bridge/objc/WebScriptObject.h44
-rw-r--r--Source/WebCore/bridge/objc/objc_class.h59
-rw-r--r--Source/WebCore/bridge/objc/objc_class.mm253
-rw-r--r--Source/WebCore/bridge/objc/objc_header.h53
-rw-r--r--Source/WebCore/bridge/objc/objc_instance.h86
-rw-r--r--Source/WebCore/bridge/objc/objc_instance.mm465
-rw-r--r--Source/WebCore/bridge/objc/objc_runtime.h131
-rw-r--r--Source/WebCore/bridge/objc/objc_runtime.mm280
-rw-r--r--Source/WebCore/bridge/objc/objc_utility.h88
-rw-r--r--Source/WebCore/bridge/objc/objc_utility.mm373
-rw-r--r--Source/WebCore/bridge/qt/qt_class.cpp225
-rw-r--r--Source/WebCore/bridge/qt/qt_class.h59
-rw-r--r--Source/WebCore/bridge/qt/qt_instance.cpp397
-rw-r--r--Source/WebCore/bridge/qt/qt_instance.h96
-rw-r--r--Source/WebCore/bridge/qt/qt_pixmapruntime.cpp369
-rw-r--r--Source/WebCore/bridge/qt/qt_pixmapruntime.h54
-rw-r--r--Source/WebCore/bridge/qt/qt_runtime.cpp1914
-rw-r--r--Source/WebCore/bridge/qt/qt_runtime.h242
-rw-r--r--Source/WebCore/bridge/runtime_array.cpp166
-rw-r--r--Source/WebCore/bridge/runtime_array.h70
-rw-r--r--Source/WebCore/bridge/runtime_method.cpp128
-rw-r--r--Source/WebCore/bridge/runtime_method.h67
-rw-r--r--Source/WebCore/bridge/runtime_object.cpp326
-rw-r--r--Source/WebCore/bridge/runtime_object.h86
-rw-r--r--Source/WebCore/bridge/runtime_root.cpp192
-rw-r--r--Source/WebCore/bridge/runtime_root.h101
-rw-r--r--Source/WebCore/bridge/test.js19
-rw-r--r--Source/WebCore/bridge/testC.js21
-rw-r--r--Source/WebCore/bridge/testM.js29
-rw-r--r--Source/WebCore/bridge/testbindings.cpp419
-rw-r--r--Source/WebCore/bridge/testbindings.mm287
-rw-r--r--Source/WebCore/bridge/testbindings.pro7
-rw-r--r--Source/WebCore/bridge/testqtbindings.cpp139
89 files changed, 16351 insertions, 0 deletions
diff --git a/Source/WebCore/bridge/Bridge.h b/Source/WebCore/bridge/Bridge.h
new file mode 100644
index 0000000..50efc64
--- /dev/null
+++ b/Source/WebCore/bridge/Bridge.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 Bridge_h
+#define Bridge_h
+
+#include "BridgeJSC.h"
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+class Method : public Noncopyable {
+public:
+ virtual int numParameters() const = 0;
+
+ virtual ~Method() { }
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/IdentifierRep.cpp b/Source/WebCore/bridge/IdentifierRep.cpp
new file mode 100644
index 0000000..fed47ca
--- /dev/null
+++ b/Source/WebCore/bridge/IdentifierRep.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009 Apple 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 "IdentifierRep.h"
+#include "JSDOMBinding.h"
+
+#include "PlatformString.h"
+#include <runtime/UString.h>
+#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+typedef HashSet<IdentifierRep*> IdentifierSet;
+
+static IdentifierSet& identifierSet()
+{
+ DEFINE_STATIC_LOCAL(IdentifierSet, identifierSet, ());
+ return identifierSet;
+}
+
+typedef HashMap<int, IdentifierRep*> IntIdentifierMap;
+
+static IntIdentifierMap& intIdentifierMap()
+{
+ DEFINE_STATIC_LOCAL(IntIdentifierMap, intIdentifierMap, ());
+ return intIdentifierMap;
+}
+
+IdentifierRep* IdentifierRep::get(int intID)
+{
+ if (intID == 0 || intID == -1) {
+ static IdentifierRep* negativeOneAndZeroIdentifiers[2];
+
+ IdentifierRep* identifier = negativeOneAndZeroIdentifiers[intID + 1];
+ if (!identifier) {
+ identifier = new IdentifierRep(intID);
+
+ negativeOneAndZeroIdentifiers[intID + 1] = identifier;
+ }
+
+ return identifier;
+ }
+
+ pair<IntIdentifierMap::iterator, bool> result = intIdentifierMap().add(intID, 0);
+ if (result.second) {
+ ASSERT(!result.first->second);
+ result.first->second = new IdentifierRep(intID);
+
+ identifierSet().add(result.first->second);
+ }
+
+ return result.first->second;
+}
+
+typedef HashMap<RefPtr<StringImpl>, IdentifierRep*> StringIdentifierMap;
+
+static StringIdentifierMap& stringIdentifierMap()
+{
+ DEFINE_STATIC_LOCAL(StringIdentifierMap, stringIdentifierMap, ());
+ return stringIdentifierMap;
+}
+
+IdentifierRep* IdentifierRep::get(const char* name)
+{
+ ASSERT(name);
+ if (!name)
+ return 0;
+
+ UString string = stringToUString(String::fromUTF8WithLatin1Fallback(name, strlen(name)));
+ pair<StringIdentifierMap::iterator, bool> result = stringIdentifierMap().add(string.impl(), 0);
+ if (result.second) {
+ ASSERT(!result.first->second);
+ result.first->second = new IdentifierRep(name);
+
+ identifierSet().add(result.first->second);
+ }
+
+ return result.first->second;
+}
+
+bool IdentifierRep::isValid(IdentifierRep* identifier)
+{
+ return identifierSet().contains(identifier);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bridge/IdentifierRep.h b/Source/WebCore/bridge/IdentifierRep.h
new file mode 100644
index 0000000..99bae0b
--- /dev/null
+++ b/Source/WebCore/bridge/IdentifierRep.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 Apple 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 IdentifierRep_h
+#define IdentifierRep_h
+
+#include <wtf/Assertions.h>
+#include <wtf/FastAllocBase.h>
+#include <wtf/StringExtras.h>
+#include <string.h>
+
+namespace WebCore {
+
+class IdentifierRep : public FastAllocBase {
+public:
+ static IdentifierRep* get(int);
+ static IdentifierRep* get(const char*);
+
+ static bool isValid(IdentifierRep*);
+
+ bool isString() const { return m_isString; }
+
+ int number() const { return m_isString ? 0 : m_value.m_number; }
+ const char* string() const { return m_isString ? m_value.m_string : 0; }
+
+private:
+ IdentifierRep(int number)
+ : m_isString(false)
+ {
+ m_value.m_number = number;
+ }
+
+ IdentifierRep(const char* name)
+ : m_isString(true)
+ {
+ m_value.m_string = fastStrDup(name);
+ }
+
+ ~IdentifierRep()
+ {
+ // IdentifierReps should never be deleted.
+ ASSERT_NOT_REACHED();
+ }
+
+ union {
+ const char* m_string;
+ int m_number;
+ } m_value;
+ bool m_isString;
+};
+
+} // namespace WebCore
+
+#endif // IdentifierRep_h
diff --git a/Source/WebCore/bridge/NP_jsobject.cpp b/Source/WebCore/bridge/NP_jsobject.cpp
new file mode 100644
index 0000000..0780ad7
--- /dev/null
+++ b/Source/WebCore/bridge/NP_jsobject.cpp
@@ -0,0 +1,533 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NP_jsobject.h"
+
+#include "PlatformString.h"
+#include "PluginView.h"
+#include "StringSourceProvider.h"
+#include "c_utility.h"
+#include "c_instance.h"
+#include "IdentifierRep.h"
+#include "JSDOMBinding.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "runtime_root.h"
+#include <runtime/Error.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/PropertyNameArray.h>
+#include <parser/SourceCode.h>
+#include <runtime/Completion.h>
+#include <runtime/Completion.h>
+
+using namespace JSC;
+using namespace JSC::Bindings;
+using namespace WebCore;
+
+class ObjectMap {
+public:
+ NPObject* get(RootObject* rootObject, JSObject* jsObject)
+ {
+ return m_map.get(rootObject).get(jsObject);
+ }
+
+ void add(RootObject* rootObject, JSObject* jsObject, NPObject* npObject)
+ {
+ HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject);
+ if (iter == m_map.end()) {
+ rootObject->addInvalidationCallback(&m_invalidationCallback);
+ iter = m_map.add(rootObject, JSToNPObjectMap()).first;
+ }
+
+ ASSERT(iter->second.find(jsObject) == iter->second.end());
+ iter->second.add(jsObject, npObject);
+ }
+
+ void remove(RootObject* rootObject)
+ {
+ HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject);
+ ASSERT(iter != m_map.end());
+ m_map.remove(iter);
+ }
+
+ void remove(RootObject* rootObject, JSObject* jsObject)
+ {
+ HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject);
+ ASSERT(iter != m_map.end());
+ ASSERT(iter->second.find(jsObject) != iter->second.end());
+
+ iter->second.remove(jsObject);
+ }
+
+private:
+ struct RootObjectInvalidationCallback : public RootObject::InvalidationCallback {
+ virtual void operator()(RootObject*);
+ };
+ RootObjectInvalidationCallback m_invalidationCallback;
+
+ // JSObjects are protected by RootObject.
+ typedef HashMap<JSObject*, NPObject*> JSToNPObjectMap;
+ HashMap<RootObject*, JSToNPObjectMap> m_map;
+};
+
+
+static ObjectMap& objectMap()
+{
+ DEFINE_STATIC_LOCAL(ObjectMap, map, ());
+ return map;
+}
+
+void ObjectMap::RootObjectInvalidationCallback::operator()(RootObject* rootObject)
+{
+ objectMap().remove(rootObject);
+}
+
+static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, MarkedArgumentBuffer& aList)
+{
+ for (unsigned i = 0; i < argCount; ++i)
+ aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
+}
+
+static NPObject* jsAllocate(NPP, NPClass*)
+{
+ return static_cast<NPObject*>(malloc(sizeof(JavaScriptObject)));
+}
+
+static void jsDeallocate(NPObject* npObj)
+{
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(npObj);
+
+ if (obj->rootObject && obj->rootObject->isValid()) {
+ objectMap().remove(obj->rootObject, obj->imp);
+ 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, 0 };
+static NPClass noScriptClass = { 1, 0, 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)
+{
+ if (NPObject* object = objectMap().get(rootObject.get(), imp))
+ return _NPN_RetainObject(object);
+
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(_NPN_CreateObject(npp, NPScriptObjectClass));
+
+ obj->rootObject = rootObject.releaseRef();
+
+ if (obj->rootObject) {
+ obj->rootObject->gcProtect(imp);
+ objectMap().add(obj->rootObject, imp, reinterpret_cast<NPObject*>(obj));
+ }
+
+ obj->imp = imp;
+
+ return reinterpret_cast<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 = reinterpret_cast<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(SilenceAssertionsOnly);
+
+ // Call the function object.
+ JSValue function = obj->imp;
+ CallData callData;
+ CallType callType = getCallData(function, callData);
+ if (callType == CallTypeNone)
+ return false;
+
+ MarkedArgumentBuffer argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
+ globalObject->globalData().timeoutChecker.start();
+ JSValue resultV = JSC::call(exec, function, callType, callData, function, argList);
+ globalObject->globalData().timeoutChecker.stop();
+
+ // Convert and return the result of the function call.
+ convertValueToNPVariant(exec, resultV, result);
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ IdentifierRep* i = static_cast<IdentifierRep*>(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, const_cast<NPString*>(&args[0].value.stringValue), result);
+ }
+
+ // Look up the function object.
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue function = obj->imp->get(exec, identifierFromNPIdentifier(exec, i->string()));
+ CallData callData;
+ CallType callType = getCallData(function, callData);
+ if (callType == CallTypeNone)
+ return false;
+
+ // Call the function object.
+ MarkedArgumentBuffer argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
+ globalObject->globalData().timeoutChecker.start();
+ JSValue resultV = JSC::call(exec, function, callType, callData, obj->imp, argList);
+ globalObject->globalData().timeoutChecker.stop();
+
+ // Convert and return the result of the function call.
+ convertValueToNPVariant(exec, resultV, result);
+ exec->clearException();
+ 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 instance, NPObject* o, NPString* s, NPVariant* variant)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ // There is a crash in Flash when evaluating a script that destroys the
+ // PluginView, so we destroy it asynchronously.
+ PluginView::keepAlive(instance);
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ String scriptString = convertNPStringToUTF16(s);
+ ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
+ globalObject->globalData().timeoutChecker.start();
+ Completion completion = JSC::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(scriptString), JSC::JSValue());
+ globalObject->globalData().timeoutChecker.stop();
+ ComplType type = completion.complType();
+
+ JSValue result;
+ if (type == Normal) {
+ result = completion.value();
+ if (!result)
+ result = jsUndefined();
+ } else
+ result = jsUndefined();
+
+ convertValueToNPVariant(exec, result, variant);
+ exec->clearException();
+ return true;
+ }
+
+ VOID_TO_NPVARIANT(*variant);
+ return false;
+}
+
+bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ IdentifierRep* i = static_cast<IdentifierRep*>(propertyName);
+
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue result;
+ if (i->isString())
+ result = obj->imp->get(exec, identifierFromNPIdentifier(exec, i->string()));
+ else
+ result = obj->imp->get(exec, i->number());
+
+ convertValueToNPVariant(exec, result, variant);
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ IdentifierRep* i = static_cast<IdentifierRep*>(propertyName);
+
+ if (i->isString()) {
+ PutPropertySlot slot;
+ obj->imp->put(exec, identifierFromNPIdentifier(exec, i->string()), convertNPVariantToValue(exec, variant, rootObject), slot);
+ } else
+ obj->imp->put(exec, i->number(), convertNPVariantToValue(exec, variant, rootObject));
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ IdentifierRep* i = static_cast<IdentifierRep*>(propertyName);
+ if (i->isString()) {
+ if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(exec, i->string()))) {
+ exec->clearException();
+ return false;
+ }
+ } else {
+ if (!obj->imp->hasProperty(exec, i->number())) {
+ exec->clearException();
+ return false;
+ }
+ }
+
+ JSLock lock(SilenceAssertionsOnly);
+ if (i->isString())
+ obj->imp->deleteProperty(exec, identifierFromNPIdentifier(exec, i->string()));
+ else
+ obj->imp->deleteProperty(exec, i->number());
+
+ exec->clearException();
+ return true;
+ }
+ return false;
+}
+
+bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ IdentifierRep* i = static_cast<IdentifierRep*>(propertyName);
+ JSLock lock(SilenceAssertionsOnly);
+ if (i->isString()) {
+ bool result = obj->imp->hasProperty(exec, identifierFromNPIdentifier(exec, i->string()));
+ exec->clearException();
+ return result;
+ }
+
+ bool result = obj->imp->hasProperty(exec, i->number());
+ exec->clearException();
+ return result;
+ }
+
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ IdentifierRep* i = static_cast<IdentifierRep*>(methodName);
+ if (!i->isString())
+ return false;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue func = obj->imp->get(exec, identifierFromNPIdentifier(exec, i->string()));
+ exec->clearException();
+ return !func.isUndefined();
+ }
+
+ if (o->_class->hasMethod)
+ return o->_class->hasMethod(o, methodName);
+
+ return false;
+}
+
+void _NPN_SetException(NPObject*, const NPUTF8* message)
+{
+ // Ignoring the NPObject param is consistent with the Mozilla implementation.
+ UString exception(message);
+ CInstance::setGlobalException(exception);
+}
+
+bool _NPN_Enumerate(NPP, NPObject* o, NPIdentifier** identifier, uint32_t* count)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ PropertyNameArray propertyNames(exec);
+
+ 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().utf8().data());
+
+ *identifier = identifiers;
+ *count = size;
+
+ exec->clearException();
+ return true;
+ }
+
+ if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
+ return o->_class->enumerate(o, identifier, count);
+
+ return false;
+}
+
+bool _NPN_Construct(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ VOID_TO_NPVARIANT(*result);
+
+ // Lookup the constructor object.
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+
+ // Call the constructor object.
+ JSValue constructor = obj->imp;
+ ConstructData constructData;
+ ConstructType constructType = getConstructData(constructor, constructData);
+ if (constructType == ConstructTypeNone)
+ return false;
+
+ MarkedArgumentBuffer argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
+ globalObject->globalData().timeoutChecker.start();
+ JSValue resultV = JSC::construct(exec, constructor, constructType, constructData, argList);
+ globalObject->globalData().timeoutChecker.stop();
+
+ // Convert and return the result.
+ convertValueToNPVariant(exec, resultV, result);
+ exec->clearException();
+ return true;
+ }
+
+ if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(o->_class) && o->_class->construct)
+ return o->_class->construct(o, args, argCount, result);
+
+ return false;
+}
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebCore/bridge/NP_jsobject.h b/Source/WebCore/bridge/NP_jsobject.h
new file mode 100644
index 0000000..6c49d1b
--- /dev/null
+++ b/Source/WebCore/bridge/NP_jsobject.h
@@ -0,0 +1,55 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "npruntime_internal.h"
+#include <wtf/Forward.h>
+
+namespace JSC {
+ class JSObject;
+ namespace Bindings {
+ class RootObject;
+ }
+}
+
+extern NPClass* NPScriptObjectClass;
+
+struct JavaScriptObject
+{
+ NPObject object;
+ JSC::JSObject* imp;
+ JSC::Bindings::RootObject* rootObject;
+};
+
+NPObject* _NPN_CreateScriptObject(NPP npp, JSC::JSObject*, PassRefPtr<JSC::Bindings::RootObject> rootObject);
+NPObject* _NPN_CreateNoScriptObject(void);
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/Source/WebCore/bridge/c/CRuntimeObject.cpp b/Source/WebCore/bridge/c/CRuntimeObject.cpp
new file mode 100644
index 0000000..4be4982
--- /dev/null
+++ b/Source/WebCore/bridge/c/CRuntimeObject.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Apple 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 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "CRuntimeObject.h"
+#include "c_instance.h"
+
+namespace JSC {
+namespace Bindings {
+
+const ClassInfo CRuntimeObject::s_info = { "CRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+CRuntimeObject::CRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<CInstance> instance)
+ : RuntimeObject(exec, globalObject, instance)
+{
+}
+
+CRuntimeObject::~CRuntimeObject()
+{
+}
+
+CInstance* CRuntimeObject::getInternalCInstance() const
+{
+ return static_cast<CInstance*>(getInternalInstance());
+}
+
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/bridge/c/CRuntimeObject.h b/Source/WebCore/bridge/c/CRuntimeObject.h
new file mode 100644
index 0000000..bcd39d3
--- /dev/null
+++ b/Source/WebCore/bridge/c/CRuntimeObject.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 Apple 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 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 CRuntimeObject_h
+#define CRuntimeObject_h
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "runtime_object.h"
+
+namespace JSC {
+namespace Bindings {
+
+class CInstance;
+
+class CRuntimeObject : public RuntimeObject {
+public:
+ CRuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<CInstance>);
+ virtual ~CRuntimeObject();
+
+ CInstance* getInternalCInstance() const;
+
+ static const ClassInfo s_info;
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+};
+
+}
+}
+
+#endif
+#endif
diff --git a/Source/WebCore/bridge/c/c_class.cpp b/Source/WebCore/bridge/c/c_class.cpp
new file mode 100644
index 0000000..f4ae5ca
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_class.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_class.h"
+
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "npruntime_impl.h"
+#include <runtime/Identifier.h>
+#include <runtime/JSLock.h>
+#include <wtf/text/StringHash.h>
+
+namespace JSC { namespace Bindings {
+
+CClass::CClass(NPClass* aClass)
+{
+ _isa = aClass;
+}
+
+CClass::~CClass()
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ 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;
+}
+
+MethodList CClass::methodsNamed(const Identifier& identifier, Instance* instance) const
+{
+ MethodList methodList;
+
+ Method* method = _methods.get(identifier.ustring().impl());
+ if (method) {
+ methodList.append(method);
+ return methodList;
+ }
+
+ NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii().data());
+ 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(SilenceAssertionsOnly);
+ _methods.set(identifier.ustring().impl(), aMethod);
+ }
+ methodList.append(aMethod);
+ }
+
+ return methodList;
+}
+
+Field* CClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+ Field* aField = _fields.get(identifier.ustring().impl());
+ if (aField)
+ return aField;
+
+ NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii().data());
+ 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(SilenceAssertionsOnly);
+ _fields.set(identifier.ustring().impl(), aField);
+ }
+ }
+ return aField;
+}
+
+} } // namespace JSC::Bindings
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebCore/bridge/c/c_class.h b/Source/WebCore/bridge/c/c_class.h
new file mode 100644
index 0000000..52db2b9
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_class.h
@@ -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.
+ */
+
+#ifndef BINDINGS_C_CLASS_H_
+#define BINDINGS_C_CLASS_H_
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "Bridge.h"
+#include "npruntime_internal.h"
+#include <wtf/HashMap.h>
+
+namespace JSC {
+namespace Bindings {
+
+class CClass : public Class {
+protected:
+ CClass(NPClass*); // Use classForIsA to create a CClass.
+
+public:
+ static CClass* classForIsA(NPClass*);
+ virtual ~CClass();
+
+ 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 JSC
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/Source/WebCore/bridge/c/c_instance.cpp b/Source/WebCore/bridge/c/c_instance.cpp
new file mode 100644
index 0000000..f1dd4e5
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_instance.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_instance.h"
+
+#include "CRuntimeObject.h"
+#include "IdentifierRep.h"
+#include "c_class.h"
+#include "c_runtime.h"
+#include "c_utility.h"
+#include "npruntime_impl.h"
+#include "runtime_method.h"
+#include "runtime_root.h"
+#include <interpreter/CallFrame.h>
+#include <runtime/ArgList.h>
+#include <runtime/Error.h>
+#include <runtime/JSLock.h>
+#include <runtime/JSNumberCell.h>
+#include <runtime/PropertyNameArray.h>
+#include <wtf/Assertions.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace JSC {
+namespace Bindings {
+
+using JSC::UString;
+
+static JSC::UString& globalExceptionString()
+{
+ DEFINE_STATIC_LOCAL(JSC::UString, exceptionStr, ());
+ return exceptionStr;
+}
+
+void CInstance::setGlobalException(UString exception)
+{
+ globalExceptionString() = exception;
+}
+
+void CInstance::moveGlobalExceptionToExecState(ExecState* exec)
+{
+ if (globalExceptionString().isNull())
+ return;
+
+ {
+ JSLock lock(SilenceAssertionsOnly);
+ throwError(exec, createError(exec, globalExceptionString()));
+ }
+
+ globalExceptionString() = UString();
+}
+
+CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+{
+ _object = _NPN_RetainObject(o);
+ _class = 0;
+}
+
+CInstance::~CInstance()
+{
+ _NPN_ReleaseObject(_object);
+}
+
+RuntimeObject* CInstance::newRuntimeObject(ExecState* exec)
+{
+ return new (exec) CRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+Class *CInstance::getClass() const
+{
+ if (!_class)
+ _class = CClass::classForIsA(_object->_class);
+ return _class;
+}
+
+bool CInstance::supportsInvokeDefaultMethod() const
+{
+ return _object->_class->invokeDefault;
+}
+
+class CRuntimeMethod : public RuntimeMethod {
+public:
+ CRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
+ : RuntimeMethod(exec, globalObject, name, list)
+ {
+ }
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static const ClassInfo s_info;
+};
+
+const ClassInfo CRuntimeMethod::s_info = { "CRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };
+
+JSValue CInstance::getMethod(ExecState* exec, const Identifier& propertyName)
+{
+ MethodList methodList = getClass()->methodsNamed(propertyName, this);
+ return new (exec) CRuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue CInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
+{
+ if (!asObject(runtimeMethod)->inherits(&CRuntimeMethod::s_info))
+ return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));
+
+ const MethodList& methodList = *runtimeMethod->methods();
+
+ // 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 = method->identifier();
+ if (!_object->_class->hasMethod(_object, ident))
+ return jsUndefined();
+
+ unsigned count = exec->argumentCount();
+ Vector<NPVariant, 8> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, exec->argument(i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+ bool retval = true;
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+
+ {
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
+ ASSERT(globalExceptionString().isNull());
+ retval = _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ if (!retval)
+ throwError(exec, createError(exec, "Error calling method on NPObject."));
+
+ for (i = 0; i < count; i++)
+ _NPN_ReleaseVariantValue(&cArgs[i]);
+
+ JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
+ _NPN_ReleaseVariantValue(&resultVariant);
+ return resultValue;
+}
+
+
+JSValue CInstance::invokeDefaultMethod(ExecState* exec)
+{
+ if (!_object->_class->invokeDefault)
+ return jsUndefined();
+
+ unsigned count = exec->argumentCount();
+ Vector<NPVariant, 8> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, exec->argument(i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+ bool retval = true;
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+ {
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
+ ASSERT(globalExceptionString().isNull());
+ retval = _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ if (!retval)
+ throwError(exec, createError(exec, "Error calling method on NPObject."));
+
+ for (i = 0; i < count; i++)
+ _NPN_ReleaseVariantValue(&cArgs[i]);
+
+ JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
+ _NPN_ReleaseVariantValue(&resultVariant);
+ return resultValue;
+}
+
+bool CInstance::supportsConstruct() const
+{
+ return _object->_class->construct;
+}
+
+JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
+{
+ if (!_object->_class->construct)
+ return jsUndefined();
+
+ unsigned count = args.size();
+ Vector<NPVariant, 8> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+ bool retval = true;
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+ {
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
+ ASSERT(globalExceptionString().isNull());
+ retval = _object->_class->construct(_object, cArgs.data(), count, &resultVariant);
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ if (!retval)
+ throwError(exec, createError(exec, "Error calling method on NPObject."));
+
+ for (i = 0; i < count; i++)
+ _NPN_ReleaseVariantValue(&cArgs[i]);
+
+ JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
+ _NPN_ReleaseVariantValue(&resultVariant);
+ return resultValue;
+}
+
+JSValue CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue CInstance::stringValue(ExecState* exec) const
+{
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
+ return jsString(exec, buf);
+}
+
+JSValue CInstance::numberValue(ExecState*) const
+{
+ // FIXME: Implement something sensible.
+ return jsNumber(0);
+}
+
+JSValue CInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible.
+ return jsBoolean(false);
+}
+
+JSValue CInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
+{
+ if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate)
+ return;
+
+ uint32_t count;
+ NPIdentifier* identifiers;
+
+ {
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
+ ASSERT(globalExceptionString().isNull());
+ bool ok = _object->_class->enumerate(_object, &identifiers, &count);
+ moveGlobalExceptionToExecState(exec);
+ if (!ok)
+ return;
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]);
+
+ if (identifier->isString())
+ nameArray.add(identifierFromNPIdentifier(exec, identifier->string()));
+ else
+ nameArray.add(Identifier::from(exec, identifier->number()));
+ }
+
+ // FIXME: This should really call NPN_MemFree but that's in WebKit
+ free(identifiers);
+}
+
+}
+}
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebCore/bridge/c/c_instance.h b/Source/WebCore/bridge/c/c_instance.h
new file mode 100644
index 0000000..cc1a806
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_instance.h
@@ -0,0 +1,93 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "Bridge.h"
+#include "runtime_root.h"
+#include <wtf/PassRefPtr.h>
+
+typedef struct NPObject NPObject;
+
+namespace JSC {
+
+class UString;
+
+namespace Bindings {
+
+class CClass;
+
+class CInstance : public Instance {
+public:
+ static PassRefPtr<CInstance> create(NPObject* object, PassRefPtr<RootObject> rootObject)
+ {
+ return adoptRef(new CInstance(object, rootObject));
+ }
+
+ static void setGlobalException(JSC::UString exception);
+ static void moveGlobalExceptionToExecState(ExecState*);
+
+ ~CInstance ();
+
+ virtual Class *getClass() const;
+
+ virtual JSValue valueOf(ExecState*) const;
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName);
+ virtual JSValue invokeMethod(ExecState*, RuntimeMethod* method);
+ virtual bool supportsInvokeDefaultMethod() const;
+ virtual JSValue invokeDefaultMethod(ExecState*);
+
+ virtual bool supportsConstruct() const;
+ virtual JSValue invokeConstruct(ExecState*, const ArgList&);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ JSValue stringValue(ExecState*) const;
+ JSValue numberValue(ExecState*) const;
+ JSValue booleanValue() const;
+
+ NPObject *getObject() const { return _object; }
+
+private:
+ CInstance(NPObject*, PassRefPtr<RootObject>);
+
+ virtual RuntimeObject* newRuntimeObject(ExecState*);
+
+ mutable CClass *_class;
+ NPObject *_object;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/Source/WebCore/bridge/c/c_runtime.cpp b/Source/WebCore/bridge/c/c_runtime.cpp
new file mode 100644
index 0000000..e038cd4
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_runtime.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_runtime.h"
+
+#include "c_instance.h"
+#include "c_utility.h"
+#include "npruntime_impl.h"
+#include <runtime/JSLock.h>
+
+namespace JSC {
+namespace Bindings {
+
+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(SilenceAssertionsOnly);
+ result = obj->_class->getProperty(obj, _fieldIdentifier, &property);
+ CInstance::moveGlobalExceptionToExecState(exec);
+ }
+ 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(SilenceAssertionsOnly);
+ obj->_class->setProperty(obj, _fieldIdentifier, &variant);
+ CInstance::moveGlobalExceptionToExecState(exec);
+ }
+
+ _NPN_ReleaseVariantValue(&variant);
+ }
+}
+
+} }
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebCore/bridge/c/c_runtime.h b/Source/WebCore/bridge/c/c_runtime.h
new file mode 100644
index 0000000..5355934
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_runtime.h
@@ -0,0 +1,68 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "Bridge.h"
+#include "npruntime_internal.h"
+
+namespace JSC {
+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;
+
+ NPIdentifier identifier() const { return _fieldIdentifier; }
+
+private:
+ NPIdentifier _fieldIdentifier;
+};
+
+
+class CMethod : public Method
+{
+public:
+ CMethod(NPIdentifier ident) : _methodIdentifier(ident) { }
+
+ NPIdentifier identifier() const { return _methodIdentifier; }
+ virtual int numParameters() const { return 0; }
+
+private:
+ NPIdentifier _methodIdentifier;
+};
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/Source/WebCore/bridge/c/c_utility.cpp b/Source/WebCore/bridge/c/c_utility.cpp
new file mode 100644
index 0000000..ea970eb
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_utility.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_utility.h"
+
+#include "CRuntimeObject.h"
+#include "JSDOMBinding.h"
+#include "JSDOMWindow.h"
+#include "NP_jsobject.h"
+#include "c_instance.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include "PlatformString.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <wtf/Assertions.h>
+
+namespace JSC { namespace Bindings {
+
+static String convertUTF8ToUTF16WithLatin1Fallback(const NPUTF8* UTF8Chars, int UTF8Length)
+{
+ ASSERT(UTF8Chars || UTF8Length == 0);
+
+ if (UTF8Length == -1)
+ UTF8Length = static_cast<int>(strlen(UTF8Chars));
+
+ String result = String::fromUTF8(UTF8Chars, UTF8Length);
+
+ // If we got back a null string indicating an unsuccessful conversion, fall back to latin 1.
+ // 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.isNull())
+ result = String(UTF8Chars, UTF8Length);
+
+ return result;
+}
+
+// Variant value must be released with NPReleaseVariantValue()
+void convertValueToNPVariant(ExecState* exec, JSValue value, NPVariant* result)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ VOID_TO_NPVARIANT(*result);
+
+ if (value.isString()) {
+ UString ustring = value.toString(exec);
+ CString cstring = ustring.utf8();
+ NPString string = { (const NPUTF8*)cstring.data(), static_cast<uint32_t>(cstring.length()) };
+ NPN_InitializeVariantWithStringCopy(result, &string);
+ } else if (value.isNumber()) {
+ DOUBLE_TO_NPVARIANT(value.toNumber(exec), *result);
+ } else if (value.isBoolean()) {
+ BOOLEAN_TO_NPVARIANT(value.toBoolean(exec), *result);
+ } else if (value.isNull()) {
+ NULL_TO_NPVARIANT(*result);
+ } else if (value.isObject()) {
+ JSObject* object = asObject(value);
+ if (object->classInfo() == &CRuntimeObject::s_info) {
+ CRuntimeObject* runtimeObject = static_cast<CRuntimeObject*>(object);
+ CInstance* instance = runtimeObject->getInternalCInstance();
+ if (instance) {
+ NPObject* obj = instance->getObject();
+ _NPN_RetainObject(obj);
+ OBJECT_TO_NPVARIANT(obj, *result);
+ }
+ } else {
+#ifdef ANDROID
+ RootObject* rootObject = findRootObject(exec->dynamicGlobalObject());
+ if (!rootObject)
+ rootObject = findRootObject(exec->lexicalGlobalObject());
+#else
+ JSGlobalObject* globalObject = exec->dynamicGlobalObject();
+
+ RootObject* rootObject = findRootObject(globalObject);
+#endif
+ if (rootObject) {
+ NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject);
+ OBJECT_TO_NPVARIANT(npObject, *result);
+ }
+ }
+ }
+}
+
+JSValue convertNPVariantToValue(ExecState* exec, const NPVariant* variant, RootObject* rootObject)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ 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)
+ return WebCore::jsString(exec, convertNPStringToUTF16(&variant->value.stringValue));
+ 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 CInstance::create(obj, rootObject)->createRuntimeObject(exec);
+ }
+
+ return jsUndefined();
+}
+
+String convertNPStringToUTF16(const NPString* string)
+{
+ return String::fromUTF8WithLatin1Fallback(string->UTF8Characters, string->UTF8Length);
+}
+
+Identifier identifierFromNPIdentifier(ExecState* exec, const NPUTF8* name)
+{
+ return Identifier(exec, WebCore::stringToUString(convertUTF8ToUTF16WithLatin1Fallback(name, -1)));
+}
+
+} }
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebCore/bridge/c/c_utility.h b/Source/WebCore/bridge/c/c_utility.h
new file mode 100644
index 0000000..43cb16c
--- /dev/null
+++ b/Source/WebCore/bridge/c/c_utility.h
@@ -0,0 +1,55 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "npruntime_internal.h"
+#include <runtime/JSValue.h>
+#include <wtf/Forward.h>
+
+namespace JSC {
+
+class ExecState;
+class Identifier;
+
+namespace Bindings {
+
+class RootObject;
+
+typedef uint16_t NPUTF16;
+
+WTF::String convertNPStringToUTF16(const NPString *string);
+void convertValueToNPVariant(ExecState*, JSValue, NPVariant* result);
+JSValue convertNPVariantToValue(ExecState*, const NPVariant*, RootObject*);
+Identifier identifierFromNPIdentifier(ExecState*, const NPUTF8* name);
+
+} }
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/Source/WebCore/bridge/jni/JNIBridge.cpp b/Source/WebCore/bridge/jni/JNIBridge.cpp
new file mode 100644
index 0000000..c512ee7
--- /dev/null
+++ b/Source/WebCore/bridge/jni/JNIBridge.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 "JNIBridge.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace JSC;
+using namespace JSC::Bindings;
+
+JavaParameter::JavaParameter(JNIEnv* env, jstring type)
+{
+ m_type = JavaString(env, type);
+ m_JNIType = JNITypeFromClassName(m_type.utf8());
+}
+
+JavaMethod::JavaMethod(JNIEnv* env, jobject aMethod)
+{
+ // Get return type name
+ jstring returnTypeName = 0;
+ if (jobject returnType = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;")) {
+ returnTypeName = static_cast<jstring>(callJNIMethod<jobject>(returnType, "getName", "()Ljava/lang/String;"));
+ if (!returnTypeName)
+ returnTypeName = env->NewStringUTF("<Unknown>");
+ env->DeleteLocalRef(returnType);
+ }
+ m_returnType = JavaString(env, returnTypeName);
+ m_JNIReturnType = JNITypeFromClassName(m_returnType.utf8());
+ env->DeleteLocalRef(returnTypeName);
+
+ // Get method name
+ jstring methodName = static_cast<jstring>(callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;"));
+ if (!returnTypeName)
+ returnTypeName = env->NewStringUTF("<Unknown>");
+ m_name = JavaString(env, methodName);
+ env->DeleteLocalRef(methodName);
+
+ // Get parameters
+ if (jarray jparameters = static_cast<jarray>(callJNIMethod<jobject>(aMethod, "getParameterTypes", "()[Ljava/lang/Class;"))) {
+ m_numParameters = env->GetArrayLength(jparameters);
+ m_parameters = new JavaParameter[m_numParameters];
+
+ for (int i = 0; i < m_numParameters; i++) {
+ jobject aParameter = env->GetObjectArrayElement(static_cast<jobjectArray>(jparameters), i);
+ jstring parameterName = static_cast<jstring>(callJNIMethod<jobject>(aParameter, "getName", "()Ljava/lang/String;"));
+ if (!parameterName)
+ parameterName = env->NewStringUTF("<Unknown>");
+ m_parameters[i] = JavaParameter(env, parameterName);
+ env->DeleteLocalRef(aParameter);
+ env->DeleteLocalRef(parameterName);
+ }
+ env->DeleteLocalRef(jparameters);
+ } else {
+ m_numParameters = 0;
+ m_parameters = 0;
+ }
+
+ // Created lazily.
+ m_signature = 0;
+ m_methodID = 0;
+
+ jclass modifierClass = env->FindClass("java/lang/reflect/Modifier");
+ int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I");
+ m_isStatic = static_cast<bool>(callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers));
+ env->DeleteLocalRef(modifierClass);
+}
+
+JavaMethod::~JavaMethod()
+{
+ if (m_signature)
+ fastFree(m_signature);
+ delete[] m_parameters;
+};
+
+// JNI method signatures use '/' between components of a class name, but
+// we get '.' between components from the reflection API.
+static void appendClassName(StringBuilder& builder, const char* className)
+{
+#if USE(JSC)
+ ASSERT(JSLock::lockCount() > 0);
+#endif
+
+ char* c = fastStrDup(className);
+
+ char* result = c;
+ while (*c) {
+ if (*c == '.')
+ *c = '/';
+ c++;
+ }
+
+ builder.append(result);
+
+ fastFree(result);
+}
+
+const char* JavaMethod::signature() const
+{
+ if (!m_signature) {
+#if USE(JSC)
+ JSLock lock(SilenceAssertionsOnly);
+#endif
+
+ StringBuilder signatureBuilder;
+ signatureBuilder.append('(');
+ for (int i = 0; i < m_numParameters; i++) {
+ JavaParameter* aParameter = parameterAt(i);
+ JNIType type = aParameter->getJNIType();
+ if (type == array_type)
+ appendClassName(signatureBuilder, aParameter->type());
+ else {
+ signatureBuilder.append(signatureFromPrimitiveType(type));
+ if (type == object_type) {
+ appendClassName(signatureBuilder, aParameter->type());
+ signatureBuilder.append(';');
+ }
+ }
+ }
+ signatureBuilder.append(')');
+
+ const char* returnType = m_returnType.utf8();
+ if (m_JNIReturnType == array_type)
+ appendClassName(signatureBuilder, returnType);
+ else {
+ signatureBuilder.append(signatureFromPrimitiveType(m_JNIReturnType));
+ if (m_JNIReturnType == object_type) {
+ appendClassName(signatureBuilder, returnType);
+ signatureBuilder.append(';');
+ }
+ }
+
+ String signatureString = signatureBuilder.toString();
+ m_signature = fastStrDup(signatureString.utf8().data());
+ }
+
+ return m_signature;
+}
+
+JNIType JavaMethod::JNIReturnType() const
+{
+ return m_JNIReturnType;
+}
+
+jmethodID JavaMethod::methodID(jobject obj) const
+{
+ if (!m_methodID)
+ m_methodID = getMethodID(obj, m_name.utf8(), signature());
+ return m_methodID;
+}
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/JNIBridge.h b/Source/WebCore/bridge/jni/JNIBridge.h
new file mode 100644
index 0000000..4f5e6b7
--- /dev/null
+++ b/Source/WebCore/bridge/jni/JNIBridge.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 JNIBridge_h
+#define JNIBridge_h
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "Bridge.h"
+#include "JNIUtility.h"
+
+#if USE(JSC)
+#include "JavaStringJSC.h"
+#elif USE(V8)
+#include "JavaStringV8.h"
+#endif
+
+namespace JSC {
+
+namespace Bindings {
+
+typedef const char* RuntimeType;
+
+class JavaString {
+public:
+ JavaString()
+ {
+ m_impl.init();
+ }
+
+ JavaString(JNIEnv* e, jstring s)
+ {
+ m_impl.init(e, s);
+ }
+
+ JavaString(jstring s)
+ {
+ m_impl.init(getJNIEnv(), s);
+ }
+
+ const char* utf8() const { return m_impl.utf8(); }
+ const jchar* uchars() const { return m_impl.uchars(); }
+ int length() const { return m_impl.length(); }
+#if USE(JSC)
+ operator UString() const { return m_impl.uString(); }
+#endif
+
+private:
+ JavaStringImpl m_impl;
+};
+
+class JavaParameter {
+public:
+ JavaParameter() : m_JNIType(invalid_type) { }
+ JavaParameter(JNIEnv*, jstring type);
+ virtual ~JavaParameter() { }
+
+ RuntimeType type() const { return m_type.utf8(); }
+ JNIType getJNIType() const { return m_JNIType; }
+
+private:
+ JavaString m_type;
+ JNIType m_JNIType;
+};
+
+class JavaMethod : public Method {
+public:
+ JavaMethod(JNIEnv*, jobject aMethod);
+ ~JavaMethod();
+
+ const JavaString& name() const { return m_name; }
+ RuntimeType returnType() const { return m_returnType.utf8(); }
+ JavaParameter* parameterAt(int i) const { return &m_parameters[i]; }
+ int numParameters() const { return m_numParameters; }
+
+ const char* signature() const;
+ JNIType JNIReturnType() const;
+
+ jmethodID methodID(jobject obj) const;
+
+ bool isStatic() const { return m_isStatic; }
+
+private:
+ JavaParameter* m_parameters;
+ int m_numParameters;
+ JavaString m_name;
+ mutable char* m_signature;
+ JavaString m_returnType;
+ JNIType m_JNIReturnType;
+ mutable jmethodID m_methodID;
+ bool m_isStatic;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JNIBridge_h
diff --git a/Source/WebCore/bridge/jni/JNIUtility.cpp b/Source/WebCore/bridge/jni/JNIUtility.cpp
new file mode 100644
index 0000000..4b4f393
--- /dev/null
+++ b/Source/WebCore/bridge/jni/JNIUtility.cpp
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Apple 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 "JNIUtility.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include <dlfcn.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+static jint KJSGetCreatedJavaVMs(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;
+
+ typedef jint(*FunctionPointerType)(JavaVM**, jsize, jsize*);
+ static FunctionPointerType functionPointer = 0;
+ if (!functionPointer)
+ functionPointer = reinterpret_cast<FunctionPointerType>(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 = KJSGetCreatedJavaVMs(jvmArray, bufLen, &nJVMs);
+ if (jniError == JNI_OK && nJVMs > 0)
+ jvm = jvmArray[0];
+ else
+ LOG_ERROR("JNI_GetCreatedJavaVMs failed, returned %ld", static_cast<long>(jniError));
+
+ return jvm;
+}
+
+JNIEnv* getJNIEnv()
+{
+ union {
+ JNIEnv* env;
+ void* dummy;
+ } u;
+ jint jniError = 0;
+
+ jniError = getJavaVM()->AttachCurrentThread(&u.dummy, 0);
+ if (jniError == JNI_OK)
+ return u.env;
+ LOG_ERROR("AttachCurrentThread failed, returned %ld", static_cast<long>(jniError));
+ return 0;
+}
+
+jmethodID getMethodID(jobject obj, const char* name, const char* sig)
+{
+ JNIEnv* env = getJNIEnv();
+ jmethodID mid = 0;
+
+ if (env) {
+ jclass cls = env->GetObjectClass(obj);
+ if (cls) {
+ 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;
+}
+
+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(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(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))
+ type = byte_type;
+ else if (!strcmp("short", name))
+ type = short_type;
+ else if (!strcmp("int", name))
+ type = int_type;
+ else if (!strcmp("long", name))
+ type = long_type;
+ else if (!strcmp("float", name))
+ type = float_type;
+ else if (!strcmp("double", name))
+ type = double_type;
+ else if (!strcmp("char", name))
+ type = char_type;
+ else if (!strcmp("boolean", name))
+ type = boolean_type;
+ else if (!strcmp("void", name))
+ 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;
+
+ memset(&result, 0, sizeof(jvalue));
+ if (obj && jvm && env) {
+ jclass cls = env->GetObjectClass(obj);
+ if (cls) {
+ jfieldID field = env->GetFieldID(cls, name, signature);
+ if (field) {
+ 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:
+ LOG_ERROR("Invalid field type (%d)", static_cast<int>(type));
+ }
+ } else {
+ LOG_ERROR("Could not find field: %s", name);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf(stderr, "\n");
+ }
+
+ env->DeleteLocalRef(cls);
+ } else
+ LOG_ERROR("Could not find class for object");
+ }
+
+ return result;
+}
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/JNIUtility.h b/Source/WebCore/bridge/jni/JNIUtility.h
new file mode 100644
index 0000000..5fb2138
--- /dev/null
+++ b/Source/WebCore/bridge/jni/JNIUtility.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2008, 2009, 2010 Apple 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 JNIUtility_h
+#define JNIUtility_h
+
+#if ENABLE(JAVA_BRIDGE)
+
+#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 JSC {
+
+namespace Bindings {
+
+class JavaParameter;
+
+const char* getCharactersFromJString(jstring);
+void releaseCharactersForJString(jstring, const char*);
+
+const char* getCharactersFromJStringInEnv(JNIEnv*, jstring);
+void releaseCharactersForJStringInEnv(JNIEnv*, jstring, const char*);
+const jchar* getUCharactersFromJStringInEnv(JNIEnv*, jstring);
+void releaseUCharactersForJStringInEnv(JNIEnv*, jstring, const jchar*);
+
+JNIType JNITypeFromClassName(const char* name);
+JNIType JNITypeFromPrimitiveType(char type);
+const char* signatureFromPrimitiveType(JNIType);
+
+jvalue getJNIField(jobject, JNIType, const char* name, const char* signature);
+
+jmethodID getMethodID(jobject, const char* name, const char* sig);
+JNIEnv* getJNIEnv();
+JavaVM* getJavaVM();
+void setJavaVM(JavaVM*);
+
+
+template <typename T> struct JNICaller;
+
+template<> struct JNICaller<void> {
+ static void callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ getJNIEnv()->CallVoidMethodA(obj, mid, args);
+ }
+ static void callV(jobject obj, jmethodID mid, va_list args)
+ {
+ getJNIEnv()->CallVoidMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jobject> {
+ static jobject callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallObjectMethodA(obj, mid, args);
+ }
+ static jobject callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallObjectMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jboolean> {
+ static jboolean callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallBooleanMethodA(obj, mid, args);
+ }
+ static jboolean callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallBooleanMethodV(obj, mid, args);
+ }
+ static jboolean callStaticV(jclass cls, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallStaticBooleanMethod(cls, mid, args);
+ }
+};
+
+template<> struct JNICaller<jbyte> {
+ static jbyte callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallByteMethodA(obj, mid, args);
+ }
+ static jbyte callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallByteMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jchar> {
+ static jchar callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallCharMethodA(obj, mid, args);
+ }
+ static jchar callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallCharMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jshort> {
+ static jshort callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallShortMethodA(obj, mid, args);
+ }
+ static jshort callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallShortMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jint> {
+ static jint callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallIntMethodA(obj, mid, args);
+ }
+ static jint callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallIntMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jlong> {
+ static jlong callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallLongMethodA(obj, mid, args);
+ }
+ static jlong callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallLongMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jfloat> {
+ static jfloat callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallFloatMethodA(obj, mid, args);
+ }
+ static jfloat callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallFloatMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jdouble> {
+ static jdouble callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallDoubleMethodA(obj, mid, args);
+ }
+ static jdouble callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallDoubleMethodV(obj, mid, args);
+ }
+};
+
+template<typename T> T callJNIMethodIDA(jobject obj, jmethodID mid, jvalue *args)
+{
+ return JNICaller<T>::callA(obj, mid, args);
+}
+
+template<typename T>
+static T callJNIMethodV(jobject obj, const char* name, const char* sig, va_list args)
+{
+ JavaVM* jvm = getJavaVM();
+ JNIEnv* env = getJNIEnv();
+
+ if (obj && jvm && env) {
+ jclass cls = env->GetObjectClass(obj);
+ if (cls) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if (mid) {
+ // Avoids references to cls without popping the local frame.
+ env->DeleteLocalRef(cls);
+ return JNICaller<T>::callV(obj, mid, args);
+ }
+ LOG_ERROR("Could not find method: %s for %p", name, obj);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf(stderr, "\n");
+
+ env->DeleteLocalRef(cls);
+ } else
+ LOG_ERROR("Could not find class for %p", obj);
+ }
+
+ return 0;
+}
+
+template<typename T>
+T callJNIMethod(jobject obj, const char* methodName, const char* methodSignature, ...)
+{
+ va_list args;
+ va_start(args, methodSignature);
+
+ T result = callJNIMethodV<T>(obj, methodName, methodSignature, args);
+
+ va_end(args);
+
+ return result;
+}
+
+template<typename T>
+T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSignature, ...)
+{
+ JavaVM* jvm = getJavaVM();
+ JNIEnv* env = getJNIEnv();
+ va_list args;
+
+ va_start(args, methodSignature);
+
+ T result = 0;
+
+ if (cls && jvm && env) {
+ jmethodID mid = env->GetStaticMethodID(cls, methodName, methodSignature);
+ if (mid)
+ result = JNICaller<T>::callStaticV(cls, mid, args);
+ else {
+ LOG_ERROR("Could not find method: %s for %p", methodName, cls);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf(stderr, "\n");
+ }
+ }
+
+ va_end(args);
+
+ return result;
+}
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JNIUtility_h
diff --git a/Source/WebCore/bridge/jni/jni_jsobject.h b/Source/WebCore/bridge/jni/jni_jsobject.h
new file mode 100644
index 0000000..34a78ba
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jni_jsobject.h
@@ -0,0 +1,133 @@
+/*
+ * 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
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include <JavaVM/jni.h>
+#include <runtime/JSValue.h>
+#include <wtf/RefPtr.h>
+
+#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))
+#define jlong_to_impptr(a) (static_cast<JSC::JSObject*>(((void*)(uintptr_t)(a))))
+#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))
+
+#if PLATFORM(MAC)
+
+namespace JSC {
+
+class ArgList;
+class ExecState;
+class JSObject;
+class MarkedArgumentBuffer;
+
+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(ExecState*, jobject) const;
+ void getListFromJArray(ExecState*, jobjectArray, MarkedArgumentBuffer&) const;
+
+ RootObject* rootObject() const;
+
+ // Must be called from the thread that will be used to access JavaScript.
+ static void initializeJNIThreading();
+private:
+ RefPtr<RootObject> _rootObject;
+ JSObject* _imp;
+};
+
+
+} // namespace Bindings
+
+} // namespace JSC
+
+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 // PLATFORM(MAC)
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
diff --git a/Source/WebCore/bridge/jni/jni_jsobject.mm b/Source/WebCore/bridge/jni/jni_jsobject.mm
new file mode 100644
index 0000000..f8ec1c4
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jni_jsobject.mm
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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_jsobject.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "Frame.h"
+#include "JavaRuntimeObject.h"
+#include "JNIBridge.h"
+#include "JNIUtility.h"
+#include "JNIUtilityPrivate.h"
+#include "JSDOMBinding.h"
+#include "Logging.h"
+#include "ScriptController.h"
+#include "StringSourceProvider.h"
+#include "WebCoreFrameView.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <interpreter/CallFrame.h>
+#include <runtime/Completion.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+
+using WebCore::Frame;
+
+using namespace JSC::Bindings;
+using namespace JSC;
+using namespace WebCore;
+
+#define UndefinedHandle 1
+
+static CFRunLoopSourceRef _performJavaScriptSource;
+static CFRunLoopRef _performJavaScriptRunLoop;
+
+// May only be set by dispatchToJavaScriptThread().
+static CFRunLoopSourceRef completionSource;
+
+static void completedJavaScriptAccess (void *i)
+{
+ ASSERT(CFRunLoopGetCurrent() != _performJavaScriptRunLoop);
+
+ JSObjectCallContext *callContext = (JSObjectCallContext *)i;
+ CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop;
+
+ ASSERT(CFRunLoopGetCurrent() == runLoop);
+
+ CFRunLoopStop(runLoop);
+}
+
+static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT;
+static pthread_mutex_t javaScriptAccessLock;
+static int javaScriptAccessLockCount = 0;
+
+static void initializeJavaScriptAccessLock()
+{
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init(&javaScriptAccessLock, &attr);
+}
+
+static inline void lockJavaScriptAccess()
+{
+ // Perhaps add deadlock detection?
+ pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock);
+ pthread_mutex_lock(&javaScriptAccessLock);
+ javaScriptAccessLockCount++;
+}
+
+static inline void unlockJavaScriptAccess()
+{
+ javaScriptAccessLockCount--;
+ pthread_mutex_unlock(&javaScriptAccessLock);
+}
+
+static void dispatchToJavaScriptThread(JSObjectCallContext *context)
+{
+ // This lock guarantees that only one thread can invoke
+ // at a time, and also guarantees that completionSource;
+ // won't get clobbered.
+ lockJavaScriptAccess();
+
+ CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
+
+ ASSERT(currentRunLoop != _performJavaScriptRunLoop);
+
+ // Setup a source to signal once the invocation of the JavaScript
+ // call completes.
+ //
+ // FIXME: This could be a potential performance issue. Creating and
+ // adding run loop sources is expensive. We could create one source
+ // per thread, as needed, instead.
+ context->originatingLoop = currentRunLoop;
+ CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess};
+ completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+
+ // Wakeup JavaScript access thread and make it do its work.
+ CFRunLoopSourceSignal(_performJavaScriptSource);
+ if (CFRunLoopIsWaiting(_performJavaScriptRunLoop))
+ CFRunLoopWakeUp(_performJavaScriptRunLoop);
+
+ // Wait until the JavaScript access thread is done.
+ CFRunLoopRun ();
+
+ CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+ CFRelease (completionSource);
+
+ unlockJavaScriptAccess();
+}
+
+static void performJavaScriptAccess(void*)
+{
+ ASSERT(CFRunLoopGetCurrent() == _performJavaScriptRunLoop);
+
+ // Dispatch JavaScript calls here.
+ CFRunLoopSourceContext sourceContext;
+ CFRunLoopSourceGetContext (completionSource, &sourceContext);
+ JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info;
+ CFRunLoopRef originatingLoop = callContext->originatingLoop;
+
+ JavaJSObject::invoke (callContext);
+
+ // Signal the originating thread that we're done.
+ CFRunLoopSourceSignal (completionSource);
+ if (CFRunLoopIsWaiting(originatingLoop))
+ CFRunLoopWakeUp(originatingLoop);
+}
+
+// Must be called from the thread that will be used to access JavaScript.
+void JavaJSObject::initializeJNIThreading() {
+ // Should only be called once.
+ ASSERT(!_performJavaScriptRunLoop);
+
+ // Assume that we can retain this run loop forever. It'll most
+ // likely (always?) be the main loop.
+ _performJavaScriptRunLoop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent());
+
+ // Setup a source the other threads can use to signal the _runLoop
+ // thread that a JavaScript call needs to be invoked.
+ CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess};
+ _performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(_performJavaScriptRunLoop, _performJavaScriptSource, kCFRunLoopDefaultMode);
+}
+
+static bool isJavaScriptThread()
+{
+ return (_performJavaScriptRunLoop == 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.
+ 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)) {
+ LOG_ERROR("Attempt to access JavaScript from destroyed applet, type %d.", 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: {
+ LOG_ERROR("invalid JavaScript call");
+ }
+ }
+ }
+ 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
+{
+ LOG(LiveConnect, "JavaJSObject::call methodName = %s", JavaString(methodName).utf8());
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ // Lookup the function object.
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+
+ Identifier identifier(exec, JavaString(methodName));
+ JSValue function = _imp->get(exec, identifier);
+ CallData callData;
+ CallType callType = getCallData(function, callData);
+ if (callType == CallTypeNone)
+ return 0;
+
+ // Call the function object.
+ MarkedArgumentBuffer argList;
+ getListFromJArray(exec, args, argList);
+ rootObject->globalObject()->globalData().timeoutChecker.start();
+ JSValue result = JSC::call(exec, function, callType, callData, _imp, argList);
+ rootObject->globalObject()->globalData().timeoutChecker.stop();
+
+ return convertValueToJObject(result);
+}
+
+jobject JavaJSObject::eval(jstring script) const
+{
+ LOG(LiveConnect, "JavaJSObject::eval script = %s", JavaString(script).utf8());
+
+ JSValue result;
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ rootObject->globalObject()->globalData().timeoutChecker.start();
+ Completion completion = JSC::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script)), JSC::JSValue());
+ rootObject->globalObject()->globalData().timeoutChecker.stop();
+ 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
+{
+ LOG(LiveConnect, "JavaJSObject::getMember (%p) memberName = %s", _imp, JavaString(memberName).utf8());
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue result = _imp->get(exec, Identifier(exec, JavaString(memberName)));
+
+ return convertValueToJObject(result);
+}
+
+void JavaJSObject::setMember(jstring memberName, jobject value) const
+{
+ LOG(LiveConnect, "JavaJSObject::setMember memberName = %s, value = %p", JavaString(memberName).utf8(), value);
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock(SilenceAssertionsOnly);
+ PutPropertySlot slot;
+ _imp->put(exec, Identifier(exec, JavaString(memberName)), convertJObjectToValue(exec, value), slot);
+}
+
+
+void JavaJSObject::removeMember(jstring memberName) const
+{
+ LOG(LiveConnect, "JavaJSObject::removeMember memberName = %s", JavaString(memberName).utf8());
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ _imp->deleteProperty(exec, Identifier(exec, JavaString(memberName)));
+}
+
+
+jobject JavaJSObject::getSlot(jint index) const
+{
+ LOG(LiveConnect, "JavaJSObject::getSlot index = %ld", static_cast<long>(index));
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue result = _imp->get(exec, index);
+
+ return convertValueToJObject(result);
+}
+
+
+void JavaJSObject::setSlot(jint index, jobject value) const
+{
+ LOG(LiveConnect, "JavaJSObject::setSlot index = %ld, value = %p", static_cast<long>(index), value);
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(SilenceAssertionsOnly);
+ _imp->put(exec, (unsigned)index, convertJObjectToValue(exec, value));
+}
+
+
+jstring JavaJSObject::toString() const
+{
+ LOG(LiveConnect, "JavaJSObject::toString");
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ JSLock lock(SilenceAssertionsOnly);
+ JSObject *thisObj = const_cast<JSObject*>(_imp);
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ return static_cast<jstring>(convertValueToJValue(exec, rootObject, thisObj, object_type, "java.lang.String").l);
+}
+
+void JavaJSObject::finalize() const
+{
+ if (RootObject* rootObject = this->rootObject())
+ rootObject->gcUnprotect(_imp);
+}
+
+static PassRefPtr<RootObject> createRootObject(void* nativeHandle)
+{
+ Frame* frame = 0;
+ for (NSView *view = (NSView *)nativeHandle; view; view = [view superview]) {
+ if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
+ NSView<WebCoreFrameView> *webCoreFrameView = static_cast<NSView<WebCoreFrameView>*>(view);
+ frame = [webCoreFrameView _web_frame];
+ break;
+ }
+ }
+ if (!frame)
+ return 0;
+ return frame->script()->createRootObject(nativeHandle);
+}
+
+// We're either creating a 'Root' object (via a call to JavaJSObject.getWindow()), or
+// another JavaJSObject.
+jlong JavaJSObject::createNative(jlong nativeHandle)
+{
+ LOG(LiveConnect, "JavaJSObject::createNative nativeHandle = %d", static_cast<int>(nativeHandle));
+
+ if (nativeHandle == UndefinedHandle)
+ return nativeHandle;
+
+ if (findProtectingRootObject(jlong_to_impptr(nativeHandle)))
+ return nativeHandle;
+
+ 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(SilenceAssertionsOnly);
+
+ 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
+
+ if (value.isNumber()) {
+ jclass JSObjectClass = env->FindClass ("java/lang/Double");
+ jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(D)V");
+ if (constructorID != NULL) {
+ result = env->NewObject (JSObjectClass, constructorID, (jdouble)value.toNumber(exec));
+ }
+ } else if (value.isString()) {
+ UString stringValue = value.toString(exec);
+ JNIEnv *env = getJNIEnv();
+ result = env->NewString ((const jchar *)stringValue.characters(), stringValue.length());
+ } else if (value.isBoolean()) {
+ 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 (value.isObject()) {
+ JSObject* object = asObject(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 its nativeHandle.
+ if (object->inherits(&JavaRuntimeObject::s_info)) {
+ JavaRuntimeObject* runtimeObject = static_cast<JavaRuntimeObject*>(object);
+ JavaInstance* runtimeInstance = runtimeObject->getInternalJavaInstance();
+ if (!runtimeInstance)
+ return 0;
+
+ return runtimeInstance->javaInstance();
+ } else {
+ nativeHandle = ptr_to_jlong(object);
+ rootObject->gcProtect(object);
+ }
+ } else {
+ // All other types will result in an undefined object.
+ nativeHandle = UndefinedHandle;
+ }
+
+ // Now create the Java JavaJSObject. Look for the JavaJSObject in its 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(ExecState* exec, 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 = callJNIMethod<jobject>(theObject, "getClass", "()Ljava/lang/Class;");
+ if (!classOfInstance) {
+ JSLock lock(SilenceAssertionsOnly);
+ return JavaInstance::create(theObject, _rootObject)->createRuntimeObject(exec);
+ }
+
+ // 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.
+ jstring className = (jstring)callJNIMethod<jobject>(classOfInstance, "getName", "()Ljava/lang/String;");
+ if (!className || (strcmp(JavaString(className).utf8(), "sun.plugin.javascript.webkit.JSObject") != 0)) {
+ JSLock lock(SilenceAssertionsOnly);
+ return JavaInstance::create(theObject, _rootObject)->createRuntimeObject(exec);
+ }
+
+ // 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;
+}
+
+void JavaJSObject::getListFromJArray(ExecState* exec, jobjectArray jArray, MarkedArgumentBuffer& list) const
+{
+ JNIEnv *env = getJNIEnv();
+ int numObjects = jArray ? env->GetArrayLength(jArray) : 0;
+
+ for (int i = 0; i < numObjects; i++) {
+ jobject anObject = env->GetObjectArrayElement ((jobjectArray)jArray, i);
+ if (anObject) {
+ list.append(convertJObjectToValue(exec, 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;
+}
+
+}
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/jni_objc.mm b/Source/WebCore/bridge/jni/jni_objc.mm
new file mode 100644
index 0000000..8fa2c3f
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jni_objc.mm
@@ -0,0 +1,84 @@
+/*
+ * 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 ENABLE(JAVA_BRIDGE)
+
+#import <Foundation/Foundation.h>
+#import "JNIUtility.h"
+#import "JNIUtilityPrivate.h"
+#import "objc_utility.h"
+#include <runtime/JSLock.h>
+
+using namespace JSC::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 JSC::Bindings::dispatchJNICall(ExecState* exec, 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(SilenceAssertionsOnly);
+ result = [view webPlugInCallJava:obj isStatic:isStatic returnType:returnType method:methodID arguments:args callingURL:nil exceptionDescription:&_exceptionDescription];
+ }
+
+ if (_exceptionDescription != 0) {
+ exceptionDescription = convertNSStringToString(exec, _exceptionDescription);
+ }
+ return true;
+ }
+ else if ([view respondsToSelector:@selector(webPlugInCallJava:method:returnType:arguments:)]) {
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
+ result = [view webPlugInCallJava:obj method:methodID returnType:returnType arguments:args];
+ return true;
+ }
+
+ bzero (&result, sizeof(jvalue));
+ return false;
+}
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp b/Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp
new file mode 100644
index 0000000..3c16d05
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 "JNIBridgeJSC.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "JNIUtilityPrivate.h"
+#include "Logging.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <runtime/Error.h>
+
+using namespace JSC;
+using namespace JSC::Bindings;
+using namespace WebCore;
+
+JavaField::JavaField(JNIEnv* env, jobject aField)
+{
+ // Get field type name
+ jstring fieldTypeName = 0;
+ if (jobject fieldType = callJNIMethod<jobject>(aField, "getType", "()Ljava/lang/Class;"))
+ fieldTypeName = static_cast<jstring>(callJNIMethod<jobject>(fieldType, "getName", "()Ljava/lang/String;"));
+ if (!fieldTypeName)
+ fieldTypeName = env->NewStringUTF("<Unknown>");
+ m_type = JavaString(env, fieldTypeName);
+
+ m_JNIType = JNITypeFromClassName(m_type.utf8());
+
+ // Get field name
+ jstring fieldName = static_cast<jstring>(callJNIMethod<jobject>(aField, "getName", "()Ljava/lang/String;"));
+ if (!fieldName)
+ fieldName = env->NewStringUTF("<Unknown>");
+ m_name = JavaString(env, fieldName);
+
+ m_field = new JObjectWrapper(aField);
+}
+
+JSValue JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
+{
+ if (type[0] != '[')
+ return jsUndefined();
+
+ return new (exec) RuntimeArray(exec, new JavaArray(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 = m_field->m_instance;
+ JNIEnv* env = getJNIEnv();
+ jvalue result;
+
+ memset(&result, 0, sizeof(jvalue));
+ jclass cls = env->GetObjectClass(fieldJInstance);
+ if (cls) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if (mid) {
+ RootObject* rootObject = instance->rootObject();
+ if (rootObject && rootObject->nativeHandle()) {
+ JSValue exceptionDescription;
+ jvalue args[1];
+
+ args[0].l = jinstance;
+ dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
+ if (exceptionDescription)
+ throwError(exec, createError(exec, 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 (m_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;
+
+ if (!anObject)
+ return jsNull();
+
+ const char* arrayType = type();
+ if (arrayType[0] == '[')
+ jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject());
+ else if (anObject)
+ jsresult = JavaInstance::create(anObject, instance->rootObject())->createRuntimeObject(exec);
+ }
+ 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(static_cast<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(static_cast<double>(value));
+ }
+ break;
+ default:
+ break;
+ }
+
+ LOG(LiveConnect, "JavaField::valueFromInstance getting %s = %s", UString(name()).utf8().data(), jsresult.toString(exec).ascii().data());
+
+ 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 = m_field->m_instance;
+ JNIEnv* env = getJNIEnv();
+
+ jclass cls = env->GetObjectClass(fieldJInstance);
+ if (cls) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if (mid) {
+ RootObject* rootObject = instance->rootObject();
+ if (rootObject && rootObject->nativeHandle()) {
+ JSValue exceptionDescription;
+ jvalue args[2];
+ jvalue result;
+
+ args[0].l = jinstance;
+ args[1] = javaValue;
+ dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
+ if (exceptionDescription)
+ throwError(exec, createError(exec, 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, i->rootObject(), aValue, m_JNIType, type());
+
+ LOG(LiveConnect, "JavaField::setValueToInstance setting value %s to %s", UString(name()).utf8().data(), aValue.toString(exec).ascii().data());
+
+ switch (m_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;
+ }
+}
+
+JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
+ : Array(rootObject)
+{
+ m_array = new JObjectWrapper(array);
+ // Java array are fixed length, so we can cache length.
+ JNIEnv* env = getJNIEnv();
+ m_length = env->GetArrayLength(static_cast<jarray>(m_array->m_instance));
+ m_type = strdup(type);
+}
+
+JavaArray::~JavaArray()
+{
+ free(const_cast<char*>(m_type));
+}
+
+RootObject* JavaArray::rootObject() const
+{
+ return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
+}
+
+void JavaArray::setValueAt(ExecState* exec, unsigned index, JSValue aValue) const
+{
+ JNIEnv* env = getJNIEnv();
+ char* javaClassName = 0;
+
+ JNIType arrayType = JNITypeFromPrimitiveType(m_type[1]);
+ if (m_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(&m_type[2]);
+ javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
+ }
+ jvalue aJValue = convertValueToJValue(exec, m_rootObject.get(), aValue, arrayType, javaClassName);
+
+ switch (arrayType) {
+ case object_type:
+ {
+ env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray()), index, aJValue.l);
+ break;
+ }
+
+ case boolean_type:
+ {
+ env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray()), index, 1, &aJValue.z);
+ break;
+ }
+
+ case byte_type:
+ {
+ env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray()), index, 1, &aJValue.b);
+ break;
+ }
+
+ case char_type:
+ {
+ env->SetCharArrayRegion(static_cast<jcharArray>(javaArray()), index, 1, &aJValue.c);
+ break;
+ }
+
+ case short_type:
+ {
+ env->SetShortArrayRegion(static_cast<jshortArray>(javaArray()), index, 1, &aJValue.s);
+ break;
+ }
+
+ case int_type:
+ {
+ env->SetIntArrayRegion(static_cast<jintArray>(javaArray()), index, 1, &aJValue.i);
+ break;
+ }
+
+ case long_type:
+ {
+ env->SetLongArrayRegion(static_cast<jlongArray>(javaArray()), index, 1, &aJValue.j);
+ }
+
+ case float_type:
+ {
+ env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray()), index, 1, &aJValue.f);
+ break;
+ }
+
+ case double_type:
+ {
+ env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray()), index, 1, &aJValue.d);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (javaClassName)
+ free(const_cast<char*>(javaClassName));
+}
+
+
+JSValue JavaArray::valueAt(ExecState* exec, unsigned index) const
+{
+ JNIEnv* env = getJNIEnv();
+ JNIType arrayType = JNITypeFromPrimitiveType(m_type[1]);
+ switch (arrayType) {
+ case object_type:
+ {
+ jobjectArray objectArray = static_cast<jobjectArray>(javaArray());
+ jobject anObject;
+ anObject = env->GetObjectArrayElement(objectArray, index);
+
+ // No object?
+ if (!anObject)
+ return jsNull();
+
+ // Nested array?
+ if (m_type[1] == '[')
+ return JavaArray::convertJObjectToArray(exec, anObject, m_type + 1, rootObject());
+ // or array of other object type?
+ return JavaInstance::create(anObject, rootObject())->createRuntimeObject(exec);
+ }
+
+ case boolean_type:
+ {
+ jbooleanArray booleanArray = static_cast<jbooleanArray>(javaArray());
+ jboolean aBoolean;
+ env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
+ return jsBoolean(aBoolean);
+ }
+
+ case byte_type:
+ {
+ jbyteArray byteArray = static_cast<jbyteArray>(javaArray());
+ jbyte aByte;
+ env->GetByteArrayRegion(byteArray, index, 1, &aByte);
+ return jsNumber(aByte);
+ }
+
+ case char_type:
+ {
+ jcharArray charArray = static_cast<jcharArray>(javaArray());
+ jchar aChar;
+ env->GetCharArrayRegion(charArray, index, 1, &aChar);
+ return jsNumber(aChar);
+ break;
+ }
+
+ case short_type:
+ {
+ jshortArray shortArray = static_cast<jshortArray>(javaArray());
+ jshort aShort;
+ env->GetShortArrayRegion(shortArray, index, 1, &aShort);
+ return jsNumber(aShort);
+ }
+
+ case int_type:
+ {
+ jintArray intArray = static_cast<jintArray>(javaArray());
+ jint anInt;
+ env->GetIntArrayRegion(intArray, index, 1, &anInt);
+ return jsNumber(anInt);
+ }
+
+ case long_type:
+ {
+ jlongArray longArray = static_cast<jlongArray>(javaArray());
+ jlong aLong;
+ env->GetLongArrayRegion(longArray, index, 1, &aLong);
+ return jsNumber(aLong);
+ }
+
+ case float_type:
+ {
+ jfloatArray floatArray = static_cast<jfloatArray>(javaArray());
+ jfloat aFloat;
+ env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
+ return jsNumber(aFloat);
+ }
+
+ case double_type:
+ {
+ jdoubleArray doubleArray = static_cast<jdoubleArray>(javaArray());
+ jdouble aDouble;
+ env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
+ return jsNumber(aDouble);
+ }
+ default:
+ break;
+ }
+ return jsUndefined();
+}
+
+unsigned int JavaArray::getLength() const
+{
+ return m_length;
+}
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.h b/Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.h
new file mode 100644
index 0000000..afb1bce
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JNIBridgeJSC.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 JNIBridgeJSC_h
+#define JNIBridgeJSC_h
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "Bridge.h"
+#include "JNIBridge.h"
+#include <JavaVM/jni.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaField : public Field {
+public:
+ JavaField(JNIEnv*, jobject aField);
+
+ virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
+
+ const JavaString& name() const { return m_name; }
+ virtual RuntimeType type() const { return m_type.utf8(); }
+
+ JNIType getJNIType() const { return m_JNIType; }
+
+private:
+ void dispatchSetValueToInstance(ExecState*, const JavaInstance*, jvalue, const char* name, const char* sig) const;
+ jvalue dispatchValueFromInstance(ExecState*, const JavaInstance*, const char* name, const char* sig, JNIType returnType) const;
+
+ JavaString m_name;
+ JavaString m_type;
+ JNIType m_JNIType;
+ RefPtr<JObjectWrapper> m_field;
+};
+
+class JavaArray : public Array {
+public:
+ JavaArray(jobject array, const char* type, PassRefPtr<RootObject>);
+ virtual ~JavaArray();
+
+ RootObject* rootObject() const;
+
+ virtual void setValueAt(ExecState*, unsigned int index, JSValue) const;
+ virtual JSValue valueAt(ExecState*, unsigned int index) const;
+ virtual unsigned int getLength() const;
+
+ jobject javaArray() const { return m_array->m_instance; }
+
+ static JSValue convertJObjectToArray(ExecState*, jobject, const char* type, PassRefPtr<RootObject>);
+
+private:
+ RefPtr<JObjectWrapper> m_array;
+ unsigned int m_length;
+ const char* m_type;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JNIBridge_h
diff --git a/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp b/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp
new file mode 100644
index 0000000..bf19642
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2003, 2010 Apple, Inc. All rights reserved.
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JNIUtilityPrivate.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "JavaRuntimeObject.h"
+#include "JNIBridgeJSC.h"
+#include "jni_jsobject.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <runtime/JSArray.h>
+#include <runtime/JSLock.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+static jobject convertArrayInstanceToJavaArray(ExecState* exec, JSArray* jsArray, const char* javaClassName)
+{
+ 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.
+ unsigned length = jsArray->length();
+ jobjectArray jarray = 0;
+
+ // Build the correct array type
+ switch (JNITypeFromPrimitiveType(javaClassName[1])) {
+ case object_type:
+ {
+ // Only support string object types
+ if (!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->get(exec, i);
+ UString stringValue = item.toString(exec);
+ env->SetObjectArrayElement(jarray, i,
+ env->functions->NewString(env, (const jchar *)stringValue.characters(), stringValue.length()));
+ }
+ }
+ break;
+ }
+
+ case boolean_type:
+ {
+ jarray = (jobjectArray)env->NewBooleanArray(length);
+ for (unsigned i = 0; i < length; i++) {
+ JSValue item = jsArray->get(exec, 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->get(exec, 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->get(exec, i);
+ UString stringValue = item.toString(exec);
+ jchar value = 0;
+ if (stringValue.length() > 0)
+ value = ((const jchar*)stringValue.characters())[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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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, RootObject* rootObject, JSValue value, JNIType jniType, const char* javaClassName)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ jvalue result;
+ memset(&result, 0, sizeof(jvalue));
+
+ switch (jniType) {
+ case array_type:
+ case object_type:
+ {
+ // FIXME: JavaJSObject::convertValueToJObject functionality is almost exactly the same,
+ // these functions should use common code.
+
+ if (value.isObject()) {
+ JSObject* object = asObject(value);
+ if (object->inherits(&JavaRuntimeObject::s_info)) {
+ // Unwrap a Java instance.
+ JavaRuntimeObject* runtimeObject = static_cast<JavaRuntimeObject*>(object);
+ JavaInstance* instance = runtimeObject->getInternalJavaInstance();
+ if (instance)
+ result.l = instance->javaInstance();
+ } else if (object->classInfo() == &RuntimeArray::s_info) {
+ // Input is a JavaScript Array that was originally created from a Java Array
+ RuntimeArray* imp = static_cast<RuntimeArray*>(object);
+ JavaArray* array = static_cast<JavaArray*>(imp->getConcreteArray());
+ result.l = array->javaArray();
+ } else if (object->classInfo() == &JSArray::info) {
+ // Input is a Javascript Array. We need to create it to a Java Array.
+ result.l = convertArrayInstanceToJavaArray(exec, asArray(value), javaClassName);
+ } else if ((!result.l && (!strcmp(javaClassName, "java.lang.Object")))
+ || (!strcmp(javaClassName, "netscape.javascript.JSObject"))) {
+ // Wrap objects in JSObject instances.
+ JNIEnv* env = getJNIEnv();
+ jclass jsObjectClass = env->FindClass("sun/plugin/javascript/webkit/JSObject");
+ jmethodID constructorID = env->GetMethodID(jsObjectClass, "<init>", "(J)V");
+ if (constructorID) {
+ jlong nativeHandle = ptr_to_jlong(object);
+ rootObject->gcProtect(object);
+ result.l = env->NewObject(jsObjectClass, constructorID, nativeHandle);
+ }
+ }
+ }
+
+ // Create an appropriate Java object if target type is java.lang.Object.
+ if (!result.l && !strcmp(javaClassName, "java.lang.Object")) {
+ if (value.isString()) {
+ UString stringValue = asString(value)->value(exec);
+ JNIEnv* env = getJNIEnv();
+ jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.characters(), stringValue.length());
+ result.l = javaString;
+ } else if (value.isNumber()) {
+ double doubleValue = value.uncheckedGetNumber();
+ JNIEnv* env = getJNIEnv();
+ jclass clazz = env->FindClass("java/lang/Double");
+ jmethodID constructor = env->GetMethodID(clazz, "<init>", "(D)V");
+ jobject javaDouble = env->functions->NewObject(env, clazz, constructor, doubleValue);
+ result.l = javaDouble;
+ } else if (value.isBoolean()) {
+ bool boolValue = value.getBoolean();
+ JNIEnv* env = getJNIEnv();
+ jclass clazz = env->FindClass("java/lang/Boolean");
+ jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V");
+ jobject javaBoolean = env->functions->NewObject(env, clazz, constructor, boolValue);
+ result.l = javaBoolean;
+ } else if (value.isUndefined()) {
+ UString stringValue = "undefined";
+ JNIEnv* env = getJNIEnv();
+ jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.characters(), stringValue.length());
+ result.l = javaString;
+ }
+ }
+
+ // 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 && !strcmp(javaClassName, "java.lang.String")) {
+ if (!value.isNull()) {
+ UString stringValue = value.toString(exec);
+ JNIEnv* env = getJNIEnv();
+ jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.characters(), stringValue.length());
+ result.l = javaString;
+ }
+ }
+ }
+ 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;
+
+ case invalid_type:
+ case void_type:
+ break;
+ }
+ return result;
+}
+
+} // end of namespace Bindings
+
+} // end of namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h b/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h
new file mode 100644
index 0000000..1266acd
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JNIUtilityPrivate_h
+#define JNIUtilityPrivate_h
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "JNIUtility.h"
+#include <runtime/JSValue.h>
+
+namespace JSC {
+
+class ExecState;
+class JSObject;
+
+namespace Bindings {
+
+class RootObject;
+
+jvalue convertValueToJValue(ExecState*, RootObject*, JSValue, JNIType, const char* javaClassName);
+bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValue& exceptionDescription);
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JNIUtilityPrivate_h
diff --git a/Source/WebCore/bridge/jni/jsc/JavaClassJSC.cpp b/Source/WebCore/bridge/jni/jsc/JavaClassJSC.cpp
new file mode 100644
index 0000000..43cdc96
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaClassJSC.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple 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 "JavaClassJSC.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "JNIUtility.h"
+#include "JSDOMWindow.h"
+#include <runtime/Identifier.h>
+#include <runtime/JSLock.h>
+
+using namespace JSC::Bindings;
+
+JavaClass::JavaClass(jobject anInstance)
+{
+ jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;");
+
+ if (!aClass) {
+ LOG_ERROR("Unable to call getClass on instance %p", anInstance);
+ m_name = fastStrDup("<Unknown>");
+ return;
+ }
+
+ if (jstring className = (jstring)callJNIMethod<jobject>(aClass, "getName", "()Ljava/lang/String;")) {
+ const char* classNameC = getCharactersFromJString(className);
+ m_name = fastStrDup(classNameC);
+ releaseCharactersForJString(className, classNameC);
+ } else
+ m_name = fastStrDup("<Unknown>");
+
+ int i;
+ JNIEnv* env = getJNIEnv();
+
+ // Get the fields
+ if (jarray fields = (jarray)callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;")) {
+ int numFields = env->GetArrayLength(fields);
+ for (i = 0; i < numFields; i++) {
+ jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i);
+ JavaField* aField = new JavaField(env, aJField); // deleted in the JavaClass destructor
+ {
+ JSLock lock(SilenceAssertionsOnly);
+ m_fields.set(((UString)aField->name()).impl(), aField);
+ }
+ env->DeleteLocalRef(aJField);
+ }
+ env->DeleteLocalRef(fields);
+ }
+
+ // Get the methods
+ if (jarray methods = (jarray)callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;")) {
+ int numMethods = env->GetArrayLength(methods);
+ for (i = 0; i < numMethods; i++) {
+ jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i);
+ JavaMethod* aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor
+ MethodList* methodList;
+ {
+ JSLock lock(SilenceAssertionsOnly);
+
+ methodList = m_methods.get(((UString)aMethod->name()).impl());
+ if (!methodList) {
+ methodList = new MethodList();
+ m_methods.set(((UString)aMethod->name()).impl(), methodList);
+ }
+ }
+ methodList->append(aMethod);
+ env->DeleteLocalRef(aJMethod);
+ }
+ env->DeleteLocalRef(methods);
+ }
+
+ env->DeleteLocalRef(aClass);
+}
+
+JavaClass::~JavaClass()
+{
+ fastFree(const_cast<char*>(m_name));
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ deleteAllValues(m_fields);
+ m_fields.clear();
+
+ MethodListMap::const_iterator end = m_methods.end();
+ for (MethodListMap::const_iterator it = m_methods.begin(); it != end; ++it) {
+ const MethodList* methodList = it->second;
+ deleteAllValues(*methodList);
+ delete methodList;
+ }
+ m_methods.clear();
+}
+
+MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+ MethodList* methodList = m_methods.get(identifier.ustring().impl());
+
+ if (methodList)
+ return *methodList;
+ return MethodList();
+}
+
+Field* JavaClass::fieldNamed(const Identifier& identifier, Instance*) const
+{
+ return m_fields.get(identifier.ustring().impl());
+}
+
+bool JavaClass::isNumberClass() const
+{
+ return (!strcmp(m_name, "java.lang.Byte")
+ || !strcmp(m_name, "java.lang.Short")
+ || !strcmp(m_name, "java.lang.Integer")
+ || !strcmp(m_name, "java.lang.Long")
+ || !strcmp(m_name, "java.lang.Float")
+ || !strcmp(m_name, "java.lang.Double"));
+}
+
+bool JavaClass::isBooleanClass() const
+{
+ return !strcmp(m_name, "java.lang.Boolean");
+}
+
+bool JavaClass::isStringClass() const
+{
+ return !strcmp(m_name, "java.lang.String");
+}
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/jsc/JavaClassJSC.h b/Source/WebCore/bridge/jni/jsc/JavaClassJSC.h
new file mode 100644
index 0000000..0527162
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaClassJSC.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007, 2009, 2010 Apple 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 JavaClassJSC_h
+#define JavaClassJSC_h
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "JNIBridgeJSC.h"
+#include <wtf/HashMap.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaClass : public Class {
+public:
+ JavaClass(jobject);
+ ~JavaClass();
+
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+ virtual Field* fieldNamed(const Identifier&, Instance*) const;
+
+ bool isNumberClass() const;
+ bool isBooleanClass() const;
+ bool isStringClass() const;
+
+private:
+ const char* m_name;
+ FieldMap m_fields;
+ MethodListMap m_methods;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JavaClassJSC_h
diff --git a/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp b/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp
new file mode 100644
index 0000000..6332545
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2003, 2008, 2010 Apple 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 "JavaInstanceJSC.h"
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "JavaRuntimeObject.h"
+#include "JNIBridgeJSC.h"
+#include "JNIUtility.h"
+#include "JNIUtilityPrivate.h"
+#include "JavaClassJSC.h"
+#include "Logging.h"
+#include "jni_jsobject.h"
+#include "runtime_method.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <runtime/ArgList.h>
+#include <runtime/Error.h>
+#include <runtime/JSLock.h>
+
+using namespace JSC::Bindings;
+using namespace JSC;
+using namespace WebCore;
+
+JavaInstance::JavaInstance(jobject instance, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+{
+ m_instance = new JObjectWrapper(instance);
+ m_class = 0;
+}
+
+JavaInstance::~JavaInstance()
+{
+ delete m_class;
+}
+
+RuntimeObject* JavaInstance::newRuntimeObject(ExecState* exec)
+{
+ return new (exec) JavaRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+#define NUM_LOCAL_REFS 64
+
+void JavaInstance::virtualBegin()
+{
+ getJNIEnv()->PushLocalFrame(NUM_LOCAL_REFS);
+}
+
+void JavaInstance::virtualEnd()
+{
+ getJNIEnv()->PopLocalFrame(0);
+}
+
+Class* JavaInstance::getClass() const
+{
+ if (!m_class)
+ m_class = new JavaClass (m_instance->m_instance);
+ return m_class;
+}
+
+JSValue JavaInstance::stringValue(ExecState* exec) const
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ jstring stringValue = (jstring)callJNIMethod<jobject>(m_instance->m_instance, "toString", "()Ljava/lang/String;");
+
+ // Should throw a JS exception, rather than returning ""? - but better than a null dereference.
+ if (!stringValue)
+ return jsString(exec, UString());
+
+ JNIEnv* env = getJNIEnv();
+ const jchar* c = getUCharactersFromJStringInEnv(env, stringValue);
+ UString u((const UChar*)c, (int)env->GetStringLength(stringValue));
+ releaseUCharactersForJStringInEnv(env, stringValue, c);
+ return jsString(exec, u);
+}
+
+JSValue JavaInstance::numberValue(ExecState*) const
+{
+ jdouble doubleValue = callJNIMethod<jdouble>(m_instance->m_instance, "doubleValue", "()D");
+ return jsNumber(doubleValue);
+}
+
+JSValue JavaInstance::booleanValue() const
+{
+ jboolean booleanValue = callJNIMethod<jboolean>(m_instance->m_instance, "booleanValue", "()Z");
+ return jsBoolean(booleanValue);
+}
+
+class JavaRuntimeMethod : public RuntimeMethod {
+public:
+ JavaRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
+ : RuntimeMethod(exec, globalObject, name, list)
+ {
+ }
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static const ClassInfo s_info;
+};
+
+const ClassInfo JavaRuntimeMethod::s_info = { "JavaRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };
+
+JSValue JavaInstance::getMethod(ExecState* exec, const Identifier& propertyName)
+{
+ MethodList methodList = getClass()->methodsNamed(propertyName, this);
+ return new (exec) JavaRuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue JavaInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
+{
+ if (!asObject(runtimeMethod)->inherits(&JavaRuntimeMethod::s_info))
+ return throwError(exec, createTypeError(exec, "Attempt to invoke non-Java method on Java object."));
+
+ const MethodList& methodList = *runtimeMethod->methods();
+
+ int i;
+ int count = exec->argumentCount();
+ 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't 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.
+ for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
+ Method* aMethod = methodList[methodIndex];
+ if (aMethod->numParameters() == count) {
+ method = aMethod;
+ break;
+ }
+ }
+ if (!method) {
+ LOG(LiveConnect, "JavaInstance::invokeMethod unable to find an appropiate method");
+ return jsUndefined();
+ }
+
+ const JavaMethod* jMethod = static_cast<const JavaMethod*>(method);
+ LOG(LiveConnect, "JavaInstance::invokeMethod call %s %s on %p", UString(jMethod->name()).utf8().data(), jMethod->signature(), m_instance->m_instance);
+
+ Vector<jvalue> jArgs(count);
+
+ for (i = 0; i < count; i++) {
+ JavaParameter* aParameter = jMethod->parameterAt(i);
+ jArgs[i] = convertValueToJValue(exec, m_rootObject.get(), exec->argument(i), aParameter->getJNIType(), aParameter->type());
+ LOG(LiveConnect, "JavaInstance::invokeMethod arg[%d] = %s", i, exec->argument(i).toString(exec).ascii().data());
+ }
+
+ jvalue result;
+
+ // Try to use the JNI abstraction first, otherwise fall back to
+ // normal 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 = m_instance->m_instance;
+ JSValue exceptionDescription;
+ const char *callingURL = 0; // FIXME, need to propagate calling URL to Java
+ handled = dispatchJNICall(exec, rootObject->nativeHandle(), obj, jMethod->isStatic(), jMethod->JNIReturnType(), jMethod->methodID(obj), jArgs.data(), result, callingURL, exceptionDescription);
+ if (exceptionDescription) {
+ throwError(exec, createError(exec, exceptionDescription.toString(exec)));
+ return jsUndefined();
+ }
+ }
+
+// This is a deprecated code path which should not be required on Android.
+// Remove this guard once Bug 39476 is fixed.
+#if PLATFORM(ANDROID) || defined(BUILDING_ON_TIGER)
+ if (!handled) {
+ jobject obj = m_instance->m_instance;
+ switch (jMethod->JNIReturnType()) {
+ case void_type:
+ callJNIMethodIDA<void>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case object_type:
+ result.l = callJNIMethodIDA<jobject>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case boolean_type:
+ result.z = callJNIMethodIDA<jboolean>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case byte_type:
+ result.b = callJNIMethodIDA<jbyte>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case char_type:
+ result.c = callJNIMethodIDA<jchar>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case short_type:
+ result.s = callJNIMethodIDA<jshort>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case int_type:
+ result.i = callJNIMethodIDA<jint>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case long_type:
+ result.j = callJNIMethodIDA<jlong>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case float_type:
+ result.f = callJNIMethodIDA<jfloat>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case double_type:
+ result.d = callJNIMethodIDA<jdouble>(obj, jMethod->methodID(obj), jArgs.data());
+ break;
+ case array_type:
+ case invalid_type:
+ break;
+ }
+ }
+#endif
+
+ switch (jMethod->JNIReturnType()) {
+ case void_type:
+ {
+ resultValue = jsUndefined();
+ }
+ break;
+
+ case object_type:
+ {
+ if (result.l) {
+ // FIXME: array_type return type is handled below, can we actually get an array here?
+ const char* arrayType = jMethod->returnType();
+ if (arrayType[0] == '[')
+ resultValue = JavaArray::convertJObjectToArray(exec, result.l, arrayType, rootObject);
+ else {
+ jobject classOfInstance = callJNIMethod<jobject>(result.l, "getClass", "()Ljava/lang/Class;");
+ jstring className = static_cast<jstring>(callJNIMethod<jobject>(classOfInstance, "getName", "()Ljava/lang/String;"));
+ if (!strcmp(JavaString(className).utf8(), "sun.plugin.javascript.webkit.JSObject")) {
+ // Pull the nativeJSObject value from the Java instance. This is a pointer to the JSObject.
+ JNIEnv* env = getJNIEnv();
+ jfieldID fieldID = env->GetFieldID(static_cast<jclass>(classOfInstance), "nativeJSObject", "J");
+ jlong nativeHandle = env->GetLongField(result.l, fieldID);
+ // FIXME: Handling of undefined values differs between functions in JNIUtilityPrivate.cpp and those in those in jni_jsobject.mm,
+ // and so it does between different versions of LiveConnect spec. There should not be multiple code paths to do the same work.
+ if (nativeHandle == 1 /* UndefinedHandle */)
+ return jsUndefined();
+ return static_cast<JSObject*>(jlong_to_ptr(nativeHandle));
+ } else
+ return JavaInstance::create(result.l, rootObject)->createRuntimeObject(exec);
+ }
+ } else
+ return 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 array_type:
+ {
+ const char* arrayType = jMethod->returnType();
+ ASSERT(arrayType[0] == '[');
+ resultValue = JavaArray::convertJObjectToArray(exec, result.l, arrayType, rootObject);
+ }
+ break;
+
+ case invalid_type:
+ {
+ resultValue = jsUndefined();
+ }
+ break;
+ }
+
+ return resultValue;
+}
+
+JSValue JavaInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ JavaClass* aClass = static_cast<JavaClass*>(getClass());
+ if (aClass->isStringClass())
+ return stringValue(exec);
+ if (aClass->isNumberClass())
+ return numberValue(exec);
+ if (aClass->isBooleanClass())
+ return booleanValue();
+ return valueOf(exec);
+}
+
+JSValue JavaInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+JObjectWrapper::JObjectWrapper(jobject instance)
+ : m_refCount(0)
+{
+ ASSERT(instance);
+
+ // Cache the JNIEnv used to get the global ref for this java instance.
+ // It'll be used to delete the reference.
+ m_env = getJNIEnv();
+
+ m_instance = m_env->NewGlobalRef(instance);
+
+ LOG(LiveConnect, "JObjectWrapper ctor new global ref %p for %p", m_instance, instance);
+
+ if (!m_instance)
+ LOG_ERROR("Could not get GlobalRef for %p", instance);
+}
+
+JObjectWrapper::~JObjectWrapper()
+{
+ LOG(LiveConnect, "JObjectWrapper dtor deleting global ref %p", m_instance);
+ m_env->DeleteGlobalRef(m_instance);
+}
+
+#endif // ENABLE(JAVA_BRIDGE)
diff --git a/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.h b/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.h
new file mode 100644
index 0000000..dbfcf75
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaInstanceJSC.h
@@ -0,0 +1,112 @@
+/*
+ * 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 JavaInstanceJSC_h
+#define JavaInstanceJSC_h
+
+#if ENABLE(JAVA_BRIDGE)
+
+#include "Bridge.h"
+#include "runtime_root.h"
+
+#include <JavaVM/jni.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaClass;
+
+class JObjectWrapper {
+friend class RefPtr<JObjectWrapper>;
+friend class JavaArray;
+friend class JavaField;
+friend class JavaInstance;
+friend class JavaMethod;
+
+public:
+ jobject instance() const { return m_instance; }
+ void setInstance(jobject instance) { m_instance = instance; }
+
+ void ref() { m_refCount++; }
+ void deref()
+ {
+ if (!(--m_refCount))
+ delete this;
+ }
+
+protected:
+ JObjectWrapper(jobject instance);
+ ~JObjectWrapper();
+
+ jobject m_instance;
+
+private:
+ JNIEnv* m_env;
+ unsigned int m_refCount;
+};
+
+class JavaInstance : public Instance {
+public:
+ static PassRefPtr<JavaInstance> create(jobject instance, PassRefPtr<RootObject> rootObject)
+ {
+ return adoptRef(new JavaInstance(instance, rootObject));
+ }
+
+ ~JavaInstance();
+
+ virtual Class* getClass() const;
+
+ virtual JSValue valueOf(ExecState*) const;
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName);
+ virtual JSValue invokeMethod(ExecState* exec, RuntimeMethod* method);
+
+ jobject javaInstance() const { return m_instance->m_instance; }
+
+ JSValue stringValue(ExecState*) const;
+ JSValue numberValue(ExecState*) const;
+ JSValue booleanValue() const;
+
+protected:
+ JavaInstance(jobject instance, PassRefPtr<RootObject>);
+
+ virtual RuntimeObject* newRuntimeObject(ExecState*);
+
+ virtual void virtualBegin();
+ virtual void virtualEnd();
+
+ RefPtr<JObjectWrapper> m_instance;
+ mutable JavaClass* m_class;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(JAVA_BRIDGE)
+
+#endif // JavaInstanceJSC_h
diff --git a/Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.cpp b/Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.cpp
new file mode 100644
index 0000000..6270f9f
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Apple 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 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 "JavaInstanceJSC.h"
+#include "JavaRuntimeObject.h"
+
+namespace JSC {
+namespace Bindings {
+
+const ClassInfo JavaRuntimeObject::s_info = { "JavaRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+JavaRuntimeObject::JavaRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<JavaInstance> instance)
+ : RuntimeObject(exec, globalObject, instance)
+{
+}
+
+JavaRuntimeObject::~JavaRuntimeObject()
+{
+}
+
+JavaInstance* JavaRuntimeObject::getInternalJavaInstance() const
+{
+ return static_cast<JavaInstance*>(getInternalInstance());
+}
+
+
+
+}
+}
diff --git a/Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.h b/Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.h
new file mode 100644
index 0000000..0e400f4
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaRuntimeObject.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Apple 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 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 JavaRuntimeObject_h
+#define JavaRuntimeObject_h
+
+#include "runtime_object.h"
+
+namespace JSC {
+namespace Bindings {
+
+class JavaInstance;
+
+class JavaRuntimeObject : public RuntimeObject {
+public:
+ JavaRuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<JavaInstance>);
+ virtual ~JavaRuntimeObject();
+
+ JavaInstance* getInternalJavaInstance() const;
+
+ static const ClassInfo s_info;
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+};
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/bridge/jni/jsc/JavaStringJSC.h b/Source/WebCore/bridge/jni/jsc/JavaStringJSC.h
new file mode 100644
index 0000000..cf575b2
--- /dev/null
+++ b/Source/WebCore/bridge/jni/jsc/JavaStringJSC.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JavaStringJSC_h
+#define JavaStringJSC_h
+
+#include "JNIUtility.h"
+#include "JavaInstanceJSC.h"
+#include <runtime/JSLock.h>
+
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaStringImpl {
+public:
+ ~JavaStringImpl()
+ {
+ JSLock lock(SilenceAssertionsOnly);
+ m_impl = 0;
+ }
+
+ void init()
+ {
+ JSLock lock(SilenceAssertionsOnly);
+ m_impl = UString().impl();
+ }
+
+ void init(JNIEnv* e, jstring s)
+ {
+ int size = e->GetStringLength(s);
+ const jchar* uc = getUCharactersFromJStringInEnv(e, s);
+ {
+ JSLock lock(SilenceAssertionsOnly);
+ m_impl = UString(reinterpret_cast<const UChar*>(uc), size).impl();
+ }
+ releaseUCharactersForJStringInEnv(e, s, uc);
+ }
+
+ const char* utf8() const
+ {
+ if (!m_utf8String.data()) {
+ JSLock lock(SilenceAssertionsOnly);
+ m_utf8String = UString(m_impl).utf8();
+ }
+ return m_utf8String.data();
+ }
+ const jchar* uchars() const { return (const jchar*)m_impl->characters(); }
+ int length() const { return m_impl->length(); }
+ UString uString() const { return UString(m_impl); }
+
+private:
+ RefPtr<StringImpl> m_impl;
+ mutable CString m_utf8String;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JavaStringJSC_h
diff --git a/Source/WebCore/bridge/jni/v8/JNIBridgeV8.cpp b/Source/WebCore/bridge/jni/v8/JNIBridgeV8.cpp
new file mode 100644
index 0000000..35775dc
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JNIBridgeV8.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JNIBridgeV8.h"
+
+using namespace JSC::Bindings;
+
+JavaField::JavaField(JNIEnv* env, jobject aField)
+{
+ // Get field type
+ jobject fieldType = callJNIMethod<jobject>(aField, "getType", "()Ljava/lang/Class;");
+ jstring fieldTypeName = static_cast<jstring>(callJNIMethod<jobject>(fieldType, "getName", "()Ljava/lang/String;"));
+ m_type = JavaString(env, fieldTypeName);
+ m_JNIType = JNITypeFromClassName(m_type.utf8());
+
+ // Get field name
+ jstring fieldName = static_cast<jstring>(callJNIMethod<jobject>(aField, "getName", "()Ljava/lang/String;"));
+ m_name = JavaString(env, fieldName);
+
+ m_field = new JObjectWrapper(aField);
+}
diff --git a/Source/WebCore/bridge/jni/v8/JNIBridgeV8.h b/Source/WebCore/bridge/jni/v8/JNIBridgeV8.h
new file mode 100644
index 0000000..46cbd56
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JNIBridgeV8.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JNIBridgeV8_h
+#define JNIBridgeV8_h
+
+#include "JNIBridge.h" // For JavaString
+#include "JavaInstanceV8.h" // For JObjectWrapper
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaField {
+public:
+ JavaField(JNIEnv*, jobject aField);
+
+ const JavaString& name() const { return m_name; }
+ const char* type() const { return m_type.utf8(); }
+
+ JNIType getJNIType() const { return m_JNIType; }
+
+private:
+ JavaString m_name;
+ JavaString m_type;
+ JNIType m_JNIType;
+ RefPtr<JObjectWrapper> m_field;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JNIBridgeV8_h
diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
new file mode 100644
index 0000000..f104e65
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JNIUtilityPrivate.h"
+
+#include "JavaInstanceV8.h"
+#include "JavaNPObjectV8.h"
+#include "npruntime_impl.h"
+
+namespace JSC {
+
+namespace Bindings {
+
+jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* javaClassName)
+{
+ jvalue result;
+ NPVariantType type = value.type;
+
+ switch (jniType) {
+ case array_type:
+ {
+ JNIEnv* env = getJNIEnv();
+ jobject javaArray;
+ NPObject* object = NPVARIANT_IS_OBJECT(value) ? NPVARIANT_TO_OBJECT(value) : 0;
+ NPVariant npvLength;
+ bool success = _NPN_GetProperty(0, object, _NPN_GetStringIdentifier("length"), &npvLength);
+ if (!success) {
+ // No length property so we don't know how many elements to put into the array.
+ // Treat this as an error.
+#ifdef EMULATE_JSC_BINDINGS
+ // JSC sends null for an array that is not an array of strings or basic types,
+ // do this also in the unknown length case.
+ memset(&result, 0, sizeof(jvalue));
+#else
+ // Sending NULL as JSC does seems dangerous. (Imagine the java method that asks
+ // for the length of the array it was passed). Here we send a 0 length array.
+ jclass objectClass = env->FindClass("java/lang/Object");
+ javaArray = env->NewObjectArray(0, objectClass, 0);
+ env->DeleteLocalRef(objectClass);
+#endif
+ break;
+ }
+
+ jsize length = 0;
+ if (NPVARIANT_IS_INT32(npvLength))
+ length = static_cast<jsize>(NPVARIANT_TO_INT32(npvLength));
+ else if (NPVARIANT_IS_DOUBLE(npvLength))
+ length = static_cast<jsize>(NPVARIANT_TO_DOUBLE(npvLength));
+
+ if (!strcmp(javaClassName, "[Ljava.lang.String;")) {
+ // Match JSC behavior by only allowing Object arrays if they are Strings.
+ jclass stringClass = env->FindClass("java/lang/String");
+ javaArray = env->NewObjectArray(length, stringClass, 0);
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if(NPVARIANT_IS_STRING(npvValue)) {
+ NPString str = NPVARIANT_TO_STRING(npvValue);
+ env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray), i, env->NewStringUTF(str.UTF8Characters));
+ }
+ }
+
+ env->DeleteLocalRef(stringClass);
+ } else if (!strcmp(javaClassName, "[B")) {
+ // array of bytes
+ javaArray = env->NewByteArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ jbyte bVal = 0;
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ bVal = static_cast<jbyte>(NPVARIANT_TO_INT32(npvValue));
+ } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ bVal = static_cast<jbyte>(NPVARIANT_TO_DOUBLE(npvValue));
+ }
+ env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray), i, 1, &bVal);
+ }
+ } else if (!strcmp(javaClassName, "[C")) {
+ // array of chars
+ javaArray = env->NewCharArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ jchar cVal = 0;
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ cVal = static_cast<jchar>(NPVARIANT_TO_INT32(npvValue));
+ } else if (NPVARIANT_IS_STRING(npvValue)) {
+ NPString str = NPVARIANT_TO_STRING(npvValue);
+ cVal = str.UTF8Characters[0];
+ }
+ env->SetCharArrayRegion(static_cast<jcharArray>(javaArray), i, 1, &cVal);
+ }
+ } else if (!strcmp(javaClassName, "[D")) {
+ // array of doubles
+ javaArray = env->NewDoubleArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ jdouble dVal = NPVARIANT_TO_DOUBLE(npvValue);
+ env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray), i, 1, &dVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[F")) {
+ // array of floats
+ javaArray = env->NewFloatArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ jfloat fVal = static_cast<jfloat>(NPVARIANT_TO_DOUBLE(npvValue));
+ env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray), i, 1, &fVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[I")) {
+ // array of ints
+ javaArray = env->NewIntArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ jint iVal = 0;
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ iVal = NPVARIANT_TO_INT32(npvValue);
+ } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ iVal = static_cast<jint>(NPVARIANT_TO_DOUBLE(npvValue));
+ }
+ env->SetIntArrayRegion(static_cast<jintArray>(javaArray), i, 1, &iVal);
+ }
+ } else if (!strcmp(javaClassName, "[J")) {
+ // array of longs
+ javaArray = env->NewLongArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ jlong jVal = 0;
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ jVal = static_cast<jlong>(NPVARIANT_TO_INT32(npvValue));
+ } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ jVal = static_cast<jlong>(NPVARIANT_TO_DOUBLE(npvValue));
+ }
+ env->SetLongArrayRegion(static_cast<jlongArray>(javaArray), i, 1, &jVal);
+ }
+ } else if (!strcmp(javaClassName, "[S")) {
+ // array of shorts
+ javaArray = env->NewShortArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ jshort sVal = 0;
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ sVal = static_cast<jshort>(NPVARIANT_TO_INT32(npvValue));
+ } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ sVal = static_cast<jshort>(NPVARIANT_TO_DOUBLE(npvValue));
+ }
+ env->SetShortArrayRegion(static_cast<jshortArray>(javaArray), i, 1, &sVal);
+ }
+ } else if (!strcmp(javaClassName, "[Z")) {
+ // array of booleans
+ javaArray = env->NewBooleanArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_BOOLEAN(npvValue)) {
+ jboolean zVal = NPVARIANT_TO_BOOLEAN(npvValue);
+ env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray), i, 1, &zVal);
+ }
+ }
+ } else {
+#ifdef EMULATE_JSC_BINDINGS
+ // JSC sends null for an array that is not an array of strings or basic types.
+ memset(&result, 0, sizeof(jvalue));
+ break;
+#else
+ // Sending NULL as JSC does seems dangerous. (Imagine the java method that asks
+ // for the length of the array it was passed). Here we send a 0 length array.
+ jclass objectClass = env->FindClass("java/lang/Object");
+ javaArray = env->NewObjectArray(0, objectClass, 0);
+ env->DeleteLocalRef(objectClass);
+#endif
+ }
+
+ result.l = javaArray;
+ }
+ break;
+
+ case object_type:
+ {
+ JNIEnv* env = getJNIEnv();
+ result.l = static_cast<jobject>(0);
+ jobject javaString;
+
+ // First see if we have a Java instance.
+ if (type == NPVariantType_Object) {
+ NPObject* objectImp = NPVARIANT_TO_OBJECT(value);
+ if (JavaInstance* instance = ExtractJavaInstance(objectImp))
+ result.l = instance->javaInstance();
+ }
+
+ // 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 && !strcmp(javaClassName, "java.lang.String")) {
+#ifdef CONVERT_NULL_TO_EMPTY_STRING
+ if (type == NPVariantType_Null) {
+ jchar buf[2];
+ jobject javaString = env->functions->NewString(env, buf, 0);
+ result.l = javaString;
+ } else
+#else
+ if (type == NPVariantType_String)
+#endif
+ {
+ NPString src = NPVARIANT_TO_STRING(value);
+ javaString = env->NewStringUTF(src.UTF8Characters);
+ result.l = javaString;
+ } else if (type == NPVariantType_Int32) {
+ jint src = NPVARIANT_TO_INT32(value);
+ jclass integerClass = env->FindClass("java/lang/Integer");
+ jmethodID toString = env->GetStaticMethodID(integerClass, "toString", "(I)Ljava/lang/String;");
+ javaString = env->CallStaticObjectMethod(integerClass, toString, src);
+ result.l = javaString;
+ env->DeleteLocalRef(integerClass);
+ } else if (type == NPVariantType_Bool) {
+ jboolean src = NPVARIANT_TO_BOOLEAN(value);
+ jclass booleanClass = env->FindClass("java/lang/Boolean");
+ jmethodID toString = env->GetStaticMethodID(booleanClass, "toString", "(Z)Ljava/lang/String;");
+ javaString = env->CallStaticObjectMethod(booleanClass, toString, src);
+ result.l = javaString;
+ env->DeleteLocalRef(booleanClass);
+ } else if (type == NPVariantType_Double) {
+ jdouble src = NPVARIANT_TO_DOUBLE(value);
+ jclass doubleClass = env->FindClass("java/lang/Double");
+ jmethodID toString = env->GetStaticMethodID(doubleClass, "toString", "(D)Ljava/lang/String;");
+ javaString = env->CallStaticObjectMethod(doubleClass, toString, src);
+ result.l = javaString;
+ env->DeleteLocalRef(doubleClass);
+ }
+#ifdef EMULATE_JSC_BINDINGS
+ // For the undefined value, JSC sends the String "undefined". Feels to me like we
+ // should send null in this case.
+ else if (!NPVARIANT_IS_NULL(value)) {
+ javaString = env->NewStringUTF("undefined");
+ result.l = javaString;
+ }
+#endif
+ } else if (!result.l)
+ memset(&result, 0, sizeof(jvalue)); // Handle it the same as a void case
+ }
+ break;
+
+ case boolean_type:
+ {
+ if (type == NPVariantType_Bool)
+ result.z = NPVARIANT_TO_BOOLEAN(value);
+ else
+ memset(&result, 0, sizeof(jvalue)); // as void case
+ }
+ break;
+
+ case byte_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.b = static_cast<jbyte>(NPVARIANT_TO_INT32(value));
+ else if (type == NPVariantType_Double)
+ result.b = static_cast<jbyte>(NPVARIANT_TO_DOUBLE(value));
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case char_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.c = static_cast<char>(NPVARIANT_TO_INT32(value));
+#ifndef EMULATE_JSC_BINDINGS
+ // There is no char type in JavaScript - just strings 1 character
+ // long. So just converting it to an int above doesn't work. Again,
+ // we emulate the behavior for now for maximum compatability.
+ else if (type == NPVariantType_String) {
+ NPString str = NPVARIANT_TO_STRING(value);
+ result.c = str.UTF8Characters[0];
+ }
+#endif
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case short_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.s = static_cast<jshort>(NPVARIANT_TO_INT32(value));
+ else if (type == NPVariantType_Double)
+ result.s = static_cast<jshort>(NPVARIANT_TO_DOUBLE(value));
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case int_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.i = static_cast<jint>(NPVARIANT_TO_INT32(value));
+ else if (type == NPVariantType_Double)
+ result.i = static_cast<jint>(NPVARIANT_TO_DOUBLE(value));
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case long_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.j = static_cast<jlong>(NPVARIANT_TO_INT32(value));
+ else if (type == NPVariantType_Double)
+ result.j = static_cast<jlong>(NPVARIANT_TO_DOUBLE(value));
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case float_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.f = static_cast<jfloat>(NPVARIANT_TO_INT32(value));
+ else if (type == NPVariantType_Double)
+ result.f = static_cast<jfloat>(NPVARIANT_TO_DOUBLE(value));
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case double_type:
+ {
+ if (type == NPVariantType_Int32)
+ result.d = static_cast<jdouble>(NPVARIANT_TO_INT32(value));
+ else if (type == NPVariantType_Double)
+ result.d = static_cast<jdouble>(NPVARIANT_TO_DOUBLE(value));
+ else
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+
+ case invalid_type:
+ default:
+ case void_type:
+ {
+ memset(&result, 0, sizeof(jvalue));
+ }
+ break;
+ }
+ return result;
+}
+
+
+void convertJValueToNPVariant(jvalue value, JNIType jniType, const char* javaTypeName, NPVariant* result)
+{
+ switch (jniType) {
+ case void_type:
+ {
+ VOID_TO_NPVARIANT(*result);
+ }
+ break;
+
+ case object_type:
+ {
+ if (value.l) {
+ if (!strcmp(javaTypeName, "java.lang.String")) {
+ const char* v = getCharactersFromJString(static_cast<jstring>(value.l));
+ // s is freed in NPN_ReleaseVariantValue (see npruntime.cpp)
+ const char* s = strdup(v);
+ releaseCharactersForJString(static_cast<jstring>(value.l), v);
+ STRINGZ_TO_NPVARIANT(s, *result);
+ } else
+ OBJECT_TO_NPVARIANT(JavaInstanceToNPObject(new JavaInstance(value.l)), *result);
+ } else
+ VOID_TO_NPVARIANT(*result);
+ }
+ break;
+
+ case boolean_type:
+ {
+ BOOLEAN_TO_NPVARIANT(value.z, *result);
+ }
+ break;
+
+ case byte_type:
+ {
+ INT32_TO_NPVARIANT(value.b, *result);
+ }
+ break;
+
+ case char_type:
+ {
+#ifndef EMULATE_JSC_BINDINGS
+ // There is no char type in JavaScript - just strings 1 character
+ // long. So just converting it to an int above doesn't work. Again,
+ // we emulate the behavior for now for maximum compatability.
+ if (!strcmp(javaTypeName, "char")) {
+ const char c = value.c;
+ const char* v = strndup(&c, 1);
+ STRINGZ_TO_NPVARIANT(v, *result);
+ } else
+#endif
+ INT32_TO_NPVARIANT(value.c, *result);
+ }
+ break;
+
+ case short_type:
+ {
+ INT32_TO_NPVARIANT(value.s, *result);
+ }
+ break;
+
+ case int_type:
+ {
+ INT32_TO_NPVARIANT(value.i, *result);
+ }
+ break;
+
+ // TODO: Check if cast to double is needed.
+ case long_type:
+ {
+ DOUBLE_TO_NPVARIANT(value.j, *result);
+ }
+ break;
+
+ case float_type:
+ {
+ DOUBLE_TO_NPVARIANT(value.f, *result);
+ }
+ break;
+
+ case double_type:
+ {
+ DOUBLE_TO_NPVARIANT(value.d, *result);
+ }
+ break;
+
+ case invalid_type:
+ default:
+ {
+ VOID_TO_NPVARIANT(*result);
+ }
+ break;
+ }
+}
+
+} // end of namespace Bindings
+
+} // end of namespace JSC
diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
new file mode 100644
index 0000000..da7a24c
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JNIUtilityPrivate_h
+#define JNIUtilityPrivate_h
+
+#include "JNIUtility.h"
+#include "npruntime.h"
+
+// FIXME: While fully implementing the bindings I noticed some differences between what
+// I wrote and seemed intuitive and what JSC does. Need to verify if my intuition is wrong
+// or there are bugs in the JSC bindings. For now, this macro makes the V8 bindings do the
+// same as the JSC bindings.
+#define EMULATE_JSC_BINDINGS 1
+
+namespace JSC {
+
+namespace Bindings {
+
+jvalue convertNPVariantToJValue(NPVariant, JNIType, const char* javaClassName);
+void convertJValueToNPVariant(jvalue, JNIType, const char* javaClassName, NPVariant*);
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JNIUtilityPrivate_h
diff --git a/Source/WebCore/bridge/jni/v8/JavaClassV8.cpp b/Source/WebCore/bridge/jni/v8/JavaClassV8.cpp
new file mode 100644
index 0000000..1d381af
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaClassV8.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JavaClassV8.h"
+
+using namespace JSC::Bindings;
+
+JavaClass::JavaClass(jobject anInstance)
+{
+ jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;");
+
+ if (!aClass) {
+ fprintf(stderr, "%s: unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance);
+ return;
+ }
+
+ int i;
+ JNIEnv* env = getJNIEnv();
+
+ // Get the fields
+ jarray fields = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;"));
+ int numFields = env->GetArrayLength(fields);
+ for (i = 0; i < numFields; i++) {
+ jobject aJField = env->GetObjectArrayElement(static_cast<jobjectArray>(fields), i);
+ JavaField* aField = new JavaField(env, aJField); // deleted in the JavaClass destructor
+ {
+ m_fields.set(aField->name().utf8(), aField);
+ }
+ env->DeleteLocalRef(aJField);
+ }
+
+ // Get the methods
+ jarray methods = static_cast<jarray>(callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;"));
+ int numMethods = env->GetArrayLength(methods);
+ for (i = 0; i < numMethods; i++) {
+ jobject aJMethod = env->GetObjectArrayElement(static_cast<jobjectArray>(methods), i);
+ JavaMethod* aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor
+ MethodList* methodList;
+ {
+ methodList = m_methods.get(aMethod->name().utf8());
+ if (!methodList) {
+ methodList = new MethodList();
+ m_methods.set(aMethod->name().utf8(), methodList);
+ }
+ }
+ methodList->append(aMethod);
+ env->DeleteLocalRef(aJMethod);
+ }
+ env->DeleteLocalRef(fields);
+ env->DeleteLocalRef(methods);
+ env->DeleteLocalRef(aClass);
+}
+
+JavaClass::~JavaClass()
+{
+ deleteAllValues(m_fields);
+ m_fields.clear();
+
+ MethodListMap::const_iterator end = m_methods.end();
+ for (MethodListMap::const_iterator it = m_methods.begin(); it != end; ++it) {
+ const MethodList* methodList = it->second;
+ deleteAllValues(*methodList);
+ delete methodList;
+ }
+ m_methods.clear();
+}
+
+MethodList JavaClass::methodsNamed(const char* name) const
+{
+ MethodList* methodList = m_methods.get(name);
+
+ if (methodList)
+ return *methodList;
+ return MethodList();
+}
+
+JavaField* JavaClass::fieldNamed(const char* name) const
+{
+ return m_fields.get(name);
+}
diff --git a/Source/WebCore/bridge/jni/v8/JavaClassV8.h b/Source/WebCore/bridge/jni/v8/JavaClassV8.h
new file mode 100644
index 0000000..99137f1
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaClassV8.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JavaClassV8_h
+#define JavaClassV8_h
+
+#include "JNIBridgeV8.h"
+#include "PlatformString.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+typedef Vector<JavaMethod*> MethodList;
+typedef HashMap<WTF::String, MethodList*> MethodListMap;
+typedef HashMap<WTF::String, JavaField*> FieldMap;
+
+class JavaClass {
+public:
+ JavaClass(jobject anInstance);
+ ~JavaClass();
+
+ MethodList methodsNamed(const char* name) const;
+ JavaField* fieldNamed(const char* name) const;
+
+private:
+ MethodListMap m_methods;
+ FieldMap m_fields;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JavaClassV8_h
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceV8.cpp b/Source/WebCore/bridge/jni/v8/JavaInstanceV8.cpp
new file mode 100644
index 0000000..27adca3
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceV8.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2003, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JavaInstanceV8.h"
+
+#include "JNIBridge.h"
+#include "JNIUtilityPrivate.h"
+#include "JavaClassV8.h"
+
+#include <assert.h>
+
+using namespace JSC::Bindings;
+
+JavaInstance::JavaInstance(jobject instance)
+{
+ m_instance = new JObjectWrapper(instance);
+ m_class = 0;
+}
+
+JavaInstance::~JavaInstance()
+{
+ m_instance = 0;
+ delete m_class;
+}
+
+#define NUM_LOCAL_REFS 64
+
+void JavaInstance::virtualBegin()
+{
+ getJNIEnv()->PushLocalFrame(NUM_LOCAL_REFS);
+}
+
+void JavaInstance::virtualEnd()
+{
+ getJNIEnv()->PopLocalFrame(0);
+}
+
+JavaClass* JavaInstance::getClass() const
+{
+ if (!m_class)
+ m_class = new JavaClass(javaInstance());
+ return m_class;
+}
+
+bool JavaInstance::invokeMethod(const char* methodName, const NPVariant* args, int count, NPVariant* resultValue)
+{
+ VOID_TO_NPVARIANT(*resultValue);
+
+ MethodList methodList = getClass()->methodsNamed(methodName);
+
+ size_t numMethods = methodList.size();
+
+ // Try to find a good match for the overloaded method. The
+ // fundamental problem is that JavaScript doesn't 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.
+ JavaMethod* aMethod;
+ JavaMethod* method = 0;
+ for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
+ aMethod = methodList[methodIndex];
+ if (aMethod->numParameters() == count) {
+ method = aMethod;
+ break;
+ }
+ }
+ if (!method)
+ return false;
+
+ const JavaMethod* jMethod = static_cast<const JavaMethod*>(method);
+
+ jvalue* jArgs = 0;
+ if (count > 0)
+ jArgs = static_cast<jvalue*>(malloc(count * sizeof(jvalue)));
+
+ for (int i = 0; i < count; i++) {
+ JavaParameter* aParameter = jMethod->parameterAt(i);
+ jArgs[i] = convertNPVariantToJValue(args[i], aParameter->getJNIType(), aParameter->type());
+ }
+
+ jvalue result;
+
+ // 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.
+ {
+ jobject obj = javaInstance();
+ switch (jMethod->JNIReturnType()) {
+ case void_type:
+ callJNIMethodIDA<void>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case object_type:
+ result.l = callJNIMethodIDA<jobject>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case boolean_type:
+ result.z = callJNIMethodIDA<jboolean>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case byte_type:
+ result.b = callJNIMethodIDA<jbyte>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case char_type:
+ result.c = callJNIMethodIDA<jchar>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case short_type:
+ result.s = callJNIMethodIDA<jshort>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case int_type:
+ result.i = callJNIMethodIDA<jint>(obj, jMethod->methodID(obj), jArgs);
+ break;
+
+ case long_type:
+ result.j = callJNIMethodIDA<jlong>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case float_type:
+ result.f = callJNIMethodIDA<jfloat>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case double_type:
+ result.d = callJNIMethodIDA<jdouble>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case invalid_type:
+ default:
+ break;
+ }
+ }
+
+ convertJValueToNPVariant(result, jMethod->JNIReturnType(), jMethod->returnType(), resultValue);
+ free(jArgs);
+
+ return true;
+}
+
+JObjectWrapper::JObjectWrapper(jobject instance)
+ : m_refCount(0)
+{
+ assert(instance);
+
+ // Cache the JNIEnv used to get the global ref for this java instanace.
+ // It'll be used to delete the reference.
+ m_env = getJNIEnv();
+
+ m_instance = m_env->NewGlobalRef(instance);
+
+ if (!m_instance)
+ fprintf(stderr, "%s: could not get GlobalRef for %p\n", __PRETTY_FUNCTION__, instance);
+}
+
+JObjectWrapper::~JObjectWrapper()
+{
+ m_env->DeleteGlobalRef(m_instance);
+}
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h b/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h
new file mode 100644
index 0000000..4f009a5
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2003, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JavaInstanceV8_h
+#define JavaInstanceV8_h
+
+#include "npruntime.h"
+
+#include <JavaVM/jni.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaClass;
+
+class JObjectWrapper {
+friend class RefPtr<JObjectWrapper>;
+friend class JavaField;
+friend class JavaInstance;
+
+public:
+ jobject instance() const { return m_instance; }
+ void setInstance(jobject instance) { m_instance = instance; }
+
+ void ref() { m_refCount++; }
+ void deref()
+ {
+ if (!(--m_refCount))
+ delete this;
+ }
+
+protected:
+ JObjectWrapper(jobject);
+ ~JObjectWrapper();
+
+ jobject m_instance;
+
+private:
+ JNIEnv* m_env;
+ unsigned int m_refCount;
+};
+
+class JavaInstance : public RefCounted<JavaInstance> {
+public:
+ JavaInstance(jobject instance);
+ virtual ~JavaInstance();
+
+ JavaClass* getClass() const;
+
+ bool invokeMethod(const char* name, const NPVariant* args, int argsCount, NPVariant* result);
+
+ jobject javaInstance() const { return m_instance->m_instance; }
+
+ // These functions are called before and after the main entry points into
+ // the native implementations. They can be used to establish and cleanup
+ // any needed state.
+ void begin() { virtualBegin(); }
+ void end() { virtualEnd(); }
+
+protected:
+ RefPtr<JObjectWrapper> m_instance;
+ mutable JavaClass* m_class;
+
+ virtual void virtualBegin();
+ virtual void virtualEnd();
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JavaInstanceV8_h
diff --git a/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
new file mode 100644
index 0000000..3bb8e27
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 "JavaNPObjectV8.h"
+
+#include "JNIUtilityPrivate.h"
+#include "JavaClassV8.h"
+#include "JavaInstanceV8.h"
+#include "npruntime_impl.h"
+
+namespace JSC {
+
+namespace Bindings {
+
+static NPObject* AllocJavaNPObject(NPP, NPClass*)
+{
+ JavaNPObject* obj = static_cast<JavaNPObject*>(malloc(sizeof(JavaNPObject)));
+ if (!obj)
+ return 0;
+ memset(obj, 0, sizeof(JavaNPObject));
+ return reinterpret_cast<NPObject*>(obj);
+}
+
+static void FreeJavaNPObject(NPObject* npobj)
+{
+ JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(npobj);
+ obj->m_instance = 0; // free does not call the destructor
+ free(obj);
+}
+
+static NPClass JavaNPObjectClass = {
+ NP_CLASS_STRUCT_VERSION,
+ AllocJavaNPObject, // allocate,
+ FreeJavaNPObject, // free,
+ 0, // invalidate
+ JavaNPObjectHasMethod,
+ JavaNPObjectInvoke,
+ 0, // invokeDefault,
+ JavaNPObjectHasProperty,
+ JavaNPObjectGetProperty,
+ 0, // setProperty
+ 0, // removeProperty
+ 0, // enumerate
+ 0 // construct
+};
+
+NPObject* JavaInstanceToNPObject(JavaInstance* instance)
+{
+ JavaNPObject* object = reinterpret_cast<JavaNPObject*>(_NPN_CreateObject(0, &JavaNPObjectClass));
+ object->m_instance = instance;
+ return reinterpret_cast<NPObject*>(object);
+}
+
+// Returns null if obj is not a wrapper of JavaInstance
+JavaInstance* ExtractJavaInstance(NPObject* obj)
+{
+ if (obj->_class == &JavaNPObjectClass)
+ return reinterpret_cast<JavaNPObject*>(obj)->m_instance.get();
+ return 0;
+}
+
+bool JavaNPObjectHasMethod(NPObject* obj, NPIdentifier identifier)
+{
+ JavaInstance* instance = ExtractJavaInstance(obj);
+ if (!instance)
+ return false;
+ NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
+ if (!name)
+ return false;
+
+ instance->begin();
+ bool result = (instance->getClass()->methodsNamed(name).size() > 0);
+ instance->end();
+
+ // TODO: use NPN_MemFree
+ free(name);
+
+ return result;
+}
+
+bool JavaNPObjectInvoke(NPObject* obj, NPIdentifier identifier, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ JavaInstance* instance = ExtractJavaInstance(obj);
+ if (!instance)
+ return false;
+ NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
+ if (!name)
+ return false;
+
+ instance->begin();
+ bool r = instance->invokeMethod(name, args, argCount, result);
+ instance->end();
+
+ // TODO: use NPN_MemFree
+ free(name);
+ return r;
+}
+
+bool JavaNPObjectHasProperty(NPObject* obj, NPIdentifier identifier)
+{
+ JavaInstance* instance = ExtractJavaInstance(obj);
+ if (!instance)
+ return false;
+ NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
+ if (!name)
+ return false;
+ instance->begin();
+ bool result = instance->getClass()->fieldNamed(name);
+ instance->end();
+ free(name);
+ return result;
+}
+
+bool JavaNPObjectGetProperty(NPObject* obj, NPIdentifier identifier, NPVariant* result)
+{
+ VOID_TO_NPVARIANT(*result);
+ JavaInstance* instance = ExtractJavaInstance(obj);
+ if (!instance)
+ return false;
+ NPUTF8* name = _NPN_UTF8FromIdentifier(identifier);
+ if (!name)
+ return false;
+
+ instance->begin();
+ JavaField* field = instance->getClass()->fieldNamed(name);
+ instance->end();
+ free(name); // TODO: use NPN_MemFree
+
+ if (!field)
+ return false;
+
+#ifdef EMULATE_JSC_BINDINGS
+ // JSC does not seem to support returning object properties so we emulate that
+ // behaviour here.
+ jvalue value;
+#else
+ // FIXME: Note here that field->type() refers to the Java class name and NOT the
+ // JNI signature i.e. "int" as opposed to "I". This means that the field lookup
+ // will fail.
+ jvalue value = getJNIField(instance->javaInstance(),
+ field->getJNIType(),
+ field->name().utf8(),
+ field->type());
+#endif
+ convertJValueToNPVariant(value, field->getJNIType(), field->type(), result);
+
+ return true;
+}
+
+} // namespace Bindings
+
+} // namespace JSC
diff --git a/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.h b/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.h
new file mode 100644
index 0000000..31b0ac7
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JavaNPObjectV8_h
+#define JavaNPObjectV8_h
+
+#include "npruntime.h"
+#include <wtf/RefPtr.h>
+
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaInstance;
+
+struct JavaNPObject {
+ NPObject m_object;
+ RefPtr<JavaInstance> m_instance;
+};
+
+NPObject* JavaInstanceToNPObject(JavaInstance*);
+JavaInstance* ExtractJavaInstance(NPObject*);
+
+bool JavaNPObjectHasMethod(NPObject*, NPIdentifier name);
+bool JavaNPObjectInvoke(NPObject*, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result);
+bool JavaNPObjectHasProperty(NPObject*, NPIdentifier name);
+bool JavaNPObjectGetProperty(NPObject*, NPIdentifier name, NPVariant* result);
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JavaNPObjectV8_h
diff --git a/Source/WebCore/bridge/jni/v8/JavaStringV8.h b/Source/WebCore/bridge/jni/v8/JavaStringV8.h
new file mode 100644
index 0000000..827d9f5
--- /dev/null
+++ b/Source/WebCore/bridge/jni/v8/JavaStringV8.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 JavaStringV8_h
+#define JavaStringV8_h
+
+#include "JNIUtility.h"
+#include <wtf/text/CString.h>
+
+
+namespace JSC {
+
+namespace Bindings {
+
+class JavaStringImpl {
+public:
+ void init() {}
+
+ void init(JNIEnv* e, jstring s)
+ {
+ int size = e->GetStringLength(s);
+ const char* cs = getCharactersFromJStringInEnv(e, s);
+ m_utf8String = WTF::CString(cs, size);
+ releaseCharactersForJStringInEnv(e, s, cs);
+ }
+
+ const char* utf8() const { return m_utf8String.data(); }
+ const jchar* uchars() const { return 0; } // Not implemented
+ int length() const { return m_utf8String.length(); }
+
+private:
+ WTF::CString m_utf8String;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // JavaStringV8_h
diff --git a/Source/WebCore/bridge/jsc/BridgeJSC.cpp b/Source/WebCore/bridge/jsc/BridgeJSC.cpp
new file mode 100644
index 0000000..49ffb2a
--- /dev/null
+++ b/Source/WebCore/bridge/jsc/BridgeJSC.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 "BridgeJSC.h"
+
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <runtime/JSLock.h>
+
+#if PLATFORM(QT)
+#include "qt_instance.h"
+#endif
+
+namespace JSC {
+
+namespace Bindings {
+
+Array::Array(PassRefPtr<RootObject> rootObject)
+ : m_rootObject(rootObject)
+{
+ ASSERT(m_rootObject);
+}
+
+Array::~Array()
+{
+}
+
+Instance::Instance(PassRefPtr<RootObject> rootObject)
+ : m_rootObject(rootObject)
+{
+ ASSERT(m_rootObject);
+}
+
+Instance::~Instance()
+{
+ ASSERT(!m_runtimeObject);
+ ASSERT(!m_runtimeObject.hasDeadObject());
+}
+
+static KJSDidExecuteFunctionPtr s_didExecuteFunction;
+
+void Instance::setDidExecuteFunction(KJSDidExecuteFunctionPtr func)
+{
+ s_didExecuteFunction = func;
+}
+
+KJSDidExecuteFunctionPtr Instance::didExecuteFunction()
+{
+ return s_didExecuteFunction;
+}
+
+void Instance::begin()
+{
+ virtualBegin();
+}
+
+void Instance::end()
+{
+ virtualEnd();
+}
+
+JSObject* Instance::createRuntimeObject(ExecState* exec)
+{
+ ASSERT(m_rootObject);
+ ASSERT(m_rootObject->isValid());
+ if (RuntimeObject* existingObject = m_runtimeObject.get())
+ return existingObject;
+
+ JSLock lock(SilenceAssertionsOnly);
+ RuntimeObject* newObject = newRuntimeObject(exec);
+ m_runtimeObject = newObject;
+ m_rootObject->addRuntimeObject(newObject);
+ return newObject;
+}
+
+RuntimeObject* Instance::newRuntimeObject(ExecState* exec)
+{
+ JSLock lock(SilenceAssertionsOnly);
+ return new (exec)RuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+void Instance::willDestroyRuntimeObject(RuntimeObject* object)
+{
+ ASSERT(m_rootObject);
+ ASSERT(m_rootObject->isValid());
+ m_rootObject->removeRuntimeObject(object);
+ m_runtimeObject.clear(object);
+}
+
+void Instance::willInvalidateRuntimeObject(RuntimeObject* object)
+{
+ ASSERT(object);
+ m_runtimeObject.clear(object);
+}
+
+RootObject* Instance::rootObject() const
+{
+ return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
+}
+
+} // namespace Bindings
+
+} // namespace JSC
diff --git a/Source/WebCore/bridge/jsc/BridgeJSC.h b/Source/WebCore/bridge/jsc/BridgeJSC.h
new file mode 100644
index 0000000..96974d9
--- /dev/null
+++ b/Source/WebCore/bridge/jsc/BridgeJSC.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright 2010, The Android Open Source Project
+ *
+ * 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 BridgeJSC_h
+#define BridgeJSC_h
+
+#if USE(JSC)
+
+#include <runtime/JSString.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class ArgList;
+class Identifier;
+class JSGlobalObject;
+class PropertyNameArray;
+class RuntimeMethod;
+
+namespace Bindings {
+
+class Instance;
+class Method;
+class RootObject;
+class RuntimeObject;
+
+typedef Vector<Method*> MethodList;
+
+class Field {
+public:
+ virtual JSValue valueFromInstance(ExecState*, const Instance*) const = 0;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const = 0;
+
+ virtual ~Field() { }
+};
+
+class Class : public Noncopyable {
+public:
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const = 0;
+ virtual Field* fieldNamed(const Identifier&, Instance*) const = 0;
+ virtual JSValue fallbackObject(ExecState*, Instance*, const Identifier&) { return jsUndefined(); }
+
+ virtual ~Class() { }
+};
+
+typedef void (*KJSDidExecuteFunctionPtr)(ExecState*, JSObject* rootObject);
+
+class Instance : public RefCounted<Instance> {
+public:
+ Instance(PassRefPtr<RootObject>);
+
+ static void setDidExecuteFunction(KJSDidExecuteFunctionPtr func);
+ static KJSDidExecuteFunctionPtr didExecuteFunction();
+
+ // These functions are called before and after the main entry points into
+ // the native implementations. They can be used to establish and cleanup
+ // any needed state.
+ void begin();
+ void end();
+
+ virtual Class* getClass() const = 0;
+ JSObject* createRuntimeObject(ExecState*);
+ void willInvalidateRuntimeObject(RuntimeObject*);
+ void willDestroyRuntimeObject(RuntimeObject*);
+
+ // Returns false if the value was not set successfully.
+ virtual bool setValueOfUndefinedField(ExecState*, const Identifier&, JSValue) { return false; }
+
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName) = 0;
+ virtual JSValue invokeMethod(ExecState*, RuntimeMethod* method) = 0;
+
+ virtual bool supportsInvokeDefaultMethod() const { return false; }
+ virtual JSValue invokeDefaultMethod(ExecState*) { return jsUndefined(); }
+
+ virtual bool supportsConstruct() const { return false; }
+ virtual JSValue invokeConstruct(ExecState*, const ArgList&) { return JSValue(); }
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&) { }
+
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const = 0;
+
+ virtual JSValue valueOf(ExecState* exec) const = 0;
+
+ RootObject* rootObject() const;
+
+ virtual ~Instance();
+
+ virtual bool getOwnPropertySlot(JSObject*, ExecState*, const Identifier&, PropertySlot&) { return false; }
+ virtual bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&) { return false; }
+ virtual void put(JSObject*, ExecState*, const Identifier&, JSValue, PutPropertySlot&) { }
+
+protected:
+ virtual void virtualBegin() { }
+ virtual void virtualEnd() { }
+ virtual RuntimeObject* newRuntimeObject(ExecState*);
+
+ RefPtr<RootObject> m_rootObject;
+
+private:
+ WeakGCPtr<RuntimeObject> m_runtimeObject;
+};
+
+class Array : public Noncopyable {
+public:
+ Array(PassRefPtr<RootObject>);
+ virtual ~Array();
+
+ virtual void setValueAt(ExecState*, unsigned index, JSValue) const = 0;
+ virtual JSValue valueAt(ExecState*, unsigned index) const = 0;
+ virtual unsigned int getLength() const = 0;
+
+protected:
+ RefPtr<RootObject> m_rootObject;
+};
+
+const char* signatureForParameters(const ArgList&);
+
+typedef HashMap<RefPtr<StringImpl>, MethodList*> MethodListMap;
+typedef HashMap<RefPtr<StringImpl>, Method*> MethodMap;
+typedef HashMap<RefPtr<StringImpl>, Field*> FieldMap;
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // USE(JSC)
+
+#endif
diff --git a/Source/WebCore/bridge/make_testbindings b/Source/WebCore/bridge/make_testbindings
new file mode 100755
index 0000000..1f528fe
--- /dev/null
+++ b/Source/WebCore/bridge/make_testbindings
@@ -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/Source/WebCore/bridge/npapi.h b/Source/WebCore/bridge/npapi.h
new file mode 100644
index 0000000..48e78c0
--- /dev/null
+++ b/Source/WebCore/bridge/npapi.h
@@ -0,0 +1,897 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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 ***** */
+
+#ifndef npapi_h_
+#define npapi_h_
+
+#if defined(__OS2__)
+#pragma pack(1)
+#endif
+
+#include "nptypes.h"
+
+#if defined(__OS2__) || defined(OS2)
+#ifndef XP_OS2
+#define XP_OS2 1
+#endif
+#endif
+
+#ifdef INCLUDE_JAVA
+#include "jri.h" /* Java Runtime Interface */
+#else
+#define jref void *
+#define JRIEnv void
+#endif
+
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+#include <windows.h>
+#ifndef XP_WIN
+#define XP_WIN 1
+#endif
+#endif
+
+#if defined(__SYMBIAN32__)
+#ifndef XP_SYMBIAN
+#define XP_SYMBIAN 1
+#endif
+#endif
+
+#if defined(__APPLE_CC__) && !defined(XP_UNIX)
+#ifndef XP_MACOSX
+#define XP_MACOSX 1
+#endif
+#endif
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#define NP_NO_QUICKDRAW
+#define NP_NO_CARBON
+#endif
+
+#if defined(XP_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#include <OpenGL/OpenGL.h>
+#ifndef NP_NO_CARBON
+#include <Carbon/Carbon.h>
+#endif
+#endif
+
+#if defined(XP_UNIX)
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#endif
+
+#if defined(XP_SYMBIAN)
+#include <QEvent>
+#include <QRegion>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Plugin Version Constants */
+/*----------------------------------------------------------------------*/
+
+#define NP_VERSION_MAJOR 0
+#define NP_VERSION_MINOR 24
+
+
+/* The OS/2 version of Netscape uses RC_DATA to define the
+ mime types, file extensions, etc that are required.
+ Use a vertical bar to separate types, end types with \0.
+ FileVersion and ProductVersion are 32bit ints, all other
+ entries are strings that MUST be terminated with a \0.
+
+AN EXAMPLE:
+
+RCDATA NP_INFO_ProductVersion { 1,0,0,1,}
+
+RCDATA NP_INFO_MIMEType { "video/x-video|",
+ "video/x-flick\0" }
+RCDATA NP_INFO_FileExtents { "avi|",
+ "flc\0" }
+RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|",
+ "MMOS2 Flc/Fli player(*.flc)\0" }
+
+RCDATA NP_INFO_FileVersion { 1,0,0,1 }
+RCDATA NP_INFO_CompanyName { "Netscape Communications\0" }
+RCDATA NP_INFO_FileDescription { "NPAVI32 Extension DLL\0"
+RCDATA NP_INFO_InternalName { "NPAVI32\0" )
+RCDATA NP_INFO_LegalCopyright { "Copyright Netscape Communications \251 1996\0"
+RCDATA NP_INFO_OriginalFilename { "NVAPI32.DLL" }
+RCDATA NP_INFO_ProductName { "NPAVI32 Dynamic Link Library\0" }
+*/
+/* RC_DATA types for version info - required */
+#define NP_INFO_ProductVersion 1
+#define NP_INFO_MIMEType 2
+#define NP_INFO_FileOpenName 3
+#define NP_INFO_FileExtents 4
+/* RC_DATA types for version info - used if found */
+#define NP_INFO_FileDescription 5
+#define NP_INFO_ProductName 6
+/* RC_DATA types for version info - optional */
+#define NP_INFO_CompanyName 7
+#define NP_INFO_FileVersion 8
+#define NP_INFO_InternalName 9
+#define NP_INFO_LegalCopyright 10
+#define NP_INFO_OriginalFilename 11
+
+#ifndef RC_INVOKED
+
+/*----------------------------------------------------------------------*/
+/* Definition of Basic Types */
+/*----------------------------------------------------------------------*/
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef NULL
+#define NULL (0L)
+#endif
+
+typedef unsigned char NPBool;
+typedef int16_t NPError;
+typedef int16_t NPReason;
+typedef char* NPMIMEType;
+
+/*----------------------------------------------------------------------*/
+/* Structures and definitions */
+/*----------------------------------------------------------------------*/
+
+#if !defined(__LP64__)
+#if 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_t end;
+ uint32_t 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_t offset; /* negative offset means from the end */
+ uint32_t length;
+ struct _NPByteRange* next;
+} NPByteRange;
+
+typedef struct _NPSavedData
+{
+ int32_t len;
+ void* buf;
+} NPSavedData;
+
+typedef struct _NPRect
+{
+ uint16_t top;
+ uint16_t left;
+ uint16_t bottom;
+ uint16_t right;
+} NPRect;
+
+typedef struct _NPSize
+{
+ int32_t width;
+ int32_t height;
+} NPSize;
+
+/* Return values for NPP_HandleEvent */
+#define kNPEventNotHandled 0
+#define kNPEventHandled 1
+/* Exact meaning must be spec'd in event model. */
+#define kNPEventStartIME 2
+
+#if defined(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_t type;
+} NPAnyCallbackStruct;
+
+typedef struct
+{
+ int32_t type;
+ Display* display;
+ Visual* visual;
+ Colormap colormap;
+ unsigned int depth;
+} NPSetWindowCallbackStruct;
+
+typedef struct
+{
+ int32_t type;
+ FILE* fp;
+} NPPrintCallbackStruct;
+
+#endif /* XP_UNIX */
+
+#if defined(XP_MACOSX)
+typedef enum {
+#ifndef NP_NO_QUICKDRAW
+ NPDrawingModelQuickDraw = 0,
+#endif
+ NPDrawingModelCoreGraphics = 1,
+ NPDrawingModelOpenGL = 2,
+ NPDrawingModelCoreAnimation = 3
+} NPDrawingModel;
+
+typedef enum {
+#ifndef NP_NO_CARBON
+ NPEventModelCarbon = 0,
+#endif
+ NPEventModelCocoa = 1
+} NPEventModel;
+#endif
+
+/*
+ * 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 different 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
+
+#if defined(XP_MACOSX)
+#define NP_ABI_MACHO_MASK 0x01000000
+#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 */
+ 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. Introduced in NPAPI minor version 14.
+ */
+ 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. Introduced
+ * in NPAPI minor version 15.
+ */
+ NPPVformValue = 16, /* Not implemented in WebKit */
+
+ NPPVpluginUrlRequestsDisplayedBool = 17, /* Not implemented in WebKit */
+
+ /* Checks if the plugin is interested in receiving the http body of
+ * all http requests (including failed ones, http status != 200).
+ */
+ NPPVpluginWantsAllNetworkStreams = 18,
+
+ /* Browsers can retrieve a native ATK accessibility plug ID via this variable. */
+ NPPVpluginNativeAccessibleAtkPlugId = 19,
+
+ /* Checks to see if the plug-in would like the browser to load the "src" attribute. */
+ NPPVpluginCancelSrcStream = 20
+
+#if defined(XP_MACOSX)
+ /* Used for negotiating drawing models */
+ , NPPVpluginDrawingModel = 1000
+ /* Used for negotiating event models */
+ , NPPVpluginEventModel = 1001
+ /* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
+ , NPPVpluginCoreAnimationLayer = 1003
+#endif
+
+#ifdef ANDROID
+ /* Used when the plugin returns 0 from NPN_WriteReady and wishes the browser
+ * to wait a certain amount of millis before calling NPN_WriteReady again.
+ */
+ , NPPDataDeliveryDelayMs = 100
+
+ // TODO(reed): upstream
+ , NPPFakeValueToForce32Bits = 0x7FFFFFFF
+#endif
+
+#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
+ , NPPVpluginWindowlessLocalBool = 2002
+#endif
+} NPPVariable;
+
+/*
+ * List of variable names for which NPN_GetValue should be implemented.
+ */
+typedef enum {
+ NPNVxDisplay = 1,
+ NPNVxtAppContext,
+ NPNVnetscapeWindow,
+ NPNVjavascriptEnabledBool,
+ NPNVasdEnabledBool,
+ NPNVisOfflineBool,
+
+ 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 = 16,
+
+ NPNVSupportsWindowless = 17,
+
+ NPNVprivateModeBool = 18
+
+#if defined(XP_MACOSX)
+ /* Used for negotiating drawing models */
+ , NPNVpluginDrawingModel = 1000
+#ifndef NP_NO_QUICKDRAW
+ , NPNVsupportsQuickDrawBool = 2000
+#endif
+ , NPNVsupportsCoreGraphicsBool = 2001
+ , NPNVsupportsOpenGLBool = 2002
+ , NPNVsupportsCoreAnimationBool = 2003
+#ifndef NP_NO_CARBON
+ , NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
+#endif
+ , NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
+#endif /* XP_MACOSX */
+
+#ifdef ANDROID
+ , NPNFakeValueToForce32Bits = 0x7FFFFFFF
+#endif
+
+#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5)
+ , NPNVSupportsWindowlessLocal = 2002
+#endif
+} NPNVariable;
+
+typedef enum {
+ NPNURLVCookie = 501,
+ NPNURLVProxy
+} NPNURLVariable;
+
+/*
+ * The type of Toolkit the widgets use
+ */
+typedef enum {
+ NPNVGtk12 = 1,
+ NPNVGtk2
+} NPNToolkitType;
+
+/*
+ * The type of a NPWindow - it specifies the type of the data structure
+ * returned in the window field.
+ */
+typedef enum {
+ NPWindowTypeWindow = 1,
+ NPWindowTypeDrawable
+} NPWindowType;
+
+typedef struct _NPWindow
+{
+ void* window; /* Platform specific window handle */
+ /* OS/2: x - Position of bottom left corner */
+ /* OS/2: y - relative to visible netscape window */
+ int32_t x; /* Position of top left corner relative */
+ int32_t y; /* to a netscape page. */
+ uint32_t width; /* Maximum window size */
+ uint32_t height;
+ NPRect clipRect; /* Clipping rectangle in port coordinates */
+#if defined(XP_UNIX) || defined(XP_SYMBIAN)
+ void * ws_info; /* Platform-dependent additonal data */
+#endif /* XP_UNIX || XP_SYMBIAN */
+ NPWindowType type; /* Is this a window or a drawable? */
+} NPWindow;
+
+typedef struct _NPImageExpose
+{
+ char* data; /* image pointer */
+ int32_t stride; /* Stride of data image pointer */
+ int32_t depth; /* Depth of image pointer */
+ int32_t x; /* Expose x */
+ int32_t y; /* Expose y */
+ uint32_t width; /* Expose width */
+ uint32_t height; /* Expose height */
+ NPSize dataSize; /* Data buffer size */
+ float translateX; /* translate X matrix value */
+ float translateY; /* translate Y matrix value */
+ float scaleX; /* scale X matrix value */
+ float scaleY; /* scale Y matrix value */
+} NPImageExpose;
+
+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_t 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_MACOSX)
+#ifndef NP_NO_CARBON
+typedef EventRecord NPEvent;
+#else
+typedef void* NPEvent;
+#endif
+#elif defined(XP_SYMBIAN)
+typedef QEvent NPEvent;
+#elif defined(XP_WIN)
+typedef struct _NPEvent
+{
+ uint16_t event;
+ uintptr_t wParam;
+ uintptr_t lParam;
+} NPEvent;
+#elif defined(XP_OS2)
+typedef struct _NPEvent
+{
+ uint32_t event;
+ uint32_t wParam;
+ uint32_t lParam;
+} NPEvent;
+#elif defined(XP_UNIX)
+typedef XEvent NPEvent;
+#else
+typedef void* NPEvent;
+#endif
+
+#if defined(XP_MACOSX)
+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;
+#elif defined(XP_SYMBIAN)
+typedef QRegion* NPRegion;
+#else
+typedef void *NPRegion;
+#endif
+
+typedef struct _NPNSString NPNSString;
+typedef struct _NPNSWindow NPNSWindow;
+typedef struct _NPNSMenu NPNSMenu;
+
+#if defined(XP_MACOSX)
+typedef NPNSMenu NPMenu;
+#else
+typedef void *NPMenu;
+#endif
+
+typedef enum {
+ NPCoordinateSpacePlugin = 1,
+ NPCoordinateSpaceWindow,
+ NPCoordinateSpaceFlippedWindow,
+ NPCoordinateSpaceScreen,
+ NPCoordinateSpaceFlippedScreen
+} NPCoordinateSpace;
+
+#if defined(XP_MACOSX)
+
+#ifndef NP_NO_QUICKDRAW
+typedef struct NP_Port
+{
+ CGrafPtr port;
+ int32_t portx; /* position inside the topmost window */
+ int32_t porty;
+} NP_Port;
+#endif /* NP_NO_QUICKDRAW */
+
+/*
+ * 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;
+#ifdef NP_NO_CARBON
+ NPNSWindow *window;
+#else
+ void *window; /* A WindowRef or NULL for the Cocoa event model. */
+#endif
+} 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;
+#ifdef NP_NO_CARBON
+ NPNSWindow *window;
+#else
+ void *window; /* Can be either an NSWindow or a WindowRef depending on the event model */
+#endif
+} NP_GLContext;
+
+typedef enum {
+ NPCocoaEventDrawRect = 1,
+ NPCocoaEventMouseDown,
+ NPCocoaEventMouseUp,
+ NPCocoaEventMouseMoved,
+ NPCocoaEventMouseEntered,
+ NPCocoaEventMouseExited,
+ NPCocoaEventMouseDragged,
+ NPCocoaEventKeyDown,
+ NPCocoaEventKeyUp,
+ NPCocoaEventFlagsChanged,
+ NPCocoaEventFocusChanged,
+ NPCocoaEventWindowFocusChanged,
+ NPCocoaEventScrollWheel,
+ NPCocoaEventTextInput
+} NPCocoaEventType;
+
+typedef struct _NPCocoaEvent {
+ NPCocoaEventType type;
+ uint32_t version;
+ union {
+ struct {
+ uint32_t modifierFlags;
+ double pluginX;
+ double pluginY;
+ int32_t buttonNumber;
+ int32_t clickCount;
+ double deltaX;
+ double deltaY;
+ double deltaZ;
+ } mouse;
+ struct {
+ uint32_t modifierFlags;
+ NPNSString *characters;
+ NPNSString *charactersIgnoringModifiers;
+ NPBool isARepeat;
+ uint16_t keyCode;
+ } key;
+ struct {
+ CGContextRef context;
+ double x;
+ double y;
+ double width;
+ double height;
+ } draw;
+ struct {
+ NPBool hasFocus;
+ } focus;
+ struct {
+ NPNSString *text;
+ } text;
+ } data;
+} NPCocoaEvent;
+
+#ifndef NP_NO_CARBON
+/* Non-standard event types that can be passed to HandleEvent */
+enum NPEventType {
+ NPEventType_GetFocusEvent = (osEvt + 16),
+ NPEventType_LoseFocusEvent,
+ NPEventType_AdjustCursorEvent,
+ NPEventType_MenuCommandEvent,
+ NPEventType_ClippingChangedEvent,
+ NPEventType_ScrollingBeginsEvent = 1000,
+ NPEventType_ScrollingEndsEvent
+};
+#endif /* NP_NO_CARBON */
+
+#endif /* XP_MACOSX */
+
+/*
+ * 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_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
+#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
+#define NPVERS_HAS_ALL_NETWORK_STREAMS 20
+#define NPVERS_HAS_URL_AND_AUTH_INFO 21
+#define NPVERS_HAS_PRIVATE_MODE 22
+#define NPVERS_MACOSX_HAS_EVENT_MODELS 23
+#define NPVERS_HAS_CANCEL_SRC_STREAM 24
+
+/*----------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------*/
+
+#if defined(__OS2__)
+#define NP_LOADDS _System
+#else
+#define NP_LOADDS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NPP_* functions are provided by the plugin and called by the navigator. */
+
+#if defined(XP_UNIX)
+char* NPP_GetMIMEDescription(void);
+#endif
+
+NPError NP_LOADDS NPP_Initialize(void);
+void NP_LOADDS NPP_Shutdown(void);
+NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
+ uint16_t mode, int16_t 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_t* stype);
+NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
+ NPReason reason);
+int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
+int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset,
+ int32_t 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_t NP_LOADDS 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 NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
+NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
+
+/* NPN_* functions are provided by the navigator and called by the plugin. */
+void NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
+ int* netscape_major, int* netscape_minor);
+NPError NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url,
+ const char* target, void* notifyData);
+NPError NP_LOADDS NPN_GetURL(NPP instance, const char* url,
+ const char* target);
+NPError NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url,
+ const char* target, uint32_t len,
+ const char* buf, NPBool file,
+ void* notifyData);
+NPError NP_LOADDS NPN_PostURL(NPP instance, const char* url,
+ const char* target, uint32_t len,
+ const char* buf, NPBool file);
+NPError NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
+NPError NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type,
+ const char* target, NPStream** stream);
+int32_t NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32_t len,
+ void* buffer);
+NPError NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream,
+ NPReason reason);
+void NP_LOADDS NPN_Status(NPP instance, const char* message);
+const char* NP_LOADDS NPN_UserAgent(NPP instance);
+void* NP_LOADDS NPN_MemAlloc(uint32_t size);
+void NP_LOADDS NPN_MemFree(void* ptr);
+uint32_t NP_LOADDS NPN_MemFlush(uint32_t size);
+void NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages);
+JRIEnv* NP_LOADDS NPN_GetJavaEnv(void);
+jref NP_LOADDS NPN_GetJavaPeer(NPP instance);
+NPError NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable,
+ void *value);
+NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable,
+ void *value);
+void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
+void NP_LOADDS NPN_InvalidateRegion(NPP instance,
+ NPRegion invalidRegion);
+void NP_LOADDS NPN_ForceRedraw(NPP instance);
+void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
+void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
+void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
+ void (*func) (void *),
+ void *userData);
+NPError NP_LOADDS NPN_GetValueForURL(NPP instance, NPNURLVariable variable,
+ const char *url, char **value,
+ uint32_t *len);
+NPError NP_LOADDS NPN_SetValueForURL(NPP instance, NPNURLVariable variable,
+ const char *url, const char *value,
+ uint32_t len);
+NPError NP_LOADDS NPN_GetAuthenticationInfo(NPP instance,
+ const char *protocol,
+ const char *host, int32_t port,
+ const char *scheme,
+ const char *realm,
+ char **username, uint32_t *ulen,
+ char **password,
+ uint32_t *plen);
+uint32_t NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
+void NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
+NPError NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
+NPBool NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* RC_INVOKED */
+#if defined(__OS2__)
+#pragma pack()
+#endif
+
+#endif /* npapi_h_ */
diff --git a/Source/WebCore/bridge/npruntime.cpp b/Source/WebCore/bridge/npruntime.cpp
new file mode 100644
index 0000000..ab67076
--- /dev/null
+++ b/Source/WebCore/bridge/npruntime.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "IdentifierRep.h"
+#include "npruntime_internal.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+
+#include "c_utility.h"
+#include <runtime/Identifier.h>
+#include <runtime/JSLock.h>
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+
+using namespace JSC::Bindings;
+using namespace WebCore;
+
+NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
+{
+ return static_cast<NPIdentifier>(IdentifierRep::get(name));
+}
+
+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)
+{
+ return static_cast<NPIdentifier>(IdentifierRep::get(intid));
+}
+
+bool _NPN_IdentifierIsString(NPIdentifier identifier)
+{
+ return static_cast<IdentifierRep*>(identifier)->isString();
+}
+
+NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier)
+{
+ const char* string = static_cast<IdentifierRep*>(identifier)->string();
+ if (!string)
+ return 0;
+
+ return strdup(string);
+}
+
+int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
+{
+ return static_cast<IdentifierRep*>(identifier)->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);
+ if (!variant->value.stringValue.UTF8Characters)
+ CRASH();
+ 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));
+ if (!obj)
+ CRASH();
+ 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 // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/Source/WebCore/bridge/npruntime.h b/Source/WebCore/bridge/npruntime.h
new file mode 100644
index 0000000..468cf92
--- /dev/null
+++ b/Source/WebCore/bridge/npruntime.h
@@ -0,0 +1,393 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.
+ *
+ */
+#ifndef _NP_RUNTIME_H_
+#define _NP_RUNTIME_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "npapi.h"
+
+/*
+ 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.
+*/
+
+#define NP_BEGIN_MACRO do {
+#define NP_END_MACRO } while (0)
+
+/*
+ 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 to be called on variants that own
+ their value, as is the case with all non-const NPVariant*
+ arguments after a successful call to any methods (except this one)
+ in this API.
+
+ After calling NPN_ReleaseVariantValue, the type of the variant
+ will be NPVariantType_Void.
+*/
+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 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, uint32_t(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, uint32_t(_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 lifetime is controlled
+ by the browser. Plugins do not need to worry about memory management
+ with regards to NPIdentifiers.
+*/
+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 *npobj);
+typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj);
+typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name);
+typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, 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 *npobj, NPIdentifier name);
+typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
+ NPVariant *result);
+typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
+ const NPVariant *value);
+typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
+ NPIdentifier name);
+typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value,
+ uint32_t *count);
+typedef bool (*NPConstructFunctionPtr)(NPObject *npobj,
+ const NPVariant *args,
+ uint32_t argCount,
+ NPVariant *result);
+
+/*
+ NPObjects returned by create, retain, invoke, and getProperty pass
+ a reference count to the caller. That is, the callee adds a
+ reference count which passes to the caller. It is the caller's
+ responsibility to release the returned object.
+
+ NPInvokeFunctionPtr function may return 0 to indicate a void
+ result.
+
+ 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;
+ NPConstructFunctionPtr construct;
+};
+
+#define NP_CLASS_STRUCT_VERSION 3
+
+#define NP_CLASS_STRUCT_VERSION_ENUM 2
+#define NP_CLASS_STRUCT_VERSION_CTOR 3
+
+#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
+ ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
+
+#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \
+ ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
+
+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. This method will initialize the referenceCount member of
+ the NPObject to 1.
+*/
+NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
+
+/*
+ Increment the NPObject's reference count.
+*/
+NPObject *NPN_RetainObject(NPObject *npobj);
+
+/*
+ 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 *npobj);
+
+/*
+ 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);
+bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args,
+ uint32_t argCount, NPVariant *result);
+
+/*
+ NPN_SetException may be called to trigger a script exception upon
+ return from entry points into NPObjects. Typical usage:
+
+ NPN_SetException (npobj, message);
+*/
+void NPN_SetException(NPObject *npobj, const NPUTF8 *message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Source/WebCore/bridge/npruntime_impl.h b/Source/WebCore/bridge/npruntime_impl.h
new file mode 100644
index 0000000..559f340
--- /dev/null
+++ b/Source/WebCore/bridge/npruntime_impl.h
@@ -0,0 +1,66 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "npruntime_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void _NPN_ReleaseVariantValue(NPVariant*);
+extern NPIdentifier _NPN_GetStringIdentifier(const NPUTF8*);
+extern void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers);
+extern NPIdentifier _NPN_GetIntIdentifier(int32_t);
+extern bool _NPN_IdentifierIsString(NPIdentifier);
+extern NPUTF8* _NPN_UTF8FromIdentifier(NPIdentifier);
+extern int32_t _NPN_IntFromIdentifier(NPIdentifier);
+extern NPObject* _NPN_CreateObject(NPP, NPClass*);
+extern NPObject* _NPN_RetainObject(NPObject*);
+extern void _NPN_ReleaseObject(NPObject*);
+extern void _NPN_DeallocateObject(NPObject*);
+extern bool _NPN_Invoke(NPP, NPObject*, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result);
+extern bool _NPN_InvokeDefault(NPP, NPObject*, const NPVariant* args, uint32_t argCount, NPVariant* result);
+extern bool _NPN_Evaluate(NPP, NPObject*, NPString*, NPVariant* result);
+extern bool _NPN_GetProperty(NPP, NPObject*, NPIdentifier, NPVariant* result);
+extern bool _NPN_SetProperty(NPP, NPObject*, NPIdentifier, const NPVariant*);
+extern bool _NPN_RemoveProperty(NPP, NPObject*, NPIdentifier);
+extern bool _NPN_HasProperty(NPP, NPObject*, NPIdentifier);
+extern bool _NPN_HasMethod(NPP, NPObject*, NPIdentifier);
+extern void _NPN_SetException(NPObject*, const NPUTF8*);
+extern bool _NPN_Enumerate(NPP, NPObject*, NPIdentifier**, uint32_t* count);
+extern bool _NPN_Construct(NPP, NPObject*, const NPVariant* args, uint32_t argCount, NPVariant *result);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/Source/WebCore/bridge/npruntime_internal.h b/Source/WebCore/bridge/npruntime_internal.h
new file mode 100644
index 0000000..550c34c
--- /dev/null
+++ b/Source/WebCore/bridge/npruntime_internal.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007-2008 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 "npapi.h"
+#include "npfunctions.h"
+#include "npruntime.h"
+
+#ifdef XP_UNIX
+ #include <X11/Xresource.h>
+
+ #undef None
+ #undef Above
+ #undef Below
+ #undef Auto
+ #undef Complex
+ #undef Status
+ #undef CursorShape
+ #undef FocusIn
+ #undef FocusOut
+ #undef KeyPress
+ #undef KeyRelease
+ #undef Unsorted
+ #undef Bool
+ #undef FontChange
+ #undef GrayScale
+ #undef NormalState
+ #undef True
+ #undef False
+#endif
diff --git a/Source/WebCore/bridge/npruntime_priv.h b/Source/WebCore/bridge/npruntime_priv.h
new file mode 100644
index 0000000..301c163
--- /dev/null
+++ b/Source/WebCore/bridge/npruntime_priv.h
@@ -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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#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 // ENABLE(NETSCAPE_PLUGIN_API)
+#endif
+
diff --git a/Source/WebCore/bridge/nptypes.h b/Source/WebCore/bridge/nptypes.h
new file mode 100644
index 0000000..11e9683
--- /dev/null
+++ b/Source/WebCore/bridge/nptypes.h
@@ -0,0 +1,214 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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
+ * mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Johnny Stenback <jst@mozilla.org> (Original author)
+ *
+ * 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 ***** */
+
+/*
+ * Header file for ensuring that C99 types ([u]int32_t and bool) are
+ * available.
+ */
+
+#if defined(WIN32) || defined(OS2)
+ /*
+ * Win32 and OS/2 don't know C99, so define [u]int_16/32 here. The bool
+ * is predefined tho, both in C and C++.
+ */
+ typedef short int16_t;
+ typedef unsigned short uint16_t;
+ typedef int int32_t;
+ typedef unsigned int uint32_t;
+#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
+ /*
+ * AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
+ * but not bool for C.
+ */
+ #include <inttypes.h>
+
+ #ifndef __cplusplus
+ typedef int bool;
+ #endif
+#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD)
+ /*
+ * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and
+ * u_int32_t.
+ */
+ #include <sys/types.h>
+
+ /*
+ * BSD/OS ships no header that defines uint32_t, nor bool (for C)
+ */
+ #if defined(bsdi)
+ typedef u_int32_t uint32_t;
+
+ #if !defined(__cplusplus)
+ typedef int bool;
+ #endif
+ #else
+ /*
+ * FreeBSD and OpenBSD define uint32_t and bool.
+ */
+ #include <inttypes.h>
+ #include <stdbool.h>
+ #endif
+#elif defined(BEOS)
+ #include <inttypes.h>
+#else
+ /*
+ * For those that ship a standard C99 stdint.h header file, include
+ * it. Can't do the same for stdbool.h tho, since some systems ship
+ * with a stdbool.h file that doesn't compile!
+ */
+ #include <stdint.h>
+
+ #ifndef __cplusplus
+ #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
+ #include <stdbool.h>
+ #else
+ /*
+ * GCC 2.91 can't deal with a typedef for bool, but a #define
+ * works.
+ */
+ #define bool int
+ #endif
+ #endif
+#endif
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** 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
+ * mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Johnny Stenback <jst@mozilla.org> (Original author)
+ *
+ * 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 ***** */
+
+/*
+ * Header file for ensuring that C99 types ([u]int32_t and bool) are
+ * available.
+ */
+
+#if defined(WIN32) || defined(OS2)
+ /*
+ * Win32 and OS/2 don't know C99, so define [u]int_16/32 here. The bool
+ * is predefined tho, both in C and C++.
+ */
+ typedef short int16_t;
+ typedef unsigned short uint16_t;
+ typedef int int32_t;
+ typedef unsigned int uint32_t;
+#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
+ /*
+ * AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
+ * but not bool for C.
+ */
+ #include <inttypes.h>
+
+ #ifndef __cplusplus
+ typedef int bool;
+ #endif
+#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD)
+ /*
+ * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and
+ * u_int32_t.
+ */
+ #include <sys/types.h>
+
+ /*
+ * BSD/OS ships no header that defines uint32_t, nor bool (for C)
+ */
+ #if defined(bsdi)
+ typedef u_int32_t uint32_t;
+
+ #if !defined(__cplusplus)
+ typedef int bool;
+ #endif
+ #else
+ /*
+ * FreeBSD and OpenBSD define uint32_t and bool.
+ */
+ #include <inttypes.h>
+ #include <stdbool.h>
+ #endif
+#elif defined(BEOS)
+ #include <inttypes.h>
+#else
+ /*
+ * For those that ship a standard C99 stdint.h header file, include
+ * it. Can't do the same for stdbool.h tho, since some systems ship
+ * with a stdbool.h file that doesn't compile!
+ */
+ #include <stdint.h>
+
+ #ifndef __cplusplus
+ #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
+ #include <stdbool.h>
+ #else
+ /*
+ * GCC 2.91 can't deal with a typedef for bool, but a #define
+ * works.
+ */
+ #define bool int
+ #endif
+ #endif
+#endif
diff --git a/Source/WebCore/bridge/objc/ObjCRuntimeObject.h b/Source/WebCore/bridge/objc/ObjCRuntimeObject.h
new file mode 100644
index 0000000..78550b9
--- /dev/null
+++ b/Source/WebCore/bridge/objc/ObjCRuntimeObject.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Apple 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 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 ObjCRuntimeObject_h
+#define ObjCRuntimeObject_h
+
+#include "runtime_object.h"
+
+namespace JSC {
+namespace Bindings {
+
+class ObjcInstance;
+
+class ObjCRuntimeObject : public RuntimeObject {
+public:
+ ObjCRuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<ObjcInstance>);
+ virtual ~ObjCRuntimeObject();
+
+ ObjcInstance* getInternalObjCInstance() const;
+
+ static const ClassInfo s_info;
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+};
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/bridge/objc/ObjCRuntimeObject.mm b/Source/WebCore/bridge/objc/ObjCRuntimeObject.mm
new file mode 100644
index 0000000..d9afdf2
--- /dev/null
+++ b/Source/WebCore/bridge/objc/ObjCRuntimeObject.mm
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Apple 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 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 "ObjCRuntimeObject.h"
+#import "objc_instance.h"
+
+namespace JSC {
+namespace Bindings {
+
+const ClassInfo ObjCRuntimeObject::s_info = { "ObjCRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+ObjCRuntimeObject::ObjCRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<ObjcInstance> instance)
+ : RuntimeObject(exec, globalObject, instance)
+{
+}
+
+ObjCRuntimeObject::~ObjCRuntimeObject()
+{
+}
+
+ObjcInstance* ObjCRuntimeObject::getInternalObjCInstance() const
+{
+ return static_cast<ObjcInstance*>(getInternalInstance());
+}
+
+
+}
+}
diff --git a/Source/WebCore/bridge/objc/WebScriptObject.h b/Source/WebCore/bridge/objc/WebScriptObject.h
new file mode 100644
index 0000000..6d9ff2c
--- /dev/null
+++ b/Source/WebCore/bridge/objc/WebScriptObject.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 Apple 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>
+#import "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:(JSC::JSValue)value originRootObject:(JSC::Bindings::RootObject*)originRootObject rootObject:(JSC::Bindings::RootObject*)rootObject;
+- _initWithJSObject:(JSC::JSObject*)imp originRootObject:(PassRefPtr<JSC::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<JSC::Bindings::RootObject>)rootObject;
+- (JSC::JSObject *)_imp;
+@end
+
+@protocol WebUndefined
++ (WebUndefined *)undefined;
+@end
diff --git a/Source/WebCore/bridge/objc/objc_class.h b/Source/WebCore/bridge/objc/objc_class.h
new file mode 100644
index 0000000..eebfd2a
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_class.h
@@ -0,0 +1,59 @@
+/*
+ * 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 "objc_runtime.h"
+
+namespace JSC {
+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 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 JSC
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_class.mm b/Source/WebCore/bridge/objc/objc_class.mm
new file mode 100644
index 0000000..2d29499
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_class.mm
@@ -0,0 +1,253 @@
+/*
+ * 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 JSC {
+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;
+}
+
+MethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+ MethodList methodList;
+ char fixedSizeBuffer[1024];
+ char* buffer = fixedSizeBuffer;
+ CString jsName = identifier.ascii();
+ if (!convertJSMethodNameToObjc(jsName.data(), buffer, sizeof(fixedSizeBuffer))) {
+ int length = jsName.length() + 1;
+ buffer = new char[length];
+ if (!buffer || !convertJSMethodNameToObjc(jsName.data(), 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, objcMethodSelector); // 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;
+
+ CString jsName = identifier.ascii();
+ RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, jsName.data(), 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, jsName.data()) == 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* exec, 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 (exec) ObjcFallbackObjectImp(exec, exec->lexicalGlobalObject(), objcInstance, propertyName);
+}
+
+}
+}
diff --git a/Source/WebCore/bridge/objc/objc_header.h b/Source/WebCore/bridge/objc/objc_header.h
new file mode 100644
index 0000000..07954a1
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_header.h
@@ -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/Source/WebCore/bridge/objc/objc_instance.h b/Source/WebCore/bridge/objc/objc_instance.h
new file mode 100644
index 0000000..ae6972a
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_instance.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2003, 2009 Apple 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 "objc_class.h"
+#include "objc_utility.h"
+
+namespace JSC {
+
+namespace Bindings {
+
+class ObjcClass;
+
+class ObjcInstance : public Instance {
+public:
+ static PassRefPtr<ObjcInstance> create(ObjectStructPtr, PassRefPtr<RootObject>);
+ virtual ~ObjcInstance();
+
+ static void setGlobalException(NSString*, JSGlobalObject* exceptionEnvironment = 0); // A null exceptionEnvironment means the exception should propogate to any execution environment.
+
+ virtual Class* getClass() const;
+
+ virtual JSValue valueOf(ExecState*) const;
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName);
+ JSValue invokeObjcMethod(ExecState*, ObjcMethod* method);
+ virtual JSValue invokeMethod(ExecState*, RuntimeMethod* method);
+ virtual bool supportsInvokeDefaultMethod() const;
+ virtual JSValue invokeDefaultMethod(ExecState*);
+
+ JSValue getValueOfUndefinedField(ExecState*, const Identifier&) const;
+ virtual bool setValueOfUndefinedField(ExecState*, const Identifier&, JSValue);
+
+ ObjectStructPtr getObject() const { return _instance.get(); }
+
+ JSValue stringValue(ExecState*) const;
+ JSValue numberValue(ExecState*) const;
+ JSValue booleanValue() const;
+
+protected:
+ virtual void virtualBegin();
+ virtual void virtualEnd();
+
+private:
+ static void moveGlobalExceptionToExecState(ExecState*);
+
+ ObjcInstance(ObjectStructPtr, PassRefPtr<RootObject>);
+
+ virtual RuntimeObject* newRuntimeObject(ExecState*);
+
+ RetainPtr<ObjectStructPtr> _instance;
+ mutable ObjcClass *_class;
+ ObjectStructPtr _pool;
+ int _beginCount;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // BINDINGS_OBJC_INSTANCE_H_
diff --git a/Source/WebCore/bridge/objc/objc_instance.mm b/Source/WebCore/bridge/objc/objc_instance.mm
new file mode 100644
index 0000000..ae9d95d
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_instance.mm
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2004, 2008, 2009 Apple 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 "runtime_method.h"
+#import "ObjCRuntimeObject.h"
+#import "WebScriptObject.h"
+#import <objc/objc-auto.h>
+#import <runtime/Error.h>
+#import <runtime/JSLock.h>
+#import <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 JSC::Bindings;
+using namespace JSC;
+
+static NSString *s_exception;
+static JSGlobalObject* s_exceptionEnvironment; // No need to protect this value, since we just use it for a pointer comparison.
+static NSMapTable *s_instanceWrapperCache;
+
+static NSMapTable *createInstanceWrapperCache()
+{
+#ifdef BUILDING_ON_TIGER
+ return NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0);
+#else
+ // NSMapTable with zeroing weak pointers is the recommended way to build caches like this under garbage collection.
+ NSPointerFunctionsOptions keyOptions = NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsOpaquePersonality;
+ NSPointerFunctionsOptions valueOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
+ return [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
+#endif
+}
+
+RuntimeObject* ObjcInstance::newRuntimeObject(ExecState* exec)
+{
+ return new (exec) ObjCRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+void ObjcInstance::setGlobalException(NSString* exception, JSGlobalObject* exceptionEnvironment)
+{
+ NSString *oldException = s_exception;
+ s_exception = [exception copy];
+ [oldException release];
+
+ s_exceptionEnvironment = exceptionEnvironment;
+}
+
+void ObjcInstance::moveGlobalExceptionToExecState(ExecState* exec)
+{
+ if (!s_exception) {
+ ASSERT(!s_exceptionEnvironment);
+ return;
+ }
+
+ if (!s_exceptionEnvironment || s_exceptionEnvironment == exec->dynamicGlobalObject()) {
+ JSLock lock(SilenceAssertionsOnly);
+ throwError(exec, s_exception);
+ }
+
+ [s_exception release];
+ s_exception = nil;
+ s_exceptionEnvironment = 0;
+}
+
+ObjcInstance::ObjcInstance(id instance, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+ , _instance(instance)
+ , _class(0)
+ , _pool(0)
+ , _beginCount(0)
+{
+}
+
+PassRefPtr<ObjcInstance> ObjcInstance::create(id instance, PassRefPtr<RootObject> rootObject)
+{
+ if (!s_instanceWrapperCache)
+ s_instanceWrapperCache = createInstanceWrapperCache();
+ if (void* existingWrapper = NSMapGet(s_instanceWrapperCache, instance))
+ return static_cast<ObjcInstance*>(existingWrapper);
+ RefPtr<ObjcInstance> wrapper = adoptRef(new ObjcInstance(instance, rootObject));
+ NSMapInsert(s_instanceWrapperCache, instance, wrapper.get());
+ return wrapper.release();
+}
+
+ObjcInstance::~ObjcInstance()
+{
+ // Both -finalizeForWebScript and -dealloc/-finalize of _instance may require autorelease pools.
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ ASSERT(s_instanceWrapperCache);
+ ASSERT(_instance);
+ NSMapRemove(s_instanceWrapperCache, _instance.get());
+
+ if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
+ [_instance.get() performSelector:@selector(finalizeForWebScript)];
+ _instance = 0;
+
+ [pool drain];
+}
+
+static NSAutoreleasePool* allocateAutoReleasePool()
+{
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ // If GC is enabled an autorelease pool is unnecessary, and the
+ // pool cannot be protected from GC so may be collected leading
+ // to a crash when we try to drain the release pool.
+ if (objc_collectingEnabled())
+ return nil;
+#endif
+ return [[NSAutoreleasePool alloc] init];
+}
+
+void ObjcInstance::virtualBegin()
+{
+ if (!_pool)
+ _pool = allocateAutoReleasePool();
+ _beginCount++;
+}
+
+void ObjcInstance::virtualEnd()
+{
+ _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::supportsInvokeDefaultMethod() const
+{
+ return [_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)];
+}
+
+class ObjCRuntimeMethod : public RuntimeMethod {
+public:
+ ObjCRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
+ : RuntimeMethod(exec, globalObject, name, list)
+ {
+ }
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static const ClassInfo s_info;
+};
+
+const ClassInfo ObjCRuntimeMethod::s_info = { "ObjCRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };
+
+JSValue ObjcInstance::getMethod(ExecState* exec, const Identifier& propertyName)
+{
+ MethodList methodList = getClass()->methodsNamed(propertyName, this);
+ return new (exec) ObjCRuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue ObjcInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
+{
+ if (!asObject(runtimeMethod)->inherits(&ObjCRuntimeMethod::s_info))
+ return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));
+
+ const MethodList& methodList = *runtimeMethod->methods();
+
+ // Overloading methods is not allowed in ObjectiveC. Should only be one
+ // name match for a particular method.
+ ASSERT(methodList.size() == 1);
+
+ return invokeObjcMethod(exec, static_cast<ObjcMethod*>(methodList[0]));
+}
+
+JSValue ObjcInstance::invokeObjcMethod(ExecState* exec, ObjcMethod* method)
+{
+ JSValue result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ setGlobalException(nil);
+
+@try {
+ NSMethodSignature* signature = method->getMethodSignature();
+ NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setSelector:method->selector()];
+ [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 = exec->argumentCount();
+ for (int i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, exec->argument(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, exec->argument(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, m_rootObject.get());
+ }
+} @catch(NSException* localException) {
+}
+ moveGlobalExceptionToExecState(exec);
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+JSValue ObjcInstance::invokeDefaultMethod(ExecState* exec)
+{
+ JSValue result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+ setGlobalException(nil);
+
+@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 = exec->argumentCount();
+ for (unsigned i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, exec->argument(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, m_rootObject.get());
+} @catch(NSException* localException) {
+}
+ moveGlobalExceptionToExecState(exec);
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+bool ObjcInstance::setValueOfUndefinedField(ExecState* exec, const Identifier& property, JSValue aValue)
+{
+ id targetObject = getObject();
+ if (![targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)])
+ return false;
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // This check is not really necessary because NSObject implements
+ // setValue:forUndefinedKey:, and unfortunately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)]){
+ setGlobalException(nil);
+
+ ObjcValue objcValue = convertValueToObjcValue(exec, aValue, ObjcObjectType);
+
+ @try {
+ [targetObject setValue:objcValue.objectValue forUndefinedKey:[NSString stringWithCString:property.ascii().data() encoding:NSASCIIStringEncoding]];
+ } @catch(NSException* localException) {
+ // Do nothing. Class did not override valueForUndefinedKey:.
+ }
+
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ return true;
+}
+
+JSValue ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property) const
+{
+ JSValue result = jsUndefined();
+
+ id targetObject = getObject();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // This check is not really necessary because NSObject implements
+ // valueForUndefinedKey:, and unfortunately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(valueForUndefinedKey:)]){
+ setGlobalException(nil);
+
+ @try {
+ id objcValue = [targetObject valueForUndefinedKey:[NSString stringWithCString:property.ascii().data() encoding:NSASCIIStringEncoding]];
+ result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, m_rootObject.get());
+ } @catch(NSException* localException) {
+ // Do nothing. Class did not override valueForUndefinedKey:.
+ }
+
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+JSValue ObjcInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ if ([_instance.get() isKindOfClass:[NSString class]])
+ return stringValue(exec);
+ if ([_instance.get() isKindOfClass:[NSNumber class]])
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue ObjcInstance::stringValue(ExecState* exec) const
+{
+ return convertNSStringToString(exec, [getObject() description]);
+}
+
+JSValue ObjcInstance::numberValue(ExecState*) const
+{
+ // FIXME: Implement something sensible
+ return jsNumber(0);
+}
+
+JSValue ObjcInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible
+ return jsBoolean(false);
+}
+
+JSValue ObjcInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
diff --git a/Source/WebCore/bridge/objc/objc_runtime.h b/Source/WebCore/bridge/objc/objc_runtime.h
new file mode 100644
index 0000000..60fbdac
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_runtime.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 "Bridge.h"
+#include "objc_header.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSObjectWithGlobalObject.h>
+#include <wtf/RetainPtr.h>
+
+namespace JSC {
+namespace Bindings {
+
+ClassStructPtr webScriptObjectClass();
+ClassStructPtr webUndefinedClass();
+
+class ObjcInstance;
+
+class ObjcField : public Field {
+public:
+ ObjcField(IvarStructPtr);
+ ObjcField(CFStringRef name);
+
+ virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
+
+private:
+ IvarStructPtr _ivar;
+ RetainPtr<CFStringRef> _name;
+};
+
+class ObjcMethod : public Method {
+public:
+ ObjcMethod() : _objcClass(0), _selector(0), _javaScriptName(0) {}
+ ObjcMethod(ClassStructPtr aClass, SEL _selector);
+
+ virtual int numParameters() const;
+
+ NSMethodSignature *getMethodSignature() const;
+
+ bool isFallbackMethod() const { return _selector == @selector(invokeUndefinedMethodFromWebScript:withArguments:); }
+ void setJavaScriptName(CFStringRef n) { _javaScriptName = n; }
+ CFStringRef javaScriptName() const { return _javaScriptName.get(); }
+
+ SEL selector() const { return _selector; }
+
+private:
+ ClassStructPtr _objcClass;
+ SEL _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 JSObjectWithGlobalObject {
+public:
+ ObjcFallbackObjectImp(ExecState*, JSGlobalObject*, ObjcInstance*, const Identifier& propertyName);
+
+ static const ClassInfo s_info;
+
+ const Identifier& propertyName() const { return _item; }
+
+ static ObjectPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
+ {
+ return globalObject->objectPrototype();
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+private:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual CallType getCallData(CallData&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual bool toBoolean(ExecState*) const;
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ RefPtr<ObjcInstance> _instance;
+ Identifier _item;
+};
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_runtime.mm b/Source/WebCore/bridge/objc/objc_runtime.mm
new file mode 100644
index 0000000..3c4ba23
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_runtime.mm
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 "JSDOMBinding.h"
+#include "ObjCRuntimeObject.h"
+#include "WebScriptObject.h"
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <runtime/Error.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/ObjectPrototype.h>
+#include <wtf/RetainPtr.h>
+
+using namespace WebCore;
+
+namespace JSC {
+namespace Bindings {
+
+ClassStructPtr webScriptObjectClass()
+{
+ static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");
+ return webScriptObjectClass;
+}
+
+ClassStructPtr webUndefinedClass()
+{
+ static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");
+ return webUndefinedClass;
+}
+
+// ---------------------- ObjcMethod ----------------------
+
+ObjcMethod::ObjcMethod(ClassStructPtr aClass, SEL selector)
+ : _objcClass(aClass)
+ , _selector(selector)
+{
+}
+
+int ObjcMethod::numParameters() const
+{
+ return [getMethodSignature() numberOfArguments] - 2;
+}
+
+NSMethodSignature* ObjcMethod::getMethodSignature() const
+{
+ return [_objcClass instanceMethodSignatureForSelector:_selector];
+}
+
+// ---------------------- ObjcField ----------------------
+
+ObjcField::ObjcField(Ivar ivar)
+ : _ivar(ivar)
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ , _name(AdoptCF, CFStringCreateWithCString(0, ivar_getName(_ivar), kCFStringEncodingASCII))
+#else
+ , _name(AdoptCF, CFStringCreateWithCString(0, _ivar->ivar_name, kCFStringEncodingASCII))
+#endif
+{
+}
+
+ObjcField::ObjcField(CFStringRef name)
+ : _ivar(0)
+ , _name(name)
+{
+}
+
+JSValue ObjcField::valueFromInstance(ExecState* exec, const Instance* instance) const
+{
+ JSValue result = jsUndefined();
+
+ id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ @try {
+ if (id objcValue = [targetObject valueForKey:(NSString *)_name.get()])
+ result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, instance->rootObject());
+ } @catch(NSException* localException) {
+ JSLock::lock(SilenceAssertionsOnly);
+ throwError(exec, [localException reason]);
+ JSLock::unlock(SilenceAssertionsOnly);
+ }
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(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(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ @try {
+ [targetObject setValue:value forKey:(NSString *)_name.get()];
+ } @catch(NSException* localException) {
+ JSLock::lock(SilenceAssertionsOnly);
+ throwError(exec, [localException reason]);
+ JSLock::unlock(SilenceAssertionsOnly);
+ }
+}
+
+// ---------------------- 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, createTypeError(exec, "Array is not mutable."));
+ return;
+ }
+
+ if (index > [_array.get() count]) {
+ throwError(exec, createRangeError(exec, "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, createError(exec, "Objective-C exception."));
+ }
+}
+
+JSValue ObjcArray::valueAt(ExecState* exec, unsigned int index) const
+{
+ if (index > [_array.get() count])
+ return throwError(exec, createRangeError(exec, "Index exceeds array size."));
+ @try {
+ id obj = [_array.get() objectAtIndex:index];
+ if (obj)
+ return convertObjcValueToValue (exec, &obj, ObjcObjectType, m_rootObject.get());
+ } @catch(NSException* localException) {
+ return throwError(exec, createError(exec, "Objective-C exception."));
+ }
+ return jsUndefined();
+}
+
+unsigned int ObjcArray::getLength() const
+{
+ return [_array.get() count];
+}
+
+const ClassInfo ObjcFallbackObjectImp::s_info = { "ObjcFallbackObject", 0, 0, 0 };
+
+ObjcFallbackObjectImp::ObjcFallbackObjectImp(ExecState* exec, JSGlobalObject* globalObject, ObjcInstance* i, const Identifier& propertyName)
+ // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
+ : JSObjectWithGlobalObject(globalObject, deprecatedGetDOMStructure<ObjcFallbackObjectImp>(exec))
+ , _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();
+ return true;
+}
+
+bool ObjcFallbackObjectImp::getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor& descriptor)
+{
+ // keep the prototype from getting called instead of just returning false
+ descriptor.setUndefined();
+ return true;
+}
+
+void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue, PutPropertySlot&)
+{
+}
+
+static EncodedJSValue JSC_HOST_CALL callObjCFallbackObject(ExecState* exec)
+{
+ JSValue thisValue = exec->hostThisValue();
+ if (!thisValue.inherits(&ObjCRuntimeObject::s_info))
+ return throwVMTypeError(exec);
+
+ JSValue result = jsUndefined();
+
+ ObjCRuntimeObject* runtimeObject = static_cast<ObjCRuntimeObject*>(asObject(thisValue));
+ ObjcInstance* objcInstance = runtimeObject->getInternalObjCInstance();
+
+ if (!objcInstance)
+ return JSValue::encode(RuntimeObject::throwInvalidAccessError(exec));
+
+ objcInstance->begin();
+
+ id targetObject = objcInstance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
+ ObjcClass* objcClass = static_cast<ObjcClass*>(objcInstance->getClass());
+ OwnPtr<ObjcMethod> fallbackMethod(new ObjcMethod(objcClass->isa(), @selector(invokeUndefinedMethodFromWebScript:withArguments:)));
+ const Identifier& nameIdentifier = static_cast<ObjcFallbackObjectImp*>(exec->callee())->propertyName();
+ RetainPtr<CFStringRef> name(AdoptCF, CFStringCreateWithCharacters(0, nameIdentifier.characters(), nameIdentifier.length()));
+ fallbackMethod->setJavaScriptName(name.get());
+ result = objcInstance->invokeObjcMethod(exec, fallbackMethod.get());
+ }
+
+ objcInstance->end();
+
+ return JSValue::encode(result);
+}
+
+CallType ObjcFallbackObjectImp::getCallData(CallData& callData)
+{
+ id targetObject = _instance->getObject();
+ if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return CallTypeNone;
+ callData.native.function = callObjCFallbackObject;
+ return CallTypeHost;
+}
+
+bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+ return false;
+}
+
+JSValue ObjcFallbackObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType) const
+{
+ return _instance->getValueOfUndefinedField(exec, _item);
+}
+
+bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
+{
+ id targetObject = _instance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return true;
+
+ return false;
+}
+
+}
+}
diff --git a/Source/WebCore/bridge/objc/objc_utility.h b/Source/WebCore/bridge/objc/objc_utility.h
new file mode 100644
index 0000000..4810752
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_utility.h
@@ -0,0 +1,88 @@
+/*
+ * 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 "objc_header.h"
+#include <runtime/Error.h>
+#include <runtime/JSObject.h>
+
+#ifdef __OBJC__
+@class NSString;
+#else
+class NSString;
+#endif
+
+namespace JSC {
+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*, JSValue, ObjcValueType);
+JSValue convertNSStringToString(ExecState* exec, NSString *nsstring);
+JSValue convertObjcValueToValue(ExecState*, void* buffer, ObjcValueType, RootObject*);
+ObjcValueType objcValueTypeForType(const char *type);
+
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize);
+
+JSObject *throwError(ExecState *, NSString *message);
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_utility.mm b/Source/WebCore/bridge/objc/objc_utility.mm
new file mode 100644
index 0000000..dfba852
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_utility.mm
@@ -0,0 +1,373 @@
+/*
+ * 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 "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.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 JSC {
+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(SilenceAssertionsOnly);
+
+ JSGlobalObject *originGlobalObject = exec->dynamicGlobalObject();
+ RootObject* originRootObject = findRootObject(originGlobalObject);
+
+ JSGlobalObject* globalObject = 0;
+ if (value.isObject() && asObject(value)->isGlobalObject())
+ globalObject = static_cast<JSGlobalObject*>(asObject(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(ExecState* exec, NSString *nsstring)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ 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(exec, 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(SilenceAssertionsOnly);
+
+ switch (type) {
+ case ObjcObjectType: {
+ id obj = *(id*)buffer;
+ if ([obj isKindOfClass:[NSString class]])
+ return convertNSStringToString(exec, (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 (exec) 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 ObjcInstance::create(obj, rootObject)->createRuntimeObject(exec);
+ }
+ 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 jsUndefined();
+}
+
+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, NSString *message)
+{
+ ASSERT(message);
+ size_t length = [message length];
+ unichar *buffer = new unichar[length];
+ [message getCharacters:buffer];
+ JSObject *error = JSC::throwError(exec, JSC::createError(exec, UString(buffer, length)));
+ delete [] buffer;
+ return error;
+}
+
+}
+}
diff --git a/Source/WebCore/bridge/qt/qt_class.cpp b/Source/WebCore/bridge/qt/qt_class.cpp
new file mode 100644
index 0000000..4c29c69
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_class.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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_class.h"
+
+#include "Identifier.h"
+#include "qt_instance.h"
+#include "qt_runtime.h"
+
+#include <qdebug.h>
+#include <qmetaobject.h>
+
+namespace JSC {
+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 object and return the same object for the same
+// identifier.
+JSValue QtClass::fallbackObject(ExecState* exec, Instance* inst, const Identifier& identifier)
+{
+ QtInstance* qtinst = static_cast<QtInstance*>(inst);
+
+ const UString& ustring = identifier.ustring();
+ const QByteArray name = QString(reinterpret_cast<const QChar*>(ustring.characters()), ustring.length()).toAscii();
+
+ // First see if we have a cache hit
+ JSObject* val = qtinst->m_methods.value(name);
+ if (val)
+ return val;
+
+ // Nope, create an entry
+ const 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) {
+ QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+ qtinst->m_methods.insert(name, val);
+ return val;
+ }
+ }
+
+ // Nope.. try a basename match
+ const 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;
+
+ int iter = 0;
+ const char* signature = m.signature();
+ while (signature[iter] && signature[iter] != '(')
+ ++iter;
+
+ if (normal == QByteArray::fromRawData(signature, iter)) {
+ QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+ 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();
+ const UString& ustring = identifier.ustring();
+ const QString name(reinterpret_cast<const QChar*>(ustring.characters()), ustring.length());
+ const QByteArray ascii = name.toAscii();
+
+ // First check for a cached field
+ QtField* f = qtinst->m_fields.value(name);
+
+ 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;
+#ifndef QT_NO_PROPERTIES
+ if (f->fieldType() == QtField::DynamicProperty) {
+ if (obj->dynamicPropertyNames().indexOf(ascii) >= 0)
+ return f;
+ // Dynamic property that disappeared
+ qtinst->m_fields.remove(name);
+ delete f;
+ }
+#endif
+ else {
+ const QList<QObject*>& children = obj->children();
+ const int count = children.size();
+ for (int index = 0; index < count; ++index) {
+ QObject* child = children.at(index);
+ if (child->objectName() == name)
+ return f;
+ }
+
+ // Didn't find it, delete it from the cache
+ qtinst->m_fields.remove(name);
+ delete f;
+ }
+ }
+
+ int index = m_metaObject->indexOfProperty(ascii);
+ if (index >= 0) {
+ const QMetaProperty prop = m_metaObject->property(index);
+
+ if (prop.isScriptable(obj)) {
+ f = new QtField(prop);
+ qtinst->m_fields.insert(name, f);
+ return f;
+ }
+ }
+
+#ifndef QT_NO_PROPERTIES
+ // Dynamic properties
+ index = obj->dynamicPropertyNames().indexOf(ascii);
+ if (index >= 0) {
+ f = new QtField(ascii);
+ qtinst->m_fields.insert(name, f);
+ return f;
+ }
+#endif
+
+ // Child objects
+
+ const QList<QObject*>& children = obj->children();
+ const int count = children.count();
+ for (index = 0; index < count; ++index) {
+ QObject* child = children.at(index);
+ if (child->objectName() == name) {
+ f = new QtField(child);
+ qtinst->m_fields.insert(name, f);
+ return f;
+ }
+ }
+
+ // Nothing named this
+ return 0;
+ }
+ // 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(ascii))
+ return 0;
+
+#ifndef QT_NO_PROPERTIES
+ // 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(ascii);
+ qtinst->m_fields.insert(name, f);
+ }
+#endif
+ return f;
+}
+
+}
+}
+
diff --git a/Source/WebCore/bridge/qt/qt_class.h b/Source/WebCore/bridge/qt/qt_class.h
new file mode 100644
index 0000000..9d55cc5
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_class.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 qt_class_h
+#define qt_class_h
+
+#include "Bridge.h"
+#include "qglobal.h"
+
+QT_BEGIN_NAMESPACE
+class QObject;
+struct QMetaObject;
+QT_END_NAMESPACE
+
+namespace JSC {
+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 JSC
+
+#endif
diff --git a/Source/WebCore/bridge/qt/qt_instance.cpp b/Source/WebCore/bridge/qt/qt_instance.cpp
new file mode 100644
index 0000000..78263e9
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_instance.cpp
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "Error.h"
+#include "JSDOMBinding.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "qt_class.h"
+#include "qt_runtime.h"
+#include "runtime_object.h"
+
+#include <qdebug.h>
+#include <qhash.h>
+#include <qmetaobject.h>
+#include <qmetatype.h>
+
+namespace JSC {
+namespace Bindings {
+
+// Cache QtInstances
+typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
+static QObjectInstanceMap cachedInstances;
+
+// Derived RuntimeObject
+class QtRuntimeObject : public RuntimeObject {
+public:
+ QtRuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<Instance>);
+
+ static const ClassInfo s_info;
+
+ virtual void markChildren(MarkStack& markStack)
+ {
+ RuntimeObject::markChildren(markStack);
+ QtInstance* instance = static_cast<QtInstance*>(getInternalInstance());
+ if (instance)
+ instance->markAggregate(markStack);
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+protected:
+ static const unsigned StructureFlags = RuntimeObject::StructureFlags | OverridesMarkChildren;
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+};
+
+const ClassInfo QtRuntimeObject::s_info = { "QtRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+QtRuntimeObject::QtRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<Instance> instance)
+ : RuntimeObject(exec, globalObject, WebCore::deprecatedGetDOMStructure<QtRuntimeObject>(exec), instance)
+{
+}
+
+// QtInstance
+QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership)
+ : Instance(rootObject)
+ , m_class(0)
+ , m_object(o)
+ , m_hashkey(o)
+ , m_defaultMethod(0)
+ , m_ownership(ownership)
+{
+}
+
+QtInstance::~QtInstance()
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ cachedInstances.remove(m_hashkey);
+
+ // clean up (unprotect from gc) the JSValues we've created
+ m_methods.clear();
+
+ qDeleteAll(m_fields);
+ m_fields.clear();
+
+ if (m_object) {
+ switch (m_ownership) {
+ case QScriptEngine::QtOwnership:
+ break;
+ case QScriptEngine::AutoOwnership:
+ if (m_object->parent())
+ break;
+ // fall through!
+ case QScriptEngine::ScriptOwnership:
+ delete m_object;
+ break;
+ }
+ }
+}
+
+PassRefPtr<QtInstance> QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ foreach (QtInstance* instance, cachedInstances.values(o))
+ if (instance->rootObject() == rootObject) {
+ // The garbage collector removes instances, but it may happen that the wrapped
+ // QObject dies before the gc kicks in. To handle that case we have to do an additional
+ // check if to see if the instance's wrapped object is still alive. If it isn't, then
+ // we have to create a new wrapper.
+ if (!instance->getObject())
+ cachedInstances.remove(instance->hashKey());
+ else
+ return instance;
+ }
+
+ RefPtr<QtInstance> ret = QtInstance::create(o, rootObject, ownership);
+ cachedInstances.insert(o, ret.get());
+
+ return ret.release();
+}
+
+bool QtInstance::getOwnPropertySlot(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return object->JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+void QtInstance::put(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ object->JSObject::put(exec, propertyName, value, slot);
+}
+
+void QtInstance::removeCachedMethod(JSObject* method)
+{
+ if (m_defaultMethod == method)
+ m_defaultMethod = 0;
+
+ for (QHash<QByteArray, JSObject*>::Iterator it = m_methods.begin(),
+ end = m_methods.end(); it != end; ++it)
+ if (it.value() == method) {
+ m_methods.erase(it);
+ return;
+ }
+}
+
+QtInstance* QtInstance::getInstance(JSObject* object)
+{
+ if (!object)
+ return 0;
+ if (!object->inherits(&QtRuntimeObject::s_info))
+ return 0;
+ return static_cast<QtInstance*>(static_cast<RuntimeObject*>(object)->getInternalInstance());
+}
+
+Class* QtInstance::getClass() const
+{
+ if (!m_class) {
+ if (!m_object)
+ return 0;
+ m_class = QtClass::classForObject(m_object);
+ }
+ return m_class;
+}
+
+RuntimeObject* QtInstance::newRuntimeObject(ExecState* exec)
+{
+ JSLock lock(SilenceAssertionsOnly);
+ m_methods.clear();
+ return new (exec) QtRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+void QtInstance::markAggregate(MarkStack& markStack)
+{
+ if (m_defaultMethod)
+ markStack.append(m_defaultMethod);
+ foreach (JSObject* val, m_methods.values()) {
+ if (val)
+ markStack.append(val);
+ }
+}
+
+void QtInstance::begin()
+{
+ // Do nothing.
+}
+
+void QtInstance::end()
+{
+ // Do nothing.
+}
+
+void QtInstance::getPropertyNames(ExecState* exec, 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(exec, prop.name()));
+ }
+
+#ifndef QT_NO_PROPERTIES
+ QList<QByteArray> dynProps = obj->dynamicPropertyNames();
+ foreach (const QByteArray& ba, dynProps)
+ array.add(Identifier(exec, ba.constData()));
+#endif
+
+ const int methodCount = meta->methodCount();
+ for (i = 0; i < methodCount; i++) {
+ QMetaMethod method = meta->method(i);
+ if (method.access() != QMetaMethod::Private)
+ array.add(Identifier(exec, method.signature()));
+ }
+ }
+}
+
+JSValue QtInstance::getMethod(ExecState* exec, const Identifier& propertyName)
+{
+ if (!getClass())
+ return jsNull();
+ MethodList methodList = m_class->methodsNamed(propertyName, this);
+ return new (exec) RuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue QtInstance::invokeMethod(ExecState*, RuntimeMethod*)
+{
+ // Implemented via fallbackMethod & QtRuntimeMetaMethod::callAsFunction
+ return jsUndefined();
+}
+
+JSValue QtInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue QtInstance::stringValue(ExecState* exec) const
+{
+ QObject* obj = getObject();
+ if (!obj)
+ return jsNull();
+
+ // Hmm.. see if there is a toString defined
+ QByteArray buf;
+ bool useDefault = true;
+ getClass();
+ if (m_class) {
+ // 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().isEmpty()) {
+ const char* retsig = m.typeName();
+ if (retsig && *retsig) {
+ QVariant ret(QMetaType::type(retsig), (void*)0);
+ void * qargs[1];
+ qargs[0] = ret.data();
+
+ if (QMetaObject::metacall(obj, 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(exec, buf.constData());
+}
+
+JSValue QtInstance::numberValue(ExecState*) const
+{
+ return jsNumber(0);
+}
+
+JSValue QtInstance::booleanValue() const
+{
+ // ECMA 9.2
+ return jsBoolean(getObject());
+}
+
+JSValue QtInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+// In qt_runtime.cpp
+JSValue convertQVariantToValue(ExecState*, PassRefPtr<RootObject> root, const QVariant& variant);
+QVariant convertValueToQVariant(ExecState*, JSValue, QMetaType::Type hint, int *distance);
+
+QByteArray QtField::name() const
+{
+ if (m_type == MetaProperty)
+ return m_property.name();
+ if (m_type == ChildObject && m_childObject)
+ return m_childObject->objectName().toLatin1();
+#ifndef QT_NO_PROPERTIES
+ if (m_type == DynamicProperty)
+ return m_dynamicProperty;
+#endif
+ return QByteArray(); // 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);
+#ifndef QT_NO_PROPERTIES
+ else if (m_type == DynamicProperty)
+ val = obj->property(m_dynamicProperty);
+#endif
+ return convertQVariantToValue(exec, inst->rootObject(), val);
+ }
+ QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
+ return throwError(exec, createError(exec, 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);
+ }
+#ifndef QT_NO_PROPERTIES
+ else if (m_type == DynamicProperty)
+ obj->setProperty(m_dynamicProperty.constData(), val);
+#endif
+ } else {
+ QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
+ throwError(exec, createError(exec, msg.toLatin1().constData()));
+ }
+}
+
+
+}
+}
diff --git a/Source/WebCore/bridge/qt/qt_instance.h b/Source/WebCore/bridge/qt/qt_instance.h
new file mode 100644
index 0000000..dd24a92
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_instance.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 qt_instance_h
+#define qt_instance_h
+
+#include "Bridge.h"
+#include "runtime_root.h"
+#include <QtScript/qscriptengine.h>
+#include <qhash.h>
+#include <qpointer.h>
+#include <qset.h>
+
+namespace JSC {
+
+namespace Bindings {
+
+class QtClass;
+class QtField;
+class QtRuntimeMetaMethod;
+
+class QtInstance : public Instance {
+public:
+ ~QtInstance();
+
+ virtual Class* getClass() const;
+ virtual RuntimeObject* newRuntimeObject(ExecState*);
+
+ virtual void begin();
+ virtual void end();
+
+ virtual JSValue valueOf(ExecState*) const;
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ void markAggregate(MarkStack&);
+
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName);
+ virtual JSValue invokeMethod(ExecState*, RuntimeMethod*);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ JSValue stringValue(ExecState* exec) const;
+ JSValue numberValue(ExecState* exec) const;
+ JSValue booleanValue() const;
+
+ QObject* getObject() const { return m_object; }
+ QObject* hashKey() const { return m_hashkey; }
+
+ static PassRefPtr<QtInstance> getQtInstance(QObject*, PassRefPtr<RootObject>, QScriptEngine::ValueOwnership ownership);
+
+ virtual bool getOwnPropertySlot(JSObject*, ExecState*, const Identifier&, PropertySlot&);
+ virtual void put(JSObject*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+
+ void removeCachedMethod(JSObject*);
+
+ static QtInstance* getInstance(JSObject*);
+
+private:
+ static PassRefPtr<QtInstance> create(QObject *instance, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership)
+ {
+ return adoptRef(new QtInstance(instance, rootObject, ownership));
+ }
+
+ friend class QtClass;
+ friend class QtField;
+ QtInstance(QObject*, PassRefPtr<RootObject>, QScriptEngine::ValueOwnership ownership); // Factory produced only..
+ mutable QtClass* m_class;
+ QPointer<QObject> m_object;
+ QObject* m_hashkey;
+ mutable QHash<QByteArray, JSObject*> m_methods;
+ mutable QHash<QString, QtField*> m_fields;
+ mutable QtRuntimeMetaMethod* m_defaultMethod;
+ QScriptEngine::ValueOwnership m_ownership;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/qt/qt_pixmapruntime.cpp b/Source/WebCore/bridge/qt/qt_pixmapruntime.cpp
new file mode 100644
index 0000000..1ef20c3
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_pixmapruntime.cpp
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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_pixmapruntime.h"
+
+#include "CachedImage.h"
+#include "HTMLImageElement.h"
+#include "JSGlobalObject.h"
+#include "JSHTMLImageElement.h"
+#include "JSLock.h"
+#include "ObjectPrototype.h"
+#include "StillImageQt.h"
+#include <QBuffer>
+#include <QByteArray>
+#include <QImage>
+#include <QPixmap>
+#include <QVariant>
+#include <runtime_method.h>
+#include <runtime_object.h>
+#include <runtime_root.h>
+
+using namespace WebCore;
+namespace JSC {
+
+namespace Bindings {
+
+class QtPixmapClass : public Class {
+public:
+ QtPixmapClass();
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+ virtual Field* fieldNamed(const Identifier&, Instance*) const;
+};
+
+
+class QtPixmapWidthField : public Field {
+public:
+ static const char* name() { return "width"; }
+ virtual JSValue valueFromInstance(ExecState*, const Instance* instance) const
+ {
+ return jsNumber(static_cast<const QtPixmapInstance*>(instance)->width());
+ }
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {}
+};
+
+class QtPixmapHeightField : public Field {
+public:
+ static const char* name() { return "height"; }
+ virtual JSValue valueFromInstance(ExecState*, const Instance* instance) const
+ {
+ return jsNumber(static_cast<const QtPixmapInstance*>(instance)->height());
+ }
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {}
+};
+
+class QtPixmapRuntimeMethod : public Method {
+public:
+ virtual int numParameters() const
+ {
+ return 0;
+ }
+ virtual JSValue invoke(ExecState* exec, QtPixmapInstance*) = 0;
+
+};
+
+// this function receives an HTML image element as a parameter, makes it display the pixmap/image from Qt
+class QtPixmapAssignToElementMethod : public QtPixmapRuntimeMethod {
+public:
+ static const char* name() { return "assignToHTMLImageElement"; }
+ JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
+ {
+ if (!exec->argumentCount())
+ return jsUndefined();
+
+ JSObject* objectArg = exec->argument(0).toObject(exec);
+ if (!objectArg)
+ return jsUndefined();
+
+ if (!objectArg->inherits(&JSHTMLImageElement::s_info))
+ return jsUndefined();
+
+ // we now know that we have a valid <img> element as the argument, we can attach the pixmap to it.
+ PassRefPtr<StillImage> stillImage = WebCore::StillImage::create(instance->toPixmap());
+ HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(objectArg)->impl());
+ imageElement->setCachedImage(new CachedImage(stillImage.get()));
+ JSDOMGlobalObject* global = static_cast<JSDOMGlobalObject*>(instance->rootObject()->globalObject());
+ toJS(exec, global, imageElement->document());
+ return jsUndefined();
+ }
+
+ virtual int numParameters() const
+ {
+ return 1;
+ }
+};
+
+// this function encodes the image to a dataUrl, to be used in background etc. Note: very slow.
+class QtPixmapToDataUrlMethod : public QtPixmapRuntimeMethod {
+public:
+ static const char* name() { return "toDataUrl"; }
+ JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
+ {
+ QByteArray byteArray;
+ QBuffer buffer(&byteArray);
+ instance->toImage().save(&buffer, "PNG");
+ const QString encodedString = QString("data:image/png;base64,") + byteArray.toBase64();
+ const UString ustring((UChar*)encodedString.utf16(), encodedString.length());
+ return jsString(exec, ustring);
+ }
+};
+
+class QtPixmapToStringMethod : public QtPixmapRuntimeMethod {
+ public:
+ static const char* name() { return "toString"; }
+ JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
+ {
+ return instance->valueOf(exec);
+ }
+};
+
+struct QtPixmapMetaData {
+ QtPixmapToDataUrlMethod toDataUrlMethod;
+ QtPixmapAssignToElementMethod assignToElementMethod;
+ QtPixmapToStringMethod toStringMethod;
+ QtPixmapHeightField heightField;
+ QtPixmapWidthField widthField;
+ QtPixmapClass cls;
+} qt_pixmap_metaData;
+
+// Derived RuntimeObject
+class QtPixmapRuntimeObject : public RuntimeObject {
+public:
+ QtPixmapRuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<Instance>);
+
+ static const ClassInfo s_info;
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+protected:
+ static const unsigned StructureFlags = RuntimeObject::StructureFlags | OverridesMarkChildren;
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+};
+
+QtPixmapRuntimeObject::QtPixmapRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<Instance> instance)
+ : RuntimeObject(exec, globalObject, WebCore::deprecatedGetDOMStructure<QtPixmapRuntimeObject>(exec), instance)
+{
+}
+
+const ClassInfo QtPixmapRuntimeObject::s_info = { "QtPixmapRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+QtPixmapClass::QtPixmapClass()
+{
+}
+
+
+Class* QtPixmapInstance::getClass() const
+{
+ return &qt_pixmap_metaData.cls;
+}
+
+JSValue QtPixmapInstance::getMethod(ExecState* exec, const Identifier& propertyName)
+{
+ MethodList methodList = getClass()->methodsNamed(propertyName, this);
+ return new (exec) RuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue QtPixmapInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
+{
+ const MethodList& methods = *runtimeMethod->methods();
+
+ if (methods.size() == 1) {
+ QtPixmapRuntimeMethod* method = static_cast<QtPixmapRuntimeMethod*>(methods[0]);
+ return method->invoke(exec, this);
+ }
+ return jsUndefined();
+}
+
+MethodList QtPixmapClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+ MethodList methods;
+ if (identifier == QtPixmapToDataUrlMethod::name())
+ methods.append(&qt_pixmap_metaData.toDataUrlMethod);
+ else if (identifier == QtPixmapAssignToElementMethod::name())
+ methods.append(&qt_pixmap_metaData.assignToElementMethod);
+ else if (identifier == QtPixmapToStringMethod::name())
+ methods.append(&qt_pixmap_metaData.toStringMethod);
+ return methods;
+}
+
+Field* QtPixmapClass::fieldNamed(const Identifier& identifier, Instance*) const
+{
+ if (identifier == QtPixmapWidthField::name())
+ return &qt_pixmap_metaData.widthField;
+ if (identifier == QtPixmapHeightField::name())
+ return &qt_pixmap_metaData.heightField;
+ return 0;
+}
+
+void QtPixmapInstance::getPropertyNames(ExecState*exec, PropertyNameArray& arr)
+{
+ arr.add(Identifier(exec, UString(QtPixmapToDataUrlMethod::name())));
+ arr.add(Identifier(exec, UString(QtPixmapAssignToElementMethod::name())));
+ arr.add(Identifier(exec, UString(QtPixmapToStringMethod::name())));
+ arr.add(Identifier(exec, UString(QtPixmapWidthField::name())));
+ arr.add(Identifier(exec, UString(QtPixmapHeightField::name())));
+}
+
+JSValue QtPixmapInstance::defaultValue(ExecState* exec, PreferredPrimitiveType ptype) const
+{
+ if (ptype == PreferNumber) {
+ return jsBoolean(
+ (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()) && !(data.value<QImage>()).isNull())
+ || (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()) && !data.value<QPixmap>().isNull()));
+ }
+
+ if (ptype == PreferString)
+ return valueOf(exec);
+
+ return jsUndefined();
+}
+
+JSValue QtPixmapInstance::valueOf(ExecState* exec) const
+{
+ const QString stringValue = QString("[Qt Native Pixmap %1,%2]").arg(width()).arg(height());
+ UString ustring((UChar*)stringValue.utf16(), stringValue.length());
+ return jsString(exec, ustring);
+}
+
+QtPixmapInstance::QtPixmapInstance(PassRefPtr<RootObject> rootObj, const QVariant& d)
+ :Instance(rootObj), data(d)
+{
+}
+
+int QtPixmapInstance::width() const
+{
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
+ return data.value<QPixmap>().width();
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
+ return data.value<QImage>().width();
+ return 0;
+}
+
+int QtPixmapInstance::height() const
+{
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
+ return data.value<QPixmap>().height();
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
+ return data.value<QImage>().height();
+ return 0;
+}
+
+QPixmap QtPixmapInstance::toPixmap()
+{
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
+ return data.value<QPixmap>();
+
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) {
+ const QPixmap pixmap = QPixmap::fromImage(data.value<QImage>());
+ data = QVariant::fromValue<QPixmap>(pixmap);
+ return pixmap;
+ }
+
+ return QPixmap();
+}
+
+QImage QtPixmapInstance::toImage()
+{
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
+ return data.value<QImage>();
+
+ if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) {
+ const QImage image = data.value<QPixmap>().toImage();
+ data = QVariant::fromValue<QImage>(image);
+ return image;
+ }
+
+ return QImage();
+}
+
+QVariant QtPixmapInstance::variantFromObject(JSObject* object, QMetaType::Type hint)
+{
+ if (!object)
+ goto returnEmptyVariant;
+
+ if (object->inherits(&JSHTMLImageElement::s_info)) {
+ JSHTMLImageElement* elementJSWrapper = static_cast<JSHTMLImageElement*>(object);
+ HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(elementJSWrapper->impl());
+
+ if (!imageElement)
+ goto returnEmptyVariant;
+
+ CachedImage* cachedImage = imageElement->cachedImage();
+ if (!cachedImage)
+ goto returnEmptyVariant;
+
+ Image* image = cachedImage->image();
+ if (!image)
+ goto returnEmptyVariant;
+
+ QPixmap* pixmap = image->nativeImageForCurrentFrame();
+ if (!pixmap)
+ goto returnEmptyVariant;
+
+ return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>()))
+ ? QVariant::fromValue<QPixmap>(*pixmap)
+ : QVariant::fromValue<QImage>(pixmap->toImage());
+ }
+
+ if (object->inherits(&QtPixmapRuntimeObject::s_info)) {
+ QtPixmapRuntimeObject* runtimeObject = static_cast<QtPixmapRuntimeObject*>(object);
+ QtPixmapInstance* instance = static_cast<QtPixmapInstance*>(runtimeObject->getInternalInstance());
+ if (!instance)
+ goto returnEmptyVariant;
+
+ if (hint == qMetaTypeId<QPixmap>())
+ return QVariant::fromValue<QPixmap>(instance->toPixmap());
+
+ if (hint == qMetaTypeId<QImage>())
+ return QVariant::fromValue<QImage>(instance->toImage());
+ }
+
+returnEmptyVariant:
+ if (hint == qMetaTypeId<QPixmap>())
+ return QVariant::fromValue<QPixmap>(QPixmap());
+ if (hint == qMetaTypeId<QImage>())
+ return QVariant::fromValue<QImage>(QImage());
+ return QVariant();
+}
+
+RuntimeObject* QtPixmapInstance::newRuntimeObject(ExecState* exec)
+{
+ return new(exec) QtPixmapRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+JSObject* QtPixmapInstance::createPixmapRuntimeObject(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& data)
+{
+ JSLock lock(SilenceAssertionsOnly);
+ RefPtr<QtPixmapInstance> instance = adoptRef(new QtPixmapInstance(root, data));
+ return instance->createRuntimeObject(exec);
+}
+
+bool QtPixmapInstance::canHandle(QMetaType::Type hint)
+{
+ return hint == qMetaTypeId<QImage>() || hint == qMetaTypeId<QPixmap>();
+}
+
+}
+
+}
diff --git a/Source/WebCore/bridge/qt/qt_pixmapruntime.h b/Source/WebCore/bridge/qt/qt_pixmapruntime.h
new file mode 100644
index 0000000..e2ae5e9
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_pixmapruntime.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 qt_pixmapruntime_h
+#define qt_pixmapruntime_h
+
+#include "Bridge.h"
+#include <QVariant>
+
+namespace JSC {
+
+namespace Bindings {
+
+class QtPixmapInstance : public Instance {
+ QVariant data;
+public:
+ QtPixmapInstance(PassRefPtr<RootObject> rootObj, const QVariant& newData);
+ virtual Class* getClass() const;
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName);
+ virtual JSValue invokeMethod(ExecState*, RuntimeMethod*);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+ virtual JSValue valueOf(ExecState* exec) const;
+ int width() const;
+ int height() const;
+ QPixmap toPixmap();
+ QImage toImage();
+ RuntimeObject* newRuntimeObject(ExecState* exec);
+ static JSObject* createPixmapRuntimeObject(ExecState*, PassRefPtr<RootObject>, const QVariant&);
+ static QVariant variantFromObject(JSObject*, QMetaType::Type hint);
+ static bool canHandle(QMetaType::Type hint);
+};
+
+}
+
+}
+#endif
diff --git a/Source/WebCore/bridge/qt/qt_runtime.cpp b/Source/WebCore/bridge/qt/qt_runtime.cpp
new file mode 100644
index 0000000..0fb811b
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_runtime.cpp
@@ -0,0 +1,1914 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "BooleanObject.h"
+#include "DateInstance.h"
+#include "DateMath.h"
+#include "DatePrototype.h"
+#include "DumpRenderTreeSupportQt.h"
+#include "FunctionPrototype.h"
+#include "Interpreter.h"
+#include "JSArray.h"
+#include "JSByteArray.h"
+#include "JSDocument.h"
+#include "JSDOMBinding.h"
+#include "JSDOMWindow.h"
+#include <JSFunction.h>
+#include "JSGlobalObject.h"
+#include "JSHTMLElement.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "RegExpConstructor.h"
+#include "RegExpObject.h"
+#include "qdatetime.h"
+#include "qdebug.h"
+#include "qmetaobject.h"
+#include "qmetatype.h"
+#include "qobject.h"
+#include "qstringlist.h"
+#include "qt_instance.h"
+#include "qt_pixmapruntime.h"
+#include "qvarlengtharray.h"
+#include "qwebelement.h"
+#include <limits.h>
+#include <runtime/Error.h>
+#include <runtime_array.h>
+#include <runtime_object.h>
+
+// QtScript has these
+Q_DECLARE_METATYPE(QObjectList);
+Q_DECLARE_METATYPE(QList<int>);
+Q_DECLARE_METATYPE(QVariant);
+
+using namespace WebCore;
+
+namespace JSC {
+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 = 0,
+ Number,
+ Boolean,
+ String,
+ Date,
+ RegExp,
+ Array,
+ QObj,
+ Object,
+ Null,
+ RTArray,
+ JSByteArray
+} JSRealType;
+
+#if defined(QTWK_RUNTIME_CONVERSION_DEBUG) || defined(QTWK_RUNTIME_MATCH_DEBUG)
+QDebug operator<<(QDebug dbg, const JSRealType &c)
+{
+ const char *map[] = { "Variant", "Number", "Boolean", "String", "Date",
+ "RegExp", "Array", "RTObject", "Object", "Null", "RTArray"};
+
+ dbg.nospace() << "JSType(" << ((int)c) << ", " << map[c] << ")";
+
+ return dbg.space();
+}
+#endif
+
+// this is here as a proxy, so we'd have a class to friend in QWebElement,
+// as getting/setting a WebCore in QWebElement is private
+class QtWebElementRuntime {
+public:
+ static QWebElement create(Element* element)
+ {
+ return QWebElement(element);
+ }
+
+ static Element* get(const QWebElement& element)
+ {
+ return element.m_element;
+ }
+};
+
+// this is here as a proxy, so we'd have a class to friend in QDRTNode,
+// as getting/setting a WebCore in QDRTNode is private.
+// We only need to pass WebCore Nodes for layout tests.
+class QtDRTNodeRuntime {
+public:
+ static QDRTNode create(Node* node)
+ {
+ return QDRTNode(node);
+ }
+
+ static Node* get(const QDRTNode& node)
+ {
+ return node.m_node;
+ }
+};
+
+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 (isJSByteArray(&exec->globalData(), val))
+ return JSByteArray;
+ else if (val.isObject()) {
+ JSObject *object = val.toObject(exec);
+ if (object->inherits(&RuntimeArray::s_info)) // RuntimeArray 'inherits' from Array, but not in C++
+ return RTArray;
+ else if (object->inherits(&JSArray::info))
+ return Array;
+ else if (object->inherits(&DateInstance::info))
+ return Date;
+ else if (object->inherits(&RegExpObject::info))
+ return RegExp;
+ else if (object->inherits(&RuntimeObject::s_info))
+ return QObj;
+ return Object;
+ }
+
+ return String; // I don't know.
+}
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance, HashSet<JSObject*>* visitedObjects, int recursionLimit)
+{
+ --recursionLimit;
+
+ if (!value || !recursionLimit)
+ return QVariant();
+
+ JSObject* object = 0;
+ if (value.isObject()) {
+ object = value.toObject(exec);
+ if (visitedObjects->contains(object))
+ return QVariant();
+
+ visitedObjects->add(object);
+ }
+
+ // check magic pointer values before dereferencing value
+ if (value == jsNaN()
+ || (value == jsUndefined()
+ && hint != QMetaType::QString
+ && hint != (QMetaType::Type) qMetaTypeId<QVariant>())) {
+ if (distance)
+ *distance = -1;
+ return QVariant();
+ }
+
+ JSLock lock(SilenceAssertionsOnly);
+ 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 Object:
+ if (object->inherits(&NumberObject::info))
+ hint = QMetaType::Double;
+ else if (object->inherits(&BooleanObject::info))
+ hint = QMetaType::Bool;
+ else
+ hint = QMetaType::QVariantMap;
+ break;
+ case QObj:
+ hint = QMetaType::QObjectStar;
+ break;
+ case JSByteArray:
+ hint = QMetaType::QByteArray;
+ break;
+ case Array:
+ case RTArray:
+ hint = QMetaType::QVariantList;
+ break;
+ }
+ }
+
+ qConvDebug() << "convertValueToQVariant: jstype is " << type << ", hint is" << hint;
+
+ if (value == jsNull()
+ && hint != QMetaType::QObjectStar
+ && hint != QMetaType::VoidStar
+ && hint != QMetaType::QString
+ && hint != (QMetaType::Type) qMetaTypeId<QVariant>()) {
+ if (distance)
+ *distance = -1;
+ return QVariant();
+ }
+
+ QVariant ret;
+ int dist = -1;
+ switch (hint) {
+ case QMetaType::Bool:
+ if (type == Object && object->inherits(&BooleanObject::info))
+ ret = QVariant(asBooleanObject(value)->internalValue().toBoolean(exec));
+ else
+ 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.length() ? *(const ushort*)str.impl()->characters() : 0));
+ if (type == String)
+ dist = 3;
+ else
+ dist = 10;
+ }
+ break;
+
+ case QMetaType::QString: {
+ if (value.isUndefinedOrNull()) {
+ if (distance)
+ *distance = 1;
+ return QString();
+ } else {
+ UString ustring = value.toString(exec);
+ ret = QVariant(QString((const QChar*)ustring.impl()->characters(), ustring.length()));
+ if (type == String)
+ dist = 0;
+ else
+ dist = 10;
+ }
+ break;
+ }
+
+ case QMetaType::QVariantMap:
+ if (type == Object || type == Array || type == RTArray) {
+ // Enumerate the contents of the object
+ PropertyNameArray properties(exec);
+ 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, visitedObjects, recursionLimit);
+ if (objdist >= 0) {
+ UString ustring = (*it).ustring();
+ QString id = QString((const QChar*)ustring.impl()->characters(), ustring.length());
+ result.insert(id, v);
+ }
+ }
+ ++it;
+ }
+ dist = 1;
+ ret = QVariant(result);
+ }
+ break;
+
+ case QMetaType::QVariantList:
+ if (type == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QVariantList result;
+ int len = rtarray->getLength();
+ int objdist = 0;
+ qConvDebug() << "converting a " << len << " length Array";
+ for (int i = 0; i < len; ++i) {
+ JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
+ result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects, recursionLimit));
+ if (objdist == -1) {
+ qConvDebug() << "Failed converting element at index " << i;
+ break; // Failed converting a list entry, so fail the array
+ }
+ }
+ if (objdist != -1) {
+ dist = 5;
+ ret = QVariant(result);
+ }
+ } else if (type == Array) {
+ JSArray* array = static_cast<JSArray*>(object);
+
+ QVariantList result;
+ int len = array->length();
+ int objdist = 0;
+ qConvDebug() << "converting a " << len << " length Array";
+ for (int i = 0; i < len; ++i) {
+ JSValue val = array->get(exec, i);
+ result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects, recursionLimit));
+ if (objdist == -1) {
+ qConvDebug() << "Failed converting element at index " << i;
+ break; // Failed converting a list entry, so fail the array
+ }
+ }
+ if (objdist != -1) {
+ dist = 5;
+ ret = QVariant(result);
+ }
+ } else {
+ // Make a single length array
+ int objdist;
+ qConvDebug() << "making a single length variantlist";
+ QVariant var = convertValueToQVariant(exec, value, QMetaType::Void, &objdist, visitedObjects, recursionLimit);
+ if (objdist != -1) {
+ QVariantList result;
+ result << var;
+ ret = QVariant(result);
+ dist = 10;
+ } else {
+ qConvDebug() << "failed making single length varlist";
+ }
+ }
+ break;
+
+ case QMetaType::QStringList: {
+ if (type == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QStringList result;
+ int len = rtarray->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
+ UString ustring = val.toString(exec);
+ QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
+
+ result.append(qstring);
+ }
+ dist = 5;
+ ret = QVariant(result);
+ } else if (type == Array) {
+ JSArray* array = static_cast<JSArray*>(object);
+
+ QStringList result;
+ int len = array->length();
+ for (int i = 0; i < len; ++i) {
+ JSValue val = array->get(exec, i);
+ UString ustring = val.toString(exec);
+ QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
+
+ result.append(qstring);
+ }
+ dist = 5;
+ ret = QVariant(result);
+ } else {
+ // Make a single length array
+ UString ustring = value.toString(exec);
+ QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
+ QStringList result;
+ result.append(qstring);
+ ret = QVariant(result);
+ dist = 10;
+ }
+ break;
+ }
+
+ case QMetaType::QByteArray: {
+ if (type == JSByteArray) {
+ WTF::ByteArray* arr = asByteArray(value)->storage();
+ ret = QVariant(QByteArray(reinterpret_cast<const char*>(arr->data()), arr->length()));
+ dist = 0;
+ } else {
+ UString ustring = value.toString(exec);
+ ret = QVariant(QString((const QChar*)ustring.impl()->characters(), ustring.length()).toLatin1());
+ if (type == String)
+ dist = 5;
+ else
+ dist = 10;
+ }
+ break;
+ }
+
+ case QMetaType::QDateTime:
+ case QMetaType::QDate:
+ case QMetaType::QTime:
+ if (type == Date) {
+ DateInstance* date = static_cast<DateInstance*>(object);
+ GregorianDateTime gdt;
+ msToGregorianDateTime(exec, date->internalNumber(), 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 = 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(exec, 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;
+ }
+#ifndef QT_NO_DATESTRING
+ } else if (type == String) {
+ UString ustring = value.toString(exec);
+ QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
+
+ 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;
+ }
+ }
+#endif // QT_NO_DATESTRING
+ }
+ break;
+
+ case QMetaType::QRegExp:
+ if (type == RegExp) {
+/*
+ RegExpObject *re = static_cast<RegExpObject*>(object);
+*/
+ // Attempt to convert.. a bit risky
+ UString ustring = value.toString(exec);
+ QString qstring = QString((const QChar*)ustring.impl()->characters(), ustring.length());
+
+ // this is of the form '/xxxxxx/i'
+ int firstSlash = qstring.indexOf(QLatin1Char('/'));
+ int lastSlash = qstring.lastIndexOf(QLatin1Char('/'));
+ if (firstSlash >=0 && lastSlash > firstSlash) {
+ QRegExp realRe;
+
+ realRe.setPattern(qstring.mid(firstSlash + 1, lastSlash - firstSlash - 1));
+
+ if (qstring.mid(lastSlash + 1).contains(QLatin1Char('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((const QChar*)ustring.impl()->characters(), ustring.length());
+
+ QRegExp re(qstring);
+ if (re.isValid()) {
+ ret = qVariantFromValue(re);
+ dist = 10;
+ }
+ }
+ break;
+
+ case QMetaType::QObjectStar:
+ if (type == QObj) {
+ QtInstance* qtinst = QtInstance::getInstance(object);
+ 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) {
+ QtInstance* qtinst = QtInstance::getInstance(object);
+ 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 == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QObjectList result;
+ int len = rtarray->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects, recursionLimit);
+ 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 if (type == Array) {
+ JSObject* object = value.toObject(exec);
+ JSArray* array = static_cast<JSArray *>(object);
+ QObjectList result;
+ int len = array->length();
+ for (int i = 0; i < len; ++i) {
+ JSValue val = array->get(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects, recursionLimit);
+ 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 {
+ // Make a single length array
+ QObjectList result;
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist, visitedObjects, recursionLimit);
+ 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 == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QList<int> result;
+ int len = rtarray->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects, recursionLimit);
+ 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 if (type == Array) {
+ JSArray* array = static_cast<JSArray *>(object);
+
+ QList<int> result;
+ int len = array->length();
+ for (int i = 0; i < len; ++i) {
+ JSValue val = array->get(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects, recursionLimit);
+ 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 {
+ // Make a single length array
+ QList<int> result;
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist, visitedObjects, recursionLimit);
+ if (itemdist >= 0) {
+ result.append(item.value<int>());
+ dist = 10;
+ ret = QVariant::fromValue(result);
+ }
+ }
+ break;
+ } else if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(hint))) {
+ ret = QtPixmapInstance::variantFromObject(object, static_cast<QMetaType::Type>(hint));
+ } else if (hint == (QMetaType::Type) qMetaTypeId<QWebElement>()) {
+ if (object && object->inherits(&JSHTMLElement::s_info))
+ ret = QVariant::fromValue<QWebElement>(QtWebElementRuntime::create((static_cast<JSHTMLElement*>(object))->impl()));
+ else if (object && object->inherits(&JSDocument::s_info))
+ ret = QVariant::fromValue<QWebElement>(QtWebElementRuntime::create((static_cast<JSDocument*>(object))->impl()->documentElement()));
+ else
+ ret = QVariant::fromValue<QWebElement>(QWebElement());
+ } else if (hint == (QMetaType::Type) qMetaTypeId<QDRTNode>()) {
+ if (object && object->inherits(&JSNode::s_info))
+ ret = QVariant::fromValue<QDRTNode>(QtDRTNodeRuntime::create((static_cast<JSNode*>(object))->impl()));
+ } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) {
+ if (value.isUndefinedOrNull()) {
+ if (distance)
+ *distance = 1;
+ return QVariant();
+ } else {
+ if (type == Object) {
+ // Since we haven't really visited this object yet, we remove it
+ visitedObjects->remove(object);
+ }
+
+ // And then recurse with the autodetect flag
+ ret = convertValueToQVariant(exec, value, QMetaType::Void, distance, visitedObjects, recursionLimit);
+ dist = 10;
+ }
+ break;
+ }
+
+ dist = 10;
+ break;
+ }
+
+ if (!ret.isValid())
+ dist = -1;
+ if (distance)
+ *distance = dist;
+
+ return ret;
+}
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance)
+{
+ const int recursionLimit = 200;
+ HashSet<JSObject*> visitedObjects;
+ return convertValueToQVariant(exec, value, hint, distance, &visitedObjects, recursionLimit);
+}
+
+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();
+
+ qConvDebug() << "convertQVariantToValue: metatype:" << type << ", isnull: " << variant.isNull();
+ if (variant.isNull() &&
+ type != QMetaType::QObjectStar &&
+ type != QMetaType::VoidStar &&
+ type != QMetaType::QWidgetStar &&
+ type != QMetaType::QString) {
+ return jsNull();
+ }
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ 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()) {
+ UString uflags;
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ uflags = "i"; // ### Can't do g or m
+
+ UString pattern((UChar*)re.pattern().utf16(), re.pattern().length());
+
+ RefPtr<JSC::RegExp> regExp = JSC::RegExp::create(&exec->globalData(), pattern, uflags);
+ if (regExp->isValid())
+ return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
+ else
+ return jsNull();
+ }
+ }
+
+ if (type == QMetaType::QDateTime ||
+ type == QMetaType::QDate ||
+ type == QMetaType::QTime) {
+
+ 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)
+ GregorianDateTime dt;
+ dt.year = date.year() - 1900;
+ dt.month = date.month() - 1;
+ dt.monthDay = date.day();
+ dt.hour = time.hour();
+ dt.minute = time.minute();
+ dt.second = time.second();
+ dt.isDST = -1;
+ double ms = gregorianDateTimeToMS(exec, dt, time.msec(), /*inputIsUTC*/ false);
+
+ return new (exec) DateInstance(exec, trunc(ms));
+ }
+
+ if (type == QMetaType::QByteArray) {
+ QByteArray qtByteArray = variant.value<QByteArray>();
+ WTF::RefPtr<WTF::ByteArray> wtfByteArray = WTF::ByteArray::create(qtByteArray.length());
+ memcpy(wtfByteArray->data(), qtByteArray.constData(), qtByteArray.length());
+ return new (exec) JSC::JSByteArray(exec, JSC::JSByteArray::createStructure(jsNull()), wtfByteArray.get());
+ }
+
+ if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
+ QObject* obj = variant.value<QObject*>();
+ if (!obj)
+ return jsNull();
+ return QtInstance::getQtInstance(obj, root, QScriptEngine::QtOwnership)->createRuntimeObject(exec);
+ }
+
+ if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type())))
+ return QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant);
+
+ if (type == qMetaTypeId<QWebElement>()) {
+ if (!root->globalObject()->inherits(&JSDOMWindow::s_info))
+ return jsUndefined();
+
+ Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document();
+ if (!document)
+ return jsUndefined();
+
+ return toJS(exec, toJSDOMGlobalObject(document, exec), QtWebElementRuntime::get(variant.value<QWebElement>()));
+ }
+
+ if (type == qMetaTypeId<QDRTNode>()) {
+ if (!root->globalObject()->inherits(&JSDOMWindow::s_info))
+ return jsUndefined();
+
+ Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document();
+ if (!document)
+ return jsUndefined();
+
+ return toJS(exec, toJSDOMGlobalObject(document, exec), QtDRTNodeRuntime::get(variant.value<QDRTNode>()));
+ }
+
+ if (type == QMetaType::QVariantMap) {
+ // create a new object, and stuff properties into it
+ JSObject* ret = constructEmptyObject(exec);
+ QVariantMap map = variant.value<QVariantMap>();
+ QVariantMap::const_iterator i = map.constBegin();
+ while (i != map.constEnd()) {
+ QString s = i.key();
+ JSValue val = convertQVariantToValue(exec, root.get(), i.value());
+ if (val) {
+ PutPropertySlot slot;
+ ret->put(exec, Identifier(exec, reinterpret_cast_ptr<const UChar *>(s.constData()), s.length()), val, slot);
+ // ### error case?
+ }
+ ++i;
+ }
+
+ return ret;
+ }
+
+ // List types
+ if (type == QMetaType::QVariantList) {
+ QVariantList vl = variant.toList();
+ qConvDebug() << "got a " << vl.count() << " length list:" << vl;
+ return new (exec) RuntimeArray(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
+ } else if (type == QMetaType::QStringList) {
+ QStringList sl = variant.value<QStringList>();
+ return new (exec) RuntimeArray(exec, new QtArray<QString>(sl, QMetaType::QString, root));
+ } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
+ QObjectList ol= variant.value<QObjectList>();
+ return new (exec) 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 (exec) 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((UChar*)string.utf16(), string.length());
+ return jsString(exec, ustring);
+}
+
+// ===============
+
+// Qt-like macros
+#define QW_D(Class) Class##Data* d = d_func()
+#define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()
+
+const ClassInfo QtRuntimeMethod::s_info = { "QtRuntimeMethod", 0, 0, 0 };
+
+QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst)
+ : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject(), deprecatedGetDOMStructure<QtRuntimeMethod>(exec), ident)
+ , d_ptr(dd)
+{
+ QW_D(QtRuntimeMethod);
+ d->m_instance = inst;
+}
+
+QtRuntimeMethod::~QtRuntimeMethod()
+{
+ QW_D(QtRuntimeMethod);
+ d->m_instance->removeCachedMethod(this);
+ delete d_ptr;
+}
+
+// ===============
+
+QtRuntimeMethodData::~QtRuntimeMethodData()
+{
+}
+
+QtRuntimeMetaMethodData::~QtRuntimeMetaMethodData()
+{
+
+}
+
+QtRuntimeConnectionMethodData::~QtRuntimeConnectionMethodData()
+{
+
+}
+
+// ===============
+
+// Type conversion metadata (from QtScript originally)
+class QtMethodMatchType
+{
+public:
+ enum Kind {
+ Invalid,
+ Variant,
+ MetaType,
+ Unresolved,
+ MetaEnum
+ };
+
+
+ QtMethodMatchType()
+ : m_kind(Invalid) { }
+
+ Kind kind() const
+ { return m_kind; }
+
+ QMetaType::Type typeId() const;
+
+ bool isValid() const
+ { return (m_kind != Invalid); }
+
+ bool isVariant() const
+ { return (m_kind == Variant); }
+
+ bool isMetaType() const
+ { return (m_kind == MetaType); }
+
+ bool isUnresolved() const
+ { return (m_kind == Unresolved); }
+
+ bool isMetaEnum() const
+ { return (m_kind == MetaEnum); }
+
+ QByteArray name() const;
+
+ int enumeratorIndex() const
+ { Q_ASSERT(isMetaEnum()); return m_typeId; }
+
+ static QtMethodMatchType variant()
+ { return QtMethodMatchType(Variant); }
+
+ static QtMethodMatchType metaType(int typeId, const QByteArray &name)
+ { return QtMethodMatchType(MetaType, typeId, name); }
+
+ static QtMethodMatchType metaEnum(int enumIndex, const QByteArray &name)
+ { return QtMethodMatchType(MetaEnum, enumIndex, name); }
+
+ static QtMethodMatchType unresolved(const QByteArray &name)
+ { return QtMethodMatchType(Unresolved, /*typeId=*/0, name); }
+
+private:
+ QtMethodMatchType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray())
+ : m_kind(kind), m_typeId(typeId), m_name(name) { }
+
+ Kind m_kind;
+ int m_typeId;
+ QByteArray m_name;
+};
+
+QMetaType::Type QtMethodMatchType::typeId() const
+{
+ if (isVariant())
+ return (QMetaType::Type) QMetaType::type("QVariant");
+ return (QMetaType::Type) (isMetaEnum() ? QMetaType::Int : m_typeId);
+}
+
+QByteArray QtMethodMatchType::name() const
+{
+ if (!m_name.isEmpty())
+ return m_name;
+ else if (m_kind == Variant)
+ return "QVariant";
+ return QByteArray();
+}
+
+struct QtMethodMatchData
+{
+ int matchDistance;
+ int index;
+ QVector<QtMethodMatchType> types;
+ QVarLengthArray<QVariant, 10> args;
+
+ QtMethodMatchData(int dist, int idx, QVector<QtMethodMatchType> typs,
+ const QVarLengthArray<QVariant, 10> &as)
+ : matchDistance(dist), index(idx), types(typs), args(as) { }
+ QtMethodMatchData()
+ : index(-1) { }
+
+ bool isValid() const
+ { return (index != -1); }
+
+ int firstUnresolvedIndex() const
+ {
+ for (int i=0; i < types.count(); i++) {
+ if (types.at(i).isUnresolved())
+ return i;
+ }
+ return -1;
+ }
+};
+
+static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str)
+{
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = str.indexOf("::");
+ if (scopeIdx != -1) {
+ scope = str.left(scopeIdx);
+ name = str.mid(scopeIdx + 2);
+ } else {
+ name = str;
+ }
+ for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = meta->enumerator(i);
+ if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/)
+ return i;
+ }
+ return -1;
+}
+
+// Helper function for resolving methods
+// Largely based on code in QtScript for compatibility reasons
+static int findMethodIndex(ExecState* exec,
+ const QMetaObject* meta,
+ const QByteArray& signature,
+ bool allowPrivate,
+ QVarLengthArray<QVariant, 10> &vars,
+ void** vvars,
+ JSObject **pError)
+{
+ QList<int> matchingIndices;
+
+ bool overloads = !signature.contains('(');
+
+ int count = meta->methodCount();
+ for (int i = count - 1; i >= 0; --i) {
+ const QMetaMethod m = meta->method(i);
+
+ // Don't choose private methods
+ if (m.access() == QMetaMethod::Private && !allowPrivate)
+ continue;
+
+ // try and find all matching named methods
+ if (m.signature() == signature)
+ matchingIndices.append(i);
+ else if (overloads) {
+ QByteArray rawsignature = m.signature();
+ rawsignature.truncate(rawsignature.indexOf('('));
+ if (rawsignature == signature)
+ matchingIndices.append(i);
+ }
+ }
+
+ int chosenIndex = -1;
+ *pError = 0;
+ QVector<QtMethodMatchType> chosenTypes;
+
+ QVarLengthArray<QVariant, 10> args;
+ QVector<QtMethodMatchData> candidates;
+ QVector<QtMethodMatchData> unresolved;
+ QVector<int> tooFewArgs;
+ QVector<int> conversionFailed;
+
+ foreach(int index, matchingIndices) {
+ QMetaMethod method = meta->method(index);
+
+ QVector<QtMethodMatchType> types;
+ bool unresolvedTypes = false;
+
+ // resolve return type
+ QByteArray returnTypeName = method.typeName();
+ int rtype = QMetaType::type(returnTypeName);
+ if ((rtype == 0) && !returnTypeName.isEmpty()) {
+ if (returnTypeName == "QVariant") {
+ types.append(QtMethodMatchType::variant());
+ } else if (returnTypeName.endsWith('*')) {
+ types.append(QtMethodMatchType::metaType(QMetaType::VoidStar, returnTypeName));
+ } else {
+ int enumIndex = indexOfMetaEnum(meta, returnTypeName);
+ if (enumIndex != -1)
+ types.append(QtMethodMatchType::metaEnum(enumIndex, returnTypeName));
+ else {
+ unresolvedTypes = true;
+ types.append(QtMethodMatchType::unresolved(returnTypeName));
+ }
+ }
+ } else {
+ if (returnTypeName == "QVariant")
+ types.append(QtMethodMatchType::variant());
+ else
+ types.append(QtMethodMatchType::metaType(rtype, returnTypeName));
+ }
+
+ // resolve argument types
+ QList<QByteArray> parameterTypeNames = method.parameterTypes();
+ for (int i = 0; i < parameterTypeNames.count(); ++i) {
+ QByteArray argTypeName = parameterTypeNames.at(i);
+ int atype = QMetaType::type(argTypeName);
+ if (atype == 0) {
+ if (argTypeName == "QVariant") {
+ types.append(QtMethodMatchType::variant());
+ } else {
+ int enumIndex = indexOfMetaEnum(meta, argTypeName);
+ if (enumIndex != -1)
+ types.append(QtMethodMatchType::metaEnum(enumIndex, argTypeName));
+ else {
+ unresolvedTypes = true;
+ types.append(QtMethodMatchType::unresolved(argTypeName));
+ }
+ }
+ } else {
+ if (argTypeName == "QVariant")
+ types.append(QtMethodMatchType::variant());
+ else
+ types.append(QtMethodMatchType::metaType(atype, argTypeName));
+ }
+ }
+
+ // If the native method requires more arguments than what was passed from JavaScript
+ if (exec->argumentCount() + 1 < static_cast<unsigned>(types.count())) {
+ qMatchDebug() << "Match:too few args for" << method.signature();
+ tooFewArgs.append(index);
+ continue;
+ }
+
+ if (unresolvedTypes) {
+ qMatchDebug() << "Match:unresolved arg types for" << method.signature();
+ // remember it so we can give an error message later, if necessary
+ unresolved.append(QtMethodMatchData(/*matchDistance=*/INT_MAX, index,
+ types, QVarLengthArray<QVariant, 10>()));
+ continue;
+ }
+
+ // Now convert arguments
+ if (args.count() != types.count())
+ args.resize(types.count());
+
+ QtMethodMatchType retType = types[0];
+ args[0] = QVariant(retType.typeId(), (void *)0); // the return value
+
+ bool converted = true;
+ int matchDistance = 0;
+ for (unsigned i = 0; converted && i + 1 < static_cast<unsigned>(types.count()); ++i) {
+ JSValue arg = i < exec->argumentCount() ? exec->argument(i) : jsUndefined();
+
+ int argdistance = -1;
+ QVariant v = convertValueToQVariant(exec, arg, types.at(i+1).typeId(), &argdistance);
+ if (argdistance >= 0) {
+ matchDistance += argdistance;
+ args[i+1] = v;
+ } else {
+ qMatchDebug() << "failed to convert argument " << i << "type" << types.at(i+1).typeId() << QMetaType::typeName(types.at(i+1).typeId());
+ converted = false;
+ }
+ }
+
+ qMatchDebug() << "Match: " << method.signature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance;
+
+ if (converted) {
+ if ((exec->argumentCount() + 1 == static_cast<unsigned>(types.count()))
+ && (matchDistance == 0)) {
+ // perfect match, use this one
+ chosenIndex = index;
+ break;
+ } else {
+ QtMethodMatchData currentMatch(matchDistance, index, types, args);
+ if (candidates.isEmpty()) {
+ candidates.append(currentMatch);
+ } else {
+ QtMethodMatchData bestMatchSoFar = candidates.at(0);
+ if ((args.count() > bestMatchSoFar.args.count())
+ || ((args.count() == bestMatchSoFar.args.count())
+ && (matchDistance <= bestMatchSoFar.matchDistance))) {
+ candidates.prepend(currentMatch);
+ } else {
+ candidates.append(currentMatch);
+ }
+ }
+ }
+ } else {
+ conversionFailed.append(index);
+ }
+
+ if (!overloads)
+ break;
+ }
+
+ if (chosenIndex == -1 && candidates.count() == 0) {
+ // No valid functions at all - format an error message
+ if (!conversionFailed.isEmpty()) {
+ QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
+ .arg(QLatin1String(signature));
+ for (int i = 0; i < conversionFailed.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = meta->method(conversionFailed.at(i));
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ *pError = throwError(exec, createTypeError(exec, message.toLatin1().constData()));
+ } else if (!unresolved.isEmpty()) {
+ QtMethodMatchData argsInstance = unresolved.first();
+ int unresolvedIndex = argsInstance.firstUnresolvedIndex();
+ Q_ASSERT(unresolvedIndex != -1);
+ QtMethodMatchType unresolvedType = argsInstance.types.at(unresolvedIndex);
+ QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'")
+ .arg(QString::fromLatin1(signature))
+ .arg(QLatin1String(unresolvedType.name()));
+ *pError = throwError(exec, createTypeError(exec, message.toLatin1().constData()));
+ } else {
+ QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
+ .arg(QLatin1String(signature));
+ for (int i = 0; i < tooFewArgs.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = meta->method(tooFewArgs.at(i));
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ *pError = throwError(exec, createSyntaxError(exec, message.toLatin1().constData()));
+ }
+ }
+
+ if (chosenIndex == -1 && candidates.count() > 0) {
+ QtMethodMatchData bestMatch = candidates.at(0);
+ if ((candidates.size() > 1)
+ && (bestMatch.args.count() == candidates.at(1).args.count())
+ && (bestMatch.matchDistance == candidates.at(1).matchDistance)) {
+ // ambiguous call
+ QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
+ .arg(QLatin1String(signature));
+ for (int i = 0; i < candidates.size(); ++i) {
+ // Only candidate for overload if argument count and match distance is same as best match
+ if (candidates.at(i).args.count() == bestMatch.args.count()
+ || candidates.at(i).matchDistance == bestMatch.matchDistance) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = meta->method(candidates.at(i).index);
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ }
+ *pError = throwError(exec, createTypeError(exec, message.toLatin1().constData()));
+ } else {
+ chosenIndex = bestMatch.index;
+ args = bestMatch.args;
+ }
+ }
+
+ if (chosenIndex != -1) {
+ /* Copy the stuff over */
+ int i;
+ vars.resize(args.count());
+ for (i=0; i < args.count(); i++) {
+ vars[i] = args[i];
+ vvars[i] = vars[i].data();
+ }
+ }
+
+ return chosenIndex;
+}
+
+// Signals are not fuzzy matched as much as methods
+static int findSignalIndex(const QMetaObject* meta, int initialIndex, QByteArray signature)
+{
+ int index = initialIndex;
+ QMetaMethod method = meta->method(index);
+ bool overloads = !signature.contains('(');
+ if (overloads && (method.attributes() & QMetaMethod::Cloned)) {
+ // find the most general method
+ do {
+ method = meta->method(--index);
+ } while (method.attributes() & QMetaMethod::Cloned);
+ }
+ return index;
+}
+
+QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate)
+ : QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, ident, inst)
+{
+ QW_D(QtRuntimeMetaMethod);
+ d->m_signature = signature;
+ d->m_index = index;
+ d->m_connect = 0;
+ d->m_disconnect = 0;
+ d->m_allowPrivate = allowPrivate;
+}
+
+void QtRuntimeMetaMethod::markChildren(MarkStack& markStack)
+{
+ QtRuntimeMethod::markChildren(markStack);
+ QW_D(QtRuntimeMetaMethod);
+ if (d->m_connect)
+ markStack.append(d->m_connect);
+ if (d->m_disconnect)
+ markStack.append(d->m_disconnect);
+}
+
+EncodedJSValue QtRuntimeMetaMethod::call(ExecState* exec)
+{
+ QtRuntimeMetaMethodData* d = static_cast<QtRuntimeMetaMethod *>(exec->callee())->d_func();
+
+ // We're limited to 10 args
+ if (exec->argumentCount() > 10)
+ return JSValue::encode(jsUndefined());
+
+ // We have to pick a method that matches..
+ JSLock lock(SilenceAssertionsOnly);
+
+ QObject *obj = d->m_instance->getObject();
+ if (obj) {
+ QVarLengthArray<QVariant, 10> vargs;
+ void *qargs[11];
+
+ int methodIndex;
+ JSObject* errorObj = 0;
+ if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, d->m_allowPrivate, vargs, (void **)qargs, &errorObj)) != -1) {
+ if (QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0)
+ return JSValue::encode(jsUndefined());
+
+ if (vargs[0].isValid())
+ return JSValue::encode(convertQVariantToValue(exec, d->m_instance->rootObject(), vargs[0]));
+ }
+
+ if (errorObj)
+ return JSValue::encode(errorObj);
+ } else {
+ return throwVMError(exec, createError(exec, "cannot call function of deleted QObject"));
+ }
+
+ // void functions return undefined
+ return JSValue::encode(jsUndefined());
+}
+
+CallType QtRuntimeMetaMethod::getCallData(CallData& callData)
+{
+ callData.native.function = call;
+ return CallTypeHost;
+}
+
+bool QtRuntimeMetaMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == "connect") {
+ slot.setCustom(this, connectGetter);
+ return true;
+ } else if (propertyName == "disconnect") {
+ slot.setCustom(this, disconnectGetter);
+ return true;
+ } else if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool QtRuntimeMetaMethod::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (propertyName == "connect") {
+ PropertySlot slot;
+ slot.setCustom(this, connectGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
+ return true;
+ }
+
+ if (propertyName == "disconnect") {
+ PropertySlot slot;
+ slot.setCustom(this, disconnectGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ PropertySlot slot;
+ slot.setCustom(this, lengthGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
+ return true;
+ }
+
+ return QtRuntimeMethod::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void QtRuntimeMetaMethod::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ if (mode == IncludeDontEnumProperties) {
+ propertyNames.add(Identifier(exec, "connect"));
+ propertyNames.add(Identifier(exec, "disconnect"));
+ propertyNames.add(exec->propertyNames().length);
+ }
+
+ QtRuntimeMethod::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+JSValue QtRuntimeMetaMethod::lengthGetter(ExecState*, JSValue, const Identifier&)
+{
+ // QtScript always returns 0
+ return jsNumber(0);
+}
+
+JSValue QtRuntimeMetaMethod::connectGetter(ExecState* exec, JSValue slotBase, const Identifier& ident)
+{
+ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slotBase));
+ QW_DS(QtRuntimeMetaMethod, thisObj);
+
+ if (!d->m_connect)
+ d->m_connect = new (exec) QtRuntimeConnectionMethod(exec, ident, true, d->m_instance, d->m_index, d->m_signature);
+ return d->m_connect;
+}
+
+JSValue QtRuntimeMetaMethod::disconnectGetter(ExecState* exec, JSValue slotBase, const Identifier& ident)
+{
+ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slotBase));
+ QW_DS(QtRuntimeMetaMethod, thisObj);
+
+ if (!d->m_disconnect)
+ d->m_disconnect = new (exec) QtRuntimeConnectionMethod(exec, ident, false, d->m_instance, d->m_index, d->m_signature);
+ return d->m_disconnect;
+}
+
+// ===============
+
+QMultiMap<QObject*, QtConnectionObject*> QtRuntimeConnectionMethod::connections;
+
+QtRuntimeConnectionMethod::QtRuntimeConnectionMethod(ExecState* exec, const Identifier& ident, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature)
+ : QtRuntimeMethod (new QtRuntimeConnectionMethodData(), exec, ident, inst)
+{
+ QW_D(QtRuntimeConnectionMethod);
+
+ d->m_signature = signature;
+ d->m_index = index;
+ d->m_isConnect = isConnect;
+}
+
+EncodedJSValue QtRuntimeConnectionMethod::call(ExecState* exec)
+{
+ QtRuntimeConnectionMethodData* d = static_cast<QtRuntimeConnectionMethod *>(exec->callee())->d_func();
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ QObject* sender = d->m_instance->getObject();
+
+ if (sender) {
+
+ JSObject* thisObject = exec->lexicalGlobalObject();
+ JSObject* funcObject = 0;
+
+ // QtScript checks signalness first, arguments second
+ int signalIndex = -1;
+
+ // Make sure the initial index is a signal
+ QMetaMethod m = sender->metaObject()->method(d->m_index);
+ if (m.methodType() == QMetaMethod::Signal)
+ signalIndex = findSignalIndex(sender->metaObject(), d->m_index, d->m_signature);
+
+ if (signalIndex != -1) {
+ if (exec->argumentCount() == 1) {
+ funcObject = exec->argument(0).toObject(exec);
+ CallData callData;
+ if (funcObject->getCallData(callData) == CallTypeNone) {
+ if (d->m_isConnect)
+ return throwVMError(exec, createTypeError(exec, "QtMetaMethod.connect: target is not a function"));
+ else
+ return throwVMError(exec, createTypeError(exec, "QtMetaMethod.disconnect: target is not a function"));
+ }
+ } else if (exec->argumentCount() >= 2) {
+ if (exec->argument(0).isObject()) {
+ thisObject = exec->argument(0).toObject(exec);
+
+ // Get the actual function to call
+ JSObject *asObj = exec->argument(1).toObject(exec);
+ CallData callData;
+ if (asObj->getCallData(callData) != CallTypeNone) {
+ // Function version
+ funcObject = asObj;
+ } else {
+ // Convert it to a string
+ UString funcName = exec->argument(1).toString(exec);
+ Identifier funcIdent(exec, funcName);
+
+ // ### DropAllLocks
+ // This is resolved at this point in QtScript
+ JSValue val = thisObject->get(exec, funcIdent);
+ JSObject* asFuncObj = val.toObject(exec);
+
+ if (asFuncObj->getCallData(callData) != CallTypeNone) {
+ funcObject = asFuncObj;
+ } else {
+ if (d->m_isConnect)
+ return throwVMError(exec, createTypeError(exec, "QtMetaMethod.connect: target is not a function"));
+ else
+ return throwVMError(exec, createTypeError(exec, "QtMetaMethod.disconnect: target is not a function"));
+ }
+ }
+ } else {
+ if (d->m_isConnect)
+ return throwVMError(exec, createTypeError(exec, "QtMetaMethod.connect: thisObject is not an object"));
+ else
+ return throwVMError(exec, createTypeError(exec, "QtMetaMethod.disconnect: thisObject is not an object"));
+ }
+ } else {
+ if (d->m_isConnect)
+ return throwVMError(exec, createError(exec, "QtMetaMethod.connect: no arguments given"));
+ else
+ return throwVMError(exec, createError(exec, "QtMetaMethod.disconnect: no arguments given"));
+ }
+
+ if (d->m_isConnect) {
+ // to connect, we need:
+ // target object [from ctor]
+ // target signal index etc. [from ctor]
+ // receiver function [from arguments]
+ // receiver this object [from arguments]
+
+ QtConnectionObject* conn = new QtConnectionObject(d->m_instance, signalIndex, thisObject, funcObject);
+ bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
+ if (!ok) {
+ delete conn;
+ QString msg = QString(QLatin1String("QtMetaMethod.connect: failed to connect to %1::%2()"))
+ .arg(QLatin1String(sender->metaObject()->className()))
+ .arg(QLatin1String(d->m_signature));
+ return throwVMError(exec, createError(exec, msg.toLatin1().constData()));
+ }
+ else {
+ // Store connection
+ connections.insert(sender, conn);
+ }
+ } else {
+ // Now to find our previous connection object. Hmm.
+ QList<QtConnectionObject*> conns = connections.values(sender);
+ bool ret = false;
+
+ foreach(QtConnectionObject* conn, conns) {
+ // Is this the right connection?
+ if (conn->match(sender, signalIndex, thisObject, funcObject)) {
+ // Yep, disconnect it
+ QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
+ delete conn; // this will also remove it from the map
+ ret = true;
+ break;
+ }
+ }
+
+ if (!ret) {
+ QString msg = QString(QLatin1String("QtMetaMethod.disconnect: failed to disconnect from %1::%2()"))
+ .arg(QLatin1String(sender->metaObject()->className()))
+ .arg(QLatin1String(d->m_signature));
+ return throwVMError(exec, createError(exec, msg.toLatin1().constData()));
+ }
+ }
+ } else {
+ QString msg = QString(QLatin1String("QtMetaMethod.%1: %2::%3() is not a signal"))
+ .arg(QLatin1String(d->m_isConnect ? "connect": "disconnect"))
+ .arg(QLatin1String(sender->metaObject()->className()))
+ .arg(QLatin1String(d->m_signature));
+ return throwVMError(exec, createTypeError(exec, msg.toLatin1().constData()));
+ }
+ } else {
+ return throwVMError(exec, createError(exec, "cannot call function of deleted QObject"));
+ }
+
+ return JSValue::encode(jsUndefined());
+}
+
+CallType QtRuntimeConnectionMethod::getCallData(CallData& callData)
+{
+ callData.native.function = call;
+ return CallTypeHost;
+}
+
+bool QtRuntimeConnectionMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool QtRuntimeConnectionMethod::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (propertyName == exec->propertyNames().length) {
+ PropertySlot slot;
+ slot.setCustom(this, lengthGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
+ return true;
+ }
+
+ return QtRuntimeMethod::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void QtRuntimeConnectionMethod::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ if (mode == IncludeDontEnumProperties)
+ propertyNames.add(exec->propertyNames().length);
+
+ QtRuntimeMethod::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+JSValue QtRuntimeConnectionMethod::lengthGetter(ExecState*, JSValue, const Identifier&)
+{
+ // we have one formal argument, and one optional
+ return jsNumber(1);
+}
+
+// ===============
+
+QtConnectionObject::QtConnectionObject(PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject)
+ : m_instance(instance)
+ , m_signalIndex(signalIndex)
+ , m_originalObject(m_instance->getObject())
+ , m_thisObject(thisObject)
+ , m_funcObject(funcObject)
+{
+ setParent(m_originalObject);
+ ASSERT(JSLock::currentThreadIsHoldingLock()); // so our ProtectedPtrs are safe
+}
+
+QtConnectionObject::~QtConnectionObject()
+{
+ // Remove us from the map of active connections
+ QtRuntimeConnectionMethod::connections.remove(m_originalObject, this);
+}
+
+static const uint qt_meta_data_QtConnectionObject[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 10, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ // slots: signature, parameters, type, tag, flags
+ 28, 27, 27, 27, 0x0a,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QtConnectionObject[] = {
+ "JSC::Bindings::QtConnectionObject\0\0execute()\0"
+};
+
+const QMetaObject QtConnectionObject::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QtConnectionObject,
+ qt_meta_data_QtConnectionObject, 0 }
+};
+
+const QMetaObject *QtConnectionObject::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *QtConnectionObject::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_QtConnectionObject))
+ return static_cast<void*>(const_cast<QtConnectionObject*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int QtConnectionObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: execute(_a); break;
+ }
+ _id -= 1;
+ }
+ return _id;
+}
+
+void QtConnectionObject::execute(void **argv)
+{
+ QObject* obj = m_instance->getObject();
+ if (obj) {
+ const QMetaObject* meta = obj->metaObject();
+ const QMetaMethod method = meta->method(m_signalIndex);
+
+ QList<QByteArray> parameterTypes = method.parameterTypes();
+
+ int argc = parameterTypes.count();
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ // ### Should the Interpreter/ExecState come from somewhere else?
+ RefPtr<RootObject> ro = m_instance->rootObject();
+ if (ro) {
+ JSGlobalObject* globalobj = ro->globalObject();
+ if (globalobj) {
+ ExecState* exec = globalobj->globalExec();
+ if (exec) {
+ // Build the argument list (up to the formal argument length of the slot)
+ MarkedArgumentBuffer l;
+ // ### DropAllLocks?
+ int funcArgC = m_funcObject->get(exec, exec->propertyNames().length).toInt32(exec);
+ int argTotal = qMax(funcArgC, argc);
+ for(int i=0; i < argTotal; i++) {
+ if (i < argc) {
+ int argType = QMetaType::type(parameterTypes.at(i));
+ l.append(convertQVariantToValue(exec, ro, QVariant(argType, argv[i+1])));
+ } else {
+ l.append(jsUndefined());
+ }
+ }
+ // Stuff in the __qt_sender property, if we can
+ ScopeChain oldsc = ScopeChain(NoScopeChain());
+ JSFunction* fimp = 0;
+ if (m_funcObject->inherits(&JSFunction::info)) {
+ fimp = static_cast<JSFunction*>(m_funcObject.get());
+
+ JSObject* qt_sender = QtInstance::getQtInstance(sender(), ro, QScriptEngine::QtOwnership)->createRuntimeObject(exec);
+ JSObject* wrapper = new (exec) JSObject(JSObject::createStructure(jsNull()));
+ PutPropertySlot slot;
+ wrapper->put(exec, Identifier(exec, "__qt_sender__"), qt_sender, slot);
+ oldsc = fimp->scope();
+ ScopeChain sc = oldsc;
+ sc.push(wrapper);
+ fimp->setScope(sc);
+ }
+
+ CallData callData;
+ CallType callType = m_funcObject->getCallData(callData);
+ call(exec, m_funcObject, callType, callData, m_thisObject, l);
+
+ if (fimp)
+ fimp->setScope(oldsc);
+ }
+ }
+ }
+ } else {
+ // A strange place to be - a deleted object emitted a signal here.
+ qWarning() << "sender deleted, cannot deliver signal";
+ }
+}
+
+bool QtConnectionObject::match(QObject* sender, int signalIndex, JSObject* thisObject, JSObject *funcObject)
+{
+ if (m_originalObject == sender && m_signalIndex == signalIndex
+ && thisObject == (JSObject*)m_thisObject && funcObject == (JSObject*)m_funcObject)
+ return true;
+ return false;
+}
+
+// ===============
+
+template <typename T> QtArray<T>::QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject> rootObject)
+ : Array(rootObject)
+ , m_list(list)
+ , m_type(type)
+{
+ m_length = m_list.count();
+}
+
+template <typename T> QtArray<T>::~QtArray ()
+{
+}
+
+template <typename T> RootObject* QtArray<T>::rootObject() const
+{
+ return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
+}
+
+template <typename T> void QtArray<T>::setValueAt(ExecState* exec, unsigned index, JSValue aValue) const
+{
+ // QtScript sets the value, but doesn't forward it to the original source
+ // (e.g. if you do 'object.intList[5] = 6', the object is not updated, but the
+ // copy of the list is).
+ int dist = -1;
+ QVariant val = convertValueToQVariant(exec, aValue, m_type, &dist);
+
+ if (dist >= 0) {
+ m_list[index] = val.value<T>();
+ }
+}
+
+
+template <typename T> JSValue QtArray<T>::valueAt(ExecState *exec, unsigned int index) const
+{
+ if (index < m_length) {
+ T val = m_list.at(index);
+ return convertQVariantToValue(exec, rootObject(), QVariant::fromValue(val));
+ }
+
+ return jsUndefined();
+}
+
+// ===============
+
+} }
diff --git a/Source/WebCore/bridge/qt/qt_runtime.h b/Source/WebCore/bridge/qt/qt_runtime.h
new file mode 100644
index 0000000..68bf865
--- /dev/null
+++ b/Source/WebCore/bridge/qt/qt_runtime.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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_RUNTIME_H_
+#define BINDINGS_QT_RUNTIME_H_
+
+#include "Bridge.h"
+#include "Completion.h"
+#include "Protect.h"
+#include "runtime_method.h"
+
+#include <qbytearray.h>
+#include <qmetaobject.h>
+#include <qpointer.h>
+#include <qvariant.h>
+
+namespace JSC {
+namespace Bindings {
+
+class QtInstance;
+
+class QtField : public Field {
+public:
+
+ typedef enum {
+ MetaProperty,
+#ifndef QT_NO_PROPERTIES
+ DynamicProperty,
+#endif
+ ChildObject
+ } QtFieldType;
+
+ QtField(const QMetaProperty &p)
+ : m_type(MetaProperty), m_property(p)
+ {}
+
+#ifndef QT_NO_PROPERTIES
+ QtField(const QByteArray &b)
+ : m_type(DynamicProperty), m_dynamicProperty(b)
+ {}
+#endif
+
+ QtField(QObject *child)
+ : m_type(ChildObject), m_childObject(child)
+ {}
+
+ virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
+ QByteArray name() const;
+ QtFieldType fieldType() const {return m_type;}
+private:
+ QtFieldType m_type;
+ QByteArray m_dynamicProperty;
+ QMetaProperty m_property;
+ QPointer<QObject> m_childObject;
+};
+
+
+class QtMethod : public Method
+{
+public:
+ QtMethod(const QMetaObject *mo, int i, const QByteArray &ident, int numParameters)
+ : m_metaObject(mo),
+ m_index(i),
+ m_identifier(ident),
+ m_nParams(numParameters)
+ { }
+
+ virtual const char* name() const { return m_identifier.constData(); }
+ virtual int numParameters() const { return m_nParams; }
+
+private:
+ friend class QtInstance;
+ const QMetaObject *m_metaObject;
+ int m_index;
+ QByteArray m_identifier;
+ int m_nParams;
+};
+
+
+template <typename T> class QtArray : public Array
+{
+public:
+ QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject>);
+ virtual ~QtArray();
+
+ RootObject* rootObject() const;
+
+ virtual void setValueAt(ExecState*, unsigned index, JSValue) const;
+ virtual JSValue valueAt(ExecState*, unsigned index) const;
+ virtual unsigned int getLength() const {return m_length;}
+
+private:
+ mutable QList<T> m_list; // setValueAt is const!
+ unsigned int m_length;
+ QMetaType::Type m_type;
+};
+
+// Based on RuntimeMethod
+
+// Extra data classes (to avoid the CELL_SIZE limit on JS objects)
+
+class QtRuntimeMethodData {
+ public:
+ virtual ~QtRuntimeMethodData();
+ RefPtr<QtInstance> m_instance;
+};
+
+class QtRuntimeConnectionMethod;
+class QtRuntimeMetaMethodData : public QtRuntimeMethodData {
+ public:
+ ~QtRuntimeMetaMethodData();
+ QByteArray m_signature;
+ bool m_allowPrivate;
+ int m_index;
+ QtRuntimeConnectionMethod *m_connect;
+ QtRuntimeConnectionMethod *m_disconnect;
+};
+
+class QtRuntimeConnectionMethodData : public QtRuntimeMethodData {
+ public:
+ ~QtRuntimeConnectionMethodData();
+ QByteArray m_signature;
+ int m_index;
+ bool m_isConnect;
+};
+
+// Common base class (doesn't really do anything interesting)
+class QtRuntimeMethod : public InternalFunction {
+public:
+ virtual ~QtRuntimeMethod();
+
+ static const ClassInfo s_info;
+
+ static FunctionPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
+ {
+ return globalObject->functionPrototype();
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | InternalFunction::StructureFlags | OverridesMarkChildren;
+
+ QtRuntimeMethodData *d_func() const {return d_ptr;}
+ QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst);
+ QtRuntimeMethodData *d_ptr;
+};
+
+class QtRuntimeMetaMethod : public QtRuntimeMethod
+{
+public:
+ QtRuntimeMetaMethod(ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate);
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+
+ virtual void markChildren(MarkStack& markStack);
+
+protected:
+ QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);}
+
+private:
+ virtual CallType getCallData(CallData&);
+ static EncodedJSValue JSC_HOST_CALL call(ExecState* exec);
+ static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
+ static JSValue connectGetter(ExecState*, JSValue, const Identifier&);
+ static JSValue disconnectGetter(ExecState*, JSValue, const Identifier&);
+};
+
+class QtConnectionObject;
+class QtRuntimeConnectionMethod : public QtRuntimeMethod
+{
+public:
+ QtRuntimeConnectionMethod(ExecState *exec, const Identifier &n, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature );
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+
+protected:
+ QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);}
+
+private:
+ virtual CallType getCallData(CallData&);
+ static EncodedJSValue JSC_HOST_CALL call(ExecState* exec);
+ static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
+ static QMultiMap<QObject *, QtConnectionObject *> connections;
+ friend class QtConnectionObject;
+};
+
+class QtConnectionObject: public QObject
+{
+public:
+ QtConnectionObject(PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject);
+ ~QtConnectionObject();
+
+ static const QMetaObject staticMetaObject;
+ virtual const QMetaObject *metaObject() const;
+ virtual void *qt_metacast(const char *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **argv);
+
+ bool match(QObject *sender, int signalIndex, JSObject* thisObject, JSObject *funcObject);
+
+ // actual slot:
+ void execute(void **argv);
+
+private:
+ RefPtr<QtInstance> m_instance;
+ int m_signalIndex;
+ QObject* m_originalObject; // only used as a key, not dereferenced
+ ProtectedPtr<JSObject> m_thisObject;
+ ProtectedPtr<JSObject> m_funcObject;
+};
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance);
+JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/runtime_array.cpp b/Source/WebCore/bridge/runtime_array.cpp
new file mode 100644
index 0000000..2d0b7e3
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_array.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 "runtime_array.h"
+
+#include <runtime/ArrayPrototype.h>
+#include <runtime/Error.h>
+#include <runtime/PropertyNameArray.h>
+#include "JSDOMBinding.h"
+
+using namespace WebCore;
+
+namespace JSC {
+
+const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &JSArray::info, 0, 0 };
+
+RuntimeArray::RuntimeArray(ExecState* exec, Bindings::Array* array)
+ // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
+ // We need to pass in the right global object for "array".
+ : JSArray(deprecatedGetDOMStructure<RuntimeArray>(exec))
+{
+ setSubclassData(array);
+}
+
+RuntimeArray::~RuntimeArray()
+{
+ delete getConcreteArray();
+}
+
+JSValue RuntimeArray::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
+{
+ RuntimeArray* thisObj = static_cast<RuntimeArray*>(asObject(slotBase));
+ return jsNumber(thisObj->getLength());
+}
+
+JSValue RuntimeArray::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)
+{
+ RuntimeArray* thisObj = static_cast<RuntimeArray*>(asObject(slotBase));
+ return thisObj->getConcreteArray()->valueAt(exec, index);
+}
+
+void RuntimeArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ unsigned length = getLength();
+ for (unsigned i = 0; i < length; ++i)
+ propertyNames.add(Identifier::from(exec, i));
+
+ if (mode == IncludeDontEnumProperties)
+ propertyNames.add(exec->propertyNames().length);
+
+ JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+bool RuntimeArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCacheableCustom(this, lengthGetter);
+ return true;
+ }
+
+ bool ok;
+ unsigned index = propertyName.toArrayIndex(ok);
+ if (ok) {
+ if (index < getLength()) {
+ slot.setCustomIndex(this, index, indexGetter);
+ return true;
+ }
+ }
+
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool RuntimeArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (propertyName == exec->propertyNames().length) {
+ PropertySlot slot;
+ slot.setCustom(this, lengthGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+
+ bool ok;
+ unsigned index = propertyName.toArrayIndex(ok);
+ if (ok) {
+ if (index < getLength()) {
+ PropertySlot slot;
+ slot.setCustomIndex(this, index, indexGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | DontEnum);
+ return true;
+ }
+ }
+
+ return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+bool RuntimeArray::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot)
+{
+ if (index < getLength()) {
+ slot.setCustomIndex(this, index, indexGetter);
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(exec, index, slot);
+}
+
+void RuntimeArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ throwError(exec, createRangeError(exec, "Range error"));
+ return;
+ }
+
+ bool ok;
+ unsigned index = propertyName.toArrayIndex(ok);
+ if (ok) {
+ getConcreteArray()->setValueAt(exec, index, value);
+ return;
+ }
+
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+void RuntimeArray::put(ExecState* exec, unsigned index, JSValue value)
+{
+ if (index >= getLength()) {
+ throwError(exec, createRangeError(exec, "Range error"));
+ return;
+ }
+
+ getConcreteArray()->setValueAt(exec, index, value);
+}
+
+bool RuntimeArray::deleteProperty(ExecState*, const Identifier&)
+{
+ return false;
+}
+
+bool RuntimeArray::deleteProperty(ExecState*, unsigned)
+{
+ return false;
+}
+
+}
diff --git a/Source/WebCore/bridge/runtime_array.h b/Source/WebCore/bridge/runtime_array.h
new file mode 100644
index 0000000..e301268
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_array.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 RUNTIME_ARRAY_H_
+#define RUNTIME_ARRAY_H_
+
+#include "Bridge.h"
+#include <runtime/ArrayPrototype.h>
+
+namespace JSC {
+
+class RuntimeArray : public JSArray {
+public:
+ RuntimeArray(ExecState*, Bindings::Array*);
+ virtual ~RuntimeArray();
+
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue);
+
+ virtual bool deleteProperty(ExecState* exec, const Identifier &propertyName);
+ virtual bool deleteProperty(ExecState* exec, unsigned propertyName);
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ unsigned getLength() const { return getConcreteArray()->getLength(); }
+
+ Bindings::Array* getConcreteArray() const { return static_cast<Bindings::Array*>(subclassData()); }
+
+ static const ClassInfo s_info;
+
+ static ArrayPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
+ {
+ return globalObject->arrayPrototype();
+ }
+
+private:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
+ static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
+ static JSValue indexGetter(ExecState*, JSValue, unsigned);
+};
+
+} // namespace JSC
+
+#endif // RUNTIME_ARRAY_H_
diff --git a/Source/WebCore/bridge/runtime_method.cpp b/Source/WebCore/bridge/runtime_method.cpp
new file mode 100644
index 0000000..8a61f2e
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_method.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 "runtime_method.h"
+
+#include "JSDOMBinding.h"
+#include "JSHTMLElement.h"
+#include "JSPluginElementFunctions.h"
+#include "runtime_object.h"
+#include <runtime/Error.h>
+#include <runtime/FunctionPrototype.h>
+
+using namespace WebCore;
+
+namespace JSC {
+
+using namespace Bindings;
+
+ASSERT_CLASS_FITS_IN_CELL(RuntimeMethod);
+
+const ClassInfo RuntimeMethod::s_info = { "RuntimeMethod", &InternalFunction::info, 0, 0 };
+
+RuntimeMethod::RuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& ident, Bindings::MethodList& m)
+ // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
+ // exec-globalData() is also likely wrong.
+ // Callers will need to pass in the right global object corresponding to this native object "m".
+ : InternalFunction(&exec->globalData(), globalObject, deprecatedGetDOMStructure<RuntimeMethod>(exec), ident)
+ , _methodList(new MethodList(m))
+{
+}
+
+JSValue RuntimeMethod::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
+{
+ RuntimeMethod* thisObj = static_cast<RuntimeMethod*>(asObject(slotBase));
+
+ // Ick! There may be more than one method with this name. Arbitrarily
+ // just pick the first method. The fundamental problem here is that
+ // JavaScript doesn't have the notion of method overloading and
+ // Java does.
+ // FIXME: a better solution might be to give the maximum number of parameters
+ // of any method
+ return jsNumber(thisObj->_methodList->at(0)->numParameters());
+}
+
+bool RuntimeMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCacheableCustom(this, lengthGetter);
+ return true;
+ }
+
+ return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool RuntimeMethod::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor &descriptor)
+{
+ if (propertyName == exec->propertyNames().length) {
+ PropertySlot slot;
+ slot.setCustom(this, lengthGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+
+ return InternalFunction::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+static EncodedJSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec)
+{
+ RuntimeMethod* method = static_cast<RuntimeMethod*>(exec->callee());
+
+ if (method->methods()->isEmpty())
+ return JSValue::encode(jsUndefined());
+
+ RefPtr<Instance> instance;
+
+ JSValue thisValue = exec->hostThisValue();
+ if (thisValue.inherits(&RuntimeObject::s_info)) {
+ RuntimeObject* runtimeObject = static_cast<RuntimeObject*>(asObject(thisValue));
+ instance = runtimeObject->getInternalInstance();
+ if (!instance)
+ return JSValue::encode(RuntimeObject::throwInvalidAccessError(exec));
+ } else {
+ // Calling a runtime object of a plugin element?
+ if (thisValue.inherits(&JSHTMLElement::s_info)) {
+ HTMLElement* element = static_cast<JSHTMLElement*>(asObject(thisValue))->impl();
+ instance = pluginInstance(element);
+ }
+ if (!instance)
+ return throwVMTypeError(exec);
+ }
+ ASSERT(instance);
+
+ instance->begin();
+ JSValue result = instance->invokeMethod(exec, method);
+ instance->end();
+ return JSValue::encode(result);
+}
+
+CallType RuntimeMethod::getCallData(CallData& callData)
+{
+ callData.native.function = callRuntimeMethod;
+ return CallTypeHost;
+}
+
+}
diff --git a/Source/WebCore/bridge/runtime_method.h b/Source/WebCore/bridge/runtime_method.h
new file mode 100644
index 0000000..96d12aa
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_method.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 RUNTIME_FUNCTION_H_
+#define RUNTIME_FUNCTION_H_
+
+#include "Bridge.h"
+#include <runtime/InternalFunction.h>
+#include <runtime/JSGlobalObject.h>
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+class RuntimeMethod : public InternalFunction {
+public:
+ RuntimeMethod(ExecState*, JSGlobalObject*, const Identifier& name, Bindings::MethodList&);
+ Bindings::MethodList* methods() const { return _methodList.get(); }
+
+ static const ClassInfo s_info;
+
+ static FunctionPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
+ {
+ return globalObject->functionPrototype();
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+private:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | InternalFunction::StructureFlags;
+ static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual CallType getCallData(CallData&);
+
+ OwnPtr<Bindings::MethodList> _methodList;
+};
+
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/runtime_object.cpp b/Source/WebCore/bridge/runtime_object.cpp
new file mode 100644
index 0000000..368f7b0
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_object.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2003, 2008, 2009 Apple 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 "runtime_object.h"
+
+#include "JSDOMBinding.h"
+#include "runtime_method.h"
+#include <runtime/Error.h>
+#include <runtime/ObjectPrototype.h>
+
+using namespace WebCore;
+
+namespace JSC {
+namespace Bindings {
+
+const ClassInfo RuntimeObject::s_info = { "RuntimeObject", 0, 0, 0 };
+
+RuntimeObject::RuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<Instance> instance)
+ // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
+ // We need to pass in the right global object for "i".
+ : JSObjectWithGlobalObject(globalObject, deprecatedGetDOMStructure<RuntimeObject>(exec))
+ , m_instance(instance)
+{
+}
+
+RuntimeObject::RuntimeObject(ExecState*, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, PassRefPtr<Instance> instance)
+ : JSObjectWithGlobalObject(globalObject, structure)
+ , m_instance(instance)
+{
+}
+
+RuntimeObject::~RuntimeObject()
+{
+ if (m_instance)
+ m_instance->willDestroyRuntimeObject(this);
+}
+
+void RuntimeObject::invalidate()
+{
+ ASSERT(m_instance);
+ if (m_instance)
+ m_instance->willInvalidateRuntimeObject(this);
+ m_instance = 0;
+}
+
+JSValue RuntimeObject::fallbackObjectGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+{
+ RuntimeObject* thisObj = static_cast<RuntimeObject*>(asObject(slotBase));
+ RefPtr<Instance> instance = thisObj->m_instance;
+
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+ JSValue result = aClass->fallbackObject(exec, instance.get(), propertyName);
+
+ instance->end();
+
+ return result;
+}
+
+JSValue RuntimeObject::fieldGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+{
+ RuntimeObject* thisObj = static_cast<RuntimeObject*>(asObject(slotBase));
+ RefPtr<Instance> instance = thisObj->m_instance;
+
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+ Field* aField = aClass->fieldNamed(propertyName, instance.get());
+ JSValue result = aField->valueFromInstance(exec, instance.get());
+
+ instance->end();
+
+ return result;
+}
+
+JSValue RuntimeObject::methodGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+{
+ RuntimeObject* thisObj = static_cast<RuntimeObject*>(asObject(slotBase));
+ RefPtr<Instance> instance = thisObj->m_instance;
+
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ JSValue method = instance->getMethod(exec, propertyName);
+
+ instance->end();
+
+ return method;
+}
+
+bool RuntimeObject::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (!m_instance) {
+ throwInvalidAccessError(exec);
+ return false;
+ }
+
+ RefPtr<Instance> instance = m_instance;
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+
+ if (aClass) {
+ // See if the instance has a field with the specified name.
+ Field *aField = aClass->fieldNamed(propertyName, instance.get());
+ if (aField) {
+ slot.setCustom(this, fieldGetter);
+ instance->end();
+ return true;
+ } else {
+ // Now check if a method with specified name exists, if so return a function object for
+ // that method.
+ MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
+ if (methodList.size() > 0) {
+ slot.setCustom(this, methodGetter);
+
+ instance->end();
+ return true;
+ }
+ }
+
+ // Try a fallback object.
+ if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
+ slot.setCustom(this, fallbackObjectGetter);
+ instance->end();
+ return true;
+ }
+ }
+
+ instance->end();
+
+ return instance->getOwnPropertySlot(this, exec, propertyName, slot);
+}
+
+bool RuntimeObject::getOwnPropertyDescriptor(ExecState *exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (!m_instance) {
+ throwInvalidAccessError(exec);
+ return false;
+ }
+
+ RefPtr<Instance> instance = m_instance;
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+
+ if (aClass) {
+ // See if the instance has a field with the specified name.
+ Field *aField = aClass->fieldNamed(propertyName, instance.get());
+ if (aField) {
+ PropertySlot slot;
+ slot.setCustom(this, fieldGetter);
+ instance->end();
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete);
+ return true;
+ } else {
+ // Now check if a method with specified name exists, if so return a function object for
+ // that method.
+ MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
+ if (methodList.size() > 0) {
+ PropertySlot slot;
+ slot.setCustom(this, methodGetter);
+ instance->end();
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly);
+ return true;
+ }
+ }
+
+ // Try a fallback object.
+ if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
+ PropertySlot slot;
+ slot.setCustom(this, fallbackObjectGetter);
+ instance->end();
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
+ return true;
+ }
+ }
+
+ instance->end();
+
+ return instance->getOwnPropertyDescriptor(this, exec, propertyName, descriptor);
+}
+
+void RuntimeObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ if (!m_instance) {
+ throwInvalidAccessError(exec);
+ return;
+ }
+
+ RefPtr<Instance> instance = m_instance;
+ instance->begin();
+
+ // Set the value of the property.
+ Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
+ if (aField)
+ aField->setValueToInstance(exec, instance.get(), value);
+ else if (!instance->setValueOfUndefinedField(exec, propertyName, value))
+ instance->put(this, exec, propertyName, value, slot);
+
+ instance->end();
+}
+
+bool RuntimeObject::deleteProperty(ExecState*, const Identifier&)
+{
+ // Can never remove a property of a RuntimeObject.
+ return false;
+}
+
+JSValue RuntimeObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (!m_instance)
+ return throwInvalidAccessError(exec);
+
+ RefPtr<Instance> instance = m_instance;
+
+ instance->begin();
+ JSValue result = instance->defaultValue(exec, hint);
+ instance->end();
+ return result;
+}
+
+static EncodedJSValue JSC_HOST_CALL callRuntimeObject(ExecState* exec)
+{
+ ASSERT(exec->callee()->inherits(&RuntimeObject::s_info));
+ RefPtr<Instance> instance(static_cast<RuntimeObject*>(exec->callee())->getInternalInstance());
+ instance->begin();
+ JSValue result = instance->invokeDefaultMethod(exec);
+ instance->end();
+ return JSValue::encode(result);
+}
+
+CallType RuntimeObject::getCallData(CallData& callData)
+{
+ if (!m_instance)
+ return CallTypeNone;
+
+ RefPtr<Instance> instance = m_instance;
+ if (!instance->supportsInvokeDefaultMethod())
+ return CallTypeNone;
+
+ callData.native.function = callRuntimeObject;
+ return CallTypeHost;
+}
+
+static EncodedJSValue JSC_HOST_CALL callRuntimeConstructor(ExecState* exec)
+{
+ JSObject* constructor = exec->callee();
+ ASSERT(constructor->inherits(&RuntimeObject::s_info));
+ RefPtr<Instance> instance(static_cast<RuntimeObject*>(exec->callee())->getInternalInstance());
+ instance->begin();
+ ArgList args(exec);
+ JSValue result = instance->invokeConstruct(exec, args);
+ instance->end();
+
+ ASSERT(result);
+ return JSValue::encode(result.isObject() ? static_cast<JSObject*>(result.asCell()) : constructor);
+}
+
+ConstructType RuntimeObject::getConstructData(ConstructData& constructData)
+{
+ if (!m_instance)
+ return ConstructTypeNone;
+
+ RefPtr<Instance> instance = m_instance;
+ if (!instance->supportsConstruct())
+ return ConstructTypeNone;
+
+ constructData.native.function = callRuntimeConstructor;
+ return ConstructTypeHost;
+}
+
+void RuntimeObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode)
+{
+ if (!m_instance) {
+ throwInvalidAccessError(exec);
+ return;
+ }
+
+ RefPtr<Instance> instance = m_instance;
+
+ instance->begin();
+ instance->getPropertyNames(exec, propertyNames);
+ instance->end();
+}
+
+JSObject* RuntimeObject::throwInvalidAccessError(ExecState* exec)
+{
+ return throwError(exec, createReferenceError(exec, "Trying to access object from destroyed plug-in."));
+}
+
+}
+}
diff --git a/Source/WebCore/bridge/runtime_object.h b/Source/WebCore/bridge/runtime_object.h
new file mode 100644
index 0000000..64c8049
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_object.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2003, 2008, 2009 Apple 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_RUNTIME_OBJECT_H
+#define KJS_RUNTIME_OBJECT_H
+
+#include "Bridge.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSObjectWithGlobalObject.h>
+
+namespace JSC {
+namespace Bindings {
+
+class RuntimeObject : public JSObjectWithGlobalObject {
+public:
+ RuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<Instance>);
+ virtual ~RuntimeObject();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+ virtual CallType getCallData(CallData&);
+ virtual ConstructType getConstructData(ConstructData&);
+
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+
+ void invalidate();
+
+ Instance* getInternalInstance() const { return m_instance.get(); }
+
+ static JSObject* throwInvalidAccessError(ExecState*);
+
+ static const ClassInfo s_info;
+
+ static ObjectPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
+ {
+ return globalObject->objectPrototype();
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
+ RuntimeObject(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, PassRefPtr<Instance>);
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static JSValue fallbackObjectGetter(ExecState*, JSValue, const Identifier&);
+ static JSValue fieldGetter(ExecState*, JSValue, const Identifier&);
+ static JSValue methodGetter(ExecState*, JSValue, const Identifier&);
+
+ RefPtr<Instance> m_instance;
+};
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/bridge/runtime_root.cpp b/Source/WebCore/bridge/runtime_root.cpp
new file mode 100644
index 0000000..796354f
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_root.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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 "runtime_root.h"
+
+#include "Bridge.h"
+#include "runtime_object.h"
+#include <runtime/JSGlobalObject.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC { namespace Bindings {
+
+// This code attempts to solve two problems: (1) plug-ins leaking references to
+// JS and the DOM; (2) plug-ins holding stale references to JS and the DOM. Previous
+// comments in this file claimed that problem #1 was an issue in Java, in particular,
+// because Java, allegedly, didn't always call finalize when collecting an object.
+
+typedef HashSet<RootObject*> RootObjectSet;
+
+static RootObjectSet* rootObjectSet()
+{
+ DEFINE_STATIC_LOCAL(RootObjectSet, staticRootObjectSet, ());
+ return &staticRootObjectSet;
+}
+
+// FIXME: These two functions are a potential performance problem. We could
+// fix them by adding a JSObject to RootObject dictionary.
+
+RootObject* findProtectingRootObject(JSObject* jsObject)
+{
+ RootObjectSet::const_iterator end = rootObjectSet()->end();
+ for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) {
+ if ((*it)->gcIsProtected(jsObject))
+ return *it;
+ }
+ return 0;
+}
+
+RootObject* findRootObject(JSGlobalObject* globalObject)
+{
+ RootObjectSet::const_iterator end = rootObjectSet()->end();
+ for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) {
+ if ((*it)->globalObject() == globalObject)
+ return *it;
+ }
+ return 0;
+}
+
+RootObject::InvalidationCallback::~InvalidationCallback()
+{
+}
+
+PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject)
+{
+ return adoptRef(new RootObject(nativeHandle, globalObject));
+}
+
+RootObject::RootObject(const void* nativeHandle, JSGlobalObject* globalObject)
+ : m_isValid(true)
+ , m_nativeHandle(nativeHandle)
+ , m_globalObject(globalObject)
+{
+ ASSERT(globalObject);
+ rootObjectSet()->add(this);
+}
+
+RootObject::~RootObject()
+{
+ if (m_isValid)
+ invalidate();
+}
+
+void RootObject::invalidate()
+{
+ if (!m_isValid)
+ return;
+
+ {
+ HashSet<RuntimeObject*>::iterator end = m_runtimeObjects.end();
+ for (HashSet<RuntimeObject*>::iterator it = m_runtimeObjects.begin(); it != end; ++it)
+ (*it)->invalidate();
+
+ m_runtimeObjects.clear();
+ }
+
+ m_isValid = false;
+
+ m_nativeHandle = 0;
+ m_globalObject = 0;
+
+ {
+ HashSet<InvalidationCallback*>::iterator end = m_invalidationCallbacks.end();
+ for (HashSet<InvalidationCallback*>::iterator iter = m_invalidationCallbacks.begin(); iter != end; ++iter)
+ (**iter)(this);
+
+ m_invalidationCallbacks.clear();
+ }
+
+ ProtectCountSet::iterator end = m_protectCountSet.end();
+ for (ProtectCountSet::iterator it = m_protectCountSet.begin(); it != end; ++it)
+ JSC::gcUnprotect(it->first);
+ m_protectCountSet.clear();
+
+ rootObjectSet()->remove(this);
+}
+
+void RootObject::gcProtect(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+
+ if (!m_protectCountSet.contains(jsObject))
+ JSC::gcProtect(jsObject);
+ m_protectCountSet.add(jsObject);
+}
+
+void RootObject::gcUnprotect(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+
+ if (!jsObject)
+ return;
+
+ if (m_protectCountSet.count(jsObject) == 1)
+ JSC::gcUnprotect(jsObject);
+ m_protectCountSet.remove(jsObject);
+}
+
+bool RootObject::gcIsProtected(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+ return m_protectCountSet.contains(jsObject);
+}
+
+const void* RootObject::nativeHandle() const
+{
+ ASSERT(m_isValid);
+ return m_nativeHandle;
+}
+
+JSGlobalObject* RootObject::globalObject() const
+{
+ ASSERT(m_isValid);
+ return m_globalObject;
+}
+
+void RootObject::updateGlobalObject(JSGlobalObject* globalObject)
+{
+ m_globalObject = globalObject;
+}
+
+void RootObject::addRuntimeObject(RuntimeObject* object)
+{
+ ASSERT(m_isValid);
+ ASSERT(!m_runtimeObjects.contains(object));
+
+ m_runtimeObjects.add(object);
+}
+
+void RootObject::removeRuntimeObject(RuntimeObject* object)
+{
+ ASSERT(m_isValid);
+ ASSERT(m_runtimeObjects.contains(object));
+
+ m_runtimeObjects.remove(object);
+}
+
+} } // namespace JSC::Bindings
diff --git a/Source/WebCore/bridge/runtime_root.h b/Source/WebCore/bridge/runtime_root.h
new file mode 100644
index 0000000..babd7ad
--- /dev/null
+++ b/Source/WebCore/bridge/runtime_root.h
@@ -0,0 +1,101 @@
+/*
+ * 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 RUNTIME_ROOT_H_
+#define RUNTIME_ROOT_H_
+
+#if PLATFORM(MAC)
+#include "jni_jsobject.h"
+#endif
+#include <runtime/Protect.h>
+
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+class Interpreter;
+class JSGlobalObject;
+
+namespace Bindings {
+
+class RootObject;
+class RuntimeObject;
+
+typedef HashCountedSet<JSObject*> ProtectCountSet;
+
+extern RootObject* findProtectingRootObject(JSObject*);
+extern RootObject* findRootObject(JSGlobalObject*);
+
+class RootObject : public RefCounted<RootObject> {
+ friend class JavaJSObject;
+
+public:
+ ~RootObject();
+
+ static PassRefPtr<RootObject> create(const void* nativeHandle, JSGlobalObject*);
+
+ bool isValid() { return m_isValid; }
+ void invalidate();
+
+ void gcProtect(JSObject*);
+ void gcUnprotect(JSObject*);
+ bool gcIsProtected(JSObject*);
+
+ const void* nativeHandle() const;
+ JSGlobalObject* globalObject() const;
+ void updateGlobalObject(JSGlobalObject*);
+
+ void addRuntimeObject(RuntimeObject*);
+ void removeRuntimeObject(RuntimeObject*);
+
+ struct InvalidationCallback {
+ virtual void operator()(RootObject*) = 0;
+ virtual ~InvalidationCallback();
+ };
+ void addInvalidationCallback(InvalidationCallback* callback) { m_invalidationCallbacks.add(callback); }
+
+private:
+ RootObject(const void* nativeHandle, JSGlobalObject*);
+
+ bool m_isValid;
+
+ const void* m_nativeHandle;
+ ProtectedPtr<JSGlobalObject> m_globalObject;
+
+ ProtectCountSet m_protectCountSet;
+ HashSet<RuntimeObject*> m_runtimeObjects;
+
+ HashSet<InvalidationCallback*> m_invalidationCallbacks;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // RUNTIME_ROOT_H_
diff --git a/Source/WebCore/bridge/test.js b/Source/WebCore/bridge/test.js
new file mode 100644
index 0000000..5d4f79f
--- /dev/null
+++ b/Source/WebCore/bridge/test.js
@@ -0,0 +1,19 @@
+myInterface.logMessage ("Starting test");
+
+myInterface.logMessage ("Testing properties:");
+myInterface.logMessage ("myInterface.doubleValue = " + myInterface.doubleValue);
+myInterface.logMessage ("myInterface.intValue = " + myInterface.intValue);
+myInterface.logMessage ("myInterface.stringValue = " + myInterface.stringValue);
+myInterface.logMessage ("myInterface.booleanValue = " + myInterface.booleanValue);
+myInterface.logMessage ("myInterface.nullValue = " + myInterface.nullValue);
+myInterface.logMessage ("myInterface.undefinedValue = " + myInterface.undefinedValue);
+
+myInterface.logMessage ("myInterface.setInt_(666) = " + myInterface.setInt_(666));
+myInterface.logMessage ("myInterface.getInt() = " + myInterface.getInt());
+myInterface.logMessage ("myInterface.getString() = " + myInterface.getString());
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("setting myInterface.myInt = 777");
+myInterface.myInt = 777;
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("myInterface.getMySecondInterface().doubleValue = " + myInterface.getMySecondInterface().doubleValue);
+myInterface.logMessage ("myInterface.getMySecondInterface() = " + myInterface.getMySecondInterface());
diff --git a/Source/WebCore/bridge/testC.js b/Source/WebCore/bridge/testC.js
new file mode 100644
index 0000000..44677c7
--- /dev/null
+++ b/Source/WebCore/bridge/testC.js
@@ -0,0 +1,21 @@
+myInterface.logMessage ("Starting test");
+
+myInterface.logMessage ("Testing properties:");
+myInterface.logMessage (" myInterface.doubleValue = " + myInterface.doubleValue);
+myInterface.logMessage (" myInterface.intValue = " + myInterface.intValue);
+myInterface.logMessage (" myInterface.stringValue = " + myInterface.stringValue);
+myInterface.logMessage (" myInterface.booleanValue = " + myInterface.booleanValue);
+myInterface.logMessage (" myInterface.nullValue = " + myInterface.nullValue);
+myInterface.logMessage (" myInterface.undefinedValue = " + myInterface.undefinedValue);
+
+myInterface.logMessage ("Testing methods:");
+myInterface.logMessage (" myInterface.setDoubleValue(1234.1234) = " + myInterface.setDoubleValue(1234.1234));
+myInterface.logMessage (" myInterface.setIntValue(5678) = " + myInterface.setIntValue(5678));
+myInterface.logMessage (" myInterface.setStringValue(Goodbye) = " + myInterface.setStringValue('Goodbye'));
+myInterface.logMessage (" myInterface.setBooleanValue(false) = " + myInterface.setBooleanValue(false));
+
+myInterface.logMessage ("Value of properties after calling setters:");
+myInterface.logMessage (" myInterface.getDoubleValue() = " + myInterface.getDoubleValue());
+myInterface.logMessage (" myInterface.getIntValue() = " + myInterface.getIntValue());
+myInterface.logMessage (" myInterface.getStringValue() = " + myInterface.getStringValue());
+myInterface.logMessage (" myInterface.getBooleanValue() = " + myInterface.getBooleanValue());
diff --git a/Source/WebCore/bridge/testM.js b/Source/WebCore/bridge/testM.js
new file mode 100644
index 0000000..7985d21
--- /dev/null
+++ b/Source/WebCore/bridge/testM.js
@@ -0,0 +1,29 @@
+myInterface.logMessage ("Starting test");
+
+myInterface.logMessage ("Testing properties:");
+
+myInterface.jsobject = new Function ("arg1","arg2","return arg1 + arg2;");
+myInterface.logMessage ("myInterface.jsobject =" + myInterface.jsobject);
+
+var functionBody = 'return arg1*arg2;'
+
+myInterface.setJSObject_(new Function ("arg1","arg2",functionBody));
+myInterface.logMessage ("myInterface.jsobject =" + myInterface.jsobject);
+myInterface.callJSObject__(5,6);
+myInterface.callJSObject__(8,9);
+
+myInterface.logMessage ("myInterface.setInt_(666) = " + myInterface.setInt_(666));
+myInterface.logMessage ("myInterface.getInt() = " + myInterface.getInt());
+myInterface.logMessage ("myInterface.getString().foo() = " + myInterface.getString().foo());
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("setting myInterface.myInt = 777");
+myInterface.myInt = 777;
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("myInterface.getMySecondInterface().doubleValue = " + myInterface.getMySecondInterface().doubleValue);
+myInterface.logMessage ("myInterface.getMySecondInterface() = " + myInterface.getMySecondInterface());
+
+myInterface.logMessageWithPrefix ("msg", "prefix");
+
+var strings = [ "one", "two", "three" ];
+
+myInterface.logMessages (strings); \ No newline at end of file
diff --git a/Source/WebCore/bridge/testbindings.cpp b/Source/WebCore/bridge/testbindings.cpp
new file mode 100644
index 0000000..bcba115
--- /dev/null
+++ b/Source/WebCore/bridge/testbindings.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "config.h"
+
+#include "Bridge.h"
+#include "JSObject.h"
+#include "JSValue.h"
+#include "interpreter.h"
+#include "npruntime_internal.h"
+#include "runtime_object.h"
+#include "types.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+
+
+// ------------------ NP Interface definition --------------------
+typedef struct
+{
+ NPObject object;
+ double doubleValue;
+ int intValue;
+ NPVariant stringValue;
+ bool boolValue;
+} MyObject;
+
+
+static bool identifiersInitialized = false;
+
+#define ID_DOUBLE_VALUE 0
+#define ID_INT_VALUE 1
+#define ID_STRING_VALUE 2
+#define ID_BOOLEAN_VALUE 3
+#define ID_NULL_VALUE 4
+#define ID_UNDEFINED_VALUE 5
+#define NUM_PROPERTY_IDENTIFIERS 6
+
+static NPIdentifier myPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
+static const NPUTF8 *myPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
+ "doubleValue",
+ "intValue",
+ "stringValue",
+ "booleanValue",
+ "nullValue",
+ "undefinedValue"
+};
+
+#define ID_LOG_MESSAGE 0
+#define ID_SET_DOUBLE_VALUE 1
+#define ID_SET_INT_VALUE 2
+#define ID_SET_STRING_VALUE 3
+#define ID_SET_BOOLEAN_VALUE 4
+#define ID_GET_DOUBLE_VALUE 5
+#define ID_GET_INT_VALUE 6
+#define ID_GET_STRING_VALUE 7
+#define ID_GET_BOOLEAN_VALUE 8
+#define NUM_METHOD_IDENTIFIERS 9
+
+static NPIdentifier myMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
+static const NPUTF8 *myMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
+ "logMessage",
+ "setDoubleValue",
+ "setIntValue",
+ "setStringValue",
+ "setBooleanValue",
+ "getDoubleValue",
+ "getIntValue",
+ "getStringValue",
+ "getBooleanValue"
+};
+
+static void initializeIdentifiers()
+{
+ NPN_GetStringIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers);
+ NPN_GetStringIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers);
+};
+
+bool myHasProperty (NPClass *theClass, NPIdentifier name)
+{
+ int i;
+ for (i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) {
+ if (name == myPropertyIdentifiers[i]){
+ return true;
+ }
+ }
+ return false;
+}
+
+bool myHasMethod (NPClass *theClass, NPIdentifier name)
+{
+ int i;
+ for (i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
+ if (name == myMethodIdentifiers[i]){
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void logMessage (const NPVariant *message)
+{
+ if (message->type == NPVariantStringType) {
+ char msgBuf[1024];
+ strncpy (msgBuf, message->value.stringValue.UTF8Characters, message->value.stringValue.UTF8Length);
+ msgBuf[message->value.stringValue.UTF8Length] = 0;
+ printf ("%s\n", msgBuf);
+ }
+ else if (message->type == NPVariantDoubleType)
+ printf ("%f\n", (float)message->value.doubleValue);
+ else if (message->type == NPVariantInt32Type)
+ printf ("%d\n", message->value.intValue);
+ else if (message->type == NPVariantObjectType)
+ printf ("%p\n", message->value.objectValue);
+}
+
+void setDoubleValue (MyObject *obj, const NPVariant *variant)
+{
+ if (!NPN_VariantToDouble (variant, &obj->doubleValue)) {
+ NPUTF8 *msg = "Attempt to set double value with invalid type.";
+ NPString aString;
+ aString.UTF8Characters = msg;
+ aString.UTF8Length = strlen (msg);
+ NPN_SetException ((NPObject *)obj, &aString);
+ }
+}
+
+void setIntValue (MyObject *obj, const NPVariant *variant)
+{
+ if (!NPN_VariantToInt32 (variant, &obj->intValue)) {
+ NPUTF8 *msg = "Attempt to set int value with invalid type.";
+ NPString aString;
+ aString.UTF8Characters = msg;
+ aString.UTF8Length = strlen (msg);
+ NPN_SetException ((NPObject *)obj, &aString);
+ }
+}
+
+void setStringValue (MyObject *obj, const NPVariant *variant)
+{
+ NPN_ReleaseVariantValue (&obj->stringValue);
+ NPN_InitializeVariantWithVariant (&obj->stringValue, variant);
+}
+
+void setBooleanValue (MyObject *obj, const NPVariant *variant)
+{
+ if (!NPN_VariantToBool (variant, (NPBool *)&obj->boolValue)) {
+ NPUTF8 *msg = "Attempt to set bool value with invalid type.";
+ NPString aString;
+ aString.UTF8Characters = msg;
+ aString.UTF8Length = strlen (msg);
+ NPN_SetException ((NPObject *)obj, &aString);
+ }
+}
+
+void getDoubleValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithDouble (variant, obj->doubleValue);
+}
+
+void getIntValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithInt32 (variant, obj->intValue);
+}
+
+void getStringValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithVariant (variant, &obj->stringValue);
+}
+
+void getBooleanValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithBool (variant, obj->boolValue);
+}
+
+void myGetProperty (MyObject *obj, NPIdentifier name, NPVariant *variant)
+{
+ if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]){
+ getDoubleValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_INT_VALUE]){
+ getIntValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_STRING_VALUE]){
+ getStringValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]){
+ getBooleanValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_NULL_VALUE]){
+ return NPN_InitializeVariantAsNull (variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]){
+ return NPN_InitializeVariantAsUndefined (variant);
+ }
+ else
+ NPN_InitializeVariantAsUndefined(variant);
+}
+
+void mySetProperty (MyObject *obj, NPIdentifier name, const NPVariant *variant)
+{
+ if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]) {
+ setDoubleValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_INT_VALUE]) {
+ setIntValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_STRING_VALUE]) {
+ setStringValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]) {
+ setBooleanValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_NULL_VALUE]) {
+ // Do nothing!
+ }
+ else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]) {
+ // Do nothing!
+ }
+}
+
+void myInvoke (MyObject *obj, NPIdentifier name, NPVariant *args, unsigned argCount, NPVariant *result)
+{
+ if (name == myMethodIdentifiers[ID_LOG_MESSAGE]) {
+ if (argCount == 1 && NPN_VariantIsString(&args[0]))
+ logMessage (&args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_DOUBLE_VALUE]) {
+ if (argCount == 1 && NPN_VariantIsDouble (&args[0]))
+ setDoubleValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_INT_VALUE]) {
+ if (argCount == 1 && (NPN_VariantIsDouble (&args[0]) || NPN_VariantIsInt32 (&args[0])))
+ setIntValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_STRING_VALUE]) {
+ if (argCount == 1 && NPN_VariantIsString (&args[0]))
+ setStringValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_BOOLEAN_VALUE]) {
+ if (argCount == 1 && NPN_VariantIsBool (&args[0]))
+ setBooleanValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_DOUBLE_VALUE]) {
+ getDoubleValue (obj, result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_INT_VALUE]) {
+ getIntValue (obj, result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_STRING_VALUE]) {
+ getStringValue (obj, result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_BOOLEAN_VALUE]) {
+ getBooleanValue (obj, result);
+ }
+ else
+ NPN_InitializeVariantAsUndefined (result);
+}
+
+NPObject *myAllocate ()
+{
+ MyObject *newInstance = (MyObject *)malloc (sizeof(MyObject));
+
+ if (!identifiersInitialized) {
+ identifiersInitialized = true;
+ initializeIdentifiers();
+ }
+
+
+ newInstance->doubleValue = 666.666;
+ newInstance->intValue = 1234;
+ newInstance->boolValue = true;
+ newInstance->stringValue.type = NPVariantType_String;
+ newInstance->stringValue.value.stringValue.UTF8Length = strlen ("Hello world");
+ newInstance->stringValue.value.stringValue.UTF8Characters = strdup ("Hello world");
+
+ return (NPObject *)newInstance;
+}
+
+void myInvalidate ()
+{
+ // Make sure we've released any remaining references to JavaScript objects.
+}
+
+void myDeallocate (MyObject *obj)
+{
+ free ((void *)obj);
+}
+
+static NPClass _myFunctionPtrs = {
+ kNPClassStructVersionCurrent,
+ (NPAllocateFunctionPtr) myAllocate,
+ (NPDeallocateFunctionPtr) myDeallocate,
+ (NPInvalidateFunctionPtr) myInvalidate,
+ (NPHasMethodFunctionPtr) myHasMethod,
+ (NPInvokeFunctionPtr) myInvoke,
+ (NPHasPropertyFunctionPtr) myHasProperty,
+ (NPGetPropertyFunctionPtr) myGetProperty,
+ (NPSetPropertyFunctionPtr) mySetProperty,
+};
+static NPClass *myFunctionPtrs = &_myFunctionPtrs;
+
+// --------------------------------------------------------
+
+using namespace JSC;
+using namespace JSC::Bindings;
+
+class GlobalImp : public ObjectImp {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+#define BufferSize 200000
+static char code[BufferSize];
+
+const char *readJavaScriptFromFile (const char *file)
+{
+ FILE *f = fopen(file, "r");
+ if (!f) {
+ fprintf(stderr, "Error opening %s.\n", file);
+ return 0;
+ }
+
+ int num = fread(code, 1, BufferSize, f);
+ code[num] = '\0';
+ if(num >= BufferSize)
+ fprintf(stderr, "Warning: File may have been too long.\n");
+
+ fclose(f);
+
+ return code;
+}
+
+int main(int argc, char **argv)
+{
+ // expecting a filename
+ if (argc < 2) {
+ fprintf(stderr, "You have to specify at least one filename\n");
+ return -1;
+ }
+
+ bool ret = true;
+ {
+ JSLock lock;
+
+ // create interpreter w/ global object
+ Object global(new GlobalImp());
+ Interpreter interp;
+ interp.setGlobalObject(global);
+ ExecState *exec = interp.globalExec();
+
+ MyObject *myObject = (MyObject *)NPN_CreateObject (myFunctionPtrs);
+
+ global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage, (void *)myObject));
+
+ for (int i = 1; i < argc; i++) {
+ const char *code = readJavaScriptFromFile(argv[i]);
+
+ if (code) {
+ // run
+ Completion comp(interp.evaluate(code));
+
+ if (comp.complType() == Throw) {
+ Value exVal = comp.value();
+ char *msg = exVal.toString(exec).ascii();
+ int lineno = -1;
+ if (exVal.type() == ObjectType) {
+ Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
+ if (lineVal.type() == NumberType)
+ lineno = int(lineVal.toNumber(exec));
+ }
+ if (lineno != -1)
+ fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
+ else
+ fprintf(stderr,"Exception: %s\n",msg);
+ ret = false;
+ }
+ else if (comp.complType() == ReturnValue) {
+ char *msg = comp.value().toString(interp.globalExec()).ascii();
+ fprintf(stderr,"Return value: %s\n",msg);
+ }
+ }
+ }
+
+ NPN_ReleaseObject ((NPObject *)myObject);
+
+ } // end block, so that Interpreter and global get deleted
+
+ return ret ? 0 : 3;
+}
diff --git a/Source/WebCore/bridge/testbindings.mm b/Source/WebCore/bridge/testbindings.mm
new file mode 100644
index 0000000..31564a8
--- /dev/null
+++ b/Source/WebCore/bridge/testbindings.mm
@@ -0,0 +1,287 @@
+/*
+ * 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 "Bridge.h"
+#include <Foundation/Foundation.h>
+#include "JSObject.h"
+#include "JSValue.h"
+#import <WebKit/WebScriptObject.h>
+#include "interpreter.h"
+#include "runtime_object.h"
+#include <stdio.h>
+#include <string.h>
+#include "types.h"
+
+
+#define LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+
+@interface MySecondInterface : NSObject
+{
+ double doubleValue;
+}
+
+- init;
+
+@end
+
+@implementation MySecondInterface
+
+- init
+{
+ LOG ("\n");
+ doubleValue = 666.666;
+ return self;
+}
+
+@end
+
+@interface MyFirstInterface : NSObject
+{
+ int myInt;
+ MySecondInterface *mySecondInterface;
+ id jsobject;
+ NSString *string;
+}
+
+- (int)getInt;
+- (void)setInt: (int)anInt;
+- (MySecondInterface *)getMySecondInterface;
+- (void)logMessage:(NSString *)message;
+- (void)setJSObject:(id)jsobject;
+@end
+
+@implementation MyFirstInterface
+
++ (NSString *)webScriptNameForSelector:(SEL)aSelector
+{
+ if (aSelector == @selector(logMessage:))
+ return @"logMessage";
+ if (aSelector == @selector(logMessages:))
+ return @"logMessages";
+ if (aSelector == @selector(logMessage:prefix:))
+ return @"logMessageWithPrefix";
+ return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
+{
+ return NO;
+}
+
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name
+{
+ return NO;
+}
+
+/*
+- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args
+{
+ NSLog (@"Call to undefined method %@", name);
+ NSLog (@"%d args\n", [args count]);
+ int i;
+ for (i = 0; i < [args count]; i++) {
+ NSLog (@"%d: %@\n", i, [args objectAtIndex:i]);
+ }
+ return @"success";
+}
+*/
+
+/*
+- (id)valueForUndefinedKey:(NSString *)key
+{
+ NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
+ return @"aValue";
+}
+*/
+
+- (void)setValue:(id)value forUndefinedKey:(NSString *)key
+{
+ NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
+}
+
+- init
+{
+ LOG ("\n");
+ mySecondInterface = [[MySecondInterface alloc] init];
+ return self;
+}
+
+- (void)dealloc
+{
+ LOG ("\n");
+ [mySecondInterface release];
+ [super dealloc];
+}
+
+- (int)getInt
+{
+ LOG ("myInt = %d\n", myInt);
+ return myInt;
+}
+
+- (void)setInt: (int)anInt
+{
+ LOG ("anInt = %d\n", anInt);
+ myInt = anInt;
+}
+
+- (NSString *)getString
+{
+ return string;
+}
+
+- (MySecondInterface *)getMySecondInterface
+{
+ LOG ("\n");
+ return mySecondInterface;
+}
+
+- (void)logMessage:(NSString *)message
+{
+ printf ("%s\n", [message lossyCString]);
+}
+
+- (void)logMessages:(id)messages
+{
+ int i, count = [[messages valueForKey:@"length"] intValue];
+ for (i = 0; i < count; i++)
+ printf ("%s\n", [[messages webScriptValueAtIndex:i] lossyCString]);
+}
+
+- (void)logMessage:(NSString *)message prefix:(NSString *)prefix
+{
+ printf ("%s:%s\n", [prefix lossyCString], [message lossyCString]);
+}
+
+- (void)setJSObject:(id)jso
+{
+ [jsobject autorelease];
+ jsobject = [jso retain];
+}
+
+- (void)callJSObject:(int)arg1 :(int)arg2
+{
+ id foo1 = [jsobject callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:jsobject, [NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil]];
+ printf ("foo (via call) = %s\n", [[foo1 description] lossyCString] );
+ id foo2 = [jsobject callWebScriptMethod:@"apply" withArguments:[NSArray arrayWithObjects:jsobject, [NSArray arrayWithObjects:[NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil], nil]];
+ printf ("foo (via apply) = %s\n", [[foo2 description] lossyCString] );
+}
+
+@end
+
+
+using namespace JSC;
+using namespace JSC::Bindings;
+
+class GlobalImp : public ObjectImp {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+#define BufferSize 200000
+static char code[BufferSize];
+
+const char *readJavaScriptFromFile (const char *file)
+{
+ FILE *f = fopen(file, "r");
+ if (!f) {
+ fprintf(stderr, "Error opening %s.\n", file);
+ return 0;
+ }
+
+ int num = fread(code, 1, BufferSize, f);
+ code[num] = '\0';
+ if(num >= BufferSize)
+ fprintf(stderr, "Warning: File may have been too long.\n");
+
+ fclose(f);
+
+ return code;
+}
+
+int main(int argc, char **argv)
+{
+ // expecting a filename
+ if (argc < 2) {
+ fprintf(stderr, "You have to specify at least one filename\n");
+ return -1;
+ }
+
+ bool ret = true;
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ JSLock lock;
+
+ // create interpreter w/ global object
+ Object global(new GlobalImp());
+ Interpreter interp;
+ interp.setGlobalObject(global);
+ ExecState *exec = interp.globalExec();
+
+ MyFirstInterface *myInterface = [[MyFirstInterface alloc] init];
+
+ global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::ObjectiveCLanguage, (void *)myInterface));
+
+ for (int i = 1; i < argc; i++) {
+ const char *code = readJavaScriptFromFile(argv[i]);
+
+ if (code) {
+ // run
+ Completion comp(interp.evaluate(code));
+
+ if (comp.complType() == Throw) {
+ Value exVal = comp.value();
+ char *msg = exVal.toString(exec).ascii();
+ int lineno = -1;
+ if (exVal.type() == ObjectType) {
+ Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
+ if (lineVal.type() == NumberType)
+ lineno = int(lineVal.toNumber(exec));
+ }
+ if (lineno != -1)
+ fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
+ else
+ fprintf(stderr,"Exception: %s\n",msg);
+ ret = false;
+ }
+ else if (comp.complType() == ReturnValue) {
+ char *msg = comp.value().toString(interp.globalExec()).ascii();
+ fprintf(stderr,"Return value: %s\n",msg);
+ }
+ }
+ }
+
+ [myInterface release];
+ [pool drain];
+ } // end block, so that Interpreter and global get deleted
+
+ return ret ? 0 : 3;
+}
diff --git a/Source/WebCore/bridge/testbindings.pro b/Source/WebCore/bridge/testbindings.pro
new file mode 100644
index 0000000..a854d4f
--- /dev/null
+++ b/Source/WebCore/bridge/testbindings.pro
@@ -0,0 +1,7 @@
+QT -= gui
+
+include(../../WebKit.pri)
+INCLUDEPATH += .. ../ . bindings/qt
+
+SOURCES += testqtbindings.cpp
+
diff --git a/Source/WebCore/bridge/testqtbindings.cpp b/Source/WebCore/bridge/testqtbindings.cpp
new file mode 100644
index 0000000..73df155
--- /dev/null
+++ b/Source/WebCore/bridge/testqtbindings.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "Bridge.h"
+#include "JSObject.h"
+#include "JSValue.h"
+#include "interpreter.h"
+#include "qdebug.h"
+#include "qobject.h"
+#include "runtime_object.h"
+#include "types.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString testString READ testString WRITE setTestString)
+ Q_PROPERTY(int testInt READ testInt WRITE setTestInt)
+
+public:
+ MyObject() : QObject(0), integer(0){}
+
+ void setTestString(const QString &str) {
+ qDebug() << "called setTestString" << str;
+ string = str;
+ }
+ void setTestInt(int i) {
+ qDebug() << "called setTestInt" << i;
+ integer = i;
+ }
+ QString testString() const {
+ qDebug() << "called testString" << string;
+ return string;
+ }
+ int testInt() const {
+ qDebug() << "called testInt" << integer;
+ return integer;
+ }
+ QString string;
+ int integer;
+
+public slots:
+ void foo() { qDebug() << "foo invoked"; }
+};
+
+// --------------------------------------------------------
+
+using namespace JSC;
+using namespace JSC::Bindings;
+
+class Global : public JSObject {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+static char code[] =
+ "myInterface.foo();\n"
+ "myInterface.testString = \"Hello\";\n"
+ "str = myInterface.testString;\n"
+ "myInterface.testInt = 10;\n"
+ "i = myInterface.testInt;\n";
+
+int main(int argc, char** argv)
+{
+ // expecting a filename
+ bool ret = true;
+ {
+ JSLock lock;
+
+ // create interpreter w/ global object
+ Global* global = new Global();
+
+ // create interpreter
+ RefPtr<Interpreter> interp = new Interpreter(global);
+ ExecState* exec = interp->globalExec();
+
+ MyObject* myObject = new MyObject;
+
+ global->put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::QtLanguage, (void*)myObject));
+
+
+ if (code) {
+ // run
+ Completion comp(interp->evaluate("", 0, code));
+
+ if (comp.complType() == Throw) {
+ qDebug() << "exception thrown";
+ JSValue* exVal = comp.value();
+ char* msg = exVal->toString(exec).ascii();
+ int lineno = -1;
+ if (exVal->type() == ObjectType) {
+ JSValue* lineVal = exVal->getObject()->get(exec, Identifier("line"));
+ if (lineVal->type() == NumberType)
+ lineno = int(lineVal->toNumber(exec));
+ }
+ if (lineno != -1)
+ fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
+ else
+ fprintf(stderr,"Exception: %s\n",msg);
+ ret = false;
+ }
+ else if (comp.complType() == ReturnValue) {
+ char* msg = comp.value()->toString(interp->globalExec()).ascii();
+ fprintf(stderr,"Return value: %s\n",msg);
+ }
+ }
+
+ } // end block, so that Interpreter and global get deleted
+
+ return ret ? 0 : 1;
+}
+
+#include "testqtbindings.moc"