From: Daniel Carl Date: Sat, 11 Jan 2014 22:16:25 +0000 (+0100) Subject: Run hint script as anonymous object. X-Git-Url: https://git.owens.tech/assets/favicon.png/assets/favicon.png/git?a=commitdiff_plain;h=0cf646a648a964e3373d8de97d5ccb4cb487e338;p=vimb.git Run hint script as anonymous object. This avoids clashes between scripts on pages that defined a variable VbHint. --- diff --git a/src/hints.c b/src/hints.c index 69da66d..07e4ffd 100644 --- a/src/hints.c +++ b/src/hints.c @@ -30,26 +30,36 @@ #include "input.h" #include "map.h" -#define HINT_VAR "VbHint" #define HINT_FILE "hints.js" static struct { - guint num; /* olds the numeric filter for hints typed by the user */ - char mode; /* mode identifying char - that last char of the hint prompt */ - int promptlen; /* lenfth of the hint prompt chars 2 or 3 */ - gboolean gmode; /* indicate if the hints g mode is used */ + JSObjectRef obj; /* the js object */ + guint num; /* olds the numeric filter for hints typed by the user */ + char mode; /* mode identifying char - that last char of the hint prompt */ + int promptlen; /* lenfth of the hint prompt chars 2 or 3 */ + gboolean gmode; /* indicate if the hints g mode is used */ + JSContextRef ctx; } hints; + extern VbCore vb; -static void run_script(char *js); +static JSObjectRef create_hints_object(WebKitWebFrame *frame, const char *script); +static void call_hints_function(const char *func, int count, JSValueRef params[]); +static char *js_ref_to_string(JSContextRef context, JSValueRef ref); +static JSValueRef js_string_to_ref(JSContextRef ctx, const char *string); void hints_init(WebKitWebFrame *frame) { - char *value = NULL; - vb_eval_script(frame, HINTS_JS, HINT_FILE, &value); - g_free(value); + if (hints.obj) { + JSValueUnprotect(hints.ctx, hints.obj); + hints.obj = NULL; + } + if (!hints.obj) { + hints.obj = create_hints_object(frame, HINTS_JS); + hints.ctx = webkit_web_frame_get_global_context(frame); + } } VbResult hints_keypress(int key) @@ -100,15 +110,11 @@ VbResult hints_keypress(int key) void hints_clear(void) { - char *js, *value = NULL; - if (vb.mode->flags & FLAG_HINTING) { vb.mode->flags &= ~FLAG_HINTING; vb_set_input_text(""); - js = g_strconcat(HINT_VAR, ".clear();", NULL); - vb_eval_script(webkit_web_view_get_main_frame(vb.gui.webview), js, HINT_FILE, &value); - g_free(value); - g_free(js); + + call_hints_function("clear", 0, NULL); g_signal_emit_by_name(vb.gui.webview, "hovering-over-link", NULL, NULL); } @@ -116,8 +122,6 @@ void hints_clear(void) void hints_create(const char *input) { - char *js = NULL; - /* check if the input contains a valid hinting prompt */ if (!hints_parse_prompt(input, &hints.mode, &hints.gmode)) { /* if input is not valid, clear possible previous hint mode */ @@ -135,53 +139,52 @@ void hints_create(const char *input) hints.num = 0; hints.promptlen = hints.gmode ? 3 : 2; - js = g_strdup_printf("%s.init('%c', %d);", HINT_VAR, hints.mode, MAXIMUM_HINTS); - - run_script(js); - g_free(js); + JSValueRef arguments[] = { + js_string_to_ref(hints.ctx, (char[]){hints.mode, '\0'}), + JSValueMakeNumber(hints.ctx, MAXIMUM_HINTS) + }; + call_hints_function("init", 2, arguments); /* if hinting is started there won't be any aditional filter given and * we can go out of this function */ return; } - js = g_strdup_printf("%s.filter('%s');", HINT_VAR, *(input + hints.promptlen) ? input + hints.promptlen : ""); - run_script(js); - g_free(js); + JSValueRef arguments[] = {js_string_to_ref(hints.ctx, *(input + hints.promptlen) ? input + hints.promptlen : "")}; + call_hints_function("filter", 1, arguments); } void hints_update(int num) { - char *js = g_strdup_printf("%s.update(%d);", HINT_VAR, hints.num); - run_script(js); - g_free(js); + JSValueRef arguments[] = { + JSValueMakeNumber(hints.ctx, num) + }; + call_hints_function("update", 1, arguments); } void hints_focus_next(const gboolean back) { - char *js = g_strdup_printf("%s.focus(%d);", HINT_VAR, back); - run_script(js); - g_free(js); + JSValueRef arguments[] = { + JSValueMakeNumber(hints.ctx, back) + }; + call_hints_function("focus", 1, arguments); } void hints_fire(void) { - char *js = g_strconcat(HINT_VAR, ".fire();", NULL); - run_script(js); - g_free(js); + call_hints_function("fire", 0, NULL); } void hints_follow_link(const gboolean back, int count) { char *pattern = back ? vb.config.prevpattern : vb.config.nextpattern; - char *js = g_strdup_printf( - "%s.followLink('%s', [%s], %d);", HINT_VAR, - back ? "prev" : "next", - pattern, - count - ); - run_script(js); - g_free(js); + + JSValueRef arguments[] = { + js_string_to_ref(hints.ctx, back ? "prev" : "next"), + js_string_to_ref(hints.ctx, pattern), + JSValueMakeNumber(hints.ctx, count) + }; + call_hints_function("followLink", 3, arguments); } /** @@ -243,22 +246,60 @@ gboolean hints_parse_prompt(const char *prompt, char *mode, gboolean *is_gmode) return res; } -static void run_script(char *js) +static JSObjectRef create_hints_object(WebKitWebFrame *frame, const char *script) +{ + if (!script) { + return NULL; + } + + JSStringRef str, file; + JSValueRef result, exc = NULL; + JSObjectRef object; + + JSContextRef ctx = webkit_web_frame_get_global_context(frame); + str = JSStringCreateWithUTF8CString(script); + file = JSStringCreateWithUTF8CString(HINT_FILE); + result = JSEvaluateScript(ctx, str, NULL, file, 0, &exc); + JSStringRelease(str); + JSStringRelease(file); + if (exc) { + return NULL; + } + + object = JSValueToObject(ctx, result, &exc); + if (exc) { + return NULL; + } + JSValueProtect(ctx, result); + + return object; +} + +static void call_hints_function(const char *func, int count, JSValueRef params[]) { - char *value = NULL; + JSValueRef js_ret, function; + JSObjectRef function_object; + JSStringRef js_func = NULL; + char *value; - gboolean success = vb_eval_script( - webkit_web_view_get_main_frame(vb.gui.webview), js, HINT_FILE, &value - ); - if (!success) { - fprintf(stderr, "%s\n", value); - g_free(value); + if (!hints.obj) { + return; + } - mode_enter('n'); + js_func = JSStringCreateWithUTF8CString(func); + if (!JSObjectHasProperty(hints.ctx, hints.obj, js_func)) { + JSStringRelease(js_func); return; } + function = JSObjectGetProperty(hints.ctx, hints.obj, js_func, NULL); + function_object = JSValueToObject(hints.ctx, function, NULL); + js_ret = JSObjectCallAsFunction(hints.ctx, function_object, NULL, count, params, NULL); + JSStringRelease(js_func); + + value = js_ref_to_string(hints.ctx, js_ret); + if (!strncmp(value, "OVER:", 5)) { g_signal_emit_by_name( vb.gui.webview, "hovering-over-link", NULL, *(value + 5) == '\0' ? NULL : (value + 5) @@ -330,3 +371,25 @@ static void run_script(char *js) } g_free(value); } + +/* FIXME duplicate to main.c */ +static char *js_ref_to_string(JSContextRef ctx, JSValueRef ref) +{ + char *string; + JSStringRef str_ref = JSValueToStringCopy(ctx, ref, NULL); + size_t len = JSStringGetMaximumUTF8CStringSize(str_ref); + + string = g_new0(char, len); + JSStringGetUTF8CString(str_ref, string, len); + JSStringRelease(str_ref); + + return string; +} + +static JSValueRef js_string_to_ref(JSContextRef ctx, const char *string) +{ + JSStringRef js = JSStringCreateWithUTF8CString(string); + JSValueRef ret = JSValueMakeString(ctx, js); + JSStringRelease(js); + return ret; +} diff --git a/src/hints.js b/src/hints.js index f0cb659..cb1cf25 100644 --- a/src/hints.js +++ b/src/hints.js @@ -1,4 +1,4 @@ -function VimbHint() { +Object.freeze((function(){ 'use strict'; var hints = [], /* holds all hint data (hinted element, label, number) in view port */ @@ -531,13 +531,4 @@ function VimbHint() { /* not really hintings but uses similar logic */ followLink: followLink }; -} - -/* don't overwrite an already existing instance of VbHint, else we loose the */ -/* hinted elements after a hint was fired and we call VbHint.clear() from */ -/* hints.c */ -/* TODO implement the VimbHint as singleton */ -if (typeof VbHint == "undefined") { - var VbHint = new VimbHint(); - Object.freeze(VbHint); -} +})());