summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wing <ewing -dot- public |-at-| gmail.com>2014-05-19 17:15:49 -0700
committerOliver Buchtala <oliver.buchtala@googlemail.com>2014-05-26 22:35:27 +0200
commit6f69555225d818530e60cc50a7cd57f8bafd46f1 (patch)
tree137592820fa5c1d40a558f8dd13ef2880b430ae2
parent01f8253b192224d8996e5bffd3c8121fa32ad0ea (diff)
downloadswig-6f69555225d818530e60cc50a7cd57f8bafd46f1.tar.gz
JavaScriptCore: Fixed exception object so sourceURL (file name), line (number), and message can be recovered.
The current implementation only returns an error string. But this is insufficient for debugging (what file and line number did it fail at?). As documented here: http://parmanoir.com/Taming_JavascriptCore_within_and_without_WebView converting the JSValueRef of string to an JSObjectRef (via JSValueToObject) will trigger JSCore into filling the "sourceURL" and "line" properties into the object so they can be inspected by the caller. Additionally, JavaScriptCore has a "message" property which contains the message string. JSCore doesn't seem to be filling this in for us automatically, unlike "sourceURL" and "line". So this patch also fills that property in too. Thanks to Brian Barnes for the detailed information about "sourceURL", "line", and "message". Below is an example (derived from Brian Barnes's information) on how you typically use/extract these exception details. void script_exception_to_string(JSContextRef js_context,JSValueRef exception_value_ref,char* return_error_string, int return_error_string_max_length) { JSObjectRef exception_object; JSValueRef value_ref; JSStringRef jsstring_property_name = NULL; JSValueRef temporary_exception = NULL; JSStringRef js_return_string = NULL; size_t bytes_needed; char* c_result_string = NULL; exception_object = JSValueToObject(js_context, exception_value_ref, NULL); // source and line numbers strcpy(return_error_string,"["); jsstring_property_name = JSStringCreateWithUTF8CString("sourceURL"); value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &temporary_exception); JSStringRelease(jsstring_property_name); js_return_string = JSValueToStringCopy(js_context, value_ref, NULL); bytes_needed = JSStringGetMaximumUTF8CStringSize(js_return_string); c_result_string = (char*)calloc(bytes_needed, sizeof(char)); JSStringGetUTF8CString(js_return_string, c_result_string, bytes_needed); SDL_Log("c_result_string: %s\n", c_result_string); JSStringRelease(js_return_string); strncat(return_error_string, c_result_string, return_error_string_max_length-1); free(c_result_string); strncat(return_error_string, ":", return_error_string_max_length-1); jsstring_property_name = JSStringCreateWithUTF8CString("line"); value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &temporary_exception); JSStringRelease(jsstring_property_name); js_return_string = JSValueToStringCopy(js_context, value_ref, NULL); bytes_needed = JSStringGetMaximumUTF8CStringSize(js_return_string); c_result_string = (char*)calloc(bytes_needed, sizeof(char)); JSStringGetUTF8CString(js_return_string, c_result_string, bytes_needed); SDL_Log("c_result_string: %s\n", c_result_string); JSStringRelease(js_return_string); strncat(return_error_string, c_result_string, return_error_string_max_length-1); //SDL_Log("c_result_string: %s\n", c_result_string); free(c_result_string); strncat(return_error_string, "]", return_error_string_max_length-1); /* get message */ jsstring_property_name = JSStringCreateWithUTF8CString("message"); value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &temporary_exception); JSStringRelease(jsstring_property_name); if(NULL == value_ref) { strncat(return_error_string, "Unknown Error", return_error_string_max_length-1); } else { js_return_string = JSValueToStringCopy(js_context, value_ref, NULL); bytes_needed = JSStringGetMaximumUTF8CStringSize(js_return_string); c_result_string = (char*)calloc(bytes_needed, sizeof(char)); JSStringGetUTF8CString(js_return_string, c_result_string, bytes_needed); SDL_Log("c_result_string: %s\n", c_result_string); JSStringRelease(js_return_string); strncat(return_error_string, c_result_string, return_error_string_max_length-1); //SDL_Log("c_result_string: %s\n", c_result_string); free(c_result_string); } } To use: if(js_exception) { char return_error_string[256]; script_exception_to_string(js_context, js_exception, return_error_string, 256); SDL_Log("Compile error is %s", return_error_string); }
-rw-r--r--Lib/javascript/jsc/javascriptrun.swg25
1 files changed, 23 insertions, 2 deletions
diff --git a/Lib/javascript/jsc/javascriptrun.swg b/Lib/javascript/jsc/javascriptrun.swg
index ae1567e87..1fde8855b 100644
--- a/Lib/javascript/jsc/javascriptrun.swg
+++ b/Lib/javascript/jsc/javascriptrun.swg
@@ -9,8 +9,29 @@
SWIGRUNTIME void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* type) {
JSStringRef message = JSStringCreateWithUTF8CString(type);
- *exception = JSValueMakeString(context, message);
- JSStringRelease(message);
+ JSStringRef message_property_key;
+ JSObjectRef exception_object;
+ JSValueRef exception_value;
+ JSValueRef message_value;
+ exception_value = JSValueMakeString(context, message);
+ /* Converting the result to an object will let JavascriptCore add "sourceURL" (file) and "line" (number) to the exception,
+ instead of just returning a raw string. This is extremely important for debugging your errors.
+ */
+ exception_object = JSValueToObject(context, exception_value, NULL);
+
+ /* Additionally, JSCore uses "message" which contains the error description.
+ But it seems that unlike "sourceURL" and "line", converting to an object is not automatically doing this.
+ So we can add it ourselves.
+ */
+ message_property_key = JSStringCreateWithUTF8CString("message");
+ message_value = JSValueMakeString(context, message);
+ JSObjectSetProperty(context, exception_object, message_property_key, message_value, kJSClassAttributeNone, NULL);
+
+ /* Return the exception_object */
+ *exception = exception_object;
+
+ JSStringRelease(message_property_key);
+ JSStringRelease(message);
}
SWIGRUNTIME void SWIG_JSC_exception(JSContextRef context, JSValueRef *exception, int code, const char* msg) {