Bug Summary

File:content/handlers/javascript/duktape/dukky.c
Warning:line 1681, column 2
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dukky.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I . -I include -I build/Linux-gtk2 -I frontends -I content/handlers -D WITH_JPEG -U WITH_PDF_EXPORT -D LIBICONV_PLUG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /usr/include/x86_64-linux-gnu -D WITH_CURL -D WITH_OPENSSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D UTF8PROC_EXPORTS -D WITH_UTF8PROC -D WITH_WEBP -I /usr/include/libpng16 -D WITH_PNG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include/ -D WITH_BMP -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_GIF -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NS_SVG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSSPRITE -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSPSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSLOG -D NETSURF_UA_FORMAT_STRING="Mozilla/5.0 (%s) NetSurf/%d.%d" -D NETSURF_HOMEPAGE="about:welcome" -D NETSURF_LOG_LEVEL=VERBOSE -D NETSURF_BUILTIN_LOG_FILTER="(level:WARNING || cat:jserrors)" -D NETSURF_BUILTIN_VERBOSE_FILTER="(level:VERBOSE || cat:jserrors)" -D STMTEXPR=1 -I /usr/include/librsvg-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/libpng16 -I /usr/include/x86_64-linux-gnu -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/freetype2 -D WITH_RSVG -I /usr/include/gtk-2.0 -I /usr/lib/x86_64-linux-gnu/gtk-2.0/include -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/atk-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -D gtk -D nsgtk -D G_DISABLE_SINGLE_INCLUDES -D G_DISABLE_DEPRECATED -D GTK_DISABLE_SINGLE_INCLUDES -D GTK_MULTIHEAD_SAFE -D PANGO_DISABLE_DEPRECATED -D GTK_DISABLE_DEPRECATED -D _XOPEN_SOURCE=700 -D _POSIX_C_SOURCE=200809L -D _BSD_SOURCE -D _DEFAULT_SOURCE -D _NETBSD_SOURCE -D GTK_RESPATH="/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf/:./frontends/gtk/res/" -D WITH_GRESOURCE -D DUK_OPT_HAVE_CUSTOM_H -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wwrite-strings -Wno-unused-parameter -Wno-unused-but-set-variable -std=c99 -fconst-strings -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-netsurf/clangScanBuildReports/2024-12-27-084849-3370695-1 -x c content/handlers/javascript/duktape/dukky.c
1/*
2 * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
3 * Copyright 2015 Daniel Dilverstone <dsilvers@netsurf-browser.org>
4 * Copyright 2016 Michael Drake <tlsa@netsurf-browser.org>
5 * Copyright 2016 John-Mark Bell <jmb@netsurf-browser.org>
6 *
7 * This file is part of NetSurf, http://www.netsurf-browser.org/
8 *
9 * NetSurf is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * NetSurf is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/**
23 * \file
24 * Duktapeish implementation of javascript engine functions.
25 */
26
27#include <stdint.h>
28#include <nsutils/time.h>
29
30#include "netsurf/inttypes.h"
31#include "utils/utils.h"
32#include "utils/nsoption.h"
33#include "utils/log.h"
34#include "utils/corestrings.h"
35#include "content/content.h"
36
37#include "javascript/js.h"
38#include "javascript/content.h"
39
40#include "duktape/binding.h"
41#include "duktape/generics.js.inc"
42#include "duktape/polyfill.js.inc"
43
44#include "duktape.h"
45#include "dukky.h"
46
47#include <dom/dom.h>
48
49#define EVENT_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_MAP") MAGIC(EVENT_MAP)("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_MAP")
50#define HANDLER_LISTENER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_LISTENER_MAP") MAGIC(HANDLER_LISTENER_MAP)("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_LISTENER_MAP")
51#define HANDLER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_MAP") MAGIC(HANDLER_MAP)("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_MAP")
52#define EVENT_LISTENER_JS_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_LISTENER_JS_MAP") MAGIC(EVENT_LISTENER_JS_MAP)("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_LISTENER_JS_MAP")
53#define GENERICS_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "GENERICS_TABLE") MAGIC(GENERICS_TABLE)("\xFF\xFFNETSURF_DUKTAPE_" "GENERICS_TABLE")
54#define THREAD_MAP("\xFF\xFFNETSURF_DUKTAPE_" "THREAD_MAP") MAGIC(THREAD_MAP)("\xFF\xFFNETSURF_DUKTAPE_" "THREAD_MAP")
55
56/**
57 * dukky javascript heap
58 */
59struct jsheap {
60 duk_context *ctx; /**< duktape base context */
61 duk_uarridx_t next_thread; /**< monotonic thread counter */
62 bool_Bool pending_destroy; /**< Whether this heap is pending destruction */
63 unsigned int live_threads; /**< number of live threads */
64 uint64_t exec_start_time;
65};
66
67/**
68 * dukky javascript thread
69 */
70struct jsthread {
71 bool_Bool pending_destroy; /**< Whether this thread is pending destruction */
72 unsigned int in_use; /**< The number of times this thread is in use */
73 jsheap *heap; /**< The heap this thread belongs to */
74 duk_context *ctx; /**< The duktape thread context */
75 duk_uarridx_t thread_idx; /**< The thread number */
76};
77
78static duk_ret_t dukky_populate_object(duk_context *ctx, void *udata)
79{
80 /* ... obj args protoname nargs */
81 int nargs = duk_get_int(ctx, -1);
82 duk_pop(ctx);
83 /* ... obj args protoname */
84 duk_get_global_string(ctx, PROTO_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPES"));
85 /* .. obj args protoname prototab */
86 duk_dup(ctx, -2);
87 /* ... obj args protoname prototab protoname */
88 duk_get_prop(ctx, -2);
89 /* ... obj args protoname prototab {proto/undefined} */
90 if (duk_is_undefined(ctx, -1)) {
91 NSLOG(dukky, WARNING,do { if (NSLOG_LEVEL_WARNING >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_WARNING, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 93, }; nslog__log(&_nslog_ctx
, "Unable to find dukky prototype for `%s` - falling back to HTMLUnknownElement"
, duk_get_string(ctx, -3) + 2); } } while(0)
92 "Unable to find dukky prototype for `%s` - falling back to HTMLUnknownElement",do { if (NSLOG_LEVEL_WARNING >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_WARNING, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 93, }; nslog__log(&_nslog_ctx
, "Unable to find dukky prototype for `%s` - falling back to HTMLUnknownElement"
, duk_get_string(ctx, -3) + 2); } } while(0)
93 duk_get_string(ctx, -3) + 2 /* Skip the two unprintables */)do { if (NSLOG_LEVEL_WARNING >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_WARNING, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 93, }; nslog__log(&_nslog_ctx
, "Unable to find dukky prototype for `%s` - falling back to HTMLUnknownElement"
, duk_get_string(ctx, -3) + 2); } } while(0)
;
94 duk_pop(ctx);
95 duk_push_string(ctx, PROTO_NAME(HTMLUNKNOWNELEMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "HTMLUNKNOWNELEMENT"
)
);
96 duk_get_prop(ctx, -2);
97 }
98 /* ... obj args protoname prototab proto */
99 duk_remove(ctx, -3);
100 /* ... obj args prototab proto */
101 duk_dup(ctx, -1);
102 /* ... obj args prototab proto proto */
103 duk_set_prototype(ctx, -(nargs+4));
104 /* ... obj[proto] args prototab proto */
105 duk_get_prop_string(ctx, -1, INIT_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "INIT"));
106 /* ... obj[proto] args prototab proto initfn */
107 duk_insert(ctx, -(nargs+4));
108 /* ... initfn obj[proto] args prototab proto */
109 duk_pop_2(ctx);
110 /* ... initfn obj[proto] args */
111 NSLOG(dukky, DEEPDEBUG, "Call the init function")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 111, }; nslog__log(&_nslog_ctx
, "Call the init function"); } } while(0)
;
112 duk_call(ctx, nargs + 1);
113 return 1; /* The object */
114}
115
116duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args)
117{
118 duk_ret_t ret;
119 NSLOG(dukky, DEEPDEBUG, "name=%s nargs=%d", name + 2, args)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 119, }; nslog__log(&_nslog_ctx
, "name=%s nargs=%d", name + 2, args); } } while(0)
;
120 /* ... args */
121 duk_push_object(ctx);
122 /* ... args obj */
123 duk_push_object(ctx);
124 /* ... args obj handlers */
125 duk_put_prop_string(ctx, -2, HANDLER_LISTENER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_LISTENER_MAP"));
126 /* ... args obj */
127 duk_push_object(ctx);
128 /* ... args obj handlers */
129 duk_put_prop_string(ctx, -2, HANDLER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_MAP"));
130 /* ... args obj */
131 duk_insert(ctx, -(args+1));
132 /* ... obj args */
133 duk_push_string(ctx, name);
134 /* ... obj args name */
135 duk_push_int(ctx, args);
136 /* ... obj args name nargs */
137 if ((ret = duk_safe_call(ctx, dukky_populate_object, NULL((void*)0), args + 3, 1))
138 != DUK_EXEC_SUCCESS0)
139 return ret;
140 NSLOG(dukky, DEEPDEBUG, "created")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 140, }; nslog__log(&_nslog_ctx
, "created"); } } while(0)
;
141 return DUK_EXEC_SUCCESS0;
142}
143
144
145
146duk_bool_t
147dukky_push_node_stacked(duk_context *ctx)
148{
149 int top_at_fail = duk_get_top(ctx) - 2;
150 /* ... nodeptr klass */
151 duk_get_global_string(ctx, NODE_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "NODE_MAP"));
152 /* ... nodeptr klass nodes */
153 duk_dup(ctx, -3);
154 /* ... nodeptr klass nodes nodeptr */
155 duk_get_prop(ctx, -2);
156 /* ... nodeptr klass nodes node/undefined */
157 if (duk_is_undefined(ctx, -1)) {
158 /* ... nodeptr klass nodes undefined */
159 duk_pop(ctx);
160 /* ... nodeptr klass nodes */
161 duk_push_object(ctx);
162 /* ... nodeptr klass nodes obj */
163 duk_push_object(ctx);
164 /* ... nodeptr klass nodes obj handlers */
165 duk_put_prop_string(ctx, -2, HANDLER_LISTENER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_LISTENER_MAP"));
166 /* ... nodeptr klass nodes obj */
167 duk_push_object(ctx);
168 /* ... nodeptr klass nodes obj handlers */
169 duk_put_prop_string(ctx, -2, HANDLER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_MAP"));
170 /* ... nodeptr klass nodes obj */
171 duk_dup(ctx, -4);
172 /* ... nodeptr klass nodes obj nodeptr */
173 duk_dup(ctx, -4);
174 /* ... nodeptr klass nodes obj nodeptr klass */
175 duk_push_int(ctx, 1);
176 /* ... nodeptr klass nodes obj nodeptr klass 1 */
177 if (duk_safe_call(ctx, dukky_populate_object, NULL((void*)0), 4, 1)
178 != DUK_EXEC_SUCCESS0) {
179 duk_set_top(ctx, top_at_fail);
180 NSLOG(dukky, ERROR, "Failed to populate object prototype")do { if (NSLOG_LEVEL_ERROR >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_ERROR, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 180, }; nslog__log(&_nslog_ctx
, "Failed to populate object prototype"); } } while(0)
;
181 return false0;
182 }
183 /* ... nodeptr klass nodes node */
184 duk_dup(ctx, -4);
185 /* ... nodeptr klass nodes node nodeptr */
186 duk_dup(ctx, -2);
187 /* ... nodeptr klass nodes node nodeptr node */
188 duk_put_prop(ctx, -4);
189 /* ... nodeptr klass nodes node */
190 }
191 /* ... nodeptr klass nodes node */
192 duk_insert(ctx, -4);
193 /* ... node nodeptr klass nodes */
194 duk_pop_3(ctx);
195 /* ... node */
196 if (NSLOG_COMPILED_MIN_LEVELNSLOG_LEVEL_VERBOSE <= NSLOG_LEVEL_DEEPDEBUG) {
197 duk_dup(ctx, -1);
198 const char * what = duk_safe_to_string(ctx, -1)duk_safe_to_lstring((ctx), (-1), ((void*)0));
199 NSLOG(dukky, DEEPDEBUG, "Created: %s", what)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 199, }; nslog__log(&_nslog_ctx
, "Created: %s", what); } } while(0)
;
200 duk_pop(ctx);
201 }
202 return true1;
203}
204
205#define SET_HTML_CLASS(CLASS) \
206 *html_class = PROTO_NAME(HTML##CLASS##ELEMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "HTML##CLASS##ELEMENT"
)
; \
207 *html_class_len = \
208 SLEN(PROTO_NAME(HTML))(sizeof((("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "HTML"))) -
1)
+ \
209 SLEN(#CLASS)(sizeof((#CLASS)) - 1) + \
210 SLEN("ELEMENT")(sizeof(("ELEMENT")) - 1);
211
212static void dukky_html_element_class_from_tag_type(dom_html_element_type type,
213 const char **html_class, size_t *html_class_len)
214{
215 switch(type) {
216 case DOM_HTML_ELEMENT_TYPE_HTML:
217 SET_HTML_CLASS(HTML)
218 break;
219 case DOM_HTML_ELEMENT_TYPE_HEAD:
220 SET_HTML_CLASS(HEAD)
221 break;
222 case DOM_HTML_ELEMENT_TYPE_META:
223 SET_HTML_CLASS(META)
224 break;
225 case DOM_HTML_ELEMENT_TYPE_BASE:
226 SET_HTML_CLASS(BASE)
227 break;
228 case DOM_HTML_ELEMENT_TYPE_TITLE:
229 SET_HTML_CLASS(TITLE)
230 break;
231 case DOM_HTML_ELEMENT_TYPE_BODY:
232 SET_HTML_CLASS(BODY)
233 break;
234 case DOM_HTML_ELEMENT_TYPE_DIV:
235 SET_HTML_CLASS(DIV)
236 break;
237 case DOM_HTML_ELEMENT_TYPE_FORM:
238 SET_HTML_CLASS(FORM)
239 break;
240 case DOM_HTML_ELEMENT_TYPE_LINK:
241 SET_HTML_CLASS(LINK)
242 break;
243 case DOM_HTML_ELEMENT_TYPE_BUTTON:
244 SET_HTML_CLASS(BUTTON)
245 break;
246 case DOM_HTML_ELEMENT_TYPE_INPUT:
247 SET_HTML_CLASS(INPUT)
248 break;
249 case DOM_HTML_ELEMENT_TYPE_TEXTAREA:
250 SET_HTML_CLASS(TEXTAREA)
251 break;
252 case DOM_HTML_ELEMENT_TYPE_OPTGROUP:
253 SET_HTML_CLASS(OPTGROUP)
254 break;
255 case DOM_HTML_ELEMENT_TYPE_OPTION:
256 SET_HTML_CLASS(OPTION)
257 break;
258 case DOM_HTML_ELEMENT_TYPE_SELECT:
259 SET_HTML_CLASS(SELECT)
260 break;
261 case DOM_HTML_ELEMENT_TYPE_HR:
262 SET_HTML_CLASS(HR)
263 break;
264 case DOM_HTML_ELEMENT_TYPE_DL:
265 SET_HTML_CLASS(DLIST)
266 break;
267 case DOM_HTML_ELEMENT_TYPE_DIR:
268 SET_HTML_CLASS(DIRECTORY)
269 break;
270 case DOM_HTML_ELEMENT_TYPE_MENU:
271 SET_HTML_CLASS(MENU)
272 break;
273 case DOM_HTML_ELEMENT_TYPE_FIELDSET:
274 SET_HTML_CLASS(FIELDSET)
275 break;
276 case DOM_HTML_ELEMENT_TYPE_LEGEND:
277 SET_HTML_CLASS(LEGEND)
278 break;
279 case DOM_HTML_ELEMENT_TYPE_P:
280 SET_HTML_CLASS(PARAGRAPH)
281 break;
282 case DOM_HTML_ELEMENT_TYPE_H1:
283 case DOM_HTML_ELEMENT_TYPE_H2:
284 case DOM_HTML_ELEMENT_TYPE_H3:
285 case DOM_HTML_ELEMENT_TYPE_H4:
286 case DOM_HTML_ELEMENT_TYPE_H5:
287 case DOM_HTML_ELEMENT_TYPE_H6:
288 SET_HTML_CLASS(HEADING)
289 break;
290 case DOM_HTML_ELEMENT_TYPE_BLOCKQUOTE:
291 case DOM_HTML_ELEMENT_TYPE_Q:
292 SET_HTML_CLASS(QUOTE)
293 break;
294 case DOM_HTML_ELEMENT_TYPE_PRE:
295 SET_HTML_CLASS(PRE)
296 break;
297 case DOM_HTML_ELEMENT_TYPE_BR:
298 SET_HTML_CLASS(BR)
299 break;
300 case DOM_HTML_ELEMENT_TYPE_LABEL:
301 SET_HTML_CLASS(LABEL)
302 break;
303 case DOM_HTML_ELEMENT_TYPE_UL:
304 SET_HTML_CLASS(ULIST)
305 break;
306 case DOM_HTML_ELEMENT_TYPE_OL:
307 SET_HTML_CLASS(OLIST)
308 break;
309 case DOM_HTML_ELEMENT_TYPE_LI:
310 SET_HTML_CLASS(LI)
311 break;
312 case DOM_HTML_ELEMENT_TYPE_FONT:
313 SET_HTML_CLASS(FONT)
314 break;
315 case DOM_HTML_ELEMENT_TYPE_DEL:
316 case DOM_HTML_ELEMENT_TYPE_INS:
317 SET_HTML_CLASS(MOD)
318 break;
319 case DOM_HTML_ELEMENT_TYPE_A:
320 SET_HTML_CLASS(ANCHOR)
321 break;
322 case DOM_HTML_ELEMENT_TYPE_BASEFONT:
323 SET_HTML_CLASS(BASEFONT)
324 break;
325 case DOM_HTML_ELEMENT_TYPE_IMG:
326 SET_HTML_CLASS(IMAGE)
327 break;
328 case DOM_HTML_ELEMENT_TYPE_OBJECT:
329 SET_HTML_CLASS(OBJECT)
330 break;
331 case DOM_HTML_ELEMENT_TYPE_PARAM:
332 SET_HTML_CLASS(PARAM)
333 break;
334 case DOM_HTML_ELEMENT_TYPE_APPLET:
335 SET_HTML_CLASS(APPLET)
336 break;
337 case DOM_HTML_ELEMENT_TYPE_MAP:
338 SET_HTML_CLASS(MAP)
339 break;
340 case DOM_HTML_ELEMENT_TYPE_AREA:
341 SET_HTML_CLASS(AREA)
342 break;
343 case DOM_HTML_ELEMENT_TYPE_SCRIPT:
344 SET_HTML_CLASS(SCRIPT)
345 break;
346 case DOM_HTML_ELEMENT_TYPE_CAPTION:
347 SET_HTML_CLASS(TABLECAPTION)
348 break;
349 case DOM_HTML_ELEMENT_TYPE_TD:
350 case DOM_HTML_ELEMENT_TYPE_TH:
351 SET_HTML_CLASS(TABLECELL)
352 break;
353 case DOM_HTML_ELEMENT_TYPE_COL:
354 case DOM_HTML_ELEMENT_TYPE_COLGROUP:
355 SET_HTML_CLASS(TABLECOL)
356 break;
357 case DOM_HTML_ELEMENT_TYPE_THEAD:
358 case DOM_HTML_ELEMENT_TYPE_TBODY:
359 case DOM_HTML_ELEMENT_TYPE_TFOOT:
360 SET_HTML_CLASS(TABLESECTION)
361 break;
362 case DOM_HTML_ELEMENT_TYPE_TABLE:
363 SET_HTML_CLASS(TABLE)
364 break;
365 case DOM_HTML_ELEMENT_TYPE_TR:
366 SET_HTML_CLASS(TABLEROW)
367 break;
368 case DOM_HTML_ELEMENT_TYPE_STYLE:
369 SET_HTML_CLASS(STYLE)
370 break;
371 case DOM_HTML_ELEMENT_TYPE_FRAMESET:
372 SET_HTML_CLASS(FRAMESET)
373 break;
374 case DOM_HTML_ELEMENT_TYPE_FRAME:
375 SET_HTML_CLASS(FRAME)
376 break;
377 case DOM_HTML_ELEMENT_TYPE_IFRAME:
378 SET_HTML_CLASS(IFRAME)
379 break;
380 case DOM_HTML_ELEMENT_TYPE_ISINDEX:
381 SET_HTML_CLASS(ISINDEX)
382 break;
383 case DOM_HTML_ELEMENT_TYPE_CANVAS:
384 SET_HTML_CLASS(CANVAS)
385 break;
386 case DOM_HTML_ELEMENT_TYPE__COUNT:
387 assert(type != DOM_HTML_ELEMENT_TYPE__COUNT)((type != DOM_HTML_ELEMENT_TYPE__COUNT) ? (void) (0) : __assert_fail
("type != DOM_HTML_ELEMENT_TYPE__COUNT", "content/handlers/javascript/duktape/dukky.c"
, 387, __extension__ __PRETTY_FUNCTION__))
;
388 fallthrough__attribute__((__fallthrough__));
389 case DOM_HTML_ELEMENT_TYPE__UNKNOWN:
390 SET_HTML_CLASS(UNKNOWN)
391 break;
392 default:
393 /* Known HTML element without a specialisation */
394 *html_class = PROTO_NAME(HTMLELEMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "HTMLELEMENT");
395 *html_class_len =
396 SLEN(PROTO_NAME(HTML))(sizeof((("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "HTML"))) -
1)
+
397 SLEN("ELEMENT")(sizeof(("ELEMENT")) - 1);
398 break;
399 }
400 return;
401}
402
403#undef SET_HTML_CLASS
404
405static void
406dukky_push_node_klass(duk_context *ctx, struct dom_node *node)
407{
408 dom_node_type nodetype;
409 dom_exception err;
410
411 err = dom_node_get_node_type(node, &nodetype)dom_node_get_node_type( (dom_node *) (node), (dom_node_type *
) (&nodetype))
;
412 if (err != DOM_NO_ERR) {
413 /* Oh bum, just node then */
414 duk_push_string(ctx, PROTO_NAME(NODE)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "NODE"));
415 return;
416 }
417
418 switch(nodetype) {
419 case DOM_ELEMENT_NODE: {
420 dom_string *namespace;
421 dom_html_element_type type;
422 const char *html_class;
423 size_t html_class_len;
424 err = dom_node_get_namespace(node, &namespace)dom_node_get_namespace((dom_node *) (node), (&namespace));
425 if (err != DOM_NO_ERR) {
426 /* Feck it, element */
427 NSLOG(dukky, ERROR,do { if (NSLOG_LEVEL_ERROR >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_ERROR, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 428, }; nslog__log(&_nslog_ctx
, "dom_node_get_namespace() failed"); } } while(0)
428 "dom_node_get_namespace() failed")do { if (NSLOG_LEVEL_ERROR >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_ERROR, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 428, }; nslog__log(&_nslog_ctx
, "dom_node_get_namespace() failed"); } } while(0)
;
429 duk_push_string(ctx, PROTO_NAME(ELEMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "ELEMENT"));
430 break;
431 }
432 if (namespace == NULL((void*)0)) {
433 /* No namespace, -> element */
434 NSLOG(dukky, DEBUG, "no namespace")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 434, }; nslog__log(&_nslog_ctx
, "no namespace"); } } while(0)
;
435 duk_push_string(ctx, PROTO_NAME(ELEMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "ELEMENT"));
436 break;
437 }
438
439 if (dom_string_isequal(namespace, corestring_dom_html_namespace) == false0) {
440 /* definitely not an HTML element of some kind */
441 duk_push_string(ctx, PROTO_NAME(ELEMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "ELEMENT"));
442 dom_string_unref(namespace);
443 break;
444 }
445 dom_string_unref(namespace);
446
447 err = dom_html_element_get_tag_type(node, &type)dom_html_element_get_tag_type((const dom_html_element *) (node
), (&type))
;
448 if (err != DOM_NO_ERR) {
449 type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
450 }
451
452 dukky_html_element_class_from_tag_type(type,
453 &html_class, &html_class_len);
454
455 duk_push_lstring(ctx, html_class, html_class_len);
456 break;
457 }
458 case DOM_TEXT_NODE:
459 duk_push_string(ctx, PROTO_NAME(TEXT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "TEXT"));
460 break;
461 case DOM_COMMENT_NODE:
462 duk_push_string(ctx, PROTO_NAME(COMMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "COMMENT"));
463 break;
464 case DOM_DOCUMENT_NODE:
465 duk_push_string(ctx, PROTO_NAME(DOCUMENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "DOCUMENT"));
466 break;
467 case DOM_ATTRIBUTE_NODE:
468 case DOM_PROCESSING_INSTRUCTION_NODE:
469 case DOM_DOCUMENT_TYPE_NODE:
470 case DOM_DOCUMENT_FRAGMENT_NODE:
471 case DOM_NOTATION_NODE:
472 case DOM_ENTITY_REFERENCE_NODE:
473 case DOM_ENTITY_NODE:
474 case DOM_CDATA_SECTION_NODE:
475 default:
476 /* Oh bum, just node then */
477 duk_push_string(ctx, PROTO_NAME(NODE)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "NODE"));
478 }
479}
480
481duk_bool_t
482dukky_push_node(duk_context *ctx, struct dom_node *node)
483{
484 NSLOG(dukky, DEEPDEBUG, "Pushing node %p", node)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 484, }; nslog__log(&_nslog_ctx
, "Pushing node %p", node); } } while(0)
;
485 /* First check if we can find the node */
486 /* ... */
487 duk_get_global_string(ctx, NODE_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "NODE_MAP"));
488 /* ... nodes */
489 duk_push_pointer(ctx, node);
490 /* ... nodes nodeptr */
491 duk_get_prop(ctx, -2);
492 /* ... nodes node/undefined */
493 if (!duk_is_undefined(ctx, -1)) {
494 /* ... nodes node */
495 duk_insert(ctx, -2);
496 /* ... node nodes */
497 duk_pop(ctx);
498 /* ... node */
499 if (NSLOG_COMPILED_MIN_LEVELNSLOG_LEVEL_VERBOSE <= NSLOG_LEVEL_DEEPDEBUG) {
500 duk_dup(ctx, -1);
501 const char * what = duk_safe_to_string(ctx, -1)duk_safe_to_lstring((ctx), (-1), ((void*)0));
502 NSLOG(dukky, DEEPDEBUG, "Found it memoised: %s", what)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 502, }; nslog__log(&_nslog_ctx
, "Found it memoised: %s", what); } } while(0)
;
503 duk_pop(ctx);
504 }
505 return true1;
506 }
507 /* ... nodes undefined */
508 duk_pop_2(ctx);
509 /* ... */
510 /* We couldn't, so now we determine the node type and then
511 * we ask for it to be created
512 */
513 duk_push_pointer(ctx, node);
514 /* ... nodeptr */
515 dukky_push_node_klass(ctx, node);
516 /* ... nodeptr klass */
517 return dukky_push_node_stacked(ctx);
518}
519
520static duk_ret_t
521dukky_bad_constructor(duk_context *ctx)
522{
523 return duk_error(ctx, DUK_ERR_ERROR, "Bad constructor")(duk_error_raw((ctx), (duk_errcode_t) (1), (const char *) ("content/handlers/javascript/duktape/dukky.c"
), (duk_int_t) (523), "Bad constructor"), (duk_ret_t) 0)
;
524}
525
526void
527dukky_inject_not_ctr(duk_context *ctx, int idx, const char *name)
528{
529 /* ... p[idx] ... proto */
530 duk_push_c_function(ctx, dukky_bad_constructor, 0);
531 /* ... p[idx] ... proto cons */
532 duk_insert(ctx, -2);
533 /* ... p[idx] ... cons proto */
534 duk_put_prop_string(ctx, -2, "prototype");
535 /* ... p[idx] ... cons[proto] */
536 duk_put_prop_string(ctx, idx, name);
537 /* ... p ... */
538 return;
539}
540
541/* Duktape heap utility functions */
542
543/* We need to override the defaults because not all platforms are fully ANSI
544 * compatible. E.g. RISC OS gets upset if we malloc or realloc a zero byte
545 * block, as do debugging tools such as Electric Fence by Bruce Perens.
546 */
547
548static void *dukky_alloc_function(void *udata, duk_size_t size)
549{
550 if (size == 0)
551 return NULL((void*)0);
552
553 return malloc(size);
554}
555
556static void *dukky_realloc_function(void *udata, void *ptr, duk_size_t size)
557{
558 if (ptr == NULL((void*)0) && size == 0)
559 return NULL((void*)0);
560
561 if (size == 0) {
562 free(ptr);
563 return NULL((void*)0);
564 }
565
566 return realloc(ptr, size);
567}
568
569
570static void dukky_free_function(void *udata, void *ptr)
571{
572 if (ptr != NULL((void*)0))
573 free(ptr);
574}
575
576/* exported interface documented in js.h */
577void js_initialise(void)
578{
579 /** TODO: Forces JS on for our testing, needs changing before a release
580 * lest we incur the wrath of others.
581 */
582 /* Disabled force-on for forthcoming release */
583 /* nsoption_set_bool(enable_javascript, true);
584 */
585 javascript_init();
586}
587
588
589/* exported interface documented in js.h */
590void js_finalise(void)
591{
592 /* NADA for now */
593}
594
595
596/* exported interface documented in js.h */
597nserror
598js_newheap(int timeout, jsheap **heap)
599{
600 duk_context *ctx;
601 jsheap *ret = calloc(1, sizeof(*ret));
602 *heap = NULL((void*)0);
603 NSLOG(dukky, DEBUG, "Creating new duktape javascript heap")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 603, }; nslog__log(&_nslog_ctx
, "Creating new duktape javascript heap"); } } while(0)
;
604 if (ret == NULL((void*)0)) return NSERROR_NOMEM;
605 ctx = ret->ctx = duk_create_heap(
606 dukky_alloc_function,
607 dukky_realloc_function,
608 dukky_free_function,
609 ret,
610 NULL((void*)0));
611 if (ret->ctx == NULL((void*)0)) { free(ret); return NSERROR_NOMEM; }
612 /* Create the prototype stuffs */
613 duk_push_global_object(ctx);
614 duk_push_boolean(ctx, true1);
615 duk_put_prop_string(ctx, -2, "protos");
616 duk_put_global_string(ctx, PROTO_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPES"));
617 /* Create prototypes here */
618 dukky_create_prototypes(ctx);
619 /* Now create the thread map */
620 duk_push_object(ctx);
621 duk_put_global_string(ctx, THREAD_MAP("\xFF\xFFNETSURF_DUKTAPE_" "THREAD_MAP"));
622
623 *heap = ret;
624 return NSERROR_OK;
625}
626
627
628static void dukky_destroyheap(jsheap *heap)
629{
630 assert(heap->pending_destroy == true)((heap->pending_destroy == 1) ? (void) (0) : __assert_fail
("heap->pending_destroy == true", "content/handlers/javascript/duktape/dukky.c"
, 630, __extension__ __PRETTY_FUNCTION__))
;
631 assert(heap->live_threads == 0)((heap->live_threads == 0) ? (void) (0) : __assert_fail ("heap->live_threads == 0"
, "content/handlers/javascript/duktape/dukky.c", 631, __extension__
__PRETTY_FUNCTION__))
;
632 NSLOG(dukky, DEBUG, "Destroying duktape javascript context")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 632, }; nslog__log(&_nslog_ctx
, "Destroying duktape javascript context"); } } while(0)
;
633 duk_destroy_heap(heap->ctx);
634 free(heap);
635}
636
637/* exported interface documented in js.h */
638void js_destroyheap(jsheap *heap)
639{
640 heap->pending_destroy = true1;
641 if (heap->live_threads == 0) {
642 dukky_destroyheap(heap);
643 }
644}
645
646/* Just for here, the CTX is in ret, not thread */
647#define CTX(thread->ctx) (ret->ctx)
648
649/* exported interface documented in js.h */
650nserror js_newthread(jsheap *heap, void *win_priv, void *doc_priv, jsthread **thread)
651{
652 jsthread *ret;
653 assert(heap != NULL)((heap != ((void*)0)) ? (void) (0) : __assert_fail ("heap != NULL"
, "content/handlers/javascript/duktape/dukky.c", 653, __extension__
__PRETTY_FUNCTION__))
;
654 assert(heap->pending_destroy == false)((heap->pending_destroy == 0) ? (void) (0) : __assert_fail
("heap->pending_destroy == false", "content/handlers/javascript/duktape/dukky.c"
, 654, __extension__ __PRETTY_FUNCTION__))
;
655
656 ret = calloc(1, sizeof (*ret));
657 if (ret == NULL((void*)0)) {
658 NSLOG(dukky, ERROR, "Unable to allocate new JS thread structure")do { if (NSLOG_LEVEL_ERROR >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_ERROR, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 658, }; nslog__log(&_nslog_ctx
, "Unable to allocate new JS thread structure"); } } while(0)
;
659 return NSERROR_NOMEM;
660 }
661
662 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 664, }; nslog__log(&_nslog_ctx
, "New javascript/duktape thread, win_priv=%p, doc_priv=%p", win_priv
, doc_priv); } } while(0)
663 "New javascript/duktape thread, win_priv=%p, doc_priv=%p",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 664, }; nslog__log(&_nslog_ctx
, "New javascript/duktape thread, win_priv=%p, doc_priv=%p", win_priv
, doc_priv); } } while(0)
664 win_priv, doc_priv)do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 664, }; nslog__log(&_nslog_ctx
, "New javascript/duktape thread, win_priv=%p, doc_priv=%p", win_priv
, doc_priv); } } while(0)
;
665
666 /* create new thread */
667 duk_get_global_string(heap->ctx, THREAD_MAP("\xFF\xFFNETSURF_DUKTAPE_" "THREAD_MAP")); /* ... threads */
668 duk_push_thread(heap->ctx)duk_push_thread_raw((heap->ctx), 0 ); /* ... threads thread */
669 ret->heap = heap;
670 ret->ctx = duk_require_context(heap->ctx, -1);
671 ret->thread_idx = heap->next_thread++;
672 duk_put_prop_index(heap->ctx, -2, ret->thread_idx);
673 heap->live_threads++;
674 duk_pop(heap->ctx); /* ... */
675 duk_push_int(CTX(thread->ctx), 0);
676 duk_push_int(CTX(thread->ctx), 1);
677 duk_push_int(CTX(thread->ctx), 2);
678 /* Manufacture a Window object */
679 /* win_priv is a browser_window, doc_priv is an html content struct */
680 duk_push_pointer(CTX(thread->ctx), win_priv);
681 duk_push_pointer(CTX(thread->ctx), doc_priv);
682 dukky_create_object(CTX(thread->ctx), PROTO_NAME(WINDOW)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "WINDOW"), 2);
683 duk_push_global_object(CTX(thread->ctx));
684 duk_put_prop_string(CTX(thread->ctx), -2, PROTO_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPES"));
685 duk_set_global_object(CTX(thread->ctx));
686
687 /* Now we need to prepare our node mapping table */
688 duk_push_object(CTX(thread->ctx));
689 duk_push_pointer(CTX(thread->ctx), NULL((void*)0));
690 duk_push_null(CTX(thread->ctx));
691 duk_put_prop(CTX(thread->ctx), -3);
692 duk_put_global_string(CTX(thread->ctx), NODE_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "NODE_MAP"));
693
694 /* And now the event mapping table */
695 duk_push_object(CTX(thread->ctx));
696 duk_put_global_string(CTX(thread->ctx), EVENT_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_MAP"));
697
698 /* Now load the polyfills */
699 /* ... */
700 duk_push_string(CTX(thread->ctx), "polyfill.js");
701 /* ..., polyfill.js */
702 if (duk_pcompile_lstring_filename(CTX, DUK_COMPILE_EVAL,(duk_compile_raw(((thread->ctx)), (const char *)polyfill_js
, polyfill_js_len, 1 | ((1U << 3)) | (1U << 7) | (
1U << 9)))
703 (const char *)polyfill_js, polyfill_js_len)(duk_compile_raw(((thread->ctx)), (const char *)polyfill_js
, polyfill_js_len, 1 | ((1U << 3)) | (1U << 7) | (
1U << 9)))
!= 0) {
704 NSLOG(dukky, CRITICAL, "%s", duk_safe_to_string(CTX, -1))do { if (NSLOG_LEVEL_CRITICAL >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_CRITICAL, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 704, }; nslog__log(&_nslog_ctx
, "%s", duk_safe_to_lstring(((thread->ctx)), (-1), ((void*
)0))); } } while(0)
;
705 NSLOG(dukky, CRITICAL, "Unable to compile polyfill.js, thread aborted")do { if (NSLOG_LEVEL_CRITICAL >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_CRITICAL, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 705, }; nslog__log(&_nslog_ctx
, "Unable to compile polyfill.js, thread aborted"); } } while
(0)
;
706 js_destroythread(ret);
707 return NSERROR_INIT_FAILED;
708 }
709 /* ..., (generics.js) */
710 if (dukky_pcall(CTX(thread->ctx), 0, true1) != 0) {
711 NSLOG(dukky, CRITICAL, "Unable to run polyfill.js, thread aborted")do { if (NSLOG_LEVEL_CRITICAL >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_CRITICAL, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 711, }; nslog__log(&_nslog_ctx
, "Unable to run polyfill.js, thread aborted"); } } while(0)
;
712 js_destroythread(ret);
713 return NSERROR_INIT_FAILED;
714 }
715 /* ..., result */
716 duk_pop(CTX(thread->ctx));
717 /* ... */
718
719 /* Now load the NetSurf table in */
720 /* ... */
721 duk_push_string(CTX(thread->ctx), "generics.js");
722 /* ..., generics.js */
723 if (duk_pcompile_lstring_filename(CTX, DUK_COMPILE_EVAL,(duk_compile_raw(((thread->ctx)), (const char *)generics_js
, generics_js_len, 1 | ((1U << 3)) | (1U << 7) | (
1U << 9)))
724 (const char *)generics_js, generics_js_len)(duk_compile_raw(((thread->ctx)), (const char *)generics_js
, generics_js_len, 1 | ((1U << 3)) | (1U << 7) | (
1U << 9)))
!= 0) {
725 NSLOG(dukky, CRITICAL, "%s", duk_safe_to_string(CTX, -1))do { if (NSLOG_LEVEL_CRITICAL >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_CRITICAL, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 725, }; nslog__log(&_nslog_ctx
, "%s", duk_safe_to_lstring(((thread->ctx)), (-1), ((void*
)0))); } } while(0)
;
726 NSLOG(dukky, CRITICAL, "Unable to compile generics.js, thread aborted")do { if (NSLOG_LEVEL_CRITICAL >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_CRITICAL, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 726, }; nslog__log(&_nslog_ctx
, "Unable to compile generics.js, thread aborted"); } } while
(0)
;
727 js_destroythread(ret);
728 return NSERROR_INIT_FAILED;
729 }
730 /* ..., (generics.js) */
731 if (dukky_pcall(CTX(thread->ctx), 0, true1) != 0) {
732 NSLOG(dukky, CRITICAL, "Unable to run generics.js, thread aborted")do { if (NSLOG_LEVEL_CRITICAL >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_CRITICAL, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 732, }; nslog__log(&_nslog_ctx
, "Unable to run generics.js, thread aborted"); } } while(0)
;
733 js_destroythread(ret);
734 return NSERROR_INIT_FAILED;
735 }
736 /* ..., result */
737 duk_pop(CTX(thread->ctx));
738 /* ... */
739 duk_push_global_object(CTX(thread->ctx));
740 /* ..., Win */
741 duk_get_prop_string(CTX(thread->ctx), -1, "NetSurf");
742 /* ..., Win, NetSurf */
743 duk_put_global_string(CTX(thread->ctx), GENERICS_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "GENERICS_TABLE"));
744 /* ..., Win */
745 duk_del_prop_string(CTX(thread->ctx), -1, "NetSurf");
746 duk_pop(CTX(thread->ctx));
747 /* ... */
748
749 dukky_log_stack_frame(CTX(thread->ctx), "New thread created");
750 NSLOG(dukky, DEBUG, "New thread is %p in heap %p", thread, heap)do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 750, }; nslog__log(&_nslog_ctx
, "New thread is %p in heap %p", thread, heap); } } while(0)
;
751 *thread = ret;
752
753 return NSERROR_OK;
754}
755
756/* Now switch to the long term CTX behaviour */
757#undef CTX(thread->ctx)
758#define CTX(thread->ctx) (thread->ctx)
759
760/* exported interface documented in js.h */
761nserror js_closethread(jsthread *thread)
762{
763 /* We can always close down a thread, it might just confuse
764 * the code running, though we don't mind since we're in the
765 * process of destruction at this point
766 */
767 duk_int_t top = duk_get_top(CTX(thread->ctx));
768
769 /* Closing down the extant thread */
770 NSLOG(dukky, DEBUG, "Closing down extant thread %p in heap %p", thread, thread->heap)do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 770, }; nslog__log(&_nslog_ctx
, "Closing down extant thread %p in heap %p", thread, thread->
heap); } } while(0)
;
771 duk_get_global_string(CTX(thread->ctx), MAGIC(closedownThread)("\xFF\xFFNETSURF_DUKTAPE_" "closedownThread"));
772 dukky_pcall(CTX(thread->ctx), 0, true1);
773
774 /* Restore whatever stack we had */
775 duk_set_top(CTX(thread->ctx), top);
776
777 return NSERROR_OK;
778}
779
780/**
781 * Destroy a Duktape thread
782 */
783static void dukky_destroythread(jsthread *thread)
784{
785 jsheap *heap = thread->heap;
786
787 assert(thread->in_use == 0)((thread->in_use == 0) ? (void) (0) : __assert_fail ("thread->in_use == 0"
, "content/handlers/javascript/duktape/dukky.c", 787, __extension__
__PRETTY_FUNCTION__))
;
28
'?' condition is true
788 assert(thread->pending_destroy == true)((thread->pending_destroy == 1) ? (void) (0) : __assert_fail
("thread->pending_destroy == true", "content/handlers/javascript/duktape/dukky.c"
, 788, __extension__ __PRETTY_FUNCTION__))
;
29
'?' condition is true
789
790 /* Closing down the extant thread */
791 NSLOG(dukky, DEBUG, "Closing down extant thread %p in heap %p", thread, heap)do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 791, }; nslog__log(&_nslog_ctx
, "Closing down extant thread %p in heap %p", thread, heap); }
} while(0)
;
30
Taking false branch
31
Loop condition is false. Exiting loop
792 duk_get_global_string(CTX(thread->ctx), MAGIC(closedownThread)("\xFF\xFFNETSURF_DUKTAPE_" "closedownThread"));
793 dukky_pcall(CTX(thread->ctx), 0, true1);
794
795 /* Now delete the thread from the heap */
796 duk_get_global_string(heap->ctx, THREAD_MAP("\xFF\xFFNETSURF_DUKTAPE_" "THREAD_MAP")); /* ... threads */
797 duk_del_prop_index(heap->ctx, -1, thread->thread_idx);
798 duk_pop(heap->ctx); /* ... */
799
800 /* We can now free the thread object */
801 free(thread);
32
Memory is released
802
803 /* Finally give the heap a chance to clean up */
804 duk_gc(heap->ctx, 0);
805 duk_gc(heap->ctx, DUK_GC_COMPACT(1U << 0));
806 heap->live_threads--;
807
808 /* And if the heap should now go, blow it away */
809 if (heap->pending_destroy == true1 && heap->live_threads == 0) {
33
Assuming field 'pending_destroy' is not equal to true
810 dukky_destroyheap(heap);
811 }
812}
813
814/* exported interface documented in js.h */
815void js_destroythread(jsthread *thread)
816{
817 thread->pending_destroy = true1;
818 if (thread->in_use == 0) {
819 dukky_destroythread(thread);
820 }
821}
822
823static void dukky_enter_thread(jsthread *thread)
824{
825 assert(thread != NULL)((thread != ((void*)0)) ? (void) (0) : __assert_fail ("thread != NULL"
, "content/handlers/javascript/duktape/dukky.c", 825, __extension__
__PRETTY_FUNCTION__))
;
11
Assuming 'thread' is not equal to null
12
'?' condition is true
826 thread->in_use++;
827}
828
829static void dukky_leave_thread(jsthread *thread)
830{
831 assert(thread != NULL)((thread != ((void*)0)) ? (void) (0) : __assert_fail ("thread != NULL"
, "content/handlers/javascript/duktape/dukky.c", 831, __extension__
__PRETTY_FUNCTION__))
;
21
'?' condition is true
832 assert(thread->in_use > 0)((thread->in_use > 0) ? (void) (0) : __assert_fail ("thread->in_use > 0"
, "content/handlers/javascript/duktape/dukky.c", 832, __extension__
__PRETTY_FUNCTION__))
;
22
Assuming field 'in_use' is > 0
23
'?' condition is true
833
834 thread->in_use--;
835 if (thread->in_use == 0 && thread->pending_destroy == true1) {
24
Assuming field 'in_use' is equal to 0
25
Assuming field 'pending_destroy' is equal to true
26
Taking true branch
836 dukky_destroythread(thread);
27
Calling 'dukky_destroythread'
34
Returning; memory was released via 1st parameter
837 }
838}
839
840duk_bool_t dukky_check_timeout(void *udata)
841{
842#define JS_EXEC_TIMEOUT_MS10000 10000 /* 10 seconds */
843 jsheap *heap = (jsheap *) udata;
844 uint64_t now;
845
846 (void) nsu_getmonotonic_ms(&now);
847
848 /* This function may be called during duk heap construction,
849 * so only test for execution timeout if we've recorded a
850 * start time.
851 */
852 return heap->exec_start_time != 0 &&
853 now > (heap->exec_start_time + JS_EXEC_TIMEOUT_MS10000);
854}
855
856static void dukky_dump_error(duk_context *ctx)
857{
858 /* stack is ..., errobj */
859 duk_dup_top(ctx);
860 /* ..., errobj, errobj */
861 NSLOG(jserrors, WARNING, "Uncaught error in JS: %s", duk_safe_to_stacktrace(ctx, -1))do { if (NSLOG_LEVEL_WARNING >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_jserrors
, NSLOG_LEVEL_WARNING, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 861, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s", duk_safe_to_stacktrace(ctx, -1)
); } } while(0)
;
862 /* ..., errobj, errobj.stackstring */
863 duk_pop(ctx);
864 /* ..., errobj */
865}
866
867static void dukky_reset_start_time(duk_context *ctx)
868{
869 duk_memory_functions funcs;
870 jsheap *heap;
871 duk_get_memory_functions(ctx, &funcs);
872 heap = funcs.udata;
873 (void) nsu_getmonotonic_ms(&heap->exec_start_time);
874}
875
876duk_int_t dukky_pcall(duk_context *ctx, duk_size_t argc, bool_Bool reset_timeout)
877{
878 if (reset_timeout) {
879 dukky_reset_start_time(ctx);
880 }
881
882 duk_int_t ret = duk_pcall(ctx, argc);
883 if (ret) {
884 /* Something went wrong calling this... */
885 dukky_dump_error(ctx);
886 }
887
888 return ret;
889}
890
891
892void dukky_push_generics(duk_context *ctx, const char *generic)
893{
894 /* ... */
895 duk_get_global_string(ctx, GENERICS_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "GENERICS_TABLE"));
896 /* ..., generics */
897 duk_get_prop_string(ctx, -1, generic);
898 /* ..., generics, generic */
899 duk_remove(ctx, -2);
900 /* ..., generic */
901}
902
903static duk_int_t dukky_push_context_dump(duk_context *ctx, void *udata)
904{
905 duk_push_context_dump(ctx);
906 return 1;
907}
908
909void dukky_log_stack_frame(duk_context *ctx, const char * reason)
910{
911 if (duk_safe_call(ctx, dukky_push_context_dump, NULL((void*)0), 0, 1) != 0) {
912 duk_pop(ctx);
913 duk_push_string(ctx, "[???]");
914 }
915 NSLOG(dukky, DEEPDEBUG, "%s, stack is: %s", reason, duk_safe_to_string(ctx, -1))do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 915, }; nslog__log(&_nslog_ctx
, "%s, stack is: %s", reason, duk_safe_to_lstring((ctx), (-1)
, ((void*)0))); } } while(0)
;
916 duk_pop(ctx);
917}
918
919
920/* exported interface documented in js.h */
921bool_Bool
922js_exec(jsthread *thread, const uint8_t *txt, size_t txtlen, const char *name)
923{
924 bool_Bool ret = false0;
925 assert(thread)((thread) ? (void) (0) : __assert_fail ("thread", "content/handlers/javascript/duktape/dukky.c"
, 925, __extension__ __PRETTY_FUNCTION__))
;
926
927 if (txt == NULL((void*)0) || txtlen == 0) {
928 return false0;
929 }
930
931 if (thread->pending_destroy) {
932 NSLOG(dukky, DEEPDEBUG, "Skipping exec call because thread is dead")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 932, }; nslog__log(&_nslog_ctx
, "Skipping exec call because thread is dead"); } } while(0)
;
933 return false0;
934 }
935
936 dukky_enter_thread(thread);
937
938 duk_set_top(CTX(thread->ctx), 0);
939 NSLOG(dukky, DEEPDEBUG, "Running %"PRIsizet" bytes from %s", txtlen, name)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 939, }; nslog__log(&_nslog_ctx
, "Running %""zu"" bytes from %s", txtlen, name); } } while(0
)
;
940 /* NSLOG(dukky, DEEPDEBUG, "\n%s\n", txt); */
941
942 dukky_reset_start_time(CTX(thread->ctx));
943 if (name != NULL((void*)0)) {
944 duk_push_string(CTX(thread->ctx), name);
945 } else {
946 duk_push_string(CTX(thread->ctx), "?unknown source?");
947 }
948 if (duk_pcompile_lstring_filename(CTX,(duk_compile_raw(((thread->ctx)), (const char *)txt, txtlen
, 1 | ((1U << 3)) | (1U << 7) | (1U << 9)))
949 DUK_COMPILE_EVAL,(duk_compile_raw(((thread->ctx)), (const char *)txt, txtlen
, 1 | ((1U << 3)) | (1U << 7) | (1U << 9)))
950 (const char *)txt,(duk_compile_raw(((thread->ctx)), (const char *)txt, txtlen
, 1 | ((1U << 3)) | (1U << 7) | (1U << 9)))
951 txtlen)(duk_compile_raw(((thread->ctx)), (const char *)txt, txtlen
, 1 | ((1U << 3)) | (1U << 7) | (1U << 9)))
!= 0) {
952 NSLOG(dukky, DEBUG, "Failed to compile JavaScript input")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 952, }; nslog__log(&_nslog_ctx
, "Failed to compile JavaScript input"); } } while(0)
;
953 goto handle_error;
954 }
955
956 if (duk_pcall(CTX(thread->ctx), 0/*nargs*/) == DUK_EXEC_ERROR1) {
957 NSLOG(dukky, DEBUG, "Failed to execute JavaScript")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 957, }; nslog__log(&_nslog_ctx
, "Failed to execute JavaScript"); } } while(0)
;
958 goto handle_error;
959 }
960
961 if (duk_get_top(CTX(thread->ctx)) == 0) duk_push_boolean(CTX(thread->ctx), false0);
962 NSLOG(dukky, DEEPDEBUG, "Returning %s",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 963, }; nslog__log(&_nslog_ctx
, "Returning %s", duk_get_boolean((thread->ctx), 0) ? "true"
: "false"); } } while(0)
963 duk_get_boolean(CTX, 0) ? "true" : "false")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 963, }; nslog__log(&_nslog_ctx
, "Returning %s", duk_get_boolean((thread->ctx), 0) ? "true"
: "false"); } } while(0)
;
964 ret = duk_get_boolean(CTX(thread->ctx), 0);
965 goto out;
966
967handle_error:
968 dukky_dump_error(CTX(thread->ctx));
969out:
970 dukky_leave_thread(thread);
971 return ret;
972}
973
974static const char* dukky_event_proto(dom_event *evt)
975{
976 const char *ret = PROTO_NAME(EVENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "EVENT");
977 dom_string *type = NULL((void*)0);
978 dom_exception err;
979
980 err = dom_event_get_type(evt, &type)_dom_event_get_type((dom_event *) (evt), (dom_string **) (&
type))
;
981 if (err != DOM_NO_ERR) {
982 goto out;
983 }
984
985 if (dom_string_isequal(type, corestring_dom_keydown)) {
986 ret = PROTO_NAME(KEYBOARDEVENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "KEYBOARDEVENT");
987 goto out;
988 } else if (dom_string_isequal(type, corestring_dom_keyup)) {
989 ret = PROTO_NAME(KEYBOARDEVENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "KEYBOARDEVENT");
990 goto out;
991 } else if (dom_string_isequal(type, corestring_dom_keypress)) {
992 ret = PROTO_NAME(KEYBOARDEVENT)("\xFF\xFFNETSURF_DUKTAPE_" "PROTOTYPE_" "KEYBOARDEVENT");
993 goto out;
994 }
995
996out:
997 if (type != NULL((void*)0)) {
998 dom_string_unref(type);
999 }
1000
1001 return ret;
1002}
1003
1004/*** New style event handling ***/
1005
1006void dukky_push_event(duk_context *ctx, dom_event *evt)
1007{
1008 /* ... */
1009 duk_get_global_string(ctx, EVENT_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_MAP"));
1010 /* ... events */
1011 duk_push_pointer(ctx, evt);
1012 /* ... events eventptr */
1013 duk_get_prop(ctx, -2);
1014 /* ... events event? */
1015 if (duk_is_undefined(ctx, -1)) {
1016 /* ... events undefined */
1017 duk_pop(ctx);
1018 /* ... events */
1019 duk_push_pointer(ctx, evt);
1020 if (dukky_create_object(ctx, dukky_event_proto(evt), 1) != DUK_EXEC_SUCCESS0) {
1021 /* ... events err */
1022 duk_pop(ctx);
1023 /* ... events */
1024 duk_push_object(ctx);
1025 /* ... events eobj[meh] */
1026 }
1027 /* ... events eobj */
1028 duk_push_pointer(ctx, evt);
1029 /* ... events eobj eventptr */
1030 duk_dup(ctx, -2);
1031 /* ... events eobj eventptr eobj */
1032 duk_put_prop(ctx, -4);
1033 /* ... events eobj */
1034 }
1035 /* ... events event */
1036 duk_replace(ctx, -2);
1037 /* ... event */
1038}
1039
1040static void dukky_push_handler_code_(duk_context *ctx, dom_string *name,
1041 dom_event_target *et)
1042{
1043 dom_string *onname, *val;
1044 dom_element *ele = (dom_element *)et;
1045 dom_exception exc;
1046 dom_node_type ntype;
1047
1048 /* If et is NULL, then we're actually dealing with the Window object
1049 * which has no default handlers and no way to assign handlers
1050 * which aren't directly stored in the HANDLER_MAGIC
1051 */
1052 if (et == NULL((void*)0)) {
1053 duk_push_lstring(ctx, "", 0);
1054 return;
1055 }
1056
1057 /* The rest of this assumes et is a proper event target and expands
1058 * out from there based on the assumption that all valid event targets
1059 * are nodes.
1060 */
1061 exc = dom_node_get_node_type(et, &ntype)dom_node_get_node_type( (dom_node *) (et), (dom_node_type *) (
&ntype))
;
1062 if (exc != DOM_NO_ERR) {
1063 duk_push_lstring(ctx, "", 0);
1064 return;
1065 }
1066
1067 if (ntype != DOM_ELEMENT_NODE) {
1068 duk_push_lstring(ctx, "", 0);
1069 return;
1070 }
1071
1072 exc = dom_string_concat(corestring_dom_on, name, &onname);
1073 if (exc != DOM_NO_ERR) {
1074 duk_push_lstring(ctx, "", 0);
1075 return;
1076 }
1077
1078 exc = dom_element_get_attribute(ele, onname, &val)dom_element_get_attribute( (dom_element *) (ele), (onname), (
&val))
;
1079 if ((exc != DOM_NO_ERR) || (val == NULL((void*)0))) {
1080 dom_string_unref(onname);
1081 duk_push_lstring(ctx, "", 0);
1082 return;
1083 }
1084
1085 dom_string_unref(onname);
1086 duk_push_lstring(ctx, dom_string_data(val), dom_string_length(val));
1087 dom_string_unref(val);
1088}
1089
1090bool_Bool dukky_get_current_value_of_event_handler(duk_context *ctx,
1091 dom_string *name,
1092 dom_event_target *et)
1093{
1094 /* Must be entered as:
1095 * ... node(et)
1096 */
1097 duk_get_prop_string(ctx, -1, HANDLER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_MAP"));
1098 /* ... node handlers */
1099 duk_push_lstring(ctx, dom_string_data(name), dom_string_length(name));
1100 /* ... node handlers name */
1101 duk_get_prop(ctx, -2);
1102 /* ... node handlers handler? */
1103 if (duk_is_undefined(ctx, -1)) {
1104 /* ... node handlers undefined */
1105 duk_pop_2(ctx);
1106 /* ... node */
1107 dukky_push_handler_code_(ctx, name, et);
1108 /* ... node handlercode? */
1109 /* TODO: If this is null, clean up and propagate */
1110 /* ... node handlercode */
1111 /** @todo This is entirely wrong, but it's hard to get right */
1112 duk_push_string(ctx, "function (event) {");
1113 /* ... node handlercode prefix */
1114 duk_insert(ctx, -2);
1115 /* ... node prefix handlercode */
1116 duk_push_string(ctx, "}");
1117 /* ... node prefix handlercode suffix */
1118 duk_concat(ctx, 3);
1119 /* ... node fullhandlersrc */
1120 duk_push_string(ctx, "internal raw uncompiled handler");
1121 /* ... node fullhandlersrc filename */
1122 if (duk_pcompile(ctx, DUK_COMPILE_FUNCTION)(duk_compile_raw((ctx), ((void*)0), 0, 2 | ((1U << 4)) |
(1U << 7)))
!= 0) {
1123 /* ... node err */
1124 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1125, }; nslog__log(&_nslog_ctx
, "Unable to proceed with handler, could not compile"); } } while
(0)
1125 "Unable to proceed with handler, could not compile")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1125, }; nslog__log(&_nslog_ctx
, "Unable to proceed with handler, could not compile"); } } while
(0)
;
1126 duk_pop_2(ctx);
1127 return false0;
1128 }
1129 /* ... node handler */
1130 duk_insert(ctx, -2);
1131 /* ... handler node */
1132 } else {
1133 /* ... node handlers handler */
1134 duk_insert(ctx, -3);
1135 /* ... handler node handlers */
1136 duk_pop(ctx);
1137 /* ... handler node */
1138 }
1139 /* ... handler node */
1140 return true1;
1141}
1142
1143static void dukky_generic_event_handler(dom_event *evt, void *pw)
1144{
1145 duk_context *ctx = (duk_context *)pw;
1146 dom_string *name;
1147 dom_exception exc;
1148 dom_event_target *targ;
1149 dom_event_flow_phase phase;
1150 duk_uarridx_t idx;
1151 event_listener_flags flags;
1152
1153 NSLOG(dukky, DEBUG, "Handling an event in duktape interface...")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1153, }; nslog__log(&_nslog_ctx
, "Handling an event in duktape interface..."); } } while(0)
;
1154 exc = dom_event_get_type(evt, &name)_dom_event_get_type((dom_event *) (evt), (dom_string **) (&
name))
;
1155 if (exc != DOM_NO_ERR) {
1156 NSLOG(dukky, DEBUG, "Unable to find the event name")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1156, }; nslog__log(&_nslog_ctx
, "Unable to find the event name"); } } while(0)
;
1157 return;
1158 }
1159 NSLOG(dukky, DEBUG, "Event's name is %*s", (int)dom_string_length(name),do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1160, }; nslog__log(&_nslog_ctx
, "Event's name is %*s", (int)dom_string_length(name), dom_string_data
(name)); } } while(0)
1160 dom_string_data(name))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1160, }; nslog__log(&_nslog_ctx
, "Event's name is %*s", (int)dom_string_length(name), dom_string_data
(name)); } } while(0)
;
1161 exc = dom_event_get_event_phase(evt, &phase)_dom_event_get_event_phase( (dom_event *) (evt), (dom_event_flow_phase
*) (&phase))
;
1162 if (exc != DOM_NO_ERR) {
1163 NSLOG(dukky, WARNING, "Unable to get event phase")do { if (NSLOG_LEVEL_WARNING >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_WARNING, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1163, }; nslog__log(&_nslog_ctx
, "Unable to get event phase"); } } while(0)
;
1164 return;
1165 }
1166 NSLOG(dukky, DEBUG, "Event phase is: %s (%d)",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1168, }; nslog__log(&_nslog_ctx
, "Event phase is: %s (%d)", phase == DOM_CAPTURING_PHASE ? "capturing"
: phase == DOM_AT_TARGET ? "at-target" : phase == DOM_BUBBLING_PHASE
? "bubbling" : "unknown", (int)phase); } } while(0)
1167 phase == DOM_CAPTURING_PHASE ? "capturing" : phase == DOM_AT_TARGET ? "at-target" : phase == DOM_BUBBLING_PHASE ? "bubbling" : "unknown",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1168, }; nslog__log(&_nslog_ctx
, "Event phase is: %s (%d)", phase == DOM_CAPTURING_PHASE ? "capturing"
: phase == DOM_AT_TARGET ? "at-target" : phase == DOM_BUBBLING_PHASE
? "bubbling" : "unknown", (int)phase); } } while(0)
1168 (int)phase)do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1168, }; nslog__log(&_nslog_ctx
, "Event phase is: %s (%d)", phase == DOM_CAPTURING_PHASE ? "capturing"
: phase == DOM_AT_TARGET ? "at-target" : phase == DOM_BUBBLING_PHASE
? "bubbling" : "unknown", (int)phase); } } while(0)
;
1169
1170 exc = dom_event_get_current_target(evt, &targ)_dom_event_get_current_target( (dom_event *) (evt), (dom_event_target
**) (&targ))
;
1171 if (exc != DOM_NO_ERR) {
1172 dom_string_unref(name);
1173 NSLOG(dukky, DEBUG, "Unable to find the event target")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1173, }; nslog__log(&_nslog_ctx
, "Unable to find the event target"); } } while(0)
;
1174 return;
1175 }
1176
1177 /* If we're capturing right now, we skip the 'event handler'
1178 * and go straight to the extras
1179 */
1180 if (phase == DOM_CAPTURING_PHASE)
1181 goto handle_extras;
1182
1183 /* ... */
1184 if (dukky_push_node(ctx, (dom_node *)targ) == false0) {
1185 dom_string_unref(name);
1186 dom_node_unref(targ)dom_node_unref((dom_node *) (targ));
1187 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1188, }; nslog__log(&_nslog_ctx
, "Unable to push JS node representation?!"); } } while(0)
1188 "Unable to push JS node representation?!")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1188, }; nslog__log(&_nslog_ctx
, "Unable to push JS node representation?!"); } } while(0)
;
1189 return;
1190 }
1191 /* ... node */
1192 if (dukky_get_current_value_of_event_handler(
1193 ctx, name, (dom_event_target *)targ) == false0) {
1194 /* ... */
1195 goto handle_extras;
1196 }
1197 /* ... handler node */
1198 dukky_push_event(ctx, evt);
1199 /* ... handler node event */
1200 dukky_reset_start_time(ctx);
1201 if (duk_pcall_method(ctx, 1) != 0) {
1202 /* Failed to run the method */
1203 /* ... err */
1204 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1205, }; nslog__log(&_nslog_ctx
, "OH NOES! An error running a callback. Meh."); } } while(0
)
1205 "OH NOES! An error running a callback. Meh.")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1205, }; nslog__log(&_nslog_ctx
, "OH NOES! An error running a callback. Meh."); } } while(0
)
;
1206 exc = dom_event_stop_immediate_propagation(evt)_dom_event_stop_immediate_propagation((dom_event *) (evt));
1207 if (exc != DOM_NO_ERR)
1208 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1209, }; nslog__log(&_nslog_ctx
, "WORSE! could not stop propagation"); } } while(0)
1209 "WORSE! could not stop propagation")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1209, }; nslog__log(&_nslog_ctx
, "WORSE! could not stop propagation"); } } while(0)
;
1210 duk_get_prop_string(ctx, -1, "name");
1211 duk_get_prop_string(ctx, -2, "message");
1212 duk_get_prop_string(ctx, -3, "fileName");
1213 duk_get_prop_string(ctx, -4, "lineNumber");
1214 duk_get_prop_string(ctx, -5, "stack");
1215 /* ... err name message fileName lineNumber stack */
1216 NSLOG(dukky, DEBUG, "Uncaught error in JS: %s: %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1218, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring((ctx), (
-5), ((void*)0)), duk_safe_to_lstring((ctx), (-4), ((void*)0)
)); } } while(0)
1217 duk_safe_to_string(ctx, -5),do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1218, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring((ctx), (
-5), ((void*)0)), duk_safe_to_lstring((ctx), (-4), ((void*)0)
)); } } while(0)
1218 duk_safe_to_string(ctx, -4))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1218, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring((ctx), (
-5), ((void*)0)), duk_safe_to_lstring((ctx), (-4), ((void*)0)
)); } } while(0)
;
1219 NSLOG(dukky, INFO, " was at: %s line %s",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_INFO, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1221, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
1220 duk_safe_to_string(ctx, -3),do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_INFO, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1221, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
1221 duk_safe_to_string(ctx, -2))do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_INFO, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1221, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
;
1222 NSLOG(dukky, INFO, " Stack trace: %s",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_INFO, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1223, }; nslog__log(&_nslog_ctx
, " Stack trace: %s", duk_safe_to_lstring((ctx), (-1)
, ((void*)0))); } } while(0)
1223 duk_safe_to_string(ctx, -1))do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_INFO, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1223, }; nslog__log(&_nslog_ctx
, " Stack trace: %s", duk_safe_to_lstring((ctx), (-1)
, ((void*)0))); } } while(0)
;
1224
1225 duk_pop_n(ctx, 6);
1226 /* ... */
1227 goto handle_extras;
1228 }
1229 /* ... result */
1230 if (duk_is_boolean(ctx, -1) &&
1231 duk_to_boolean(ctx, -1) == 0) {
1232 dom_event_prevent_default(evt)_dom_event_prevent_default( (dom_event *) (evt));
1233 }
1234 duk_pop(ctx);
1235handle_extras:
1236 /* ... */
1237 duk_push_lstring(ctx, dom_string_data(name), dom_string_length(name));
1238 dukky_push_node(ctx, (dom_node *)targ);
1239 /* ... type node */
1240 if (dukky_event_target_push_listeners(ctx, true1)) {
1241 /* Nothing to do */
1242 duk_pop(ctx);
1243 goto out;
1244 }
1245 /* ... sublisteners */
1246 duk_push_array(ctx);
1247 /* ... sublisteners copy */
1248 idx = 0;
1249 while (duk_get_prop_index(ctx, -2, idx)) {
1250 /* ... sublisteners copy handler */
1251 duk_get_prop_index(ctx, -1, 1);
1252 /* ... sublisteners copy handler flags */
1253 if ((event_listener_flags)duk_to_int(ctx, -1) & ELF_ONCE) {
1254 duk_dup(ctx, -4);
1255 /* ... subl copy handler flags subl */
1256 dukky_shuffle_array(ctx, idx);
1257 duk_pop(ctx);
1258 /* ... subl copy handler flags */
1259 }
1260 duk_pop(ctx);
1261 /* ... sublisteners copy handler */
1262 duk_put_prop_index(ctx, -2, idx);
1263 /* ... sublisteners copy */
1264 idx++;
1265 }
1266 /* ... sublisteners copy undefined */
1267 duk_pop(ctx);
1268 /* ... sublisteners copy */
1269 duk_insert(ctx, -2);
1270 /* ... copy sublisteners */
1271 duk_pop(ctx);
1272 /* ... copy */
1273 idx = 0;
1274 while (duk_get_prop_index(ctx, -1, idx++)) {
1275 /* ... copy handler */
1276 if (duk_get_prop_index(ctx, -1, 2)) {
1277 /* ... copy handler meh */
1278 duk_pop_2(ctx);
1279 continue;
1280 }
1281 duk_pop(ctx);
1282 duk_get_prop_index(ctx, -1, 0);
1283 duk_get_prop_index(ctx, -2, 1);
1284 /* ... copy handler callback flags */
1285 flags = (event_listener_flags)duk_get_int(ctx, -1);
1286 duk_pop(ctx);
1287 /* ... copy handler callback */
1288 if (((phase == DOM_CAPTURING_PHASE) && !(flags & ELF_CAPTURE)) ||
1289 ((phase != DOM_CAPTURING_PHASE) && (flags & ELF_CAPTURE))) {
1290 duk_pop_2(ctx);
1291 /* ... copy */
1292 continue;
1293 }
1294 /* ... copy handler callback */
1295 dukky_push_node(ctx, (dom_node *)targ);
1296 /* ... copy handler callback node */
1297 dukky_push_event(ctx, evt);
1298 /* ... copy handler callback node event */
1299 dukky_reset_start_time(ctx);
1300 if (duk_pcall_method(ctx, 1) != 0) {
1301 /* Failed to run the method */
1302 /* ... copy handler err */
1303 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1304, }; nslog__log(&_nslog_ctx
, "OH NOES! An error running a callback. Meh."); } } while(0
)
1304 "OH NOES! An error running a callback. Meh.")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1304, }; nslog__log(&_nslog_ctx
, "OH NOES! An error running a callback. Meh."); } } while(0
)
;
1305 exc = dom_event_stop_immediate_propagation(evt)_dom_event_stop_immediate_propagation((dom_event *) (evt));
1306 if (exc != DOM_NO_ERR)
1307 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1308, }; nslog__log(&_nslog_ctx
, "WORSE! could not stop propagation"); } } while(0)
1308 "WORSE! could not stop propagation")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1308, }; nslog__log(&_nslog_ctx
, "WORSE! could not stop propagation"); } } while(0)
;
1309 duk_get_prop_string(ctx, -1, "name");
1310 duk_get_prop_string(ctx, -2, "message");
1311 duk_get_prop_string(ctx, -3, "fileName");
1312 duk_get_prop_string(ctx, -4, "lineNumber");
1313 duk_get_prop_string(ctx, -5, "stack");
1314 /* ... err name message fileName lineNumber stack */
1315 NSLOG(dukky, DEBUG, "Uncaught error in JS: %s: %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1317, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring((ctx), (
-5), ((void*)0)), duk_safe_to_lstring((ctx), (-4), ((void*)0)
)); } } while(0)
1316 duk_safe_to_string(ctx, -5),do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1317, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring((ctx), (
-5), ((void*)0)), duk_safe_to_lstring((ctx), (-4), ((void*)0)
)); } } while(0)
1317 duk_safe_to_string(ctx, -4))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1317, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring((ctx), (
-5), ((void*)0)), duk_safe_to_lstring((ctx), (-4), ((void*)0)
)); } } while(0)
;
1318 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1321, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
1319 " was at: %s line %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1321, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
1320 duk_safe_to_string(ctx, -3),do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1321, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
1321 duk_safe_to_string(ctx, -2))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1321, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring((ctx
), (-3), ((void*)0)), duk_safe_to_lstring((ctx), (-2), ((void
*)0))); } } while(0)
;
1322 NSLOG(dukky, DEBUG, " Stack trace: %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1323, }; nslog__log(&_nslog_ctx
, " Stack trace: %s", duk_safe_to_lstring((ctx), (-1)
, ((void*)0))); } } while(0)
1323 duk_safe_to_string(ctx, -1))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1323, }; nslog__log(&_nslog_ctx
, " Stack trace: %s", duk_safe_to_lstring((ctx), (-1)
, ((void*)0))); } } while(0)
;
1324
1325 duk_pop_n(ctx, 7);
1326 /* ... copy */
1327 continue;
1328 }
1329 /* ... copy handler result */
1330 if (duk_is_boolean(ctx, -1) &&
1331 duk_to_boolean(ctx, -1) == 0) {
1332 dom_event_prevent_default(evt)_dom_event_prevent_default( (dom_event *) (evt));
1333 }
1334 duk_pop_2(ctx);
1335 /* ... copy */
1336 }
1337 duk_pop_2(ctx);
1338out:
1339 /* ... */
1340 dom_node_unref(targ)dom_node_unref((dom_node *) (targ));
1341 dom_string_unref(name);
1342}
1343
1344void dukky_register_event_listener_for(duk_context *ctx,
1345 struct dom_element *ele,
1346 dom_string *name,
1347 bool_Bool capture)
1348{
1349 dom_event_listener *listen = NULL((void*)0);
1350 dom_exception exc;
1351
1352 /* ... */
1353 if (ele == NULL((void*)0)) {
1354 /* A null element is the Window object */
1355 duk_push_global_object(ctx);
1356 } else {
1357 /* Non null elements must be pushed as a node object */
1358 if (dukky_push_node(ctx, (struct dom_node *)ele) == false0)
1359 return;
1360 }
1361 /* ... node */
1362 duk_get_prop_string(ctx, -1, HANDLER_LISTENER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_LISTENER_MAP"));
1363 /* ... node handlers */
1364 duk_push_lstring(ctx, dom_string_data(name), dom_string_length(name));
1365 /* ... node handlers name */
1366 if (duk_has_prop(ctx, -2)) {
1367 /* ... node handlers */
1368 duk_pop_2(ctx);
1369 /* ... */
1370 return;
1371 }
1372 /* ... node handlers */
1373 duk_push_lstring(ctx, dom_string_data(name), dom_string_length(name));
1374 /* ... node handlers name */
1375 duk_push_boolean(ctx, true1);
1376 /* ... node handlers name true */
1377 duk_put_prop(ctx, -3);
1378 /* ... node handlers */
1379 duk_pop_2(ctx);
1380 /* ... */
1381 if (ele == NULL((void*)0)) {
1382 /* Nothing more to do, Window doesn't register in the
1383 * normal event listener flow
1384 */
1385 return;
1386 }
1387
1388 /* Otherwise add an event listener to the element */
1389 exc = dom_event_listener_create(dukky_generic_event_handler, ctx,
1390 &listen);
1391 if (exc != DOM_NO_ERR) return;
1392 exc = dom_event_target_add_event_listener(dom_event_target_add_event_listener((dom_event_target *) (ele
), (dom_string *) (name), (struct dom_event_listener *) (listen
), (_Bool) (capture))
1393 ele, name, listen, capture)dom_event_target_add_event_listener((dom_event_target *) (ele
), (dom_string *) (name), (struct dom_event_listener *) (listen
), (_Bool) (capture))
;
1394 if (exc != DOM_NO_ERR) {
1395 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1397, }; nslog__log(&_nslog_ctx
, "Unable to register listener for %p.%*s", ele, (int)dom_string_length
(name), dom_string_data(name)); } } while(0)
1396 "Unable to register listener for %p.%*s", ele,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1397, }; nslog__log(&_nslog_ctx
, "Unable to register listener for %p.%*s", ele, (int)dom_string_length
(name), dom_string_data(name)); } } while(0)
1397 (int)dom_string_length(name), dom_string_data(name))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1397, }; nslog__log(&_nslog_ctx
, "Unable to register listener for %p.%*s", ele, (int)dom_string_length
(name), dom_string_data(name)); } } while(0)
;
1398 } else {
1399 NSLOG(dukky, DEBUG, "have registered listener for %p.%*s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1400, }; nslog__log(&_nslog_ctx
, "have registered listener for %p.%*s", ele, (int)dom_string_length
(name), dom_string_data(name)); } } while(0)
1400 ele, (int)dom_string_length(name), dom_string_data(name))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1400, }; nslog__log(&_nslog_ctx
, "have registered listener for %p.%*s", ele, (int)dom_string_length
(name), dom_string_data(name)); } } while(0)
;
1401 }
1402 dom_event_listener_unref(listen);
1403}
1404
1405/* The sub-listeners are a list of {callback,flags} tuples */
1406/* We return true if we created a new sublistener table */
1407/* If we're told to not create, but we want to, we still return true */
1408bool_Bool dukky_event_target_push_listeners(duk_context *ctx, bool_Bool dont_create)
1409{
1410 bool_Bool ret = false0;
1411 /* ... type this */
1412 duk_get_prop_string(ctx, -1, EVENT_LISTENER_JS_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_LISTENER_JS_MAP"));
1413 if (duk_is_undefined(ctx, -1)) {
1414 /* ... type this null */
1415 duk_pop(ctx);
1416 duk_push_object(ctx);
1417 duk_dup(ctx, -1);
1418 /* ... type this listeners listeners */
1419 duk_put_prop_string(ctx, -3, EVENT_LISTENER_JS_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_LISTENER_JS_MAP"));
1420 /* ... type this listeners */
1421 }
1422 /* ... type this listeners */
1423 duk_insert(ctx, -3);
1424 /* ... listeners type this */
1425 duk_pop(ctx);
1426 /* ... listeners type */
1427 duk_dup(ctx, -1);
1428 /* ... listeners type type */
1429 duk_get_prop(ctx, -3);
1430 /* ... listeners type ??? */
1431 if (duk_is_undefined(ctx, -1)) {
1432 /* ... listeners type ??? */
1433 if (dont_create == true1) {
1434 duk_pop_3(ctx);
1435 duk_push_undefined(ctx);
1436 return true1;
1437 }
1438 duk_pop(ctx);
1439 duk_push_array(ctx);
1440 duk_dup(ctx, -2);
1441 duk_dup(ctx, -2);
1442 /* ... listeners type sublisteners type sublisteners */
1443 duk_put_prop(ctx, -5);
1444 /* ... listeners type sublisteners */
1445 ret = true1;
1446 }
1447 duk_insert(ctx, -3);
1448 /* ... sublisteners listeners type */
1449 duk_pop_2(ctx);
1450 /* ... sublisteners */
1451 return ret;
1452}
1453
1454/* Shuffle a duktape array "down" one. This involves iterating from
1455 * the index provided, shuffling elements down, until we reach an
1456 * undefined
1457 */
1458void dukky_shuffle_array(duk_context *ctx, duk_uarridx_t idx)
1459{
1460 /* ... somearr */
1461 while (duk_get_prop_index(ctx, -1, idx + 1)) {
1462 duk_put_prop_index(ctx, -2, idx);
1463 idx++;
1464 }
1465 /* ... somearr undefined */
1466 duk_del_prop_index(ctx, -2, idx + 1);
1467 duk_pop(ctx);
1468}
1469
1470
1471void js_handle_new_element(jsthread *thread, struct dom_element *node)
1472{
1473 assert(thread)((thread) ? (void) (0) : __assert_fail ("thread", "content/handlers/javascript/duktape/dukky.c"
, 1473, __extension__ __PRETTY_FUNCTION__))
;
1474 assert(node)((node) ? (void) (0) : __assert_fail ("node", "content/handlers/javascript/duktape/dukky.c"
, 1474, __extension__ __PRETTY_FUNCTION__))
;
1475 dom_namednodemap *map;
1476 dom_exception exc;
1477 dom_ulong idx;
1478 dom_ulong siz;
1479 dom_attr *attr = NULL((void*)0);
1480 dom_string *key = NULL((void*)0);
1481 dom_string *nodename;
1482 duk_bool_t is_body = false0;
1483
1484 exc = dom_node_get_node_name(node, &nodename)dom_node_get_node_name((dom_node *) (node), (&nodename));
1485 if (exc != DOM_NO_ERR) return;
1486
1487 if (nodename == corestring_dom_BODY)
1488 is_body = true1;
1489
1490 dom_string_unref(nodename);
1491
1492 exc = dom_node_get_attributes(node, &map)dom_node_get_attributes( (dom_node *) (node), (struct dom_namednodemap
**) (&map))
;
1493 if (exc != DOM_NO_ERR) return;
1494 if (map == NULL((void*)0)) return;
1495
1496 dukky_enter_thread(thread);
1497
1498 exc = dom_namednodemap_get_length(map, &siz);
1499 if (exc != DOM_NO_ERR) goto out;
1500
1501 for (idx = 0; idx < siz; idx++) {
1502 exc = dom_namednodemap_item(map, idx, &attr)_dom_namednodemap_item( (dom_namednodemap *) (map), (uint32_t
) (idx), (dom_node **) (&attr))
;
1503 if (exc != DOM_NO_ERR) goto out;
1504 exc = dom_attr_get_name(attr, &key)dom_attr_get_name((struct dom_attr *) (attr), (&key));
1505 if (exc != DOM_NO_ERR) goto out;
1506 if (is_body && (
1507 key == corestring_dom_onblur ||
1508 key == corestring_dom_onerror ||
1509 key == corestring_dom_onfocus ||
1510 key == corestring_dom_onload ||
1511 key == corestring_dom_onresize ||
1512 key == corestring_dom_onscroll)) {
1513 /* This is a forwarded event, it doesn't matter,
1514 * we should skip registering for it and later
1515 * we will register it for Window itself
1516 */
1517 goto skip_register;
1518 }
1519 if (dom_string_length(key) > 2) {
1520 /* Can be on* */
1521 const uint8_t *data = (const uint8_t *)dom_string_data(key);
1522 if (data[0] == 'o' && data[1] == 'n') {
1523 dom_string *sub = NULL((void*)0);
1524 exc = dom_string_substr(
1525 key, 2, dom_string_length(key),
1526 &sub);
1527 if (exc == DOM_NO_ERR) {
1528 dukky_register_event_listener_for(
1529 CTX(thread->ctx), node, sub, false0);
1530 dom_string_unref(sub);
1531 }
1532 }
1533 }
1534 skip_register:
1535 dom_string_unref(key); key = NULL((void*)0);
1536 dom_node_unref(attr)dom_node_unref((dom_node *) (attr)); attr = NULL((void*)0);
1537 }
1538
1539out:
1540 if (key != NULL((void*)0))
1541 dom_string_unref(key);
1542
1543 if (attr != NULL((void*)0))
1544 dom_node_unref(attr)dom_node_unref((dom_node *) (attr));
1545
1546 dom_namednodemap_unref(map);
1547
1548 dukky_leave_thread(thread);
1549}
1550
1551void js_event_cleanup(jsthread *thread, struct dom_event *evt)
1552{
1553 assert(thread)((thread) ? (void) (0) : __assert_fail ("thread", "content/handlers/javascript/duktape/dukky.c"
, 1553, __extension__ __PRETTY_FUNCTION__))
;
19
'?' condition is true
1554 dukky_enter_thread(thread);
1555 /* ... */
1556 duk_get_global_string(CTX(thread->ctx), EVENT_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "EVENT_MAP"));
1557 /* ... EVENT_MAP */
1558 duk_push_pointer(CTX(thread->ctx), evt);
1559 /* ... EVENT_MAP eventptr */
1560 duk_del_prop(CTX(thread->ctx), -2);
1561 /* ... EVENT_MAP */
1562 duk_pop(CTX(thread->ctx));
1563 /* ... */
1564 dukky_leave_thread(thread);
20
Calling 'dukky_leave_thread'
35
Returning; memory was released via 1st parameter
1565}
1566
1567bool_Bool js_fire_event(jsthread *thread, const char *type, struct dom_document *doc, struct dom_node *target)
1568{
1569 dom_exception exc;
1570 dom_event *evt;
1571 dom_event_target *body;
1572
1573 NSLOG(dukky, DEBUG, "Event: %s (doc=%p, target=%p)", type, doc,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1574, }; nslog__log(&_nslog_ctx
, "Event: %s (doc=%p, target=%p)", type, doc, target); } } while
(0)
1
Taking false branch
2
Loop condition is false. Exiting loop
1574 target)do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1574, }; nslog__log(&_nslog_ctx
, "Event: %s (doc=%p, target=%p)", type, doc, target); } } while
(0)
;
1575
1576 /** @todo Make this more generic, this only handles load and only
1577 * targetting the window, so that we actually stand a chance of
1578 * getting 3.4 out.
1579 */
1580
1581 if (target != NULL((void*)0))
3
Assuming 'target' is equal to NULL
4
Taking false branch
1582 /* Swallow non-Window-targetted events quietly */
1583 return true1;
1584
1585 if (strcmp(type, "load") != 0)
5
Taking false branch
1586 /* Swallow non-load events quietly */
1587 return true1;
1588
1589 /* Okay, we're processing load, targetted at Window, do the single
1590 * thing which gets us there, which is to find the appropriate event
1591 * handler and call it. If we have no event handler on Window then
1592 * we divert to the body, and if there's no event handler there
1593 * we swallow the event silently
1594 */
1595
1596 exc = dom_event_create(&evt)_dom_event_create((dom_event **) (&evt));
1597 if (exc != DOM_NO_ERR) return true1;
6
Assuming 'exc' is equal to DOM_NO_ERR
7
Taking false branch
1598 exc = dom_event_init(evt, corestring_dom_load, false, false)_dom_event_init((dom_event *) (evt), (dom_string *) (corestring_dom_load
), (_Bool) (0), (_Bool) (0))
;
1599 if (exc != DOM_NO_ERR) {
8
Assuming 'exc' is equal to DOM_NO_ERR
9
Taking false branch
1600 dom_event_unref(evt)_dom_event_unref((dom_event *) (evt));
1601 return true1;
1602 }
1603 dukky_enter_thread(thread);
10
Calling 'dukky_enter_thread'
13
Returning from 'dukky_enter_thread'
1604 /* ... */
1605 duk_get_global_string(CTX(thread->ctx), HANDLER_MAGIC("\xFF\xFFNETSURF_DUKTAPE_" "HANDLER_MAP"));
1606 /* ... handlers */
1607 duk_push_lstring(CTX(thread->ctx), "load", 4);
1608 /* ... handlers "load" */
1609 duk_get_prop(CTX(thread->ctx), -2);
1610 /* ... handlers handler? */
1611 if (duk_is_undefined(CTX(thread->ctx), -1)) {
14
Assuming the condition is false
15
Taking false branch
1612 /* No handler here, *try* and retrieve a handler from
1613 * the body
1614 */
1615 duk_pop(CTX(thread->ctx));
1616 /* ... handlers */
1617 exc = dom_html_document_get_body(doc, &body)dom_html_document_get_body((dom_html_document *) (doc), (struct
dom_html_element **) (&body))
;
1618 if (exc != DOM_NO_ERR) {
1619 dom_event_unref(evt)_dom_event_unref((dom_event *) (evt));
1620 dukky_leave_thread(thread);
1621 return true1;
1622 }
1623 dukky_push_node(CTX(thread->ctx), (struct dom_node *)body);
1624 /* ... handlers bodynode */
1625 if (dukky_get_current_value_of_event_handler(
1626 CTX(thread->ctx), corestring_dom_load, body) == false0) {
1627 /* Unref the body, we don't need it any more */
1628 dom_node_unref(body)dom_node_unref((dom_node *) (body));
1629 /* ... handlers */
1630 duk_pop(CTX(thread->ctx));
1631 dukky_leave_thread(thread);
1632 return true1;
1633 }
1634 /* Unref the body, we don't need it any more */
1635 dom_node_unref(body)dom_node_unref((dom_node *) (body));
1636 /* ... handlers handler bodynode */
1637 duk_pop(CTX(thread->ctx));
1638 }
1639 /* ... handlers handler */
1640 duk_insert(CTX(thread->ctx), -2);
1641 /* ... handler handlers */
1642 duk_pop(CTX(thread->ctx));
1643 /* ... handler */
1644 duk_push_global_object(CTX(thread->ctx));
1645 /* ... handler Window */
1646 dukky_push_event(CTX(thread->ctx), evt);
1647 /* ... handler Window event */
1648 dukky_reset_start_time(CTX(thread->ctx));
1649 if (duk_pcall_method(CTX(thread->ctx), 1) != 0) {
16
Assuming the condition is false
17
Taking false branch
1650 /* Failed to run the handler */
1651 /* ... err */
1652 NSLOG(dukky, DEBUG,do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1653, }; nslog__log(&_nslog_ctx
, "OH NOES! An error running a handler. Meh."); } } while(0)
1653 "OH NOES! An error running a handler. Meh.")do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1653, }; nslog__log(&_nslog_ctx
, "OH NOES! An error running a handler. Meh."); } } while(0)
;
1654 duk_get_prop_string(CTX(thread->ctx), -1, "name");
1655 duk_get_prop_string(CTX(thread->ctx), -2, "message");
1656 duk_get_prop_string(CTX(thread->ctx), -3, "fileName");
1657 duk_get_prop_string(CTX(thread->ctx), -4, "lineNumber");
1658 duk_get_prop_string(CTX(thread->ctx), -5, "stack");
1659 /* ... err name message fileName lineNumber stack */
1660 NSLOG(dukky, DEBUG, "Uncaught error in JS: %s: %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1662, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring(((thread
->ctx)), (-5), ((void*)0)), duk_safe_to_lstring(((thread->
ctx)), (-4), ((void*)0))); } } while(0)
1661 duk_safe_to_string(CTX, -5),do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1662, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring(((thread
->ctx)), (-5), ((void*)0)), duk_safe_to_lstring(((thread->
ctx)), (-4), ((void*)0))); } } while(0)
1662 duk_safe_to_string(CTX, -4))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1662, }; nslog__log(&_nslog_ctx
, "Uncaught error in JS: %s: %s", duk_safe_to_lstring(((thread
->ctx)), (-5), ((void*)0)), duk_safe_to_lstring(((thread->
ctx)), (-4), ((void*)0))); } } while(0)
;
1663 NSLOG(dukky, DEBUG, " was at: %s line %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1665, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring(((thread
->ctx)), (-3), ((void*)0)), duk_safe_to_lstring(((thread->
ctx)), (-2), ((void*)0))); } } while(0)
1664 duk_safe_to_string(CTX, -3),do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1665, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring(((thread
->ctx)), (-3), ((void*)0)), duk_safe_to_lstring(((thread->
ctx)), (-2), ((void*)0))); } } while(0)
1665 duk_safe_to_string(CTX, -2))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1665, }; nslog__log(&_nslog_ctx
, " was at: %s line %s", duk_safe_to_lstring(((thread
->ctx)), (-3), ((void*)0)), duk_safe_to_lstring(((thread->
ctx)), (-2), ((void*)0))); } } while(0)
;
1666 NSLOG(dukky, DEBUG, " Stack trace: %s",do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1667, }; nslog__log(&_nslog_ctx
, " Stack trace: %s", duk_safe_to_lstring(((thread->
ctx)), (-1), ((void*)0))); } } while(0)
1667 duk_safe_to_string(CTX, -1))do { if (NSLOG_LEVEL_DEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_dukky
, NSLOG_LEVEL_DEBUG, "content/handlers/javascript/duktape/dukky.c"
, sizeof("content/handlers/javascript/duktape/dukky.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1667, }; nslog__log(&_nslog_ctx
, " Stack trace: %s", duk_safe_to_lstring(((thread->
ctx)), (-1), ((void*)0))); } } while(0)
;
1668
1669 duk_pop_n(CTX(thread->ctx), 6);
1670 /* ... */
1671 js_event_cleanup(thread, evt);
1672 dom_event_unref(evt)_dom_event_unref((dom_event *) (evt));
1673 dukky_leave_thread(thread);
1674 return true1;
1675 }
1676 /* ... result */
1677 duk_pop(CTX(thread->ctx));
1678 /* ... */
1679 js_event_cleanup(thread, evt);
18
Calling 'js_event_cleanup'
36
Returning; memory was released via 1st parameter
1680 dom_event_unref(evt)_dom_event_unref((dom_event *) (evt));
1681 dukky_leave_thread(thread);
37
Use of memory after it is freed
1682 return true1;
1683}