| /* | 
 |  * 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()); | 
 | } |