Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/546ed22b553eb380e906816cdf81a0b267a79837
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/546ed22b553eb380e906816cdf81a0b267a79837
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/546ed22b553eb380e906816cdf81a0b267a79837

The branch, dsilvers/eventtarget has been updated
       via  546ed22b553eb380e906816cdf81a0b267a79837 (commit)
       via  77eb3c576efeafd9dd4801487da5f868e80ab0d5 (commit)
      from  bfde01c854284a9dcf1ae1e11639566c79cf8019 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=546ed22b553eb380e906816cdf81a0b267a79837
commit 546ed22b553eb380e906816cdf81a0b267a79837
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>

    foldme: This is still a mess, but maybe, just maybe, we're closer to 
runnable

diff --git a/content/handlers/javascript/duktape/EventTarget.bnd 
b/content/handlers/javascript/duktape/EventTarget.bnd
index 66c2eb0..41bdbd9 100644
--- a/content/handlers/javascript/duktape/EventTarget.bnd
+++ b/content/handlers/javascript/duktape/EventTarget.bnd
@@ -10,60 +10,13 @@
 
 class EventTarget {
        private bool is_node;
+       private bool capture_registered;
+       private bool bubbling_registered;
 };
 
 prologue EventTarget()
 %{
-#define EVENT_LISTENER_JS_MAGIC MAGIC(EVENT_LISTENER_JS_MAP)
        
-       
-/* The sub-listeners are a list of {callback,flags} tuples */
-static void event_target_push_listeners(duk_context *ctx) {
-       /* ... type (this=EventTarget) */
-       duk_push_this(ctx);
-       /* ... type this */
-       duk_get_prop_string(ctx, -1, EVENT_LISTENER_JS_MAGIC);
-       if (duk_is_null(ctx, -1)) {
-               /* ... type this null */
-               duk_pop(ctx);
-               duk_push_object(ctx);
-               duk_dup(ctx, -1);
-               /* ... type this listeners listeners */
-               duk_put_prop_string(ctx, -3, EVENT_LISTENER_JS_MAGIC);
-               /* ... type this listeners */
-       }
-       /* ... type this listeners */
-       duk_insert(ctx, -3);
-       /* ... listeners type this */
-       duk_pop(ctx);
-       /* ... listeners type */
-       duk_dup(ctx, -1);
-       /* ... listeners type type */
-       duk_get_prop(ctx, -3);
-       /* ... listeners type ??? */
-       if (duk_is_null(ctx, -1)) {
-               /* ... listeners type ??? */
-               duk_pop(ctx);
-               duk_push_object(ctx);
-               duk_dup(ctx, -2);
-               duk_dup(ctx, -2);
-               /* ... listeners type sublisteners type sublisteners */
-               duk_put_prop(ctx, -5);
-               /* ... listeners type sublisteners */
-       }
-       duk_insert(ctx, -3);
-       /* ... sublisteners listeners type */
-       duk_pop_2(ctx);
-       /* ... sublisteners */
-}
-
-typedef enum {
-       ELF_CAPTURE = 1 << 0,
-       ELF_PASSIVE = 1 << 1,
-       ELF_ONCE    = 1 << 2,
-       ELF_NONE    = 0
-} event_listener_flags;
-
 static event_listener_flags event_listener_pop_options(duk_context *ctx)
 {
        event_listener_flags ret = ELF_NONE;
@@ -92,14 +45,102 @@ static void event_target_register_listener(duk_context 
*ctx,
         * we do not re-add it, otherwise we need to add to listeners
         * a tuple of the callback and flags
         */
-       
+       duk_uarridx_t idx = 0;
+       while (duk_get_prop_index(ctx, -1, idx)) {
+               /* ... listeners callback candidate */
+               duk_get_prop_index(ctx, -1, 0);
+               duk_get_prop_index(ctx, -2, 1);
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               if (duk_strict_equals(ctx, -1, -3) &&
+                   duk_get_int(ctx, -1) == (duk_int_t)flags) {
+                       /* already present, nothing to do */
+                       duk_pop_n(ctx, 5);
+                       /* ... */
+                       return;
+               }
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               duk_pop_3(ctx);
+               /* ... listeners callback */
+               idx++;
+       }
+       /* ... listeners callback undefined */
+       duk_pop(ctx);
+       /* ... listeners callback */
+       duk_push_array(ctx);
+       /* ... listeners callback newcandidate */
+       duk_insert(ctx, -2);
+       /* ... listeners newcandidate callback */
+       duk_put_prop_index(ctx, -2, 0);
+       /* ... listeners newcandidate */
+       duk_push_int(ctx, (duk_int_t)flags);
+       /* ... listeners newcandidate flags */
+       duk_put_prop_index(ctx, -2, 1);
+       /* ... listeners newcandidate */
+       duk_put_prop_index(ctx, -2, idx);
+       /* ... listeners */
+       duk_pop(ctx);
+       /* ... */
+}
+
+static void event_target_unregister_listener(duk_context *ctx,
+                                            event_listener_flags flags)
+{
+       /* ... listeners callback */
+       /* If the given callback with the given flags is present,
+        * we remove it and shuffle the rest up.
+        */
+       duk_uarridx_t idx = 0;
+       while (duk_get_prop_index(ctx, -1, idx)) {
+               /* ... listeners callback candidate */
+               duk_get_prop_index(ctx, -1, 0);
+               duk_get_prop_index(ctx, -2, 1);
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               if (duk_strict_equals(ctx, -1, -3) &&
+                   duk_get_int(ctx, -1) == (duk_int_t)flags) {
+                       /* present */
+                       duk_pop(ctx);
+                       /* ... listeners callback candidate candidatecallback */
+                       duk_put_prop_index(ctx, -2, 2);
+                       /* ... listeners callback candidate */
+                       duk_pop(ctx);
+                       /* ... listeners callback */
+                       duk_push_int(ctx, idx);
+                       /* ... listeners callback found_at */
+                       break;
+               }
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               duk_pop_3(ctx);
+               /* ... listeners callback */
+               idx++;
+       }
+       /* ... listeners callback undefined/found_at */
+       if (duk_is_undefined(ctx, -1)) {
+               /* not found, clean up and come out */
+               duk_pop_3(ctx);
+               return;
+       }
+       idx = duk_to_int(ctx, -1);
+       duk_pop_2(ctx);
+       /* ... listeners */
+       while (duk_get_prop_index(ctx, -1, idx + 1)) {
+               duk_put_prop_index(ctx, -2, idx);
+               idx++;
+       }
+       /* ... listeners undefined */
+       duk_del_prop_index(ctx, -2, idx + 1);
+       duk_pop_2(ctx);
+       /* ... */
 }
 
+
 %}
 
 init EventTarget()
 %{
        priv->is_node = false;
+       priv->capture_registered = false;
+       priv->bubbling_registered = false;
+       
 %}
 
 method EventTarget::addEventListener()
@@ -127,20 +168,69 @@ method EventTarget::addEventListener()
        /* type callback */
        duk_dup(ctx, -2);
        /* type callback type */
-       event_target_push_listeners(ctx);
+       duk_push_this(ctx);
+       /* type callback type this(=EventTarget) */
+       if (dukky_event_target_push_listeners(ctx, false) && priv->is_node) {
+               /* Take a moment to register a JS callback */
+               duk_size_t ev_ty_l;
+               const char *ev_ty = duk_to_lstring(ctx, -3, &ev_ty_l);
+               dom_string *ev_ty_s;
+               exc = dom_string_create((const uint8_t*)ev_ty, ev_ty_l,
+                                       &ev_ty_s);
+               if (exc != DOM_NO_ERR) {
+                       LOG("Oh dear, failed to create dom_string in 
addEventListener()");
+                       return 0;
+               }
+               /* TODO: Enable passing of capture vs. bubble for this */
+               dukky_register_event_listener_for(
+                       ctx, (dom_element *)((node_private_t *)priv)->node,
+                       ev_ty_s);
+               dom_string_unref(ev_ty_s);
+       }
        /* type callback typelisteners */
        duk_insert(ctx, -2);
        /* type typelisteners callback */
        event_target_register_listener(ctx, flags);
-       
-       
-       // TODO: FINISH
+       /* type */
        return 0;
 %}
 
 method EventTarget::removeEventListener()
 %{
-       dom_exception exc;
+       event_listener_flags flags = ELF_NONE;
+       /* Incoming stack is: type callback [options] */
+       if (duk_get_top(ctx) < 2) return 0; /* Bad arguments */
+       if (duk_get_top(ctx) > 3) return 0; /* Bad arguments */
+       if (duk_get_top(ctx) == 2) {
+               duk_push_object(ctx);
+               /* type callback options */
+       }
+       if (duk_get_type(ctx, -1) != DUK_TYPE_OBJECT) {
+               /* legacy support, if not object, it's the capture value */
+               duk_push_object(ctx);
+               /* ... capture options */
+               duk_insert(ctx, -2);
+               /* ... options capture */
+               duk_put_prop_string(ctx, -2, "capture");
+               /* ... options */
+       }
+       /* type callback options */
+       flags = event_listener_pop_options(ctx);
+       /* type callback */
+       duk_dup(ctx, -2);
+       /* type callback type */
+       duk_push_this(ctx);
+       /* type callback type this(=EventTarget) */
+       if (dukky_event_target_push_listeners(ctx, true)) {
+               /* nothing to do because the listener wasn't there at all */
+               duk_pop_3(ctx);
+               return 0;
+       }
+       /* type callback typelisteners */
+       duk_insert(ctx, -2);
+       /* type typelisteners callback */
+       event_target_unregister_listener(ctx, flags);
+       /* type */
        return 0;
 %}
 
diff --git a/content/handlers/javascript/duktape/dukky.c 
b/content/handlers/javascript/duktape/dukky.c
index 1282ad9..638430a 100644
--- a/content/handlers/javascript/duktape/dukky.c
+++ b/content/handlers/javascript/duktape/dukky.c
@@ -46,6 +46,7 @@
 #define EVENT_MAGIC MAGIC(EVENT_MAP)
 #define HANDLER_LISTENER_MAGIC MAGIC(HANDLER_LISTENER_MAP)
 #define HANDLER_MAGIC MAGIC(HANDLER_MAP)
+#define EVENT_LISTENER_JS_MAGIC MAGIC(EVENT_LISTENER_JS_MAP)
 
 static duk_ret_t dukky_populate_object(duk_context *ctx)
 {
@@ -809,6 +810,8 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
        dom_exception exc;
        dom_event_target *targ;
        dom_event_flow_phase phase;
+       duk_uarridx_t idx;
+       event_listener_flags flags;
 
        /* Retrieve the JS context from the Duktape context */
        duk_get_memory_functions(ctx, &funcs);
@@ -850,17 +853,14 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
        /* ... node */
        if (dukky_get_current_value_of_event_handler(
                    ctx, name, (dom_event_target *)targ) == false) {
-               dom_node_unref(targ);
-               dom_string_unref(name);
-               return;
+               /* TODO: Do I have to manage if there's other event handlers */
+               goto out;
        }
-       /** @todo handle other kinds of event than the generic case */
-       dom_node_unref(targ);
-       dom_string_unref(name);
        /* ... handler node */
        dukky_push_event(ctx, evt);
        /* ... handler node event */
        (void) nsu_getmonotonic_ms(&jsctx->exec_start_time);
+       /* Maybe skip calling if not capture or at-target ? */
        if (duk_pcall_method(ctx, 1) != 0) {
                /* Failed to run the method */
                /* ... err */
@@ -882,7 +882,7 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
 
                duk_pop_n(ctx, 6);
                /* ... */
-               return;
+               goto handle_extras;
        }
        /* ... result */
        if (duk_is_boolean(ctx, -1) &&
@@ -890,7 +890,92 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
                dom_event_prevent_default(evt);
        }
        duk_pop(ctx);
+handle_extras:
+       /* ... */
+       duk_push_lstring(ctx, dom_string_data(name), dom_string_length(name));
+       dukky_push_node(ctx, (dom_node *)targ);
+       /* ... type node */
+       if (dukky_event_target_push_listeners(ctx, true)) {
+               /* Nothing to do */
+               duk_pop(ctx);
+               goto out;
+       }
+       /* ... sublisteners */
+       duk_push_array(ctx);
+       /* ... sublisteners copy */
+       idx = 0;
+       while (duk_get_prop_index(ctx, -2, idx)) {
+               /* ... sublisteners copy handler */
+               /* TODO check if the handler is ONCE, if so, remove it from
+                * the sublisteners */
+               duk_put_prop_index(ctx, -2, idx);
+               /* ... sublisteners copy */
+               idx++;
+       }
+       /* ... sublisteners copy undefined */
+       duk_pop(ctx);
+       /* ... sublisteners copy */
+       duk_insert(ctx, -2);
+       /* ... copy sublisteners */
+       duk_pop(ctx);
+       /* ... copy */
+       idx = 0;
+       while (duk_get_prop_index(ctx, -1, idx++)) {
+               /* ... copy handler */
+               if (duk_get_prop_index(ctx, -1, 2)) {
+                       /* ... copy handler meh */
+                       duk_pop_2(ctx);
+                       continue;
+               }
+               duk_pop(ctx);
+               duk_get_prop_index(ctx, -1, 0);
+               duk_get_prop_index(ctx, -2, 1);
+               /* ... copy handler callback flags */
+               flags = (event_listener_flags)duk_get_int(ctx, -1);
+               duk_pop(ctx);
+               /* TODO: So, should we run the event handler? */
+               dukky_push_node(ctx, (dom_node *)targ);
+               /* ... copy handler callback node */
+               dukky_push_event(ctx, evt);
+               /* ... copy handler callback node event */
+               (void) nsu_getmonotonic_ms(&jsctx->exec_start_time);
+               /* Maybe skip calling if not capture or at-target ? */
+               if (duk_pcall_method(ctx, 1) != 0) {
+                       /* Failed to run the method */
+                       /* ... copy handler err */
+                       LOG("OH NOES! An error running a callback.  Meh.");
+                       exc = dom_event_stop_immediate_propagation(evt);
+                       if (exc != DOM_NO_ERR)
+                               LOG("WORSE! could not stop propagation");
+                       duk_get_prop_string(ctx, -1, "name");
+                       duk_get_prop_string(ctx, -2, "message");
+                       duk_get_prop_string(ctx, -3, "fileName");
+                       duk_get_prop_string(ctx, -4, "lineNumber");
+                       duk_get_prop_string(ctx, -5, "stack");
+                       /* ... err name message fileName lineNumber stack */
+                       LOG("Uncaught error in JS: %s: %s", 
duk_safe_to_string(ctx, -5),
+                           duk_safe_to_string(ctx, -4));
+                       LOG("              was at: %s line %s", 
duk_safe_to_string(ctx, -3),
+                           duk_safe_to_string(ctx, -2));
+                       LOG("         Stack trace: %s", duk_safe_to_string(ctx, 
-1));
+                       
+                       duk_pop_n(ctx, 7);
+                       /* ... copy */
+                       continue;
+               }
+               /* ... copy handler result */
+               if (duk_is_boolean(ctx, -1) &&
+                   duk_to_boolean(ctx, -1) == 0) {
+                       dom_event_prevent_default(evt);
+               }
+               duk_pop_2(ctx);
+               /* ... copy */
+       }
+       duk_pop_2(ctx);
+out:
        /* ... */
+       dom_node_unref(targ);
+       dom_string_unref(name);
 }
 
 void dukky_register_event_listener_for(duk_context *ctx,
@@ -938,6 +1023,54 @@ void dukky_register_event_listener_for(duk_context *ctx,
        dom_event_listener_unref(listen);
 }
 
+/* The sub-listeners are a list of {callback,flags} tuples */
+/* We return true if we created a new sublistener table */
+/* If we're told to not create, but we want to, we still return true */        
+bool dukky_event_target_push_listeners(duk_context *ctx, bool dont_create)
+{
+       bool ret = false;
+       /* ... type this */
+       duk_get_prop_string(ctx, -1, EVENT_LISTENER_JS_MAGIC);
+       if (duk_is_null(ctx, -1)) {
+               /* ... type this null */
+               duk_pop(ctx);
+               duk_push_object(ctx);
+               duk_dup(ctx, -1);
+               /* ... type this listeners listeners */
+               duk_put_prop_string(ctx, -3, EVENT_LISTENER_JS_MAGIC);
+               /* ... type this listeners */
+       }
+       /* ... type this listeners */
+       duk_insert(ctx, -3);
+       /* ... listeners type this */
+       duk_pop(ctx);
+       /* ... listeners type */
+       duk_dup(ctx, -1);
+       /* ... listeners type type */
+       duk_get_prop(ctx, -3);
+       /* ... listeners type ??? */
+       if (duk_is_null(ctx, -1)) {
+               /* ... listeners type ??? */
+               if (dont_create == true) {
+                       duk_pop_3(ctx);
+                       duk_push_undefined(ctx);
+                       return true;
+               }
+               duk_pop(ctx);
+               duk_push_array(ctx);
+               duk_dup(ctx, -2);
+               duk_dup(ctx, -2);
+               /* ... listeners type sublisteners type sublisteners */
+               duk_put_prop(ctx, -5);
+               /* ... listeners type sublisteners */
+               ret = true;
+       }
+       duk_insert(ctx, -3);
+       /* ... sublisteners listeners type */
+       duk_pop_2(ctx);
+       /* ... sublisteners */
+       return ret;
+}
 
 void js_handle_new_element(jscontext *ctx, struct dom_element *node)
 {
diff --git a/content/handlers/javascript/duktape/dukky.h 
b/content/handlers/javascript/duktape/dukky.h
index 0c3ff0e..6ef9fdf 100644
--- a/content/handlers/javascript/duktape/dukky.h
+++ b/content/handlers/javascript/duktape/dukky.h
@@ -41,5 +41,13 @@ void dukky_register_event_listener_for(duk_context *ctx,
 bool dukky_get_current_value_of_event_handler(duk_context *ctx,
                                              dom_string *name,
                                              dom_event_target *et);
+bool dukky_event_target_push_listeners(duk_context *ctx, bool dont_create);
+
+typedef enum {
+       ELF_CAPTURE = 1 << 0,
+       ELF_PASSIVE = 1 << 1,
+       ELF_ONCE    = 1 << 2,
+       ELF_NONE    = 0
+} event_listener_flags;
 
 #endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=77eb3c576efeafd9dd4801487da5f868e80ab0d5
commit 77eb3c576efeafd9dd4801487da5f868e80ab0d5
Author: Daniel Silverstone <[email protected]>
Commit: Daniel Silverstone <[email protected]>

    more bits

diff --git a/content/handlers/javascript/duktape/EventTarget.bnd 
b/content/handlers/javascript/duktape/EventTarget.bnd
index fb20883..66c2eb0 100644
--- a/content/handlers/javascript/duktape/EventTarget.bnd
+++ b/content/handlers/javascript/duktape/EventTarget.bnd
@@ -16,6 +16,8 @@ prologue EventTarget()
 %{
 #define EVENT_LISTENER_JS_MAGIC MAGIC(EVENT_LISTENER_JS_MAP)
        
+       
+/* The sub-listeners are a list of {callback,flags} tuples */
 static void event_target_push_listeners(duk_context *ctx) {
        /* ... type (this=EventTarget) */
        duk_push_this(ctx);
@@ -82,6 +84,17 @@ static event_listener_flags 
event_listener_pop_options(duk_context *ctx)
        return ret;
 }
 
+static void event_target_register_listener(duk_context *ctx,
+                                          event_listener_flags flags)
+{
+       /* ... listeners callback */
+       /* If the given callback with the given flags is already present,
+        * we do not re-add it, otherwise we need to add to listeners
+        * a tuple of the callback and flags
+        */
+       
+}
+
 %}
 
 init EventTarget()
@@ -116,7 +129,12 @@ method EventTarget::addEventListener()
        /* type callback type */
        event_target_push_listeners(ctx);
        /* type callback typelisteners */
+       duk_insert(ctx, -2);
+       /* type typelisteners callback */
+       event_target_register_listener(ctx, flags);
+       
        
+       // TODO: FINISH
        return 0;
 %}
 


-----------------------------------------------------------------------

Summary of changes:
 .../handlers/javascript/duktape/EventTarget.bnd    |  208 +++++++++++++++-----
 content/handlers/javascript/duktape/dukky.c        |  147 +++++++++++++-
 content/handlers/javascript/duktape/dukky.h        |    8 +
 3 files changed, 306 insertions(+), 57 deletions(-)

diff --git a/content/handlers/javascript/duktape/EventTarget.bnd 
b/content/handlers/javascript/duktape/EventTarget.bnd
index fb20883..41bdbd9 100644
--- a/content/handlers/javascript/duktape/EventTarget.bnd
+++ b/content/handlers/javascript/duktape/EventTarget.bnd
@@ -10,58 +10,13 @@
 
 class EventTarget {
        private bool is_node;
+       private bool capture_registered;
+       private bool bubbling_registered;
 };
 
 prologue EventTarget()
 %{
-#define EVENT_LISTENER_JS_MAGIC MAGIC(EVENT_LISTENER_JS_MAP)
        
-static void event_target_push_listeners(duk_context *ctx) {
-       /* ... type (this=EventTarget) */
-       duk_push_this(ctx);
-       /* ... type this */
-       duk_get_prop_string(ctx, -1, EVENT_LISTENER_JS_MAGIC);
-       if (duk_is_null(ctx, -1)) {
-               /* ... type this null */
-               duk_pop(ctx);
-               duk_push_object(ctx);
-               duk_dup(ctx, -1);
-               /* ... type this listeners listeners */
-               duk_put_prop_string(ctx, -3, EVENT_LISTENER_JS_MAGIC);
-               /* ... type this listeners */
-       }
-       /* ... type this listeners */
-       duk_insert(ctx, -3);
-       /* ... listeners type this */
-       duk_pop(ctx);
-       /* ... listeners type */
-       duk_dup(ctx, -1);
-       /* ... listeners type type */
-       duk_get_prop(ctx, -3);
-       /* ... listeners type ??? */
-       if (duk_is_null(ctx, -1)) {
-               /* ... listeners type ??? */
-               duk_pop(ctx);
-               duk_push_object(ctx);
-               duk_dup(ctx, -2);
-               duk_dup(ctx, -2);
-               /* ... listeners type sublisteners type sublisteners */
-               duk_put_prop(ctx, -5);
-               /* ... listeners type sublisteners */
-       }
-       duk_insert(ctx, -3);
-       /* ... sublisteners listeners type */
-       duk_pop_2(ctx);
-       /* ... sublisteners */
-}
-
-typedef enum {
-       ELF_CAPTURE = 1 << 0,
-       ELF_PASSIVE = 1 << 1,
-       ELF_ONCE    = 1 << 2,
-       ELF_NONE    = 0
-} event_listener_flags;
-
 static event_listener_flags event_listener_pop_options(duk_context *ctx)
 {
        event_listener_flags ret = ELF_NONE;
@@ -82,11 +37,110 @@ static event_listener_flags 
event_listener_pop_options(duk_context *ctx)
        return ret;
 }
 
+static void event_target_register_listener(duk_context *ctx,
+                                          event_listener_flags flags)
+{
+       /* ... listeners callback */
+       /* If the given callback with the given flags is already present,
+        * we do not re-add it, otherwise we need to add to listeners
+        * a tuple of the callback and flags
+        */
+       duk_uarridx_t idx = 0;
+       while (duk_get_prop_index(ctx, -1, idx)) {
+               /* ... listeners callback candidate */
+               duk_get_prop_index(ctx, -1, 0);
+               duk_get_prop_index(ctx, -2, 1);
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               if (duk_strict_equals(ctx, -1, -3) &&
+                   duk_get_int(ctx, -1) == (duk_int_t)flags) {
+                       /* already present, nothing to do */
+                       duk_pop_n(ctx, 5);
+                       /* ... */
+                       return;
+               }
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               duk_pop_3(ctx);
+               /* ... listeners callback */
+               idx++;
+       }
+       /* ... listeners callback undefined */
+       duk_pop(ctx);
+       /* ... listeners callback */
+       duk_push_array(ctx);
+       /* ... listeners callback newcandidate */
+       duk_insert(ctx, -2);
+       /* ... listeners newcandidate callback */
+       duk_put_prop_index(ctx, -2, 0);
+       /* ... listeners newcandidate */
+       duk_push_int(ctx, (duk_int_t)flags);
+       /* ... listeners newcandidate flags */
+       duk_put_prop_index(ctx, -2, 1);
+       /* ... listeners newcandidate */
+       duk_put_prop_index(ctx, -2, idx);
+       /* ... listeners */
+       duk_pop(ctx);
+       /* ... */
+}
+
+static void event_target_unregister_listener(duk_context *ctx,
+                                            event_listener_flags flags)
+{
+       /* ... listeners callback */
+       /* If the given callback with the given flags is present,
+        * we remove it and shuffle the rest up.
+        */
+       duk_uarridx_t idx = 0;
+       while (duk_get_prop_index(ctx, -1, idx)) {
+               /* ... listeners callback candidate */
+               duk_get_prop_index(ctx, -1, 0);
+               duk_get_prop_index(ctx, -2, 1);
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               if (duk_strict_equals(ctx, -1, -3) &&
+                   duk_get_int(ctx, -1) == (duk_int_t)flags) {
+                       /* present */
+                       duk_pop(ctx);
+                       /* ... listeners callback candidate candidatecallback */
+                       duk_put_prop_index(ctx, -2, 2);
+                       /* ... listeners callback candidate */
+                       duk_pop(ctx);
+                       /* ... listeners callback */
+                       duk_push_int(ctx, idx);
+                       /* ... listeners callback found_at */
+                       break;
+               }
+               /* ... listeners callback candidate candidatecallback 
candidateflags */
+               duk_pop_3(ctx);
+               /* ... listeners callback */
+               idx++;
+       }
+       /* ... listeners callback undefined/found_at */
+       if (duk_is_undefined(ctx, -1)) {
+               /* not found, clean up and come out */
+               duk_pop_3(ctx);
+               return;
+       }
+       idx = duk_to_int(ctx, -1);
+       duk_pop_2(ctx);
+       /* ... listeners */
+       while (duk_get_prop_index(ctx, -1, idx + 1)) {
+               duk_put_prop_index(ctx, -2, idx);
+               idx++;
+       }
+       /* ... listeners undefined */
+       duk_del_prop_index(ctx, -2, idx + 1);
+       duk_pop_2(ctx);
+       /* ... */
+}
+
+
 %}
 
 init EventTarget()
 %{
        priv->is_node = false;
+       priv->capture_registered = false;
+       priv->bubbling_registered = false;
+       
 %}
 
 method EventTarget::addEventListener()
@@ -114,15 +168,69 @@ method EventTarget::addEventListener()
        /* type callback */
        duk_dup(ctx, -2);
        /* type callback type */
-       event_target_push_listeners(ctx);
+       duk_push_this(ctx);
+       /* type callback type this(=EventTarget) */
+       if (dukky_event_target_push_listeners(ctx, false) && priv->is_node) {
+               /* Take a moment to register a JS callback */
+               duk_size_t ev_ty_l;
+               const char *ev_ty = duk_to_lstring(ctx, -3, &ev_ty_l);
+               dom_string *ev_ty_s;
+               exc = dom_string_create((const uint8_t*)ev_ty, ev_ty_l,
+                                       &ev_ty_s);
+               if (exc != DOM_NO_ERR) {
+                       LOG("Oh dear, failed to create dom_string in 
addEventListener()");
+                       return 0;
+               }
+               /* TODO: Enable passing of capture vs. bubble for this */
+               dukky_register_event_listener_for(
+                       ctx, (dom_element *)((node_private_t *)priv)->node,
+                       ev_ty_s);
+               dom_string_unref(ev_ty_s);
+       }
        /* type callback typelisteners */
-       
+       duk_insert(ctx, -2);
+       /* type typelisteners callback */
+       event_target_register_listener(ctx, flags);
+       /* type */
        return 0;
 %}
 
 method EventTarget::removeEventListener()
 %{
-       dom_exception exc;
+       event_listener_flags flags = ELF_NONE;
+       /* Incoming stack is: type callback [options] */
+       if (duk_get_top(ctx) < 2) return 0; /* Bad arguments */
+       if (duk_get_top(ctx) > 3) return 0; /* Bad arguments */
+       if (duk_get_top(ctx) == 2) {
+               duk_push_object(ctx);
+               /* type callback options */
+       }
+       if (duk_get_type(ctx, -1) != DUK_TYPE_OBJECT) {
+               /* legacy support, if not object, it's the capture value */
+               duk_push_object(ctx);
+               /* ... capture options */
+               duk_insert(ctx, -2);
+               /* ... options capture */
+               duk_put_prop_string(ctx, -2, "capture");
+               /* ... options */
+       }
+       /* type callback options */
+       flags = event_listener_pop_options(ctx);
+       /* type callback */
+       duk_dup(ctx, -2);
+       /* type callback type */
+       duk_push_this(ctx);
+       /* type callback type this(=EventTarget) */
+       if (dukky_event_target_push_listeners(ctx, true)) {
+               /* nothing to do because the listener wasn't there at all */
+               duk_pop_3(ctx);
+               return 0;
+       }
+       /* type callback typelisteners */
+       duk_insert(ctx, -2);
+       /* type typelisteners callback */
+       event_target_unregister_listener(ctx, flags);
+       /* type */
        return 0;
 %}
 
diff --git a/content/handlers/javascript/duktape/dukky.c 
b/content/handlers/javascript/duktape/dukky.c
index 1282ad9..638430a 100644
--- a/content/handlers/javascript/duktape/dukky.c
+++ b/content/handlers/javascript/duktape/dukky.c
@@ -46,6 +46,7 @@
 #define EVENT_MAGIC MAGIC(EVENT_MAP)
 #define HANDLER_LISTENER_MAGIC MAGIC(HANDLER_LISTENER_MAP)
 #define HANDLER_MAGIC MAGIC(HANDLER_MAP)
+#define EVENT_LISTENER_JS_MAGIC MAGIC(EVENT_LISTENER_JS_MAP)
 
 static duk_ret_t dukky_populate_object(duk_context *ctx)
 {
@@ -809,6 +810,8 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
        dom_exception exc;
        dom_event_target *targ;
        dom_event_flow_phase phase;
+       duk_uarridx_t idx;
+       event_listener_flags flags;
 
        /* Retrieve the JS context from the Duktape context */
        duk_get_memory_functions(ctx, &funcs);
@@ -850,17 +853,14 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
        /* ... node */
        if (dukky_get_current_value_of_event_handler(
                    ctx, name, (dom_event_target *)targ) == false) {
-               dom_node_unref(targ);
-               dom_string_unref(name);
-               return;
+               /* TODO: Do I have to manage if there's other event handlers */
+               goto out;
        }
-       /** @todo handle other kinds of event than the generic case */
-       dom_node_unref(targ);
-       dom_string_unref(name);
        /* ... handler node */
        dukky_push_event(ctx, evt);
        /* ... handler node event */
        (void) nsu_getmonotonic_ms(&jsctx->exec_start_time);
+       /* Maybe skip calling if not capture or at-target ? */
        if (duk_pcall_method(ctx, 1) != 0) {
                /* Failed to run the method */
                /* ... err */
@@ -882,7 +882,7 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
 
                duk_pop_n(ctx, 6);
                /* ... */
-               return;
+               goto handle_extras;
        }
        /* ... result */
        if (duk_is_boolean(ctx, -1) &&
@@ -890,7 +890,92 @@ static void dukky_generic_event_handler(dom_event *evt, 
void *pw)
                dom_event_prevent_default(evt);
        }
        duk_pop(ctx);
+handle_extras:
+       /* ... */
+       duk_push_lstring(ctx, dom_string_data(name), dom_string_length(name));
+       dukky_push_node(ctx, (dom_node *)targ);
+       /* ... type node */
+       if (dukky_event_target_push_listeners(ctx, true)) {
+               /* Nothing to do */
+               duk_pop(ctx);
+               goto out;
+       }
+       /* ... sublisteners */
+       duk_push_array(ctx);
+       /* ... sublisteners copy */
+       idx = 0;
+       while (duk_get_prop_index(ctx, -2, idx)) {
+               /* ... sublisteners copy handler */
+               /* TODO check if the handler is ONCE, if so, remove it from
+                * the sublisteners */
+               duk_put_prop_index(ctx, -2, idx);
+               /* ... sublisteners copy */
+               idx++;
+       }
+       /* ... sublisteners copy undefined */
+       duk_pop(ctx);
+       /* ... sublisteners copy */
+       duk_insert(ctx, -2);
+       /* ... copy sublisteners */
+       duk_pop(ctx);
+       /* ... copy */
+       idx = 0;
+       while (duk_get_prop_index(ctx, -1, idx++)) {
+               /* ... copy handler */
+               if (duk_get_prop_index(ctx, -1, 2)) {
+                       /* ... copy handler meh */
+                       duk_pop_2(ctx);
+                       continue;
+               }
+               duk_pop(ctx);
+               duk_get_prop_index(ctx, -1, 0);
+               duk_get_prop_index(ctx, -2, 1);
+               /* ... copy handler callback flags */
+               flags = (event_listener_flags)duk_get_int(ctx, -1);
+               duk_pop(ctx);
+               /* TODO: So, should we run the event handler? */
+               dukky_push_node(ctx, (dom_node *)targ);
+               /* ... copy handler callback node */
+               dukky_push_event(ctx, evt);
+               /* ... copy handler callback node event */
+               (void) nsu_getmonotonic_ms(&jsctx->exec_start_time);
+               /* Maybe skip calling if not capture or at-target ? */
+               if (duk_pcall_method(ctx, 1) != 0) {
+                       /* Failed to run the method */
+                       /* ... copy handler err */
+                       LOG("OH NOES! An error running a callback.  Meh.");
+                       exc = dom_event_stop_immediate_propagation(evt);
+                       if (exc != DOM_NO_ERR)
+                               LOG("WORSE! could not stop propagation");
+                       duk_get_prop_string(ctx, -1, "name");
+                       duk_get_prop_string(ctx, -2, "message");
+                       duk_get_prop_string(ctx, -3, "fileName");
+                       duk_get_prop_string(ctx, -4, "lineNumber");
+                       duk_get_prop_string(ctx, -5, "stack");
+                       /* ... err name message fileName lineNumber stack */
+                       LOG("Uncaught error in JS: %s: %s", 
duk_safe_to_string(ctx, -5),
+                           duk_safe_to_string(ctx, -4));
+                       LOG("              was at: %s line %s", 
duk_safe_to_string(ctx, -3),
+                           duk_safe_to_string(ctx, -2));
+                       LOG("         Stack trace: %s", duk_safe_to_string(ctx, 
-1));
+                       
+                       duk_pop_n(ctx, 7);
+                       /* ... copy */
+                       continue;
+               }
+               /* ... copy handler result */
+               if (duk_is_boolean(ctx, -1) &&
+                   duk_to_boolean(ctx, -1) == 0) {
+                       dom_event_prevent_default(evt);
+               }
+               duk_pop_2(ctx);
+               /* ... copy */
+       }
+       duk_pop_2(ctx);
+out:
        /* ... */
+       dom_node_unref(targ);
+       dom_string_unref(name);
 }
 
 void dukky_register_event_listener_for(duk_context *ctx,
@@ -938,6 +1023,54 @@ void dukky_register_event_listener_for(duk_context *ctx,
        dom_event_listener_unref(listen);
 }
 
+/* The sub-listeners are a list of {callback,flags} tuples */
+/* We return true if we created a new sublistener table */
+/* If we're told to not create, but we want to, we still return true */        
+bool dukky_event_target_push_listeners(duk_context *ctx, bool dont_create)
+{
+       bool ret = false;
+       /* ... type this */
+       duk_get_prop_string(ctx, -1, EVENT_LISTENER_JS_MAGIC);
+       if (duk_is_null(ctx, -1)) {
+               /* ... type this null */
+               duk_pop(ctx);
+               duk_push_object(ctx);
+               duk_dup(ctx, -1);
+               /* ... type this listeners listeners */
+               duk_put_prop_string(ctx, -3, EVENT_LISTENER_JS_MAGIC);
+               /* ... type this listeners */
+       }
+       /* ... type this listeners */
+       duk_insert(ctx, -3);
+       /* ... listeners type this */
+       duk_pop(ctx);
+       /* ... listeners type */
+       duk_dup(ctx, -1);
+       /* ... listeners type type */
+       duk_get_prop(ctx, -3);
+       /* ... listeners type ??? */
+       if (duk_is_null(ctx, -1)) {
+               /* ... listeners type ??? */
+               if (dont_create == true) {
+                       duk_pop_3(ctx);
+                       duk_push_undefined(ctx);
+                       return true;
+               }
+               duk_pop(ctx);
+               duk_push_array(ctx);
+               duk_dup(ctx, -2);
+               duk_dup(ctx, -2);
+               /* ... listeners type sublisteners type sublisteners */
+               duk_put_prop(ctx, -5);
+               /* ... listeners type sublisteners */
+               ret = true;
+       }
+       duk_insert(ctx, -3);
+       /* ... sublisteners listeners type */
+       duk_pop_2(ctx);
+       /* ... sublisteners */
+       return ret;
+}
 
 void js_handle_new_element(jscontext *ctx, struct dom_element *node)
 {
diff --git a/content/handlers/javascript/duktape/dukky.h 
b/content/handlers/javascript/duktape/dukky.h
index 0c3ff0e..6ef9fdf 100644
--- a/content/handlers/javascript/duktape/dukky.h
+++ b/content/handlers/javascript/duktape/dukky.h
@@ -41,5 +41,13 @@ void dukky_register_event_listener_for(duk_context *ctx,
 bool dukky_get_current_value_of_event_handler(duk_context *ctx,
                                              dom_string *name,
                                              dom_event_target *et);
+bool dukky_event_target_push_listeners(duk_context *ctx, bool dont_create);
+
+typedef enum {
+       ELF_CAPTURE = 1 << 0,
+       ELF_PASSIVE = 1 << 1,
+       ELF_ONCE    = 1 << 2,
+       ELF_NONE    = 0
+} event_listener_flags;
 
 #endif


-- 
NetSurf Browser

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to