diff options
Diffstat (limited to 'src/xwidget.c')
| -rw-r--r-- | src/xwidget.c | 219 |
1 files changed, 92 insertions, 127 deletions
diff --git a/src/xwidget.c b/src/xwidget.c index 121510ebac0..ecb37936293 100644 --- a/src/xwidget.c +++ b/src/xwidget.c | |||
| @@ -31,14 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 31 | #include <webkit2/webkit2.h> | 31 | #include <webkit2/webkit2.h> |
| 32 | #include <JavaScriptCore/JavaScript.h> | 32 | #include <JavaScriptCore/JavaScript.h> |
| 33 | 33 | ||
| 34 | /* Suppress GCC deprecation warnings starting in WebKitGTK+ 2.21.1 for | ||
| 35 | webkit_javascript_result_get_global_context and | ||
| 36 | webkit_javascript_result_get_value (Bug#33679). | ||
| 37 | FIXME: Use the JavaScriptCore GLib API instead, and remove this hack. */ | ||
| 38 | #if WEBKIT_CHECK_VERSION (2, 21, 1) && GNUC_PREREQ (4, 2, 0) | ||
| 39 | # pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||
| 40 | #endif | ||
| 41 | |||
| 42 | static struct xwidget * | 34 | static struct xwidget * |
| 43 | allocate_xwidget (void) | 35 | allocate_xwidget (void) |
| 44 | { | 36 | { |
| @@ -284,95 +276,70 @@ webkit_view_load_changed_cb (WebKitWebView *webkitwebview, | |||
| 284 | 276 | ||
| 285 | /* Recursively convert a JavaScript value to a Lisp value. */ | 277 | /* Recursively convert a JavaScript value to a Lisp value. */ |
| 286 | static Lisp_Object | 278 | static Lisp_Object |
| 287 | webkit_js_to_lisp (JSContextRef context, JSValueRef value) | 279 | webkit_js_to_lisp (JSCValue *value) |
| 288 | { | 280 | { |
| 289 | switch (JSValueGetType (context, value)) | 281 | if (jsc_value_is_string (value)) |
| 290 | { | 282 | { |
| 291 | case kJSTypeString: | 283 | gchar *str_value = jsc_value_to_string (value); |
| 292 | { | 284 | Lisp_Object ret = build_string (str_value); |
| 293 | JSStringRef js_str_value; | 285 | g_free (str_value); |
| 294 | gchar *str_value; | 286 | |
| 295 | gsize str_length; | 287 | return ret; |
| 296 | 288 | } | |
| 297 | js_str_value = JSValueToStringCopy (context, value, NULL); | 289 | else if (jsc_value_is_boolean (value)) |
| 298 | str_length = JSStringGetMaximumUTF8CStringSize (js_str_value); | 290 | { |
| 299 | str_value = (gchar *)g_malloc (str_length); | 291 | return (jsc_value_to_boolean (value)) ? Qt : Qnil; |
| 300 | JSStringGetUTF8CString (js_str_value, str_value, str_length); | 292 | } |
| 301 | JSStringRelease (js_str_value); | 293 | else if (jsc_value_is_number (value)) |
| 302 | return build_string (str_value); | 294 | { |
| 303 | } | 295 | return make_fixnum (jsc_value_to_int32 (value)); |
| 304 | case kJSTypeBoolean: | 296 | } |
| 305 | return (JSValueToBoolean (context, value)) ? Qt : Qnil; | 297 | else if (jsc_value_is_array (value)) |
| 306 | case kJSTypeNumber: | 298 | { |
| 307 | return make_fixnum (JSValueToNumber (context, value, NULL)); | 299 | JSCValue *len = jsc_value_object_get_property (value, "length"); |
| 308 | case kJSTypeObject: | 300 | const gint32 dlen = jsc_value_to_int32 (len); |
| 309 | { | 301 | |
| 310 | if (JSValueIsArray (context, value)) | 302 | Lisp_Object obj; |
| 311 | { | 303 | if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0)) |
| 312 | JSStringRef pname = JSStringCreateWithUTF8CString("length"); | 304 | memory_full (SIZE_MAX); |
| 313 | JSValueRef len = JSObjectGetProperty (context, (JSObjectRef) value, | 305 | |
| 314 | pname, NULL); | 306 | ptrdiff_t n = dlen; |
| 315 | double dlen = JSValueToNumber (context, len, NULL); | 307 | struct Lisp_Vector *p = allocate_vector (n); |
| 316 | JSStringRelease(pname); | 308 | |
| 317 | 309 | for (ptrdiff_t i = 0; i < n; ++i) | |
| 318 | Lisp_Object obj; | 310 | { |
| 319 | if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0)) | 311 | p->contents[i] = |
| 320 | memory_full (SIZE_MAX); | 312 | webkit_js_to_lisp (jsc_value_object_get_property_at_index (value, i)); |
| 321 | ptrdiff_t n = dlen; | 313 | } |
| 322 | struct Lisp_Vector *p = allocate_vector (n); | 314 | XSETVECTOR (obj, p); |
| 323 | 315 | return obj; | |
| 324 | for (ptrdiff_t i = 0; i < n; ++i) | 316 | } |
| 325 | { | 317 | else if (jsc_value_is_object (value)) |
| 326 | p->contents[i] = | 318 | { |
| 327 | webkit_js_to_lisp (context, | 319 | char **properties_names = jsc_value_object_enumerate_properties (value); |
| 328 | JSObjectGetPropertyAtIndex (context, | 320 | guint n = g_strv_length (properties_names); |
| 329 | (JSObjectRef) value, | 321 | |
| 330 | i, NULL)); | 322 | Lisp_Object obj; |
| 331 | } | 323 | if (PTRDIFF_MAX < n) |
| 332 | XSETVECTOR (obj, p); | 324 | memory_full (n); |
| 333 | return obj; | 325 | struct Lisp_Vector *p = allocate_vector (n); |
| 334 | } | 326 | |
| 335 | else | 327 | for (ptrdiff_t i = 0; i < n; ++i) |
| 336 | { | 328 | { |
| 337 | JSPropertyNameArrayRef properties = | 329 | const char *name = properties_names[i]; |
| 338 | JSObjectCopyPropertyNames (context, (JSObjectRef) value); | 330 | JSCValue *property = jsc_value_object_get_property (value, name); |
| 339 | 331 | ||
| 340 | size_t n = JSPropertyNameArrayGetCount (properties); | 332 | p->contents[i] = |
| 341 | Lisp_Object obj; | 333 | Fcons (build_string (name), webkit_js_to_lisp (property)); |
| 342 | 334 | } | |
| 343 | /* TODO: can we use a regular list here? */ | 335 | |
| 344 | if (PTRDIFF_MAX < n) | 336 | g_strfreev (properties_names); |
| 345 | memory_full (n); | 337 | |
| 346 | struct Lisp_Vector *p = allocate_vector (n); | 338 | XSETVECTOR (obj, p); |
| 347 | 339 | return obj; | |
| 348 | for (ptrdiff_t i = 0; i < n; ++i) | ||
| 349 | { | ||
| 350 | JSStringRef name = JSPropertyNameArrayGetNameAtIndex (properties, i); | ||
| 351 | JSValueRef property = JSObjectGetProperty (context, | ||
| 352 | (JSObjectRef) value, | ||
| 353 | name, NULL); | ||
| 354 | gchar *str_name; | ||
| 355 | gsize str_length; | ||
| 356 | str_length = JSStringGetMaximumUTF8CStringSize (name); | ||
| 357 | str_name = (gchar *)g_malloc (str_length); | ||
| 358 | JSStringGetUTF8CString (name, str_name, str_length); | ||
| 359 | JSStringRelease (name); | ||
| 360 | |||
| 361 | p->contents[i] = | ||
| 362 | Fcons (build_string (str_name), | ||
| 363 | webkit_js_to_lisp (context, property)); | ||
| 364 | } | ||
| 365 | |||
| 366 | JSPropertyNameArrayRelease (properties); | ||
| 367 | XSETVECTOR (obj, p); | ||
| 368 | return obj; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | case kJSTypeUndefined: | ||
| 372 | case kJSTypeNull: | ||
| 373 | default: | ||
| 374 | return Qnil; | ||
| 375 | } | 340 | } |
| 341 | |||
| 342 | return Qnil; | ||
| 376 | } | 343 | } |
| 377 | 344 | ||
| 378 | static void | 345 | static void |
| @@ -380,41 +347,39 @@ webkit_javascript_finished_cb (GObject *webview, | |||
| 380 | GAsyncResult *result, | 347 | GAsyncResult *result, |
| 381 | gpointer arg) | 348 | gpointer arg) |
| 382 | { | 349 | { |
| 383 | WebKitJavascriptResult *js_result; | 350 | GError *error = NULL; |
| 384 | JSValueRef value; | 351 | struct xwidget *xw = g_object_get_data (G_OBJECT (webview), XG_XWIDGET); |
| 385 | JSGlobalContextRef context; | ||
| 386 | GError *error = NULL; | ||
| 387 | struct xwidget *xw = g_object_get_data (G_OBJECT (webview), | ||
| 388 | XG_XWIDGET); | ||
| 389 | ptrdiff_t script_idx = (intptr_t) arg; | ||
| 390 | Lisp_Object script_callback = AREF (xw->script_callbacks, script_idx); | ||
| 391 | ASET (xw->script_callbacks, script_idx, Qnil); | ||
| 392 | if (!NILP (script_callback)) | ||
| 393 | xfree (xmint_pointer (XCAR (script_callback))); | ||
| 394 | |||
| 395 | js_result = webkit_web_view_run_javascript_finish | ||
| 396 | (WEBKIT_WEB_VIEW (webview), result, &error); | ||
| 397 | |||
| 398 | if (!js_result) | ||
| 399 | { | ||
| 400 | g_warning ("Error running javascript: %s", error->message); | ||
| 401 | g_error_free (error); | ||
| 402 | return; | ||
| 403 | } | ||
| 404 | 352 | ||
| 405 | if (!NILP (script_callback) && !NILP (XCDR (script_callback))) | 353 | ptrdiff_t script_idx = (intptr_t) arg; |
| 406 | { | 354 | Lisp_Object script_callback = AREF (xw->script_callbacks, script_idx); |
| 407 | context = webkit_javascript_result_get_global_context (js_result); | 355 | ASET (xw->script_callbacks, script_idx, Qnil); |
| 408 | value = webkit_javascript_result_get_value (js_result); | 356 | if (!NILP (script_callback)) |
| 409 | Lisp_Object lisp_value = webkit_js_to_lisp (context, value); | 357 | xfree (xmint_pointer (XCAR (script_callback))); |
| 410 | 358 | ||
| 411 | /* Register an xwidget event here, which then runs the callback. | 359 | WebKitJavascriptResult *js_result = |
| 412 | This ensures that the callback runs in sync with the Emacs | 360 | webkit_web_view_run_javascript_finish |
| 413 | event loop. */ | 361 | (WEBKIT_WEB_VIEW (webview), result, &error); |
| 414 | store_xwidget_js_callback_event (xw, XCDR (script_callback), lisp_value); | 362 | |
| 415 | } | 363 | if (!js_result) |
| 364 | { | ||
| 365 | g_warning ("Error running javascript: %s", error->message); | ||
| 366 | g_error_free (error); | ||
| 367 | return; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (!NILP (script_callback) && !NILP (XCDR (script_callback))) | ||
| 371 | { | ||
| 372 | JSCValue *value = webkit_javascript_result_get_js_value (js_result); | ||
| 373 | |||
| 374 | Lisp_Object lisp_value = webkit_js_to_lisp (value); | ||
| 375 | |||
| 376 | /* Register an xwidget event here, which then runs the callback. | ||
| 377 | This ensures that the callback runs in sync with the Emacs | ||
| 378 | event loop. */ | ||
| 379 | store_xwidget_js_callback_event (xw, XCDR (script_callback), lisp_value); | ||
| 380 | } | ||
| 416 | 381 | ||
| 417 | webkit_javascript_result_unref (js_result); | 382 | webkit_javascript_result_unref (js_result); |
| 418 | } | 383 | } |
| 419 | 384 | ||
| 420 | 385 | ||