Bug 984458 - e. Add NativeJSObject object getter; r=blassey

This commit is contained in:
Jim Chen 2014-04-01 15:16:55 -04:00
parent 825979accf
commit 7e177c1c5f
3 changed files with 110 additions and 1 deletions

View File

@ -15,9 +15,16 @@ import org.mozilla.gecko.mozglue.JNITarget;
public class NativeJSObject
{
private final NativeJSContainer mContainer;
private final int mObjectIndex;
protected NativeJSObject() {
mContainer = (NativeJSContainer)this;
mObjectIndex = -1;
}
private NativeJSObject(NativeJSContainer container, int index) {
mContainer = container;
mObjectIndex = index;
}
/**
@ -68,6 +75,22 @@ public class NativeJSObject
*/
public native int getInt(String name);
/**
* Returns the value of an object property.
*
* @param name
* Property name
* @throws IllegalArgumentException
* If the property does not exist or if its type does not match the return type
* @throws NullPointerException
* If name is null or if this JS object has been disposed
* @throws IllegalThreadStateException
* If not called on the thread this object is attached to
* @throws UnsupportedOperationException
* If an internal JSAPI call failed
*/
public native NativeJSObject getObject(String name);
/**
* Returns the value of a string property.
*

View File

@ -666,6 +666,25 @@ Java_org_mozilla_gecko_util_NativeJSObject_getInt(JNIEnv * arg0, jobject arg1, j
#ifdef JNI_STUBS
typedef jobject (*Java_org_mozilla_gecko_util_NativeJSObject_getObject_t)(JNIEnv *, jobject, jstring);
static Java_org_mozilla_gecko_util_NativeJSObject_getObject_t f_Java_org_mozilla_gecko_util_NativeJSObject_getObject;
extern "C" NS_EXPORT jobject JNICALL
Java_org_mozilla_gecko_util_NativeJSObject_getObject(JNIEnv * arg0, jobject arg1, jstring arg2) {
if (!f_Java_org_mozilla_gecko_util_NativeJSObject_getObject) {
arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
"JNI Function called before it was loaded");
return nullptr;
}
return f_Java_org_mozilla_gecko_util_NativeJSObject_getObject(arg0, arg1, arg2);
}
#endif
#ifdef JNI_BINDINGS
xul_dlsym("Java_org_mozilla_gecko_util_NativeJSObject_getObject", &f_Java_org_mozilla_gecko_util_NativeJSObject_getObject);
#endif
#ifdef JNI_STUBS
typedef jstring (*Java_org_mozilla_gecko_util_NativeJSObject_getString_t)(JNIEnv *, jobject, jstring);
static Java_org_mozilla_gecko_util_NativeJSObject_getString_t f_Java_org_mozilla_gecko_util_NativeJSObject_getString;
extern "C" NS_EXPORT jstring JNICALL

View File

@ -38,6 +38,13 @@ public:
env, jNativeJSObject, "mContainer",
"Lorg/mozilla/gecko/util/NativeJSContainer;");
MOZ_ASSERT(jObjectContainer);
jObjectIndex = AndroidBridge::GetFieldID(
env, jNativeJSObject, "mObjectIndex", "I");
MOZ_ASSERT(jObjectIndex);
jObjectConstructor = AndroidBridge::GetMethodID(
env, jNativeJSObject, "<init>",
"(Lorg/mozilla/gecko/util/NativeJSContainer;I)V");
MOZ_ASSERT(jContainerConstructor);
}
static jobject CreateInstance(JNIEnv* env, JSContext* cx,
@ -119,7 +126,37 @@ public:
!container->EnsureObject(env)) { // Do thread check
return nullptr;
}
return container->mJSObject;
const jint index = env->GetIntField(object, jObjectIndex);
if (index < 0) {
// -1 for index field means it's the root object of the container
return container->mJSObject;
}
return container->mRootedObjects[index];
}
static jobject CreateObjectInstance(JNIEnv* env, jobject object,
JS::HandleObject jsObject) {
MOZ_ASSERT(object);
MOZ_ASSERT(jsObject);
AutoLocalJNIFrame frame(env, 2);
jobject instance = GetInstanceFromObject(env, object);
NativeJSContainer* const container = FromInstance(env, instance);
if (!container) {
return nullptr;
}
size_t newIndex = container->mRootedObjects.length();
if (!container->mRootedObjects.append(jsObject)) {
AndroidBridge::ThrowException(env,
"java/lang/OutOfMemoryError", "Cannot allocate object");
return nullptr;
}
const jobject newObject =
env->NewObject(jNativeJSObject, jObjectConstructor,
instance, newIndex);
AndroidBridge::HandleUncaughtException(env);
MOZ_ASSERT(newObject);
return frame.Pop(newObject);
}
// Make sure we have a JSObject and deserialize if necessary/possible
@ -161,6 +198,8 @@ private:
static jmethodID jContainerConstructor;
static jclass jNativeJSObject;
static jfieldID jObjectContainer;
static jfieldID jObjectIndex;
static jmethodID jObjectConstructor;
static jobject CreateInstance(JNIEnv* env,
NativeJSContainer* nativeObject) {
@ -182,6 +221,8 @@ private:
JS::Heap<JSObject*> mJSObject;
// Serialized object, or empty if object is in deserialized form
JSAutoStructuredCloneBuffer mBuffer;
// Objects derived from mJSObject
Vector<JS::Heap<JSObject*>, 4> mRootedObjects;
// Create a new container containing the given deserialized object
NativeJSContainer(JSContext* cx, JS::HandleObject object)
@ -213,6 +254,8 @@ jfieldID NativeJSContainer::jContainerNativeObject = 0;
jmethodID NativeJSContainer::jContainerConstructor = 0;
jclass NativeJSContainer::jNativeJSObject = 0;
jfieldID NativeJSContainer::jObjectContainer = 0;
jfieldID NativeJSContainer::jObjectIndex = 0;
jmethodID NativeJSContainer::jObjectConstructor = 0;
jobject
CreateNativeJSContainer(JNIEnv* env, JSContext* cx, JS::HandleObject object)
@ -335,6 +378,24 @@ struct StringProperty
}
};
struct ObjectProperty
{
typedef jobject Type;
static bool InValue(JS::HandleValue val) {
return val.isObjectOrNull();
}
static Type FromValue(JNIEnv* env, jobject instance,
JSContext* cx, JS::HandleValue val) {
if (val.isNull()) {
return nullptr;
}
JS::RootedObject object(cx, &val.toObject());
return NativeJSContainer::CreateObjectInstance(env, instance, object);
}
};
struct HasProperty
{
typedef jboolean Type;
@ -413,6 +474,12 @@ Java_org_mozilla_gecko_util_NativeJSObject_getInt(JNIEnv* env, jobject instance,
return GetProperty<IntProperty>(env, instance, name);
}
NS_EXPORT jobject JNICALL
Java_org_mozilla_gecko_util_NativeJSObject_getObject(JNIEnv* env, jobject instance, jstring name)
{
return GetProperty<ObjectProperty>(env, instance, name);
}
NS_EXPORT jstring JNICALL
Java_org_mozilla_gecko_util_NativeJSObject_getString(JNIEnv* env, jobject instance, jstring name)
{