Skip to content

Commit

Permalink
JavaScriptCore: Fixed exception object so sourceURL (file name), line…
Browse files Browse the repository at this point in the history
… (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);
}
  • Loading branch information
Eric Wing authored and oliver7654 committed May 26, 2014
1 parent 01f8253 commit 6f69555
Showing 1 changed file with 23 additions and 2 deletions.
25 changes: 23 additions & 2 deletions Lib/javascript/jsc/javascriptrun.swg
Expand Up @@ -9,8 +9,29 @@


SWIGRUNTIME void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* type) { SWIGRUNTIME void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* type) {
JSStringRef message = JSStringCreateWithUTF8CString(type); JSStringRef message = JSStringCreateWithUTF8CString(type);
*exception = JSValueMakeString(context, message); JSStringRef message_property_key;
JSStringRelease(message); 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) { SWIGRUNTIME void SWIG_JSC_exception(JSContextRef context, JSValueRef *exception, int code, const char* msg) {
Expand Down

0 comments on commit 6f69555

Please sign in to comment.