diff options
author | Feng Qian <fqian@google.com> | 2009-04-30 20:00:54 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-04-30 20:00:54 -0700 |
commit | b2318f335c407832166c7568f3e50afedad5b9db (patch) | |
tree | eab734e32d524e57fe074d4790513bb7dc3ea431 /V8Binding/jni | |
parent | ffdfe220d2fa9a605c4f5ea060ceb90b80c919f0 (diff) | |
download | external_webkit-b2318f335c407832166c7568f3e50afedad5b9db.zip external_webkit-b2318f335c407832166c7568f3e50afedad5b9db.tar.gz external_webkit-b2318f335c407832166c7568f3e50afedad5b9db.tar.bz2 |
Implement Java <-> JS bindings.
Implemented invoke Java methods and fecth Java fields from JavaScript.
Java-side access native-JS objects is not supported. JavaScript-side
modification of JS objects is not supported.
The implementation uses NPAPI, which is simple, but less efficient.
Java abstraction is very much copied from original WebCore/bridge/jni,
except all JSC bindings are replaced by NPAPI.
Diffstat (limited to 'V8Binding/jni')
-rw-r--r-- | V8Binding/jni/jni_class.cpp | 43 | ||||
-rw-r--r-- | V8Binding/jni/jni_class.h | 15 | ||||
-rw-r--r-- | V8Binding/jni/jni_instance.cpp | 95 | ||||
-rw-r--r-- | V8Binding/jni/jni_instance.h | 32 | ||||
-rw-r--r-- | V8Binding/jni/jni_npobject.cpp | 137 | ||||
-rw-r--r-- | V8Binding/jni/jni_npobject.h | 42 | ||||
-rw-r--r-- | V8Binding/jni/jni_runtime.cpp | 117 | ||||
-rw-r--r-- | V8Binding/jni/jni_runtime.h | 24 | ||||
-rw-r--r-- | V8Binding/jni/jni_utility.cpp | 113 | ||||
-rw-r--r-- | V8Binding/jni/jni_utility.h | 7 |
10 files changed, 419 insertions, 206 deletions
diff --git a/V8Binding/jni/jni_class.cpp b/V8Binding/jni/jni_class.cpp index 4e3b5f9..1c68d66 100644 --- a/V8Binding/jni/jni_class.cpp +++ b/V8Binding/jni/jni_class.cpp @@ -1,5 +1,6 @@ /* * 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 @@ -24,13 +25,8 @@ */ #include "config.h" -#include "jni_class.h" - -#if ENABLE(MAC_JAVA_BRIDGE) -#include "JSDOMWindow.h" -#include <runtime/Identifier.h> -#include <runtime/JSLock.h> +#include "jni_class.h" #include "jni_utility.h" #include "jni_runtime.h" @@ -60,7 +56,6 @@ JavaClass::JavaClass(jobject anInstance) jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i); JavaField *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor { - JSLock lock(false); _fields.set(aField->name(), aField); } env->DeleteLocalRef(aJField); @@ -74,8 +69,6 @@ JavaClass::JavaClass(jobject anInstance) JavaMethod *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor MethodList* methodList; { - JSLock lock(false); - methodList = _methods.get(aMethod->name()); if (!methodList) { methodList = new MethodList(); @@ -95,8 +88,6 @@ JavaClass::JavaClass(jobject anInstance) JavaClass::~JavaClass() { free((void *)_name); - JSLock lock(false); - deleteAllValues(_fields); _fields.clear(); @@ -109,38 +100,16 @@ JavaClass::~JavaClass() { _methods.clear(); } -MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const +MethodList JavaClass::methodsNamed(const char* name) const { - MethodList *methodList = _methods.get(identifier.ustring().rep()); + MethodList *methodList = _methods.get(name); if (methodList) return *methodList; return MethodList(); } -Field *JavaClass::fieldNamed(const Identifier& identifier, Instance*) const -{ - return _fields.get(identifier.ustring().rep()); -} - -bool JavaClass::isNumberClass() const +JavaField* JavaClass::fieldNamed(const char* name) const { - return ((strcmp(_name, "java.lang.Byte") == 0 || - strcmp(_name, "java.lang.Short") == 0 || - strcmp(_name, "java.lang.Integer") == 0 || - strcmp(_name, "java.lang.Long") == 0 || - strcmp(_name, "java.lang.Float") == 0 || - strcmp(_name, "java.lang.Double") == 0) ); + return _fields.get(name); } - -bool JavaClass::isBooleanClass() const -{ - return strcmp(_name, "java.lang.Boolean") == 0; -} - -bool JavaClass::isStringClass() const -{ - return strcmp(_name, "java.lang.String") == 0; -} - -#endif // ENABLE(MAC_JAVA_BRIDGE) diff --git a/V8Binding/jni/jni_class.h b/V8Binding/jni/jni_class.h index 2865be5..58787d3 100644 --- a/V8Binding/jni/jni_class.h +++ b/V8Binding/jni/jni_class.h @@ -1,5 +1,6 @@ /* * 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 @@ -28,22 +29,30 @@ #include <jni_runtime.h> #include <wtf/HashMap.h> +#include <wtf/Vector.h> +#include "PlatformString.h" +#include "StringHash.h" namespace JSC { namespace Bindings { typedef Vector<JavaMethod*> MethodList; -class JavaClass +typedef HashMap<WebCore::String, MethodList*> MethodListMap; +typedef HashMap<WebCore::String, JavaField*> FieldMap; + +class JavaClass { public: JavaClass (jobject anInstance); ~JavaClass (); - MethodList methodsNamed(NPIdentifier name, Instance* instance) const; - + MethodList methodsNamed(const char* name) const; + JavaField* fieldNamed(const char* name) const; + private: const char *_name; MethodListMap _methods; + FieldMap _fields; }; } // namespace Bindings diff --git a/V8Binding/jni/jni_instance.cpp b/V8Binding/jni/jni_instance.cpp index 887886e..9204ba7 100644 --- a/V8Binding/jni/jni_instance.cpp +++ b/V8Binding/jni/jni_instance.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2003, 2008 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 @@ -25,6 +26,7 @@ #include "config.h" +#include "jni_class.h" #include "jni_instance.h" #include "jni_runtime.h" #include "jni_utility.h" @@ -44,20 +46,32 @@ using namespace JSC::Bindings; JavaInstance::JavaInstance (jobject instance) { - _instance = new JObjectWrapper (instance); + _instance = new JObjectWrapper(instance); + _class = 0; } JavaInstance::~JavaInstance () { + delete _class; } -#define NUM_LOCAL_REFS 64 +JavaClass* JavaInstance::getClass() const +{ + if (_class == 0) + _class = new JavaClass(_instance->_instance); + return _class; +} -bool JavaInstance::invokeMethod(NPIdentifier methodName, NPVariant* args, uint32_t count, NPVariant* resultValue) +bool JavaInstance::invokeMethod(const char* methodName, const NPVariant* args, uint32_t count, NPVariant* resultValue) { int i; jvalue *jArgs; - Method *method = 0; + JavaMethod *method = 0; + + 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 @@ -65,7 +79,7 @@ bool JavaInstance::invokeMethod(NPIdentifier methodName, NPVariant* args, uint32 // notion of method overloading and Java does. We could // get a bit more sophisticated and attempt to does some // type checking as we as checking the number of parameters. - Method *aMethod; + JavaMethod *aMethod; for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) { aMethod = methodList[methodIndex]; if (aMethod->numParameters() == count) { @@ -75,7 +89,7 @@ bool JavaInstance::invokeMethod(NPIdentifier methodName, NPVariant* args, uint32 } if (method == 0) { JS_LOG ("unable to find an appropiate method\n"); - return jsUndefined(); + return false; } const JavaMethod *jMethod = static_cast<const JavaMethod*>(method); @@ -134,74 +148,11 @@ bool JavaInstance::invokeMethod(NPIdentifier methodName, NPVariant* args, uint32 break; } } - - switch (jMethod->JNIReturnType()){ - case void_type: { - VOID_TO_NPVARIANT(*resultValue); - } - break; - - case object_type: { - if (result.l != 0) { - OBJECT_TO_NPVARIANT(JavaObjectToNPObject(JavaInstance::create(result.l)), *resultValue); - } - else { - VOID_TO_NPVARIANT(*resultValue); - } - } - break; - - case boolean_type: { - BOOLEAN_TO_NPVARIANT(result.z, *resultValue); - } - break; - - case byte_type: { - INT32_TO_NPVARIANT(result.b, *resultValue); - } - break; - - case char_type: { - INT32_TO_NPVARIANT(result.c, *resultValue); - } - break; - - case short_type: { - INT32_TO_NPVARIANT(result.s, *resultValue); - } - break; - - case int_type: { - INT32_TO_NPVARIANT(result.i, *resultValue); - } - break; - - // TODO(fqian): check if cast to double is needed. - case long_type: { - DOUBLE_TO_NPVARIANT(result.j, *resultValue); - } - break; - - case float_type: { - DOUBLE_TO_NPVARIANT(result.f, *resultValue); - } - break; - - case double_type: { - DOUBLE_TO_NPVARIANT(result.d, *resultValue); - } - break; - - case invalid_type: - default: { - VOID_TO_NPVARIANT(*resultValue); - } - break; - } - + + convertJValueToNPVariant(result, jMethod->JNIReturnType(), resultValue); free (jArgs); - return resultValue; + return true; } JObjectWrapper::JObjectWrapper(jobject instance) diff --git a/V8Binding/jni/jni_instance.h b/V8Binding/jni/jni_instance.h index 5fa4141..0ee487e 100644 --- a/V8Binding/jni/jni_instance.h +++ b/V8Binding/jni/jni_instance.h @@ -1,5 +1,6 @@ /* * 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 @@ -27,24 +28,24 @@ #define _JNI_INSTANCE_H_ #include <JavaVM/jni.h> +#include <wtf/RefPtr.h> namespace android { class WeakJavaInstance; } +using namespace WTF; + namespace JSC { namespace Bindings { +class JavaClass; + class JObjectWrapper { -friend class RefPtr<JObjectWrapper>; -friend class JavaArray; friend class JavaInstance; -friend class JavaMethod; -friend class android::WeakJavaInstance; - -protected: +public: JObjectWrapper(jobject instance); ~JObjectWrapper(); @@ -55,31 +56,28 @@ protected: delete this; } - jobject _instance; - private: JNIEnv *_env; unsigned int _refCount; + jobject _instance; }; class JavaInstance { public: - static PassRefPtr<JavaInstance> create(jobject instance) - { - return adoptRef(new JavaInstance(instance)); - } - + JavaInstance(jobject instance); ~JavaInstance(); - - NPVariant invokeMethod(NPIdentifier methodName, NPVariant* args, uint32_t argsCount); + + JavaClass* getClass() const; + + bool invokeMethod(const char* name, const NPVariant* args, uint32_t argsCount, NPVariant* result); jobject javaInstance() const { return _instance->_instance; } private: - JavaInstance(jobject instance); - RefPtr<JObjectWrapper> _instance; + unsigned int _refCount; + mutable JavaClass* _class; }; } // namespace Bindings diff --git a/V8Binding/jni/jni_npobject.cpp b/V8Binding/jni/jni_npobject.cpp index daa26a8..7b315ab 100644 --- a/V8Binding/jni/jni_npobject.cpp +++ b/V8Binding/jni/jni_npobject.cpp @@ -1,46 +1,149 @@ +/* + * 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 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_npobject.h" +#include "jni_class.h" +#include "jni_instance.h" +#include "jni_runtime.h" +#include "jni_utility.h" -namespace V8 { namespace Binding { +namespace JSC { namespace Bindings { +static NPObject* AllocJavaNPObject(NPP, NPClass*) +{ + return static_cast<NPObject*>(malloc(sizeof(JavaNPObject))); +} + +static void FreeJavaNPObject(NPObject* npobj) +{ + JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(npobj); + free(obj); +} -static NPClass JavaNPClass = { +static NPClass JavaNPObjectClass = { NP_CLASS_STRUCT_VERSION, - 0, // allocate, - 0, // free, + AllocJavaNPObject, // allocate, + FreeJavaNPObject, // free, 0, // invalidate JavaNPObject_HasMethod, JavaNPObject_Invoke, 0, // invokeDefault, JavaNPObject_HasProperty, - JavaNPobject_GetProperty, - JavaNPObject_SetProperty, + JavaNPObject_GetProperty, + 0, // setProperty 0, // removeProperty 0, // enumerate 0 // construct }; -NPObject* JavaInstanceToNPObject(PassRefPtr<JavaInstance> instance) { - JavaNPObject* object = new JavaNPObject(instance); - return static_cast<NPObject*>(object); + +NPObject* JavaInstanceToNPObject(JavaInstance* instance) { + JavaNPObject* object = reinterpret_cast<JavaNPObject*>(NPN_CreateObject(0, &JavaNPObjectClass)); + object->_instance = instance; + return reinterpret_cast<NPObject*>(object); } -bool JavaNPObject_HasMethod(NPObject* obj, NPIdentifier name) { - // FIXME: for now, always pretend the object has the named method. - return true; + +// Returns null if obj is not a wrapper of JavaInstance +JavaInstance* ExtractJavaInstance(NPObject* obj) { + if (obj->_class == &JavaNPObjectClass) { + return reinterpret_cast<JavaNPObject*>(obj)->_instance; + } + return 0; } -bool JavaNPObject_Invoke(NPobject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) { +bool JavaNPObject_HasMethod(NPObject* obj, NPIdentifier identifier) { + JavaInstance* instance = ExtractJavaInstance(obj); + if (instance == 0) + return false; + NPUTF8* name = NPN_UTF8FromIdentifier(identifier); + if (name == 0) + return false; + + bool result = (instance->getClass()->methodsNamed(name).size() > 0); + // TODO: use NPN_MemFree + free(name); + + return result; } -bool JavaNPObject_HasProperty(NPObject* obj, NPIdentifier name) { +bool JavaNPObject_Invoke(NPObject* obj, NPIdentifier identifier, + const NPVariant* args, uint32_t argCount, NPVariant* result) { + JavaInstance* instance = ExtractJavaInstance(obj); + if (instance == 0) + return false; + NPUTF8* name = NPN_UTF8FromIdentifier(identifier); + if (name == 0) + return false; + + bool r = instance->invokeMethod(name, args, argCount, result); + + // TODO: use NPN_MemFree + free(name); + return r; + } -bool JavaNPObject_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* ressult) { +bool JavaNPObject_HasProperty(NPObject* obj, NPIdentifier identifier) { + JavaInstance* instance = ExtractJavaInstance(obj); + if (instance == 0) + return false; + NPUTF8* name = NPN_UTF8FromIdentifier(identifier); + if (name == 0) + return false; + bool result = instance->getClass()->fieldNamed(name) != 0; + free(name); + return result; } -bool JavaNPObject_SetProperty(NPObject* obj, NPIdentifier name, const NPVariant* value) { +bool JavaNPObject_GetProperty(NPObject* obj, NPIdentifier identifier, NPVariant* result) { + VOID_TO_NPVARIANT(*result); + JavaInstance* instance = ExtractJavaInstance(obj); + if (instance == 0) + return false; + NPUTF8* name = NPN_UTF8FromIdentifier(identifier); + if (name == 0) + return false; + JavaField* field = instance->getClass()->fieldNamed(name); + free(name); // TODO: use NPN_MemFree + + if (field == 0) { + return false; + } + + jvalue value = getJNIField(instance->javaInstance(), + field->getJNIType(), + field->name(), + field->type()); + convertJValueToNPVariant(value, field->getJNIType(), result); + + return true; } -} } // namespace V8::Binding +}} // namespace diff --git a/V8Binding/jni/jni_npobject.h b/V8Binding/jni/jni_npobject.h index 99fe368..9ba8ced 100644 --- a/V8Binding/jni/jni_npobject.h +++ b/V8Binding/jni/jni_npobject.h @@ -1,26 +1,52 @@ -// A wrapper of a JNI value as an NPObject - +/* + * 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 APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef JNI_NPOBJECT_H_ #define JNI_NPOBJECT_H_ -#include "npapi.h" +#include "npruntime.h" +#include "jni_runtime.h" + #include <JavaVM/jni.h> -namespace V8 { namespace V8Binding { +namespace JSC { namespace Bindings { struct JavaNPObject { NPObject _object; - RefPtr<JavaInstance> _instance; + JavaInstance* _instance; + + ~JavaNPObject() { delete _instance; } }; -NPObject* JavaInstanceToNPObject(PassRefPtr<JavaInstance> instance); +NPObject* JavaInstanceToNPObject(JavaInstance* instance); +JavaInstance* ExtractJavaInstance(NPObject* obj); bool JavaNPObject_HasMethod(NPObject* obj, NPIdentifier name); -bool JavaNPObject_Invoke(NPobject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result); +bool JavaNPObject_Invoke(NPObject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result); bool JavaNPObject_HasProperty(NPObject* obj, NPIdentifier name); bool JavaNPObject_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* ressult); -bool JavaNPObject_SetProperty(NPObject* obj, NPIdentifier name, const NPVariant* value); } } diff --git a/V8Binding/jni/jni_runtime.cpp b/V8Binding/jni/jni_runtime.cpp index 1ff640a..9c87c54 100644 --- a/V8Binding/jni/jni_runtime.cpp +++ b/V8Binding/jni/jni_runtime.cpp @@ -1,5 +1,6 @@ /* * 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 @@ -46,6 +47,22 @@ JavaParameter::JavaParameter (JNIEnv *env, jstring type) } +JavaField::JavaField (JNIEnv *env, jobject aField) +{ + // Get field type + jobject fieldType = callJNIMethod<jobject>(aField, "getType", "()Ljava/lang/Class;"); + jstring fieldTypeName = (jstring)callJNIMethod<jobject>(fieldType, "getName", "()Ljava/lang/String;"); + _type = JavaString(env, fieldTypeName); + _JNIType = JNITypeFromClassName (_type.UTF8String()); + + // Get field name + jstring fieldName = (jstring)callJNIMethod<jobject>(aField, "getName", "()Ljava/lang/String;"); + _name = JavaString(env, fieldName); + + _field = new JObjectWrapper(aField); +} + + JavaMethod::JavaMethod (JNIEnv *env, jobject aMethod) { // Get return type @@ -95,41 +112,93 @@ JavaMethod::~JavaMethod() delete [] _parameters; }; -// JNI method signatures use '/' between components of a class name, but -// we get '.' between components from the reflection API. -static void appendClassName(UString& aString, const char* className) -{ - ASSERT(JSLock::lockCount() > 0); - - char *result, *cp = strdup(className); + +class SignatureBuilder { +public: + explicit SignatureBuilder(int init_size) { + if (init_size <= 0) + init_size = 16; + size_ = init_size; + length_ = 0; + storage_ = (char*)malloc(size_ * sizeof(char)); + } + + ~SignatureBuilder() { + free(storage_); + } + + void append(const char* s) { + int l = strlen(s); + expandIfNeeded(l); + memcpy(storage_ + length_, s, l); + length_ += l; + } + + // JNI method signatures use '/' between components of a class name, but + // we get '.' between components from the reflection API. + void appendClassName(const char* className) { + int l = strlen(className); + expandIfNeeded(l); + + char* sp = storage_ + length_; + const char* cp = className; - result = cp; - while (*cp) { - if (*cp == '.') - *cp = '/'; - cp++; + while (*cp) { + if (*cp == '.') + *sp = '/'; + else + *sp = *cp; + + cp++; + sp++; + } + + length_ += l; } - - aString.append(result); - free (result); -} + // make a duplicated copy of the content. + char* ascii() { + if (length_ == 0) + return NULL; + storage_[length_] = '\0'; + return strndup(storage_, length_); + } + +private: + void expandIfNeeded(int l) { + // expand storage if needed + if (l + length_ >= size_) { + int new_size = 2 * size_; + if (l + length_ >= new_size) + new_size = l + length_ + 1; + + char* new_storage = (char*)malloc(new_size * sizeof(char)); + memcpy(new_storage, storage_, length_); + size_ = new_size; + free(storage_); + storage_ = new_storage; + } + } + + int size_; + int length_; + char* storage_; +}; const char *JavaMethod::signature() const { if (!_signature) { - JSLock lock(false); - - UString signatureBuilder("("); + SignatureBuilder signatureBuilder(64); + signatureBuilder.append("("); for (int i = 0; i < _numParameters; i++) { JavaParameter* aParameter = parameterAt(i); JNIType _JNIType = aParameter->getJNIType(); if (_JNIType == array_type) - appendClassName(signatureBuilder, aParameter->type()); + signatureBuilder.appendClassName(aParameter->type()); else { signatureBuilder.append(signatureFromPrimitiveType(_JNIType)); if (_JNIType == object_type) { - appendClassName(signatureBuilder, aParameter->type()); + signatureBuilder.appendClassName(aParameter->type()); signatureBuilder.append(";"); } } @@ -138,16 +207,16 @@ const char *JavaMethod::signature() const const char *returnType = _returnType.UTF8String(); if (_JNIReturnType == array_type) { - appendClassName(signatureBuilder, returnType); + signatureBuilder.appendClassName(returnType); } else { signatureBuilder.append(signatureFromPrimitiveType(_JNIReturnType)); if (_JNIReturnType == object_type) { - appendClassName(signatureBuilder, returnType); + signatureBuilder.appendClassName(returnType); signatureBuilder.append(";"); } } - _signature = strdup(signatureBuilder.ascii()); + _signature = signatureBuilder.ascii(); } return _signature; diff --git a/V8Binding/jni/jni_runtime.h b/V8Binding/jni/jni_runtime.h index 932f26b..0e3f98f 100644 --- a/V8Binding/jni/jni_runtime.h +++ b/V8Binding/jni/jni_runtime.h @@ -1,5 +1,6 @@ /* * 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 @@ -62,16 +63,17 @@ public: ~JavaString() { } - int length() const { return _utf8String->length(); } + int length() const { return _utf8String.length(); } const char* UTF8String() const { - return _utf8String.c_str(); + return _utf8String.data(); } private: WebCore::CString _utf8String; }; + class JavaParameter { public: @@ -88,6 +90,24 @@ private: }; +class JavaField +{ +public: + JavaField (JNIEnv *env, jobject aField); + + const char* name() const { return _name.UTF8String(); } + const char* type() const { return _type.UTF8String(); } + + JNIType getJNIType() const { return _JNIType; } + +private: + JavaString _name; + JavaString _type; + JNIType _JNIType; + RefPtr<JObjectWrapper> _field; +}; + + class JavaMethod { public: diff --git a/V8Binding/jni/jni_utility.cpp b/V8Binding/jni/jni_utility.cpp index d86dd7b..5ab2041 100644 --- a/V8Binding/jni/jni_utility.cpp +++ b/V8Binding/jni/jni_utility.cpp @@ -1,5 +1,6 @@ /* * 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 @@ -24,8 +25,10 @@ */ #include "config.h" +#include "npruntime.h" #include "jni_utility.h" #include "jni_runtime.h" +#include "jni_npobject.h" #include <dlfcn.h> @@ -342,10 +345,10 @@ jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *sig } -jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* javaClassName) +jvalue convertNPVariantToJValue(NPVariant value, JNIType _JNIType, const char* javaClassName) { jvalue result; - NPVariantType type = value->type; + NPVariantType type = value.type; switch (_JNIType){ case array_type: @@ -354,13 +357,9 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* // First see if we have a Java instance. if (type == NPVariantType_Object) { - NPObject* objectImp = NPVARIANT_TO_OBJECT(*value); - if (objectImp->_class == &JavaNPClass) { - JavaNPObject* imp = static_cast<JavaNPObject*>(objectImp); - JavaInstance *instance = imp->_instance; - if (instance) - result.l = instance->javaInstance(); - } + 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 @@ -377,9 +376,9 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* #else if (type == NPVariantType_String) { #endif - NPString src = NPVARIANT_TO_STRING(*variant); + NPString src = NPVARIANT_TO_STRING(value); JNIEnv *env = getJNIEnv(); - jobject javaString = env->functions->NewStringUTF(env, src.UTF8Characters, src.UTF8Length); + jobject javaString = env->NewStringUTF(src.UTF8Characters); result.l = javaString; } } else if (result.l == 0) @@ -388,8 +387,8 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* break; case boolean_type: { - if (type == NPVariantType_Boolean) - result.z = NPVARIANT_TO_BOOLEAN(*value); + if (type == NPVariantType_Bool) + result.z = NPVARIANT_TO_BOOLEAN(value); else bzero(&result, sizeof(jvalue)); // as void case } @@ -397,7 +396,7 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case byte_type: { if (type == NPVariantType_Int32) - result.b = (byte)NPVARIANT_TO_INT32(*value); + result.b = (char)NPVARIANT_TO_INT32(value); else bzero(&result, sizeof(jvalue)); } @@ -405,7 +404,7 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case char_type: { if (type == NPVariantType_Int32) - result.c = (char)NPVARIANT_TO_INT32(*value); + result.c = (char)NPVARIANT_TO_INT32(value); else bzero(&result, sizeof(jvalue)); } @@ -413,7 +412,7 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case short_type: { if (type == NPVariantType_Int32) - result.s = (jshort)NPVARIANT_TO_INT32(*value); + result.s = (jshort)NPVARIANT_TO_INT32(value); else bzero(&result, sizeof(jvalue)); } @@ -421,7 +420,7 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case int_type: { if (type == NPVariantType_Int32) - result.i = (jint)NPVARIANT_TO_INT32(*value); + result.i = (jint)NPVARIANT_TO_INT32(value); else bzero(&result, sizeof(jvalue)); } @@ -429,9 +428,9 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case long_type: { if (type == NPVariantType_Int32) - result.j = (jlong)NPVARIANT_TO_INT32(*value); + result.j = (jlong)NPVARIANT_TO_INT32(value); else if (type == NPVariantType_Double) - result.j = (jlong)NPVARIANT_TO_DOUBLE(*value); + result.j = (jlong)NPVARIANT_TO_DOUBLE(value); else bzero(&result, sizeof(jvalue)); } @@ -439,9 +438,9 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case float_type: { if (type == NPVariantType_Int32) - result.j = (jfloat)NPVARIANT_TO_INT32(*value); + result.j = (jfloat)NPVARIANT_TO_INT32(value); else if (type == NPVariantType_Double) - result.j = (jfloat)NPVARIANT_TO_DOUBLE(*value); + result.j = (jfloat)NPVARIANT_TO_DOUBLE(value); else bzero(&result, sizeof(jvalue)); } @@ -449,9 +448,9 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* case double_type: { if (type == NPVariantType_Int32) - result.j = (jdouble)NPVARIANT_TO_INT32(*value); + result.j = (jdouble)NPVARIANT_TO_INT32(value); else if (type == NPVariantType_Double) - result.j = (jdouble)NPVARIANT_TO_DOUBLE(*value); + result.j = (jdouble)NPVARIANT_TO_DOUBLE(value); else bzero(&result, sizeof(jvalue)); } @@ -469,6 +468,74 @@ jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* return result; } + +void convertJValueToNPVariant(jvalue value, JNIType _JNIType, NPVariant* result) +{ + switch (_JNIType){ + case void_type: { + VOID_TO_NPVARIANT(*result); + } + break; + + case object_type: { + if (value.l != 0) { + 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: { + 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(fqian): 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/V8Binding/jni/jni_utility.h b/V8Binding/jni/jni_utility.h index 28b0763..dfa97ef 100644 --- a/V8Binding/jni/jni_utility.h +++ b/V8Binding/jni/jni_utility.h @@ -1,5 +1,6 @@ /* * 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 @@ -27,6 +28,7 @@ #define _JNI_UTILITY_H_ #include <JavaVM/jni.h> +#include "npruntime.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 @@ -52,8 +54,6 @@ namespace JSC { namespace Bindings { -class JavaParameter; - const char *getCharactersFromJString(jstring aJString); void releaseCharactersForJString(jstring aJString, const char *s); @@ -66,7 +66,8 @@ JNIType JNITypeFromClassName(const char *name); JNIType JNITypeFromPrimitiveType(char type); const char *signatureFromPrimitiveType(JNIType type); -jvalue convertNPVariantToJValue(NPVariant*, JNIType, const char* javaClassName); +jvalue convertNPVariantToJValue(NPVariant, JNIType, const char* javaClassName); +void convertJValueToNPVariant(jvalue, JNIType, NPVariant*); jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature); |