Index: emacs-26.1/src/xwidget.c =================================================================== --- emacs-26.2/src/xwidget.c | 85 ++++++++++++++++++++++++++++++++--------------- emacs-26.2/src/xwidget.h | 3 + 2 files changed, 61 insertions(+), 27 deletions(-) --- emacs-26.2/src/xwidget.c +++ emacs-26.2/src/xwidget.c 2019-04-15 12:01:41.038073221 +0000 @@ -364,7 +364,7 @@ webkit_js_to_lisp (JSContextRef context, static void webkit_javascript_finished_cb (GObject *webview, GAsyncResult *result, - gpointer lisp_callback) + gpointer arg) { WebKitJavascriptResult *js_result; JSValueRef value; @@ -372,6 +372,11 @@ webkit_javascript_finished_cb (GObject GError *error = NULL; struct xwidget *xw = g_object_get_data (G_OBJECT (webview), XG_XWIDGET); + ptrdiff_t script_idx = (intptr_t) arg; + Lisp_Object script_callback = AREF (xw->script_callbacks, script_idx); + ASET (xw->script_callbacks, script_idx, Qnil); + if (!NILP (script_callback)) + xfree (XSAVE_POINTER (XCAR (script_callback), 0)); js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (webview), result, &error); @@ -383,19 +388,19 @@ webkit_javascript_finished_cb (GObject return; } - context = webkit_javascript_result_get_global_context (js_result); - value = webkit_javascript_result_get_value (js_result); - Lisp_Object lisp_value = webkit_js_to_lisp (context, value); - webkit_javascript_result_unref (js_result); + if (!NILP (script_callback) && !NILP (XCDR (script_callback))) + { + context = webkit_javascript_result_get_global_context (js_result); + value = webkit_javascript_result_get_value (js_result); + Lisp_Object lisp_value = webkit_js_to_lisp (context, value); + + /* Register an xwidget event here, which then runs the callback. + This ensures that the callback runs in sync with the Emacs + event loop. */ + store_xwidget_js_callback_event (xw, XCDR (script_callback), lisp_value); + } - /* Register an xwidget event here, which then runs the callback. - This ensures that the callback runs in sync with the Emacs - event loop. */ - /* FIXME: This might lead to disaster if LISP_CALLBACK's object - was garbage collected before now. See the FIXME in - Fxwidget_webkit_execute_script. */ - store_xwidget_js_callback_event (xw, XIL ((intptr_t) lisp_callback), - lisp_value); + webkit_javascript_result_unref (js_result); } @@ -693,8 +698,7 @@ DEFUN ("xwidget-webkit-goto-uri", DEFUN ("xwidget-webkit-zoom", Fxwidget_webkit_zoom, Sxwidget_webkit_zoom, 2, 2, 0, - doc: /* Change the zoom factor of the xwidget webkit instance -referenced by XWIDGET. */) + doc: /* Change the zoom factor of the xwidget webkit instance referenced by XWIDGET. */) (Lisp_Object xwidget, Lisp_Object factor) { WEBKIT_FN_INIT (); @@ -709,12 +713,33 @@ referenced by XWIDGET. */) return Qnil; } +/* Save script and fun in the script/callback save vector and return + its index. */ +static ptrdiff_t +save_script_callback (struct xwidget *xw, Lisp_Object script, Lisp_Object fun) +{ + Lisp_Object cbs = xw->script_callbacks; + if (NILP (cbs)) + xw->script_callbacks = cbs = Fmake_vector (make_number (32), Qnil); + + /* Find first free index. */ + ptrdiff_t idx; + for (idx = 0; !NILP (AREF (cbs, idx)); idx++) + if (idx + 1 == ASIZE (cbs)) + { + xw->script_callbacks = cbs = larger_vector (cbs, 1, -1); + break; + } + + ASET (cbs, idx, Fcons (make_save_ptr (xlispstrdup (script)), fun)); + return idx; +} DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script, 2, 3, 0, - doc: /* Make the Webkit XWIDGET execute JavaScript SCRIPT. If -FUN is provided, feed the JavaScript return value to the single + doc: /* Make the Webkit XWIDGET execute JavaScript SCRIPT. +If FUN is provided, feed the JavaScript return value to the single argument procedure FUN.*/) (Lisp_Object xwidget, Lisp_Object script, Lisp_Object fun) { @@ -723,23 +748,19 @@ argument procedure FUN.*/) if (!NILP (fun) && !FUNCTIONP (fun)) wrong_type_argument (Qinvalid_function, fun); - GAsyncReadyCallback callback - = FUNCTIONP (fun) ? webkit_javascript_finished_cb : NULL; + script = ENCODE_SYSTEM (script); - /* FIXME: The following hack assumes USE_LSB_TAG. */ - verify (USE_LSB_TAG); - /* FIXME: This hack might lead to disaster if FUN is garbage - collected before store_xwidget_js_callback_event makes it visible - to Lisp again. See the FIXME in webkit_javascript_finished_cb. */ - gpointer callback_arg = (gpointer) (intptr_t) XLI (fun); + /* Protect script and fun during GC. */ + intptr_t idx = save_script_callback (xw, script, fun); /* JavaScript execution happens asynchronously. If an elisp callback function is provided we pass it to the C callback procedure that retrieves the return value. */ webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (xw->widget_osr), - SSDATA (script), + XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0), NULL, /* cancelable */ - callback, callback_arg); + webkit_javascript_finished_cb, + (gpointer) idx); return Qnil; } @@ -1204,6 +1225,16 @@ kill_buffer_xwidgets (Lisp_Object buffer gtk_widget_destroy (xw->widget_osr); gtk_widget_destroy (xw->widgetwindow_osr); } + if (!NILP (xw->script_callbacks)) + { + ptrdiff_t idx; + for (idx = 0; idx < ASIZE (xw->script_callbacks); idx++) + { + if (!NILP (AREF (xw->script_callbacks, idx))) + xfree (XSAVE_POINTER (XCAR (AREF (xw->script_callbacks, idx)), 0)); + ASET (xw->script_callbacks, idx, Qnil); + } + } } } } --- emacs-26.2/src/xwidget.h +++ emacs-26.2/src/xwidget.h 2019-04-15 12:01:41.038073221 +0000 @@ -47,6 +47,9 @@ struct xwidget /* A title used for button labels, for instance. */ Lisp_Object title; + /* Vector of currently executing scripts with callbacks. */ + Lisp_Object script_callbacks; + /* Here ends the Lisp part. "height" is the marker field. */ int height;