diff options
Diffstat (limited to 'content/handlers/javascript/duktape/Window.bnd')
-rw-r--r-- | content/handlers/javascript/duktape/Window.bnd | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/content/handlers/javascript/duktape/Window.bnd b/content/handlers/javascript/duktape/Window.bnd index 478f92b99..a5ff2002d 100644 --- a/content/handlers/javascript/duktape/Window.bnd +++ b/content/handlers/javascript/duktape/Window.bnd @@ -12,13 +12,14 @@ class Window { private struct browser_window * win; private struct html_content * htmlc; private struct window_schedule_s * schedule_ring; + private bool closed_down; prologue %{ #include "utils/corestrings.h" #include "utils/nsurl.h" #include "netsurf/browser_window.h" #include "content/hlcache.h" #include "html/html.h" -#include "html/html_internal.h" +#include "html/private.h" #include "desktop/gui_internal.h" #include "netsurf/misc.h" #include "utils/ring.h" @@ -138,7 +139,7 @@ window_alloc_new_callback(duk_context *ctx, int timeout) { size_t new_handle = next_handle++; - window_schedule_t *sched = calloc(sizeof *sched, 1); + window_schedule_t *sched = calloc(1, sizeof *sched); if (sched == NULL) { return new_handle; } @@ -216,8 +217,8 @@ window_remove_callback_by_handle(duk_context *ctx, } RING_ITERATE_END(window->schedule_ring, sched); } -/* This is the dodgy compartment closedown method */ -static duk_ret_t dukky_window_closedown_compartment(duk_context *ctx) +/* This is the dodgy thread closedown method */ +static duk_ret_t dukky_window_closedown_thread(duk_context *ctx) { window_private_t *priv = NULL; @@ -230,11 +231,42 @@ static duk_ret_t dukky_window_closedown_compartment(duk_context *ctx) return 0; } - NSLOG(dukky, DEEPDEBUG, "Closing down compartment"); + priv->closed_down = true; + + NSLOG(dukky, DEEPDEBUG, "Closing down thread"); while (priv->schedule_ring != NULL) { + window_schedule_t *to_remove = NULL; + // Find a schedule item to remove + RING_ITERATE_START(window_schedule_t, priv->schedule_ring, sched) { + if (sched->running == false) { + // This one is not running, we can remove it + to_remove = sched; + RING_ITERATE_STOP(window->schedule_ring, sched); + } else if (sched->repeat_timeout != 0) { + // This one is running and has yet to be + // cancelled, so prevent it rescheduling itself + NSLOG(dukky, DEEPDEBUG, + "Cancelling in-train callback %"PRIsizet, + sched->handle); + sched->repeat_timeout = 0; + } + } RING_ITERATE_END(priv->schedule_ring, sched); + + if (to_remove == NULL) { + // We didn't find any non-running callbacks + // so let's log that and break out of the closedown + // loop so we can continue and hopefully close down + NSLOG(dukky, DEEPDEBUG, + "Leaving in-train callbacks to unwind"); + break; + } + + // Remove the handle we found, this will reduce the callback + // scheduler ring by one and perhaps leave it empty so we can + // finish the closedown. window_remove_callback_by_handle(ctx, priv, - priv->schedule_ring->handle); + to_remove->handle); } return 0; @@ -245,10 +277,14 @@ static duk_ret_t dukky_window_closedown_compartment(duk_context *ctx) init Window(struct browser_window *win, struct html_content *htmlc) %{ + /* It makes no sense if win or htmlc are NULL */ + assert(win != NULL); + assert(htmlc != NULL); /* element window */ priv->win = win; priv->htmlc = htmlc; priv->schedule_ring = NULL; + priv->closed_down = false; NSLOG(netsurf, DEEPDEBUG, "win=%p htmlc=%p", priv->win, priv->htmlc); NSLOG(netsurf, DEEPDEBUG, @@ -273,7 +309,7 @@ prototype Window() duk_put_prop_string(ctx, 0, #v) /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects */ /* ** Value properties */ - EXPOSE(infinity); + EXPOSE(Infinity); EXPOSE(NaN); EXPOSE(undefined); EXPOSE(null); @@ -361,10 +397,10 @@ prototype Window() /* ** WebAssembly */ /* As yet, Duktape lacks WA */ #undef EXPOSE - /* Add s3kr1t method to close the compartment */ + /* Add s3kr1t method to close the JS thread (browsing context) */ duk_dup(ctx, 0); - duk_push_string(ctx, MAGIC(closedownCompartment)); - duk_push_c_function(ctx, dukky_window_closedown_compartment, DUK_VARARGS); + duk_push_string(ctx, MAGIC(closedownThread)); + duk_push_c_function(ctx, dukky_window_closedown_thread, DUK_VARARGS); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | @@ -481,6 +517,11 @@ method Window::setTimeout() %{ duk_idx_t argc = duk_get_top(ctx); duk_int_t timeout = 10; + + if (priv->closed_down == true) { + return 0; /* coerced to undefined */ + } + if (argc >= 2) { timeout = duk_get_int(ctx, 1); } @@ -496,6 +537,11 @@ method Window::setInterval() %{ duk_idx_t argc = duk_get_top(ctx); duk_int_t timeout = 10; + + if (priv->closed_down == true) { + return 0; /* coerced to undefined */ + } + if (argc >= 2) { timeout = duk_get_int(ctx, 1); } |