|  | /* | 
|  | * Copyright 2008 Google Inc. | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
|  | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
|  | * License for the specific language governing permissions and limitations under | 
|  | * the License. | 
|  | */ | 
|  |  | 
|  | #include <iostream> | 
|  | #include <JavaScriptCore/JavaScriptCore.h> | 
|  | #include "gwt-webkit.h" | 
|  | #include "JStringWrap.h" | 
|  | #include "java-dispatch.h" | 
|  | #include "trace.h" | 
|  |  | 
|  |  | 
|  | // http://unixjunkie.blogspot.com/2006/07/access-argc-and-argv-from-anywhere.html | 
|  | extern "C" int *_NSGetArgc(void); | 
|  | extern "C" char ***_NSGetArgv(void); | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JSContextRef ToJSContextRef(jint context) { | 
|  | return reinterpret_cast<JSContextRef>(context); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JSValueRef ToJSValueRef(jint value) { | 
|  | return reinterpret_cast<JSValueRef>(value); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JSObjectRef ToJSObjectRef(JSContextRef jsContext, jint object, | 
|  | JSValueRef* jsException) { | 
|  | JSValueRef jsValue = reinterpret_cast<JSValueRef>(object); | 
|  | if (!jsValue || !JSValueIsObject(jsContext, jsValue)) { | 
|  | return NULL; | 
|  | } | 
|  | return JSValueToObject(jsContext, jsValue, jsException); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JSObjectRef ToJSObjectRef(JSContextRef jsContext, JSValueRef jsValue, | 
|  | JSValueRef* jsException) { | 
|  | if (!jsValue || !JSValueIsObject(jsContext, jsValue)) { | 
|  | return NULL; | 
|  | } | 
|  | return JSValueToObject(jsContext, jsValue, jsException); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JSObjectRef GetStringConstructor(JSContextRef jsContext, | 
|  | JSValueRef* jsException) { | 
|  | // This could only be cached relative to jsContext. | 
|  | JSStringRef script = JSStringCreateWithUTF8CString("(String)"); | 
|  | JSValueRef ctorVal = JSEvaluateScript(jsContext, script, NULL, NULL, 0, jsException); | 
|  | JSStringRelease(script); | 
|  | return ToJSObjectRef(jsContext, ctorVal, jsException); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | bool IsObjectOfStringConstructor(JSContextRef jsContext, JSValueRef jsValue, | 
|  | JSValueRef* jsException) { | 
|  | JSObjectRef jsObject = ToJSObjectRef(jsContext, jsValue, jsException); | 
|  | if (!jsObject) { | 
|  | return false; | 
|  | } | 
|  | JSObjectRef stringCtor = GetStringConstructor(jsContext, jsException); | 
|  | if (!stringCtor) { | 
|  | return false; | 
|  | } | 
|  | return JSValueIsInstanceOfConstructor(jsContext, jsObject, stringCtor, | 
|  | jsException); | 
|  | } | 
|  |  | 
|  | #if 0 // For debugging purposes only. | 
|  | void PrintJSString(JSStringRef jsString) | 
|  | { | 
|  | size_t length = JSStringGetMaximumUTF8CStringSize(jsString); | 
|  | char* buffer = new char[length]; | 
|  | JSStringGetUTF8CString(jsString, buffer, length); | 
|  | std::cerr << "JSString: " << buffer << std::endl; | 
|  | delete[] buffer; | 
|  | } | 
|  |  | 
|  | void PrintJSValue(JSContextRef jsContext, JSValueRef jsValue) | 
|  | { | 
|  | JSValueRef jsException = NULL; | 
|  | JSStringRef jsResult = JSValueToStringCopy(jsContext, jsValue, | 
|  | &jsException); | 
|  | if (!jsException && jsValue) { | 
|  | PrintJSString(jsResult); | 
|  | } else { | 
|  | std::cerr << "Could not convert the value to string." << std::endl; | 
|  | } | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JSStringRef ToJSStringRef(JNIEnv* env, jstring jstr) { | 
|  | if (!jstr) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | JStringWrap jstrw(env, jstr); | 
|  | if (!jstrw.jstr()) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return JSStringCreateWithCharacters(static_cast<const JSChar*>(jstrw.jstr()), | 
|  | static_cast<size_t>(jstrw.length())); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsNull | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueIsNull(jsContext, jsValue)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsUndefined | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueIsUndefined(jsContext, jsValue)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getJsUndefined | 
|  | (JNIEnv *env, jclass klass, jint context) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | return static_cast<jint>(NULL); | 
|  | } | 
|  |  | 
|  | JSValueRef jsUndefined = JSValueMakeUndefined(jsContext); | 
|  | JSValueProtectChecked(jsContext, jsUndefined); | 
|  | TR_LEAVE(); | 
|  | return reinterpret_cast<jint>(jsUndefined); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getJsNull | 
|  | (JNIEnv *env, jclass klass, jint context) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | return static_cast<jint>(NULL); | 
|  | } | 
|  | JSValueRef jsNull = JSValueMakeNull(jsContext); | 
|  | JSValueProtectChecked(jsContext, jsNull); | 
|  | TR_LEAVE(); | 
|  | return reinterpret_cast<jint>(jsNull); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsBoolean | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueIsBoolean(jsContext, jsValue)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsNumber | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueIsNumber(jsContext, jsValue)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_toJsBooleanImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jboolean jValue, jintArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueRef jsValue = JSValueMakeBoolean(jsContext, static_cast<bool>(jValue)); | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<const jint*>(&jsValue)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | JSValueProtectChecked(jsContext, jsValue); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_gcUnprotect | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | return; | 
|  | } | 
|  | JSValueUnprotectChecked(jsContext, jsValue); | 
|  | TR_LEAVE(); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_toJsNumberImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jdouble jValue, jintArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueRef jsValue = JSValueMakeNumber(jsContext, static_cast<jdouble>(jValue)); | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<const jint*>(&jsValue)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsValue); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_executeScriptWithInfoImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jstring jScript, jstring jUrl, | 
|  | jint jLine, jintArray rval) { | 
|  | TR_ENTER(); | 
|  | JSValueRef jsException = NULL; | 
|  |  | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSStringRef jsScript = ToJSStringRef(env, jScript); | 
|  | if (!jsScript) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSStringRef jsUrl = ToJSStringRef(env, jUrl); | 
|  |  | 
|  | // Evaluate will set this to global object. | 
|  | JSValueRef jsResult = JSEvaluateScript(jsContext, jsScript, NULL, jsUrl, | 
|  | static_cast<int>(jLine), &jsException); | 
|  | if (jsException) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSStringRelease(jsScript); | 
|  | if (jsUrl) { | 
|  | JSStringRelease(jsUrl); | 
|  | } | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<const jint*>(&jsResult)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsResult); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_toJsStringImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jstring jValue, jintArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSStringRef jsString = ToJSStringRef(env, jValue); | 
|  | if (!jsString) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueRef jsValue = JSValueMakeString(jsContext, jsString); | 
|  | JSStringRelease(jsString); | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<const jint*>(&jsValue)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsValue); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsStringImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint value, jbooleanArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | bool isString = JSValueIsString(jsContext, jsValue); | 
|  | if (!isString) { | 
|  | JSValueRef jsException = NULL; | 
|  | isString = IsObjectOfStringConstructor(jsContext, jsValue, &jsException); | 
|  | if (jsException) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | } | 
|  |  | 
|  | jboolean jIsString = static_cast<jboolean>(isString); | 
|  | env->SetBooleanArrayRegion(rval, 0, 1, &jIsString); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_invokeImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint scriptValue, | 
|  | jstring jMethodName, jint thisVal, jintArray jArgs, jint jArgsLength, | 
|  | jintArray rval) { | 
|  | TR_ENTER(); | 
|  |  | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSObjectRef jsScriptObj = ToJSObjectRef(jsContext, scriptValue, NULL); | 
|  | if (!jsScriptObj) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueRef jsThisVal = ToJSValueRef(thisVal); | 
|  | JSObjectRef jsThisObj = NULL; | 
|  | // If thisVal is null, jsNull, or jsUndefined use the script object | 
|  | // as this. | 
|  | if (!jsThisVal || JSValueIsNull(jsContext, jsThisVal) | 
|  | || JSValueIsUndefined(jsContext, jsThisVal)) { | 
|  | jsThisObj = jsScriptObj; | 
|  | } else { | 
|  | // If we are given a value, ensure that it is an object. | 
|  | jsThisObj = ToJSObjectRef(jsContext, jsThisVal, NULL); | 
|  | if (!jsThisObj) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  | } | 
|  |  | 
|  | JSStringRef jsMethodName = ToJSStringRef(env, jMethodName); | 
|  | if (!jsMethodName) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSObjectRef jsMethod = ToJSObjectRef(jsContext, JSObjectGetProperty(jsContext, | 
|  | jsScriptObj, jsMethodName, NULL), NULL); | 
|  | if (!jsMethod || !JSObjectIsFunction(jsContext, jsMethod)) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSStringRelease(jsMethodName); | 
|  |  | 
|  | // NOTE (knorton): Fix for 64-bit. | 
|  | JSValueRef* jsArgs = new JSValueRef[static_cast<size_t>(jArgsLength)]; | 
|  | env->GetIntArrayRegion(jArgs, 0, jArgsLength, | 
|  | reinterpret_cast<jint*>(jsArgs)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | delete[] jsArgs; | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueRef jsException = NULL; | 
|  | JSValueRef jsResult = JSObjectCallAsFunction(jsContext, jsMethod, jsThisObj, | 
|  | static_cast<size_t>(jArgsLength), jsArgs, &jsException); | 
|  | if (jsException) { | 
|  | TR_FAIL(); | 
|  | delete[] jsArgs; | 
|  | return JNI_FALSE; | 
|  | } | 
|  | delete[] jsArgs; | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<const jint*>(&jsResult)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsResult); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsObject | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueIsObject(jsContext, jsValue)); | 
|  | } | 
|  |  | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_toBooleanImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint value, jbooleanArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | jboolean jResult = static_cast<jboolean>(JSValueToBoolean(jsContext, jsValue)); | 
|  | env->SetBooleanArrayRegion(rval, 0, 1, &jResult); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_toDoubleImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint value, jdoubleArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueRef jsException = NULL; | 
|  | double result = JSValueToNumber(jsContext, jsValue, &jsException); | 
|  | if (jsException) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | env->SetDoubleArrayRegion(rval, 0, 1, static_cast<jdouble*>(&result)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_toStringImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint value, jobjectArray rval) { | 
|  | TR_ENTER(); | 
|  | JSValueRef jsException = NULL; | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | jstring jResult = NULL; | 
|  | // Convert all objects to their string representation, EXCEPT | 
|  | // null and undefined which will be returned as a true NULL. | 
|  | if (!JSValueIsNull(jsContext, jsValue) && | 
|  | !JSValueIsUndefined(jsContext, jsValue)) { | 
|  | JSStringRef jsResult = JSValueToStringCopy(jsContext, jsValue, &jsException); | 
|  | if (jsException) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | jResult = env->NewString( | 
|  | static_cast<const jchar*>(JSStringGetCharactersPtr(jsResult)), | 
|  | static_cast<jsize>(JSStringGetLength(jsResult))); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSStringRelease(jsResult); | 
|  | } | 
|  |  | 
|  | env->SetObjectArrayElement(rval, 0, jResult); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_wrapDispatchObjectImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jobject dispatch, jintArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSObjectRef jsDispatch = gwt::DispatchObjectCreate(jsContext, dispatch); | 
|  | if (!jsDispatch || env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<jint*>(&jsDispatch)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsDispatch); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_unwrapDispatchObjectImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint value, jobjectArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | if (!JSValueIsObjectOfClass(jsContext, jsValue, gwt::GetDispatchObjectClass())) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSObjectRef jsObject = ToJSObjectRef(jsContext, jsValue, NULL); | 
|  | if (!jsObject) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | env->SetObjectArrayElement(rval, 0, reinterpret_cast<jobject>(JSObjectGetPrivate(jsObject))); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_initImpl | 
|  | (JNIEnv *env, jclass klass, jclass dispatchObjectClass, | 
|  | jclass dispatchMethodClass, jclass lowLevelSafClass) { | 
|  | TR_ENTER(); | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(gwt::Initialize(env, dispatchObjectClass, dispatchMethodClass, lowLevelSafClass)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_wrapDispatchMethodImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jstring name, jobject jDispatch, | 
|  | jintArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JStringWrap nameWrap(env, name); | 
|  | std::string nameStr(nameWrap.str()); | 
|  | JSObjectRef jsDispatch = gwt::DispatchMethodCreate(jsContext, nameStr, | 
|  | jDispatch); | 
|  | if (!jsDispatch || env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<jint*>(&jsDispatch)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsDispatch); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jstring JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getTypeString | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | switch (JSValueGetType(jsContext, jsValue)) { | 
|  | case kJSTypeUndefined: | 
|  | return env->NewStringUTF("undefined"); | 
|  | case kJSTypeNull: | 
|  | return env->NewStringUTF("null"); | 
|  | case kJSTypeBoolean: | 
|  | return env->NewStringUTF("boolean"); | 
|  | case kJSTypeNumber: | 
|  | return env->NewStringUTF("number"); | 
|  | case kJSTypeString: | 
|  | return env->NewStringUTF("string"); | 
|  | case kJSTypeObject: | 
|  | return (JSValueIsObjectOfClass(jsContext, jsValue, gwt::GetDispatchObjectClass())) | 
|  | ? env->NewStringUTF("Java object") : env->NewStringUTF("JavaScript object"); | 
|  | default: | 
|  | return env->NewStringUTF("unknown"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isDispatchObjectImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jint value, jbooleanArray rval) { | 
|  | TR_ENTER(); | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | jboolean jIsDispatchObject = static_cast<jboolean>(JSValueIsObjectOfClass( | 
|  | jsContext, jsValue, gwt::GetDispatchObjectClass())); | 
|  | env->SetBooleanArrayRegion(rval, 0, 1, &jIsDispatchObject); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jint JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getArgc | 
|  | (JNIEnv *env, jclass klass) { | 
|  | return *_NSGetArgc(); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jstring JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getArgv | 
|  | (JNIEnv *env, jclass klass, jint index) { | 
|  | int argc = *_NSGetArgc(); | 
|  | if (index < 0 || index >= argc) { | 
|  | return 0; | 
|  | } | 
|  | char **argv = *_NSGetArgv(); | 
|  | return env->NewStringUTF(argv[index]); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_getGlobalJsObjectImpl | 
|  | (JNIEnv *env, jclass klass, jint context, jintArray rval) { | 
|  | TR_ENTER(); | 
|  |  | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSObjectRef jsGlobalObject = JSContextGetGlobalObject(jsContext); | 
|  | env->SetIntArrayRegion(rval, 0, 1, reinterpret_cast<jint*>(&jsGlobalObject)); | 
|  | if (env->ExceptionCheck()) { | 
|  | TR_FAIL(); | 
|  | return JNI_FALSE; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsGlobalObject); | 
|  |  | 
|  | TR_LEAVE(); | 
|  | return JNI_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_gcProtect | 
|  | (JNIEnv *env, jclass klass, jint context, jint value) { | 
|  | TR_ENTER(); | 
|  |  | 
|  | JSContextRef jsContext = ToJSContextRef(context); | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | if (!jsContext || !jsValue) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | JSValueProtectChecked(jsContext, jsValue); | 
|  | TR_LEAVE(); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_retainJsGlobalContext | 
|  | (JNIEnv *env, jclass klass, jint context) { | 
|  | TR_ENTER(); | 
|  | JSGlobalContextRef jsContext = reinterpret_cast<JSGlobalContextRef>(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return; | 
|  | } | 
|  | JSGlobalContextRetain(jsContext); | 
|  | TR_LEAVE(); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT void JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_releaseJsGlobalContext | 
|  | (JNIEnv *env, jclass klass, jint context) { | 
|  | TR_ENTER(); | 
|  | JSGlobalContextRef jsContext = reinterpret_cast<JSGlobalContextRef>(context); | 
|  | if (!jsContext) { | 
|  | TR_FAIL(); | 
|  | return; | 
|  | } | 
|  | JSGlobalContextRelease(jsContext); | 
|  | TR_LEAVE(); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * | 
|  | */ | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isGcProtected | 
|  | (JNIEnv *env, jclass klass, jint value) { | 
|  | JSValueRef jsValue = ToJSValueRef(value); | 
|  | TR_ENTER(); | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueIsProtected(jsValue)); | 
|  | } | 
|  |  | 
|  | JNIEXPORT jboolean JNICALL Java_com_google_gwt_dev_shell_mac_LowLevelSaf_isJsValueProtectionCheckingEnabledImpl | 
|  | (JNIEnv *env, jclass klass) { | 
|  | TR_ENTER(); | 
|  | TR_LEAVE(); | 
|  | return static_cast<jboolean>(JSValueProtectCheckingIsEnabled()); | 
|  | } |