diff --git a/include/libhttp.h b/include/libhttp.h index b0004d38..9e703275 100644 --- a/include/libhttp.h +++ b/include/libhttp.h @@ -967,7 +967,6 @@ CIVETWEB_API int mg_get_response(struct mg_connection *conn, 8 support IPv6 (USE_IPV6 set) 16 support WebSocket (USE_WEBSOCKET set) 32 support Lua scripts and Lua server pages (USE_LUA is set) - 64 support server side JavaScript (USE_DUKTAPE is set) 128 support caching (NO_CACHING not set) The result is undefined for all other feature values. diff --git a/src/httplib_check_feature.c b/src/httplib_check_feature.c index b7b1a7e5..001b8fd9 100644 --- a/src/httplib_check_feature.c +++ b/src/httplib_check_feature.c @@ -59,9 +59,6 @@ unsigned mg_check_feature( unsigned feature ) { #if defined(USE_LUA) | 0x0020u #endif -#if defined(USE_DUKTAPE) - | 0x0040u -#endif #if !defined(NO_CACHING) | 0x0080u #endif diff --git a/src/libhttp-private.h b/src/libhttp-private.h index 91f4f500..d3b07c10 100644 --- a/src/libhttp-private.h +++ b/src/libhttp-private.h @@ -479,9 +479,6 @@ enum { LUA_SCRIPT_EXTENSIONS, LUA_SERVER_PAGE_EXTENSIONS, #endif -#if defined(USE_DUKTAPE) - DUKTAPE_SCRIPT_EXTENSIONS, -#endif #if defined(USE_WEBSOCKET) WEBSOCKET_ROOT, diff --git a/src/libhttp.c b/src/libhttp.c index 047ceb3b..bc234c18 100644 --- a/src/libhttp.c +++ b/src/libhttp.c @@ -640,12 +640,6 @@ struct mg_option XX_httplib_config_options[] = { {"lua_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"}, {"lua_server_page_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"}, #endif -#if defined(USE_DUKTAPE) - /* The support for duktape is still in alpha version state. - * The name of this config option might change. */ - {"duktape_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"}, -#endif - #if defined(USE_WEBSOCKET) {"websocket_root", CONFIG_TYPE_DIRECTORY, NULL}, #endif @@ -3628,7 +3622,7 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */ /* Local file path and name, corresponding to requested URI * is now stored in "filename" variable. */ if (mg_stat(conn, filename, filep)) { -#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) +#if !defined(NO_CGI) || defined(USE_LUA) /* File exists. Check if it is a script type. */ if (0 #if !defined(NO_CGI) @@ -3640,12 +3634,6 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */ || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS], strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]), filename) > 0 -#endif -#if defined(USE_DUKTAPE) - || match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], - strlen( - conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]), - filename) > 0 #endif ) { /* The request addresses a CGI script or a Lua script. The URI @@ -3660,7 +3648,7 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */ * generated response. */ *is_script_resource = !*is_put_or_delete_request; } -#endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */ +#endif /* !defined(NO_CGI) || defined(USE_LUA) */ *is_found = 1; return; } @@ -3691,7 +3679,7 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */ } } -#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) +#if !defined(NO_CGI) || defined(USE_LUA) /* Support PATH_INFO for CGI scripts. */ for (p = filename + strlen(filename); p > filename + 1; p--) { if (*p == '/') { @@ -3707,12 +3695,6 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */ strlen( conn->ctx->config[LUA_SCRIPT_EXTENSIONS]), filename) > 0 -#endif -#if defined(USE_DUKTAPE) - || match_prefix( - conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], - strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]), - filename) > 0 #endif ) && mg_stat(conn, filename, filep)) { /* Shift PATH_INFO block one character right, e.g. @@ -3731,7 +3713,7 @@ interpret_uri(struct mg_connection *conn, /* in: request (must be valid) */ } } } -#endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */ +#endif /* !defined(NO_CGI) || defined(USE_LUA) */ #endif /* !defined(NO_FILES) */ return; @@ -7200,10 +7182,6 @@ mg_unlock_context(struct mg_context *ctx) #include "mod_lua.inl" #endif /* USE_LUA */ -#ifdef USE_DUKTAPE -#include "mod_duktape.inl" -#endif /* USE_DUKTAPE */ - #if defined(USE_WEBSOCKET) /* START OF SHA-1 code @@ -8803,14 +8781,6 @@ handle_file_based_request(struct mg_connection *conn, * entire reply. */ mg_exec_lua_script(conn, path, NULL); #endif -#if defined(USE_DUKTAPE) - } else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], - strlen( - conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]), - path) > 0) { - /* Call duktape to generate the page */ - mg_exec_duktape_script(conn, path); -#endif #if !defined(NO_CGI) } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS], strlen(conn->ctx->config[CGI_EXTENSIONS]), diff --git a/src/main.c b/src/main.c index c2e64da5..7b3c5587 100644 --- a/src/main.c +++ b/src/main.c @@ -786,38 +786,6 @@ run_lua(const char *file_name) #endif /* USE_LUA */ -#ifdef USE_DUKTAPE - -#include "duktape.h" - -static int -run_duktape(const char *file_name) -{ - duk_context *ctx = NULL; - -#ifdef WIN32 - (void)MakeConsole(); -#endif /* WIN32 */ - - ctx = duk_create_heap_default(); - if (!ctx) { - fprintf(stderr, "Failed to create a Duktape heap.\n"); - goto finished; - } - - if (duk_peval_file(ctx, file_name) != 0) { - fprintf(stderr, "%s\n", duk_safe_to_string(ctx, -1)); - goto finished; - } - duk_pop(ctx); /* ignore result */ - -finished: - duk_destroy_heap(ctx); - - return 0; -} -#endif /* USE_DUKTAPE */ - #if defined(__MINGW32__) || defined(__MINGW64__) /* For __MINGW32/64_MAJOR/MINOR_VERSION define */ @@ -975,21 +943,6 @@ start_libhttp(int argc, char *argv[]) #endif /* USE_LUA */ } - /* Call Duktape, if -E option is specified */ - if (argc > 1 && !strcmp(argv[1], "-E")) { - -#ifdef USE_DUKTAPE - if (argc != 3) { - show_usage_and_exit(argv[0]); - } - exit(run_duktape(argv[2])); -#else /* USE_DUKTAPE */ - show_server_name(); - fprintf(stderr, "\nError: Ecmascript support not enabled\n"); - exit(EXIT_FAILURE); -#endif /* USE_DUKTAPE */ - } - /* Show usage if -h or --help options are specified */ if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-H") || !strcmp(argv[1], "--help"))) { diff --git a/src/mod_duktape.inl b/src/mod_duktape.inl deleted file mode 100644 index 5637ae9e..00000000 --- a/src/mod_duktape.inl +++ /dev/null @@ -1,250 +0,0 @@ -/* This file is part of the CivetWeb web server. - * See https://github.com/civetweb/civetweb/ - * (C) 2015 by the CivetWeb authors, MIT license. - */ - -#include "duktape.h" - -/* TODO: the mg context should be added to duktape as well */ -/* Alternative: redefine a new, clean API from scratch (instead of using mg), - * or at least do not add problematic functions. */ -/* For evaluation purposes, currently only "send" is supported. - * All other ~50 functions will be added later. */ - -/* Note: This is only experimental support, so the API may still change. */ - -static const char *civetweb_conn_id = "\xFF" - "civetweb_conn"; -static const char *civetweb_ctx_id = "\xFF" - "civetweb_ctx"; - - -static void * -mg_duk_mem_alloc(void *udata, duk_size_t size) -{ - return mg_malloc(size); -} - - -static void * -mg_duk_mem_realloc(void *udata, void *ptr, duk_size_t newsize) -{ - return mg_realloc(ptr, newsize); -} - - -static void -mg_duk_mem_free(void *udata, void *ptr) -{ - mg_free(ptr); -} - - -static void -mg_duk_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) -{ - /* Script is called "protected" (duk_peval_file), so script errors should - * never yield in a call to this function. Maybe calls prior to executing - * the script could raise a fatal error. */ - struct mg_connection *conn; - - duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, civetweb_conn_id); - conn = (struct mg_connection *)duk_to_pointer(ctx, -1); - - mg_cry(conn, "%s", msg); -} - - -static duk_ret_t -duk_itf_write(duk_context *ctx) -{ - struct mg_connection *conn; - duk_double_t ret; - duk_size_t len = 0; - const char *val = duk_require_lstring(ctx, -1, &len); - - /* - duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, civetweb_conn_id); - conn = (struct mg_connection *)duk_to_pointer(ctx, -1); - */ - duk_push_current_function(ctx); - duk_get_prop_string(ctx, -1, civetweb_conn_id); - conn = (struct mg_connection *)duk_to_pointer(ctx, -1); - - if (!conn) { - duk_error(ctx, - DUK_ERR_INTERNAL_ERROR, - "function not available without connection object"); - /* probably never reached, but satisfies static code analysis */ - return DUK_RET_INTERNAL_ERROR; - } - - ret = mg_write(conn, val, len); - - duk_push_number(ctx, ret); - return 1; -} - - -static duk_ret_t -duk_itf_read(duk_context *ctx) -{ - struct mg_connection *conn; - char buf[1024]; - int len; - - duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, civetweb_conn_id); - conn = (struct mg_connection *)duk_to_pointer(ctx, -1); - - if (!conn) { - duk_error(ctx, - DUK_ERR_INTERNAL_ERROR, - "function not available without connection object"); - /* probably never reached, but satisfies static code analysis */ - return DUK_RET_INTERNAL_ERROR; - } - - len = mg_read(conn, buf, sizeof(buf)); - - duk_push_lstring(ctx, buf, len); - return 1; -} - - -static duk_ret_t -duk_itf_getoption(duk_context *ctx) -{ - struct mg_context *cv_ctx; - const char *ret; - duk_size_t len = 0; - const char *val = duk_require_lstring(ctx, -1, &len); - - duk_push_current_function(ctx); - duk_get_prop_string(ctx, -1, civetweb_ctx_id); - cv_ctx = (struct mg_context *)duk_to_pointer(ctx, -1); - - if (!cv_ctx) { - duk_error(ctx, - DUK_ERR_INTERNAL_ERROR, - "function not available without connection object"); - /* probably never reached, but satisfies static code analysis */ - return DUK_RET_INTERNAL_ERROR; - } - - ret = mg_get_option(cv_ctx, val); - if (ret) { - duk_push_string(ctx, ret); - } else { - duk_push_null(ctx); - } - - return 1; -} - - -static void -mg_exec_duktape_script(struct mg_connection *conn, const char *script_name) -{ - int i; - duk_context *ctx = NULL; - - conn->must_close = 1; - - /* Create Duktape interpreter state */ - ctx = duk_create_heap(mg_duk_mem_alloc, - mg_duk_mem_realloc, - mg_duk_mem_free, - NULL, - mg_duk_fatal_handler); - if (!ctx) { - mg_cry(conn, "Failed to create a Duktape heap."); - goto exec_duktape_finished; - } - - /* Add "conn" object */ - duk_push_global_object(ctx); - duk_push_object(ctx); /* create a new table/object ("conn") */ - - duk_push_c_function(ctx, duk_itf_write, 1 /* 1 = nargs */); - duk_push_pointer(ctx, (void *)conn); - duk_put_prop_string(ctx, -2, civetweb_conn_id); - duk_put_prop_string(ctx, -2, "write"); /* add function conn.write */ - - duk_push_c_function(ctx, duk_itf_read, 0 /* 0 = nargs */); - duk_push_pointer(ctx, (void *)conn); - duk_put_prop_string(ctx, -2, civetweb_conn_id); - duk_put_prop_string(ctx, -2, "read"); /* add function conn.read */ - - duk_push_string(ctx, conn->request_info.request_method); - duk_put_prop_string(ctx, -2, "request_method"); /* add string conn.r... */ - - duk_push_string(ctx, conn->request_info.request_uri); - duk_put_prop_string(ctx, -2, "request_uri"); - - duk_push_string(ctx, conn->request_info.local_uri); - duk_put_prop_string(ctx, -2, "uri"); - - duk_push_string(ctx, conn->request_info.http_version); - duk_put_prop_string(ctx, -2, "http_version"); - - duk_push_string(ctx, conn->request_info.query_string); - duk_put_prop_string(ctx, -2, "query_string"); - - duk_push_string(ctx, conn->request_info.remote_addr); - duk_put_prop_string(ctx, -2, "remote_addr"); - - duk_push_int(ctx, conn->request_info.remote_port); - duk_put_prop_string(ctx, -2, "remote_port"); - - duk_push_int(ctx, ntohs(conn->client.lsa.sin.sin_port)); - duk_put_prop_string(ctx, -2, "server_port"); - - duk_push_object(ctx); /* subfolder "conn.http_headers" */ - for (i = 0; i < conn->request_info.num_headers; i++) { - duk_push_string(ctx, conn->request_info.http_headers[i].value); - duk_put_prop_string(ctx, -2, conn->request_info.http_headers[i].name); - } - duk_put_prop_string(ctx, -2, "http_headers"); - - duk_put_prop_string(ctx, -2, "conn"); /* call the table "conn" */ - - /* Add "civetweb" object */ - duk_push_global_object(ctx); - duk_push_object(ctx); /* create a new table/object ("conn") */ - - duk_push_string(ctx, CIVETWEB_VERSION); - duk_put_prop_string(ctx, -2, "version"); - - duk_push_string(ctx, script_name); - duk_put_prop_string(ctx, -2, "script_name"); - - if (conn->ctx != NULL) { - duk_push_c_function(ctx, duk_itf_getoption, 1 /* 1 = nargs */); - duk_push_pointer(ctx, (void *)(conn->ctx)); - duk_put_prop_string(ctx, -2, civetweb_ctx_id); - duk_put_prop_string(ctx, -2, "getoption"); /* add function conn.write */ - - if (conn->ctx->systemName != NULL) { - duk_push_string(ctx, conn->ctx->systemName); - duk_put_prop_string(ctx, -2, "system"); - } - } - - duk_put_prop_string(ctx, -2, "civetweb"); /* call the table "civetweb" */ - - duk_push_global_stash(ctx); - duk_push_pointer(ctx, (void *)conn); - duk_put_prop_string(ctx, -2, civetweb_conn_id); - - if (duk_peval_file(ctx, script_name) != 0) { - mg_cry(conn, "%s", duk_safe_to_string(ctx, -1)); - goto exec_duktape_finished; - } - duk_pop(ctx); /* ignore result */ - -exec_duktape_finished: - duk_destroy_heap(ctx); -} diff --git a/src/third_party/duktape-1.3.0/AUTHORS.rst b/src/third_party/duktape-1.3.0/AUTHORS.rst deleted file mode 100644 index 47b6de90..00000000 --- a/src/third_party/duktape-1.3.0/AUTHORS.rst +++ /dev/null @@ -1,67 +0,0 @@ -=============== -Duktape authors -=============== - -Copyright -========= - -Duktape copyrights are held by its authors. Each author has a copyright -to their contribution, and agrees to irrevocably license the contribution -under the Duktape ``LICENSE.txt``. - -Authors -======= - -Please include an e-mail address, a link to your GitHub profile, or something -similar to allow your contribution to be identified accurately. - -The following people have contributed code, website contents, or Wiki contents, -and agreed to irrevocably license their contributions under the Duktape -``LICENSE.txt`` (in order of appearance): - -* Sami Vaarala -* Niki Dobrev -* Andreas Öman -* László Langó -* Legimet -* Karl Skomski -* Bruce Pascoe - -Other contributions -=================== - -The following people have contributed something other than code (e.g. reported -bugs, provided ideas, etc; roughly in order of appearance): - -* Greg Burns -* Anthony Rabine -* Carlos Costa -* Aurélien Bouilland -* Preet Desai (Pris Matic) -* judofyr (http://www.reddit.com/user/judofyr) -* Jason Woofenden -* Michał Przybyś -* Anthony Howe -* Conrad Pankoff -* Jim Schimpf -* Rajaran Gaunker (https://github.com/zimbabao) -* Andreas Öman -* Doug Sanden -* Josh Engebretson (https://github.com/JoshEngebretson) -* Remo Eichenberger (https://github.com/remoe) -* Mamod Mehyar (https://github.com/mamod) -* David Demelier (https://github.com/markand) -* Tim Caswell (https://github.com/creationix) -* Mitchell Blank Jr (https://github.com/mitchblank) -* https://github.com/yushli -* Seo Sanghyeon (https://github.com/sanxiyn) -* Han ChoongWoo (https://github.com/tunz) -* Joshua Peek (https://github.com/josh) -* Bruce E. Pascoe (https://github.com/fatcerberus) -* https://github.com/Kelledin -* https://github.com/sstruchtrup -* Michael Drake (https://github.com/tlsa) -* https://github.com/chris-y - -If you are accidentally missing from this list, send me an e-mail -(``sami.vaarala@iki.fi``) and I'll fix the omission. diff --git a/src/third_party/duktape-1.3.0/LICENSE.txt b/src/third_party/duktape-1.3.0/LICENSE.txt deleted file mode 100644 index 8358da37..00000000 --- a/src/third_party/duktape-1.3.0/LICENSE.txt +++ /dev/null @@ -1,25 +0,0 @@ -=============== -Duktape license -=============== - -(http://opensource.org/licenses/MIT) - -Copyright (c) 2013-2015 by Duktape authors (see AUTHORS.rst) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/third_party/duktape-1.3.0/Makefile.cmdline b/src/third_party/duktape-1.3.0/Makefile.cmdline deleted file mode 100644 index 798c7631..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.cmdline +++ /dev/null @@ -1,30 +0,0 @@ -# -# Example Makefile for building a program with embedded Duktape. -# The example program here is the Duktape command line tool. -# - -DUKTAPE_SOURCES = src/duktape.c - -DUKTAPE_CMDLINE_SOURCES = \ - examples/cmdline/duk_cmdline.c - -CC = gcc -CCOPTS = -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer -CCOPTS += -I./src # duktape.h and duk_config.h must be in include path -CCLIBS = -lm - -# If you have readline, you may want to enable these. On some platforms -# -lreadline also requires -lncurses (e.g. RHEL), so it is added by default -# (you may be able to remove it) -#CCOPTS += -DDUK_CMDLINE_FANCY -#CCLIBS += -lreadline -#CCLIBS += -lncurses - -# Optional feature defines, see: http://duktape.org/guide.html#compiling -CCOPTS += -DDUK_OPT_SELF_TESTS -#CCOPTS += -DDUK_OPT_DEBUG -#CCOPTS += -DDUK_OPT_DPRINT -# ... - -duk: $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) - $(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS) diff --git a/src/third_party/duktape-1.3.0/Makefile.codepage b/src/third_party/duktape-1.3.0/Makefile.codepage deleted file mode 100644 index cdce9ab5..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.codepage +++ /dev/null @@ -1,4 +0,0 @@ -codepage: - gcc -o $@ -std=c99 -O2 -Wall -Wextra -Isrc/ \ - src/duktape.c examples/codepage-conv/duk_codepage_conv.c \ - examples/codepage-conv/test.c -lm diff --git a/src/third_party/duktape-1.3.0/Makefile.coffee b/src/third_party/duktape-1.3.0/Makefile.coffee deleted file mode 100644 index b99eea23..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.coffee +++ /dev/null @@ -1,4 +0,0 @@ -dummy: - coffee -c examples/coffee/globals.coffee - coffee -c examples/coffee/hello.coffee - coffee -c examples/coffee/mandel.coffee diff --git a/src/third_party/duktape-1.3.0/Makefile.dukdebug b/src/third_party/duktape-1.3.0/Makefile.dukdebug deleted file mode 100644 index bc7b9d5b..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.dukdebug +++ /dev/null @@ -1,23 +0,0 @@ -# -# Duktape command line tool with debugger support. -# - -DUKTAPE_SOURCES = src/duktape.c - -DUKTAPE_CMDLINE_SOURCES = \ - examples/cmdline/duk_cmdline.c \ - examples/debug-trans-socket/duk_trans_socket.c - -CC = gcc -CCOPTS = -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer -CCOPTS += -I./src -I./examples/debug-trans-socket -CCOPTS += -DDUK_CMDLINE_DEBUGGER_SUPPORT # enable --debugger in ./duk -CCOPTS += -DDUK_OPT_DEBUGGER_SUPPORT # enable debugger support in Duktape -CCOPTS += -DDUK_OPT_INTERRUPT_COUNTER # prerequisite for debugging -CCOPTS += -DDUK_OPT_DEBUGGER_FWD_PRINTALERT # optional debugger features -CCOPTS += -DDUK_OPT_DEBUGGER_FWD_LOGGING -CCOPTS += -DDUK_OPT_DEBUGGER_DUMPHEAP -CCLIBS = -lm - -duk: $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) - $(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS) diff --git a/src/third_party/duktape-1.3.0/Makefile.eval b/src/third_party/duktape-1.3.0/Makefile.eval deleted file mode 100644 index 73c52250..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.eval +++ /dev/null @@ -1,7 +0,0 @@ -# -# Example Makefile for building the eval example -# - -eval: - gcc -o $@ -std=c99 -O2 -Wall -Wextra -Isrc/ \ - src/duktape.c examples/eval/eval.c -lm diff --git a/src/third_party/duktape-1.3.0/Makefile.eventloop b/src/third_party/duktape-1.3.0/Makefile.eventloop deleted file mode 100644 index 14806ac8..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.eventloop +++ /dev/null @@ -1,22 +0,0 @@ -# -# Example Makefile for building the eventloop example -# - -evloop: - @echo "NOTE: The eventloop is example is intended to be used on Linux" - @echo " or other common UNIX variants. It is not fully portable." - @echo "" - - gcc -o $@ -std=c99 -Wall -Wextra -O2 -Isrc \ - examples/eventloop/main.c \ - examples/eventloop/c_eventloop.c \ - examples/eventloop/poll.c \ - examples/eventloop/socket.c \ - examples/eventloop/fileio.c \ - examples/eventloop/ncurses.c \ - src/duktape.c \ - -lm -lncurses - - @echo "" - @echo "NOTE: You must 'cd examples/eventloop' before you execute the" - @echo " eventloop binary: it relies on finding .js files in CWD" diff --git a/src/third_party/duktape-1.3.0/Makefile.hello b/src/third_party/duktape-1.3.0/Makefile.hello deleted file mode 100644 index 82e9ab6b..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.hello +++ /dev/null @@ -1,35 +0,0 @@ -# -# Example Makefile for building a program with embedded Duktape. -# -# There are two source sets in the distribution: (1) combined sources where -# you only need duktape.c, duktape.h, and duk_config.h, and (2) separate -# sources where you have a bunch of source and header files. Whichever -# you use, simply include the relevant sources into your C project. This -# Makefile uses the combined source file. -# - -DUKTAPE_SOURCES = src/duktape.c - -# Compiler options are quite flexible. GCC versions have a significant impact -# on the size of -Os code, e.g. gcc-4.6 is much worse than gcc-4.5. - -CC = gcc -CCOPTS = -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer -CCOPTS += -I./src # for combined sources -CCLIBS = -lm -DEFINES = - -# If you want a 32-bit build on a 64-bit host -#CCOPTS += -m32 - -# Optional feature defines, see: http://duktape.org/guide.html#compiling -DEFINES += -DDUK_OPT_SELF_TESTS -#DEFINES += -DDUK_OPT_DEBUG -#DEFINES += -DDUK_OPT_DPRINT -#DEFINES += -DDUK_OPT_NO_TRACEBACKS -# ... - -# For debugging, use -O0 -g -ggdb, and don't add -fomit-frame-pointer - -hello: $(DUKTAPE_SOURCES) examples/hello/hello.c - $(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) examples/hello/hello.c $(CCLIBS) diff --git a/src/third_party/duktape-1.3.0/Makefile.jxpretty b/src/third_party/duktape-1.3.0/Makefile.jxpretty deleted file mode 100644 index 199247ee..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.jxpretty +++ /dev/null @@ -1,8 +0,0 @@ -# -# Example Makefile for building the jxpretty example -# - -jxpretty: - gcc -o $@ -std=c99 -Wall -Wextra -O2 -Isrc \ - src/duktape.c examples/jxpretty/jxpretty.c \ - -lm diff --git a/src/third_party/duktape-1.3.0/Makefile.sandbox b/src/third_party/duktape-1.3.0/Makefile.sandbox deleted file mode 100644 index acd922ae..00000000 --- a/src/third_party/duktape-1.3.0/Makefile.sandbox +++ /dev/null @@ -1,7 +0,0 @@ -# -# Example Makefile for building the sandbox example -# - -sandbox: - gcc -o $@ -std=c99 -O2 -Wall -Wextra -Isrc/ \ - src/duktape.c examples/sandbox/sandbox.c -lm diff --git a/src/third_party/duktape-1.3.0/README.rst b/src/third_party/duktape-1.3.0/README.rst deleted file mode 100644 index 78e72b95..00000000 --- a/src/third_party/duktape-1.3.0/README.rst +++ /dev/null @@ -1,103 +0,0 @@ -======= -Duktape -======= - -Duktape is a small and portable Ecmascript E5/E5.1 implementation. It is -intended to be easily embeddable into C programs, with a C API similar in -spirit to Lua's. - -Duktape supports the full E5/E5.1 feature set including errors, Unicode -strings, and regular expressions, a subset of E6 features (e.g. Proxy -objects), Khronos/ES6 ArrayBuffer/TypedView, and Node.js Buffer bindings. - -Duktape also provides a number of custom features such as error tracebacks, -additional data types for better C integration, combined reference counting -and mark-and sweep garbage collector, object finalizers, co-operative -threads a.k.a. coroutines, tail calls, built-in logging and module frameworks, -a built-in debugger protocol, function bytecode dump/load, and so on. - -You can browse Duktape programmer's API and other documentation at: - -* http://duktape.org/ - -In particular, you should read the getting started section: - -* http://duktape.org/guide.html#gettingstarted - -More examples and how-to articles are in the Duktape Wiki: - -* http://wiki.duktape.org/ - -Building and integrating Duktape into your project is very straightforward: - -* http://duktape.org/guide.html#compiling - -See Makefile.hello for a concrete example:: - - $ cd - $ make -f Makefile.hello - [...] - $ ./hello - Hello world! - 2+3=5 - -To build an example command line tool, use the following:: - - $ cd - $ make -f Makefile.cmdline - [...] - - $ ./duk - ((o) Duktape - duk> print('Hello world!'); - Hello world! - = undefined - - $ ./duk mandel.js - [...] - -This distributable contains: - -* ``src/``: main Duktape library in a "single source file" format (duktape.c, - duktape.h, and duk_config.h). - -* ``src-separate/``: main Duktape library in multiple files format. - -* ``config/``: genconfig utility for creating duk_config.h configuration - files, see: http://wiki.duktape.org/Configuring.html. - -* ``examples/``: further examples for using Duktape. Although Duktape - itself is widely portable, some of the examples are Linux only. - For instance the ``eventloop`` example illustrates how ``setTimeout()`` - and other standard timer functions could be implemented on Unix/Linux. - -* ``extras/``: utilities and modules which don't comfortably fit into the - main Duktape library because of footprint or portability concerns. - Extras are maintained and bug fixed code, but don't have the same version - guarantees as the main Duktape library. - -* ``polyfills/``: a few replacement suggestions for non-standard Javascript - functions provided by other implementations. - -* ``debugger/``: a debugger with a web UI, see ``debugger/README.rst`` and - https://github.com/svaarala/duktape/blob/master/doc/debugger.rst for - details on Duktape debugger support. - -* ``licenses/``: licensing information. - -You can find release notes at: - -* https://github.com/svaarala/duktape/blob/master/RELEASES.rst - -This distributable contains Duktape version 1.3.0, created from git -commit 675165f35ea3a5bac34ff4d0a58b007cc2f442dc (v1.3.0). - -Duktape is copyrighted by its authors (see ``AUTHORS.rst``) and licensed -under the MIT license (see ``LICENSE.txt``). MurmurHash2 is used internally, -it is also under the MIT license. Duktape module loader is based on the -CommonJS module loading specification (without sharing any code), CommonJS -is under the MIT license. - -Have fun! - -Sami Vaarala (sami.vaarala@iki.fi) diff --git a/src/third_party/duktape-1.3.0/config/README.rst b/src/third_party/duktape-1.3.0/config/README.rst deleted file mode 100644 index 1d172261..00000000 --- a/src/third_party/duktape-1.3.0/config/README.rst +++ /dev/null @@ -1,39 +0,0 @@ -================= -Duktape genconfig -================= - -Overview -======== - -``genconfig`` is a helper script for coming up with a ``duk_config.h`` for -compiling Duktape for your platform. - -To support this: - -* It creates a Duktape 1.2.x compatible ``duk_config.h`` with automatic - platform detection and ``DUK_OPT_xxx`` feature options. - -* It helps to create a ``duk_config.h`` for your platform/compiler - combination. You can give a base configuration and then force certain - values manually based on a YAML configuration file. - -* It autogenerates documentation for config options (and Duktape 1.2.x - feature options) based on option metadata files written in YAML. - -Usage -===== - -To create an autodetect duk_config.h header (compatible with Duktape 1.2.x):: - - $ python config/genconfig.py --metadata config --output /tmp/duk_config.h \ - autodetect-header - -To create a barebones duk_config.h header for a specific platform (easier to -edit manually):: - - $ python config/genconfig.py --metadata config --output /tmp/duk_config.h \ - --platform linux --compiler gcc --architecture x64 \ - barebones-header - -There are further commands to e.g. autogenerate config option documentation; -see ``genconfig.py`` for details. diff --git a/src/third_party/duktape-1.3.0/config/genconfig.py b/src/third_party/duktape-1.3.0/config/genconfig.py deleted file mode 100644 index 778705e6..00000000 --- a/src/third_party/duktape-1.3.0/config/genconfig.py +++ /dev/null @@ -1,1872 +0,0 @@ -#!/usr/bin/python -# -# Process Duktape option metadata and produce various useful outputs: -# -# - duk_config.h matching Duktape 1.x feature option model (DUK_OPT_xxx) -# - duk_config.h for a selected platform, compiler, forced options, etc. -# - option documentation for Duktape 1.x feature options (DUK_OPT_xxx) -# - option documentation for Duktape 1.x/2.x config options (DUK_USE_xxx) -# -# Genconfig tries to build all outputs based on modular metadata, so that -# managing a large number of config options (which is hard to avoid given -# the wide range of targets Duktape supports) remains maintainable. -# -# Genconfig does *not* try to support all exotic platforms out there. -# Instead, the goal is to allow the metadata to be extended, or to provide -# a reasonable starting point for manual duk_config.h tweaking. -# -# NOTE: For Duktape 1.3 release the main goal is to autogenerate a Duktape -# 1.2 compatible "autodetect" header from snippets. Other outputs are still -# experimental. -# - -import os -import sys -import re -import json -import yaml -import optparse -import tarfile -import tempfile -import atexit -import shutil -import StringIO - -# -# Globals holding scanned metadata, helper snippets, etc -# - -# Metadata to scan from config files. -use_defs = None -use_defs_list = None -opt_defs = None -opt_defs_list = None -use_tags = None -use_tags_list = None -tags_meta = None -required_use_meta_keys = [ - 'define', - 'introduced', - 'default', - 'tags', - 'description' -] -allowed_use_meta_keys = [ - 'define', - 'feature_enables', - 'feature_disables', - 'feature_snippet', - 'related_feature_defines', - 'introduced', - 'deprecated', - 'removed', - 'unused', - 'requires', - 'conflicts', - 'related', - 'default', - 'tags', - 'description', -] -required_opt_meta_keys = [ - 'define', - 'introduced', - 'tags', - 'description' -] -allowed_opt_meta_keys = [ - 'define', - 'introduced', - 'deprecated', - 'removed', - 'unused', - 'requires', - 'conflicts', - 'related', - 'tags', - 'description' -] - -# Preferred tag order for option documentation. -doc_tag_order = [ - 'portability', - 'memory', - 'lowmemory', - 'ecmascript', - 'execution', - 'debugger', - 'debug', - 'development' -] - -# Preferred tag order for generated C header files. -header_tag_order = doc_tag_order - -# Helper headers snippets. -helper_snippets = None - -# Assume these provides come from outside. -assumed_provides = { - 'DUK_SINGLE_FILE': True, # compiling Duktape from a single source file (duktape.c) version - 'DUK_COMPILING_DUKTAPE': True, # compiling Duktape (not user application) - 'DUK_CONFIG_H_INCLUDED': True, # artifact, include guard -} - -# Platform files must provide at least these (additional checks -# in validate_platform_file()). -platform_required_provides = [ - 'DUK_USE_OS_STRING', - 'DUK_SETJMP', 'DUK_LONGJMP', -] - -# Architecture files must provide at least these (additional checks -# in validate_architecture_file()). -architecture_required_provides = [ - 'DUK_USE_ARCH_STRING', - 'DUK_USE_ALIGN_BY', 'DUK_USE_UNALIGNED_ACCESSES_POSSIBLE', 'DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS', - 'DUK_USE_PACKED_TVAL', 'DUK_USE_PACKED_TVAL_POSSIBLE' -] - -# Compiler files must provide at least these (additional checks -# in validate_compiler_file()). -compiler_required_provides = [ - # XXX: incomplete, maybe a generic fill-in for missing stuff because - # there's quite a lot of required compiler defines. - - 'DUK_USE_COMPILER_STRING', - - 'DUK_EXTERNAL_DECL', 'DUK_EXTERNAL', - 'DUK_INTERNAL_DECL', 'DUK_INTERNAL', - 'DUK_LOCAL_DECL', 'DUK_LOCAL', - - 'DUK_FILE_MACRO', 'DUK_LINE_MACRO', 'DUK_FUNC_MACRO' -] - -# -# Miscellaneous helpers -# - -def get_auto_delete_tempdir(): - tmpdir = tempfile.mkdtemp(suffix='-genconfig') - def _f(dirname): - print 'Deleting temporary directory: %r' % dirname - if os.path.isdir(dirname) and '-genconfig' in dirname: - shutil.rmtree(dirname) - atexit.register(_f, tmpdir) - return tmpdir - -def strip_comments_from_lines(lines): - # Not exact but close enough. Doesn't handle string literals etc, - # but these are not a concrete issue for scanning preprocessor - # #define references. - # - # Comment contents are stripped of any DUK_ prefixed text to avoid - # incorrect requires/provides detection. Other comment text is kept; - # in particular a "/* redefine */" comment must remain intact here. - # - # Avoid Python 2.6 vs. Python 2.7 argument differences. - - def censor(x): - return re.sub(re.compile('DUK_\w+', re.MULTILINE), 'xxx', x.group(0)) - - tmp = '\n'.join(lines) - tmp = re.sub(re.compile('/\*.*?\*/', re.MULTILINE | re.DOTALL), censor, tmp) - tmp = re.sub(re.compile('//.*?$', re.MULTILINE), censor, tmp) - return tmp.split('\n') - -# Header snippet representation: lines, provides defines, requires defines. -re_line_provides = re.compile(r'^#(?:define|undef)\s+(\w+).*$') -re_line_requires = re.compile(r'(DUK_[A-Z0-9_]+)') # uppercase only, don't match DUK_USE_xxx for example -class Snippet: - lines = None # lines of text and/or snippets - provides = None # map from define to 'True' for now - requires = None # map from define to 'True' for now - - def __init__(self, lines, provides=None, requires=None, autoscan_requires=True, autoscan_provides=True): - self.lines = [] - if not isinstance(lines, list): - raise Exception('Snippet constructor must be a list (not e.g. a string): %s' % repr(lines)) - for line in lines: - if isinstance(line, str): - self.lines.append(line) - elif isinstance(line, unicode): - self.lines.append(line.encode('utf-8')) - else: - raise Exception('invalid line: %r' % line) - self.provides = {} - if provides is not None: - for k in provides.keys(): - self.provides[k] = True - self.requires = {} - if requires is not None: - for k in requires.keys(): - self.requires[k] = True - - stripped_lines = strip_comments_from_lines(lines) - # for line in stripped_lines: print(line) - - for line in stripped_lines: - # Careful with order, snippet may self-reference its own - # defines in which case there's no outward dependency. - # (This is not 100% because the order of require/provide - # matters and this is not handled now.) - # - # Also, some snippets may #undef/#define another define but - # they don't "provide" the define as such. For example, - # DUK_F_CLANG.h.in undefines DUK_F_GCC defines if clang is - # detected: DUK_F_CLANG.h.in is considered to require - # DUK_F_GCC but doesn't provide it. Such redefinitions are - # marked "/* redefine */" in the snippets. They're best - # avoided, of course. - - if autoscan_provides: - m = re_line_provides.match(line) - if m is not None and '/* redefine */' not in line and \ - len(m.group(1)) > 0 and m.group(1)[-1] != '_': - # Don't allow e.g. DUK_USE_ which results from matching DUK_USE_xxx - #print('PROVIDES: %r' % m.group(1)) - self.provides[m.group(1)] = True - if autoscan_requires: - matches = re.findall(re_line_requires, line) - for m in matches: - if len(m) > 0 and m[-1] == '_': - # Don't allow e.g. DUK_USE_ which results from matching DUK_USE_xxx - pass - elif m[:7] == 'DUK_OPT': - # DUK_OPT_xxx always come from outside - pass - elif m[:7] == 'DUK_USE': - # DUK_USE_xxx are internal and they should not be 'requirements' - pass - elif self.provides.has_key(m): - # Snippet provides it's own require; omit - pass - else: - #print('REQUIRES: %r' % m) - self.requires[m] = True - - def fromFile(cls, filename): - lines = [] - with open(filename, 'rb') as f: - for line in f: - if line[-1] == '\n': - line = line[:-1] - lines.append(line) - return Snippet(lines, autoscan_requires=True, autoscan_provides=True) - fromFile = classmethod(fromFile) - - def merge(cls, snippets): - ret = Snippet([], [], []) - for s in snippets: - ret.lines += s.lines - for k in s.provides.keys(): - ret.provides[k] = True - for k in s.requires.keys(): - ret.requires[k] = True - return ret - merge = classmethod(merge) - -# Helper for building a text file from individual lines, injected files, etc. -# Inserted values are converted to Snippets so that their provides/requires -# information can be tracked. When non-C outputs are created, these will be -# bogus but ignored. -class FileBuilder: - vals = None # snippet list - base_dir = None - use_cpp_warning = False - - def __init__(self, base_dir=None, use_cpp_warning=False): - self.vals = [] - self.base_dir = base_dir - self.use_cpp_warning = use_cpp_warning - - def line(self, line): - self.vals.append(Snippet([ line ])) - - def lines(self, lines): - if len(lines) > 0 and lines[-1] == '\n': - lines = lines[:-1] # strip last newline to avoid empty line - self.vals.append(Snippet(lines.split('\n'))) - - def empty(self): - self.vals.append(Snippet([ '' ])) - - def rst_heading(self, title, char, doubled=False): - tmp = [] - if doubled: - tmp.append(char * len(title)) - tmp.append(title) - tmp.append(char * len(title)) - self.vals.append(Snippet(tmp)) - - def snippet_relative(self, fn): - sn = Snippet.fromFile(os.path.join(self.base_dir, fn)) - self.vals.append(sn) - - def snippet_absolute(fn): - sn = Snippet.fromFile(fn) - self.vals.append(sn) - - def cpp_error(self, msg): - # XXX: assume no newlines etc - self.vals.append(Snippet([ '#error %s' % msg ])) - - def cpp_warning(self, msg): - # XXX: assume no newlines etc - # XXX: support compiler specific warning mechanisms - if self.use_cpp_warning: - # C preprocessor '#warning' is often supported - self.vals.append(Snippet([ '#warning %s' % msg ])) - else: - self.vals.append(Snippet([ '/* WARNING: %s */' % msg ])) - - def cpp_warning_or_error(self, msg, is_error=True): - if is_error: - self.cpp_error(msg) - else: - self.cpp_warning(msg) - - def chdr_block_heading(self, msg): - lines = [] - lines.append('') - lines.append('/*') - lines.append(' * ' + msg) - lines.append(' */') - lines.append('') - self.vals.append(Snippet(lines)) - - def join(self): - tmp = [] - for line in self.vals: - if not isinstance(line, object): - raise Exception('self.vals must be all snippets') - for x in line.lines: # x is a Snippet - tmp.append(x) - return '\n'.join(tmp) - - def fill_dependencies_for_snippets(self, idx_deps): - fill_dependencies_for_snippets(self.vals, idx_deps) - -# Insert missing define dependencies into index 'idx_deps' repeatedly -# until no unsatisfied dependencies exist. This is used to pull in -# the required DUK_F_xxx helper defines without pulling them all in. -# The resolution mechanism also ensures dependencies are pulled in the -# correct order, i.e. DUK_F_xxx helpers may depend on each other (as -# long as there are no circular dependencies). -# -# XXX: this can be simplified a lot -def fill_dependencies_for_snippets(snippets, idx_deps): - # graph[A] = [ B, ... ] <-> B, ... provide something A requires. - graph = {} - snlist = [] - resolved = [] # for printing only - - def add(sn): - if sn in snlist: - return # already present - snlist.append(sn) - - to_add = [] - - for k in sn.requires.keys(): - if assumed_provides.has_key(k): - continue - - found = False - for sn2 in snlist: - if sn2.provides.has_key(k): - if not graph.has_key(sn): - graph[sn] = [] - graph[sn].append(sn2) - found = True # at least one other node provides 'k' - - if not found: - #print 'Resolving %r' % k - resolved.append(k) - - # Find a header snippet which provides the missing define. - # Some DUK_F_xxx files provide multiple defines, so we don't - # necessarily know the snippet filename here. - - sn_req = None - for sn2 in helper_snippets: - if sn2.provides.has_key(k): - sn_req = sn2 - break - if sn_req is None: - print(repr(sn.lines)) - raise Exception('cannot resolve missing require: %r' % k) - - # Snippet may have further unresolved provides; add recursively - to_add.append(sn_req) - - if not graph.has_key(sn): - graph[sn] = [] - graph[sn].append(sn_req) - - for sn in to_add: - add(sn) - - # Add original snippets. This fills in the required nodes - # recursively. - for sn in snippets: - add(sn) - - # Figure out fill-ins by looking for snippets not in original - # list and without any unserialized dependent nodes. - handled = {} - for sn in snippets: - handled[sn] = True - keepgoing = True - while keepgoing: - keepgoing = False - for sn in snlist: - if handled.has_key(sn): - continue - - success = True - for dep in graph.get(sn, []): - if not handled.has_key(dep): - success = False - if success: - snippets.insert(idx_deps, sn) - idx_deps += 1 - snippets.insert(idx_deps, Snippet([ '' ])) - idx_deps += 1 - handled[sn] = True - keepgoing = True - break - - # XXX: detect and handle loops cleanly - for sn in snlist: - if handled.has_key(sn): - continue - print('UNHANDLED KEY') - print('PROVIDES: %r' % sn.provides) - print('REQUIRES: %r' % sn.requires) - print('\n'.join(sn.lines)) - -# print(repr(graph)) -# print(repr(snlist)) - print 'Resolved helper defines: %r' % resolved - -def serialize_snippet_list(snippets): - ret = [] - - emitted_provides = {} - for k in assumed_provides.keys(): - emitted_provides[k] = True - - for sn in snippets: - ret += sn.lines - for k in sn.provides.keys(): - emitted_provides[k] = True - for k in sn.requires.keys(): - if not emitted_provides.has_key(k): - # XXX: conditional warning, happens in some normal cases - #print('WARNING: define %r required, not provided so far' % k) - pass - - return '\n'.join(ret) - -def remove_duplicate_newlines(x): - ret = [] - empty = False - for line in x.split('\n'): - if line == '': - if empty: - pass - else: - ret.append(line) - empty = True - else: - empty = False - ret.append(line) - return '\n'.join(ret) - -def scan_use_defs(dirname): - global use_defs, use_defs_list - use_defs = {} - use_defs_list = [] - - for fn in os.listdir(dirname): - root, ext = os.path.splitext(fn) - if not root.startswith('DUK_USE_') or ext != '.yaml': - continue - with open(os.path.join(dirname, fn), 'rb') as f: - doc = yaml.load(f) - if doc.get('example', False): - continue - if doc.get('unimplemented', False): - print('WARNING: unimplemented: %s' % fn) - continue - dockeys = doc.keys() - for k in dockeys: - if not k in allowed_use_meta_keys: - print('WARNING: unknown key %s in metadata file %s' % (k, fn)) - for k in required_use_meta_keys: - if not k in dockeys: - print('WARNING: missing key %s in metadata file %s' % (k, fn)) - - use_defs[doc['define']] = doc - - keys = use_defs.keys() - keys.sort() - for k in keys: - use_defs_list.append(use_defs[k]) - -def scan_opt_defs(dirname): - global opt_defs, opt_defs_list - opt_defs = {} - opt_defs_list = [] - - for fn in os.listdir(dirname): - root, ext = os.path.splitext(fn) - if not root.startswith('DUK_OPT_') or ext != '.yaml': - continue - with open(os.path.join(dirname, fn), 'rb') as f: - doc = yaml.load(f) - if doc.get('example', False): - continue - if doc.get('unimplemented', False): - print('WARNING: unimplemented: %s' % fn) - continue - dockeys = doc.keys() - for k in dockeys: - if not k in allowed_opt_meta_keys: - print('WARNING: unknown key %s in metadata file %s' % (k, fn)) - for k in required_opt_meta_keys: - if not k in dockeys: - print('WARNING: missing key %s in metadata file %s' % (k, fn)) - - opt_defs[doc['define']] = doc - - keys = opt_defs.keys() - keys.sort() - for k in keys: - opt_defs_list.append(opt_defs[k]) - -def scan_use_tags(): - global use_tags, use_tags_list - use_tags = {} - - for doc in use_defs_list: - for tag in doc.get('tags', []): - use_tags[tag] = True - - use_tags_list = use_tags.keys() - use_tags_list.sort() - -def scan_tags_meta(filename): - global tags_meta - - with open(filename, 'rb') as f: - tags_meta = yaml.load(f) - -def scan_snippets(dirname): - global helper_snippets - helper_snippets = [] - - for fn in os.listdir(dirname): - if (fn[0:6] != 'DUK_F_'): - continue - #print('Autoscanning snippet: %s' % fn) - helper_snippets.append(Snippet.fromFile(os.path.join(dirname, fn))) - -def validate_platform_file(filename): - sn = Snippet.fromFile(filename) - - # XXX: move required provides/defines into metadata only - for req in platform_required_provides: - if req not in sn.provides: - raise Exception('Platform %s is missing %s' % (filename, req)) - - if not ('DUK_USE_SETJMP' in sn.provides or 'DUK_USE_UNDERSCORE_SETJMP' in sn.provides or - 'DUK_USE_SIGSETJMP' in sn.provides): - raise Exception('Platform %s is missing a setjmp provider' % filename) - -def validate_architecture_file(filename): - sn = Snippet.fromFile(filename) - - # XXX: move required provides/defines into metadata only - for req in architecture_required_provides: - if req not in sn.provides: - raise Exception('Architecture %s is missing %s' % (filename, req)) - -def validate_compiler_file(filename): - sn = Snippet.fromFile(filename) - - # XXX: move required provides/defines into metadata only - for req in compiler_required_provides: - if req not in sn.provides: - raise Exception('Architecture %s is missing %s' % (filename, req)) - -def get_tag_title(tag): - meta = tags_meta.get(tag, None) - if meta is None: - return tag - else: - return meta.get('title', tag) - -def get_tag_description(tag): - meta = tags_meta.get(tag, None) - if meta is None: - return None - else: - return meta.get('description', None) - -def get_tag_list_with_preferred_order(preferred): - tags = [] - - # Preferred tags first - for tag in preferred: - if tag not in tags: - tags.append(tag) - - # Remaining tags in alphabetic order - for tag in use_tags_list: - if tag not in tags: - tags.append(tag) - - #print('Effective tag order: %r' % tags) - return tags - -def rst_format(text): - # XXX: placeholder, need to decide on markup conventions for YAML files - ret = [] - for para in text.split('\n'): - if para == '': - continue - ret.append(para) - return '\n\n'.join(ret) - -def cint_encode(x): - if not isinstance(x, (int, long)): - raise Exception('invalid input: %r' % x) - - # XXX: unsigned constants? - if x > 0x7fffffff or x < -0x80000000: - return '%dLL' % x - elif x > 0x7fff or x < -0x8000: - return '%dL' % x - else: - return '%d' % x - -def cstr_encode(x): - if isinstance(x, unicode): - x = x.encode('utf-8') - if not isinstance(x, str): - raise Exception('invalid input: %r' % x) - - res = '"' - term = False - has_terms = False - for c in x: - if term: - # Avoid ambiguous hex escapes - res += '" "' - term = False - has_terms = True - o = ord(c) - if o < 0x20 or o > 0x7e or c in '"\\': - res += '\\x%02x' % o - term = True - else: - res += c - res += '"' - - if has_terms: - res = '(' + res + ')' - - return res - -# -# Autogeneration of option documentation -# - -# Shared helper to generate DUK_OPT_xxx and DUK_USE_xxx documentation. -# XXX: unfinished placeholder -def generate_option_documentation(opts, opt_list=None, rst_title=None, include_default=False): - ret = FileBuilder(use_cpp_warning=opts.use_cpp_warning) - - tags = get_tag_list_with_preferred_order(doc_tag_order) - - title = rst_title - ret.rst_heading(title, '=', doubled=True) - - handled = {} - - for tag in tags: - first = True - - for doc in opt_list: - if tag != doc['tags'][0]: # sort under primary tag - continue - dname = doc['define'] - desc = doc.get('description', None) - - if handled.has_key(dname): - raise Exception('define handled twice, should not happen: %r' % dname) - handled[dname] = True - - if first: # emit tag heading only if there are subsections - ret.empty() - ret.rst_heading(get_tag_title(tag), '=') - - tag_desc = get_tag_description(tag) - if tag_desc is not None: - ret.empty() - ret.line(rst_format(tag_desc)) - first = False - - ret.empty() - ret.rst_heading(dname, '-') - - if desc is not None: - ret.empty() - ret.line(rst_format(desc)) - - if include_default: - ret.empty() - ret.line('Default: ``' + str(doc['default']) + '``') # XXX: rst or other format - - for doc in opt_list: - dname = doc['define'] - if not handled.has_key(dname): - raise Exception('unhandled define (maybe missing from tags list?): %r' % dname) - - ret.empty() - return ret.join() - -def generate_feature_option_documentation(opts): - return generate_option_documentation(opts, opt_list=opt_defs_list, rst_title='Duktape feature options', include_default=False) - -def generate_config_option_documentation(opts): - return generate_option_documentation(opts, opt_list=use_defs_list, rst_title='Duktape config options', include_default=True) - -# -# Helpers for duk_config.h generation -# - -def get_forced_options(opts): - # Forced options, last occurrence wins (allows a base config file to be - # overridden by a more specific one). - forced_opts = {} - for val in opts.force_options_yaml: - doc = yaml.load(StringIO.StringIO(val)) - for k in doc.keys(): - if use_defs.has_key(k): - pass # key is known - else: - print 'WARNING: option override key %s not defined in metadata, ignoring' % k - forced_opts[k] = doc[k] # shallow copy - - print 'Overrides: %s' % json.dumps(forced_opts) - - return forced_opts - -# Emit a default #define / #undef for an option based on -# a config option metadata node (parsed YAML doc). -def emit_default_from_config_meta(ret, doc, forced_opts, undef_done): - defname = doc['define'] - defval = forced_opts.get(defname, doc['default']) - - if defval == True: - ret.line('#define ' + defname) - elif defval == False: - if not undef_done: - ret.line('#undef ' + defname) - else: - # Default value is false, and caller has emitted - # an unconditional #undef, so don't emit a duplicate - pass - elif isinstance(defval, (int, long)): - # integer value - ret.line('#define ' + defname + ' ' + cint_encode(defval)) - elif isinstance(defval, (str, unicode)): - # verbatim value - ret.line('#define ' + defname + ' ' + defval) - elif isinstance(defval, dict): - if defval.has_key('verbatim'): - # verbatim text for the entire line - ret.line(defval['verbatim']) - elif defval.has_key('string'): - # C string value - ret.line('#define ' + defname + ' ' + cstr_encode(defval['string'])) - else: - raise Exception('unsupported value for option %s: %r' % (defname, defval)) - else: - raise Exception('unsupported value for option %s: %r' % (defname, defval)) - -# Add a header snippet for detecting presence of DUK_OPT_xxx feature -# options which will be removed in Duktape 2.x. -def add_legacy_feature_option_checks(opts, ret): - ret.chdr_block_heading('Checks for legacy feature options (DUK_OPT_xxx)') - - defs = [] - for doc in opt_defs_list: - if doc['define'] not in defs: - defs.append(doc['define']) - for doc in use_defs_list: - for dname in doc.get('related_feature_defines', []): - if dname not in defs: - defs.append(dname) - defs.sort() - - for optname in defs: - suggested = [] - for doc in use_defs_list: - if optname in doc.get('related_feature_defines', []): - suggested.append(doc['define']) - ret.empty() - ret.line('#if defined(%s)' % optname) - if len(suggested) > 0: - ret.cpp_warning_or_error('unsupported legacy feature option %s used, consider options: %s' % (optname, ', '.join(suggested)), opts.sanity_strict) - else: - ret.cpp_warning_or_error('unsupported legacy feature option %s used' % optname, opts.sanity_strict) - ret.line('#endif') - - ret.empty() - -# Add a header snippet for checking consistency of DUK_USE_xxx config -# options, e.g. inconsistent options, invalid option values. -def add_config_option_checks(opts, ret): - ret.chdr_block_heading('Checks for config option consistency (DUK_USE_xxx)') - - defs = [] - for doc in use_defs_list: - if doc['define'] not in defs: - defs.append(doc['define']) - defs.sort() - - for optname in defs: - doc = use_defs[optname] - dname = doc['define'] - - # XXX: more checks - - if doc.get('removed', None) is not None: - ret.empty() - ret.line('#if defined(%s)' % dname) - ret.cpp_warning_or_error('unsupported config option used (option has been removed): %s' % dname, opts.sanity_strict) - ret.line('#endif') - elif doc.get('deprecated', None) is not None: - ret.empty() - ret.line('#if defined(%s)' % dname) - ret.cpp_warning_or_error('unsupported config option used (option has been deprecated): %s' % dname, opts.sanity_strict) - ret.line('#endif') - - for req in doc.get('requires', []): - ret.empty() - ret.line('#if defined(%s) && !defined(%s)' % (dname, req)) - ret.cpp_warning_or_error('config option %s requires option %s (which is missing)' % (dname, req), opts.sanity_strict) - ret.line('#endif') - - for req in doc.get('conflicts', []): - ret.empty() - ret.line('#if defined(%s) && defined(%s)' % (dname, req)) - ret.cpp_warning_or_error('config option %s conflicts with option %s (which is also defined)' % (dname, req), opts.sanity_strict) - ret.line('#endif') - - ret.empty() - -# Add a header snippet for providing a __OVERRIDE_DEFINES__ section. -def add_override_defines_section(opts, ret): - ret.empty() - ret.line('/*') - ret.line(' * You may add overriding #define/#undef directives below for') - ret.line(' * customization. You of course cannot un-#include or un-typedef') - ret.line(' * anything; these require direct changes above.') - ret.line(' */') - ret.empty() - ret.line('/* __OVERRIDE_DEFINES__ */') - ret.empty() - -# Add automatic DUK_OPT_XXX and DUK_OPT_NO_XXX handling for backwards -# compatibility with Duktape 1.2 and before. -def add_feature_option_handling(opts, ret, forced_opts): - ret.chdr_block_heading('Feature option handling') - - for doc in use_defs_list: - # If a related feature option exists, it can be used to force - # enable/disable the target feature. If neither feature option - # (DUK_OPT_xxx or DUK_OPT_NO_xxx) is given, revert to default. - - config_define = doc['define'] - - feature_define = None - feature_no_define = None - inverted = False - if doc.has_key('feature_enables'): - feature_define = doc['feature_enables'] - elif doc.has_key('feature_disables'): - feature_define = doc['feature_disables'] - inverted = True - else: - pass - - if feature_define is not None: - feature_no_define = 'DUK_OPT_NO_' + feature_define[8:] - ret.line('#if defined(%s)' % feature_define) - if inverted: - ret.line('#undef %s' % config_define) - else: - ret.line('#define %s' % config_define) - ret.line('#elif defined(%s)' % feature_no_define) - if inverted: - ret.line('#define %s' % config_define) - else: - ret.line('#undef %s' % config_define) - ret.line('#else') - undef_done = False - emit_default_from_config_meta(ret, doc, forced_opts, undef_done) - ret.line('#endif') - elif doc.has_key('feature_snippet'): - ret.lines(doc['feature_snippet']) - else: - pass - - ret.empty() - - ret.empty() - -# Development time helper: add DUK_ACTIVE which provides a runtime C string -# indicating what DUK_USE_xxx config options are active at run time. This -# is useful in genconfig development so that one can e.g. diff the active -# run time options of two headers. This is intended just for genconfig -# development and is not available in normal headers. -def add_duk_active_defines_macro(ret): - ret.chdr_block_heading('DUK_ACTIVE_DEFINES macro (development only)') - - idx = 0 - for doc in use_defs_list: - defname = doc['define'] - - ret.line('#if defined(%s)' % defname) - ret.line('#define DUK_ACTIVE_DEF%d " %s"' % (idx, defname)) - ret.line('#else') - ret.line('#define DUK_ACTIVE_DEF%d ""' % idx) - ret.line('#endif') - - idx += 1 - - tmp = [] - for i in xrange(idx): - tmp.append('DUK_ACTIVE_DEF%d' % i) - - ret.line('#define DUK_ACTIVE_DEFINES ("Active: ["' + ' '.join(tmp) + ' " ]")') - -# -# duk_config.h generation -# - -# Generate the default duk_config.h which provides automatic detection of -# platform, compiler, architecture, and features for major platforms. -# Use manually written monolithic header snippets from Duktape 1.2 for -# generating the header. This header is Duktape 1.2 compatible and supports -# DUK_OPT_xxx feature options. Later on the DUK_OPT_xxx options will be -# removed and users can override DUK_USE_xxx flags directly by modifying -# duk_config.h or by generating a new header using genconfig. -def generate_autodetect_duk_config_header(opts, meta_dir): - ret = FileBuilder(base_dir=os.path.join(meta_dir, 'header-snippets'), \ - use_cpp_warning=opts.use_cpp_warning) - - forced_opts = get_forced_options(opts) - - ret.snippet_relative('comment_prologue.h.in') - ret.empty() - - ret.line('#ifndef DUK_CONFIG_H_INCLUDED') - ret.line('#define DUK_CONFIG_H_INCLUDED') - ret.empty() - - # Compiler features, processor/architecture, OS, compiler - ret.snippet_relative('compiler_features.h.in') - ret.empty() - ret.snippet_relative('rdtsc.h.in') # XXX: move downwards - ret.empty() - ret.snippet_relative('platform1.h.in') - ret.empty() - - # Feature selection, system include, Date provider - # Most #include statements are here - ret.snippet_relative('platform2.h.in') - ret.empty() - ret.snippet_relative('ullconsts.h.in') - ret.empty() - ret.snippet_relative('libc.h.in') - ret.empty() - - # Number types - ret.snippet_relative('types1.h.in') - ret.line('#if defined(DUK_F_HAVE_INTTYPES)') - ret.line('/* C99 or compatible */') - ret.empty() - ret.snippet_relative('types_c99.h.in') - ret.empty() - ret.line('#else /* C99 types */') - ret.empty() - ret.snippet_relative('types_legacy.h.in') - ret.empty() - ret.line('#endif /* C99 types */') - ret.empty() - ret.snippet_relative('types2.h.in') - ret.empty() - ret.snippet_relative('64bitops.h.in') - ret.empty() - - # Alignment - ret.snippet_relative('alignment.h.in') - ret.empty() - - # Object layout - ret.snippet_relative('object_layout.h.in') - ret.empty() - - # Byte order - ret.snippet_relative('byteorder.h.in') - ret.empty() - - # Packed duk_tval - ret.snippet_relative('packed_tval.h.in') - ret.empty() - - # Detect 'fast math' - ret.snippet_relative('reject_fast_math.h.in') - ret.empty() - - # IEEE double constants - ret.snippet_relative('double_const.h.in') - ret.empty() - - # Math and other ANSI replacements, NetBSD workaround, paranoid math, paranoid Date - ret.snippet_relative('repl_math.h.in') - ret.empty() - ret.snippet_relative('paranoid_date.h.in') - ret.empty() - ret.snippet_relative('repl_ansi.h.in') - ret.empty() - - # Platform function pointers - ret.snippet_relative('platform_funcptr.h.in') - ret.empty() - - # General compiler stuff - ret.snippet_relative('stringify.h.in') - ret.empty() - ret.snippet_relative('segfault.h.in') - ret.empty() - ret.snippet_relative('unreferenced.h.in') - ret.empty() - ret.snippet_relative('noreturn.h.in') - ret.empty() - ret.snippet_relative('unreachable.h.in') - ret.empty() - ret.snippet_relative('likely.h.in') - ret.empty() - ret.snippet_relative('inline.h.in') - ret.empty() - ret.snippet_relative('visibility.h.in') - ret.empty() - ret.snippet_relative('file_line_func.h.in') - ret.empty() - ret.snippet_relative('byteswap.h.in') - ret.empty() - - # Arhitecture, OS, and compiler strings - ret.snippet_relative('arch_string.h.in') - ret.empty() - ret.snippet_relative('os_string.h.in') - ret.empty() - ret.snippet_relative('compiler_string.h.in') - ret.empty() - - # Target info - ret.snippet_relative('target_info.h.in') - ret.empty() - - # Longjmp handling - ret.snippet_relative('longjmp.h.in') - ret.empty() - - # Unsorted flags, contains almost all actual Duktape-specific - # but platform independent features - ret.snippet_relative('unsorted_flags.h.in') - ret.empty() - - # User declarations - ret.snippet_relative('user_declare.h.in') - ret.empty() - - # Emit forced options. If a corresponding option is already defined - # by a snippet above, #undef it first. - - tmp = Snippet(ret.join().split('\n')) - first_forced = True - for doc in use_defs_list: - defname = doc['define'] - - if doc.get('removed', None) is not None and opts.omit_removed_config_options: - continue - if doc.get('deprecated', None) is not None and opts.omit_deprecated_config_options: - continue - if doc.get('unused', False) == True and opts.omit_unused_config_options: - continue - if not forced_opts.has_key(defname): - continue - - if not doc.has_key('default'): - raise Exception('config option %s is missing default value' % defname) - - if first_forced: - ret.chdr_block_heading('Forced options') - first_forced = False - - undef_done = False - if tmp.provides.has_key(defname): - ret.line('#undef ' + defname) - undef_done = True - - emit_default_from_config_meta(ret, doc, forced_opts, undef_done) - - ret.empty() - - # If manually-edited snippets don't #define or #undef a certain - # config option, emit a default value here. This is useful to - # fill-in for new config options not covered by manual snippets - # (which is intentional). - - tmp = Snippet(ret.join().split('\n')) - need = {} - for doc in use_defs_list: - if doc.get('removed', None) is not None: # XXX: check version - continue - need[doc['define']] = True - for k in tmp.provides.keys(): - if need.has_key(k): - del need[k] - need_keys = sorted(need.keys()) - - if len(need_keys) > 0: - ret.chdr_block_heading('Autogenerated defaults') - - for k in need_keys: - #print('config option %s not covered by manual snippets, emitting default automatically' % k) - emit_default_from_config_meta(ret, use_defs[k], {}, False) - - ret.empty() - - ret.snippet_relative('custom_header.h.in') - ret.empty() - - if len(opts.fixup_header_lines) > 0: - ret.chdr_block_heading('Fixups') - for line in opts.fixup_header_lines: - ret.line(line) - ret.empty() - - add_override_defines_section(opts, ret) - - # Date provider snippet is after custom header and overrides, so that - # the user may define e.g. DUK_USE_DATE_NOW_GETTIMEOFDAY in their - # custom header. - ret.snippet_relative('date_provider.h.in') - ret.empty() - - # Sanity checks - # XXX: use autogenerated sanity checks instead - ret.snippet_relative('sanity.h.in') - ret.empty() - - if opts.emit_legacy_feature_check: - # XXX: this doesn't really make sense for the autodetect - # header yet, because sanity.h.in already covers these. - add_legacy_feature_option_checks(opts, ret) - if opts.emit_config_sanity_check: - add_config_option_checks(opts, ret) - if opts.add_active_defines_macro: - add_duk_active_defines_macro(ret) - - ret.line('#endif /* DUK_CONFIG_H_INCLUDED */') - ret.empty() # for trailing newline - return remove_duplicate_newlines(ret.join()) - -# Generate a duk_config.h where platform, architecture, and compiler are -# all either autodetected or specified by user. When autodetection is -# used, the generated header is based on modular snippets and metadata to -# be more easily maintainable than manually edited monolithic snippets. -# -# This approach will replace the legacy autodetect header in Duktape 1.4, -# and most likely the separate barebones header also. -# -# The generated header is Duktape 1.2 compatible for now, and supports -# DUK_OPT_xxx feature options. Later on the DUK_OPT_xxx options will be -# removed and user code overrides DUK_USE_xxx flags directly by modifying -# duk_config.h manually or by generating a new header using genconfig. -def generate_autodetect_duk_config_header_modular(opts, meta_dir): - ret = FileBuilder(base_dir=os.path.join(meta_dir, 'header-snippets'), \ - use_cpp_warning=opts.use_cpp_warning) - - forced_opts = get_forced_options(opts) - - platforms = None - with open(os.path.join(meta_dir, 'platforms.yaml'), 'rb') as f: - platforms = yaml.load(f) - architectures = None - with open(os.path.join(meta_dir, 'architectures.yaml'), 'rb') as f: - architectures = yaml.load(f) - compilers = None - with open(os.path.join(meta_dir, 'compilers.yaml'), 'rb') as f: - compilers = yaml.load(f) - - ret.line('/*') - ret.line(' * duk_config.h autodetect header generated by genconfig.py.') - ret.line(' *') - ret.line(' * Git commit: %s' % opts.git_commit or 'n/a') - ret.line(' * Git describe: %s' % opts.git_describe or 'n/a') - ret.line(' *') - if opts.platform is not None: - ret.line(' * Platform: ' + opts.platform) - else: - ret.line(' * Supported platforms:') - for platf in platforms['autodetect']: - ret.line(' * - %s' % platf.get('name', platf.get('check'))) - ret.line(' *') - if opts.architecture is not None: - ret.line(' * Architecture: ' + opts.architecture) - else: - ret.line(' * Supported architectures:') - for arch in architectures['autodetect']: - ret.line(' * - %s' % arch.get('name', arch.get('check'))) - ret.line(' *') - if opts.compiler is not None: - ret.line(' * Compiler: ' + opts.compiler) - else: - ret.line(' * Supported compilers:') - for comp in compilers['autodetect']: - ret.line(' * - %s' % comp.get('name', comp.get('check'))) - ret.line(' *') - ret.line(' */') - ret.empty() - ret.line('#ifndef DUK_CONFIG_H_INCLUDED') - ret.line('#define DUK_CONFIG_H_INCLUDED') - ret.empty() - - ret.chdr_block_heading('Intermediate helper defines') - - idx_deps = len(ret.vals) # position where to emit dependencies - - # Feature selection, system include, Date provider - # Most #include statements are here - - if opts.platform is not None: - ret.chdr_block_heading('Platform: ' + opts.platform) - - ret.snippet_relative('platform_cppextras.h.in') - ret.empty() - - # XXX: better to lookup platforms metadata - include = 'platform_%s.h.in' % opts.platform - validate_platform_file(os.path.join(meta_dir, 'header-snippets', include)) - ret.snippet_relative(include) - else: - ret.chdr_block_heading('Platform autodetection') - - ret.snippet_relative('platform_cppextras.h.in') - ret.empty() - - for idx, platf in enumerate(platforms['autodetect']): - check = platf.get('check', None) - include = platf['include'] - validate_platform_file(os.path.join(meta_dir, 'header-snippets', include)) - - if idx == 0: - ret.line('#if defined(%s)' % check) - else: - if check is None: - ret.line('#else') - else: - ret.line('#elif defined(%s)' % check) - ret.snippet_relative(include) - ret.line('#endif /* autodetect platform */') - - ret.snippet_relative('platform_sharedincludes.h.in') - ret.empty() - - if opts.architecture is not None: - ret.chdr_block_heading('Architecture: ' + opts.architecture) - - # XXX: better to lookup architectures metadata - include = 'architecture_%s.h.in' % opts.architecture - validate_architecture_file(os.path.join(meta_dir, 'header-snippets', include)) - ret.snippet_relative(include) - else: - ret.chdr_block_heading('Architecture autodetection') - - for idx, arch in enumerate(architectures['autodetect']): - check = arch.get('check', None) - include = arch['include'] - validate_architecture_file(os.path.join(meta_dir, 'header-snippets', include)) - - if idx == 0: - ret.line('#if defined(%s)' % check) - else: - if check is None: - ret.line('#else') - else: - ret.line('#elif defined(%s)' % check) - ret.snippet_relative(include) - ret.line('#endif /* autodetect architecture */') - - if opts.compiler is not None: - ret.chdr_block_heading('Compiler: ' + opts.compiler) - - # XXX: better to lookup compilers metadata - include = 'compiler_%s.h.in' % opts.compiler - validate_compiler_file(os.path.join(meta_dir, 'header-snippets', include)) - ret.snippet_relative(include) - else: - ret.chdr_block_heading('Compiler autodetection') - - for idx, comp in enumerate(compilers['autodetect']): - check = comp.get('check', None) - include = comp['include'] - validate_compiler_file(os.path.join(meta_dir, 'header-snippets', include)) - - if idx == 0: - ret.line('#if defined(%s)' % check) - else: - if check is None: - ret.line('#else') - else: - ret.line('#elif defined(%s)' % check) - ret.snippet_relative(include) - ret.line('#endif /* autodetect compiler */') - - # FIXME: The snippets below have some conflicts with the platform, - # architecture, and compiler snippets files included above. These - # need to be resolved so that (a) each define is only provided from - # one place or (b) the latter definition is a "fill-in" which is - # only used when a certain define is missing from e.g. a compiler - # snippet (useful for e.g. compiler defines which have sane, standard - # defaults). - - # FIXME: __uclibc__ needs stdlib.h, but it really is the only exception - ret.snippet_relative('libc.h.in') - ret.empty() - - # Number types - ret.snippet_relative('types1.h.in') - ret.line('#if defined(DUK_F_HAVE_INTTYPES)') - ret.line('/* C99 or compatible */') - ret.empty() - ret.snippet_relative('types_c99.h.in') - ret.empty() - ret.line('#else /* C99 types */') - ret.empty() - ret.snippet_relative('types_legacy.h.in') - ret.empty() - ret.line('#endif /* C99 types */') - ret.empty() - ret.snippet_relative('types2.h.in') - ret.empty() - ret.snippet_relative('64bitops.h.in') - ret.empty() - - # Alignment - ret.snippet_relative('alignment.h.in') - ret.empty() - - # Object layout - ret.snippet_relative('object_layout.h.in') - ret.empty() - - # Byte order - # FIXME: from the architecture snippet - ret.snippet_relative('byteorder.h.in') - ret.empty() - - # Packed duk_tval - # FIXME: from the architecture snippet - ret.snippet_relative('packed_tval.h.in') - ret.empty() - - # Detect 'fast math' - ret.snippet_relative('reject_fast_math.h.in') - ret.empty() - - # IEEE double constants - # FIXME: these should maybe be 'fill-ins' if previous headers - # didn't provide something - ret.snippet_relative('double_const.h.in') - ret.empty() - - # Math and other ANSI replacements, NetBSD workaround, paranoid math, paranoid Date - ret.snippet_relative('repl_math.h.in') - ret.empty() - ret.snippet_relative('paranoid_date.h.in') - ret.empty() - ret.snippet_relative('repl_ansi.h.in') - ret.empty() - - # Platform function pointers - ret.snippet_relative('platform_funcptr.h.in') - ret.empty() - - # General compiler stuff - ret.snippet_relative('stringify.h.in') - ret.empty() - ret.snippet_relative('segfault.h.in') - ret.empty() - ret.snippet_relative('unreferenced.h.in') - ret.empty() - ret.snippet_relative('noreturn.h.in') - ret.empty() - ret.snippet_relative('unreachable.h.in') - ret.empty() - ret.snippet_relative('likely.h.in') - ret.empty() - ret.snippet_relative('inline.h.in') - ret.empty() - ret.snippet_relative('visibility.h.in') - ret.empty() - ret.snippet_relative('file_line_func.h.in') - ret.empty() - ret.snippet_relative('byteswap.h.in') - ret.empty() - - # These come directly from platform, architecture, and compiler - # snippets. - #ret.snippet_relative('arch_string.h.in') - #ret.empty() - #ret.snippet_relative('os_string.h.in') - #ret.empty() - #ret.snippet_relative('compiler_string.h.in') - #ret.empty() - #ret.snippet_relative('longjmp.h.in') - #ret.empty() - - # Target info - ret.snippet_relative('target_info.h.in') - ret.empty() - - # Automatic DUK_OPT_xxx feature option handling - # FIXME: platform setjmp/longjmp defines now conflict with this - if True: - # Unsorted flags, contains almost all actual Duktape-specific - # but platform independent features - #ret.snippet_relative('unsorted_flags.h.in') - #ret.empty() - - add_feature_option_handling(opts, ret, forced_opts) - - ret.snippet_relative('user_declare.h.in') - ret.empty() - - # Emit forced options. If a corresponding option is already defined - # by a snippet above, #undef it first. - - tmp = Snippet(ret.join().split('\n')) - first_forced = True - for doc in use_defs_list: - defname = doc['define'] - - if doc.get('removed', None) is not None and opts.omit_removed_config_options: - continue - if doc.get('deprecated', None) is not None and opts.omit_deprecated_config_options: - continue - if doc.get('unused', False) == True and opts.omit_unused_config_options: - continue - if not forced_opts.has_key(defname): - continue - - if not doc.has_key('default'): - raise Exception('config option %s is missing default value' % defname) - - if first_forced: - ret.chdr_block_heading('Forced options') - first_forced = False - - undef_done = False - if tmp.provides.has_key(defname): - ret.line('#undef ' + defname) - undef_done = True - - emit_default_from_config_meta(ret, doc, forced_opts, undef_done) - - ret.empty() - - # If manually-edited snippets don't #define or #undef a certain - # config option, emit a default value here. This is useful to - # fill-in for new config options not covered by manual snippets - # (which is intentional). - - tmp = Snippet(ret.join().split('\n')) - need = {} - for doc in use_defs_list: - if doc.get('removed', None) is not None: # XXX: check version - continue - need[doc['define']] = True - for k in tmp.provides.keys(): - if need.has_key(k): - del need[k] - need_keys = sorted(need.keys()) - - if len(need_keys) > 0: - ret.chdr_block_heading('Autogenerated defaults') - - for k in need_keys: - #print('config option %s not covered by manual snippets, emitting default automatically' % k) - emit_default_from_config_meta(ret, use_defs[k], {}, False) - - ret.empty() - - ret.snippet_relative('custom_header.h.in') - ret.empty() - - if len(opts.fixup_header_lines) > 0: - ret.chdr_block_heading('Fixups') - for line in opts.fixup_header_lines: - ret.line(line) - ret.empty() - - add_override_defines_section(opts, ret) - - # Date provider snippet is after custom header and overrides, so that - # the user may define e.g. DUK_USE_DATE_NOW_GETTIMEOFDAY in their - # custom header. - ret.snippet_relative('date_provider.h.in') - ret.empty() - - ret.fill_dependencies_for_snippets(idx_deps) - - # FIXME: use autogenerated sanity instead of sanity.h.in - - ret.snippet_relative('sanity.h.in') - ret.empty() - - if opts.emit_legacy_feature_check: - # FIXME: this doesn't really make sense for the autodetect header yet - add_legacy_feature_option_checks(opts, ret) - if opts.emit_config_sanity_check: - add_config_option_checks(opts, ret) - if opts.add_active_defines_macro: - add_duk_active_defines_macro(ret) - - ret.line('#endif /* DUK_CONFIG_H_INCLUDED */') - ret.empty() # for trailing newline - return remove_duplicate_newlines(ret.join()) - -# Generate a barebones duk_config.h header for a specific platform, architecture, -# and compiler. The header won't do automatic feature detection and does not -# support DUK_OPT_xxx feature options (which will be removed in Duktape 2.x). -# Users can then modify this barebones header for very exotic platforms and manage -# the needed changes either as a YAML file or by appending a fixup header snippet. -# -# XXX: to be replaced by generate_modular_duk_config_header(). -def generate_barebones_duk_config_header(opts, meta_dir): - ret = FileBuilder(base_dir=os.path.join(meta_dir, 'header-snippets'), \ - use_cpp_warning=opts.use_cpp_warning) - - # XXX: Provide more defines from YAML config files so that such - # defines can be overridden more conveniently (e.g. DUK_COS). - - forced_opts = get_forced_options(opts) - - ret.line('/*') - ret.line(' * duk_config.h generated by genconfig.py for:') - ret.line(' * platform: %s' % opts.platform) - ret.line(' * compiler: %s' % opts.compiler) - ret.line(' * architecture: %s' % opts.architecture) - ret.line(' *') - ret.line(' * Git commit: %s' % opts.git_commit or 'n/a') - ret.line(' * Git describe: %s' % opts.git_describe or 'n/a') - ret.line(' */') - ret.empty() - ret.line('#ifndef DUK_CONFIG_H_INCLUDED') - ret.line('#define DUK_CONFIG_H_INCLUDED') - - ret.chdr_block_heading('Intermediate helper defines') - - idx_deps = len(ret.vals) # position where to emit dependencies - - ret.chdr_block_heading('Platform headers and typedefs') - - if opts.platform is None: - raise Exception('no platform specified') - - fn = 'platform_%s.h.in' % opts.platform - ret.snippet_relative(fn) - ret.empty() - ret.snippet_relative('types_c99.h.in') # XXX: C99 typedefs forced for now - ret.snippet_relative('types2.h.in') # XXX: boilerplate type stuff - - ret.chdr_block_heading('Platform features') - - # XXX: double constants - # XXX: replacement functions - # XXX: inherit definitions (like '#define DUK_FFLUSH fflush') from a - # generic set of defaults, allow platform configs to override - - ret.snippet_relative('platform_generic.h.in') - - ret.chdr_block_heading('Compiler features') - - if opts.compiler is None: - raise Exception('no compiler specified') - - fn = 'compiler_%s.h.in' % opts.compiler - ret.snippet_relative(fn) - - # noreturn, vacopy, etc - # visibility attributes - - ret.chdr_block_heading('Architecture features') - - if opts.architecture is None: - raise Exception('no architecture specified') - - fn = 'architecture_%s.h.in' % opts.architecture - ret.snippet_relative(fn) - - ret.chdr_block_heading('Config options') - - tags = get_tag_list_with_preferred_order(header_tag_order) - - handled = {} - - # Mark all defines 'provided' by the snippets so far as handled. - # For example, if the system header provides a DUK_USE_OS_STRING, - # we won't emit it again below with its default value (but will - # emit an override value if specified). - - for sn in ret.vals: - for k in sn.provides.keys(): - handled[k] = True - - for tag in tags: - ret.line('/* ' + get_tag_title(tag) + ' */') - - for doc in use_defs_list: - defname = doc['define'] - - if doc.get('removed', None) is not None and opts.omit_removed_config_options: - continue - if doc.get('deprecated', None) is not None and opts.omit_deprecated_config_options: - continue - if doc.get('unused', False) == True and opts.omit_unused_config_options: - continue - - if tag != doc['tags'][0]: # sort under primary tag - continue - - if not doc.has_key('default'): - raise Exception('config option %s is missing default value' % defname) - - undef_done = False - - if handled.has_key(defname): - defval = forced_opts.get(defname, None) - if defval is None: - ret.line('/* %s already emitted above */' % defname) - continue - - # Define already emitted by snippets above but - # an explicit override wants to redefine it. - # Undef first and then use shared handler to - # setup the forced value. - ret.line('#undef ' + defname) - undef_done = True - - # FIXME: macro args; DUK_USE_USER_DECLARE vs. DUK_USE_USER_DECLARE() - # vs. DUK_USE_USER_DECLARE(x,y) - - handled[defname] = True - emit_default_from_config_meta(ret, doc, forced_opts, undef_done) - - ret.empty() - - if len(opts.fixup_header_lines) > 0: - ret.chdr_block_heading('Fixups') - for line in opts.fixup_header_lines: - ret.line(line) - - add_override_defines_section(opts, ret) - - # Date provider snippet is after custom header and overrides, so that - # the user may define e.g. DUK_USE_DATE_NOW_GETTIMEOFDAY in their - # custom header. - ret.empty() - ret.snippet_relative('date_provider.h.in') - ret.empty() - - ret.fill_dependencies_for_snippets(idx_deps) - - # XXX: ensure no define is unhandled at the end - - # Check for presence of legacy feature options (DUK_OPT_xxx), - # and consistency of final DUK_USE_xxx options. - # - # These could also be emitted into Duktape source code, but it's - # probably better that the checks can be easily disabled from - # duk_config.h. - - if opts.emit_legacy_feature_check: - add_legacy_feature_option_checks(opts, ret) - if opts.emit_config_sanity_check: - add_config_option_checks(opts, ret) - if opts.add_active_defines_macro: - add_duk_active_defines_macro(ret) - - ret.line('#endif /* DUK_CONFIG_H_INCLUDED */') - ret.empty() # for trailing newline - - return remove_duplicate_newlines(serialize_snippet_list(ret.vals)) # XXX: refactor into FileBuilder - -# -# Main -# - -def main(): - # Forced options from multiple sources are gathered into a shared list - # so that the override order remains the same as on the command line. - force_options_yaml = [] - def add_force_option_yaml(option, opt, value, parser): - # XXX: check that YAML parses - force_options_yaml.append(value) - def add_force_option_file(option, opt, value, parser): - # XXX: check that YAML parses - with open(value, 'rb') as f: - force_options_yaml.append(f.read()) - def add_force_option_define(option, opt, value, parser): - tmp = value.split('=') - if len(tmp) == 1: - doc = { tmp[0]: True } - elif len(tmp) == 2: - doc = { tmp[0]: tmp[1] } - else: - raise Exception('invalid option value: %r' % value) - force_options_yaml.append(yaml.safe_dump(doc)) - def add_force_option_undefine(option, opt, value, parser): - tmp = value.split('=') - if len(tmp) == 1: - doc = { tmp[0]: False } - else: - raise Exception('invalid option value: %r' % value) - force_options_yaml.append(yaml.safe_dump(doc)) - - fixup_header_lines = [] - def add_fixup_header_line(option, opt, value, parser): - fixup_header_lines.append(value) - def add_fixup_header_file(option, opt, value, parser): - with open(value, 'rb') as f: - for line in f: - if line[-1] == '\n': - line = line[:-1] - fixup_header_lines.append(line) - - commands = [ - 'autodetect-header', - 'barebones-header', - 'feature-documentation', - 'config-documentation' - ] - parser = optparse.OptionParser( - usage='Usage: %prog [options] COMMAND', - description='Generate a duk_config.h or config option documentation based on config metadata.', - epilog='COMMAND can be one of: ' + ', '.join(commands) + '.' - ) - parser.add_option('--metadata', dest='metadata', default=None, help='metadata directory or metadata tar.gz file') - parser.add_option('--output', dest='output', default=None, help='output filename for C header or RST documentation file') - parser.add_option('--platform', dest='platform', default=None, help='platform (for "barebones-header" command)') - parser.add_option('--compiler', dest='compiler', default=None, help='compiler (for "barebones-header" command)') - parser.add_option('--architecture', dest='architecture', default=None, help='architecture (for "barebones-header" command)') - parser.add_option('--dll', dest='dll', action='store_true', default=False, help='dll build of Duktape, affects symbol visibility macros especially on Windows') # FIXME: unimplemented - parser.add_option('--emit-legacy-feature-check', dest='emit_legacy_feature_check', action='store_true', default=False, help='emit preprocessor checks to reject legacy feature options (DUK_OPT_xxx)') - parser.add_option('--emit-config-sanity-check', dest='emit_config_sanity_check', action='store_true', default=False, help='emit preprocessor checks for config option consistency (DUK_OPT_xxx)') - parser.add_option('--omit-removed-config-options', dest='omit_removed_config_options', action='store_true', default=False, help='omit removed config options from generated headers') - parser.add_option('--omit-deprecated-config-options', dest='omit_deprecated_config_options', action='store_true', default=False, help='omit deprecated config options from generated headers') - parser.add_option('--omit-unused-config-options', dest='omit_unused_config_options', action='store_true', default=False, help='omit unused config options from generated headers') - parser.add_option('--add-active-defines-macro', dest='add_active_defines_macro', action='store_true', default=False, help='add DUK_ACTIVE_DEFINES macro, for development only') - parser.add_option('--define', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_define, default=force_options_yaml, help='force #define option using a C compiler like syntax, e.g. "--define DUK_USE_DEEP_C_STACK" or "--define DUK_USE_TRACEBACK_DEPTH=10"') - parser.add_option('-D', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_define, default=force_options_yaml, help='synonym for --define, e.g. "-DDUK_USE_DEEP_C_STACK" or "-DDUK_USE_TRACEBACK_DEPTH=10"') - parser.add_option('--undefine', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_undefine, default=force_options_yaml, help='force #undef option using a C compiler like syntax, e.g. "--undefine DUK_USE_DEEP_C_STACK"') - parser.add_option('-U', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_undefine, default=force_options_yaml, help='synonym for --undefine, e.g. "-UDUK_USE_DEEP_C_STACK"') - parser.add_option('--option-yaml', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_yaml, default=force_options_yaml, help='force option(s) using inline YAML (e.g. --option-yaml "DUK_USE_DEEP_C_STACK: true")') - parser.add_option('--option-file', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_file, default=force_options_yaml, help='YAML file(s) providing config option overrides') - parser.add_option('--fixup-file', type='string', dest='fixup_header_lines', action='callback', callback=add_fixup_header_file, default=fixup_header_lines, help='C header snippet file(s) to be appended to generated header, useful for manual option fixups') - parser.add_option('--fixup-line', type='string', dest='fixup_header_lines', action='callback', callback=add_fixup_header_line, default=fixup_header_lines, help='C header fixup line to be appended to generated header (e.g. --fixup-line "#define DUK_USE_FASTINT")') - parser.add_option('--sanity-warning', dest='sanity_strict', action='store_false', default=True, help='emit a warning instead of #error for option sanity check issues') - parser.add_option('--use-cpp-warning', dest='use_cpp_warning', action='store_true', default=False, help='emit a (non-portable) #warning when appropriate') - parser.add_option('--git-commit', dest='git_commit', default=None, help='git commit hash to be included in header comments') - parser.add_option('--git-describe', dest='git_describe', default=None, help='git describe string to be included in header comments') - (opts, args) = parser.parse_args() - - meta_dir = opts.metadata - if opts.metadata is None: - if os.path.isfile(os.path.join('.', 'genconfig_metadata.tar.gz')): - opts.metadata = 'genconfig_metadata.tar.gz' - elif os.path.isdir(os.path.join('.', 'config-options')): - opts.metadata = '.' - - if opts.metadata is not None and os.path.isdir(opts.metadata): - meta_dir = opts.metadata - print 'Using metadata directory: %r' % meta_dir - elif opts.metadata is not None and os.path.isfile(opts.metadata) and tarfile.is_tarfile(opts.metadata): - meta_dir = get_auto_delete_tempdir() - tar = tarfile.open(name=opts.metadata, mode='r:*') - tar.extractall(path=meta_dir) - print 'Using metadata tar file %r, unpacked to directory: %r' % (opts.metadata, meta_dir) - else: - raise Exception('metadata source must be a directory or a tar.gz file') - - scan_snippets(os.path.join(meta_dir, 'header-snippets')) - scan_use_defs(os.path.join(meta_dir, 'config-options')) - scan_opt_defs(os.path.join(meta_dir, 'feature-options')) - scan_use_tags() - scan_tags_meta(os.path.join(meta_dir, 'tags.yaml')) - print('Scanned %d DUK_OPT_xxx, %d DUK_USE_XXX, %d helper snippets' % \ - (len(opt_defs.keys()), len(use_defs.keys()), len(helper_snippets))) - #print('Tags: %r' % use_tags_list) - - if len(args) == 0: - raise Exception('missing command') - cmd = args[0] - - if cmd == 'autodetect-header': - cmd = 'autodetect-header-legacy' - - if cmd == 'autodetect-header-legacy': - # Generate a duk_config.h similar to Duktape 1.2 feature detection, - # based on manually written monolithic snippets. - # To be replaced by modular header. - result = generate_autodetect_duk_config_header(opts, meta_dir) - with open(opts.output, 'wb') as f: - f.write(result) - elif cmd == 'autodetect-header-modular': - # Generate a duk_config.h similar to Duktape 1.2 feature detection. - # Platform, architecture, and compiler can each be either autodetected - # or specified by user. Generated header is based on modular snippets - # rather than a monolithic platform detection header. - result = generate_autodetect_duk_config_header_modular(opts, meta_dir) - with open(opts.output, 'wb') as f: - f.write(result) - elif cmd == 'barebones-header': - # Generate a duk_config.h with default options for a specific platform, - # compiler, and architecture. - result = generate_barebones_duk_config_header(opts, meta_dir) - with open(opts.output, 'wb') as f: - f.write(result) - elif cmd == 'feature-documentation': - result = generate_feature_option_documentation(opts) - with open(opts.output, 'wb') as f: - f.write(result) - elif cmd == 'config-documentation': - result = generate_config_option_documentation(opts) - with open(opts.output, 'wb') as f: - f.write(result) - else: - raise Exception('invalid command: %r' % cmd) - -if __name__ == '__main__': - main() diff --git a/src/third_party/duktape-1.3.0/config/genconfig_metadata.tar.gz b/src/third_party/duktape-1.3.0/config/genconfig_metadata.tar.gz deleted file mode 100644 index 042de8f2..00000000 Binary files a/src/third_party/duktape-1.3.0/config/genconfig_metadata.tar.gz and /dev/null differ diff --git a/src/third_party/duktape-1.3.0/debugger/Makefile b/src/third_party/duktape-1.3.0/debugger/Makefile deleted file mode 100644 index a85bc012..00000000 --- a/src/third_party/duktape-1.3.0/debugger/Makefile +++ /dev/null @@ -1,80 +0,0 @@ -NODE:=$(shell which nodejs node | head -1) - -# Try to get a useful default --source-dirs which works both in the Duktape -# repo and in the distributable. We don't want to add '..' because it would -# scan a lot of undesired files in the Duktape repo (e.g. test262 testcases). -ifeq ($(wildcard ../tests/ecmascript/*.js),) -SOURCEDIRS:=../ -else -SOURCEDIRS:=../tests/ecmascript -endif - -.PHONY: all -all: run - -.PHONY: run -run: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images - $(NODE) duk_debug.js --source-dirs=$(SOURCEDIRS) - -.PHONY: runproxy -runproxy: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images - $(NODE) duk_debug.js --json-proxy - -.PHONY: clean -clean: - @rm -f static/socket.io-1.2.0.js - @rm -f static/jquery-1.11.1.min.js - @rm -f static/jquery.syntaxhighlighter.min.js - @rm -f static/jquery.snippet.min.js - @rm -f static/jquery.snippet.min.css - @rm -f static/prefixfree.min.js - @rm -f static/reset.css - @rm -f static/jquery-ui.min.js - @rm -f static/jquery-ui.min.css - @rm -rf static/images - @rm -f jquery-ui-1.11.2.zip - @rm -rf jquery-ui-1.11.2 - @rm -rf node_modules - -node_modules: - npm install - -static/socket.io-1.2.0.js: - wget -O $@ https://cdn.socket.io/socket.io-1.2.0.js - -static/jquery-1.11.1.min.js: - wget -O $@ http://code.jquery.com/jquery-1.11.1.min.js - -# http://balupton.github.io/jquery-syntaxhighlighter/demo/ -static/jquery.syntaxhighlighter.min.js: - wget -O $@ http://balupton.github.com/jquery-syntaxhighlighter/scripts/jquery.syntaxhighlighter.min.js - -# http://steamdev.com/snippet/ -static/jquery.snippet.min.js: - wget -O $@ http://steamdev.com/snippet/js/jquery.snippet.min.js -static/jquery.snippet.min.css: - wget -O $@ http://steamdev.com/snippet/css/jquery.snippet.min.css - -# http://prismjs.com/ -# http://prismjs.com/plugins/line-highlight/ -# -# XXX: prism download manually? - -# https://raw.github.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js -static/prefixfree.min.js: - wget -O $@ https://raw.github.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js - -# http://meyerweb.com/eric/tools/css/reset/ -static/reset.css: - wget -O $@ http://meyerweb.com/eric/tools/css/reset/reset.css - -jquery-ui-1.11.2.zip: - wget -O $@ http://jqueryui.com/resources/download/jquery-ui-1.11.2.zip -jquery-ui-1.11.2: jquery-ui-1.11.2.zip - unzip $< -static/jquery-ui.min.js: jquery-ui-1.11.2 - cp jquery-ui-1.11.2/jquery-ui.min.js $@ -static/jquery-ui.min.css: jquery-ui-1.11.2 - cp jquery-ui-1.11.2/jquery-ui.min.css $@ -static/images: jquery-ui-1.11.2 - cp -r jquery-ui-1.11.2/images static/ diff --git a/src/third_party/duktape-1.3.0/debugger/README.rst b/src/third_party/duktape-1.3.0/debugger/README.rst deleted file mode 100644 index 8a82d65d..00000000 --- a/src/third_party/duktape-1.3.0/debugger/README.rst +++ /dev/null @@ -1,268 +0,0 @@ -========================================= -Duktape debug client and JSON debug proxy -========================================= - -Overview -======== - -Debugger web UI which connects to the Duktape command line tool or any other -target supporting the example TCP transport (``examples/debug-trans-socket``). - -Also provides a JSON debug proxy with a JSON mapping for the Duktape debug -protocol. - -For detailed documentation of the debugger internals, see `debugger.rst`__. - -__ https://github.com/svaarala/duktape/blob/master/doc/debugger.rst - -Using the debugger web UI -========================= - -Some prerequisites: - -* You'll need Node.js v0.10.x or newer. Older Node.js versions don't support - the required packages. - -Compile Duktape command line tool with debugger support (for further options -see ``doc/feature-options.rst``): - -* ``DUK_OPT_DEBUGGER_SUPPORT`` - -* ``DUK_OPT_INTERRUPT_COUNTER`` - -* ``DUK_CMDLINE_DEBUGGER_SUPPORT`` - -The source distributable contains a Makefile to build a "duk" command with -debugger support:: - - $ cd - $ make -f Makefile.dukdebug - -The Duktape Git repo "duk" target has debugger support enabled by default:: - - $ make clean duk - -Start Duktape command line tool so that it waits for a debugger connection:: - - # For now we need to be in the directory containing the source files - # executed so that the 'fileName' properties of functions will match - # that on the debug client. - - # Using source distributable - $ cd - $ ./duk --debugger mandel.js - - # Using Duktape Git repo - $ cd /tests/ecmascript/ - $ ../../duk --debugger test-dev-mandel2-func.js - -Start the web UI:: - - # Must be in 'debugger' directory. - - $ cd debugger/ - $ make # runs 'node duk_debug.js' - -Once the required packages are installed, the NodeJS debug client will be -up and running. Open the following in your browser and start debugging: - -* http://localhost:9092/ - -The debug client automatically attaches to the debug target on startup. -If you start the debug target later, you'll need to click "Attach" in the -web UI. - -Using the JSON debug proxy -========================== - -A JSON debug proxy is also provided by ``duk_debug.js``:: - - # Same prerequisites as above - $ make runproxy - -Start Duktape command line (or whatever your target is):: - - $ cd /tests/ecmascript/ - $ ../../duk --debugger test-dev-mandel2-func.js - -You can then connect to localhost:9093 and interact with the proxy. -Here's an example session using telnet and manually typed in commands -The ``-->`` (send) and ``<--`` (receiver) markers have been added for -readability and are not part of the stream:: - - $ telnet localhost 9093 - Trying 127.0.0.1... - Connected to localhost. - Escape character is '^]'. - <-- {"notify":"_Connected","args":["1 10199 v1.1.0-275-gbd4d610-dirty duk command built from Duktape repo"]} - <-- {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]} - --> {"request":"BasicInfo"} - <-- {"reply":true,"args":[10199,"v1.1.0-275-gbd4d610-dirty","duk command built from Duktape repo",1]} - --> {"request":"Eval", "args":[ "print(Math.PI)" ]} - <-- {"notify":"Print","command":2,"args":["3.141592653589793\n"]} - <-- {"reply":true,"args":[0,{"type":"undefined"}]} - --> {"request":"Resume"} - <-- {"reply":true,"args":[]} - <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]} - <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]} - <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} - <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} - <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} - [...] - <-- {"notify":"_Disconnecting"} - -A telnet connection allows you to experiment with debug commands by simply -copy-pasting debug commands to the telnet session. This is useful even if -you decide to implement the binary protocol directly. - -The debug target used by the proxy can be configured with ``duk_debug.js`` -command line options. - -Source search path -================== - -The NodeJS debug client needs to be able to find source code files matching -code running on the target ("duk" command line). **The filenames used on the -target and on the debug client must match exactly**, because e.g. breakpoints -are targeted based on the 'fileName' property of Function objects. - -The search path can be set using the ``--source-dirs`` option given to -``duk_debug.js``, with the default search paths including only -``../tests/ecmascript/``. - -The default search path means that if a function on the target has fileName -``foo/bar.js`` it would be loaded from (relative to the duk_debug.js working -directory, ``debugger/``):: - - ../tests/ecmascript/foo/bar.js - -Similarly, if the filesystem contained:: - - ../tests/ecmascript/baz/quux.js - -the web UI dropdown would show ``baz/quux.js``. If you selected that file -and added a breakpoint, the breakpoint fileName sent to the debug target -would be ``baz/quux.js``. - -.. note:: There's much to improve in the search path. For instance, it'd - be nice to add a certain path to search but exclude files based - on paths and patterns, etc. - -Architecture -============ - -:: - - +-------------------+ - | Web browser | [debug UI] - +-------------------+ - | - | http (port 9092) - | socket.io - v - +-------------------+ - | duk_debug.js | [debug client] - +-------------------+ - | /\ - | || - +----------||---- [example tcp transport] (port 9091) - | || (application provides concrete transport) - | || - | ||---- [debug protocol stream] - | || (between debug client and Duktape) - | || - + - - | - - - - -|| - - + - : v || : -  : +-------------||-+ : [target] - : | application || | : - : +-------------||-+ : - : ^ || : - : | || : [debug API] - : +----------||-------- debug transport callbacks - : | || : (read, write, peek, read/write flush) - : | || : implemented by application - : | \/ : - : +----------------+ : - : | Duktape | : - : +----------------+ : - + - - - - - - - - - - - + - -The debug transport is application specific: - -* Duktape command line ("duk") and this debug client use an **example** TCP - transport as a concrete example. - -* It is entirely up to the application to come up with the most suitable - transport for its environment. Different mechanisms will be needed for - Wi-Fi, serial, etc. - -The debug protocol running inside the transport is transport independent: - -* The debug protocol is documented in ``doc/debugger.rst``. - -* This debug client provides further concrete examples and clarifications - on how the protocol can be used. - -Using a custom transport -======================== - -Quite possibly your target device cannot use the example TCP transport and -you need to implement your own transport. You'll need to implement your -custom transport both for the target device and for the debug client. - -Target device -------------- - -Implement the debug transport callbacks needed by ``duk_debugger_attach()``. - -See ``doc/debugger.rst`` for details and ``examples/debug-trans-socket`` -for example running code for a TCP transport. - -Debug client alternative 1: duk_debug.js + custom TCP proxy ------------------------------------------------------------ - -If you don't want to change ``duk_debug.js`` you can implement a TCP proxy -which accepts a TCP connection from ``duk_debug.js`` and then uses your -custom transport to talk to the target:: - - +--------------+ TCP +-------+ custom +--------+ - | duk_debug.js | ------> | proxy | ---------> | target | - +--------------+ +-------+ +--------+ - -This is a straightforward option and a proxy can be used with other debug -clients too (perhaps custom scripts talking to the target etc). - -You could also use netcat and implement your proxy so that it talks to -``duk_debug.js`` using stdin/stdout. - -Debug client alternative 2: duk_debug.js + custom NodeJS stream ---------------------------------------------------------------- - -To make ``duk_debug.js`` use a custom transport you need to: - -* Implement your own transport as NodeJS stream. You can add it directly to - ``duk_debug.js`` but it's probably easiest to use a separate module so that - the diff to ``duk_debug.js`` stays minimal. - -* Change ``duk_debug.js`` to use the custom transport instead of a TCP - stream. Search for "CUSTOMTRANSPORT" in ``duk_debug.js``. - -See: - -* http://nodejs.org/api/stream.html - -* https://github.com/substack/stream-handbook - -Debug client alternative 3: custom debug client ------------------------------------------------ - -You can also implement your own debug client and debug UI with support for -your custom transport. - -You'll also need to implement the client part of the Duktape debugger -protocol. See ``doc/debugger.rst`` for the specification and ``duk_debug.js`` -for example running code which should illustrate the protocol in more detail. - -The JSON debug proxy allows you to implement a debug client without needing -to implement the Duktape binary debug protocol. The JSON protocol provides -a roughly 1:1 mapping to the binary protocol but with an easier syntax. diff --git a/src/third_party/duktape-1.3.0/debugger/duk_classnames.yaml b/src/third_party/duktape-1.3.0/debugger/duk_classnames.yaml deleted file mode 100644 index b4a5cea4..00000000 --- a/src/third_party/duktape-1.3.0/debugger/duk_classnames.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Must match C header -- unused -- Arguments -- Array -- Boolean -- Date -- Error -- Function -- JSON -- Math -- Number -- Object -- RegExp -- String -- global -- ObjEnv -- DecEnv -- Buffer -- Pointer -- Thread -- ArrayBuffer -- DataView -- Int8Array -- Uint8Array -- Uint8ClampedArray -- Int16Array -- Uint16Array -- Int32Array -- Uint32Array -- Float32Array -- Float64Array diff --git a/src/third_party/duktape-1.3.0/debugger/duk_debug.js b/src/third_party/duktape-1.3.0/debugger/duk_debug.js deleted file mode 100644 index 5a294095..00000000 --- a/src/third_party/duktape-1.3.0/debugger/duk_debug.js +++ /dev/null @@ -1,2448 +0,0 @@ -/* - * Minimal debug web console for Duktape command line tool - * - * See debugger/README.rst. - * - * The web UI socket.io communication can easily become a bottleneck and - * it's important to ensure that the web UI remains responsive. Basic rate - * limiting mechanisms (token buckets, suppressing identical messages, etc) - * are used here now. Ideally the web UI would pull data on its own terms - * which would provide natural rate limiting. - * - * Promises are used to structure callback chains. - * - * https://github.com/petkaantonov/bluebird - * https://github.com/petkaantonov/bluebird/blob/master/API.md - * https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns - */ - -var Promise = require('bluebird'); -var events = require('events'); -var stream = require('stream'); -var path = require('path'); -var fs = require('fs'); -var net = require('net'); -var byline = require('byline'); -var util = require('util'); -var readline = require('readline'); -var sprintf = require('sprintf').sprintf; -var utf8 = require('utf8'); -var wrench = require('wrench'); // https://github.com/ryanmcgrath/wrench-js -var yaml = require('yamljs'); - -// Command line options (defaults here, overwritten if necessary) -var optTargetHost = '127.0.0.1'; -var optTargetPort = 9091; -var optHttpPort = 9092; -var optJsonProxyPort = 9093; -var optJsonProxy = false; -var optSourceSearchDirs = [ '../tests/ecmascript' ]; -var optDumpDebugRead = null; -var optDumpDebugWrite = null; -var optDumpDebugPretty = null; -var optLogMessages = false; - -// Constants -var UI_MESSAGE_CLIPLEN = 128; -var LOCALS_CLIPLEN = 64; -var EVAL_CLIPLEN = 4096; -var GETVAR_CLIPLEN = 4096; - -// Commands initiated by Duktape -var CMD_STATUS = 0x01; -var CMD_PRINT = 0x02; -var CMD_ALERT = 0x03; -var CMD_LOG = 0x04; - -// Commands initiated by the debug client (= us) -var CMD_BASICINFO = 0x10; -var CMD_TRIGGERSTATUS = 0x11; -var CMD_PAUSE = 0x12; -var CMD_RESUME = 0x13; -var CMD_STEPINTO = 0x14; -var CMD_STEPOVER = 0x15; -var CMD_STEPOUT = 0x16; -var CMD_LISTBREAK = 0x17; -var CMD_ADDBREAK = 0x18; -var CMD_DELBREAK = 0x19; -var CMD_GETVAR = 0x1a; -var CMD_PUTVAR = 0x1b; -var CMD_GETCALLSTACK = 0x1c; -var CMD_GETLOCALS = 0x1d; -var CMD_EVAL = 0x1e; -var CMD_DETACH = 0x1f; -var CMD_DUMPHEAP = 0x20; -var CMD_GETBYTECODE = 0x21; - -// Errors -var ERR_UNKNOWN = 0x00; -var ERR_UNSUPPORTED = 0x01; -var ERR_TOOMANY = 0x02; -var ERR_NOTFOUND = 0x03; - -// Marker objects for special protocol values -var DVAL_EOM = { type: 'eom' }; -var DVAL_REQ = { type: 'req' }; -var DVAL_REP = { type: 'rep' }; -var DVAL_ERR = { type: 'err' }; -var DVAL_NFY = { type: 'nfy' }; - -// String map for commands (debug dumping). A single map works (instead of -// separate maps for each direction) because command numbers don't currently -// overlap. -var debugCommandNames = yaml.load('duk_debugcommands.yaml'); - -// Map debug command names to numbers. -var debugCommandNumbers = {}; -debugCommandNames.forEach(function (k, i) { - debugCommandNumbers[k] = i; -}); - -// Duktape heaphdr type constants, must match C headers -var DUK_HTYPE_STRING = 1; -var DUK_HTYPE_OBJECT = 2; -var DUK_HTYPE_BUFFER = 3; - -// Duktape internal class numbers, must match C headers -var dukClassNames = yaml.load('duk_classnames.yaml'); - -// Bytecode opcode/extraop metadata -var dukOpcodes = yaml.load('duk_opcodes.yaml') -if (dukOpcodes.opcodes.length != 64) { - throw new Error('opcode metadata length incorrect'); -} -if (dukOpcodes.extra.length != 256) { - throw new Error('extraop metadata length incorrect'); -} - -/* - * Miscellaneous helpers - */ - -var nybbles = '0123456789abcdef'; - -/* Convert a buffer into a string using Unicode codepoints U+0000...U+00FF. - * This is the NodeJS 'binary' encoding, but since it's being deprecated, - * reimplement it here. We need to avoid parsing strings as e.g. UTF-8: - * although Duktape strings are usually UTF-8/CESU-8 that's not always the - * case, e.g. for internal strings. Buffer values are also represented as - * strings in the debug protocol, so we must deal accurately with arbitrary - * byte arrays. - */ -function bufferToDebugString(buf) { - var cp = []; - var i, n; - -/* - // This fails with "RangeError: Maximum call stack size exceeded" for some - // reason, so use a much slower variant. - - for (i = 0, n = buf.length; i < n; i++) { - cp[i] = buf[i]; - } - - return String.fromCharCode.apply(String, cp); -*/ - - for (i = 0, n = buf.length; i < n; i++) { - cp[i] = String.fromCharCode(buf[i]); - } - - return cp.join(''); -} - -/* Write a string into a buffer interpreting codepoints U+0000...U+00FF - * as bytes. Drop higher bits. - */ -function writeDebugStringToBuffer(str, buf, off) { - var i, n; - - for (i = 0, n = str.length; i < n; i++) { - buf[off + i] = str.charCodeAt(i) & 0xff; - } -} - -/* Encode an ordinary Unicode string into a dvalue compatible format, i.e. - * into a byte array represented as codepoints U+0000...U+00FF. Concretely, - * encode with UTF-8 and then represent the bytes with U+0000...U+00FF. - */ -function stringToDebugString(str) { - return utf8.encode(str); -} - -/* Pretty print a dvalue. Useful for dumping etc. */ -function prettyDebugValue(x) { - if (typeof x === 'object' && x !== null) { - if (x.type === 'eom') { - return 'EOM'; - } else if (x.type === 'req') { - return 'REQ'; - } else if (x.type === 'rep') { - return 'REP'; - } else if (x.type === 'err') { - return 'ERR'; - } else if (x.type === 'nfy') { - return 'NFY'; - } - } - return JSON.stringify(x); -} - -/* Pretty print a number for UI usage. Types and values should be easy to - * read and typing should be obvious. For numbers, support Infinity, NaN, - * and signed zeroes properly. - */ -function prettyUiNumber(x) { - if (x === 1/0) { return 'Infinity'; } - if (x === -1/0) { return '-Infinity'; } - if (Number.isNaN(x)) { return 'NaN'; } - if (x === 0 && 1/x > 0) { return '0'; } - if (x === 0 && 1/x < 0) { return '-0'; } - return x.toString(); -} - -/* Pretty print a dvalue string (bytes represented as U+0000...U+00FF) - * for UI usage. Try UTF-8 decoding to get a nice Unicode string (JSON - * encoded) but if that fails, ensure that bytes are encoded transparently. - * The result is a quoted string with a special quote marker for a "raw" - * string when UTF-8 decoding fails. Very long strings are optionally - * clipped. - */ -function prettyUiString(x, cliplen) { - var ret; - - if (typeof x !== 'string') { - throw new Error('invalid input to prettyUiString: ' + typeof x); - } - try { - // Here utf8.decode() is better than decoding using NodeJS buffer - // operations because we want strict UTF-8 interpretation. - ret = JSON.stringify(utf8.decode(x)); - } catch (e) { - // When we fall back to representing bytes, indicate that the string - // is "raw" with a 'r"' prefix (a somewhat arbitrary convention). - // U+0022 = ", U+0027 = ' - ret = 'r"' + x.replace(/[\u0022\u0027\u0000-\u001f\u0080-\uffff]/g, function (match) { - var cp = match.charCodeAt(0); - return '\\x' + nybbles[(cp >> 4) & 0x0f] + nybbles[cp & 0x0f]; - }) + '"'; - } - - if (cliplen && ret.length > cliplen) { - ret = ret.substring(0, cliplen) + '...'; // trailing '"' intentionally missing - } - return ret; -} - -/* Pretty print a dvalue string (bytes represented as U+0000...U+00FF) - * for UI usage without quotes. - */ -function prettyUiStringUnquoted(x, cliplen) { - var ret; - - if (typeof x !== 'string') { - throw new Error('invalid input to prettyUiStringUnquoted: ' + typeof x); - } - - try { - // Here utf8.decode() is better than decoding using NodeJS buffer - // operations because we want strict UTF-8 interpretation. - - // XXX: unprintable characters etc? In some UI cases we'd want to - // e.g. escape newlines and in others not. - ret = utf8.decode(x); - } catch (e) { - // For the unquoted version we don't need to escape single or double - // quotes. - ret = x.replace(/[\u0000-\u001f\u0080-\uffff]/g, function (match) { - var cp = match.charCodeAt(0); - return '\\x' + nybbles[(cp >> 4) & 0x0f] + nybbles[cp & 0x0f]; - }); - } - - if (cliplen && ret.length > cliplen) { - ret = ret.substring(0, cliplen) + '...'; - } - return ret; -} - -/* Pretty print a dvalue for UI usage. Everything comes out as a ready-to-use - * string. - * - * XXX: Currently the debug client formats all values for UI use. A better - * solution would be to pass values in typed form and let the UI format them, - * so that styling etc. could take typing into account. - */ -function prettyUiDebugValue(x, cliplen) { - if (typeof x === 'object' && x !== null) { - // Note: typeof null === 'object', so null special case explicitly - if (x.type === 'eom') { - return 'EOM'; - } else if (x.type === 'req') { - return 'REQ'; - } else if (x.type === 'rep') { - return 'REP'; - } else if (x.type === 'err') { - return 'ERR'; - } else if (x.type === 'nfy') { - return 'NFY'; - } else if (x.type === 'unused') { - return 'unused'; - } else if (x.type === 'undefined') { - return 'undefined'; - } else if (x.type === 'buffer') { - return '|' + x.data + '|'; - } else if (x.type === 'object') { - return '[object ' + (dukClassNames[x.class] || ('class ' + x.class)) + ' ' + x.pointer + ']'; - } else if (x.type === 'pointer') { - return ''; - } else if (x.type === 'lightfunc') { - return ''; - } else if (x.type === 'number') { - // duk_tval number, any IEEE double - var tmp = new Buffer(x.data, 'hex'); // decode into hex - var val = tmp.readDoubleBE(0); // big endian ieee double - return prettyUiNumber(val); - } - } else if (x === null) { - return 'null'; - } else if (typeof x === 'boolean') { - return x ? 'true' : 'false'; - } else if (typeof x === 'string') { - return prettyUiString(x, cliplen); - } else if (typeof x === 'number') { - // Debug protocol integer - return prettyUiNumber(x); - } - - // We shouldn't come here, but if we do, JSON is a reasonable default. - return JSON.stringify(x); -} - -/* Pretty print a debugger message given as an array of parsed dvalues. - * Result should be a pure ASCII one-liner. - */ -function prettyDebugMessage(msg) { - return msg.map(prettyDebugValue).join(' '); -} - -/* Pretty print a debugger command. */ -function prettyDebugCommand(cmd) { - return debugCommandNames[cmd] || String(cmd); -} - -/* Decode and normalize source file contents: UTF-8, tabs to 8, - * CR LF to LF. - */ -function decodeAndNormalizeSource(data) { - var tmp; - var lines, line, repl; - var i, n; - var j, m; - - try { - tmp = data.toString('utf8'); - } catch (e) { - console.log('Failed to UTF-8 decode source file, ignoring: ' + e); - tmp = String(data); - } - - lines = tmp.split(/\r?\n/); - for (i = 0, n = lines.length; i < n; i++) { - line = lines[i]; - if (/\t/.test(line)) { - repl = ''; - for (j = 0, m = line.length; j < m; j++) { - if (line.charAt(j) === '\t') { - repl += ' '; - while ((repl.length % 8) != 0) { - repl += ' '; - } - } else { - repl += line.charAt(j); - } - } - lines[i] = repl; - } - } - - // XXX: normalize last newline (i.e. force a newline if contents don't - // end with a newline)? - - return lines.join('\n'); -} - -/* Token bucket rate limiter for a given callback. Calling code calls - * trigger() to request 'cb' to be called, and the rate limiter ensures - * that 'cb' is not called too often. - */ -function RateLimited(tokens, rate, cb) { - var _this = this; - this.maxTokens = tokens; - this.tokens = this.maxTokens; - this.rate = rate; - this.cb = cb; - this.delayedCb = false; - - // Right now the implementation is setInterval-based, but could also be - // made timerless. There are so few rate limited resources that this - // doesn't matter in practice. - - this.tokenAdder = setInterval(function () { - if (_this.tokens < _this.maxTokens) { - _this.tokens++; - } - if (_this.delayedCb) { - _this.delayedCb = false; - _this.tokens--; - _this.cb(); - } - }, this.rate); -} -RateLimited.prototype.trigger = function () { - if (this.tokens > 0) { - this.tokens--; - this.cb(); - } else { - this.delayedCb = true; - } -}; - -/* - * Source file manager - * - * Scan the list of search directories for Ecmascript source files and - * build an index of them. Provides a mechanism to find a source file - * based on a raw 'fileName' property provided by the debug target, and - * to provide a file list for the web UI. - * - * NOTE: it's tempting to do loose matching for filenames, but this does - * not work in practice. Filenames must match 1:1 with the debug target - * so that e.g. breakpoints assigned based on filenames found from the - * search paths will match 1:1 on the debug target. If this is not the - * case, breakpoints won't work as expected. - */ - -function SourceFileManager(directories) { - this.directories = directories; - this.extensions = { '.js': true, '.jsm': true }; - this.files; -} - -SourceFileManager.prototype.scan = function () { - var _this = this; - var fileMap = {}; // absFn -> true - var files; - - this.directories.forEach(function (dir) { - console.log('Scanning source files: ' + dir); - try { - wrench.readdirSyncRecursive(dir).forEach(function (fn) { - var absFn = path.normalize(path.join(dir, fn)); // './foo/bar.js' -> 'foo/bar.js' - var ent; - - if (fs.existsSync(absFn) && - fs.lstatSync(absFn).isFile() && - _this.extensions[path.extname(fn)]) { - // We want the fileMap to contain the filename relative to - // the search dir root. - fileMap[fn] = true; - } - }); - } catch (e) { - console.log('Failed to scan ' + dir + ': ' + e); - } - }); - - files = Object.keys(fileMap); - files.sort(); - this.files = files; - - console.log('Found ' + files.length + ' source files in ' + this.directories.length + ' search directories'); -}; - -SourceFileManager.prototype.getFiles = function () { - return this.files; -}; - -SourceFileManager.prototype.search = function (fileName) { - var _this = this; - - // Loose matching is tempting but counterproductive: filenames must - // match 1:1 between the debug client and the debug target for e.g. - // breakpoints to work as expected. Note that a breakpoint may be - // assigned by selecting a file from a dropdown populated by scanning - // the filesystem for available sources and there's no way of knowing - // if the debug target uses the exact same name. - - function tryLookup() { - var i, fn, data; - - for (i = 0; i < _this.directories.length; i++) { - fn = path.join(_this.directories[i], fileName); - if (fs.existsSync(fn) && fs.lstatSync(fn).isFile()) { - data = fs.readFileSync(fn); // Raw bytes - return decodeAndNormalizeSource(data); // Unicode string - } - } - return null; - } - - return tryLookup(fileName); -}; - -/* - * Debug protocol parser - * - * The debug protocol parser is an EventEmitter which parses debug messages - * from an input stream and emits 'debug-message' events for completed - * messages ending in an EOM. The parser also provides debug dumping, stream - * logging functionality, and statistics gathering functionality. - * - * This parser is used to parse both incoming and outgoing messages. For - * outgoing messages the only function is to validate and debug dump the - * messages we're about to send. The downside of dumping at this low level - * is that we can't match request and reply/error messages here. - * - * http://www.sitepoint.com/nodejs-events-and-eventemitter/ - */ - -function DebugProtocolParser(inputStream, - protocolVersion, - rawDumpFileName, - textDumpFileName, - textDumpFilePrefix, - hexDumpConsolePrefix, - textDumpConsolePrefix) { - var _this = this; - this.inputStream = inputStream; - this.closed = false; // stream is closed/broken, don't parse anymore - this.bytes = 0; - this.dvalues = 0; - this.messages = 0; - this.requests = 0; - this.prevBytes = 0; - this.bytesPerSec = 0; - this.statsTimer = null; - this.readableNumberValue = true; - - events.EventEmitter.call(this); - - var buf = new Buffer(0); // accumulate data - var msg = []; // accumulated message until EOM - var versionIdentification; - - var statsInterval = 2000; - var statsIntervalSec = statsInterval / 1000; - this.statsTimer = setInterval(function () { - _this.bytesPerSec = (_this.bytes - _this.prevBytes) / statsIntervalSec; - _this.prevBytes = _this.bytes; - _this.emit('stats-update'); - }, statsInterval); - - function consume(n) { - var tmp = new Buffer(buf.length - n); - buf.copy(tmp, 0, n); - buf = tmp; - } - - inputStream.on('data', function (data) { - var i, n, x, v, gotValue, len, t, tmpbuf, verstr; - var prettyMsg; - - if (_this.closed || !_this.inputStream) { - console.log('Ignoring incoming data from closed input stream, len ' + data.length); - return; - } - - _this.bytes += data.length; - if (rawDumpFileName) { - fs.appendFileSync(rawDumpFileName, data); - } - if (hexDumpConsolePrefix) { - console.log(hexDumpConsolePrefix + data.toString('hex')); - } - - buf = Buffer.concat([ buf, data ]); - - // Protocol version handling. When dumping an output stream, the - // caller gives a non-null protocolVersion so we don't read one here. - if (protocolVersion == null) { - if (buf.length > 1024) { - _this.emit('transport-error', 'Parse error (version identification too long), dropping connection'); - _this.close(); - return; - } - - for (i = 0, n = buf.length; i < n; i++) { - if (buf[i] == 0x0a) { - tmpbuf = new Buffer(i); - buf.copy(tmpbuf, 0, 0, i); - consume(i + 1); - verstr = tmpbuf.toString('utf-8'); - t = verstr.split(' '); - protocolVersion = Number(t[0]); - versionIdentification = verstr; - - _this.emit('protocol-version', { - protocolVersion: protocolVersion, - versionIdentification: versionIdentification - }); - break; - } - } - - if (protocolVersion == null) { - // Still waiting for version identification to complete. - return; - } - } - - // Parse complete dvalues (quite inefficient now) by trial parsing. - // Consume a value only when it's fully present in 'buf'. - // See doc/debugger.rst for format description. - - while (buf.length > 0) { - x = buf[0]; - v = undefined; - gotValue = false; // used to flag special values like undefined - - if (x >= 0xc0) { - // 0xc0...0xff: integers 0-16383 - if (buf.length >= 2) { - v = ((x - 0xc0) << 8) + buf[1]; - consume(2); - } - } else if (x >= 0x80) { - // 0x80...0xbf: integers 0-63 - v = x - 0x80; - consume(1); - } else if (x >= 0x60) { - // 0x60...0x7f: strings with length 0-31 - len = x - 0x60; - if (buf.length >= 1 + len) { - v = new Buffer(len); - buf.copy(v, 0, 1, 1 + len); - v = bufferToDebugString(v); - consume(1 + len); - } - } else { - switch (x) { - case 0x00: v = DVAL_EOM; consume(1); break; - case 0x01: v = DVAL_REQ; consume(1); break; - case 0x02: v = DVAL_REP; consume(1); break; - case 0x03: v = DVAL_ERR; consume(1); break; - case 0x04: v = DVAL_NFY; consume(1); break; - case 0x10: // 4-byte signed integer - if (buf.length >= 5) { - v = buf.readInt32BE(1); - consume(5); - } - break; - case 0x11: // 4-byte string - if (buf.length >= 5) { - len = buf.readUInt32BE(1); - if (buf.length >= 5 + len) { - v = new Buffer(len); - buf.copy(v, 0, 5, 5 + len); - v = bufferToDebugString(v); - consume(5 + len); - } - } - break; - case 0x12: // 2-byte string - if (buf.length >= 3) { - len = buf.readUInt16BE(1); - if (buf.length >= 3 + len) { - v = new Buffer(len); - buf.copy(v, 0, 3, 3 + len); - v = bufferToDebugString(v); - consume(3 + len); - } - } - break; - case 0x13: // 4-byte buffer - if (buf.length >= 5) { - len = buf.readUInt32BE(1); - if (buf.length >= 5 + len) { - v = new Buffer(len); - buf.copy(v, 0, 5, 5 + len); - v = { type: 'buffer', data: v.toString('hex') }; - consume(5 + len); - // Value could be a Node.js buffer directly, but - // we prefer all dvalues to be JSON compatible - } - } - break; - case 0x14: // 2-byte buffer - if (buf.length >= 3) { - len = buf.readUInt16BE(1); - if (buf.length >= 3 + len) { - v = new Buffer(len); - buf.copy(v, 0, 3, 3 + len); - v = { type: 'buffer', data: v.toString('hex') }; - consume(3 + len); - // Value could be a Node.js buffer directly, but - // we prefer all dvalues to be JSON compatible - } - } - break; - case 0x15: // unused/none - v = { type: 'unused' }; - consume(1); - break; - case 0x16: // undefined - v = { type: 'undefined' }; - gotValue = true; // indicate 'v' is actually set - consume(1); - break; - case 0x17: // null - v = null; - gotValue = true; // indicate 'v' is actually set - consume(1); - break; - case 0x18: // true - v = true; - consume(1); - break; - case 0x19: // false - v = false; - consume(1); - break; - case 0x1a: // number (IEEE double), big endian - if (buf.length >= 9) { - v = new Buffer(8); - buf.copy(v, 0, 1, 9); - v = { type: 'number', data: v.toString('hex') } - - if (_this.readableNumberValue) { - // The _value key should not be used programmatically, - // it is just there to make the dumps more readable. - v._value = buf.readDoubleBE(1); - } - consume(9); - } - break; - case 0x1b: // object - if (buf.length >= 3) { - len = buf[2]; - if (buf.length >= 3 + len) { - v = new Buffer(len); - buf.copy(v, 0, 3, 3 + len); - v = { type: 'object', 'class': buf[1], pointer: v.toString('hex') }; - consume(3 + len); - } - } - break; - case 0x1c: // pointer - if (buf.length >= 2) { - len = buf[1]; - if (buf.length >= 2 + len) { - v = new Buffer(len); - buf.copy(v, 0, 2, 2 + len); - v = { type: 'pointer', pointer: v.toString('hex') }; - consume(2 + len); - } - } - break; - case 0x1d: // lightfunc - if (buf.length >= 4) { - len = buf[3]; - if (buf.length >= 4 + len) { - v = new Buffer(len); - buf.copy(v, 0, 4, 4 + len); - v = { type: 'lightfunc', flags: buf.readUInt16BE(1), pointer: v.toString('hex') }; - consume(4 + len); - } - } - break; - case 0x1e: // heapptr - if (buf.length >= 2) { - len = buf[1]; - if (buf.length >= 2 + len) { - v = new Buffer(len); - buf.copy(v, 0, 2, 2 + len); - v = { type: 'heapptr', pointer: v.toString('hex') }; - consume(2 + len); - } - } - break; - default: - _this.emit('transport-error', 'Parse error, dropping connection'); - _this.close(); - } - } - - if (typeof v === 'undefined' && !gotValue) { - break; - } - msg.push(v); - _this.dvalues++; - - // Could emit a 'debug-value' event here, but that's not necessary - // because the receiver will just collect statistics which can also - // be done using the finished message. - - if (v === DVAL_EOM) { - _this.messages++; - - if (textDumpFileName || textDumpConsolePrefix) { - prettyMsg = prettyDebugMessage(msg); - if (textDumpFileName) { - fs.appendFileSync(textDumpFileName, (textDumpFilePrefix || '') + prettyMsg + '\n'); - } - if (textDumpConsolePrefix) { - console.log(textDumpConsolePrefix + prettyMsg); - } - } - - _this.emit('debug-message', msg); - msg = []; // new object, old may be in circulation for a while - } - } - }); - - // Not all streams will emit this. - inputStream.on('error', function (err) { - _this.emit('transport-error', err); - _this.close(); - }); - - // Not all streams will emit this. - inputStream.on('close', function () { - _this.close(); - }); -} -DebugProtocolParser.prototype = Object.create(events.EventEmitter.prototype); - -DebugProtocolParser.prototype.close = function () { - // Although the underlying transport may not have a close() or destroy() - // method or even a 'close' event, this method is always available and - // will generate a 'transport-close'. - // - // The caller is responsible for closing the underlying stream if that - // is necessary. - - if (this.closed) { return; } - - this.closed = true; - if (this.statsTimer) { - clearInterval(this.statsTimer); - this.statsTimer = null; - } - this.emit('transport-close'); -}; - -/* - * Debugger output formatting - */ - -function formatDebugValue(v) { - var buf, dec, len; - - // See doc/debugger.rst for format description. - - if (typeof v === 'object' && v !== null) { - // Note: typeof null === 'object', so null special case explicitly - if (v.type === 'eom') { - return new Buffer([ 0x00 ]); - } else if (v.type === 'req') { - return new Buffer([ 0x01 ]); - } else if (v.type === 'rep') { - return new Buffer([ 0x02 ]); - } else if (v.type === 'err') { - return new Buffer([ 0x03 ]); - } else if (v.type === 'nfy') { - return new Buffer([ 0x04 ]); - } else if (v.type === 'unused') { - return new Buffer([ 0x15 ]); - } else if (v.type === 'undefined') { - return new Buffer([ 0x16 ]); - } else if (v.type === 'number') { - dec = new Buffer(v.data, 'hex'); - len = dec.length; - if (len !== 8) { - throw new TypeError('value cannot be converted to dvalue: ' + JSON.stringify(v)); - } - buf = new Buffer(1 + len); - buf[0] = 0x1a; - dec.copy(buf, 1); - return buf; - } else if (v.type === 'buffer') { - dec = new Buffer(v.data, 'hex'); - len = dec.length; - if (len <= 0xffff) { - buf = new Buffer(3 + len); - buf[0] = 0x14; - buf[1] = (len >> 8) & 0xff; - buf[2] = (len >> 0) & 0xff; - dec.copy(buf, 3); - return buf; - } else { - buf = new Buffer(5 + len); - buf[0] = 0x13; - buf[1] = (len >> 24) & 0xff; - buf[2] = (len >> 16) & 0xff; - buf[3] = (len >> 8) & 0xff; - buf[4] = (len >> 0) & 0xff; - dec.copy(buf, 5); - return buf; - } - } else if (v.type === 'object') { - dec = new Buffer(v.pointer, 'hex'); - len = dec.length; - buf = new Buffer(3 + len); - buf[0] = 0x1b; - buf[1] = v.class; - buf[2] = len; - dec.copy(buf, 3); - return buf; - } else if (v.type === 'pointer') { - dec = new Buffer(v.pointer, 'hex'); - len = dec.length; - buf = new Buffer(2 + len); - buf[0] = 0x1c; - buf[1] = len; - dec.copy(buf, 2); - return buf; - } else if (v.type === 'lightfunc') { - dec = new Buffer(v.pointer, 'hex'); - len = dec.length; - buf = new Buffer(4 + len); - buf[0] = 0x1d; - buf[1] = (v.flags >> 8) & 0xff; - buf[2] = v.flags & 0xff; - buf[3] = len; - dec.copy(buf, 4); - return buf; - } else if (v.type === 'heapptr') { - dec = new Buffer(v.pointer, 'hex'); - len = dec.length; - buf = new Buffer(2 + len); - buf[0] = 0x1e; - buf[1] = len; - dec.copy(buf, 2); - return buf; - } - } else if (v === null) { - return new Buffer([ 0x17 ]); - } else if (typeof v === 'boolean') { - return new Buffer([ v ? 0x18 : 0x19 ]); - } else if (typeof v === 'number') { - if (Math.floor(v) === v && /* whole */ - (v !== 0 || 1 / v > 0) && /* not negative zero */ - v >= -0x80000000 && v <= 0x7fffffff) { - // Represented signed 32-bit integers as plain integers. - // Debugger code expects this for all fields that are not - // duk_tval representations (e.g. command numbers and such). - if (v >= 0x00 && v <= 0x3f) { - return new Buffer([ 0x80 + v ]); - } else if (v >= 0x0000 && v <= 0x3fff) { - return new Buffer([ 0xc0 + (v >> 8), v & 0xff ]); - } else if (v >= -0x80000000 && v <= 0x7fffffff) { - return new Buffer([ 0x10, - (v >> 24) & 0xff, - (v >> 16) & 0xff, - (v >> 8) & 0xff, - (v >> 0) & 0xff ]); - } else { - throw new Error('internal error when encoding integer to dvalue: ' + v); - } - } else { - // Represent non-integers as IEEE double dvalues - buf = new Buffer(1 + 8); - buf[0] = 0x1a; - buf.writeDoubleBE(v, 1); - return buf; - } - } else if (typeof v === 'string') { - if (v.length < 0 || v.length > 0xffffffff) { - // Not possible in practice. - throw new TypeError('cannot convert to dvalue, invalid string length: ' + v.length); - } - if (v.length <= 0x1f) { - buf = new Buffer(1 + v.length); - buf[0] = 0x60 + v.length; - writeDebugStringToBuffer(v, buf, 1); - return buf; - } else if (v.length <= 0xffff) { - buf = new Buffer(3 + v.length); - buf[0] = 0x12; - buf[1] = (v.length >> 8) & 0xff; - buf[2] = (v.length >> 0) & 0xff; - writeDebugStringToBuffer(v, buf, 3); - return buf; - } else { - buf = new Buffer(5 + v.length); - buf[0] = 0x11; - buf[1] = (v.length >> 24) & 0xff; - buf[2] = (v.length >> 16) & 0xff; - buf[3] = (v.length >> 8) & 0xff; - buf[4] = (v.length >> 0) & 0xff; - writeDebugStringToBuffer(v, buf, 5); - return buf; - } - } - - // Shouldn't come here. - throw new TypeError('value cannot be converted to dvalue: ' + JSON.stringify(v)); -} - -/* - * Debugger implementation - * - * A debugger instance communicates with the debug target and maintains - * persistent debug state so that the current state can be resent to the - * socket.io client (web UI) if it reconnects. Whenever the debugger state - * is changed an event is generated. The socket.io handler will listen to - * state change events and push the necessary updates to the web UI, often - * in a rate limited fashion or using a client pull to ensure the web UI - * is not overloaded. - * - * The debugger instance assumes that if the debug protocol connection is - * re-established, it is always to the same target. There is no separate - * abstraction for a debugger session. - */ - -function Debugger() { - events.EventEmitter.call(this); - - this.web = null; // web UI singleton - this.targetStream = null; // transport connection to target - this.outputPassThroughStream = null; // dummy passthrough for message dumping - this.inputParser = null; // parser for incoming debug messages - this.outputParser = null; // parser for outgoing debug messages (stats, dumping) - this.protocolVersion = null; - this.dukVersion = null; - this.dukGitDescribe = null; - this.targetInfo = null; - this.attached = false; - this.handshook = false; - this.reqQueue = null; - this.stats = { // stats for current debug connection - rxBytes: 0, rxDvalues: 0, rxMessages: 0, rxBytesPerSec: 0, - txBytes: 0, txDvalues: 0, txMessages: 0, txBytesPerSec: 0 - }; - this.execStatus = { - attached: false, - state: 'detached', - fileName: '', - funcName: '', - line: 0, - pc: 0 - }; - this.breakpoints = []; - this.callstack = []; - this.locals = []; - this.messageLines = []; - this.messageScrollBack = 100; -} -Debugger.prototype = events.EventEmitter.prototype; - -Debugger.prototype.decodeBytecodeFromBuffer = function (buf, consts, funcs) { - var i, j, n, m, ins, pc; - var res = []; - var op, str, args, comments; - - // XXX: add constants inline to preformatted output (e.g. for strings, - // add a short escaped snippet as a comment on the line after the - // compact argument list). - - for (i = 0, n = buf.length; i < n; i += 4) { - pc = i / 4; - - // shift forces unsigned - if (this.endianness === 'little') { - ins = buf.readInt32LE(i) >>> 0; - } else { - ins = buf.readInt32BE(i) >>> 0; - } - - op = dukOpcodes.opcodes[ins & 0x3f]; - if (op.extra) { - op = dukOpcodes.extra[(ins >> 6) & 0xff]; - } - - args = []; - comments = []; - if (op.args) { - for (j = 0, m = op.args.length; j < m; j++) { - switch(op.args[j]) { - case 'A_R': args.push('r' + ((ins >>> 6) & 0xff)); break; - case 'A_RI': args.push('r' + ((ins >>> 6) & 0xff) + '(indirect)'); break; - case 'A_C': args.push('c' + ((ins >>> 6) & 0xff)); break; - case 'A_H': args.push('0x' + ((ins >>> 6) & 0xff).toString(16)); break; - case 'A_I': args.push(((ins >>> 6) & 0xff).toString(10)); break; - case 'A_B': args.push(((ins >>> 6) & 0xff) ? 'true' : 'false'); break; - case 'B_RC': args.push((ins & (1 << 22) ? 'c' : 'r') + ((ins >>> 14) & 0x0ff)); break; - case 'B_R': args.push('r' + ((ins >>> 14) & 0x1ff)); break; - case 'B_RI': args.push('r' + ((ins >>> 14) & 0x1ff) + '(indirect)'); break; - case 'B_C': args.push('c' + ((ins >>> 14) & 0x1ff)); break; - case 'B_H': args.push('0x' + ((ins >>> 14) & 0x1ff).toString(16)); break; - case 'B_I': args.push(((ins >>> 14) & 0x1ff).toString(10)); break; - case 'C_RC': args.push((ins & (1 << 31) ? 'c' : 'r') + ((ins >>> 23) & 0x0ff)); break; - case 'C_R': args.push('r' + ((ins >>> 23) & 0x1ff)); break; - case 'C_RI': args.push('r' + ((ins >>> 23) & 0x1ff) + '(indirect)'); break; - case 'C_C': args.push('c' + ((ins >>> 23) & 0x1ff)); break; - case 'C_H': args.push('0x' + ((ins >>> 23) & 0x1ff).toString(16)); break; - case 'C_I': args.push(((ins >>> 23) & 0x1ff).toString(10)); break; - case 'BC_R': args.push('r' + ((ins >>> 14) & 0x3ffff)); break; - case 'BC_C': args.push('c' + ((ins >>> 14) & 0x3ffff)); break; - case 'BC_H': args.push('0x' + ((ins >>> 14) & 0x3ffff).toString(16)); break; - case 'BC_I': args.push(((ins >>> 14) & 0x3ffff).toString(10)); break; - case 'ABC_H': args.push(((ins >>> 6) & 0x03ffffff).toString(16)); break; - case 'ABC_I': args.push(((ins >>> 6) & 0x03ffffff).toString(10)); break; - case 'BC_LDINT': args.push(((ins >>> 14) & 0x3ffff) - (1 << 17)); break; - case 'BC_LDINTX': args.push(((ins >>> 14) & 0x3ffff) - 0); break; // no bias in LDINTX - case 'ABC_JUMP': { - var pc_add = ((ins >>> 6) & 0x03ffffff) - (1 << 25) + 1; // pc is preincremented before adding - var pc_dst = pc + pc_add; - args.push(pc_dst + ' (' + (pc_add >= 0 ? '+' : '') + pc_add + ')'); - break; - } - default: args.push('?'); break; - } - } - } - if (op.flags) { - for (j = 0, m = op.flags.length; j < m; j++) { - if (ins & op.flags[j].mask) { - comments.push(op.flags[j].name); - } - } - } - - if (args.length > 0) { - str = sprintf('%05d %08x %-10s %s', pc, ins, op.name, args.join(', ')); - } else { - str = sprintf('%05d %08x %-10s', pc, ins, op.name); - } - if (comments.length > 0) { - str = sprintf('%-44s ; %s', str, comments.join(', ')); - } - - res.push({ - str: str, - ins: ins - }); - } - - return res; -}; - -Debugger.prototype.uiMessage = function (type, val) { - var msg; - if (typeof type === 'object') { - msg = type; - } else if (typeof type === 'string') { - msg = { type: type, message: val }; - } else { - throw new TypeError('invalid ui message: ' + type); - } - this.messageLines.push(msg); - while (this.messageLines.length > this.messageScrollBack) { - this.messageLines.shift(); - } - this.emit('ui-message-update'); // just trigger a sync, gets rate limited -}; - -Debugger.prototype.sendRequest = function (msg) { - var _this = this; - return new Promise(function (resolve, reject) { - var dvals = []; - var dval; - var data; - var i; - - if (!_this.attached || !_this.handshook || !_this.reqQueue || !_this.targetStream) { - throw new Error('invalid state for sendRequest'); - } - - for (i = 0; i < msg.length; i++) { - try { - dval = formatDebugValue(msg[i]); - } catch (e) { - console.log('Failed to format dvalue, dropping connection: ' + e); - console.log(e.stack || e); - _this.targetStream.destroy(); - throw new Error('failed to format dvalue'); - } - dvals.push(dval); - } - - data = Buffer.concat(dvals); - - _this.targetStream.write(data); - _this.outputPassThroughStream.write(data); // stats and dumping - - if (optLogMessages) { - console.log('Request ' + prettyDebugCommand(msg[1]) + ': ' + prettyDebugMessage(msg)); - } - - if (!_this.reqQueue) { - throw new Error('no reqQueue'); - } - - _this.reqQueue.push({ - reqMsg: msg, - reqCmd: msg[1], - resolveCb: resolve, - rejectCb: reject - }); - }); -}; - -Debugger.prototype.sendBasicInfoRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_BASICINFO, DVAL_EOM ]).then(function (msg) { - _this.dukVersion = msg[1]; - _this.dukGitDescribe = msg[2]; - _this.targetInfo = msg[3]; - _this.endianness = { 1: 'little', 2: 'mixed', 3: 'big' }[msg[4]] || 'unknown'; - _this.emit('basic-info-update'); - return msg; - }); -}; - -Debugger.prototype.sendGetVarRequest = function (varname) { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_GETVAR, varname, DVAL_EOM ]).then(function (msg) { - return { found: msg[1] === 1, value: msg[2] }; - }); -}; - -Debugger.prototype.sendPutVarRequest = function (varname, varvalue) { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_PUTVAR, varname, varvalue, DVAL_EOM ]); -}; - -Debugger.prototype.sendInvalidCommandTestRequest = function () { - // Intentional invalid command - var _this = this; - return this.sendRequest([ DVAL_REQ, 0xdeadbeef, DVAL_EOM ]); -} - -Debugger.prototype.sendStatusRequest = function () { - // Send a status request to trigger a status notify, result is ignored: - // target sends a status notify instead of a meaningful reply - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_TRIGGERSTATUS, DVAL_EOM ]); -} - -Debugger.prototype.sendBreakpointListRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_LISTBREAK, DVAL_EOM ]).then(function (msg) { - var i, n; - var breakpts = []; - - for (i = 1, n = msg.length - 1; i < n; i += 2) { - breakpts.push({ fileName: msg[i], lineNumber: msg[i + 1] }); - } - - _this.breakpoints = breakpts; - _this.emit('breakpoints-update'); - return msg; - }); -}; - -Debugger.prototype.sendGetLocalsRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_GETLOCALS, DVAL_EOM ]).then(function (msg) { - var i; - var locals = []; - - for (i = 1; i <= msg.length - 2; i += 2) { - // XXX: do pretty printing in debug client for now - locals.push({ key: msg[i], value: prettyUiDebugValue(msg[i + 1], LOCALS_CLIPLEN) }); - } - - _this.locals = locals; - _this.emit('locals-update'); - return msg; - }); -}; - -Debugger.prototype.sendGetCallStackRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_GETCALLSTACK, DVAL_EOM ]).then(function (msg) { - var i; - var stack = []; - - for (i = 1; i + 3 <= msg.length - 1; i += 4) { - stack.push({ - fileName: msg[i], - funcName: msg[i + 1], - lineNumber: msg[i + 2], - pc: msg[i + 3] - }); - } - - _this.callstack = stack; - _this.emit('callstack-update'); - return msg; - }); -}; - -Debugger.prototype.sendStepIntoRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_STEPINTO, DVAL_EOM ]); -}; - -Debugger.prototype.sendStepOverRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_STEPOVER, DVAL_EOM ]); -}; - -Debugger.prototype.sendStepOutRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_STEPOUT, DVAL_EOM ]); -}; - -Debugger.prototype.sendPauseRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_PAUSE, DVAL_EOM ]); -}; - -Debugger.prototype.sendResumeRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_RESUME, DVAL_EOM ]); -}; - -Debugger.prototype.sendEvalRequest = function (evalInput) { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_EVAL, evalInput, DVAL_EOM ]).then(function (msg) { - return { error: msg[1] === 1 /*error*/, value: msg[2] }; - }); -}; - -Debugger.prototype.sendDetachRequest = function () { - var _this = this; - return this.sendRequest([ DVAL_REQ, CMD_DETACH, DVAL_EOM ]); -}; - -Debugger.prototype.sendDumpHeapRequest = function () { - var _this = this; - - return this.sendRequest([ DVAL_REQ, CMD_DUMPHEAP, DVAL_EOM ]).then(function (msg) { - var res = {}; - var objs = []; - var i, j, n, m, o, prop; - - res.type = 'heapDump'; - res.heapObjects = objs; - - for (i = 1, n = msg.length - 1; i < n; /*nop*/) { - o = {}; - o.ptr = msg[i++]; - o.type = msg[i++]; - o.flags = msg[i++] >>> 0; /* unsigned */ - o.refc = msg[i++]; - - if (o.type === DUK_HTYPE_STRING) { - o.blen = msg[i++]; - o.clen = msg[i++]; - o.hash = msg[i++] >>> 0; /* unsigned */ - o.data = msg[i++]; - } else if (o.type === DUK_HTYPE_BUFFER) { - o.len = msg[i++]; - o.data = msg[i++]; - } else if (o.type === DUK_HTYPE_OBJECT) { - o['class'] = msg[i++]; - o.proto = msg[i++]; - o.esize = msg[i++]; - o.enext = msg[i++]; - o.asize = msg[i++]; - o.hsize = msg[i++]; - o.props = []; - for (j = 0, m = o.enext; j < m; j++) { - prop = {}; - prop.flags = msg[i++]; - prop.key = msg[i++]; - prop.accessor = (msg[i++] == 1); - if (prop.accessor) { - prop.getter = msg[i++]; - prop.setter = msg[i++]; - } else { - prop.value = msg[i++]; - } - o.props.push(prop); - } - o.array = []; - for (j = 0, m = o.asize; j < m; j++) { - prop = {}; - prop.value = msg[i++]; - o.array.push(prop); - } - } else { - console.log('invalid htype: ' + o.type + ', disconnect'); - _this.disconnectDebugger(); - throw new Error('invalid htype'); - return; - } - - objs.push(o); - } - - return res; - }); -}; - -Debugger.prototype.sendGetBytecodeRequest = function () { - var _this = this; - - return this.sendRequest([ DVAL_REQ, CMD_GETBYTECODE, DVAL_EOM ]).then(function (msg) { - var idx = 1; - var nconst; - var nfunc; - var val; - var buf; - var i, n; - var consts = []; - var funcs = []; - var bcode; - var preformatted; - var ret; - - //console.log(JSON.stringify(msg)); - - nconst = msg[idx++]; - for (i = 0; i < nconst; i++) { - val = msg[idx++]; - consts.push(val); - } - - nfunc = msg[idx++]; - for (i = 0; i < nfunc; i++) { - val = msg[idx++]; - funcs.push(val); - } - val = msg[idx++]; - - // Right now bytecode is a string containing a direct dump of the - // bytecode in target endianness. Decode here so that the web UI - // doesn't need to. - - buf = new Buffer(val.length); - writeDebugStringToBuffer(val, buf, 0); - bcode = _this.decodeBytecodeFromBuffer(buf, consts, funcs); - - preformatted = []; - consts.forEach(function (v, i) { - preformatted.push('; c' + i + ' ' + JSON.stringify(v)); - }); - preformatted.push(''); - bcode.forEach(function (v) { - preformatted.push(v.str); - }); - preformatted = preformatted.join('\n') + '\n'; - - ret = { - constants: consts, - functions: funcs, - bytecode: bcode, - preformatted: preformatted - }; - - return ret; - }); -}; - -Debugger.prototype.changeBreakpoint = function (fileName, lineNumber, mode) { - var _this = this; - - return this.sendRequest([ DVAL_REQ, CMD_LISTBREAK, DVAL_EOM ]).then(function (msg) { - var i, n; - var breakpts = []; - var deleted = false; - - // Up-to-date list of breakpoints on target - for (i = 1, n = msg.length - 1; i < n; i += 2) { - breakpts.push({ fileName: msg[i], lineNumber: msg[i + 1] }); - } - - // Delete matching breakpoints in reverse order so that indices - // remain valid. We do this for all operations so that duplicates - // are eliminated if present. - for (i = breakpts.length - 1; i >= 0; i--) { - var bp = breakpts[i]; - if (mode === 'deleteall' || (bp.fileName === fileName && bp.lineNumber === lineNumber)) { - deleted = true; - _this.sendRequest([ DVAL_REQ, CMD_DELBREAK, i, DVAL_EOM ], function (msg) { - // nop - }, function (err) { - // nop - }); - } - } - - // Technically we should wait for each delbreak reply but because - // target processes the requests in order, it doesn't matter. - if ((mode === 'add') || (mode === 'toggle' && !deleted)) { - _this.sendRequest([ DVAL_REQ, CMD_ADDBREAK, fileName, lineNumber, DVAL_EOM ], function (msg) { - // nop - }, function (err) { - _this.uiMessage('debugger-info', 'Failed to add breakpoint: ' + err); - }); - } - - // Read final, effective breakpoints from the target - _this.sendBreakpointListRequest(); - }); -}; - -Debugger.prototype.disconnectDebugger = function () { - if (this.targetStream) { - // We require a destroy() method from the actual target stream - this.targetStream.destroy(); - this.targetStream = null; - } - if (this.inputParser) { - this.inputParser.close(); - this.inputParser = null; - } - if (this.outputPassThroughStream) { - // There is no close() or destroy() for a passthrough stream, so just - // close the outputParser which will cancel timers etc. - } - if (this.outputParser) { - this.outputParser.close(); - this.outputParser = null; - } - - this.attached = false; - this.handshook = false; - this.reqQueue = null; - this.execStatus = { - attached: false, - state: 'detached', - fileName: '', - funcName: '', - line: 0, - pc: 0 - }; -}; - -Debugger.prototype.connectDebugger = function () { - var _this = this; - - this.disconnectDebugger(); // close previous target connection - - // CUSTOMTRANSPORT: to use a custom transport, change this.targetStream to - // use your custom transport. - - console.log('Connecting to ' + optTargetHost + ':' + optTargetPort + '...'); - this.targetStream = new net.Socket(); - this.targetStream.connect(optTargetPort, optTargetHost, function () { - console.log('Debug transport connected'); - _this.attached = true; - _this.reqQueue = []; - _this.uiMessage('debugger-info', 'Debug transport connected'); - }); - - this.inputParser = new DebugProtocolParser( - this.targetStream, - null, - optDumpDebugRead, - optDumpDebugPretty, - optDumpDebugPretty ? 'Recv: ' : null, - null, - null // console logging is done at a higher level to match request/response - ); - - // Use a PassThrough stream to debug dump and get stats for output messages. - // Simply write outgoing data to both the targetStream and this passthrough - // separately. - this.outputPassThroughStream = stream.PassThrough(); - this.outputParser = new DebugProtocolParser( - this.outputPassThroughStream, - 1, - optDumpDebugWrite, - optDumpDebugPretty, - optDumpDebugPretty ? 'Send: ' : null, - null, - null // console logging is done at a higher level to match request/response - ); - - this.inputParser.on('transport-close', function () { - _this.uiMessage('debugger-info', 'Debug transport closed'); - _this.disconnectDebugger(); - _this.emit('exec-status-update'); - _this.emit('detached'); - }); - - this.inputParser.on('transport-error', function (err) { - _this.uiMessage('debugger-info', 'Debug transport error: ' + err); - _this.disconnectDebugger(); - }); - - this.inputParser.on('protocol-version', function (msg) { - var ver = msg.protocolVersion; - console.log('Debug version identification:', msg.versionIdentification); - _this.protocolVersion = ver; - _this.uiMessage('debugger-info', 'Debug version identification: ' + msg.versionIdentification); - if (ver !== 1) { - _this.uiMessage('debugger-info', 'Protocol version ' + ver + ' unsupported, dropping connection'); - _this.targetStream.destroy(); - } else { - _this.uiMessage('debugger-info', 'Debug protocol version: ' + ver); - _this.handshook = true; - _this.execStatus = { - attached: true, - state: 'attached', - fileName: '', - funcName: '', - line: 0, - pc: 0 - }; - _this.emit('exec-status-update'); - _this.emit('attached'); // inform web UI - - // Fetch basic info right away - _this.sendBasicInfoRequest(); - } - }); - - this.inputParser.on('debug-message', function (msg) { - _this.processDebugMessage(msg); - }); - - this.inputParser.on('stats-update', function () { - _this.stats.rxBytes = this.bytes; - _this.stats.rxDvalues = this.dvalues; - _this.stats.rxMessages = this.messages; - _this.stats.rxBytesPerSec = this.bytesPerSec; - _this.emit('debug-stats-update'); - }); - - this.outputParser.on('stats-update', function () { - _this.stats.txBytes = this.bytes; - _this.stats.txDvalues = this.dvalues; - _this.stats.txMessages = this.messages; - _this.stats.txBytesPerSec = this.bytesPerSec; - _this.emit('debug-stats-update'); - }); -}; - -Debugger.prototype.processDebugMessage = function (msg) { - var req; - var prevState, newState; - var err; - - if (msg[0] === DVAL_REQ) { - // No actual requests sent by the target right now (just notifys). - console.log('Unsolicited reply message, dropping connection: ' + prettyDebugMessage(msg)); - } else if (msg[0] === DVAL_REP) { - if (this.reqQueue.length <= 0) { - console.log('Unsolicited reply message, dropping connection: ' + prettyDebugMessage(msg)); - this.targetStream.destroy(); - } - req = this.reqQueue.shift(); - - if (optLogMessages) { - console.log('Reply for ' + prettyDebugCommand(req.reqCmd) + ': ' + prettyDebugMessage(msg)); - } - - if (req.resolveCb) { - req.resolveCb(msg); - } else { - // nop: no callback - } - } else if (msg[0] === DVAL_ERR) { - if (this.reqQueue.length <= 0) { - console.log('Unsolicited error message, dropping connection: ' + prettyDebugMessage(msg)); - this.targetStream.destroy(); - } - err = new Error(String(msg[2]) + ' (code ' + String(msg[1]) + ')'); - err.errorCode = msg[1] || 0; - req = this.reqQueue.shift(); - - if (optLogMessages) { - console.log('Error for ' + prettyDebugCommand(req.reqCmd) + ': ' + prettyDebugMessage(msg)); - } - - if (req.rejectCb) { - req.rejectCb(err); - } else { - // nop: no callback - } - } else if (msg[0] === DVAL_NFY) { - if (optLogMessages) { - console.log('Notify ' + prettyDebugCommand(msg[1]) + ': ' + prettyDebugMessage(msg)); - } - - if (msg[1] === CMD_STATUS) { - prevState = this.execStatus.state; - newState = msg[2] === 0 ? 'running' : 'paused'; - this.execStatus = { - attached: true, - state: newState, - fileName: msg[3], - funcName: msg[4], - line: msg[5], - pc: msg[6] - }; - - if (prevState !== newState && newState === 'paused') { - // update run state now that we're paused - this.sendBreakpointListRequest(); - this.sendGetLocalsRequest(); - this.sendGetCallStackRequest(); - } - - this.emit('exec-status-update'); - } else if (msg[1] === CMD_PRINT) { - this.uiMessage('print', prettyUiStringUnquoted(msg[2], UI_MESSAGE_CLIPLEN)); - } else if (msg[1] === CMD_ALERT) { - this.uiMessage('alert', prettyUiStringUnquoted(msg[2], UI_MESSAGE_CLIPLEN)); - } else if (msg[1] === CMD_LOG) { - this.uiMessage({ type: 'log', level: msg[2], message: prettyUiStringUnquoted(msg[3], UI_MESSAGE_CLIPLEN) }); - } else { - console.log('Unknown notify, dropping connection: ' + prettyDebugMessage(msg)); - this.targetStream.destroy(); - } - } else { - console.log('Invalid initial dvalue, dropping connection: ' + prettyDebugMessage(msg)); - this.targetStream.destroy(); - } -}; - -Debugger.prototype.run = function () { - var _this = this; - - // Initial debugger connection - - this.connectDebugger(); - - // Poll various state items when running - - var sendRound = 0; - var statusPending = false; - var bplistPending = false; - var localsPending = false; - var callStackPending = false; - - setInterval(function () { - if (_this.execStatus.state !== 'running') { - return; - } - - // Could also check for an empty request queue, but that's probably - // too strict? - - // Pending flags are used to avoid requesting the same thing twice - // while a previous request is pending. The flag-based approach is - // quite awkward. Rework to use promises. - - switch(sendRound) { - case 0: - if (!statusPending) { - statusPending = true; - _this.sendStatusRequest().finally(function () { statusPending = false; }); - } - break; - case 1: - if (!bplistPending) { - bplistPending = true; - _this.sendBreakpointListRequest().finally(function () { bplistPending = false; }); - } - break; - case 2: - if (!localsPending) { - localsPending = true; - _this.sendGetLocalsRequest().finally(function () { localsPending = false; }); - } - break; - case 3: - if (!callStackPending) { - callStackPending = true; - _this.sendGetCallStackRequest().finally(function () { callStackPending = false; }); - } - break; - } - sendRound = (sendRound + 1) % 4; - }, 500); -}; - -/* - * Express setup and socket.io - */ - -function DebugWebServer() { - this.dbg = null; // debugger singleton - this.socket = null; // current socket (or null) - this.keepaliveTimer = null; - this.uiMessageLimiter = null; - this.cachedJson = {}; // cache to avoid resending identical data - this.sourceFileManager = new SourceFileManager(optSourceSearchDirs); - this.sourceFileManager.scan(); -} - -DebugWebServer.prototype.handleSourcePost = function (req, res) { - var fileName = req.body && req.body.fileName; - var fileData; - - console.log('Source request: ' + fileName); - - if (typeof fileName !== 'string') { - res.status(500).send('invalid request'); - return; - } - fileData = this.sourceFileManager.search(fileName, optSourceSearchDirs); - if (typeof fileData !== 'string') { - res.status(404).send('not found'); - return; - } - res.status(200).send(fileData); // UTF-8 -}; - -DebugWebServer.prototype.handleSourceListPost = function (req, res) { - console.log('Source list request'); - - var files = this.sourceFileManager.getFiles(); - res.header('Content-Type', 'application/json'); - res.status(200).json(files); -}; - -DebugWebServer.prototype.handleHeapDumpGet = function (req, res) { - console.log('Heap dump get'); - - this.dbg.sendDumpHeapRequest().then(function (val) { - res.header('Content-Type', 'application/json'); - //res.status(200).json(val); - res.status(200).send(JSON.stringify(val, null, 4)); - }).catch(function (err) { - res.status(500).send('Failed to get heap dump: ' + (err.stack || err)); - }); -}; - -DebugWebServer.prototype.run = function () { - var _this = this; - - var express = require('express'); - var bodyParser = require('body-parser'); - var app = express(); - var http = require('http').Server(app); - var io = require('socket.io')(http); - - app.use(bodyParser.json()); - app.post('/source', this.handleSourcePost.bind(this)); - app.post('/sourceList', this.handleSourceListPost.bind(this)); - app.get('/heapDump.json', this.handleHeapDumpGet.bind(this)); - app.use('/', express.static(__dirname + '/static')); - - http.listen(optHttpPort, function () { - console.log('Listening on *:' + optHttpPort); - }); - - io.on('connection', this.handleNewSocketIoConnection.bind(this)); - - this.dbg.on('attached', function () { - console.log('Debugger attached'); - }); - - this.dbg.on('detached', function () { - console.log('Debugger detached'); - }); - - this.dbg.on('debug-stats-update', function () { - _this.debugStatsLimiter.trigger(); - }); - - this.dbg.on('ui-message-update', function () { - // Explicit rate limiter because this is a source of a lot of traffic. - _this.uiMessageLimiter.trigger(); - }); - - this.dbg.on('basic-info-update', function () { - _this.emitBasicInfo(); - }); - - this.dbg.on('breakpoints-update', function () { - _this.emitBreakpoints(); - }); - - this.dbg.on('exec-status-update', function () { - // Explicit rate limiter because this is a source of a lot of traffic. - _this.execStatusLimiter.trigger(); - }); - - this.dbg.on('locals-update', function () { - _this.emitLocals(); - }); - - this.dbg.on('callstack-update', function () { - _this.emitCallStack(); - }); - - this.uiMessageLimiter = new RateLimited(10, 1000, this.uiMessageLimiterCallback.bind(this)); - this.execStatusLimiter = new RateLimited(50, 500, this.execStatusLimiterCallback.bind(this)); - this.debugStatsLimiter = new RateLimited(1, 2000, this.debugStatsLimiterCallback.bind(this)); - - this.keepaliveTimer = setInterval(this.emitKeepalive.bind(this), 30000); -}; - -DebugWebServer.prototype.handleNewSocketIoConnection = function (socket) { - var _this = this; - - console.log('Socket.io connected'); - if (this.socket) { - console.log('Closing previous socket.io socket'); - this.socket.emit('replaced'); - } - this.socket = socket; - - this.emitKeepalive(); - - socket.on('disconnect', function () { - console.log('Socket.io disconnected'); - if (_this.socket === socket) { - _this.socket = null; - } - }); - - socket.on('keepalive', function (msg) { - // nop - }); - - socket.on('attach', function (msg) { - if (_this.dbg.targetStream) { - console.log('Attach request when debugger already has a connection, ignoring'); - } else { - _this.dbg.connectDebugger(); - } - }); - - socket.on('detach', function (msg) { - // Try to detach cleanly, timeout if no response - Promise.any([ - _this.dbg.sendDetachRequest(), - Promise.delay(3000) - ]).finally(function () { - _this.dbg.disconnectDebugger(); - }); - }); - - socket.on('stepinto', function (msg) { - _this.dbg.sendStepIntoRequest(); - }); - - socket.on('stepover', function (msg) { - _this.dbg.sendStepOverRequest(); - }); - - socket.on('stepout', function (msg) { - _this.dbg.sendStepOutRequest(); - }); - - socket.on('pause', function (msg) { - _this.dbg.sendPauseRequest(); - }); - - socket.on('resume', function (msg) { - _this.dbg.sendResumeRequest(); - }); - - socket.on('eval', function (msg) { - // msg.input is a proper Unicode strings here, and needs to be - // converted into a protocol string (U+0000...U+00FF). - var input = stringToDebugString(msg.input); - _this.dbg.sendEvalRequest(input).then(function (v) { - socket.emit('eval-result', { error: v.error, result: prettyUiDebugValue(v.value, EVAL_CLIPLEN) }); - }); - - // An eval call quite possibly changes the local variables so always - // re-read locals afterwards. We don't need to wait for eval() to - // complete here; the requests will pipeline automatically and be - // executed in order. - _this.dbg.sendGetLocalsRequest(); - }); - - socket.on('getvar', function (msg) { - // msg.varname is a proper Unicode strings here, and needs to be - // converted into a protocol string (U+0000...U+00FF). - var varname = stringToDebugString(msg.varname); - _this.dbg.sendGetVarRequest(varname) - .then(function (v) { - socket.emit('getvar-result', { found: v.found, result: prettyUiDebugValue(v.value, GETVAR_CLIPLEN) }); - }); - }); - - socket.on('putvar', function (msg) { - // msg.varname and msg.varvalue are proper Unicode strings here, they - // need to be converted into protocol strings (U+0000...U+00FF). - var varname = stringToDebugString(msg.varname); - var varvalue = msg.varvalue; - - // varvalue is JSON parsed by the web UI for now, need special string - // encoding here. - if (typeof varvalue === 'string') { - varvalue = stringToDebugString(msg.varvalue); - } - - _this.dbg.sendPutVarRequest(varname, varvalue) - .then(function (v) { - console.log('putvar done'); // XXX: signal success to UI? - }); - - // A PutVar call quite possibly changes the local variables so always - // re-read locals afterwards. We don't need to wait for eval() to - // complete here; the requests will pipeline automatically and be - // executed in order. - _this.dbg.sendGetLocalsRequest(); - }); - - socket.on('add-breakpoint', function (msg) { - _this.dbg.changeBreakpoint(msg.fileName, msg.lineNumber, 'add'); - }); - - socket.on('delete-breakpoint', function (msg) { - _this.dbg.changeBreakpoint(msg.fileName, msg.lineNumber, 'delete'); - }); - - socket.on('toggle-breakpoint', function (msg) { - _this.dbg.changeBreakpoint(msg.fileName, msg.lineNumber, 'toggle'); - }); - - socket.on('delete-all-breakpoints', function (msg) { - _this.dbg.changeBreakpoint(null, null, 'deleteall'); - }); - - socket.on('get-bytecode', function (msg) { - _this.dbg.sendGetBytecodeRequest().then(function (res) { - socket.emit('bytecode', res); - }); - }); - - // Resend all debugger state for new client - this.cachedJson = {}; // clear client state cache - this.emitBasicInfo(); - this.emitStats(); - this.emitExecStatus(); - this.emitUiMessages(); - this.emitBreakpoints(); - this.emitCallStack(); - this.emitLocals(); -}; - -// Check if 'msg' would encode to the same JSON which was previously sent -// to the web client. The caller then avoid resending unnecessary stuff. -DebugWebServer.prototype.cachedJsonCheck = function (cacheKey, msg) { - var newJson = JSON.stringify(msg); - if (this.cachedJson[cacheKey] === newJson) { - return true; // cached - } - this.cachedJson[cacheKey] = newJson; - return false; // not cached, send (cache already updated) -}; - -DebugWebServer.prototype.uiMessageLimiterCallback = function () { - this.emitUiMessages(); -}; - -DebugWebServer.prototype.execStatusLimiterCallback = function () { - this.emitExecStatus(); -}; - -DebugWebServer.prototype.debugStatsLimiterCallback = function () { - this.emitStats(); -}; - -DebugWebServer.prototype.emitKeepalive = function () { - if (!this.socket) { return; } - - this.socket.emit('keepalive', { nodeVersion: process.version }); -}; - -DebugWebServer.prototype.emitBasicInfo = function () { - if (!this.socket) { return; } - - var newMsg = { - duk_version: this.dbg.dukVersion, - duk_git_describe: this.dbg.dukGitDescribe, - target_info: this.dbg.targetInfo, - endianness: this.dbg.endianness - }; - if (this.cachedJsonCheck('basic-info', newMsg)) { - return; - } - this.socket.emit('basic-info', newMsg); -}; - -DebugWebServer.prototype.emitStats = function () { - if (!this.socket) { return; } - - this.socket.emit('debug-stats', this.dbg.stats); -}; - -DebugWebServer.prototype.emitExecStatus = function () { - if (!this.socket) { return; } - - var newMsg = this.dbg.execStatus; - if (this.cachedJsonCheck('exec-status', newMsg)) { - return; - } - this.socket.emit('exec-status', newMsg); -}; - -DebugWebServer.prototype.emitUiMessages = function () { - if (!this.socket) { return; } - - var newMsg = this.dbg.messageLines; - if (this.cachedJsonCheck('output-lines', newMsg)) { - return; - } - this.socket.emit('output-lines', newMsg); -}; - -DebugWebServer.prototype.emitBreakpoints = function () { - if (!this.socket) { return; } - - var newMsg = { breakpoints: this.dbg.breakpoints }; - if (this.cachedJsonCheck('breakpoints', newMsg)) { - return; - } - this.socket.emit('breakpoints', newMsg); -}; - -DebugWebServer.prototype.emitCallStack = function () { - if (!this.socket) { return; } - - var newMsg = { callstack: this.dbg.callstack }; - if (this.cachedJsonCheck('callstack', newMsg)) { - return; - } - this.socket.emit('callstack', newMsg); -}; - -DebugWebServer.prototype.emitLocals = function () { - if (!this.socket) { return; } - - var newMsg = { locals: this.dbg.locals }; - if (this.cachedJsonCheck('locals', newMsg)) { - return; - } - this.socket.emit('locals', newMsg); -}; - -/* - * JSON debug proxy - */ - -function DebugProxy(serverPort) { - this.serverPort = serverPort; - this.server = null; - this.socket = null; - this.targetStream = null; - this.inputParser = null; - - // preformatted dvalues - this.dval_eom = formatDebugValue(DVAL_EOM); - this.dval_req = formatDebugValue(DVAL_REQ); - this.dval_rep = formatDebugValue(DVAL_REP); - this.dval_nfy = formatDebugValue(DVAL_NFY); - this.dval_err = formatDebugValue(DVAL_ERR); -} - -DebugProxy.prototype.determineCommandNumber = function (cmdString, cmdNumber) { - var ret; - if (typeof cmdString === 'string') { - ret = debugCommandNumbers[cmdString]; - } - ret = ret || cmdNumber; - if (typeof ret !== 'number') { - throw Error('cannot figure out command number for "' + cmdString + '" (' + cmdNumber + ')'); - } - return ret; -}; - -DebugProxy.prototype.commandNumberToString = function (id) { - return debugCommandNames[id] || String(id); -}; - -DebugProxy.prototype.formatDvalues = function (args) { - if (!args) { - return []; - } - return args.map(function (v) { - return formatDebugValue(v); - }); -}; - -DebugProxy.prototype.writeJson = function (val) { - this.socket.write(JSON.stringify(val) + '\n'); -}; - -DebugProxy.prototype.writeJsonSafe = function (val) { - try { - this.writeJson(val); - } catch (e) { - console.log('Failed to write JSON in writeJsonSafe, ignoring: ' + e); - } -}; - -DebugProxy.prototype.disconnectJsonClient = function () { - if (this.socket) { - this.socket.destroy(); - this.socket = null; - } -}; - -DebugProxy.prototype.disconnectTarget = function () { - if (this.inputParser) { - this.inputParser.close(); - this.inputParser = null; - } - if (this.targetStream) { - this.targetStream.destroy(); - this.targetStream = null; - } -}; - -DebugProxy.prototype.run = function () { - var _this = this; - - console.log('Waiting for client connections on port ' + this.serverPort); - this.server = net.createServer(function (socket) { - console.log('JSON proxy client connected'); - - _this.disconnectJsonClient(); - _this.disconnectTarget(); - - // A byline-parser is simple and good enough for now (assume - // compact JSON with no newlines). - var socketByline = byline(socket); - _this.socket = socket; - - socketByline.on('data', function (line) { - try { - // console.log('Received json proxy input line: ' + line.toString('utf8')); - var msg = JSON.parse(line.toString('utf8')); - var first_dval; - var args_dvalues = _this.formatDvalues(msg.args); - var last_dval = _this.dval_eom; - var cmd; - - if (msg.request) { - // "request" can be a string or "true" - first_dval = _this.dval_req; - cmd = _this.determineCommandNumber(msg.request, msg.command); - } else if (msg.reply) { - first_dval = _this.dval_rep; - } else if (msg.notify) { - // "notify" can be a string or "true" - first_dval = _this.dval_nfy; - cmd = _this.determineCommandNumber(msg.notify, msg.command); - } else if (msg.error) { - first_dval = _this.dval_err; - } else { - throw new Error('Invalid input JSON message: ' + JSON.stringify(msg)); - } - - _this.targetStream.write(first_dval); - if (cmd) { - _this.targetStream.write(formatDebugValue(cmd)); - } - args_dvalues.forEach(function (v) { - _this.targetStream.write(v); - }); - _this.targetStream.write(last_dval); - } catch (e) { - console.log(e); - - _this.writeJsonSafe({ - notify: '_Error', - args: [ 'Failed to handle input json message: ' + e ] - }); - - _this.disconnectJsonClient(); - _this.disconnectTarget(); - } - }); - - _this.connectToTarget(); - }).listen(this.serverPort); -}; - -DebugProxy.prototype.connectToTarget = function () { - var _this = this; - - console.log('Connecting to ' + optTargetHost + ':' + optTargetPort + '...'); - this.targetStream = new net.Socket(); - this.targetStream.connect(optTargetPort, optTargetHost, function () { - console.log('Debug transport connected'); - }); - - this.inputParser = new DebugProtocolParser( - this.targetStream, - null, - optDumpDebugRead, - optDumpDebugPretty, - optDumpDebugPretty ? 'Recv: ' : null, - null, - null // console logging is done at a higher level to match request/response - ); - - // Don't add a '_value' key to numbers. - this.inputParser.readableNumberValue = false; - - this.inputParser.on('transport-close', function () { - console.log('Debug transport closed'); - - _this.writeJsonSafe({ - notify: '_Disconnecting' - }); - - _this.disconnectJsonClient(); - _this.disconnectTarget(); - }); - - this.inputParser.on('transport-error', function (err) { - console.log('Debug transport error', err); - - _this.writeJsonSafe({ - notify: '_Error', - args: [ String(err) ] - }); - }); - - this.inputParser.on('protocol-version', function (msg) { - var ver = msg.protocolVersion; - console.log('Debug version identification:', msg.versionIdentification); - - _this.writeJson({ - notify: '_Connected', - args: [ msg.versionIdentification ] // raw identification string - }); - - if (ver !== 1) { - console.log('Protocol version ' + ver + ' unsupported, dropping connection'); - } - }); - - this.inputParser.on('debug-message', function (msg) { - var t; - - //console.log(msg); - - if (typeof msg[0] !== 'object' || msg[0] === null) { - throw new Error('unexpected initial dvalue: ' + msg[0]); - } else if (msg.type === 'eom') { - throw new Error('unexpected initial dvalue: ' + msg[0]); - } else if (msg.type === 'req') { - if (typeof msg[1] !== 'number') { - throw new Error('unexpected request command number: ' + msg[1]); - } - t = { - request: _this.commandNumberToString(msg[1]), - command: msg[1], - args: msg.slice(2, msg.length - 1) - } - _this.writeJson(t); - } else if (msg[0].type === 'rep') { - t = { - reply: true, - args: msg.slice(1, msg.length - 1) - } - _this.writeJson(t); - } else if (msg[0].type === 'err') { - t = { - error: true, - args: msg.slice(1, msg.length - 1) - } - _this.writeJson(t); - } else if (msg[0].type === 'nfy') { - if (typeof msg[1] !== 'number') { - throw new Error('unexpected notify command number: ' + msg[1]); - } - t = { - notify: _this.commandNumberToString(msg[1]), - command: msg[1], - args: msg.slice(2, msg.length - 1) - } - _this.writeJson(t); - } else { - throw new Error('unexpected initial dvalue: ' + msg[0]); - } - }); - - this.inputParser.on('stats-update', function () { - }); -}; - -/* - * Command line parsing and initialization - */ - -function main() { - console.log('((o) Duktape debugger'); - - // Parse arguments. - - var argv = require('minimist')(process.argv.slice(2)); - //console.dir(argv); - if (argv['target-host']) { - optTargetHost = argv['target-host']; - } - if (argv['target-port']) { - optTargetPort = argv['target-port']; - } - if (argv['http-port']) { - optHttpPort = argv['http-port']; - } - if (argv['json-proxy-port']) { - optJsonProxyPort = argv['json-proxy-port']; - } - if (argv['json-proxy']) { - optJsonProxy = argv['json-proxy']; - } - if (argv['source-dirs']) { - optSourceSearchDirs = argv['source-dirs'].split(path.delimiter); - } - if (argv['dump-debug-read']) { - optDumpDebugRead = argv['dump-debug-read']; - } - if (argv['dump-debug-write']) { - optDumpDebugWrite = argv['dump-debug-write']; - } - if (argv['dump-debug-pretty']) { - optDumpDebugPretty = argv['dump-debug-pretty']; - } - if (argv['log-messages']) { - optLogMessages = true; - } - - // Dump effective options. Also provides a list of option names. - - console.log(''); - console.log('Effective options:'); - console.log(' --target-host: ' + optTargetHost); - console.log(' --target-port: ' + optTargetPort); - console.log(' --http-port: ' + optHttpPort); - console.log(' --json-proxy-port: ' + optJsonProxyPort); - console.log(' --json-proxy: ' + optJsonProxy); - console.log(' --source-dirs: ' + optSourceSearchDirs.join(' ')); - console.log(' --dump-debug-read: ' + optDumpDebugRead); - console.log(' --dump-debug-write: ' + optDumpDebugWrite); - console.log(' --dump-debug-pretty: ' + optDumpDebugPretty); - console.log(' --log-messages: ' + optLogMessages); - console.log(''); - - // Create debugger and web UI singletons, tie them together and - // start them. - - if (optJsonProxy) { - console.log('Starting in JSON proxy mode, JSON port: ' + optJsonProxyPort); - - var prx = new DebugProxy(optJsonProxyPort); - prx.run(); - } else { - var dbg = new Debugger(); - var web = new DebugWebServer(); - dbg.web = web; - web.dbg = dbg; - dbg.run(); - web.run(); - } -} - -main(); diff --git a/src/third_party/duktape-1.3.0/debugger/duk_debugcommands.yaml b/src/third_party/duktape-1.3.0/debugger/duk_debugcommands.yaml deleted file mode 100644 index 0d4501c9..00000000 --- a/src/third_party/duktape-1.3.0/debugger/duk_debugcommands.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# Debug command names. A single map works for now because command names -# provided by client/target don't overlap. -- Reserved_0 -- Status -- Print -- Alert -- Log -- Gc -- Reserved_6 -- Reserved_7 -- Reserved_8 -- Reserved_9 -- Reserved_10 -- Reserved_11 -- Reserved_12 -- Reserved_13 -- Reserved_14 -- Reserved_15 -- BasicInfo -- TriggerStatus -- Pause -- Resume -- StepInto -- StepOver -- StepOut -- ListBreak -- AddBreak -- DelBreak -- GetVar -- PutVar -- GetCallStack -- GetLocals -- Eval -- Detach -- DumpHeap -- GetBytecode diff --git a/src/third_party/duktape-1.3.0/debugger/duk_opcodes.yaml b/src/third_party/duktape-1.3.0/debugger/duk_opcodes.yaml deleted file mode 100644 index a82ac8ca..00000000 --- a/src/third_party/duktape-1.3.0/debugger/duk_opcodes.yaml +++ /dev/null @@ -1,660 +0,0 @@ -# Duktape opcode metadata for debugger. -# - See duk_debug.js for the argument formats (A_R etc). -# - Flag bits are for the whole instruction as a 32-bit integer, -# they are not field shifted -# -# NOTE: Use YAML comments only on comment-only lines (not trailing content): -# Node.js 'yamljs' seems to refuse parsing trailing comments in some cases. - -opcodes: - - name: LDREG - args: - - A_R - - BC_R - - name: STREG - args: - - A_R - - BC_R - - name: LDCONST - args: - - A_R - - BC_C - - name: LDINT - args: - - A_R - - BC_LDINT - - name: LDINTX - args: - - A_R - - BC_LDINTX - - name: MPUTOBJ - args: - - A_R - - B_R - - C_I - - name: MPUTOBJI - args: - - A_R - - B_RI - - C_I - - name: MPUTARR - args: - - A_R - - B_R - - C_I - - name: MPUTARRI - args: - - A_R - - B_RI - - C_I - - name: NEW - args: - - B_R - - C_I - - name: NEWI - args: - - B_RI - - C_I - - name: REGEXP - args: - - A_R - - B_RC - - C_RC - - name: CSREG - args: - - A_R - - B_R - - name: CSREGI - args: - - A_RI - - B_R - - name: GETVAR - args: - - A_R - - BC_C - - name: PUTVAR - args: - - A_R - - BC_C - - name: DECLVAR - args: - - A_H - - B_RC - - C_RC - flags: - - mask: 0x40 - name: writable - - mask: 0x80 - name: enumerable - - mask: 0x100 - name: configurable - - mask: 0x200 - name: accessor - - mask: 0x400 - name: undef_value - - mask: 0x800 - name: func_decl - - name: DELVAR - args: - - A_R - - B_RC - - name: CSVAR - args: - - A_R - - B_RC - - name: CSVARI - args: - - A_RI - - B_RC - - name: CLOSURE - args: - - A_R - - BC_I - - name: GETPROP - args: - - A_R - - B_RC - - C_RC - - name: PUTPROP - args: - - A_R - - B_RC - - C_RC - - name: DELPROP - args: - - A_R - - B_R - - C_RC - - name: CSPROP - args: - - A_R - - B_R - - C_RC - - name: CSPROPI - args: - - A_RI - - B_R - - C_RC - - name: ADD - args: - - A_R - - B_RC - - C_RC - - name: SUB - args: - - A_R - - B_RC - - C_RC - - name: MUL - args: - - A_R - - B_RC - - C_RC - - name: DIV - args: - - A_R - - B_RC - - C_RC - - name: MOD - args: - - A_R - - B_RC - - C_RC - - name: BAND - args: - - A_R - - B_RC - - C_RC - - name: BOR - args: - - A_R - - B_RC - - C_RC - - name: BXOR - args: - - A_R - - B_RC - - C_RC - - name: BASL - args: - - A_R - - B_RC - - C_RC - - name: BLSR - args: - - A_R - - B_RC - - C_RC - - name: BASR - args: - - A_R - - B_RC - - C_RC - - name: EQ - args: - - A_R - - B_RC - - C_RC - - name: NEQ - args: - - A_R - - B_RC - - C_RC - - name: SEQ - args: - - A_R - - B_RC - - C_RC - - name: SNEQ - args: - - A_R - - B_RC - - C_RC - - name: GT - args: - - A_R - - B_RC - - C_RC - - name: GE - args: - - A_R - - B_RC - - C_RC - - name: LT - args: - - A_R - - B_RC - - C_RC - - name: LE - args: - - A_R - - B_RC - - C_RC - - name: IF - args: - - A_B - - B_RC - - name: JUMP - args: - - ABC_JUMP - - name: RETURN - args: - - A_H - - B_RC - flags: - - mask: 0x40 - name: fast_return - - mask: 0x80 - name: have_retval - - name: CALL - args: - - A_H - - B_R - - C_I - flags: - - mask: 0x40 - name: tailcall - - mask: 0x80 - name: evalcall - - name: CALLI - args: - - A_H - - B_RI - - C_I - - name: TRYCATCH - args: - - A_H - # base register for two consecutive regs (base_reg + 0, base_reg + 1) used for two things: - # - input: either 'with' target register or catch varname constant (base_reg + 0), depending on flags - # - output: when caught, catch value (base_reg + 0) and type (base_reg + 1) - - BC_R - flags: - - mask: 0x40 - name: have_catch - - mask: 0x80 - name: have_finally - - mask: 0x100 - name: catch_binding - - mask: 0x200 - name: with_binding - - name: EXTRA - extra: true - - name: PREINCR - args: - - A_R - - BC_R - - name: PREDECR - args: - - A_R - - BC_R - - name: POSTINCR - args: - - A_R - - BC_R - - name: POSTDECR - args: - - A_R - - BC_R - - name: PREINCV - args: - - A_R - - BC_C - - name: PREDECV - args: - - A_R - - BC_C - - name: POSTINCV - args: - - A_R - - BC_C - - name: POSTDECV - args: - - A_R - - BC_C - - name: PREINCP - args: - - A_R - - B_RC - - C_RC - - name: PREDECP - args: - - A_R - - B_RC - - C_RC - - name: POSTINCP - args: - - A_R - - B_RC - - C_RC - - name: POSTDECP - args: - - A_R - - B_RC - - C_RC - -extra: - - name: NOP - - name: INVALID - args: - - BC_I - - name: LDTHIS - args: - - BC_R - - name: LDUNDEF - args: - - BC_R - - name: LDNULL - args: - - BC_R - - name: LDTRUE - args: - - BC_R - - name: LDFALSE - args: - - BC_R - - name: NEWOBJ - args: - # XXX: extend to BC? - - B_R - - name: NEWARR - args: - # XXX: extend to BC? - - B_R - - name: SETALEN - args: - - B_R - - C_R - - name: TYPEOF - args: - - BC_R - - name: TYPEOFID - args: - - B_R - # maybe changed to C_C later - - C_RC - - name: INITENUM - args: - - B_R - - C_R - - name: NEXTENUM - args: - - B_R - - C_R - - name: INITSET - args: - - B_R - - C_R - - name: INITSETI - args: - - B_R - - C_RI - - name: INITGET - args: - - B_R - - C_RI - - name: INITGETI - args: - - B_R - - C_RI - - name: ENDTRY - - name: ENDCATCH - - name: ENDFIN - - name: THROW - args: - - BC_R - - name: INVLHS - - name: UNM - args: - - BC_R - - name: UNP - args: - - BC_R - - name: DEBUGGER - - name: BREAK - args: - - BC_I - - name: CONTINUE - args: - - BC_I - - name: BNOT - args: - - BC_R - - name: LNOT - args: - - BC_R - - name: INSTOF - args: - - B_R - - C_RC - - name: IN - args: - - B_R - - C_RC - - name: LABEL - args: - - BC_I - - name: ENDLABEL - args: - - BC_I - - name: EXTRA34 - - name: EXTRA35 - - name: EXTRA36 - - name: EXTRA37 - - name: EXTRA38 - - name: EXTRA39 - - name: EXTRA40 - - name: EXTRA41 - - name: EXTRA42 - - name: EXTRA43 - - name: EXTRA44 - - name: EXTRA45 - - name: EXTRA46 - - name: EXTRA47 - - name: EXTRA48 - - name: EXTRA49 - - name: EXTRA50 - - name: EXTRA51 - - name: EXTRA52 - - name: EXTRA53 - - name: EXTRA54 - - name: EXTRA55 - - name: EXTRA56 - - name: EXTRA57 - - name: EXTRA58 - - name: EXTRA59 - - name: EXTRA60 - - name: EXTRA61 - - name: EXTRA62 - - name: EXTRA63 - - name: EXTRA64 - - name: EXTRA65 - - name: EXTRA66 - - name: EXTRA67 - - name: EXTRA68 - - name: EXTRA69 - - name: EXTRA70 - - name: EXTRA71 - - name: EXTRA72 - - name: EXTRA73 - - name: EXTRA74 - - name: EXTRA75 - - name: EXTRA76 - - name: EXTRA77 - - name: EXTRA78 - - name: EXTRA79 - - name: EXTRA80 - - name: EXTRA81 - - name: EXTRA82 - - name: EXTRA83 - - name: EXTRA84 - - name: EXTRA85 - - name: EXTRA86 - - name: EXTRA87 - - name: EXTRA88 - - name: EXTRA89 - - name: EXTRA90 - - name: EXTRA91 - - name: EXTRA92 - - name: EXTRA93 - - name: EXTRA94 - - name: EXTRA95 - - name: EXTRA96 - - name: EXTRA97 - - name: EXTRA98 - - name: EXTRA99 - - name: EXTRA100 - - name: EXTRA101 - - name: EXTRA102 - - name: EXTRA103 - - name: EXTRA104 - - name: EXTRA105 - - name: EXTRA106 - - name: EXTRA107 - - name: EXTRA108 - - name: EXTRA109 - - name: EXTRA110 - - name: EXTRA111 - - name: EXTRA112 - - name: EXTRA113 - - name: EXTRA114 - - name: EXTRA115 - - name: EXTRA116 - - name: EXTRA117 - - name: EXTRA118 - - name: EXTRA119 - - name: EXTRA120 - - name: EXTRA121 - - name: EXTRA122 - - name: EXTRA123 - - name: EXTRA124 - - name: EXTRA125 - - name: EXTRA126 - - name: EXTRA127 - - name: EXTRA128 - - name: EXTRA129 - - name: EXTRA130 - - name: EXTRA131 - - name: EXTRA132 - - name: EXTRA133 - - name: EXTRA134 - - name: EXTRA135 - - name: EXTRA136 - - name: EXTRA137 - - name: EXTRA138 - - name: EXTRA139 - - name: EXTRA140 - - name: EXTRA141 - - name: EXTRA142 - - name: EXTRA143 - - name: EXTRA144 - - name: EXTRA145 - - name: EXTRA146 - - name: EXTRA147 - - name: EXTRA148 - - name: EXTRA149 - - name: EXTRA150 - - name: EXTRA151 - - name: EXTRA152 - - name: EXTRA153 - - name: EXTRA154 - - name: EXTRA155 - - name: EXTRA156 - - name: EXTRA157 - - name: EXTRA158 - - name: EXTRA159 - - name: EXTRA160 - - name: EXTRA161 - - name: EXTRA162 - - name: EXTRA163 - - name: EXTRA164 - - name: EXTRA165 - - name: EXTRA166 - - name: EXTRA167 - - name: EXTRA168 - - name: EXTRA169 - - name: EXTRA170 - - name: EXTRA171 - - name: EXTRA172 - - name: EXTRA173 - - name: EXTRA174 - - name: EXTRA175 - - name: EXTRA176 - - name: EXTRA177 - - name: EXTRA178 - - name: EXTRA179 - - name: EXTRA180 - - name: EXTRA181 - - name: EXTRA182 - - name: EXTRA183 - - name: EXTRA184 - - name: EXTRA185 - - name: EXTRA186 - - name: EXTRA187 - - name: EXTRA188 - - name: EXTRA189 - - name: EXTRA190 - - name: EXTRA191 - - name: EXTRA192 - - name: EXTRA193 - - name: EXTRA194 - - name: EXTRA195 - - name: EXTRA196 - - name: EXTRA197 - - name: EXTRA198 - - name: EXTRA199 - - name: EXTRA200 - - name: EXTRA201 - - name: EXTRA202 - - name: EXTRA203 - - name: EXTRA204 - - name: EXTRA205 - - name: EXTRA206 - - name: EXTRA207 - - name: EXTRA208 - - name: EXTRA209 - - name: EXTRA210 - - name: EXTRA211 - - name: EXTRA212 - - name: EXTRA213 - - name: EXTRA214 - - name: EXTRA215 - - name: EXTRA216 - - name: EXTRA217 - - name: EXTRA218 - - name: EXTRA219 - - name: EXTRA220 - - name: EXTRA221 - - name: EXTRA222 - - name: EXTRA223 - - name: EXTRA224 - - name: EXTRA225 - - name: EXTRA226 - - name: EXTRA227 - - name: EXTRA228 - - name: EXTRA229 - - name: EXTRA230 - - name: EXTRA231 - - name: EXTRA232 - - name: EXTRA233 - - name: EXTRA234 - - name: EXTRA235 - - name: EXTRA236 - - name: EXTRA237 - - name: EXTRA238 - - name: EXTRA239 - - name: EXTRA240 - - name: EXTRA241 - - name: EXTRA242 - - name: EXTRA243 - - name: EXTRA244 - - name: EXTRA245 - - name: EXTRA246 - - name: EXTRA247 - - name: EXTRA248 - - name: EXTRA249 - - name: EXTRA250 - - name: EXTRA251 - - name: EXTRA252 - - name: EXTRA253 - - name: EXTRA254 - - name: EXTRA255 diff --git a/src/third_party/duktape-1.3.0/debugger/package.json b/src/third_party/duktape-1.3.0/debugger/package.json deleted file mode 100644 index 96165744..00000000 --- a/src/third_party/duktape-1.3.0/debugger/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "duk-debug", - "version": "0.1.0", - "description": "Duktape debugger", - "author": { - "name": "Sami Vaarala", - "email": "sami.vaarala@iki.fi" - }, - "dependencies": { - "bluebird": "~2.6.4", - "minimist": "~1.1.0", - "express": "~4.10.1", - "body-parser": "~1.9.3", - "socket.io": "~1.2.1", - "utf8": "~2.0.0", - "wrench": "~1.5.8", - "sprintf": "~0.1.5", - "events": "~1.0.2", - "stream": "0.0.2", - "readline": "0.0.5", - "util": "~0.10.3", - "http": "0.0.0", - "yamljs": "~0.2.1", - "byline": "~4.2.1" - }, - "main": "duk_debug.js" -} diff --git a/src/third_party/duktape-1.3.0/debugger/static/index.html b/src/third_party/duktape-1.3.0/debugger/static/index.html deleted file mode 100644 index 5e5e2e05..00000000 --- a/src/third_party/duktape-1.3.0/debugger/static/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - -Duktape debugger - - - -
-((o) Duktape debugger -
- -
- -
- - - - - -
-
-
-
- - - - - -
- -
-

-// No source loaded
-
-
-
- -
-
-
?
-
?
?
-
-
-
(output from script, print() and alert() calls)
-
-
- -
-
-
(callstack)
-
-
-
(locals)
-
-
-
(breakpoints)
-
-
- watch (eval on pause) -
- -
-
-
- -
- - - -
-

Duktape debugger is a web UI for debugging Ecmascript on a target device.

-

This web UI talks to a NodeJS debug server using socket.io. -The debug server talks to the target device using the Duktape debug protocol -(see debugger.rst).

-
- -
-

-
- - - - - - - diff --git a/src/third_party/duktape-1.3.0/debugger/static/style.css b/src/third_party/duktape-1.3.0/debugger/static/style.css deleted file mode 100644 index ce8d34f6..00000000 --- a/src/third_party/duktape-1.3.0/debugger/static/style.css +++ /dev/null @@ -1,512 +0,0 @@ -// http://stackoverflow.com/questions/71074/how-to-remove-firefoxs-dotted-outline-on-buttons-as-well-as-links/3844452#3844452 -:focus { - outline: none; -} -::-moz-focus-inner { - border: 0; -} - -@keyframes pulsate { - from { opacity: 1; } - to { opacity: 0.25; } -} - -#part-header { - background: #444444; - color: #ffffff; - font: 24pt monospace; - border-bottom: 2px solid #cccccc; - padding: 20px 0px 20px 10px; -} - -/* http://css-tricks.com/snippets/css/a-guide-to-flexbox/ */ -#part-middle { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - justify-content: space-between; - align-items: stretch; - align-content: stretch; - - min-height: 800px; - - border-top: 1px solid #ffffff; - padding: 8px; - margin-top: 2px; -} -#left-area { - flex: 0 0 11em; - margin-right: 20px; - margin-bottom: 10px; -} -#center-area { - flex: 1 1 0; - margin-bottom: 10px; -} -#right-area { - flex: 0 0 40em; - margin-left: 20px; - margin-bottom: 10px; -} - -#part-footer { - clear: both; - border-top: 2px solid #bbbbbb; - background: #eeeeee; - color: #555555; - text-align: center; - padding-top: 12px; - padding-bottom: 12px; - line-height: 1.5; -} - -#exec-status { - margin-top: 25px; - margin-bottom: 25px; -} -#exec-state { - display: inline-block; - vertical-align: middle; -} -#exec-other { - display: inline-block; - vertical-align: middle; - font-size: 125%; -} -#current-state { - background: #228822; - color: #ffffff; - font: 16pt; - padding: 6pt; - border: 5px solid #228822; - border-radius: 10px; - font-size: 200%; - font-weight: bold; - margin-right: 10px; -} -#current-state.notrunning { - background: #882222; - border: 5px solid #882222; - border-radius: 10px; - animation: pulsate 0.7s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate; -} -#exec-other:hover { - text-decoration: underline; - color: #9999ff; -} - -#left-area button { - display: inline-block; - width: 100%; - min-width: 8em; - background: #226622; - color: #ffffff; - font: 16pt sans-serif; - font-weight: bold; - text-decoration: none; - margin: 10px 0 0 0; - padding: 0.4em; - border: 2px solid #000000; - border-radius: 4px; -} -#left-area button a { - color: #ffffff; - text-decoration: none; -} -#left-area button:hover { - background: #55aa55; -} -#left-area button:disabled { - background: #555555; - color: #888888; -} -#left-area button:disabled a { - background: #555555; - color: #888888; -} - -#pause-button.pending { - background: #5555ff; - animation: pulsate 0.2s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate; -} - -#attach-button { -} -#attach-button.enabled { - animation: pulsate 0.7s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate; -} - -.duktape-exec-line { - outline: 2px solid red; - background: #550000; -} -.duktape-break-line { - outline: 2px solid white; -} - -#output { - font: 9pt monospace; - color: #000000; - border: 2px solid #cccccc; - border-radius: 5px; - padding: 3px; - height: 30ex; - overflow: scroll; - overflow-x: auto; - overflow-y: scroll; - white-space: pre; -} -#output .alert { - color: #ff0000; -} -/* Default color (should be overridden by level) */ -#output .log { - color: #00ff00; -} -/* Trace */ -#output .loglevel0 { - color: #cccccc; -} -/* Debug */ -#output .loglevel1 { - color: #cccccc; -} -/* Info */ -#output .loglevel2 { - color: #888888; - font-weight: bold; -} -/* Warn */ -#output .loglevel3 { - color: #ff4444; - font-weight: bold; -} -/* Error */ -#output .loglevel4 { - color: #ff0000; - font-weight: bold; -} -/* Fatal */ -#output .loglevel5 { - background: #000000; - color: #ff0000; - font-weight: bold; -} -#output .debugger-info { - color: #880000; - font-weight: bold; - font-style: italic; -} -#output .debugger-debug { - color: #888888; - font-weight: bold; - font-style: italic; -} - -#callstack { - font: 9pt monospace; - color: #000000; - margin-top: 10px; - border: 2px solid #cccccc; - border-radius: 5px; - padding: 3px; - height: 14ex; - overflow: scroll; - overflow-x: auto; - overflow-y: scroll; - white-space: pre; -} -#callstack div:nth-child(2n) { - background: #eeeeee; -} -#callstack .func { -} -#callstack .rest { - float: right; - color: #6666ff; -} -#callstack .rest:hover { - text-decoration: underline; - color: #9999ff; -} - -#locals { - font: 9pt monospace; - color: #000000; - margin-top: 10px; - border: 2px solid #cccccc; - border-radius: 5px; - padding: 10px; - height: 30ex; - overflow: scroll; - overflow-x: auto; - overflow-y: scroll; - white-space: pre; -} -#locals div:nth-child(2n) { - background: #eeeeee; -} -#locals .key { -} -#locals .value { - float: right; - color: #888888; -} - -#breakpoints { - color: #000000; - margin-top: 10px; - border: 2px solid #cccccc; - border-radius: 5px; - padding: 3px; - height: 15ex; - overflow: scroll; - overflow-x: auto; - overflow-y: scroll; - white-space: pre; -} -#breakpoints div { - margin: 2px 0 2px 0; -} -#breakpoints div:nth-child(2n) { - background: #eeeeee; -} -#breakpoints a { - font: 9pt monospace; - color: #6666ff; -} -#breakpoints a:hover { - text-decoration: underline; - color: #9999ff; -} -.breakpoint-line { - clear: both; - padding-top: 2px; - padding-bottom: 2px; -} -#add-breakpoint-file { - font: 10pt monospace; - width: 10em; - padding: 5px; -} -#add-breakpoint-line { - font: 10pt monospace; - width: 3em; - margin-left: 3px; - padding: 5px; -} -#delete-all-breakpoints-button { - float: right; - font: 10pt sans-serif; - padding: 5px; - border: 1px solid #888888; - background: #ddffdd; - color: #000000; -} -#delete-all-breakpoints-button:hover { - background: #f8fff8; -} -#delete-all-breakpoints-button:disabled { - background: #dddddd; - color: #444444; -} -#add-breakpoint-button { - font: 10pt sans-serif; - margin-left: 10px; - padding: 5px; - border: 1px solid #888888; - background: #ddffdd; - color: #000000; -} -#add-breakpoint-button:hover { - background: #f8fff8; -} -#add-breakpoint-button:disabled { - background: #dddddd; - color: #444444; -} -#breakpoint-hint { - color: #aaaaaa; - font-style: italic; - margin-left: 10px; -} -.delete-breakpoint-button { - float: right; - display: inline; - font: 9pt sans-serif; - padding: 3px; - border: none; - background: none; - color: #6666ff; -} -.delete-breakpoint-button { - font: 9pt sans-serif; -} -.delete-breakpoint-button:hover { - text-decoration: underline; - color: #9999ff; -} -.delete-breakpoint-button:disabled { - color: #888888; -} - -#about-dialog p { - margin: 10px 0 10px 0; -} - -#bytecode-dialog p { - margin: 10px 0 10px 0; -} -#bytecode-dialog pre { - font: 14pt monospace; - color: #000000; -} - -#eval { - color: #000000; - margin-top: 10px; - border: 2px solid #cccccc; - border-radius: 5px; - padding: 3px; - height: 30ex; - overflow: scroll; - overflow-x: auto; - overflow-y: scroll; - white-space: pre; -} -#eval-input { - display: inline; - font: 10pt monospace; - width: 20em; - padding: 5px; -} -#eval-button { - display: inline; - margin-left: 10px; - padding: 5px; - border: 1px solid #888888; - font: 10pt sans-serif; - background: #ddffdd; - color: #000000; -} -#eval-button { -} -#eval-button:hover { - background: #f8fff8; -} -#eval-button:disabled { - background: #dddddd; - color: #444444; -} -#eval-button.pending { - background: #5555ff; - animation: pulsate 0.2s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate; -} -#eval-watch { - margin-left: 20px; - vertical-align: middle; -} -#eval-output { - font: 10pt monospace; - white-space: pre; - padding: 5px; - border: 1px solid #888888; - min-height: 4ex; - margin-top: 5px; -} - -#varname-input { - font: 10pt monospace; - width: 10em; - padding: 5px; -} -#varvalue-input { - margin-left: 10px; - font: 10pt monospace; - width: 20em; - padding: 5px; -} -#getvar-button, -#putvar-button { - display: inline; - float: right; - margin-left: 10px; - padding: 5px; - border: 1px solid #888888; - font: 10pt sans-serif; - background: #ddffdd; - color: #000000; -} -#getvar-button:hover, -#putvar-button:hover { - background: #f8fff8; -} -#getvar-button:disabled, -#putvar-button:disabled { - background: #dddddd; - color: #444444; -} -#var-output { - font: 10pt monospace; - white-space: pre; - padding: 5px; - border: 1px solid #888888; - min-height: 4ex; - margin-top: 5px; -} - -#source-pre { - margin-top: 10px; - border: 2px solid #cccccc; - border-radius: 5px; - height: 400px; - overflow: scroll; - overflow-x: auto; - overflow-y: scroll; -} -#source-pre.running { - background: #eeeeee; - color: #888888; -} -#source-pre.running #source-code { - background: #eeeeee; - color: #888888; -} -#source-filename { - font-size: 125%; - color: #888888; -} -code.sourcecode { - counter-reset: source-line; -} -code.sourcecode div { - font: 10pt monospace; - padding: 2px 5px 2px 5px; - white-space: pre; - border-bottom: 1px solid #eeeeee; -} -code.sourcecode div:before { - display: inline-block; - content: counter(source-line); - counter-increment: source-line; - width: 4em; - color: #888888; - text-align: right; - margin-right: 20px; -} -code.sourcecode div.breakpoint:before { - margin-right: 0px; - border-right: 20px solid #ff0000; -} -code.sourcecode div.highlight { - background: #aaaaaa; - color: #000000; -} -code.sourcecode div.execution { - background: #000000; - color: #ffffff; -} - -#source-select { - margin-top: 5px; -} diff --git a/src/third_party/duktape-1.3.0/debugger/static/webui.js b/src/third_party/duktape-1.3.0/debugger/static/webui.js deleted file mode 100644 index e3e1cc11..00000000 --- a/src/third_party/duktape-1.3.0/debugger/static/webui.js +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Duktape debugger web client - * - * Talks to the NodeJS server using socket.io. - * - * http://unixpapa.com/js/key.html - */ - -// Update interval for custom source highlighting. -var SOURCE_UPDATE_INTERVAL = 350; - -// Source view -var activeFileName = null; // file that we want to be loaded in source view -var activeLine = null; // scroll to line once file has been loaded -var activeHighlight = null; // line that we want to highlight (if any) -var loadedFileName = null; // currently loaded (shown) file -var loadedLineCount = 0; // currently loaded file line count -var loadedFileExecuting = false; // true if currFileName (loosely) matches loadedFileName -var loadedLinePending = null; // if set, scroll loaded file to requested line -var highlightLine = null; // highlight line -var sourceEditedLines = []; // line numbers which have been modified - // (added classes etc, tracked for removing) -var sourceUpdateInterval = null; // timer for updating source view -var sourceFetchXhr = null; // current AJAX request for fetching a source file (if any) -var forceButtonUpdate = false; // hack to reset button states - -// Execution state -var prevState = null; // previous execution state ('paused', 'running', etc) -var prevAttached = null; // previous debugger attached state (true, false, null) -var currFileName = null; // current filename being executed -var currFuncName = null; // current function name being executed -var currLine = 0; // current line being executed -var currPc = 0; // current bytecode PC being executed -var currState = 0; // current execution state ('paused', 'running', 'detached', etc) -var currAttached = false; // current debugger attached state (true or false) -var currLocals = []; // current local variables -var currCallstack = []; // current callstack (from top to bottom) -var currBreakpoints = []; // current breakpoints -var startedRunning = 0; // timestamp when last started running (if running) - // (used to grey out the source file if running for long enough) - -/* - * Helpers - */ - -function formatBytes(x) { - if (x < 1024) { - return String(x) + ' bytes'; - } else if (x < 1024 * 1024) { - return (x / 1024).toPrecision(3) + ' kB'; - } else { - return (x / (1024 * 1024)).toPrecision(3) + ' MB'; - } -} - -/* - * Source view periodic update handling - */ - -function doSourceUpdate() { - var elem; - - // Remove previously added custom classes - sourceEditedLines.forEach(function (linenum) { - elem = $('#source-code div')[linenum - 1]; - if (elem) { - elem.classList.remove('breakpoint'); - elem.classList.remove('execution'); - elem.classList.remove('highlight'); - } - }); - sourceEditedLines.length = 0; - - // If we're executing the file shown, highlight current line - if (loadedFileExecuting) { - elem = $('#source-code div')[currLine - 1]; - if (elem) { - sourceEditedLines.push(currLine); - elem.classList.add('execution'); - } - } - - // Add breakpoints - currBreakpoints.forEach(function (bp) { - if (bp.fileName === loadedFileName) { - elem = $('#source-code div')[bp.lineNumber - 1]; - if (elem) { - sourceEditedLines.push(bp.lineNumber); - elem.classList.add('breakpoint'); - } - } - }); - - if (highlightLine !== null) { - elem = $('#source-code div')[highlightLine - 1]; - if (elem) { - sourceEditedLines.push(highlightLine); - elem.classList.add('highlight'); - } - } - - // If no-one requested us to scroll to a specific line, finish. - if (loadedLinePending == null) { - return; - } - - var reqLine = loadedLinePending; - loadedLinePending = null; - - // Scroll to requested line. This is not very clean, so a better solution - // should be found: - // https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView - // http://erraticdev.blogspot.fi/2011/02/jquery-scroll-into-view-plugin-with.html - // http://flesler.blogspot.fi/2007/10/jqueryscrollto.html - var tmpLine = Math.max(reqLine - 5, 0); - elem = $('#source-code div')[tmpLine]; - if (elem) { - elem.scrollIntoView(); - } -} - -// Source is updated periodically. Other code can also call doSourceUpdate() -// directly if an immediate update is needed. -sourceUpdateInterval = setInterval(doSourceUpdate, SOURCE_UPDATE_INTERVAL); - -/* - * UI update handling when exec-status update arrives - */ - -function doUiUpdate() { - var now = Date.now(); - - // Note: loadedFileName can be either from target or from server, but they - // must match exactly. We could do a loose match here, but exact matches - // are needed for proper breakpoint handling anyway. - loadedFileExecuting = (loadedFileName === currFileName); - - // If we just started running, store a timestamp so we can grey out the - // source view only if we execute long enough (i.e. we're not just - // stepping). - if (currState !== prevState && currState === 'running') { - startedRunning = now; - } - - // If we just became paused, check for eval watch - if (currState !== prevState && currState === 'paused') { - if ($('#eval-watch').is(':checked')) { - submitEval(); // don't clear eval input - } - } - - // Update current execution state - if (currFileName === '' && currLine === 0) { - $('#current-fileline').text(''); - } else { - $('#current-fileline').text(String(currFileName) + ':' + String(currLine)); - } - if (currFuncName === '' && currPc === 0) { - $('#current-funcpc').text(''); - } else { - $('#current-funcpc').text(String(currFuncName) + '() pc ' + String(currPc)); - } - $('#current-state').text(String(currState)); - - // Update buttons - if (currState !== prevState || currAttached !== prevAttached || forceButtonUpdate) { - $('#stepinto-button').prop('disabled', !currAttached || currState !== 'paused'); - $('#stepover-button').prop('disabled', !currAttached || currState !== 'paused'); - $('#stepout-button').prop('disabled', !currAttached || currState !== 'paused'); - $('#resume-button').prop('disabled', !currAttached || currState !== 'paused'); - $('#pause-button').prop('disabled', !currAttached || currState !== 'running'); - $('#attach-button').prop('disabled', currAttached); - if (currAttached) { - $('#attach-button').removeClass('enabled'); - } else { - $('#attach-button').addClass('enabled'); - } - $('#detach-button').prop('disabled', !currAttached); - $('#eval-button').prop('disabled', !currAttached); - $('#add-breakpoint-button').prop('disabled', !currAttached); - $('#delete-all-breakpoints-button').prop('disabled', !currAttached); - $('.delete-breakpoint-button').prop('disabled', !currAttached); - $('#putvar-button').prop('disabled', !currAttached); - $('#getvar-button').prop('disabled', !currAttached); - $('#heap-dump-download-button').prop('disabled', !currAttached); - } - if (currState !== 'running' || forceButtonUpdate) { - // Remove pending highlight once we're no longer running. - $('#pause-button').removeClass('pending'); - $('#eval-button').removeClass('pending'); - } - forceButtonUpdate = false; - - // Make source window grey when running for a longer time, use a small - // delay to avoid flashing grey when stepping. - if (currState === 'running' && now - startedRunning >= 500) { - $('#source-pre').removeClass('notrunning'); - $('#current-state').removeClass('notrunning'); - } else { - $('#source-pre').addClass('notrunning'); - $('#current-state').addClass('notrunning'); - } - - // Force source view to match currFileName only when running or when - // just became paused (from running or detached). - var fetchSource = false; - if (typeof currFileName === 'string') { - if (currState === 'running' || - (prevState !== 'paused' && currState === 'paused') || - (currAttached !== prevAttached)) { - if (activeFileName !== currFileName) { - fetchSource = true; - activeFileName = currFileName; - activeLine = currLine; - activeHighlight = null; - requestSourceRefetch(); - } - } - } - - // Force line update (scrollTop) only when running or just became paused. - // Otherwise let user browse and scroll source files freely. - if (!fetchSource) { - if ((prevState !== 'paused' && currState === 'paused') || - currState === 'running') { - loadedLinePending = currLine || 0; - } - } -} - -/* - * Init socket.io and add handlers - */ - -var socket = io(); // returns a Manager - -setInterval(function () { - socket.emit('keepalive', { - userAgent: (navigator || {}).userAgent - }); -}, 30000); - -socket.on('connect', function () { - $('#socketio-info').text('connected'); - currState = 'connected'; - - fetchSourceList(); -}); -socket.on('disconnect', function () { - $('#socketio-info').text('not connected'); - currState = 'disconnected'; -}); -socket.on('reconnecting', function () { - $('#socketio-info').text('reconnecting'); - currState = 'reconnecting'; -}); -socket.on('error', function (err) { - $('#socketio-info').text(err); -}); - -socket.on('replaced', function () { - // XXX: how to minimize the chance we'll further communciate with the - // server or reconnect to it? socket.reconnection()? - - // We'd like to window.close() here but can't (not allowed from scripts). - // Alert is the next best thing. - alert('Debugger connection replaced by a new one, do you have multiple tabs open? If so, please close this tab.'); -}); - -socket.on('keepalive', function (msg) { - // Not really interesting in the UI - // $('#server-info').text(new Date() + ': ' + JSON.stringify(msg)); -}); - -socket.on('basic-info', function (msg) { - $('#duk-version').text(String(msg.duk_version)); - $('#duk-git-describe').text(String(msg.duk_git_describe)); - $('#target-info').text(String(msg.target_info)); - $('#endianness').text(String(msg.endianness)); -}); - -socket.on('exec-status', function (msg) { - currFileName = msg.fileName; - currFuncName = msg.funcName; - currLine = msg.line; - currPc = msg.pc; - currState = msg.state; - currAttached = msg.attached; - - // Duktape now restricts execution status updates quite effectively so - // there's no need to rate limit UI updates now. - - doUiUpdate(); - - prevState = currState; - prevAttached = currAttached; -}); - -// Update the "console" output based on lines sent by the server. The server -// rate limits these updates to keep the browser load under control. Even -// better would be for the client to pull this (and other stuff) on its own. -socket.on('output-lines', function (msg) { - var elem = $('#output'); - var i, n, ent; - - elem.empty(); - for (i = 0, n = msg.length; i < n; i++) { - ent = msg[i]; - if (ent.type === 'print') { - elem.append($('
').text(ent.message)); - } else if (ent.type === 'alert') { - elem.append($('
').text(ent.message)); - } else if (ent.type === 'log') { - elem.append($('
').text(ent.message)); - } else if (ent.type === 'debugger-info') { - elem.append($('
').text(ent.message)); - } else if (ent.type === 'debugger-debug') { - elem.append($('
').text(ent.message)); - } else { - elem.append($('
').text(ent.message)); - } - } - - // http://stackoverflow.com/questions/14918787/jquery-scroll-to-bottom-of-div-even-after-it-updates - // Stop queued animations so that we always scroll quickly to bottom - $('#output').stop(true); - $('#output').animate({ scrollTop: $('#output')[0].scrollHeight}, 1000); -}); - -socket.on('callstack', function (msg) { - var elem = $('#callstack'); - var s1, s2, div; - - currCallstack = msg.callstack; - - elem.empty(); - msg.callstack.forEach(function (e) { - s1 = $('').text(e.fileName + ':' + e.lineNumber + ' (pc ' + e.pc + ')'); // float - s1.on('click', function () { - activeFileName = e.fileName; - activeLine = e.lineNumber || 1; - activeHighlight = activeLine; - requestSourceRefetch(); - }); - s2 = $('').text(e.funcName + '()'); - div = $('
'); - div.append(s1); - div.append(s2); - elem.append(div); - }); -}); - -socket.on('locals', function (msg) { - var elem = $('#locals'); - var s1, s2, div; - var i, n, e; - - currLocals = msg.locals; - - elem.empty(); - for (i = 0, n = msg.locals.length; i < n; i++) { - e = msg.locals[i]; - s1 = $('').text(e.value); // float - s2 = $('').text(e.key); - div = $('
'); - div.append(s1); - div.append(s2); - elem.append(div); - } -}); - -socket.on('debug-stats', function (msg) { - $('#debug-rx-bytes').text(formatBytes(msg.rxBytes)); - $('#debug-rx-dvalues').text(msg.rxDvalues); - $('#debug-rx-messages').text(msg.rxMessages); - $('#debug-rx-kbrate').text((msg.rxBytesPerSec / 1024).toFixed(2)); - $('#debug-tx-bytes').text(formatBytes(msg.txBytes)); - $('#debug-tx-dvalues').text(msg.txDvalues); - $('#debug-tx-messages').text(msg.txMessages); - $('#debug-tx-kbrate').text((msg.txBytesPerSec / 1024).toFixed(2)); -}); - -socket.on('breakpoints', function (msg) { - var elem = $('#breakpoints'); - var div; - var sub; - - currBreakpoints = msg.breakpoints; - - elem.empty(); - - // First line is special - div = $('
'); - sub = $('').text('Delete all breakpoints'); - sub.on('click', function () { - socket.emit('delete-all-breakpoints'); - }); - div.append(sub); - sub = $('').val('file.js'); - div.append(sub); - sub = $('').text(':'); - div.append(sub); - sub = $('').val('123'); - div.append(sub); - sub = $('').text('Add breakpoint'); - sub.on('click', function () { - socket.emit('add-breakpoint', { - fileName: $('#add-breakpoint-file').val(), - lineNumber: Number($('#add-breakpoint-line').val()) - }); - }); - div.append(sub); - sub = $('').text('or dblclick source'); - div.append(sub); - elem.append(div); - - // Active breakpoints follow - msg.breakpoints.forEach(function (bp) { - var div; - var sub; - - div = $('
'); - sub = $('').text('Delete'); - sub.on('click', function () { - socket.emit('delete-breakpoint', { - fileName: bp.fileName, - lineNumber: bp.lineNumber - }); - }); - div.append(sub); - sub = $('').text((bp.fileName || '?') + ':' + (bp.lineNumber || 0)); - sub.on('click', function () { - activeFileName = bp.fileName || ''; - activeLine = bp.lineNumber || 1; - activeHighlight = activeLine; - requestSourceRefetch(); - }); - div.append(sub); - elem.append(div); - }); - - forceButtonUpdate = true; - doUiUpdate(); -}); - -socket.on('eval-result', function (msg) { - $('#eval-output').text((msg.error ? 'ERROR: ' : '') + msg.result); - - // Remove eval button "pulsating" glow when we get a result - $('#eval-button').removeClass('pending'); -}); - -socket.on('getvar-result', function (msg) { - $('#var-output').text(msg.found ? msg.result : 'NOTFOUND'); -}); - -socket.on('bytecode', function (msg) { - $('#bytecode-preformatted').text(msg.preformatted); - $('#bytecode-dialog').dialog('open'); -}); - -$('#stepinto-button').click(function () { - socket.emit('stepinto', {}); -}); - -$('#stepover-button').click(function () { - socket.emit('stepover', {}); -}); - -$('#stepout-button').click(function () { - socket.emit('stepout', {}); -}); - -$('#pause-button').click(function () { - socket.emit('pause', {}); - - // Pause may take seconds to complete so indicate it is pending. - $('#pause-button').addClass('pending'); -}); - -$('#resume-button').click(function () { - socket.emit('resume', {}); -}); - -$('#attach-button').click(function () { - socket.emit('attach', {}); -}); - -$('#detach-button').click(function () { - socket.emit('detach', {}); -}); - -$('#about-button').click(function () { - $('#about-dialog').dialog('open'); -}); - -$('#show-bytecode-button').click(function () { - socket.emit('get-bytecode', {}); -}); - -function submitEval() { - socket.emit('eval', { input: $('#eval-input').val() }); - - // Eval may take seconds to complete so indicate it is pending. - $('#eval-button').addClass('pending'); -} - -$('#eval-button').click(function () { - submitEval(); - $('#eval-input').val(''); -}); - -$('#getvar-button').click(function () { - socket.emit('getvar', { varname: $('#varname-input').val() }); -}); - -$('#putvar-button').click(function () { - // The variable value is parsed as JSON right now, but it'd be better to - // also be able to parse buffer values etc. - var val = JSON.parse($('#varvalue-input').val()); - socket.emit('putvar', { varname: $('#varname-input').val(), varvalue: val }); -}); - -$('#source-code').dblclick(function (event) { - var target = event.target; - var elems = $('#source-code div'); - var i, n; - var line = 0; - - // XXX: any faster way; elems doesn't have e.g. indexOf() - for (i = 0, n = elems.length; i < n; i++) { - if (target === elems[i]) { - line = i + 1; - } - } - - socket.emit('toggle-breakpoint', { - fileName: loadedFileName, - lineNumber: line - }); -}); - -function setSourceText(data) { - var elem, div; - - elem = $('#source-code'); - elem.empty(); - data.split('\n').forEach(function (line) { - div = $('
'); - div.text(line); - elem.append(div); - }); - - sourceEditedLines = []; -} - -function setSourceSelect(fileName) { - var elem; - var i, n, t; - - if (fileName == null) { - $('#source-select').val('__none__'); - return; - } - - elem = $('#source-select option'); - for (i = 0, n = elem.length; i < n; i++) { - // Exact match is required. - t = $(elem[i]).val(); - if (t === fileName) { - $('#source-select').val(t); - return; - } - } -} - -/* - * AJAX request handling to fetch source files - */ - -function requestSourceRefetch() { - // If previous update is pending, abort and start a new one. - if (sourceFetchXhr) { - sourceFetchXhr.abort(); - sourceFetchXhr = null; - } - - // Make copies of the requested file/line so that we have the proper - // values in case they've changed. - var fileName = activeFileName; - var lineNumber = activeLine; - - // AJAX request for the source. - sourceFetchXhr = $.ajax({ - type: 'POST', - url: '/source', - data: JSON.stringify({ fileName: fileName }), - contentType: 'application/json', - success: function (data, status, jqxhr) { - var elem; - - sourceFetchXhr = null; - - loadedFileName = fileName; - loadedLineCount = data.split('\n').length; // XXX: ignore issue with last empty line for now - loadedFileExecuting = (loadedFileName === currFileName); - setSourceText(data); - setSourceSelect(fileName); - loadedLinePending = activeLine || 1; - highlightLine = activeHighlight; // may be null - activeLine = null; - activeHighlight = null; - doSourceUpdate(); - - // XXX: hacky transition, make source change visible - $('#source-pre').fadeTo('fast', 0.25, function () { - $('#source-pre').fadeTo('fast', 1.0); - }); - }, - error: function (jqxhr, status, err) { - // Not worth alerting about because source fetch errors happen - // all the time, e.g. for dynamically evaluated code. - - sourceFetchXhr = null; - - // XXX: prevent retry of no-such-file by negative caching? - loadedFileName = fileName; - loadedLineCount = 1; - loadedFileExecuting = false; - setSourceText('// Cannot load source file: ' + fileName); - setSourceSelect(null); - loadedLinePending = 1; - activeLine = null; - activeHighlight = null; - doSourceUpdate(); - - // XXX: error transition here - $('#source-pre').fadeTo('fast', 0.25, function () { - $('#source-pre').fadeTo('fast', 1.0); - }); - }, - dataType: 'text' - }); -} - -/* - * AJAX request for fetching the source list - */ - -function fetchSourceList() { - $.ajax({ - type: 'POST', - url: '/sourceList', - data: JSON.stringify({}), - contentType: 'application/json', - success: function (data, status, jqxhr) { - var elem = $('#source-select'); - - data = JSON.parse(data); - - elem.empty(); - var opt = $('').attr({ 'value': '__none__' }).text('No source file selected'); - elem.append(opt); - data.forEach(function (ent) { - var opt = $('').attr({ 'value': ent }).text(ent); - elem.append(opt); - }); - elem.change(function () { - activeFileName = elem.val(); - activeLine = 1; - requestSourceRefetch(); - }); - }, - error: function (jqxhr, status, err) { - // This is worth alerting about as the UI is somewhat unusable - // if we don't get a source list. - - alert('Failed to load source list: ' + err); - }, - dataType: 'text' - }); -} - -/* - * Initialization - */ - -$(document).ready(function () { - var showAbout = true; - - // About dialog, shown automatically on first startup. - $('#about-dialog').dialog({ - autoOpen: false, - hide: 'fade', // puff - show: 'fade', // slide, puff - width: 500, - height: 300 - }); - - // Bytecode dialog - $('#bytecode-dialog').dialog({ - autoOpen: false, - hide: 'fade', // puff - show: 'fade', // slide, puff - width: 1000, - height: 800 - }); - - // http://diveintohtml5.info/storage.html - if (typeof localStorage !== 'undefined') { - if (localStorage.getItem('about-shown')) { - showAbout = false; - } else { - localStorage.setItem('about-shown', 'yes'); - } - } - if (showAbout) { - $('#about-dialog').dialog('open'); - } - - // onclick handler for exec status text - function loadCurrFunc() { - activeFileName = currFileName; - activeLine = currLine; - requestSourceRefetch(); - } - $('#exec-other').on('click', loadCurrFunc); - - // Enter handling for eval input - // https://forum.jquery.com/topic/bind-html-input-to-enter-key-keypress - $('#eval-input').keypress(function (event) { - if (event.keyCode == 13) { - submitEval(); - $('#eval-input').val(''); - } - }); - - // Eval watch handling - $('#eval-watch').change(function () { - // nop - }); - - forceButtonUpdate = true; - doUiUpdate(); -}); diff --git a/src/third_party/duktape-1.3.0/duk_build_meta.json b/src/third_party/duktape-1.3.0/duk_build_meta.json deleted file mode 100644 index faf177a5..00000000 --- a/src/third_party/duktape-1.3.0/duk_build_meta.json +++ /dev/null @@ -1,838 +0,0 @@ -{ - "builtin_strings": [ - "Logger", - "Thread", - "Pointer", - "DecEnv", - "ObjEnv", - "Float64Array", - "Float32Array", - "Uint32Array", - "Int32Array", - "Uint16Array", - "Int16Array", - "Uint8ClampedArray", - "Uint8Array", - "Int8Array", - "DataView", - "ArrayBuffer", - "Buffer", - "", - "global", - "Arguments", - "JSON", - "Math", - "Error", - "RegExp", - "Date", - "Number", - "Boolean", - "String", - "Array", - "Function", - "Object", - "Null", - "Undefined", - "{_func:true}", - "{\"_func\":true}", - "{\"_ninf\":true}", - "{\"_inf\":true}", - "{\"_nan\":true}", - "{\"_undef\":true}", - "toLogString", - "clog", - "l", - "n", - "fatal", - "error", - "warn", - "debug", - "trace", - "raw", - "fmt", - "current", - "resume", - "compact", - "jc", - "jx", - "base64", - "hex", - "dec", - "enc", - "fin", - "gc", - "act", - "info", - "version", - "env", - "modLoaded", - "modSearch", - "errThrow", - "errCreate", - "compile", - "\u0000Regbase", - "\u0000Thread", - "\u0000Handler", - "\u0000Finalizer", - "\u0000Callee", - "\u0000Map", - "\u0000Args", - "\u0000This", - "\u0000Pc2line", - "\u0000Source", - "\u0000Varenv", - "\u0000Lexenv", - "\u0000Varmap", - "\u0000Formals", - "\u0000Bytecode", - "\u0000Next", - "\u0000Target", - "\u0000Value", - "pointer", - "\u0000Tracedata", - "lineNumber", - "fileName", - "pc", - "stack", - "ThrowTypeError", - "Duktape", - "setFloat64", - "setFloat32", - "setUint32", - "setInt32", - "setUint16", - "setInt16", - "setUint8", - "setInt8", - "getFloat64", - "getFloat32", - "getUint32", - "getInt32", - "getUint16", - "getInt16", - "getUint8", - "getInt8", - "subarray", - "BYTES_PER_ELEMENT", - "byteOffset", - "buffer", - "isView", - "data", - "type", - "writeIntBE", - "writeIntLE", - "writeUIntBE", - "writeUIntLE", - "writeDoubleBE", - "writeDoubleLE", - "writeFloatBE", - "writeFloatLE", - "writeInt32BE", - "writeInt32LE", - "writeUInt32BE", - "writeUInt32LE", - "writeInt16BE", - "writeInt16LE", - "writeUInt16BE", - "writeUInt16LE", - "writeInt8", - "writeUInt8", - "readIntBE", - "readIntLE", - "readUIntBE", - "readUIntLE", - "readDoubleBE", - "readDoubleLE", - "readFloatBE", - "readFloatLE", - "readInt32BE", - "readInt32LE", - "readUInt32BE", - "readUInt32LE", - "readInt16BE", - "readInt16LE", - "readUInt16BE", - "readUInt16LE", - "readInt8", - "readUInt8", - "copy", - "equals", - "fill", - "write", - "compare", - "byteLength", - "isBuffer", - "isEncoding", - "exports", - "id", - "require", - "__proto__", - "setPrototypeOf", - "ownKeys", - "enumerate", - "deleteProperty", - "has", - "Proxy", - "callee", - "Invalid Date", - "[...]", - "\n\t", - " ", - ",", - "-0", - "+0", - "0", - "-Infinity", - "+Infinity", - "Infinity", - "object", - "string", - "number", - "boolean", - "undefined", - "stringify", - "tan", - "sqrt", - "sin", - "round", - "random", - "pow", - "min", - "max", - "log", - "floor", - "exp", - "cos", - "ceil", - "atan2", - "atan", - "asin", - "acos", - "abs", - "SQRT2", - "SQRT1_2", - "PI", - "LOG10E", - "LOG2E", - "LN2", - "LN10", - "E", - "message", - "name", - "input", - "index", - "(?:)", - "lastIndex", - "multiline", - "ignoreCase", - "source", - "test", - "exec", - "toGMTString", - "setYear", - "getYear", - "toJSON", - "toISOString", - "toUTCString", - "setUTCFullYear", - "setFullYear", - "setUTCMonth", - "setMonth", - "setUTCDate", - "setDate", - "setUTCHours", - "setHours", - "setUTCMinutes", - "setMinutes", - "setUTCSeconds", - "setSeconds", - "setUTCMilliseconds", - "setMilliseconds", - "setTime", - "getTimezoneOffset", - "getUTCMilliseconds", - "getMilliseconds", - "getUTCSeconds", - "getSeconds", - "getUTCMinutes", - "getMinutes", - "getUTCHours", - "getHours", - "getUTCDay", - "getDay", - "getUTCDate", - "getDate", - "getUTCMonth", - "getMonth", - "getUTCFullYear", - "getFullYear", - "getTime", - "toLocaleTimeString", - "toLocaleDateString", - "toTimeString", - "toDateString", - "now", - "UTC", - "parse", - "toPrecision", - "toExponential", - "toFixed", - "POSITIVE_INFINITY", - "NEGATIVE_INFINITY", - "NaN", - "MIN_VALUE", - "MAX_VALUE", - "substr", - "trim", - "toLocaleUpperCase", - "toUpperCase", - "toLocaleLowerCase", - "toLowerCase", - "substring", - "split", - "search", - "replace", - "match", - "localeCompare", - "charCodeAt", - "charAt", - "fromCharCode", - "reduceRight", - "reduce", - "filter", - "map", - "forEach", - "some", - "every", - "lastIndexOf", - "indexOf", - "unshift", - "splice", - "sort", - "slice", - "shift", - "reverse", - "push", - "pop", - "join", - "concat", - "isArray", - "arguments", - "caller", - "bind", - "call", - "apply", - "propertyIsEnumerable", - "isPrototypeOf", - "hasOwnProperty", - "valueOf", - "toLocaleString", - "toString", - "constructor", - "set", - "get", - "enumerable", - "configurable", - "writable", - "value", - "keys", - "isExtensible", - "isFrozen", - "isSealed", - "preventExtensions", - "freeze", - "seal", - "defineProperties", - "defineProperty", - "create", - "getOwnPropertyNames", - "getOwnPropertyDescriptor", - "getPrototypeOf", - "prototype", - "length", - "alert", - "print", - "unescape", - "escape", - "encodeURIComponent", - "encodeURI", - "decodeURIComponent", - "decodeURI", - "isFinite", - "isNaN", - "parseFloat", - "parseInt", - "eval", - "URIError", - "TypeError", - "SyntaxError", - "ReferenceError", - "RangeError", - "EvalError", - "break", - "case", - "catch", - "continue", - "debugger", - "default", - "delete", - "do", - "else", - "finally", - "for", - "function", - "if", - "in", - "instanceof", - "new", - "return", - "switch", - "this", - "throw", - "try", - "typeof", - "var", - "void", - "while", - "with", - "class", - "const", - "enum", - "export", - "extends", - "import", - "super", - "null", - "true", - "false", - "implements", - "interface", - "let", - "package", - "private", - "protected", - "public", - "static", - "yield" - ], - "builtin_strings_base64": [ - "TG9nZ2Vy", - "VGhyZWFk", - "UG9pbnRlcg==", - "RGVjRW52", - "T2JqRW52", - "RmxvYXQ2NEFycmF5", - "RmxvYXQzMkFycmF5", - "VWludDMyQXJyYXk=", - "SW50MzJBcnJheQ==", - "VWludDE2QXJyYXk=", - "SW50MTZBcnJheQ==", - "VWludDhDbGFtcGVkQXJyYXk=", - "VWludDhBcnJheQ==", - "SW50OEFycmF5", - "RGF0YVZpZXc=", - "QXJyYXlCdWZmZXI=", - "QnVmZmVy", - "", - "Z2xvYmFs", - "QXJndW1lbnRz", - "SlNPTg==", - "TWF0aA==", - "RXJyb3I=", - "UmVnRXhw", - "RGF0ZQ==", - "TnVtYmVy", - "Qm9vbGVhbg==", - "U3RyaW5n", - "QXJyYXk=", - "RnVuY3Rpb24=", - "T2JqZWN0", - "TnVsbA==", - "VW5kZWZpbmVk", - "e19mdW5jOnRydWV9", - "eyJfZnVuYyI6dHJ1ZX0=", - "eyJfbmluZiI6dHJ1ZX0=", - "eyJfaW5mIjp0cnVlfQ==", - "eyJfbmFuIjp0cnVlfQ==", - "eyJfdW5kZWYiOnRydWV9", - "dG9Mb2dTdHJpbmc=", - "Y2xvZw==", - "bA==", - "bg==", - "ZmF0YWw=", - "ZXJyb3I=", - "d2Fybg==", - "ZGVidWc=", - "dHJhY2U=", - "cmF3", - "Zm10", - "Y3VycmVudA==", - "cmVzdW1l", - "Y29tcGFjdA==", - "amM=", - "ang=", - "YmFzZTY0", - "aGV4", - "ZGVj", - "ZW5j", - "Zmlu", - "Z2M=", - "YWN0", - "aW5mbw==", - "dmVyc2lvbg==", - "ZW52", - "bW9kTG9hZGVk", - "bW9kU2VhcmNo", - "ZXJyVGhyb3c=", - "ZXJyQ3JlYXRl", - "Y29tcGlsZQ==", - "/1JlZ2Jhc2U=", - "/1RocmVhZA==", - "/0hhbmRsZXI=", - "/0ZpbmFsaXplcg==", - "/0NhbGxlZQ==", - "/01hcA==", - "/0FyZ3M=", - "/1RoaXM=", - "/1BjMmxpbmU=", - "/1NvdXJjZQ==", - "/1ZhcmVudg==", - "/0xleGVudg==", - "/1Zhcm1hcA==", - "/0Zvcm1hbHM=", - "/0J5dGVjb2Rl", - "/05leHQ=", - "/1RhcmdldA==", - "/1ZhbHVl", - "cG9pbnRlcg==", - "/1RyYWNlZGF0YQ==", - "bGluZU51bWJlcg==", - "ZmlsZU5hbWU=", - "cGM=", - "c3RhY2s=", - "VGhyb3dUeXBlRXJyb3I=", - "RHVrdGFwZQ==", - "c2V0RmxvYXQ2NA==", - "c2V0RmxvYXQzMg==", - "c2V0VWludDMy", - "c2V0SW50MzI=", - "c2V0VWludDE2", - "c2V0SW50MTY=", - "c2V0VWludDg=", - "c2V0SW50OA==", - "Z2V0RmxvYXQ2NA==", - "Z2V0RmxvYXQzMg==", - "Z2V0VWludDMy", - "Z2V0SW50MzI=", - "Z2V0VWludDE2", - "Z2V0SW50MTY=", - "Z2V0VWludDg=", - "Z2V0SW50OA==", - "c3ViYXJyYXk=", - "QllURVNfUEVSX0VMRU1FTlQ=", - "Ynl0ZU9mZnNldA==", - "YnVmZmVy", - "aXNWaWV3", - "ZGF0YQ==", - "dHlwZQ==", - "d3JpdGVJbnRCRQ==", - "d3JpdGVJbnRMRQ==", - "d3JpdGVVSW50QkU=", - "d3JpdGVVSW50TEU=", - "d3JpdGVEb3VibGVCRQ==", - "d3JpdGVEb3VibGVMRQ==", - "d3JpdGVGbG9hdEJF", - "d3JpdGVGbG9hdExF", - "d3JpdGVJbnQzMkJF", - "d3JpdGVJbnQzMkxF", - "d3JpdGVVSW50MzJCRQ==", - "d3JpdGVVSW50MzJMRQ==", - "d3JpdGVJbnQxNkJF", - "d3JpdGVJbnQxNkxF", - "d3JpdGVVSW50MTZCRQ==", - "d3JpdGVVSW50MTZMRQ==", - "d3JpdGVJbnQ4", - "d3JpdGVVSW50OA==", - "cmVhZEludEJF", - "cmVhZEludExF", - "cmVhZFVJbnRCRQ==", - "cmVhZFVJbnRMRQ==", - "cmVhZERvdWJsZUJF", - "cmVhZERvdWJsZUxF", - "cmVhZEZsb2F0QkU=", - "cmVhZEZsb2F0TEU=", - "cmVhZEludDMyQkU=", - "cmVhZEludDMyTEU=", - "cmVhZFVJbnQzMkJF", - "cmVhZFVJbnQzMkxF", - "cmVhZEludDE2QkU=", - "cmVhZEludDE2TEU=", - "cmVhZFVJbnQxNkJF", - "cmVhZFVJbnQxNkxF", - "cmVhZEludDg=", - "cmVhZFVJbnQ4", - "Y29weQ==", - "ZXF1YWxz", - "ZmlsbA==", - "d3JpdGU=", - "Y29tcGFyZQ==", - "Ynl0ZUxlbmd0aA==", - "aXNCdWZmZXI=", - "aXNFbmNvZGluZw==", - "ZXhwb3J0cw==", - "aWQ=", - "cmVxdWlyZQ==", - "X19wcm90b19f", - "c2V0UHJvdG90eXBlT2Y=", - "b3duS2V5cw==", - "ZW51bWVyYXRl", - "ZGVsZXRlUHJvcGVydHk=", - "aGFz", - "UHJveHk=", - "Y2FsbGVl", - "SW52YWxpZCBEYXRl", - "Wy4uLl0=", - "Cgk=", - "IA==", - "LA==", - "LTA=", - "KzA=", - "MA==", - "LUluZmluaXR5", - "K0luZmluaXR5", - "SW5maW5pdHk=", - "b2JqZWN0", - "c3RyaW5n", - "bnVtYmVy", - "Ym9vbGVhbg==", - "dW5kZWZpbmVk", - "c3RyaW5naWZ5", - "dGFu", - "c3FydA==", - "c2lu", - "cm91bmQ=", - "cmFuZG9t", - "cG93", - "bWlu", - "bWF4", - "bG9n", - "Zmxvb3I=", - "ZXhw", - "Y29z", - "Y2VpbA==", - "YXRhbjI=", - "YXRhbg==", - "YXNpbg==", - "YWNvcw==", - "YWJz", - "U1FSVDI=", - "U1FSVDFfMg==", - "UEk=", - "TE9HMTBF", - "TE9HMkU=", - "TE4y", - "TE4xMA==", - "RQ==", - "bWVzc2FnZQ==", - "bmFtZQ==", - "aW5wdXQ=", - "aW5kZXg=", - "KD86KQ==", - "bGFzdEluZGV4", - "bXVsdGlsaW5l", - "aWdub3JlQ2FzZQ==", - "c291cmNl", - "dGVzdA==", - "ZXhlYw==", - "dG9HTVRTdHJpbmc=", - "c2V0WWVhcg==", - "Z2V0WWVhcg==", - "dG9KU09O", - "dG9JU09TdHJpbmc=", - "dG9VVENTdHJpbmc=", - "c2V0VVRDRnVsbFllYXI=", - "c2V0RnVsbFllYXI=", - "c2V0VVRDTW9udGg=", - "c2V0TW9udGg=", - "c2V0VVRDRGF0ZQ==", - "c2V0RGF0ZQ==", - "c2V0VVRDSG91cnM=", - "c2V0SG91cnM=", - "c2V0VVRDTWludXRlcw==", - "c2V0TWludXRlcw==", - "c2V0VVRDU2Vjb25kcw==", - "c2V0U2Vjb25kcw==", - "c2V0VVRDTWlsbGlzZWNvbmRz", - "c2V0TWlsbGlzZWNvbmRz", - "c2V0VGltZQ==", - "Z2V0VGltZXpvbmVPZmZzZXQ=", - "Z2V0VVRDTWlsbGlzZWNvbmRz", - "Z2V0TWlsbGlzZWNvbmRz", - "Z2V0VVRDU2Vjb25kcw==", - "Z2V0U2Vjb25kcw==", - "Z2V0VVRDTWludXRlcw==", - "Z2V0TWludXRlcw==", - "Z2V0VVRDSG91cnM=", - "Z2V0SG91cnM=", - "Z2V0VVRDRGF5", - "Z2V0RGF5", - "Z2V0VVRDRGF0ZQ==", - "Z2V0RGF0ZQ==", - "Z2V0VVRDTW9udGg=", - "Z2V0TW9udGg=", - "Z2V0VVRDRnVsbFllYXI=", - "Z2V0RnVsbFllYXI=", - "Z2V0VGltZQ==", - "dG9Mb2NhbGVUaW1lU3RyaW5n", - "dG9Mb2NhbGVEYXRlU3RyaW5n", - "dG9UaW1lU3RyaW5n", - "dG9EYXRlU3RyaW5n", - "bm93", - "VVRD", - "cGFyc2U=", - "dG9QcmVjaXNpb24=", - "dG9FeHBvbmVudGlhbA==", - "dG9GaXhlZA==", - "UE9TSVRJVkVfSU5GSU5JVFk=", - "TkVHQVRJVkVfSU5GSU5JVFk=", - "TmFO", - "TUlOX1ZBTFVF", - "TUFYX1ZBTFVF", - "c3Vic3Ry", - "dHJpbQ==", - "dG9Mb2NhbGVVcHBlckNhc2U=", - "dG9VcHBlckNhc2U=", - "dG9Mb2NhbGVMb3dlckNhc2U=", - "dG9Mb3dlckNhc2U=", - "c3Vic3RyaW5n", - "c3BsaXQ=", - "c2VhcmNo", - "cmVwbGFjZQ==", - "bWF0Y2g=", - "bG9jYWxlQ29tcGFyZQ==", - "Y2hhckNvZGVBdA==", - "Y2hhckF0", - "ZnJvbUNoYXJDb2Rl", - "cmVkdWNlUmlnaHQ=", - "cmVkdWNl", - "ZmlsdGVy", - "bWFw", - "Zm9yRWFjaA==", - "c29tZQ==", - "ZXZlcnk=", - "bGFzdEluZGV4T2Y=", - "aW5kZXhPZg==", - "dW5zaGlmdA==", - "c3BsaWNl", - "c29ydA==", - "c2xpY2U=", - "c2hpZnQ=", - "cmV2ZXJzZQ==", - "cHVzaA==", - "cG9w", - "am9pbg==", - "Y29uY2F0", - "aXNBcnJheQ==", - "YXJndW1lbnRz", - "Y2FsbGVy", - "YmluZA==", - "Y2FsbA==", - "YXBwbHk=", - "cHJvcGVydHlJc0VudW1lcmFibGU=", - "aXNQcm90b3R5cGVPZg==", - "aGFzT3duUHJvcGVydHk=", - "dmFsdWVPZg==", - "dG9Mb2NhbGVTdHJpbmc=", - "dG9TdHJpbmc=", - "Y29uc3RydWN0b3I=", - "c2V0", - "Z2V0", - "ZW51bWVyYWJsZQ==", - "Y29uZmlndXJhYmxl", - "d3JpdGFibGU=", - "dmFsdWU=", - "a2V5cw==", - "aXNFeHRlbnNpYmxl", - "aXNGcm96ZW4=", - "aXNTZWFsZWQ=", - "cHJldmVudEV4dGVuc2lvbnM=", - "ZnJlZXpl", - "c2VhbA==", - "ZGVmaW5lUHJvcGVydGllcw==", - "ZGVmaW5lUHJvcGVydHk=", - "Y3JlYXRl", - "Z2V0T3duUHJvcGVydHlOYW1lcw==", - "Z2V0T3duUHJvcGVydHlEZXNjcmlwdG9y", - "Z2V0UHJvdG90eXBlT2Y=", - "cHJvdG90eXBl", - "bGVuZ3Ro", - "YWxlcnQ=", - "cHJpbnQ=", - "dW5lc2NhcGU=", - "ZXNjYXBl", - "ZW5jb2RlVVJJQ29tcG9uZW50", - "ZW5jb2RlVVJJ", - "ZGVjb2RlVVJJQ29tcG9uZW50", - "ZGVjb2RlVVJJ", - "aXNGaW5pdGU=", - "aXNOYU4=", - "cGFyc2VGbG9hdA==", - "cGFyc2VJbnQ=", - "ZXZhbA==", - "VVJJRXJyb3I=", - "VHlwZUVycm9y", - "U3ludGF4RXJyb3I=", - "UmVmZXJlbmNlRXJyb3I=", - "UmFuZ2VFcnJvcg==", - "RXZhbEVycm9y", - "YnJlYWs=", - "Y2FzZQ==", - "Y2F0Y2g=", - "Y29udGludWU=", - "ZGVidWdnZXI=", - "ZGVmYXVsdA==", - "ZGVsZXRl", - "ZG8=", - "ZWxzZQ==", - "ZmluYWxseQ==", - "Zm9y", - "ZnVuY3Rpb24=", - "aWY=", - "aW4=", - "aW5zdGFuY2VvZg==", - "bmV3", - "cmV0dXJu", - "c3dpdGNo", - "dGhpcw==", - "dGhyb3c=", - "dHJ5", - "dHlwZW9m", - "dmFy", - "dm9pZA==", - "d2hpbGU=", - "d2l0aA==", - "Y2xhc3M=", - "Y29uc3Q=", - "ZW51bQ==", - "ZXhwb3J0", - "ZXh0ZW5kcw==", - "aW1wb3J0", - "c3VwZXI=", - "bnVsbA==", - "dHJ1ZQ==", - "ZmFsc2U=", - "aW1wbGVtZW50cw==", - "aW50ZXJmYWNl", - "bGV0", - "cGFja2FnZQ==", - "cHJpdmF0ZQ==", - "cHJvdGVjdGVk", - "cHVibGlj", - "c3RhdGlj", - "eWllbGQ=" - ], - "comment": "Metadata for Duktape build", - "duk_version": 10300, - "duk_version_string": "1.3.0", - "git_describe": "v1.3.0" -} \ No newline at end of file diff --git a/src/third_party/duktape-1.3.0/examples/README.rst b/src/third_party/duktape-1.3.0/examples/README.rst deleted file mode 100644 index f2544328..00000000 --- a/src/third_party/duktape-1.3.0/examples/README.rst +++ /dev/null @@ -1,10 +0,0 @@ -================ -Duktape examples -================ - -Examples for using Duktape. These support user documentation and are -intended as informative illustrations only. - -Examples are unmaintained and are not production quality code. Bugs are -not not necessarily fixed, unless the bug makes the example misleading -as documentation. diff --git a/src/third_party/duktape-1.3.0/examples/alloc-hybrid/README.rst b/src/third_party/duktape-1.3.0/examples/alloc-hybrid/README.rst deleted file mode 100644 index ed63a13c..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-hybrid/README.rst +++ /dev/null @@ -1,10 +0,0 @@ -===================== -Hybrid pool allocator -===================== - -Example allocator that tries to satisfy memory allocations for small sizes -from a set of fixed pools, but always falls back to malloc/realloc/free if -a larger size is requested or the pools have been exhausted. - -This may be useful to reduce memory churn when the platform allocator does -not handle allocations for a lot of small memory areas efficiently. diff --git a/src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.c b/src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.c deleted file mode 100644 index 9235b857..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Example memory allocator with pool allocation for small sizes and - * fallback into malloc/realloc/free for larger sizes or when the pools - * are exhausted. - * - * Useful to reduce memory churn or work around a platform allocator - * that doesn't handle a lot of small allocations efficiently. - */ - -#include "duktape.h" -#include -#include -#include -#include - -/* Define to enable some debug printfs. */ -/* #define DUK_ALLOC_HYBRID_DEBUG */ - -typedef struct { - size_t size; - int count; -} pool_size_spec; - -static pool_size_spec pool_sizes[] = { - { 32, 1024 }, - { 48, 2048 }, - { 64, 2048 }, - { 128, 2048 }, - { 256, 512 }, - { 1024, 64 }, - { 2048, 32 } -}; - -#define NUM_POOLS (sizeof(pool_sizes) / sizeof(pool_size_spec)) - -/* This must fit into the smallest pool entry. */ -struct pool_free_entry; -typedef struct pool_free_entry pool_free_entry; -struct pool_free_entry { - pool_free_entry *next; -}; - -typedef struct { - pool_free_entry *free; - char *alloc_start; - char *alloc_end; - size_t size; - int count; -} pool_header; - -typedef struct { - pool_header headers[NUM_POOLS]; - size_t pool_max_size; - char *alloc_start; - char *alloc_end; -} pool_state; - -#define ADDR_IN_STATE_ALLOC(st,p) \ - ((char *) (p) >= (st)->alloc_start && (char *) (p) < (st)->alloc_end) -#define ADDR_IN_HEADER_ALLOC(hdr,p) \ - ((char *) (p) >= (hdr)->alloc_start && (char *) (p) < (hdr)->alloc_end) - -#ifdef DUK_ALLOC_HYBRID_DEBUG -static void dump_pool_state(pool_state *st) { - pool_free_entry *free; - int free_len; - int i; - - printf("=== Pool state: st=%p\n", (void *) st); - for (i = 0; i < (int) NUM_POOLS; i++) { - pool_header *hdr = st->headers + i; - - for (free = hdr->free, free_len = 0; free != NULL; free = free->next) { - free_len++; - } - - printf("[%d]: size %ld, count %ld, used %ld, free list len %ld\n", - i, (long) hdr->size, (long) hdr->count, - (long) (hdr->count - free_len), - (long) free_len); - } -} -#else -static void dump_pool_state(pool_state *st) { - (void) st; -} -#endif - -void *duk_alloc_hybrid_init(void) { - pool_state *st; - size_t total_size, max_size; - int i, j; - char *p; - - st = (pool_state *) malloc(sizeof(pool_state)); - if (!st) { - return NULL; - } - memset((void *) st, 0, sizeof(pool_state)); - st->alloc_start = NULL; - st->alloc_end = NULL; - - for (i = 0, total_size = 0, max_size = 0; i < (int) NUM_POOLS; i++) { -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("Pool %d: size %ld, count %ld\n", i, (long) pool_sizes[i].size, (long) pool_sizes[i].count); -#endif - total_size += pool_sizes[i].size * pool_sizes[i].count; - if (pool_sizes[i].size > max_size) { - max_size = pool_sizes[i].size; - } - } -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("Total size %ld, max pool size %ld\n", (long) total_size, (long) max_size); -#endif - - st->alloc_start = (char *) malloc(total_size); - if (!st->alloc_start) { - free(st); - return NULL; - } - st->alloc_end = st->alloc_start + total_size; - st->pool_max_size = max_size; - memset((void *) st->alloc_start, 0, total_size); - - for (i = 0, p = st->alloc_start; i < (int) NUM_POOLS; i++) { - pool_header *hdr = st->headers + i; - - hdr->alloc_start = p; - hdr->alloc_end = p + pool_sizes[i].size * pool_sizes[i].count; - hdr->free = (pool_free_entry *) (void *) p; - hdr->size = pool_sizes[i].size; - hdr->count = pool_sizes[i].count; - - for (j = 0; j < pool_sizes[i].count; j++) { - pool_free_entry *ent = (pool_free_entry *) (void *) p; - if (j == pool_sizes[i].count - 1) { - ent->next = (pool_free_entry *) NULL; - } else { - ent->next = (pool_free_entry *) (void *) (p + pool_sizes[i].size); - } - p += pool_sizes[i].size; - } - } - - dump_pool_state(st); - - /* Use 'st' as udata. */ - return (void *) st; -} - -void *duk_alloc_hybrid(void *udata, duk_size_t size) { - pool_state *st = (pool_state *) udata; - int i; - void *new_ptr; - -#if 0 - dump_pool_state(st); -#endif - - if (size == 0) { - return NULL; - } - if (size > st->pool_max_size) { -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("alloc fallback: %ld\n", (long) size); -#endif - return malloc(size); - } - - for (i = 0; i < (int) NUM_POOLS; i++) { - pool_header *hdr = st->headers + i; - if (hdr->size < size) { - continue; - } - - if (hdr->free) { -#if 0 - printf("alloc from pool: %ld -> pool size %ld\n", (long) size, (long) hdr->size); -#endif - new_ptr = (void *) hdr->free; - hdr->free = hdr->free->next; - return new_ptr; - } else { -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("alloc out of pool entries: %ld -> pool size %ld\n", (long) size, (long) hdr->size); -#endif - break; - } - } - -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("alloc fallback (out of pool): %ld\n", (long) size); -#endif - return malloc(size); -} - -void *duk_realloc_hybrid(void *udata, void *ptr, duk_size_t size) { - pool_state *st = (pool_state *) udata; - void *new_ptr; - int i; - -#if 0 - dump_pool_state(st); -#endif - - if (ADDR_IN_STATE_ALLOC(st, ptr)) { - /* 'ptr' cannot be NULL. */ - for (i = 0; i < (int) NUM_POOLS; i++) { - pool_header *hdr = st->headers + i; - if (ADDR_IN_HEADER_ALLOC(hdr, ptr)) { - if (size <= hdr->size) { - /* Still fits, no shrink support. */ -#if 0 - printf("realloc original from pool: still fits, size %ld, pool size %ld\n", - (long) size, (long) hdr->size); -#endif - return ptr; - } - - new_ptr = duk_alloc_hybrid(udata, size); - if (!new_ptr) { -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("realloc original from pool: needed larger size, failed to alloc\n"); -#endif - return NULL; - } - memcpy(new_ptr, ptr, hdr->size); - - ((pool_free_entry *) ptr)->next = hdr->free; - hdr->free = (pool_free_entry *) ptr; -#if 0 - printf("realloc original from pool: size %ld, pool size %ld\n", (long) size, (long) hdr->size); -#endif - return new_ptr; - } - } -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("NEVER HERE\n"); -#endif - return NULL; - } else if (ptr != NULL) { - if (size == 0) { - free(ptr); - return NULL; - } else { -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("realloc fallback: size %ld\n", (long) size); -#endif - return realloc(ptr, size); - } - } else { -#if 0 - printf("realloc NULL ptr, call alloc: %ld\n", (long) size); -#endif - return duk_alloc_hybrid(udata, size); - } -} - -void duk_free_hybrid(void *udata, void *ptr) { - pool_state *st = (pool_state *) udata; - int i; - -#if 0 - dump_pool_state(st); -#endif - - if (!ADDR_IN_STATE_ALLOC(st, ptr)) { - if (ptr == NULL) { - return; - } -#if 0 - printf("free out of pool: %p\n", (void *) ptr); -#endif - free(ptr); - return; - } - - for (i = 0; i < (int) NUM_POOLS; i++) { - pool_header *hdr = st->headers + i; - if (ADDR_IN_HEADER_ALLOC(hdr, ptr)) { - ((pool_free_entry *) ptr)->next = hdr->free; - hdr->free = (pool_free_entry *) ptr; -#if 0 - printf("free from pool: %p\n", ptr); -#endif - return; - } - } - -#ifdef DUK_ALLOC_HYBRID_DEBUG - printf("NEVER HERE\n"); -#endif -} diff --git a/src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.h b/src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.h deleted file mode 100644 index 0d631d1d..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef DUK_ALLOC_HYBRID_H_INCLUDED -#define DUK_ALLOC_HYBRID_H_INCLUDED - -#include "duktape.h" - -void *duk_alloc_hybrid_init(void); -void *duk_alloc_hybrid(void *udata, duk_size_t size); -void *duk_realloc_hybrid(void *udata, void *ptr, duk_size_t size); -void duk_free_hybrid(void *udata, void *ptr); - -#endif /* DUK_ALLOC_HYBRID_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/examples/alloc-logging/README.rst b/src/third_party/duktape-1.3.0/examples/alloc-logging/README.rst deleted file mode 100644 index 97c1a32a..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-logging/README.rst +++ /dev/null @@ -1,7 +0,0 @@ -====================== -Allocator with logging -====================== - -Example allocator that writes all memory alloc/realloc/free calls into a -log file so that memory usage can replayed later. This is useful to e.g. -optimize pool sizes. diff --git a/src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.c b/src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.c deleted file mode 100644 index 86fecc56..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Example memory allocator with machine parseable logging. - * - * Also sizes for reallocs and frees are logged so that the memory - * behavior can be essentially replayed to accurately determine e.g. - * optimal pool sizes for a pooled allocator. - * - * Allocation structure: - * - * [ alloc_hdr | user area ] - * - * ^ ^ - * | `--- pointer returned to Duktape - * `--- underlying malloc ptr - */ - -#include "duktape.h" -#include -#include -#include -#include - -#define ALLOC_LOG_FILE "/tmp/duk-alloc-log.txt" - -typedef struct { - /* The double value in the union is there to ensure alignment is - * good for IEEE doubles too. In many 32-bit environments 4 bytes - * would be sufficiently aligned and the double value is unnecessary. - */ - union { - size_t sz; - double d; - } u; -} alloc_hdr; - -static FILE *log_file = NULL; - -static void write_log(const char *fmt, ...) { - va_list ap; - - if (!log_file) { - log_file = fopen(ALLOC_LOG_FILE, "wb"); - if (!log_file) { - return; - } - } - - va_start(ap, fmt); - vfprintf(log_file, fmt, ap); - va_end(ap); -} - -void *duk_alloc_logging(void *udata, duk_size_t size) { - alloc_hdr *hdr; - void *ret; - - (void) udata; /* Suppress warning. */ - - if (size == 0) { - write_log("A NULL %ld\n", (long) size); - return NULL; - } - - hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr)); - if (!hdr) { - write_log("A FAIL %ld\n", (long) size); - return NULL; - } - hdr->u.sz = size; - ret = (void *) (hdr + 1); - write_log("A %p %ld\n", ret, (long) size); - return ret; -} - -void *duk_realloc_logging(void *udata, void *ptr, duk_size_t size) { - alloc_hdr *hdr; - size_t old_size; - void *t; - void *ret; - - (void) udata; /* Suppress warning. */ - - /* Handle the ptr-NULL vs. size-zero cases explicitly to minimize - * platform assumptions. You can get away with much less in specific - * well-behaving environments. - */ - - if (ptr) { - hdr = (alloc_hdr *) (void *) ((unsigned char *) ptr - sizeof(alloc_hdr)); - old_size = hdr->u.sz; - - if (size == 0) { - free((void *) hdr); - write_log("R %p %ld NULL 0\n", ptr, (long) old_size); - return NULL; - } else { - t = realloc((void *) hdr, size + sizeof(alloc_hdr)); - if (!t) { - write_log("R %p %ld FAIL %ld\n", ptr, (long) old_size, (long) size); - return NULL; - } - hdr = (alloc_hdr *) t; - hdr->u.sz = size; - ret = (void *) (hdr + 1); - write_log("R %p %ld %p %ld\n", ptr, (long) old_size, ret, (long) size); - return ret; - } - } else { - if (size == 0) { - write_log("R NULL 0 NULL 0\n"); - return NULL; - } else { - hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr)); - if (!hdr) { - write_log("R NULL 0 FAIL %ld\n", (long) size); - return NULL; - } - hdr->u.sz = size; - ret = (void *) (hdr + 1); - write_log("R NULL 0 %p %ld\n", ret, (long) size); - return ret; - } - } -} - -void duk_free_logging(void *udata, void *ptr) { - alloc_hdr *hdr; - - (void) udata; /* Suppress warning. */ - - if (!ptr) { - write_log("F NULL 0\n"); - return; - } - hdr = (alloc_hdr *) (void *) ((unsigned char *) ptr - sizeof(alloc_hdr)); - write_log("F %p %ld\n", ptr, (long) hdr->u.sz); - free((void *) hdr); -} diff --git a/src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.h b/src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.h deleted file mode 100644 index 67003531..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DUK_ALLOC_LOGGING_H_INCLUDED -#define DUK_ALLOC_LOGGING_H_INCLUDED - -#include "duktape.h" - -void *duk_alloc_logging(void *udata, duk_size_t size); -void *duk_realloc_logging(void *udata, void *ptr, duk_size_t size); -void duk_free_logging(void *udata, void *ptr); - -#endif /* DUK_ALLOC_LOGGING_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/examples/alloc-logging/log2gnuplot.py b/src/third_party/duktape-1.3.0/examples/alloc-logging/log2gnuplot.py deleted file mode 100644 index 7562814d..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-logging/log2gnuplot.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/python -# -# Analyze allocator logs and write total-bytes-in-use after every -# operation to stdout. The output can be gnuplotted as: -# -# $ python log2gnuplot.py /tmp/output.txt -# $ gnuplot -# > plot "output.txt" with lines -# - -import os -import sys - -def main(): - allocated = 0 - - for line in sys.stdin: - line = line.strip() - parts = line.split(' ') - - # A ptr/NULL/FAIL size - # F ptr/NULL size - # R ptr/NULL oldsize ptr/NULL/FAIL newsize - - # Note: ajduk doesn't log oldsize (uses -1 instead) - - if parts[0] == 'A': - if parts[1] != 'NULL' and parts[1] != 'FAIL': - allocated += long(parts[2]) - elif parts[0] == 'F': - allocated -= long(parts[2]) - elif parts[0] == 'R': - allocated -= long(parts[2]) - if parts[3] != 'NULL' and parts[3] != 'FAIL': - allocated += long(parts[4]) - print(allocated) - - print(allocated) - -if __name__ == '__main__': - main() diff --git a/src/third_party/duktape-1.3.0/examples/alloc-torture/README.rst b/src/third_party/duktape-1.3.0/examples/alloc-torture/README.rst deleted file mode 100644 index f3278bbf..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-torture/README.rst +++ /dev/null @@ -1,10 +0,0 @@ -========================================== -Allocator with memory wiping and red zones -========================================== - -Example allocator that wipes memory on free and checks that no out-of-bounds -writes have been made to bytes just before and after the allocated area. - -Valgrind is a better tool for detecting these memory issues, but it's not -available for all targets so you can use something like this to detect -memory lifecycle or out-of-bounds issues. diff --git a/src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.c b/src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.c deleted file mode 100644 index abca2f75..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Example torture memory allocator with memory wiping and check for - * out-of-bounds writes. - * - * Allocation structure: - * - * [ alloc_hdr | red zone before | user area | red zone after ] - * - * ^ ^ - * | `--- pointer returned to Duktape - * `--- underlying malloc ptr - */ - -#include "duktape.h" -#include -#include -#include -#include - -#define RED_ZONE_SIZE 16 -#define RED_ZONE_BYTE 0x5a -#define INIT_BYTE 0xa5 -#define WIPE_BYTE 0x27 - -typedef struct { - /* The double value in the union is there to ensure alignment is - * good for IEEE doubles too. In many 32-bit environments 4 bytes - * would be sufficiently aligned and the double value is unnecessary. - */ - union { - size_t sz; - double d; - } u; -} alloc_hdr; - -static void check_red_zone(alloc_hdr *hdr) { - size_t size; - int i; - int err; - unsigned char *p; - unsigned char *userptr; - - size = hdr->u.sz; - userptr = (unsigned char *) hdr + sizeof(alloc_hdr) + RED_ZONE_SIZE; - - err = 0; - p = (unsigned char *) hdr + sizeof(alloc_hdr); - for (i = 0; i < RED_ZONE_SIZE; i++) { - if (p[i] != RED_ZONE_BYTE) { - err = 1; - } - } - if (err) { - fprintf(stderr, "RED ZONE CORRUPTED BEFORE ALLOC: hdr=%p ptr=%p size=%ld\n", - (void *) hdr, (void *) userptr, (long) size); - fflush(stderr); - } - - err = 0; - p = (unsigned char *) hdr + sizeof(alloc_hdr) + RED_ZONE_SIZE + size; - for (i = 0; i < RED_ZONE_SIZE; i++) { - if (p[i] != RED_ZONE_BYTE) { - err = 1; - } - } - if (err) { - fprintf(stderr, "RED ZONE CORRUPTED AFTER ALLOC: hdr=%p ptr=%p size=%ld\n", - (void *) hdr, (void *) userptr, (long) size); - fflush(stderr); - } -} - -void *duk_alloc_torture(void *udata, duk_size_t size) { - unsigned char *p; - - (void) udata; /* Suppress warning. */ - - if (size == 0) { - return NULL; - } - - p = (unsigned char *) malloc(size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); - if (!p) { - return NULL; - } - - ((alloc_hdr *) (void *) p)->u.sz = size; - p += sizeof(alloc_hdr); - memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); - p += RED_ZONE_SIZE; - memset((void *) p, INIT_BYTE, size); - p += size; - memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); - p -= size; - return (void *) p; -} - -void *duk_realloc_torture(void *udata, void *ptr, duk_size_t size) { - unsigned char *p, *old_p; - size_t old_size; - - (void) udata; /* Suppress warning. */ - - /* Handle the ptr-NULL vs. size-zero cases explicitly to minimize - * platform assumptions. You can get away with much less in specific - * well-behaving environments. - */ - - if (ptr) { - old_p = (unsigned char *) ptr - sizeof(alloc_hdr) - RED_ZONE_SIZE; - old_size = ((alloc_hdr *) (void *) old_p)->u.sz; - check_red_zone((alloc_hdr *) (void *) old_p); - - if (size == 0) { - memset((void *) old_p, WIPE_BYTE, old_size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); - free((void *) old_p); - return NULL; - } else { - /* Force address change on every realloc. */ - p = (unsigned char *) malloc(size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); - if (!p) { - return NULL; - } - - ((alloc_hdr *) (void *) p)->u.sz = size; - p += sizeof(alloc_hdr); - memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); - p += RED_ZONE_SIZE; - if (size > old_size) { - memcpy((void *) p, (void *) (old_p + sizeof(alloc_hdr) + RED_ZONE_SIZE), old_size); - memset((void *) (p + old_size), INIT_BYTE, size - old_size); - } else { - memcpy((void *) p, (void *) (old_p + sizeof(alloc_hdr) + RED_ZONE_SIZE), size); - } - p += size; - memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); - p -= size; - - memset((void *) old_p, WIPE_BYTE, old_size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); - free((void *) old_p); - - return (void *) p; - } - } else { - if (size == 0) { - return NULL; - } else { - p = (unsigned char *) malloc(size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); - if (!p) { - return NULL; - } - - ((alloc_hdr *) (void *) p)->u.sz = size; - p += sizeof(alloc_hdr); - memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); - p += RED_ZONE_SIZE; - memset((void *) p, INIT_BYTE, size); - p += size; - memset((void *) p, RED_ZONE_BYTE, RED_ZONE_SIZE); - p -= size; - return (void *) p; - } - } -} - -void duk_free_torture(void *udata, void *ptr) { - unsigned char *p; - size_t old_size; - - (void) udata; /* Suppress warning. */ - - if (!ptr) { - return; - } - - p = (unsigned char *) ptr - sizeof(alloc_hdr) - RED_ZONE_SIZE; - old_size = ((alloc_hdr *) (void *) p)->u.sz; - - check_red_zone((alloc_hdr *) (void *) p); - memset((void *) p, WIPE_BYTE, old_size + sizeof(alloc_hdr) + 2 * RED_ZONE_SIZE); - free((void *) p); -} diff --git a/src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.h b/src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.h deleted file mode 100644 index a12153a2..00000000 --- a/src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DUK_ALLOC_TORTURE_H_INCLUDED -#define DUK_ALLOC_TORTURE_H_INCLUDED - -#include "duktape.h" - -void *duk_alloc_torture(void *udata, duk_size_t size); -void *duk_realloc_torture(void *udata, void *ptr, duk_size_t size); -void duk_free_torture(void *udata, void *ptr); - -#endif /* DUK_ALLOC_TORTURE_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/examples/cmdline/README.rst b/src/third_party/duktape-1.3.0/examples/cmdline/README.rst deleted file mode 100644 index e0c6bceb..00000000 --- a/src/third_party/duktape-1.3.0/examples/cmdline/README.rst +++ /dev/null @@ -1,6 +0,0 @@ -==================== -Duktape command line -==================== - -Ecmascript command line execution tool, useful for running Ecmascript code -from a file, stdin, or interactively. Also used by automatic testing. diff --git a/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline.c b/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline.c deleted file mode 100644 index df61cdf9..00000000 --- a/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline.c +++ /dev/null @@ -1,873 +0,0 @@ -/* - * Command line execution tool. Useful for test cases and manual testing. - * - * To enable readline and other fancy stuff, compile with -DDUK_CMDLINE_FANCY. - * It is not the default to maximize portability. You can also compile in - * support for example allocators, grep for DUK_CMDLINE_*. - */ - -#ifndef DUK_CMDLINE_FANCY -#define NO_READLINE -#define NO_RLIMIT -#define NO_SIGNAL -#endif - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ - defined(WIN64) || defined(_WIN64) || defined(__WIN64__) -/* Suppress warnings about plain fopen() etc. */ -#define _CRT_SECURE_NO_WARNINGS -#endif - -#define GREET_CODE(variant) \ - "print('((o) Duktape" variant " ' + " \ - "Math.floor(Duktape.version / 10000) + '.' + " \ - "Math.floor(Duktape.version / 100) % 100 + '.' + " \ - "Duktape.version % 100" \ - ", '(" DUK_GIT_DESCRIBE ")');" - -#include -#include -#include -#ifndef NO_SIGNAL -#include -#endif -#ifndef NO_RLIMIT -#include -#endif -#ifndef NO_READLINE -#include -#include -#endif -#ifdef DUK_CMDLINE_ALLOC_LOGGING -#include "duk_alloc_logging.h" -#endif -#ifdef DUK_CMDLINE_ALLOC_TORTURE -#include "duk_alloc_torture.h" -#endif -#ifdef DUK_CMDLINE_ALLOC_HYBRID -#include "duk_alloc_hybrid.h" -#endif -#include "duktape.h" - -#ifdef DUK_CMDLINE_AJSHEAP -/* Defined in duk_cmdline_ajduk.c or alljoyn.js headers. */ -void ajsheap_init(void); -void ajsheap_dump(void); -void ajsheap_register(duk_context *ctx); -void ajsheap_start_exec_timeout(void); -void ajsheap_clear_exec_timeout(void); -void *ajsheap_alloc_wrapped(void *udata, duk_size_t size); -void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size); -void ajsheap_free_wrapped(void *udata, void *ptr); -void *AJS_Alloc(void *udata, duk_size_t size); -void *AJS_Realloc(void *udata, void *ptr, duk_size_t size); -void AJS_Free(void *udata, void *ptr); -#endif - -#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT -#include "duk_trans_socket.h" -#endif - -#define MEM_LIMIT_NORMAL (128*1024*1024) /* 128 MB */ -#define MEM_LIMIT_HIGH (2047*1024*1024) /* ~2 GB */ -#define LINEBUF_SIZE 65536 - -static int interactive_mode = 0; - -#ifndef NO_RLIMIT -static void set_resource_limits(rlim_t mem_limit_value) { - int rc; - struct rlimit lim; - - rc = getrlimit(RLIMIT_AS, &lim); - if (rc != 0) { - fprintf(stderr, "Warning: cannot read RLIMIT_AS\n"); - return; - } - - if (lim.rlim_max < mem_limit_value) { - fprintf(stderr, "Warning: rlim_max < mem_limit_value (%d < %d)\n", (int) lim.rlim_max, (int) mem_limit_value); - return; - } - - lim.rlim_cur = mem_limit_value; - lim.rlim_max = mem_limit_value; - - rc = setrlimit(RLIMIT_AS, &lim); - if (rc != 0) { - fprintf(stderr, "Warning: setrlimit failed\n"); - return; - } - -#if 0 - fprintf(stderr, "Set RLIMIT_AS to %d\n", (int) mem_limit_value); -#endif -} -#endif /* NO_RLIMIT */ - -#ifndef NO_SIGNAL -static void my_sighandler(int x) { - fprintf(stderr, "Got signal %d\n", x); - fflush(stderr); -} -static void set_sigint_handler(void) { - (void) signal(SIGINT, my_sighandler); -} -#endif /* NO_SIGNAL */ - -static int get_stack_raw(duk_context *ctx) { - if (!duk_is_object(ctx, -1)) { - return 1; - } - if (!duk_has_prop_string(ctx, -1, "stack")) { - return 1; - } - if (!duk_is_error(ctx, -1)) { - /* Not an Error instance, don't read "stack". */ - return 1; - } - - duk_get_prop_string(ctx, -1, "stack"); /* caller coerces */ - duk_remove(ctx, -2); - return 1; -} - -/* Print error to stderr and pop error. */ -static void print_pop_error(duk_context *ctx, FILE *f) { - /* Print error objects with a stack trace specially. - * Note that getting the stack trace may throw an error - * so this also needs to be safe call wrapped. - */ - (void) duk_safe_call(ctx, get_stack_raw, 1 /*nargs*/, 1 /*nrets*/); - fprintf(f, "%s\n", duk_safe_to_string(ctx, -1)); - fflush(f); - duk_pop(ctx); -} - -static int wrapped_compile_execute(duk_context *ctx) { - const char *src_data; - duk_size_t src_len; - int comp_flags; - - /* XXX: Here it'd be nice to get some stats for the compilation result - * when a suitable command line is given (e.g. code size, constant - * count, function count. These are available internally but not through - * the public API. - */ - - /* Use duk_compile_lstring_filename() variant which avoids interning - * the source code. This only really matters for low memory environments. - */ - - /* [ ... bytecode_filename src_data src_len filename ] */ - - src_data = (const char *) duk_require_pointer(ctx, -3); - src_len = (duk_size_t) duk_require_uint(ctx, -2); - - if (src_data != NULL && src_len >= 2 && src_data[0] == (char) 0xff) { - /* Bytecode. */ - duk_push_lstring(ctx, src_data, src_len); - duk_to_buffer(ctx, -1, NULL); - duk_load_function(ctx); - } else { - /* Source code. */ - comp_flags = 0; - duk_compile_lstring_filename(ctx, comp_flags, src_data, src_len); - } - - /* [ ... bytecode_filename src_data src_len function ] */ - - /* Optional bytecode dump. */ - if (duk_is_string(ctx, -4)) { - FILE *f; - void *bc_ptr; - duk_size_t bc_len; - size_t wrote; - - duk_dup_top(ctx); - duk_dump_function(ctx); - bc_ptr = duk_require_buffer(ctx, -1, &bc_len); - f = fopen(duk_require_string(ctx, -5), "wb"); - if (!f) { - duk_error(ctx, DUK_ERR_ERROR, "failed to open bytecode output file"); - } - wrote = fwrite(bc_ptr, 1, (size_t) bc_len, f); /* XXX: handle partial writes */ - (void) fclose(f); - if (wrote != bc_len) { - duk_error(ctx, DUK_ERR_ERROR, "failed to write all bytecode"); - } - - return 0; /* duk_safe_call() cleans up */ - } - -#if 0 - /* Manual test for bytecode dump/load cycle: dump and load before - * execution. Enable manually, then run "make qecmatest" for a - * reasonably good coverage of different functions and programs. - */ - duk_dump_function(ctx); - duk_load_function(ctx); -#endif - -#if defined(DUK_CMDLINE_AJSHEAP) - ajsheap_start_exec_timeout(); -#endif - - duk_push_global_object(ctx); /* 'this' binding */ - duk_call_method(ctx, 0); - -#if defined(DUK_CMDLINE_AJSHEAP) - ajsheap_clear_exec_timeout(); -#endif - - if (interactive_mode) { - /* - * In interactive mode, write to stdout so output won't - * interleave as easily. - * - * NOTE: the ToString() coercion may fail in some cases; - * for instance, if you evaluate: - * - * ( {valueOf: function() {return {}}, - * toString: function() {return {}}}); - * - * The error is: - * - * TypeError: failed to coerce with [[DefaultValue]] - * duk_api.c:1420 - * - * These are handled now by the caller which also has stack - * trace printing support. User code can print out errors - * safely using duk_safe_to_string(). - */ - - fprintf(stdout, "= %s\n", duk_to_string(ctx, -1)); - fflush(stdout); - } else { - /* In non-interactive mode, success results are not written at all. - * It is important that the result value is not string coerced, - * as the string coercion may cause an error in some cases. - */ - } - - return 0; /* duk_safe_call() cleans up */ -} - -static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename) { - char *buf = NULL; - int len; - size_t got; - int rc; - int retval = -1; - - if (fseek(f, 0, SEEK_END) < 0) { - goto error; - } - len = (int) ftell(f); - if (fseek(f, 0, SEEK_SET) < 0) { - goto error; - } - buf = (char *) malloc(len); - if (!buf) { - goto error; - } - - got = fread((void *) buf, (size_t) 1, (size_t) len, f); - - duk_push_string(ctx, bytecode_filename); - duk_push_pointer(ctx, (void *) buf); - duk_push_uint(ctx, (duk_uint_t) got); - duk_push_string(ctx, filename); - - interactive_mode = 0; /* global */ - - rc = duk_safe_call(ctx, wrapped_compile_execute, 4 /*nargs*/, 1 /*nret*/); - -#if defined(DUK_CMDLINE_AJSHEAP) - ajsheap_clear_exec_timeout(); -#endif - - free(buf); - buf = NULL; - - if (rc != DUK_EXEC_SUCCESS) { - print_pop_error(ctx, stderr); - goto error; - } else { - duk_pop(ctx); - retval = 0; - } - /* fall thru */ - - cleanup: - if (buf) { - free(buf); - } - return retval; - - error: - fprintf(stderr, "error in executing file %s\n", filename); - fflush(stderr); - goto cleanup; -} - -static int handle_file(duk_context *ctx, const char *filename, const char *bytecode_filename) { - FILE *f = NULL; - int retval; - - f = fopen(filename, "rb"); - if (!f) { - fprintf(stderr, "failed to open source file: %s\n", filename); - fflush(stderr); - goto error; - } - - retval = handle_fh(ctx, f, filename, bytecode_filename); - - fclose(f); - return retval; - - error: - return -1; -} - -static int handle_eval(duk_context *ctx, const char *code) { - int rc; - int retval = -1; - - duk_push_pointer(ctx, (void *) code); - duk_push_uint(ctx, (duk_uint_t) strlen(code)); - duk_push_string(ctx, "eval"); - - interactive_mode = 0; /* global */ - - rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); - -#if defined(DUK_CMDLINE_AJSHEAP) - ajsheap_clear_exec_timeout(); -#endif - - if (rc != DUK_EXEC_SUCCESS) { - print_pop_error(ctx, stderr); - } else { - duk_pop(ctx); - retval = 0; - } - - return retval; -} - -#ifdef NO_READLINE -static int handle_interactive(duk_context *ctx) { - const char *prompt = "duk> "; - char *buffer = NULL; - int retval = 0; - int rc; - int got_eof = 0; - - duk_eval_string(ctx, GREET_CODE(" [no readline]")); - duk_pop(ctx); - - buffer = (char *) malloc(LINEBUF_SIZE); - if (!buffer) { - fprintf(stderr, "failed to allocated a line buffer\n"); - fflush(stderr); - retval = -1; - goto done; - } - - while (!got_eof) { - size_t idx = 0; - - fwrite(prompt, 1, strlen(prompt), stdout); - fflush(stdout); - - for (;;) { - int c = fgetc(stdin); - if (c == EOF) { - got_eof = 1; - break; - } else if (c == '\n') { - break; - } else if (idx >= LINEBUF_SIZE) { - fprintf(stderr, "line too long\n"); - fflush(stderr); - retval = -1; - goto done; - } else { - buffer[idx++] = (char) c; - } - } - - duk_push_pointer(ctx, (void *) buffer); - duk_push_uint(ctx, (duk_uint_t) idx); - duk_push_string(ctx, "input"); - - interactive_mode = 1; /* global */ - - rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); - -#if defined(DUK_CMDLINE_AJSHEAP) - ajsheap_clear_exec_timeout(); -#endif - - if (rc != DUK_EXEC_SUCCESS) { - /* in interactive mode, write to stdout */ - print_pop_error(ctx, stdout); - retval = -1; /* an error 'taints' the execution */ - } else { - duk_pop(ctx); - } - } - - done: - if (buffer) { - free(buffer); - buffer = NULL; - } - - return retval; -} -#else /* NO_READLINE */ -static int handle_interactive(duk_context *ctx) { - const char *prompt = "duk> "; - char *buffer = NULL; - int retval = 0; - int rc; - - duk_eval_string(ctx, GREET_CODE("")); - duk_pop(ctx); - - /* - * Note: using readline leads to valgrind-reported leaks inside - * readline itself. Execute code from an input file (and not - * through stdin) for clean valgrind runs. - */ - - rl_initialize(); - - for (;;) { - if (buffer) { - free(buffer); - buffer = NULL; - } - - buffer = readline(prompt); - if (!buffer) { - break; - } - - if (buffer && buffer[0] != (char) 0) { - add_history(buffer); - } - - duk_push_pointer(ctx, (void *) buffer); - duk_push_uint(ctx, (duk_uint_t) strlen(buffer)); - duk_push_string(ctx, "input"); - - interactive_mode = 1; /* global */ - - rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/); - -#if defined(DUK_CMDLINE_AJSHEAP) - ajsheap_clear_exec_timeout(); -#endif - - if (buffer) { - free(buffer); - buffer = NULL; - } - - if (rc != DUK_EXEC_SUCCESS) { - /* in interactive mode, write to stdout */ - print_pop_error(ctx, stdout); - retval = -1; /* an error 'taints' the execution */ - } else { - duk_pop(ctx); - } - } - - if (buffer) { - free(buffer); - buffer = NULL; - } - - return retval; -} -#endif /* NO_READLINE */ - -#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT -static void debugger_detached(void *udata) { - fprintf(stderr, "Debugger detached, udata: %p\n", (void *) udata); - fflush(stderr); -} -#endif - -#define ALLOC_DEFAULT 0 -#define ALLOC_LOGGING 1 -#define ALLOC_TORTURE 2 -#define ALLOC_HYBRID 3 -#define ALLOC_AJSHEAP 4 - -static duk_context *create_duktape_heap(int alloc_provider, int debugger) { - duk_context *ctx; - - ctx = NULL; - if (!ctx && alloc_provider == ALLOC_LOGGING) { -#ifdef DUK_CMDLINE_ALLOC_LOGGING - ctx = duk_create_heap(duk_alloc_logging, - duk_realloc_logging, - duk_free_logging, - (void *) 0xdeadbeef, - NULL); -#else - fprintf(stderr, "Warning: option --alloc-logging ignored, no logging allocator support\n"); - fflush(stderr); -#endif - } - if (!ctx && alloc_provider == ALLOC_TORTURE) { -#ifdef DUK_CMDLINE_ALLOC_TORTURE - ctx = duk_create_heap(duk_alloc_torture, - duk_realloc_torture, - duk_free_torture, - (void *) 0xdeadbeef, - NULL); -#else - fprintf(stderr, "Warning: option --alloc-torture ignored, no torture allocator support\n"); - fflush(stderr); -#endif - } - if (!ctx && alloc_provider == ALLOC_HYBRID) { -#ifdef DUK_CMDLINE_ALLOC_HYBRID - void *udata = duk_alloc_hybrid_init(); - if (!udata) { - fprintf(stderr, "Failed to init hybrid allocator\n"); - fflush(stderr); - } else { - ctx = duk_create_heap(duk_alloc_hybrid, - duk_realloc_hybrid, - duk_free_hybrid, - udata, - NULL); - } -#else - fprintf(stderr, "Warning: option --alloc-hybrid ignored, no hybrid allocator support\n"); - fflush(stderr); -#endif - } - if (!ctx && alloc_provider == ALLOC_AJSHEAP) { -#ifdef DUK_CMDLINE_AJSHEAP - ajsheap_init(); - - ctx = duk_create_heap( - ajsheap_log ? ajsheap_alloc_wrapped : AJS_Alloc, - ajsheap_log ? ajsheap_realloc_wrapped : AJS_Realloc, - ajsheap_log ? ajsheap_free_wrapped : AJS_Free, - (void *) 0xdeadbeef, /* heap_udata: ignored by AjsHeap, use as marker */ - NULL - ); /* fatal_handler */ -#else - fprintf(stderr, "Warning: option --alloc-ajsheap ignored, no ajsheap allocator support\n"); - fflush(stderr); -#endif - } - if (!ctx && alloc_provider == ALLOC_DEFAULT) { - ctx = duk_create_heap_default(); - } - - if (!ctx) { - fprintf(stderr, "Failed to create Duktape heap\n"); - fflush(stderr); - exit(-1); - } - -#ifdef DUK_CMDLINE_AJSHEAP - if (alloc_provider == ALLOC_AJSHEAP) { - fprintf(stdout, "Pool dump after heap creation\n"); - ajsheap_dump(); - } -#endif - -#ifdef DUK_CMDLINE_AJSHEAP - if (alloc_provider == ALLOC_AJSHEAP) { - ajsheap_register(ctx); - } -#endif - - if (debugger) { -#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT - fprintf(stderr, "Debugger enabled, create socket and wait for connection\n"); - fflush(stderr); - duk_trans_socket_init(); - duk_trans_socket_waitconn(); - fprintf(stderr, "Debugger connected, call duk_debugger_attach() and then execute requested file(s)/eval\n"); - fflush(stderr); - duk_debugger_attach(ctx, - duk_trans_socket_read_cb, - duk_trans_socket_write_cb, - duk_trans_socket_peek_cb, - duk_trans_socket_read_flush_cb, - duk_trans_socket_write_flush_cb, - debugger_detached, - (void *) 0xbeef1234); -#else - fprintf(stderr, "Warning: option --debugger ignored, no debugger support\n"); - fflush(stderr); -#endif - } - -#if 0 - /* Manual test for duk_debugger_cooperate() */ - { - for (i = 0; i < 60; i++) { - printf("cooperate: %d\n", i); - usleep(1000000); - duk_debugger_cooperate(ctx); - } - } -#endif - - return ctx; -} - -static void destroy_duktape_heap(duk_context *ctx, int alloc_provider) { - (void) alloc_provider; - -#ifdef DUK_CMDLINE_AJSHEAP - if (alloc_provider == ALLOC_AJSHEAP) { - fprintf(stdout, "Pool dump before duk_destroy_heap(), before forced gc\n"); - ajsheap_dump(); - - duk_gc(ctx, 0); - - fprintf(stdout, "Pool dump before duk_destroy_heap(), after forced gc\n"); - ajsheap_dump(); - } -#endif - - if (ctx) { - duk_destroy_heap(ctx); - } - -#ifdef DUK_CMDLINE_AJSHEAP - if (alloc_provider == ALLOC_AJSHEAP) { - fprintf(stdout, "Pool dump after duk_destroy_heap() (should have zero allocs)\n"); - ajsheap_dump(); - } -#endif -} - -int main(int argc, char *argv[]) { - duk_context *ctx = NULL; - int retval = 0; - int have_files = 0; - int have_eval = 0; - int interactive = 0; - int memlimit_high = 1; - int alloc_provider = ALLOC_DEFAULT; - int ajsheap_log = 0; - int debugger = 0; - int recreate_heap = 0; - int verbose = 0; - const char *compile_filename = NULL; - int i; - -#ifdef DUK_CMDLINE_AJSHEAP - alloc_provider = ALLOC_AJSHEAP; -#endif - (void) ajsheap_log; - - /* - * Signal handling setup - */ - -#ifndef NO_SIGNAL - set_sigint_handler(); - - /* This is useful at the global level; libraries should avoid SIGPIPE though */ - /*signal(SIGPIPE, SIG_IGN);*/ -#endif - - /* - * Parse options - */ - - for (i = 1; i < argc; i++) { - char *arg = argv[i]; - if (!arg) { - goto usage; - } - if (strcmp(arg, "--restrict-memory") == 0) { - memlimit_high = 0; - } else if (strcmp(arg, "-i") == 0) { - interactive = 1; - } else if (strcmp(arg, "-c") == 0) { - if (i == argc - 1) { - goto usage; - } - i++; - compile_filename = argv[i]; - } else if (strcmp(arg, "-e") == 0) { - have_eval = 1; - if (i == argc - 1) { - goto usage; - } - i++; /* skip code */ - } else if (strcmp(arg, "--alloc-default") == 0) { - alloc_provider = ALLOC_DEFAULT; - } else if (strcmp(arg, "--alloc-logging") == 0) { - alloc_provider = ALLOC_LOGGING; - } else if (strcmp(arg, "--alloc-torture") == 0) { - alloc_provider = ALLOC_TORTURE; - } else if (strcmp(arg, "--alloc-hybrid") == 0) { - alloc_provider = ALLOC_HYBRID; - } else if (strcmp(arg, "--alloc-ajsheap") == 0) { - alloc_provider = ALLOC_AJSHEAP; - } else if (strcmp(arg, "--ajsheap-log") == 0) { - ajsheap_log = 1; - } else if (strcmp(arg, "--debugger") == 0) { - debugger = 1; - } else if (strcmp(arg, "--recreate-heap") == 0) { - recreate_heap = 1; - } else if (strcmp(arg, "--verbose") == 0) { - verbose = 1; - } else if (strlen(arg) >= 1 && arg[0] == '-') { - goto usage; - } else { - have_files = 1; - } - } - if (!have_files && !have_eval) { - interactive = 1; - } - - /* - * Memory limit - */ - -#ifndef NO_RLIMIT - set_resource_limits(memlimit_high ? MEM_LIMIT_HIGH : MEM_LIMIT_NORMAL); -#else - if (memlimit_high == 0) { - fprintf(stderr, "Warning: option --restrict-memory ignored, no rlimit support\n"); - fflush(stderr); - } -#endif - - /* - * Create heap - */ - - ctx = create_duktape_heap(alloc_provider, debugger); - - /* - * Execute any argument file(s) - */ - - for (i = 1; i < argc; i++) { - char *arg = argv[i]; - if (!arg) { - continue; - } else if (strlen(arg) == 2 && strcmp(arg, "-e") == 0) { - /* Here we know the eval arg exists but check anyway */ - if (i == argc - 1) { - retval = 1; - goto cleanup; - } - if (handle_eval(ctx, argv[i + 1]) != 0) { - retval = 1; - goto cleanup; - } - i++; /* skip code */ - continue; - } else if (strlen(arg) == 2 && strcmp(arg, "-c") == 0) { - i++; /* skip filename */ - continue; - } else if (strlen(arg) >= 1 && arg[0] == '-') { - continue; - } - - if (verbose) { - fprintf(stderr, "*** Executing file: %s\n", arg); - fflush(stderr); - } - - if (handle_file(ctx, arg, compile_filename) != 0) { - retval = 1; - goto cleanup; - } - - if (recreate_heap) { - if (verbose) { - fprintf(stderr, "*** Recreating heap...\n"); - fflush(stderr); - } - - destroy_duktape_heap(ctx, alloc_provider); - ctx = create_duktape_heap(alloc_provider, debugger); - } - } - - /* - * Enter interactive mode if options indicate it - */ - - if (interactive) { - if (handle_interactive(ctx) != 0) { - retval = 1; - goto cleanup; - } - } - - /* - * Cleanup and exit - */ - - cleanup: - if (interactive) { - fprintf(stderr, "Cleaning up...\n"); - fflush(stderr); - } - - if (ctx) { - destroy_duktape_heap(ctx, alloc_provider); - } - ctx = NULL; - - return retval; - - /* - * Usage - */ - - usage: - fprintf(stderr, "Usage: duk [options] []\n" - "\n" - " -i enter interactive mode after executing argument file(s) / eval code\n" - " -e CODE evaluate code\n" - " -c FILE compile into bytecode (use with only one file argument)\n" - " --verbose verbose messages to stderr\n" - " --restrict-memory use lower memory limit (used by test runner)\n" - " --alloc-default use Duktape default allocator\n" -#ifdef DUK_CMDLINE_ALLOC_LOGGING - " --alloc-logging use logging allocator (writes to /tmp)\n" -#endif -#ifdef DUK_CMDLINE_ALLOC_TORTURE - " --alloc-torture use torture allocator\n" -#endif -#ifdef DUK_CMDLINE_ALLOC_HYBRID - " --alloc-hybrid use hybrid allocator\n" -#endif -#ifdef DUK_CMDLINE_AJSHEAP - " --alloc-ajsheap use ajsheap allocator (enabled by default with 'ajduk')\n" - " --ajsheap-log write alloc log to /tmp/ajduk-alloc-log.txt\n" -#endif -#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT - " --debugger start example debugger\n" -#endif - " --recreate-heap recreate heap after every file\n" - "\n" - "If is omitted, interactive mode is started automatically.\n"); - fflush(stderr); - exit(1); -} diff --git a/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline_ajduk.c b/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline_ajduk.c deleted file mode 100644 index c445fd44..00000000 --- a/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline_ajduk.c +++ /dev/null @@ -1,892 +0,0 @@ -/* - * 'ajduk' specific functionality, examples for low memory techniques - */ - -#ifdef DUK_CMDLINE_AJSHEAP - -#include -#include -#include -#include -#include "ajs.h" -#include "ajs_heap.h" - -extern uint8_t dbgHEAPDUMP; - -/* - * Helpers - */ - -static void safe_print_chars(const char *p, duk_size_t len, int until_nul) { - duk_size_t i; - - printf("\""); - for (i = 0; i < len; i++) { - unsigned char x = (unsigned char) p[i]; - if (until_nul && x == 0U) { - break; - } - if (x < 0x20 || x >= 0x7e || x == '"' || x == '\'' || x == '\\') { - printf("\\x%02x", (int) x); - } else { - printf("%c", (char) x); - } - } - printf("\""); -} - -/* - * Heap initialization when using AllJoyn.js pool allocator (without any - * other AllJoyn.js integration). This serves as an example of how to - * integrate Duktape with a pool allocator and is useful for low memory - * testing. - * - * The pool sizes are not optimized here. The sizes are chosen so that - * you can look at the high water mark (hwm) and use counts (use) and see - * how much allocations are needed for each pool size. To optimize pool - * sizes more accurately, you can use --alloc-logging and inspect the memory - * allocation log which provides exact byte counts etc. - * - * https://git.allseenalliance.org/cgit/core/alljoyn-js.git - * https://git.allseenalliance.org/cgit/core/alljoyn-js.git/tree/ajs.c - */ - -static const AJS_HeapConfig ajsheap_config[] = { - { 8, 10, AJS_POOL_BORROW, 0 }, - { 12, 10, AJS_POOL_BORROW, 0 }, - { 16, 200, AJS_POOL_BORROW, 0 }, - { 20, 400, AJS_POOL_BORROW, 0 }, - { 24, 400, AJS_POOL_BORROW, 0 }, - { 28, 200, AJS_POOL_BORROW, 0 }, - { 32, 200, AJS_POOL_BORROW, 0 }, - { 40, 200, AJS_POOL_BORROW, 0 }, - { 48, 50, AJS_POOL_BORROW, 0 }, - { 52, 50, AJS_POOL_BORROW, 0 }, - { 56, 50, AJS_POOL_BORROW, 0 }, - { 60, 50, AJS_POOL_BORROW, 0 }, - { 64, 50, AJS_POOL_BORROW, 0 }, - { 128, 80, AJS_POOL_BORROW, 0 }, - { 256, 16, AJS_POOL_BORROW, 0 }, - { 512, 16, AJS_POOL_BORROW, 0 }, - { 1024, 6, AJS_POOL_BORROW, 0 }, - { 1360, 1, AJS_POOL_BORROW, 0 }, /* duk_heap, with heap ptr compression */ - { 2048, 5, AJS_POOL_BORROW, 0 }, - { 4096, 3, 0, 0 }, - { 8192, 3, 0, 0 }, - { 16384, 1, 0, 0 }, - { 32768, 1, 0, 0 } -}; - -uint8_t *ajsheap_ram = NULL; - -void ajsheap_init(void) { - size_t heap_sz[1]; - uint8_t *heap_array[1]; - uint8_t num_pools, i; - AJ_Status ret; - - num_pools = (uint8_t) (sizeof(ajsheap_config) / sizeof(AJS_HeapConfig)); - heap_sz[0] = AJS_HeapRequired(ajsheap_config, /* heapConfig */ - num_pools, /* numPools */ - 0); /* heapNum */ - ajsheap_ram = (uint8_t *) malloc(heap_sz[0]); - if (ajsheap_ram == NULL) { - fprintf(stderr, "Failed to allocate AJS heap\n"); - fflush(stderr); - exit(1); - } - heap_array[0] = ajsheap_ram; - - fprintf(stderr, "Allocated AJS heap of %ld bytes, pools:", (long) heap_sz[0]); - for (i = 0; i < num_pools; i++) { - fprintf(stderr, " (sz:%ld,num:%ld,brw:%ld,idx:%ld)", - (long) ajsheap_config[i].size, (long) ajsheap_config[i].entries, - (long) ajsheap_config[i].borrow, (long) ajsheap_config[i].heapIndex); - } - fprintf(stderr, "\n"); - fflush(stderr); - - ret = AJS_HeapInit((void **) heap_array, /* heap */ - (size_t *) heap_sz, /* heapSz */ - ajsheap_config, /* heapConfig */ - num_pools, /* numPools */ - 1); /* numHeaps */ - fprintf(stderr, "AJS_HeapInit() -> %ld\n", (long) ret); - fflush(stderr); - - /* Enable heap dumps */ - dbgHEAPDUMP = 1; -} - -/* AjsHeap.dump(), allows Ecmascript code to dump heap status at suitable - * points. - */ -duk_ret_t ajsheap_dump_binding(duk_context *ctx) { - AJS_HeapDump(); - fflush(stdout); - return 0; -} - -void ajsheap_dump(void) { - AJS_HeapDump(); - fflush(stdout); -} - -void ajsheap_register(duk_context *ctx) { - duk_push_object(ctx); - duk_push_c_function(ctx, ajsheap_dump_binding, 0); - duk_put_prop_string(ctx, -2, "dump"); - duk_put_global_string(ctx, "AjsHeap"); -} - -/* - * Wrapped ajs_heap.c alloc functions - * - * Used to write an alloc log. - */ - -static FILE *ajsheap_alloc_log = NULL; - -static void ajsheap_write_alloc_log(const char *fmt, ...) { - va_list ap; - char buf[256]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - buf[sizeof(buf) - 1] = (char) 0; - va_end(ap); - - if (ajsheap_alloc_log == NULL) { - ajsheap_alloc_log = fopen("/tmp/ajduk-alloc-log.txt", "wb"); - if (ajsheap_alloc_log == NULL) { - fprintf(stderr, "WARNING: failed to write alloc log, ignoring\n"); - fflush(stderr); - return; - } - } - - (void) fwrite((const void *) buf, 1, strlen(buf), ajsheap_alloc_log); - (void) fflush(ajsheap_alloc_log); -} - -void *ajsheap_alloc_wrapped(void *udata, duk_size_t size) { - void *ret = AJS_Alloc(udata, size); - if (size > 0 && ret == NULL) { - ajsheap_write_alloc_log("A FAIL %ld\n", (long) size); - } else if (ret == NULL) { - ajsheap_write_alloc_log("A NULL %ld\n", (long) size); - } else { - ajsheap_write_alloc_log("A %p %ld\n", ret, (long) size); - } - return ret; -} - -void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size) { - void *ret = AJS_Realloc(udata, ptr, size); - if (size > 0 && ret == NULL) { - if (ptr == NULL) { - ajsheap_write_alloc_log("R NULL -1 FAIL %ld\n", (long) size); - } else { - ajsheap_write_alloc_log("R %p -1 FAIL %ld\n", ptr, (long) size); - } - } else if (ret == NULL) { - if (ptr == NULL) { - ajsheap_write_alloc_log("R NULL -1 NULL %ld\n", (long) size); - } else { - ajsheap_write_alloc_log("R %p -1 NULL %ld\n", ptr, (long) size); - } - } else { - if (ptr == NULL) { - ajsheap_write_alloc_log("R NULL -1 %p %ld\n", ret, (long) size); - } else { - ajsheap_write_alloc_log("R %p -1 %p %ld\n", ptr, ret, (long) size); - } - } - return ret; -} - -void ajsheap_free_wrapped(void *udata, void *ptr) { - AJS_Free(udata, ptr); - if (ptr == NULL) { - } else { - ajsheap_write_alloc_log("F %p -1\n", ptr); - } -} - -/* - * Example pointer compression functions. - * - * 'base' is chosen so that no non-NULL pointer results in a zero result - * which is reserved for NULL pointers. - */ - -duk_uint16_t ajsheap_enc16(void *ud, void *p) { - duk_uint32_t ret; - char *base = (char *) ajsheap_ram - 4; - - /* Userdata is not needed in this case but would be useful if heap - * pointer compression were used for multiple heaps. The userdata - * allows the callback to distinguish between heaps and their base - * pointers. - * - * If not needed, the userdata can be left out during compilation - * by simply ignoring the userdata argument of the pointer encode - * and decode macros. It is kept here so that any bugs in actually - * providing the value inside Duktape are revealed during compilation. - */ - (void) ud; -#if 1 - /* Ensure that we always get the heap_udata given in heap creation. - * (Useful for Duktape development, not needed for user programs.) - */ - if (ud != (void *) 0xdeadbeef) { - fprintf(stderr, "invalid udata for ajsheap_enc16: %p\n", ud); - fflush(stderr); - } -#endif - - if (p == NULL) { - ret = 0; - } else { - ret = (duk_uint32_t) (((char *) p - base) >> 2); - } -#if 0 - printf("ajsheap_enc16: %p -> %u\n", p, (unsigned int) ret); -#endif - if (ret > 0xffffUL) { - fprintf(stderr, "Failed to compress pointer\n"); - fflush(stderr); - abort(); - } - return (duk_uint16_t) ret; -} -void *ajsheap_dec16(void *ud, duk_uint16_t x) { - void *ret; - char *base = (char *) ajsheap_ram - 4; - - /* See userdata discussion in ajsheap_enc16(). */ - (void) ud; -#if 1 - /* Ensure that we always get the heap_udata given in heap creation. */ - if (ud != (void *) 0xdeadbeef) { - fprintf(stderr, "invalid udata for ajsheap_dec16: %p\n", ud); - fflush(stderr); - } -#endif - - if (x == 0) { - ret = NULL; - } else { - ret = (void *) (base + (((duk_uint32_t) x) << 2)); - } -#if 0 - printf("ajsheap_dec16: %u -> %p\n", (unsigned int) x, ret); -#endif - return ret; -} - -/* - * Simplified example of an external strings strategy where incoming strings - * are written sequentially into a fixed, memory mapped flash area. - * - * The example first scans if the string is already in the flash (which may - * happen if the same string is interned multiple times), then adds it to - * flash if there is space. - * - * This example is too slow to be used in a real world application: there - * should be e.g. a hash table to quickly check for strings that are already - * present in the string data (similarly to how string interning works in - * Duktape itself). - */ - -static uint8_t ajsheap_strdata[65536]; -static size_t ajsheap_strdata_used = 0; - -const void *ajsheap_extstr_check_1(const void *ptr, duk_size_t len) { - uint8_t *p, *p_end; - uint8_t initial; - uint8_t *ret; - size_t left; - - (void) safe_print_chars; /* potentially unused */ - - if (len <= 3) { - /* It's not worth it to make very small strings external, as - * they would take the same space anyway. Also avoids zero - * length degenerate case. - */ - return NULL; - } - - /* - * Check if we already have the string. Be careful to compare for - * NUL terminator too, it is NOT present in 'ptr'. This algorithm - * is too simplistic and way too slow for actual use. - */ - - initial = ((const uint8_t *) ptr)[0]; - for (p = ajsheap_strdata, p_end = p + ajsheap_strdata_used; p != p_end; p++) { - if (*p != initial) { - continue; - } - left = (size_t) (p_end - p); - if (left >= len + 1 && - memcmp(p, ptr, len) == 0 && - p[len] == 0) { - ret = p; -#if 0 - printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", - (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> existing %p (used=%ld)\n", - (void *) ret, (long) ajsheap_strdata_used); -#endif - return ret; - } - } - - /* - * Not present yet, check if we have space. Again, be careful to - * ensure there is space for a NUL following the input data. - */ - - if (ajsheap_strdata_used + len + 1 > sizeof(ajsheap_strdata)) { -#if 0 - printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> no space (used=%ld)\n", (long) ajsheap_strdata_used); -#endif - return NULL; - } - - /* - * There is space, add the string to our collection, being careful - * to append the NUL. - */ - - ret = ajsheap_strdata + ajsheap_strdata_used; - memcpy(ret, ptr, len); - ret[len] = (uint8_t) 0; - ajsheap_strdata_used += len + 1; - -#if 0 - printf("ajsheap_extstr_check_1: ptr=%p, len=%ld -> ", (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> %p (used=%ld)\n", (void *) ret, (long) ajsheap_strdata_used); -#endif - return (const void *) ret; -} - -void ajsheap_extstr_free_1(const void *ptr) { - (void) ptr; -#if 0 - printf("ajsheap_extstr_free_1: freeing extstr %p -> ", ptr); - safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/); - printf("\n"); -#endif -} - -/* - * Simplified example of an external strings strategy where a set of strings - * is gathered during application compile time and baked into the application - * binary. - * - * Duktape built-in strings are available from duk_build_meta.json, see - * util/duk_meta_to_strarray.py. There may also be a lot of application - * specific strings, e.g. those used by application specific APIs. These - * must be gathered through some other means, see e.g. util/scan_strings.py. - */ - -static const char *strdata_duk_builtin_strings[] = { - /* - * These strings are from util/duk_meta_to_strarray.py - */ - - "Logger", - "Thread", - "Pointer", - "Buffer", - "DecEnv", - "ObjEnv", - "", - "global", - "Arguments", - "JSON", - "Math", - "Error", - "RegExp", - "Date", - "Number", - "Boolean", - "String", - "Array", - "Function", - "Object", - "Null", - "Undefined", - "{_func:true}", - "{\x22" "_func\x22" ":true}", - "{\x22" "_ninf\x22" ":true}", - "{\x22" "_inf\x22" ":true}", - "{\x22" "_nan\x22" ":true}", - "{\x22" "_undef\x22" ":true}", - "toLogString", - "clog", - "l", - "n", - "fatal", - "error", - "warn", - "debug", - "trace", - "raw", - "fmt", - "current", - "resume", - "compact", - "jc", - "jx", - "base64", - "hex", - "dec", - "enc", - "fin", - "gc", - "act", - "info", - "version", - "env", - "modLoaded", - "modSearch", - "errThrow", - "errCreate", - "compile", - "\xff" "Regbase", - "\xff" "Thread", - "\xff" "Handler", - "\xff" "Finalizer", - "\xff" "Callee", - "\xff" "Map", - "\xff" "Args", - "\xff" "This", - "\xff" "Pc2line", - "\xff" "Source", - "\xff" "Varenv", - "\xff" "Lexenv", - "\xff" "Varmap", - "\xff" "Formals", - "\xff" "Bytecode", - "\xff" "Next", - "\xff" "Target", - "\xff" "Value", - "pointer", - "buffer", - "\xff" "Tracedata", - "lineNumber", - "fileName", - "pc", - "stack", - "ThrowTypeError", - "Duktape", - "id", - "require", - "__proto__", - "setPrototypeOf", - "ownKeys", - "enumerate", - "deleteProperty", - "has", - "Proxy", - "callee", - "Invalid Date", - "[...]", - "\x0a" "\x09", - " ", - ",", - "-0", - "+0", - "0", - "-Infinity", - "+Infinity", - "Infinity", - "object", - "string", - "number", - "boolean", - "undefined", - "stringify", - "tan", - "sqrt", - "sin", - "round", - "random", - "pow", - "min", - "max", - "log", - "floor", - "exp", - "cos", - "ceil", - "atan2", - "atan", - "asin", - "acos", - "abs", - "SQRT2", - "SQRT1_2", - "PI", - "LOG10E", - "LOG2E", - "LN2", - "LN10", - "E", - "message", - "name", - "input", - "index", - "(?:)", - "lastIndex", - "multiline", - "ignoreCase", - "source", - "test", - "exec", - "toGMTString", - "setYear", - "getYear", - "toJSON", - "toISOString", - "toUTCString", - "setUTCFullYear", - "setFullYear", - "setUTCMonth", - "setMonth", - "setUTCDate", - "setDate", - "setUTCHours", - "setHours", - "setUTCMinutes", - "setMinutes", - "setUTCSeconds", - "setSeconds", - "setUTCMilliseconds", - "setMilliseconds", - "setTime", - "getTimezoneOffset", - "getUTCMilliseconds", - "getMilliseconds", - "getUTCSeconds", - "getSeconds", - "getUTCMinutes", - "getMinutes", - "getUTCHours", - "getHours", - "getUTCDay", - "getDay", - "getUTCDate", - "getDate", - "getUTCMonth", - "getMonth", - "getUTCFullYear", - "getFullYear", - "getTime", - "toLocaleTimeString", - "toLocaleDateString", - "toTimeString", - "toDateString", - "now", - "UTC", - "parse", - "toPrecision", - "toExponential", - "toFixed", - "POSITIVE_INFINITY", - "NEGATIVE_INFINITY", - "NaN", - "MIN_VALUE", - "MAX_VALUE", - "substr", - "trim", - "toLocaleUpperCase", - "toUpperCase", - "toLocaleLowerCase", - "toLowerCase", - "substring", - "split", - "search", - "replace", - "match", - "localeCompare", - "charCodeAt", - "charAt", - "fromCharCode", - "reduceRight", - "reduce", - "filter", - "map", - "forEach", - "some", - "every", - "lastIndexOf", - "indexOf", - "unshift", - "splice", - "sort", - "slice", - "shift", - "reverse", - "push", - "pop", - "join", - "concat", - "isArray", - "arguments", - "caller", - "bind", - "call", - "apply", - "propertyIsEnumerable", - "isPrototypeOf", - "hasOwnProperty", - "valueOf", - "toLocaleString", - "toString", - "constructor", - "set", - "get", - "enumerable", - "configurable", - "writable", - "value", - "keys", - "isExtensible", - "isFrozen", - "isSealed", - "preventExtensions", - "freeze", - "seal", - "defineProperties", - "defineProperty", - "create", - "getOwnPropertyNames", - "getOwnPropertyDescriptor", - "getPrototypeOf", - "prototype", - "length", - "alert", - "print", - "unescape", - "escape", - "encodeURIComponent", - "encodeURI", - "decodeURIComponent", - "decodeURI", - "isFinite", - "isNaN", - "parseFloat", - "parseInt", - "eval", - "URIError", - "TypeError", - "SyntaxError", - "ReferenceError", - "RangeError", - "EvalError", - "break", - "case", - "catch", - "continue", - "debugger", - "default", - "delete", - "do", - "else", - "finally", - "for", - "function", - "if", - "in", - "instanceof", - "new", - "return", - "switch", - "this", - "throw", - "try", - "typeof", - "var", - "void", - "while", - "with", - "class", - "const", - "enum", - "export", - "extends", - "import", - "super", - "null", - "true", - "false", - "implements", - "interface", - "let", - "package", - "private", - "protected", - "public", - "static", - "yield", - - /* - * These strings are manually added, and would be gathered in some - * application specific manner. - */ - - "foo", - "bar", - "quux", - "enableFrob", - "disableFrob" - /* ... */ -}; - -const void *ajsheap_extstr_check_2(const void *ptr, duk_size_t len) { - int i, n; - - (void) safe_print_chars; /* potentially unused */ - - /* Linear scan. An actual implementation would need some acceleration - * structure, e.g. select a sublist based on first character. - * - * NOTE: input string (behind 'ptr' with 'len' bytes) DOES NOT have a - * trailing NUL character. Any strings returned from this function - * MUST have a trailing NUL character. - */ - - n = (int) (sizeof(strdata_duk_builtin_strings) / sizeof(const char *)); - for (i = 0; i < n; i++) { - const char *str; - - str = strdata_duk_builtin_strings[i]; - if (strlen(str) == len && memcmp(ptr, (const void *) str, len) == 0) { -#if 0 - printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ", - (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> constant string index %ld\n", (long) i); -#endif - return (void *) strdata_duk_builtin_strings[i]; - } - } - -#if 0 - printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ", - (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> not found\n"); -#endif - return NULL; -} - -void ajsheap_extstr_free_2(const void *ptr) { - (void) ptr; -#if 0 - printf("ajsheap_extstr_free_2: freeing extstr %p -> ", ptr); - safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/); - printf("\n"); -#endif -} - -/* - * External strings strategy intended for valgrind testing: external strings - * are allocated using malloc()/free() so that valgrind can be used to ensure - * that strings are e.g. freed exactly once. - */ - -const void *ajsheap_extstr_check_3(const void *ptr, duk_size_t len) { - duk_uint8_t *ret; - - (void) safe_print_chars; /* potentially unused */ - - ret = malloc((size_t) len + 1); - if (ret == NULL) { -#if 0 - printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ", - (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> malloc failed, return NULL\n"); -#endif - return (const void *) NULL; - } - - if (len > 0) { - memcpy((void *) ret, ptr, (size_t) len); - } - ret[len] = (duk_uint8_t) 0; - -#if 0 - printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ", - (void *) ptr, (long) len); - safe_print_chars((const char *) ptr, len, 0 /*until_nul*/); - printf(" -> %p\n", (void *) ret); -#endif - return (const void *) ret; -} - -void ajsheap_extstr_free_3(const void *ptr) { - (void) ptr; -#if 0 - printf("ajsheap_extstr_free_3: freeing extstr %p -> ", ptr); - safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/); - printf("\n"); -#endif - free((void *) ptr); -} - -/* - * Execution timeout example - */ - -#define AJSHEAP_EXEC_TIMEOUT 5 /* seconds */ - -static time_t curr_pcall_start = 0; -static long exec_timeout_check_counter = 0; - -void ajsheap_start_exec_timeout(void) { - curr_pcall_start = time(NULL); -} - -void ajsheap_clear_exec_timeout(void) { - curr_pcall_start = 0; -} - -duk_bool_t ajsheap_exec_timeout_check(void *udata) { - time_t now = time(NULL); - time_t diff = now - curr_pcall_start; - - (void) udata; /* not needed */ - - exec_timeout_check_counter++; -#if 0 - printf("exec timeout check %ld: now=%ld, start=%ld, diff=%ld\n", - (long) exec_timeout_check_counter, (long) now, (long) curr_pcall_start, (long) diff); - fflush(stdout); -#endif - - if (curr_pcall_start == 0) { - /* protected call not yet running */ - return 0; - } - if (diff > AJSHEAP_EXEC_TIMEOUT) { - return 1; - } - return 0; -} - -#else /* DUK_CMDLINE_AJSHEAP */ - -int ajs_dummy = 0; /* to avoid empty source file */ - -#endif /* DUK_CMDLINE_AJSHEAP */ diff --git a/src/third_party/duktape-1.3.0/examples/codepage-conv/README.rst b/src/third_party/duktape-1.3.0/examples/codepage-conv/README.rst deleted file mode 100644 index 98b53d26..00000000 --- a/src/third_party/duktape-1.3.0/examples/codepage-conv/README.rst +++ /dev/null @@ -1,8 +0,0 @@ -Codepage conversion example -=========================== - -Example of how to convert an 8-bit input string (e.g. ISO-8859-1 or Windows -codepage 1252) into CESU-8 without using an external library like iconv. - -This is useful e.g. when compiling non-UTF-8 source code which cannot be -converted to UTF-8 (CESU-8) at build time. diff --git a/src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.c b/src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.c deleted file mode 100644 index 932e9a60..00000000 --- a/src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Convert an 8-bit input string (e.g. ISO-8859-1) into CESU-8. - * Calling code supplies the "code page" as a 256-entry array of - * codepoints for the conversion. - * - * This is useful when input data is in non-UTF-8 format and must - * be converted at runtime, e.g. when compiling non-UTF-8 source - * code. Another alternative is to use e.g. iconv. - */ - -#include "duktape.h" - -/* Decode an 8-bit string using 'codepage' into Unicode codepoints and - * re-encode into CESU-8. Codepage argument must point to a 256-entry - * table. Only supports BMP (codepoints U+0000 to U+FFFF). - */ -void duk_decode_string_codepage(duk_context *ctx, const char *str, size_t len, unsigned int *codepage) { - unsigned char *tmp; - size_t tmplen, i; - unsigned char *p; - unsigned int cp; - - tmplen = 3 * len; /* max expansion is 1 input byte -> 3 output bytes */ - if (tmplen / 3 != len) { - /* Temporary buffer length wraps. */ - duk_error(ctx, DUK_ERR_RANGE_ERROR, "input string too long"); - return; - } - - tmp = (unsigned char *) duk_push_fixed_buffer(ctx, tmplen); - - for (i = 0, p = tmp; i < len; i++) { - cp = codepage[((unsigned char *) str)[i]] & 0xffffUL; - if (cp < 0x80UL) { - *p++ = (unsigned char) cp; - } else if (cp < 0x800UL) { - *p++ = (unsigned char) (0xc0 + ((cp >> 6) & 0x1f)); - *p++ = (unsigned char) (0x80 + (cp & 0x3f)); - } else { - /* In CESU-8 all codepoints in [0x0000,0xFFFF] are - * allowed, including surrogates. - */ - *p++ = (unsigned char) (0xe0 + ((cp >> 12) & 0x0f)); - *p++ = (unsigned char) (0x80 + ((cp >> 6) & 0x3f)); - *p++ = (unsigned char) (0x80 + (cp & 0x3f)); - } - } - - duk_push_lstring(ctx, (const char *) tmp, (duk_size_t) (p - tmp)); - - /* [ ... tmp res ] */ - - duk_remove(ctx, -2); -} diff --git a/src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.h b/src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.h deleted file mode 100644 index d2705a0d..00000000 --- a/src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DUK_CODEPAGE_CONV_H_INCLUDED -#define DUK_CODEPAGE_CONV_H_INCLUDED - -#include "duktape.h" - -void duk_decode_string_codepage(duk_context *ctx, const char *str, size_t len, unsigned int *codepage); - -#endif /* DUK_CODEPAGE_CONV_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/examples/codepage-conv/test.c b/src/third_party/duktape-1.3.0/examples/codepage-conv/test.c deleted file mode 100644 index c34299a8..00000000 --- a/src/third_party/duktape-1.3.0/examples/codepage-conv/test.c +++ /dev/null @@ -1,286 +0,0 @@ -#include "duktape.h" -#include "duk_codepage_conv.h" - -/* http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT */ -unsigned int cp1252[256] = { - (unsigned int) 0x0000, - (unsigned int) 0x0001, - (unsigned int) 0x0002, - (unsigned int) 0x0003, - (unsigned int) 0x0004, - (unsigned int) 0x0005, - (unsigned int) 0x0006, - (unsigned int) 0x0007, - (unsigned int) 0x0008, - (unsigned int) 0x0009, - (unsigned int) 0x000A, - (unsigned int) 0x000B, - (unsigned int) 0x000C, - (unsigned int) 0x000D, - (unsigned int) 0x000E, - (unsigned int) 0x000F, - (unsigned int) 0x0010, - (unsigned int) 0x0011, - (unsigned int) 0x0012, - (unsigned int) 0x0013, - (unsigned int) 0x0014, - (unsigned int) 0x0015, - (unsigned int) 0x0016, - (unsigned int) 0x0017, - (unsigned int) 0x0018, - (unsigned int) 0x0019, - (unsigned int) 0x001A, - (unsigned int) 0x001B, - (unsigned int) 0x001C, - (unsigned int) 0x001D, - (unsigned int) 0x001E, - (unsigned int) 0x001F, - (unsigned int) 0x0020, - (unsigned int) 0x0021, - (unsigned int) 0x0022, - (unsigned int) 0x0023, - (unsigned int) 0x0024, - (unsigned int) 0x0025, - (unsigned int) 0x0026, - (unsigned int) 0x0027, - (unsigned int) 0x0028, - (unsigned int) 0x0029, - (unsigned int) 0x002A, - (unsigned int) 0x002B, - (unsigned int) 0x002C, - (unsigned int) 0x002D, - (unsigned int) 0x002E, - (unsigned int) 0x002F, - (unsigned int) 0x0030, - (unsigned int) 0x0031, - (unsigned int) 0x0032, - (unsigned int) 0x0033, - (unsigned int) 0x0034, - (unsigned int) 0x0035, - (unsigned int) 0x0036, - (unsigned int) 0x0037, - (unsigned int) 0x0038, - (unsigned int) 0x0039, - (unsigned int) 0x003A, - (unsigned int) 0x003B, - (unsigned int) 0x003C, - (unsigned int) 0x003D, - (unsigned int) 0x003E, - (unsigned int) 0x003F, - (unsigned int) 0x0040, - (unsigned int) 0x0041, - (unsigned int) 0x0042, - (unsigned int) 0x0043, - (unsigned int) 0x0044, - (unsigned int) 0x0045, - (unsigned int) 0x0046, - (unsigned int) 0x0047, - (unsigned int) 0x0048, - (unsigned int) 0x0049, - (unsigned int) 0x004A, - (unsigned int) 0x004B, - (unsigned int) 0x004C, - (unsigned int) 0x004D, - (unsigned int) 0x004E, - (unsigned int) 0x004F, - (unsigned int) 0x0050, - (unsigned int) 0x0051, - (unsigned int) 0x0052, - (unsigned int) 0x0053, - (unsigned int) 0x0054, - (unsigned int) 0x0055, - (unsigned int) 0x0056, - (unsigned int) 0x0057, - (unsigned int) 0x0058, - (unsigned int) 0x0059, - (unsigned int) 0x005A, - (unsigned int) 0x005B, - (unsigned int) 0x005C, - (unsigned int) 0x005D, - (unsigned int) 0x005E, - (unsigned int) 0x005F, - (unsigned int) 0x0060, - (unsigned int) 0x0061, - (unsigned int) 0x0062, - (unsigned int) 0x0063, - (unsigned int) 0x0064, - (unsigned int) 0x0065, - (unsigned int) 0x0066, - (unsigned int) 0x0067, - (unsigned int) 0x0068, - (unsigned int) 0x0069, - (unsigned int) 0x006A, - (unsigned int) 0x006B, - (unsigned int) 0x006C, - (unsigned int) 0x006D, - (unsigned int) 0x006E, - (unsigned int) 0x006F, - (unsigned int) 0x0070, - (unsigned int) 0x0071, - (unsigned int) 0x0072, - (unsigned int) 0x0073, - (unsigned int) 0x0074, - (unsigned int) 0x0075, - (unsigned int) 0x0076, - (unsigned int) 0x0077, - (unsigned int) 0x0078, - (unsigned int) 0x0079, - (unsigned int) 0x007A, - (unsigned int) 0x007B, - (unsigned int) 0x007C, - (unsigned int) 0x007D, - (unsigned int) 0x007E, - (unsigned int) 0x007F, - (unsigned int) 0x20AC, - (unsigned int) 0xFFFD, /* undefined */ - (unsigned int) 0x201A, - (unsigned int) 0x0192, - (unsigned int) 0x201E, - (unsigned int) 0x2026, - (unsigned int) 0x2020, - (unsigned int) 0x2021, - (unsigned int) 0x02C6, - (unsigned int) 0x2030, - (unsigned int) 0x0160, - (unsigned int) 0x2039, - (unsigned int) 0x0152, - (unsigned int) 0xFFFD, /* undefined */ - (unsigned int) 0x017D, - (unsigned int) 0xFFFD, /* undefined */ - (unsigned int) 0xFFFD, /* undefined */ - (unsigned int) 0x2018, - (unsigned int) 0x2019, - (unsigned int) 0x201C, - (unsigned int) 0x201D, - (unsigned int) 0x2022, - (unsigned int) 0x2013, - (unsigned int) 0x2014, - (unsigned int) 0x02DC, - (unsigned int) 0x2122, - (unsigned int) 0x0161, - (unsigned int) 0x203A, - (unsigned int) 0x0153, - (unsigned int) 0xFFFD, /* undefined */ - (unsigned int) 0x017E, - (unsigned int) 0x0178, - (unsigned int) 0x00A0, - (unsigned int) 0x00A1, - (unsigned int) 0x00A2, - (unsigned int) 0x00A3, - (unsigned int) 0x00A4, - (unsigned int) 0x00A5, - (unsigned int) 0x00A6, - (unsigned int) 0x00A7, - (unsigned int) 0x00A8, - (unsigned int) 0x00A9, - (unsigned int) 0x00AA, - (unsigned int) 0x00AB, - (unsigned int) 0x00AC, - (unsigned int) 0x00AD, - (unsigned int) 0x00AE, - (unsigned int) 0x00AF, - (unsigned int) 0x00B0, - (unsigned int) 0x00B1, - (unsigned int) 0x00B2, - (unsigned int) 0x00B3, - (unsigned int) 0x00B4, - (unsigned int) 0x00B5, - (unsigned int) 0x00B6, - (unsigned int) 0x00B7, - (unsigned int) 0x00B8, - (unsigned int) 0x00B9, - (unsigned int) 0x00BA, - (unsigned int) 0x00BB, - (unsigned int) 0x00BC, - (unsigned int) 0x00BD, - (unsigned int) 0x00BE, - (unsigned int) 0x00BF, - (unsigned int) 0x00C0, - (unsigned int) 0x00C1, - (unsigned int) 0x00C2, - (unsigned int) 0x00C3, - (unsigned int) 0x00C4, - (unsigned int) 0x00C5, - (unsigned int) 0x00C6, - (unsigned int) 0x00C7, - (unsigned int) 0x00C8, - (unsigned int) 0x00C9, - (unsigned int) 0x00CA, - (unsigned int) 0x00CB, - (unsigned int) 0x00CC, - (unsigned int) 0x00CD, - (unsigned int) 0x00CE, - (unsigned int) 0x00CF, - (unsigned int) 0x00D0, - (unsigned int) 0x00D1, - (unsigned int) 0x00D2, - (unsigned int) 0x00D3, - (unsigned int) 0x00D4, - (unsigned int) 0x00D5, - (unsigned int) 0x00D6, - (unsigned int) 0x00D7, - (unsigned int) 0x00D8, - (unsigned int) 0x00D9, - (unsigned int) 0x00DA, - (unsigned int) 0x00DB, - (unsigned int) 0x00DC, - (unsigned int) 0x00DD, - (unsigned int) 0x00DE, - (unsigned int) 0x00DF, - (unsigned int) 0x00E0, - (unsigned int) 0x00E1, - (unsigned int) 0x00E2, - (unsigned int) 0x00E3, - (unsigned int) 0x00E4, - (unsigned int) 0x00E5, - (unsigned int) 0x00E6, - (unsigned int) 0x00E7, - (unsigned int) 0x00E8, - (unsigned int) 0x00E9, - (unsigned int) 0x00EA, - (unsigned int) 0x00EB, - (unsigned int) 0x00EC, - (unsigned int) 0x00ED, - (unsigned int) 0x00EE, - (unsigned int) 0x00EF, - (unsigned int) 0x00F0, - (unsigned int) 0x00F1, - (unsigned int) 0x00F2, - (unsigned int) 0x00F3, - (unsigned int) 0x00F4, - (unsigned int) 0x00F5, - (unsigned int) 0x00F6, - (unsigned int) 0x00F7, - (unsigned int) 0x00F8, - (unsigned int) 0x00F9, - (unsigned int) 0x00FA, - (unsigned int) 0x00FB, - (unsigned int) 0x00FC, - (unsigned int) 0x00FD, - (unsigned int) 0x00FE, - (unsigned int) 0x00FF -}; - -/* Exercise all 3 byte lengths: any ASCII character is 1 byte, 0xFC maps to - * U+00FC which is 2 bytes, and 0x80 maps to U+20AC which is 3 bytes. - */ -static const char *example_source = "print('Hello w\xfcrld - \x80');"; - -/* Example: compile and run test source encoded in Windows codepage 1252. */ -int main(int argc, char *argv[]) { - duk_context *ctx; - - (void) argc; (void) argv; - - ctx = duk_create_heap_default(); - if (!ctx) { - printf("Failed to create Duktape heap.\n"); - return 1; - } - - duk_decode_string_codepage(ctx, example_source, strlen(example_source), cp1252); - duk_eval_noresult(ctx); - - duk_destroy_heap(ctx); - return 0; -} diff --git a/src/third_party/duktape-1.3.0/examples/coffee/README.rst b/src/third_party/duktape-1.3.0/examples/coffee/README.rst deleted file mode 100644 index f1475226..00000000 --- a/src/third_party/duktape-1.3.0/examples/coffee/README.rst +++ /dev/null @@ -1,10 +0,0 @@ -===================== -Coffeescript examples -===================== - -A few tests to see how CoffeeScript works with Duktape. Just convert the -Coffeescript files to Javascript with the ``Makefile.coffee`` in the -distributable, or manually:: - - $ coffee -c hello.coffee - $ cat hello.js diff --git a/src/third_party/duktape-1.3.0/examples/coffee/globals.coffee b/src/third_party/duktape-1.3.0/examples/coffee/globals.coffee deleted file mode 100644 index 25773cd8..00000000 --- a/src/third_party/duktape-1.3.0/examples/coffee/globals.coffee +++ /dev/null @@ -1,7 +0,0 @@ - -print '*** All globals' -print(name) for name in Object.getOwnPropertyNames(this) - -print '*** Globals with a short name (<= 8 chars)' -print(name) for name in Object.getOwnPropertyNames(this) when name.length <= 8 - diff --git a/src/third_party/duktape-1.3.0/examples/coffee/hello.coffee b/src/third_party/duktape-1.3.0/examples/coffee/hello.coffee deleted file mode 100644 index 088ed8d7..00000000 --- a/src/third_party/duktape-1.3.0/examples/coffee/hello.coffee +++ /dev/null @@ -1,2 +0,0 @@ -print 'Hello world!' -print 'version: ' + Duktape.version diff --git a/src/third_party/duktape-1.3.0/examples/coffee/mandel.coffee b/src/third_party/duktape-1.3.0/examples/coffee/mandel.coffee deleted file mode 100644 index 8e3e170f..00000000 --- a/src/third_party/duktape-1.3.0/examples/coffee/mandel.coffee +++ /dev/null @@ -1,28 +0,0 @@ -mandel = (x0, y0, x1, y1, w, h, maxiter) -> - [dx, dy] = [(x1 - x0) / w, (y1 - y0) / h] - res = [] - - y = y0 - for yc in [0..h-1] - x = x0 - for xc in [0..w-1] - [xx, yy] = [x, y] - c = '*' - for i in [0..maxiter-1] - # (xx+i*yy)^2 + (x+i*y) = xx^2 + i*2*xx*yy - yy^2 + x + i*y - # = (xx^2 - yy^2 + x) + i*(2*xx*yy + y) - [xx2, yy2] = [xx*xx, yy*yy] - if xx2 + yy2 >= 4.0 - c = '.' - break - [xx, yy] = [xx2 - yy2 + x, 2*xx*yy + y] - res.push(c) - x += dx - res.push('\n') - y += dy - - print(res.join('')) - return - -mandel(-2, 2, 2, -2, 200, 100, 1000) - diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/Makefile b/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/Makefile deleted file mode 100644 index 9d9d0b58..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Set DUKTAPE_SRC to 'src' dir of Duktape distributable. -# The default is for the dist environment. -DUKTAPE_SRC=../../src -DUKTAPE_OPTS= -DUKTAPE_OPTS+=-DDUK_OPT_ASSERTIONS -DUKTAPE_OPTS+=-DDUK_OPT_DEBUGGER_SUPPORT -DDUK_OPT_INTERRUPT_COUNTER -DUKTAPE_OPTS+=-DDUK_OPT_DEBUGGER_FWD_PRINTALERT -DUKTAPE_OPTS+=-DDUK_OPT_DEBUGGER_DUMPHEAP -#DUKTAPE_OPTS+=-DDUK_OPT_DEBUGGER_TRANSPORT_TORTURE -TRANS_OPTS= -#TRANS_OPTS+=-DDEBUG_PRINTS - -test: test.c duk_trans_dvalue.c duk_trans_dvalue.h - echo $(DUKTAPE_SRC) - gcc -O0 -g -ggdb -Wall -Wextra -std=c99 -o test -I$(DUKTAPE_SRC) -I. \ - $(DUKTAPE_OPTS) $(TRANS_OPTS) \ - $(DUKTAPE_SRC)/duktape.c duk_trans_dvalue.c test.c -lm diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/README.rst b/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/README.rst deleted file mode 100644 index 86b2bb59..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/README.rst +++ /dev/null @@ -1,8 +0,0 @@ -=========================================================== -Debug transport with local debug protocol encoding/decoding -=========================================================== - -This example implements a debug transport which decodes/encodes the Duktape -debug protocol locally into a more easy to use C interface, which is useful -for debug clients implemented locally on the target. The example also -demonstrates how to trial parse dvalues in C. diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.c b/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.c deleted file mode 100644 index 8470a5f4..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Example debug transport with a local debug message encoder/decoder. - * - * Provides a "received dvalue" callback for a fully parsed dvalue (user - * code frees dvalue) and a "cooperate" callback for e.g. UI integration. - * There are a few other callbacks. See test.c for usage examples. - * - * This transport implementation is not multithreaded which means that: - * - * - Callbacks to "received dvalue" callback come from the Duktape thread, - * either during normal execution or from duk_debugger_cooperate(). - * - * - Calls into duk_trans_dvalue_send() must be made from the callbacks - * provided (e.g. "received dvalue" or "cooperate") which use the active - * Duktape thread. - * - * - The only exception to this is when Duktape is idle: you can then call - * duk_trans_dvalue_send() from any thread (only one thread at a time). - * When you next call into Duktape or call duk_debugger_cooperate(), the - * queued data will be read and processed by Duktape. - * - * There are functions for creating and freeing values; internally they use - * malloc() and free() for memory management. Duktape heap alloc functions - * are not used to minimize disturbances to the Duktape heap under debugging. - * - * Doesn't depend on C99 types; assumes "int" is at least 32 bits, and makes - * a few assumptions about format specifiers. - */ - -#include -#include -#include - -#include "duktape.h" -#include "duk_trans_dvalue.h" - -/* Define to enable debug prints to stderr. */ -#if 0 -#define DEBUG_PRINTS -#endif - -/* Define to enable error prints to stderr. */ -#if 1 -#define ERROR_PRINTS -#endif - -/* - * Dvalue handling - */ - -duk_dvalue *duk_dvalue_alloc(void) { - duk_dvalue *dv = (duk_dvalue *) malloc(sizeof(duk_dvalue)); - if (dv) { - memset((void *) dv, 0, sizeof(duk_dvalue)); - dv->buf = NULL; - } - return dv; -} - -void duk_dvalue_free(duk_dvalue *dv) { - if (dv) { - free(dv->buf); /* tolerates NULL */ - dv->buf = NULL; - free(dv); - } -} - -static void duk__dvalue_bufesc(duk_dvalue *dv, char *buf, size_t maxbytes, int stresc) { - size_t i, limit; - - *buf = (char) 0; - limit = dv->len > maxbytes ? maxbytes : dv->len; - for (i = 0; i < limit; i++) { - unsigned char c = dv->buf[i]; - if (stresc) { - if (c >= 0x20 && c <= 0x7e && c != (char) '"' && c != (char) '\'') { - sprintf(buf, "%c", c); - buf++; - } else { - sprintf(buf, "\\x%02x", (unsigned int) c); - buf += 4; - } - } else { - sprintf(buf, "%02x", (unsigned int) c); - buf += 2; - } - } - if (dv->len > maxbytes) { - sprintf(buf, "..."); - buf += 3; - } -} - -/* Caller must provide a buffer at least DUK_DVALUE_TOSTRING_BUFLEN in size. */ -void duk_dvalue_to_string(duk_dvalue *dv, char *buf) { - char hexbuf[32 * 4 + 4]; /* 32 hex encoded or \xXX escaped bytes, possible "...", NUL */ - - if (!dv) { - sprintf(buf, "NULL"); - return; - } - - switch (dv->tag) { - case DUK_DVALUE_EOM: - sprintf(buf, "EOM"); - break; - case DUK_DVALUE_REQ: - sprintf(buf, "REQ"); - break; - case DUK_DVALUE_REP: - sprintf(buf, "REP"); - break; - case DUK_DVALUE_ERR: - sprintf(buf, "ERR"); - break; - case DUK_DVALUE_NFY: - sprintf(buf, "NFY"); - break; - case DUK_DVALUE_INTEGER: - sprintf(buf, "%d", dv->i); - break; - case DUK_DVALUE_STRING: - duk__dvalue_bufesc(dv, hexbuf, 32, 1); - sprintf(buf, "str:%ld:\"%s\"", (long) dv->len, hexbuf); - break; - case DUK_DVALUE_BUFFER: - duk__dvalue_bufesc(dv, hexbuf, 32, 0); - sprintf(buf, "buf:%ld:%s", (long) dv->len, hexbuf); - break; - case DUK_DVALUE_UNUSED: - sprintf(buf, "undefined"); - break; - case DUK_DVALUE_UNDEFINED: - sprintf(buf, "undefined"); - break; - case DUK_DVALUE_NULL: - sprintf(buf, "null"); - break; - case DUK_DVALUE_TRUE: - sprintf(buf, "true"); - break; - case DUK_DVALUE_FALSE: - sprintf(buf, "false"); - break; - case DUK_DVALUE_NUMBER: - if (fpclassify(dv->d) == FP_ZERO) { - if (signbit(dv->d)) { - sprintf(buf, "-0"); - } else { - sprintf(buf, "0"); - } - } else { - sprintf(buf, "%lg", dv->d); - } - break; - case DUK_DVALUE_OBJECT: - duk__dvalue_bufesc(dv, hexbuf, 32, 0); - sprintf(buf, "obj:%d:%s", (int) dv->i, hexbuf); - break; - case DUK_DVALUE_POINTER: - duk__dvalue_bufesc(dv, hexbuf, 32, 0); - sprintf(buf, "ptr:%s", hexbuf); - break; - case DUK_DVALUE_LIGHTFUNC: - duk__dvalue_bufesc(dv, hexbuf, 32, 0); - sprintf(buf, "lfunc:%04x:%s", (unsigned int) dv->i, hexbuf); - break; - case DUK_DVALUE_HEAPPTR: - duk__dvalue_bufesc(dv, hexbuf, 32, 0); - sprintf(buf, "heapptr:%s", hexbuf); - break; - default: - sprintf(buf, "unknown:%d", (int) dv->tag); - } -} - -duk_dvalue *duk_dvalue_make_tag(int tag) { - duk_dvalue *dv = duk_dvalue_alloc(); - if (!dv) { return NULL; } - dv->tag = tag; - return dv; -} - -duk_dvalue *duk_dvalue_make_tag_int(int tag, int intval) { - duk_dvalue *dv = duk_dvalue_alloc(); - if (!dv) { return NULL; } - dv->tag = tag; - dv->i = intval; - return dv; -} - -duk_dvalue *duk_dvalue_make_tag_double(int tag, double dblval) { - duk_dvalue *dv = duk_dvalue_alloc(); - if (!dv) { return NULL; } - dv->tag = tag; - dv->d = dblval; - return dv; -} - -duk_dvalue *duk_dvalue_make_tag_data(int tag, const char *buf, size_t len) { - unsigned char *p; - duk_dvalue *dv = duk_dvalue_alloc(); - if (!dv) { return NULL; } - /* Alloc size is len + 1 so that a NUL terminator is always - * guaranteed which is convenient, e.g. you can printf() the - * value safely. - */ - p = (unsigned char *) malloc(len + 1); - if (!p) { - free(dv); - return NULL; - } - memcpy((void *) p, (const void *) buf, len); - p[len] = (unsigned char) 0; - dv->tag = tag; - dv->buf = p; - dv->len = len; - return dv; -} - -duk_dvalue *duk_dvalue_make_tag_int_data(int tag, int intval, const char *buf, size_t len) { - duk_dvalue *dv = duk_dvalue_make_tag_data(tag, buf, len); - if (!dv) { return NULL; } - dv->i = intval; - return dv; -} - -/* - * Dvalue transport handling - */ - -static void duk__trans_dvalue_double_byteswap(duk_trans_dvalue_ctx *ctx, volatile unsigned char *p) { - unsigned char t; - - /* Portable IEEE double byteswap. Relies on runtime detection of - * host endianness. - */ - - if (ctx->double_byteorder == 0) { - /* little endian */ - t = p[0]; p[0] = p[7]; p[7] = t; - t = p[1]; p[1] = p[6]; p[6] = t; - t = p[2]; p[2] = p[5]; p[5] = t; - t = p[3]; p[3] = p[4]; p[4] = t; - } else if (ctx->double_byteorder == 1) { - /* big endian: ok as is */ - ; - } else { - /* mixed endian */ - t = p[0]; p[0] = p[3]; p[3] = t; - t = p[1]; p[1] = p[2]; p[2] = t; - t = p[4]; p[4] = p[7]; p[7] = t; - t = p[5]; p[5] = p[6]; p[6] = t; - } -} - -static unsigned int duk__trans_dvalue_parse_u32(duk_trans_dvalue_ctx *ctx, unsigned char *p) { - /* Integers are network endian, read back into host format in - * a portable manner. - */ - (void) ctx; - return (((unsigned int) p[0]) << 24) + - (((unsigned int) p[1]) << 16) + - (((unsigned int) p[2]) << 8) + - (((unsigned int) p[3]) << 0); -} - -static int duk__trans_dvalue_parse_i32(duk_trans_dvalue_ctx *ctx, unsigned char *p) { - /* Portable sign handling, doesn't assume 'int' is exactly 32 bits - * like a direct cast would. - */ - unsigned int tmp = duk__trans_dvalue_parse_u32(ctx, p); - if (tmp & 0x80000000UL) { - return -((int) ((tmp ^ 0xffffffffUL) + 1UL)); - } else { - return tmp; - } -} - -static unsigned int duk__trans_dvalue_parse_u16(duk_trans_dvalue_ctx *ctx, unsigned char *p) { - /* Integers are network endian, read back into host format. */ - (void) ctx; - return (((unsigned int) p[0]) << 8) + - (((unsigned int) p[1]) << 0); -} - -static double duk__trans_dvalue_parse_double(duk_trans_dvalue_ctx *ctx, unsigned char *p) { - /* IEEE doubles are network endian, read back into host format. */ - volatile union { - double d; - unsigned char b[8]; - } u; - memcpy((void *) u.b, (const void *) p, 8); - duk__trans_dvalue_double_byteswap(ctx, u.b); - return u.d; -} - -static unsigned char *duk__trans_dvalue_encode_u32(duk_trans_dvalue_ctx *ctx, unsigned char *p, unsigned int val) { - /* Integers are written in network endian format. */ - (void) ctx; - *p++ = (unsigned char) ((val >> 24) & 0xff); - *p++ = (unsigned char) ((val >> 16) & 0xff); - *p++ = (unsigned char) ((val >> 8) & 0xff); - *p++ = (unsigned char) (val & 0xff); - return p; -} - -static unsigned char *duk__trans_dvalue_encode_i32(duk_trans_dvalue_ctx *ctx, unsigned char *p, int val) { - return duk__trans_dvalue_encode_u32(ctx, p, (unsigned int) val & 0xffffffffUL); -} - -static unsigned char *duk__trans_dvalue_encode_u16(duk_trans_dvalue_ctx *ctx, unsigned char *p, unsigned int val) { - /* Integers are written in network endian format. */ - (void) ctx; - *p++ = (unsigned char) ((val >> 8) & 0xff); - *p++ = (unsigned char) (val & 0xff); - return p; -} - -static unsigned char *duk__trans_dvalue_encode_double(duk_trans_dvalue_ctx *ctx, unsigned char *p, double val) { - /* IEEE doubles are written in network endian format. */ - volatile union { - double d; - unsigned char b[8]; - } u; - u.d = val; - duk__trans_dvalue_double_byteswap(ctx, u.b); - memcpy((void *) p, (const void *) u.b, 8); - p += 8; - return p; -} - -static unsigned char *duk__trans_buffer_ensure(duk_trans_buffer *dbuf, size_t space) { - size_t avail; - size_t used; - size_t new_size; - void *new_alloc; - - used = dbuf->write_offset; - avail = dbuf->alloc_size - dbuf->write_offset; - - if (avail >= space) { - if (avail - space > 256) { - /* Too big, resize so that we reclaim memory if we have just - * received a large string/buffer value. - */ - goto do_realloc; - } - } else { - /* Too small, resize. */ - goto do_realloc; - } - - return dbuf->base + dbuf->write_offset; - - do_realloc: - new_size = used + space + 256; /* some extra to reduce resizes */ - new_alloc = realloc(dbuf->base, new_size); - if (new_alloc) { - dbuf->base = (unsigned char *) new_alloc; - dbuf->alloc_size = new_size; -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: resized buffer %p to %ld bytes, read_offset=%ld, write_offset=%ld\n", - __func__, (void *) dbuf, (long) new_size, (long) dbuf->read_offset, (long) dbuf->write_offset); - fflush(stderr); -#endif - return dbuf->base + dbuf->write_offset; - } else { - return NULL; - } -} - -/* When read_offset is large enough, "rebase" buffer by deleting already - * read data and updating offsets. - */ -static void duk__trans_buffer_rebase(duk_trans_buffer *dbuf) { - if (dbuf->read_offset > 64) { -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: rebasing buffer %p, read_offset=%ld, write_offset=%ld\n", - __func__, (void *) dbuf, (long) dbuf->read_offset, (long) dbuf->write_offset); - fflush(stderr); -#endif - if (dbuf->write_offset > dbuf->read_offset) { - memmove((void *) dbuf->base, (const void *) (dbuf->base + dbuf->read_offset), dbuf->write_offset - dbuf->read_offset); - } - dbuf->write_offset -= dbuf->read_offset; - dbuf->read_offset = 0; - } -} - -duk_trans_dvalue_ctx *duk_trans_dvalue_init(void) { - volatile union { - double d; - unsigned char b[8]; - } u; - duk_trans_dvalue_ctx *ctx = NULL; - - ctx = (duk_trans_dvalue_ctx *) malloc(sizeof(duk_trans_dvalue_ctx)); - if (!ctx) { goto fail; } - memset((void *) ctx, 0, sizeof(duk_trans_dvalue_ctx)); - ctx->received = NULL; - ctx->cooperate = NULL; - ctx->handshake = NULL; - ctx->detached = NULL; - ctx->send_buf.base = NULL; - ctx->recv_buf.base = NULL; - - ctx->send_buf.base = malloc(256); - if (!ctx->send_buf.base) { goto fail; } - ctx->send_buf.alloc_size = 256; - - ctx->recv_buf.base = malloc(256); - if (!ctx->recv_buf.base) { goto fail; } - ctx->recv_buf.alloc_size = 256; - - /* IEEE double byte order, detect at run time (could also use - * preprocessor defines but that's verbose to make portable). - * - * >>> struct.unpack('>d', '1122334455667788'.decode('hex')) - * (3.841412024471731e-226,) - * >>> struct.unpack('>d', '8877665544332211'.decode('hex')) - * (-7.086876636573014e-268,) - * >>> struct.unpack('>d', '4433221188776655'.decode('hex')) - * (3.5294303071877444e+20,) - */ - u.b[0] = 0x11; u.b[1] = 0x22; u.b[2] = 0x33; u.b[3] = 0x44; - u.b[4] = 0x55; u.b[5] = 0x66; u.b[6] = 0x77; u.b[7] = 0x88; - if (u.d < 0.0) { - ctx->double_byteorder = 0; /* little endian */ - } else if (u.d < 1.0) { - ctx->double_byteorder = 1; /* big endian */ - } else { - ctx->double_byteorder = 2; /* mixed endian (arm) */ - } -#if defined(DEBUG_PRINTS) - fprintf(stderr, "double endianness test value is %lg -> byteorder %d\n", - u.d, ctx->double_byteorder); - fflush(stderr); -#endif - - return ctx; - - fail: - if (ctx) { - free(ctx->recv_buf.base); /* tolerates NULL */ - free(ctx->send_buf.base); /* tolerates NULL */ - free(ctx); - } - return NULL; -} - -void duk_trans_dvalue_free(duk_trans_dvalue_ctx *ctx) { - if (ctx) { - free(ctx->send_buf.base); /* tolerates NULL */ - free(ctx->recv_buf.base); /* tolerates NULL */ - free(ctx); - } -} - -void duk_trans_dvalue_send(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { - unsigned char *p; - - /* Convert argument dvalue into Duktape debug protocol format. - * Literal constants are used here for the debug protocol, - * e.g. initial byte 0x02 is REP, see doc/debugger.rst. - */ - -#if defined(DEBUG_PRINTS) - { - char buf[DUK_DVALUE_TOSTRING_BUFLEN]; - duk_dvalue_to_string(dv, buf); - fprintf(stderr, "%s: sending dvalue: %s\n", __func__, buf); - fflush(stderr); - } -#endif - - switch (dv->tag) { - case DUK_DVALUE_EOM: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x00; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_REQ: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x01; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_REP: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x02; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_ERR: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x03; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_NFY: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x04; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_INTEGER: { - int i = dv->i; - if (i >= 0 && i <= 63) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = (unsigned char) (0x80 + i); - ctx->send_buf.write_offset += 1; - } else if (i >= 0 && i <= 16383L) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 2); - if (!p) { goto alloc_error; } - *p++ = (unsigned char) (0xc0 + (i >> 8)); - *p++ = (unsigned char) (i & 0xff); - ctx->send_buf.write_offset += 2; - } else if (i >= -0x80000000L && i <= 0x7fffffffL) { /* Harmless warning on some platforms (re: range) */ - p = duk__trans_buffer_ensure(&ctx->send_buf, 5); - if (!p) { goto alloc_error; } - *p++ = 0x10; - p = duk__trans_dvalue_encode_i32(ctx, p, i); - ctx->send_buf.write_offset += 5; - } else { - goto dvalue_error; - } - break; - } - case DUK_DVALUE_STRING: { - size_t i = dv->len; - if (i <= 0x1fUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1 + i); - if (!p) { goto alloc_error; } - *p++ = (unsigned char) (0x60 + i); - memcpy((void *) p, (const void *) dv->buf, i); - p += i; - ctx->send_buf.write_offset += 1 + i; - } else if (i <= 0xffffUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 3 + i); - if (!p) { goto alloc_error; } - *p++ = 0x12; - p = duk__trans_dvalue_encode_u16(ctx, p, (unsigned int) i); - memcpy((void *) p, (const void *) dv->buf, i); - p += i; - ctx->send_buf.write_offset += 3 + i; - } else if (i <= 0xffffffffUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 5 + i); - if (!p) { goto alloc_error; } - *p++ = 0x11; - p = duk__trans_dvalue_encode_u32(ctx, p, (unsigned int) i); - memcpy((void *) p, (const void *) dv->buf, i); - p += i; - ctx->send_buf.write_offset += 5 + i; - } else { - goto dvalue_error; - } - break; - } - case DUK_DVALUE_BUFFER: { - size_t i = dv->len; - if (i <= 0xffffUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 3 + i); - if (!p) { goto alloc_error; } - *p++ = 0x14; - p = duk__trans_dvalue_encode_u16(ctx, p, (unsigned int) i); - memcpy((void *) p, (const void *) dv->buf, i); - p += i; - ctx->send_buf.write_offset += 3 + i; - } else if (i <= 0xffffffffUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 5 + i); - if (!p) { goto alloc_error; } - *p++ = 0x13; - p = duk__trans_dvalue_encode_u32(ctx, p, (unsigned int) i); - memcpy((void *) p, (const void *) dv->buf, i); - p += i; - ctx->send_buf.write_offset += 5 + i; - } else { - goto dvalue_error; - } - break; - } - case DUK_DVALUE_UNUSED: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x15; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_UNDEFINED: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x16; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_NULL: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x17; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_TRUE: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x18; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_FALSE: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 1); - if (!p) { goto alloc_error; } - *p++ = 0x19; - ctx->send_buf.write_offset += 1; - break; - } - case DUK_DVALUE_NUMBER: { - p = duk__trans_buffer_ensure(&ctx->send_buf, 9); - if (!p) { goto alloc_error; } - *p++ = 0x1a; - p = duk__trans_dvalue_encode_double(ctx, p, dv->d); - ctx->send_buf.write_offset += 9; - break; - } - case DUK_DVALUE_OBJECT: { - size_t i = dv->len; - if (i <= 0xffUL && dv->i >= 0 && dv->i <= 0xffL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 3 + i); - if (!p) { goto alloc_error; } - *p++ = 0x1b; - *p++ = (unsigned char) dv->i; - *p++ = (unsigned char) i; - memcpy((void *) p, (const void *) dv->buf, i); - ctx->send_buf.write_offset += 3 + i; - } else { - goto dvalue_error; - } - break; - } - case DUK_DVALUE_POINTER: { - size_t i = dv->len; - if (i <= 0xffUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 2 + i); - if (!p) { goto alloc_error; } - *p++ = 0x1c; - *p++ = (unsigned char) i; - memcpy((void *) p, (const void *) dv->buf, i); - ctx->send_buf.write_offset += 2 + i; - } else { - goto dvalue_error; - } - break; - } - case DUK_DVALUE_LIGHTFUNC: { - size_t i = dv->len; - if (i <= 0xffUL && dv->i >= 0 && dv->i <= 0xffffL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 4 + i); - if (!p) { goto alloc_error; } - *p++ = 0x1d; - p = duk__trans_dvalue_encode_u16(ctx, p, (unsigned int) dv->i); - *p++ = (unsigned char) i; - memcpy((void *) p, (const void *) dv->buf, i); - ctx->send_buf.write_offset += 4 + i; - } else { - goto dvalue_error; - } - break; - } - case DUK_DVALUE_HEAPPTR: { - size_t i = dv->len; - if (i <= 0xffUL) { - p = duk__trans_buffer_ensure(&ctx->send_buf, 2 + i); - if (!p) { goto alloc_error; } - *p++ = 0x1e; - *p++ = (unsigned char) i; - memcpy((void *) p, (const void *) dv->buf, i); - ctx->send_buf.write_offset += 2 + i; - } else { - goto dvalue_error; - } - break; - } - default: { - goto dvalue_error; - } - } /* end switch */ - - return; - - dvalue_error: -#if defined(ERROR_PRINTS) - fprintf(stderr, "%s: internal error, argument dvalue is invalid\n", __func__); - fflush(stdout); -#endif - return; - - alloc_error: -#if defined(ERROR_PRINTS) - fprintf(stderr, "%s: internal error, failed to allocate space for write\n", __func__); - fflush(stdout); -#endif - return; -} - -static void duk__trans_dvalue_send_and_free(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { - if (!dv) { return; } - duk_trans_dvalue_send(ctx, dv); - duk_dvalue_free(dv); -} - -void duk_trans_dvalue_send_eom(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_EOM)); -} - -void duk_trans_dvalue_send_req(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_REQ)); -} - -void duk_trans_dvalue_send_rep(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_REP)); -} - -void duk_trans_dvalue_send_err(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_ERR)); -} - -void duk_trans_dvalue_send_nfy(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_NFY)); -} - -void duk_trans_dvalue_send_integer(duk_trans_dvalue_ctx *ctx, int val) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, val)); -} - -void duk_trans_dvalue_send_string(duk_trans_dvalue_ctx *ctx, const char *str) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_STRING, str, strlen(str))); -} - -void duk_trans_dvalue_send_lstring(duk_trans_dvalue_ctx *ctx, const char *str, size_t len) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_STRING, str, len)); -} - -void duk_trans_dvalue_send_buffer(duk_trans_dvalue_ctx *ctx, const char *buf, size_t len) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_BUFFER, buf, len)); -} - -void duk_trans_dvalue_send_unused(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_UNUSED)); -} - -void duk_trans_dvalue_send_undefined(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_UNDEFINED)); -} - -void duk_trans_dvalue_send_null(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_NULL)); -} - -void duk_trans_dvalue_send_true(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_TRUE)); -} - -void duk_trans_dvalue_send_false(duk_trans_dvalue_ctx *ctx) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag(DUK_DVALUE_FALSE)); -} - -void duk_trans_dvalue_send_number(duk_trans_dvalue_ctx *ctx, double val) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_double(DUK_DVALUE_NUMBER, val)); -} - -void duk_trans_dvalue_send_object(duk_trans_dvalue_ctx *ctx, int classnum, const char *ptr_data, size_t ptr_len) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_int_data(DUK_DVALUE_OBJECT, classnum, ptr_data, ptr_len)); -} - -void duk_trans_dvalue_send_pointer(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_POINTER, ptr_data, ptr_len)); -} - -void duk_trans_dvalue_send_lightfunc(duk_trans_dvalue_ctx *ctx, int lf_flags, const char *ptr_data, size_t ptr_len) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_int_data(DUK_DVALUE_LIGHTFUNC, lf_flags, ptr_data, ptr_len)); -} - -void duk_trans_dvalue_send_heapptr(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len) { - duk__trans_dvalue_send_and_free(ctx, duk_dvalue_make_tag_data(DUK_DVALUE_HEAPPTR, ptr_data, ptr_len)); -} - -void duk_trans_dvalue_send_req_cmd(duk_trans_dvalue_ctx *ctx, int cmd) { - duk_trans_dvalue_send_req(ctx); - duk_trans_dvalue_send_integer(ctx, cmd); -} - -static duk_dvalue *duk__trans_trial_parse_dvalue(duk_trans_dvalue_ctx *ctx) { - unsigned char *p; - size_t len; - unsigned char ib; - duk_dvalue *dv; - size_t datalen; - - p = ctx->recv_buf.base + ctx->recv_buf.read_offset; - len = ctx->recv_buf.write_offset - ctx->recv_buf.read_offset; - - if (len == 0) { - return NULL; - } - ib = p[0]; - -#if defined(DEBUG_PRINTS) - { - size_t i; - fprintf(stderr, "%s: parsing dvalue, window:", __func__); - for (i = 0; i < 16; i++) { - if (i < len) { - fprintf(stderr, " %02x", (unsigned int) p[i]); - } else { - fprintf(stderr, " ??"); - } - } - fprintf(stderr, " (length %ld, read_offset %ld, write_offset %ld, alloc_size %ld)\n", - (long) len, (long) ctx->recv_buf.read_offset, (long) ctx->recv_buf.write_offset, - (long) ctx->recv_buf.alloc_size); - fflush(stderr); - } -#endif - - if (ib <= 0x1fU) { - /* 0x00 ... 0x1f */ - switch (ib) { - case 0x00: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_EOM); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x01: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_REQ); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x02: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_REP); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x03: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_ERR); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x04: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_NFY); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x10: { - int intval; - if (len < 5) { goto partial; } - intval = duk__trans_dvalue_parse_i32(ctx, p + 1); - ctx->recv_buf.read_offset += 5; - dv = duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, intval); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x11: { - if (len < 5) { goto partial; } - datalen = (size_t) duk__trans_dvalue_parse_u32(ctx, p + 1); - if (len < 5 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 5 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) (p + 5), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x12: { - if (len < 3) { goto partial; } - datalen = (size_t) duk__trans_dvalue_parse_u16(ctx, p + 1); - if (len < 3 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 3 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) (p + 3), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x13: { - if (len < 5) { goto partial; } - datalen = (size_t) duk__trans_dvalue_parse_u32(ctx, p + 1); - if (len < 5 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 5 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_BUFFER, (const char *) (p + 5), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x14: { - if (len < 3) { goto partial; } - datalen = (size_t) duk__trans_dvalue_parse_u16(ctx, p + 1); - if (len < 3 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 3 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_BUFFER, (const char *) (p + 3), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x15: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_UNUSED); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x16: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_UNDEFINED); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x17: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_NULL); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x18: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_TRUE); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x19: { - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag(DUK_DVALUE_FALSE); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x1a: { - double dblval; - if (len < 9) { goto partial; } - dblval = duk__trans_dvalue_parse_double(ctx, p + 1); - ctx->recv_buf.read_offset += 9; - dv = duk_dvalue_make_tag_double(DUK_DVALUE_NUMBER, dblval); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x1b: { - int classnum; - if (len < 3) { goto partial; } - datalen = (size_t) p[2]; - if (len < 3 + datalen) { goto partial; } - classnum = (int) p[1]; - ctx->recv_buf.read_offset += 3 + datalen; - dv = duk_dvalue_make_tag_int_data(DUK_DVALUE_OBJECT, classnum, (const char *) (p + 3), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x1c: { - if (len < 2) { goto partial; } - datalen = (size_t) p[1]; - if (len < 2 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 2 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_POINTER, (const char *) (p + 2), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x1d: { - int lf_flags; - if (len < 4) { goto partial; } - datalen = (size_t) p[3]; - if (len < 4 + datalen) { goto partial; } - lf_flags = (int) duk__trans_dvalue_parse_u16(ctx, p + 1); - ctx->recv_buf.read_offset += 4 + datalen; - dv = duk_dvalue_make_tag_int_data(DUK_DVALUE_LIGHTFUNC, lf_flags, (const char *) (p + 4), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - case 0x1e: { - if (len < 2) { goto partial; } - datalen = (size_t) p[1]; - if (len < 2 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 2 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_HEAPPTR, (const char *) (p + 2), datalen); - if (!dv) { goto alloc_error; } - return dv; - } - default: { - goto format_error; - } - } /* end switch */ - } else if (ib <= 0x5fU) { - /* 0x20 ... 0x5f */ - goto format_error; - } else if (ib <= 0x7fU) { - /* 0x60 ... 0x7f */ - datalen = (size_t) (ib - 0x60U); - if (len < 1 + datalen) { goto partial; } - ctx->recv_buf.read_offset += 1 + datalen; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) (p + 1), datalen); - if (!dv) { goto alloc_error; } - return dv; - } else if (ib <= 0xbfU) { - /* 0x80 ... 0xbf */ - int intval; - intval = (int) (ib - 0x80U); - ctx->recv_buf.read_offset += 1; - dv = duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, intval); - if (!dv) { goto alloc_error; } - return dv; - } else { - /* 0xc0 ... 0xff */ - int intval; - if (len < 2) { goto partial; } - intval = (((int) (ib - 0xc0U)) << 8) + (int) p[1]; - ctx->recv_buf.read_offset += 2; - dv = duk_dvalue_make_tag_int(DUK_DVALUE_INTEGER, intval); - if (!dv) { goto alloc_error; } - return dv; - } - - /* never here */ - - partial: - return NULL; - - alloc_error: -#if defined(ERROR_PRINTS) - fprintf(stderr, "%s: internal error, cannot allocate space for dvalue\n", __func__); - fflush(stdout); -#endif - return NULL; - - format_error: -#if defined(ERROR_PRINTS) - fprintf(stderr, "%s: internal error, dvalue format error\n", __func__); - fflush(stdout); -#endif - return NULL; -} - -static duk_dvalue *duk__trans_trial_parse_handshake(duk_trans_dvalue_ctx *ctx) { - unsigned char *p; - size_t len; - duk_dvalue *dv; - size_t i; - - p = ctx->recv_buf.base + ctx->recv_buf.read_offset; - len = ctx->recv_buf.write_offset - ctx->recv_buf.read_offset; - - for (i = 0; i < len; i++) { - if (p[i] == 0x0a) { - /* Handshake line is returned as a dvalue for convenience; it's - * not actually a part of the dvalue phase of the protocol. - */ - ctx->recv_buf.read_offset += i + 1; - dv = duk_dvalue_make_tag_data(DUK_DVALUE_STRING, (const char *) p, i); - if (!dv) { goto alloc_error; } - return dv; - } - } - - return NULL; - - alloc_error: -#if defined(ERROR_PRINTS) - fprintf(stderr, "%s: internal error, cannot allocate space for handshake line\n", __func__); - fflush(stdout); -#endif - return NULL; -} - -static void duk__trans_call_cooperate(duk_trans_dvalue_ctx *ctx, int block) { - if (ctx->cooperate) { - ctx->cooperate(ctx, block); - } -} - -static void duk__trans_call_received(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { - if (ctx->received) { - ctx->received(ctx, dv); - } -} - -static void duk__trans_call_handshake(duk_trans_dvalue_ctx *ctx, const char *line) { - if (ctx->handshake) { - ctx->handshake(ctx, line); - } -} - -static void duk__trans_call_detached(duk_trans_dvalue_ctx *ctx) { - if (ctx->detached) { - ctx->detached(ctx); - } -} - -/* - * Duktape callbacks - */ - -duk_size_t duk_trans_dvalue_read_cb(void *udata, char *buffer, duk_size_t length) { - duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: %p %p %ld\n", __func__, udata, (void *) buffer, (long) length); - fflush(stderr); -#endif - - duk__trans_call_cooperate(ctx, 0); - - for (;;) { - size_t avail, now; - - avail = (size_t) (ctx->send_buf.write_offset - ctx->send_buf.read_offset); - if (avail == 0) { - /* Must cooperate until user callback provides data. From - * Duktape's perspective we MUST block until data is received. - */ - duk__trans_call_cooperate(ctx, 1); - } else { - now = avail; - if (now > length) { - now = length; - } - memcpy((void *) buffer, (const void *) (ctx->send_buf.base + ctx->send_buf.read_offset), now); - duk__trans_buffer_rebase(&ctx->send_buf); - ctx->send_buf.read_offset += now; - return now; - } - } -} - -duk_size_t duk_trans_dvalue_write_cb(void *udata, const char *buffer, duk_size_t length) { - duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; - unsigned char *p; - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: %p %p %ld\n", __func__, udata, (void *) buffer, (long) length); - fflush(stderr); -#endif - - duk__trans_call_cooperate(ctx, 0); - - /* Append data. */ - duk__trans_buffer_rebase(&ctx->recv_buf); - p = duk__trans_buffer_ensure(&ctx->recv_buf, length); - memcpy((void *) p, (const void *) buffer, (size_t) length); - ctx->recv_buf.write_offset += length; - - /* Trial parse handshake line or dvalue(s). */ - if (!ctx->handshake_done) { - duk_dvalue *dv = duk__trans_trial_parse_handshake(ctx); - if (dv) { - /* Handshake line is available for caller for the - * duration of the callback, and must not be freed - * by the caller. - */ - duk__trans_call_handshake(ctx, (const char *) dv->buf); -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: handshake ok\n", __func__); - fflush(stderr); -#endif - duk_dvalue_free(dv); - ctx->handshake_done = 1; - } - } - if (ctx->handshake_done) { - for (;;) { - duk_dvalue *dv = duk__trans_trial_parse_dvalue(ctx); - if (dv) { -#if defined(DEBUG_PRINTS) - { - char buf[DUK_DVALUE_TOSTRING_BUFLEN]; - duk_dvalue_to_string(dv, buf); - fprintf(stderr, "%s: received dvalue: %s\n", __func__, buf); - fflush(stderr); - } -#endif - - duk__trans_call_received(ctx, dv); - } else { - break; - } - } - } - - duk__trans_call_cooperate(ctx, 0); /* just in case, if dvalues changed something */ - - return length; -} - -duk_size_t duk_trans_dvalue_peek_cb(void *udata) { - duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; - size_t avail; - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: %p\n", __func__, udata); - fflush(stderr); -#endif - - duk__trans_call_cooperate(ctx, 0); - avail = (size_t) (ctx->send_buf.write_offset - ctx->send_buf.read_offset); - return (duk_size_t) avail; -} - -void duk_trans_dvalue_read_flush_cb(void *udata) { - duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: %p\n", __func__, udata); - fflush(stderr); -#endif - - duk__trans_call_cooperate(ctx, 0); -} - -void duk_trans_dvalue_write_flush_cb(void *udata) { - duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: %p\n", __func__, udata); - fflush(stderr); -#endif - - duk__trans_call_cooperate(ctx, 0); -} - -void duk_trans_dvalue_detached_cb(void *udata) { - duk_trans_dvalue_ctx *ctx = (duk_trans_dvalue_ctx *) udata; - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: %p\n", __func__, udata); - fflush(stderr); -#endif - - duk__trans_call_detached(ctx); -} diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.h b/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.h deleted file mode 100644 index e0ba731b..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef DUK_TRANS_DVALUE_H_INCLUDED -#define DUK_TRANS_DVALUE_H_INCLUDED - -#include "duktape.h" - -typedef struct duk_dvalue duk_dvalue; -typedef struct duk_trans_buffer duk_trans_buffer; -typedef struct duk_trans_dvalue_ctx duk_trans_dvalue_ctx; - -typedef void (*duk_trans_dvalue_received_function)(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv); -typedef void (*duk_trans_dvalue_cooperate_function)(duk_trans_dvalue_ctx *ctx, int block); -typedef void (*duk_trans_dvalue_handshake_function)(duk_trans_dvalue_ctx *ctx, const char *handshake_line); -typedef void (*duk_trans_dvalue_detached_function)(duk_trans_dvalue_ctx *ctx); - -/* struct duk_dvalue 'tag' values, note that these have nothing to do with - * Duktape debug protocol inital byte. Struct fields used with the type - * are noted next to the define. - */ -#define DUK_DVALUE_EOM 1 /* no fields */ -#define DUK_DVALUE_REQ 2 /* no fields */ -#define DUK_DVALUE_REP 3 /* no fields */ -#define DUK_DVALUE_ERR 4 /* no fields */ -#define DUK_DVALUE_NFY 5 /* no fields */ -#define DUK_DVALUE_INTEGER 6 /* i: 32-bit signed integer */ -#define DUK_DVALUE_STRING 7 /* buf: string data, len: string length */ -#define DUK_DVALUE_BUFFER 8 /* buf: buffer data, len: buffer length */ -#define DUK_DVALUE_UNUSED 9 /* no fields */ -#define DUK_DVALUE_UNDEFINED 10 /* no fields */ -#define DUK_DVALUE_NULL 11 /* no fields */ -#define DUK_DVALUE_TRUE 12 /* no fields */ -#define DUK_DVALUE_FALSE 13 /* no fields */ -#define DUK_DVALUE_NUMBER 14 /* d: ieee double */ -#define DUK_DVALUE_OBJECT 15 /* i: class number, buf: pointer data, len: pointer length */ -#define DUK_DVALUE_POINTER 16 /* buf: pointer data, len: pointer length */ -#define DUK_DVALUE_LIGHTFUNC 17 /* i: lightfunc flags, buf: pointer data, len: pointer length */ -#define DUK_DVALUE_HEAPPTR 18 /* buf: pointer data, len: pointer length */ - -struct duk_dvalue { - /* Could use a union for the value but the gain would be relatively small. */ - int tag; - int i; - double d; - size_t len; - unsigned char *buf; -}; - -struct duk_trans_buffer { - unsigned char *base; - size_t write_offset; - size_t read_offset; - size_t alloc_size; -}; - -struct duk_trans_dvalue_ctx { - duk_trans_dvalue_received_function received; - duk_trans_dvalue_cooperate_function cooperate; - duk_trans_dvalue_handshake_function handshake; - duk_trans_dvalue_detached_function detached; - duk_trans_buffer send_buf; /* sending towards Duktape (duktape read callback) */ - duk_trans_buffer recv_buf; /* receiving from Duktape (duktape write callback) */ - int handshake_done; - int double_byteorder; /* 0=little endian, 1=big endian, 2=mixed endian */ -}; - -/* Buffer size needed by duk_dvalue_to_string(). */ -#define DUK_DVALUE_TOSTRING_BUFLEN 256 - -/* Dvalue handling. */ -duk_dvalue *duk_dvalue_alloc(void); -void duk_dvalue_free(duk_dvalue *dv); -void duk_dvalue_to_string(duk_dvalue *dv, char *buf); -duk_dvalue *duk_dvalue_make_tag(int tag); -duk_dvalue *duk_dvalue_make_tag_int(int tag, int intval); -duk_dvalue *duk_dvalue_make_tag_double(int tag, double dblval); -duk_dvalue *duk_dvalue_make_tag_data(int tag, const char *buf, size_t len); -duk_dvalue *duk_dvalue_make_tag_int_data(int tag, int intval, const char *buf, size_t len); - -/* Initializing and freeing the transport context. */ -duk_trans_dvalue_ctx *duk_trans_dvalue_init(void); -void duk_trans_dvalue_free(duk_trans_dvalue_ctx *ctx); - -/* Sending dvalues towards Duktape. */ -void duk_trans_dvalue_send(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv); -void duk_trans_dvalue_send_eom(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_req(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_rep(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_err(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_nfy(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_integer(duk_trans_dvalue_ctx *ctx, int val); -void duk_trans_dvalue_send_string(duk_trans_dvalue_ctx *ctx, const char *str); -void duk_trans_dvalue_send_lstring(duk_trans_dvalue_ctx *ctx, const char *str, size_t len); -void duk_trans_dvalue_send_buffer(duk_trans_dvalue_ctx *ctx, const char *buf, size_t len); -void duk_trans_dvalue_send_unused(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_undefined(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_null(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_true(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_false(duk_trans_dvalue_ctx *ctx); -void duk_trans_dvalue_send_number(duk_trans_dvalue_ctx *ctx, double val); -void duk_trans_dvalue_send_object(duk_trans_dvalue_ctx *ctx, int classnum, const char *ptr_data, size_t ptr_len); -void duk_trans_dvalue_send_pointer(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len); -void duk_trans_dvalue_send_lightfunc(duk_trans_dvalue_ctx *ctx, int lf_flags, const char *ptr_data, size_t ptr_len); -void duk_trans_dvalue_send_heapptr(duk_trans_dvalue_ctx *ctx, const char *ptr_data, size_t ptr_len); -void duk_trans_dvalue_send_req_cmd(duk_trans_dvalue_ctx *ctx, int cmd); - -/* Duktape debug callbacks provided by the transport. */ -duk_size_t duk_trans_dvalue_read_cb(void *udata, char *buffer, duk_size_t length); -duk_size_t duk_trans_dvalue_write_cb(void *udata, const char *buffer, duk_size_t length); -duk_size_t duk_trans_dvalue_peek_cb(void *udata); -void duk_trans_dvalue_read_flush_cb(void *udata); -void duk_trans_dvalue_write_flush_cb(void *udata); -void duk_trans_dvalue_detached_cb(void *udata); - -#endif /* DUK_TRANS_DVALUE_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/test.c b/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/test.c deleted file mode 100644 index 7830ec20..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/test.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Example program using the dvalue debug transport. - */ - -#include -#include - -#include "duktape.h" -#include "duk_trans_dvalue.h" - -void my_cooperate(duk_trans_dvalue_ctx *ctx, int block) { - static int first_blocked = 1; - - if (!block) { - /* Duktape is not blocked; you can cooperate with e.g. a user - * interface here and send dvalues to Duktape, but don't block. - */ - return; - } - - /* Duktape is blocked on a read and won't continue until debug - * command(s) are sent. - * - * Normally you'd enter your own event loop here, and process - * events until something needs to be sent to Duktape. For - * example, the user might press a "Step over" button in the - * UI which would cause dvalues to be sent. You can then - * return from this callback. - * - * The code below sends some example messages for testing the - * dvalue handling of the transport. - * - * If you create dvalues manually and send them using - * duk_trans_dvalue_send(), you must free the dvalues after - * the send call returns using duk_dvalue_free(). - */ - - if (first_blocked) { - char *tmp; - int i; - - /* First time Duktape becomes blocked, send DumpHeap which - * exercises a lot of parsing code. - * - * NOTE: Valgrind may complain about reading uninitialized - * bytes. This is caused by the DumpHeap command writing out - * verbatim duk_tval values which are intentionally not - * always fully initialized for performance reasons. - */ - first_blocked = 0; - - fprintf(stderr, "Duktape is blocked, send DumpHeap\n"); - fflush(stderr); - - duk_trans_dvalue_send_req(ctx); - duk_trans_dvalue_send_integer(ctx, 0x20); /* DumpHeap */ - duk_trans_dvalue_send_eom(ctx); - - /* Also send a dummy TriggerStatus request with trailing dvalues - * ignored by Duktape; Duktape will parse the dvalues to be able to - * skip them, so that the dvalue encoding is exercised. - */ - - tmp = malloc(100000); /* long buffer, >= 65536 chars */ - for (i = 0; i < 100000; i++) { - tmp[i] = (char) i; - } - duk_trans_dvalue_send_req(ctx); - duk_trans_dvalue_send_integer(ctx, 0x11); /* TriggerStatus */ - duk_trans_dvalue_send_string(ctx, "dummy"); /* short, <= 31 chars */ - duk_trans_dvalue_send_string(ctx, "123456789012345678901234567890foobar"); /* medium, >= 32 chars */ - duk_trans_dvalue_send_lstring(ctx, (const char *) tmp, 65535UL); - duk_trans_dvalue_send_lstring(ctx, (const char *) tmp, 65536UL); - duk_trans_dvalue_send_lstring(ctx, (const char *) tmp, 100000UL); - duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 255U); - duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 65535UL); - duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 65536UL); - duk_trans_dvalue_send_buffer(ctx, (const char *) tmp, 100000UL); - duk_trans_dvalue_send_unused(ctx); - duk_trans_dvalue_send_undefined(ctx); - duk_trans_dvalue_send_null(ctx); - duk_trans_dvalue_send_true(ctx); - duk_trans_dvalue_send_false(ctx); - duk_trans_dvalue_send_number(ctx, 123.456); - duk_trans_dvalue_send_object(ctx, 12 /*classnum*/, (const char *) tmp, 8); /* fake ptr len */ - duk_trans_dvalue_send_pointer(ctx, (const char *) tmp, 8); /* fake ptr len */ - duk_trans_dvalue_send_lightfunc(ctx, 0xdabc /*lf_flags*/, (const char *) tmp, 8); /* fake ptr len */ - duk_trans_dvalue_send_heapptr(ctx, (const char *) tmp, 8); /* fake ptr len */ - - duk_trans_dvalue_send_eom(ctx); - } - - fprintf(stderr, "Duktape is blocked, send Eval and StepInto to resume execution\n"); - fflush(stderr); - - /* duk_trans_dvalue_send_req_cmd() sends a REQ dvalue followed by - * an integer dvalue (command) for convenience. - */ - - duk_trans_dvalue_send_req_cmd(ctx, 0x1e); /* 0x1e = Eval */ - duk_trans_dvalue_send_string(ctx, "evalMe"); - duk_trans_dvalue_send_eom(ctx); - - duk_trans_dvalue_send_req_cmd(ctx, 0x14); /* 0x14 = StepOver */ - duk_trans_dvalue_send_eom(ctx); -} - -void my_received(duk_trans_dvalue_ctx *ctx, duk_dvalue *dv) { - char buf[DUK_DVALUE_TOSTRING_BUFLEN]; - (void) ctx; - - duk_dvalue_to_string(dv, buf); - fprintf(stderr, "Received dvalue: %s\n", buf); - fflush(stderr); - - /* Here a normal debug client would wait for dvalues until an EOM - * dvalue was received (which completes a debug message). The - * debug message would then be handled, possibly causing UI changes - * and/or causing debug commands to be sent to Duktape. - * - * The callback is responsible for eventually freeing the dvalue. - * Here we free it immediately, but an actual client would probably - * gather dvalues into an array or linked list to handle when the - * debug message was complete. - */ - - duk_dvalue_free(dv); -} - -void my_handshake(duk_trans_dvalue_ctx *ctx, const char *line) { - (void) ctx; - - /* The Duktape handshake line is given in 'line' (without LF). - * The 'line' argument can be accessed for the duration of the - * callback (read only). Don't free 'line' here, the transport - * handles that. - */ - - fprintf(stderr, "Received handshake line: '%s'\n", line); - fflush(stderr); -} - -void my_detached(duk_trans_dvalue_ctx *ctx) { - (void) ctx; - - /* Detached call forwarded as is. */ - - fprintf(stderr, "Debug transport detached\n"); - fflush(stderr); -} - -int main(int argc, char *argv[]) { - duk_context *ctx; - duk_trans_dvalue_ctx *trans_ctx; - int exitval = 0; - - (void) argc; (void) argv; /* suppress warning */ - - ctx = duk_create_heap_default(); - if (!ctx) { - fprintf(stderr, "Failed to create Duktape heap\n"); - fflush(stderr); - exitval = 1; - goto cleanup; - } - - trans_ctx = duk_trans_dvalue_init(); - if (!trans_ctx) { - fprintf(stderr, "Failed to create debug transport context\n"); - fflush(stderr); - exitval = 1; - goto cleanup; - } - trans_ctx->cooperate = my_cooperate; - trans_ctx->received = my_received; - trans_ctx->handshake = my_handshake; - trans_ctx->detached = my_detached; - - /* Attach debugger; this will fail with a fatal error here unless - * debugger support is compiled in. To fail more gracefully, call - * this under a duk_safe_call() to catch the error. - */ - duk_debugger_attach(ctx, - duk_trans_dvalue_read_cb, - duk_trans_dvalue_write_cb, - duk_trans_dvalue_peek_cb, - duk_trans_dvalue_read_flush_cb, - duk_trans_dvalue_write_flush_cb, - duk_trans_dvalue_detached_cb, - (void *) trans_ctx); - - fprintf(stderr, "Debugger attached, running eval\n"); - fflush(stderr); - - /* Evaluate simple test code, callbacks will "step over" until end. - * - * The test code here is just for exercising the debug transport. - * The 'evalMe' variable is evaluated (using debugger command Eval) - * before every step to force different dvalues to be carried over - * the transport. - */ - - duk_eval_string(ctx, - "var evalMe;\n" - "\n" - "print('Hello world!');\n" - "[ undefined, null, true, false, 123, -123, 123.1, 0, -0, 1/0, 0/0, -1/0, \n" - " 'foo', Duktape.Buffer('bar'), Duktape.Pointer('dummy'), Math.cos, \n" - "].forEach(function (val) {\n" - " print(val);\n" - " evalMe = val;\n" - "});\n" - "\n" - "var str = 'xxx'\n" - "for (i = 0; i < 10; i++) {\n" - " print(i, str);\n" - " evalMe = str;\n" - " evalMe = Duktape.Buffer(str);\n" - " str = str + str;\n" - "}\n" - ); - duk_pop(ctx); - - duk_debugger_detach(ctx); - - cleanup: - if (trans_ctx) { - duk_trans_dvalue_free(trans_ctx); - trans_ctx = NULL; - } - if (ctx) { - duk_destroy_heap(ctx); - } - - return exitval; -} diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-socket/README.rst b/src/third_party/duktape-1.3.0/examples/debug-trans-socket/README.rst deleted file mode 100644 index 787d5e40..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-socket/README.rst +++ /dev/null @@ -1,6 +0,0 @@ -================================================ -Debug transport using a simple socket connection -================================================ - -This example implements an example debug transport which uses a Linux server -socket on the debug target. diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.c b/src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.c deleted file mode 100644 index c25fa3ea..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Example debug transport using a TCP socket - * - * The application has a server socket which can be connected to. - * After that data is just passed through. - * - * NOTE: This is Linux specific on purpose, as it's just an example how - * a debug transport can be concretely implemented. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "duktape.h" - -#ifndef DUK_DEBUG_PORT -#define DUK_DEBUG_PORT 9091 -#endif - -#if 0 -#define DEBUG_PRINTS -#endif - -static int server_sock = -1; -static int client_sock = -1; - -/* - * Transport init - */ - -void duk_trans_socket_init(void) { - struct sockaddr_in addr; - int on; - - server_sock = socket(AF_INET, SOCK_STREAM, 0); - if (server_sock < 0) { - fprintf(stderr, "%s: failed to create server socket: %s\n", __FILE__, strerror(errno)); - fflush(stderr); - goto fail; - } - - on = 1; - if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) { - fprintf(stderr, "%s: failed to set SO_REUSEADDR for server socket: %s\n", __FILE__, strerror(errno)); - fflush(stderr); - goto fail; - } - - memset((void *) &addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(DUK_DEBUG_PORT); - - if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - fprintf(stderr, "%s: failed to bind server socket: %s\n", __FILE__, strerror(errno)); - fflush(stderr); - goto fail; - } - - listen(server_sock, 1 /*backlog*/); - return; - - fail: - if (server_sock >= 0) { - (void) close(server_sock); - server_sock = -1; - } -} - -void duk_trans_socket_waitconn(void) { - struct sockaddr_in addr; - socklen_t sz; - - if (server_sock < 0) { - fprintf(stderr, "%s: no server socket, skip waiting for connection\n", __FILE__); - fflush(stderr); - return; - } - if (client_sock >= 0) { - (void) close(client_sock); - client_sock = -1; - } - - fprintf(stderr, "Waiting for debug connection on port %d\n", (int) DUK_DEBUG_PORT); - fflush(stderr); - - sz = (socklen_t) sizeof(addr); - client_sock = accept(server_sock, (struct sockaddr *) &addr, &sz); - if (client_sock < 0) { - fprintf(stderr, "%s: accept() failed, skip waiting for connection: %s\n", __FILE__, strerror(errno)); - fflush(stderr); - goto fail; - } - - fprintf(stderr, "Debug connection established\n"); - fflush(stderr); - - /* XXX: For now, close the listen socket because we won't accept new - * connections anyway. A better implementation would allow multiple - * debug attaches. - */ - - if (server_sock >= 0) { - (void) close(server_sock); - server_sock = -1; - } - return; - - fail: - if (client_sock >= 0) { - (void) close(client_sock); - client_sock = -1; - } -} - -/* - * Duktape callbacks - */ - -/* Duktape debug transport callback: partial read */ -duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length) { - ssize_t ret; - - (void) udata; /* not needed by the example */ - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n", - __func__, (void *) udata, (void *) buffer, (long) length); - fflush(stderr); -#endif - - if (client_sock < 0) { - return 0; - } - - if (length == 0) { - /* This shouldn't happen. */ - fprintf(stderr, "%s: read request length == 0, closing connection\n", __FILE__); - fflush(stderr); - goto fail; - } - - if (buffer == NULL) { - /* This shouldn't happen. */ - fprintf(stderr, "%s: read request buffer == NULL, closing connection\n", __FILE__); - fflush(stderr); - goto fail; - } - - /* In a production quality implementation there would be a sanity - * timeout here to recover from "black hole" disconnects. - */ - - ret = read(client_sock, (void *) buffer, (size_t) length); - if (ret < 0) { - fprintf(stderr, "%s: debug read failed, errno %d, closing connection: %s\n", __FILE__, errno, strerror(errno)); - fflush(stderr); - goto fail; - } else if (ret == 0) { - fprintf(stderr, "%s: debug read failed, ret == 0 (EOF), closing connection\n", __FILE__); - fflush(stderr); - goto fail; - } else if (ret > (ssize_t) length) { - fprintf(stderr, "%s: debug read failed, ret too large (%ld > %ld), closing connection\n", __FILE__, (long) ret, (long) length); - fflush(stderr); - goto fail; - } - - return (duk_size_t) ret; - - fail: - if (client_sock >= 0) { - (void) close(client_sock); - client_sock = -1; - } - return 0; -} - -/* Duktape debug transport callback: partial write */ -duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length) { - ssize_t ret; - - (void) udata; /* not needed by the example */ - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n", - __func__, (void *) udata, (void *) buffer, (long) length); - fflush(stderr); -#endif - - if (client_sock < 0) { - return 0; - } - - if (length == 0) { - /* This shouldn't happen. */ - fprintf(stderr, "%s: write request length == 0, closing connection\n", __FILE__); - fflush(stderr); - goto fail; - } - - if (buffer == NULL) { - /* This shouldn't happen. */ - fprintf(stderr, "%s: write request buffer == NULL, closing connection\n", __FILE__); - fflush(stderr); - goto fail; - } - - /* In a production quality implementation there would be a sanity - * timeout here to recover from "black hole" disconnects. - */ - - ret = write(client_sock, (const void *) buffer, (size_t) length); - if (ret <= 0 || ret > (ssize_t) length) { - fprintf(stderr, "%s: debug write failed, closing connection: %s\n", __FILE__, strerror(errno)); - fflush(stderr); - goto fail; - } - - return (duk_size_t) ret; - - fail: - if (client_sock >= 0) { - (void) close(client_sock); - client_sock = -1; - } - return 0; -} - -duk_size_t duk_trans_socket_peek_cb(void *udata) { - struct pollfd fds[1]; - int poll_rc; - - (void) udata; /* not needed by the example */ - -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata); - fflush(stderr); -#endif - - fds[0].fd = client_sock; - fds[0].events = POLLIN; - fds[0].revents = 0; - - poll_rc = poll(fds, 1, 0); - if (poll_rc < 0) { - fprintf(stderr, "%s: poll returned < 0, closing connection: %s\n", __FILE__, strerror(errno)); - fflush(stderr); - goto fail; /* also returns 0, which is correct */ - } else if (poll_rc > 1) { - fprintf(stderr, "%s: poll returned > 1, treating like 1\n", __FILE__); - fflush(stderr); - return 1; /* should never happen */ - } else if (poll_rc == 0) { - return 0; /* nothing to read */ - } else { - return 1; /* something to read */ - } - - fail: - if (client_sock >= 0) { - (void) close(client_sock); - client_sock = -1; - } - return 0; -} - -void duk_trans_socket_read_flush_cb(void *udata) { -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata); - fflush(stderr); -#endif - - (void) udata; /* not needed by the example */ - - /* Read flush: Duktape may not be making any more read calls at this - * time. If the transport maintains a receive window, it can use a - * read flush as a signal to update the window status to the remote - * peer. A read flush is guaranteed to occur before Duktape stops - * reading for a while; it may occur in other situations as well so - * it's not a 100% reliable indication. - */ - - /* This TCP transport requires no read flush handling so ignore. - * You can also pass a NULL to duk_debugger_attach() and not - * implement this callback at all. - */ -} - -void duk_trans_socket_write_flush_cb(void *udata) { -#if defined(DEBUG_PRINTS) - fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata); - fflush(stderr); -#endif - - (void) udata; /* not needed by the example */ - - /* Write flush. If the transport combines multiple writes - * before actually sending, a write flush is an indication - * to write out any pending bytes: Duktape may not be doing - * any more writes on this occasion. - */ - - /* This TCP transport requires no write flush handling so ignore. - * You can also pass a NULL to duk_debugger_attach() and not - * implement this callback at all. - */ - return; -} diff --git a/src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.h b/src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.h deleted file mode 100644 index 60712a2e..00000000 --- a/src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef DUK_TRANS_SOCKET_H_INCLUDED -#define DUK_TRANS_SOCKET_H_INCLUDED - -#include "duktape.h" - -void duk_trans_socket_init(void); -void duk_trans_socket_waitconn(void); -duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length); -duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length); -duk_size_t duk_trans_socket_peek_cb(void *udata); -void duk_trans_socket_read_flush_cb(void *udata); -void duk_trans_socket_write_flush_cb(void *udata); - -#endif /* DUK_TRANS_SOCKET_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/examples/dummy-date-provider/README.rst b/src/third_party/duktape-1.3.0/examples/dummy-date-provider/README.rst deleted file mode 100644 index bc62779f..00000000 --- a/src/third_party/duktape-1.3.0/examples/dummy-date-provider/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -==================================== -Dummy external Date provider example -==================================== - -This example implements a dummy, minimal external Date provider. diff --git a/src/third_party/duktape-1.3.0/examples/dummy-date-provider/dummy_date_provider.c b/src/third_party/duktape-1.3.0/examples/dummy-date-provider/dummy_date_provider.c deleted file mode 100644 index 9c9e7163..00000000 --- a/src/third_party/duktape-1.3.0/examples/dummy-date-provider/dummy_date_provider.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Dummy Date provider - * - * There are two minimally required macros which you must provide in - * duk_config.h: - * - * extern duk_double_t dummy_get_now(void); - * - * #define DUK_USE_DATE_GET_NOW(ctx) dummy_get_now() - * #define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) 0 - * - * Note that since the providers are macros, you don't need to use - * all arguments. Similarly, you can "return" fixed values as - * constants. Above, local timezone offset is always zero i.e. - * we're always in UTC. - * - * You can also provide optional macros to parse and format timestamps - * in a platform specific format. If not provided, Duktape will use - * ISO 8601 only (which is often good enough). - */ - -#include "duktape.h" - -duk_double_t dummy_get_now(void) { - /* Return a fixed time here as a dummy example. */ - return -11504520000.0; -} diff --git a/src/third_party/duktape-1.3.0/examples/eval/README.rst b/src/third_party/duktape-1.3.0/examples/eval/README.rst deleted file mode 100644 index eed18064..00000000 --- a/src/third_party/duktape-1.3.0/examples/eval/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -============ -Eval example -============ - -Evaluate expressions from command line. diff --git a/src/third_party/duktape-1.3.0/examples/eval/eval.c b/src/third_party/duktape-1.3.0/examples/eval/eval.c deleted file mode 100644 index 44099260..00000000 --- a/src/third_party/duktape-1.3.0/examples/eval/eval.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Very simple example program for evaluating expressions from - * command line - */ - -#include "duktape.h" -#include - -static int eval_raw(duk_context *ctx) { - duk_eval(ctx); - return 1; -} - -static int tostring_raw(duk_context *ctx) { - duk_to_string(ctx, -1); - return 1; -} - -static void usage_exit(void) { - fprintf(stderr, "Usage: eval [] ...\n"); - fflush(stderr); - exit(1); -} - -int main(int argc, char *argv[]) { - duk_context *ctx; - int i; - const char *res; - - if (argc < 2) { - usage_exit(); - } - - ctx = duk_create_heap_default(); - for (i = 1; i < argc; i++) { - printf("=== eval: '%s' ===\n", argv[i]); - duk_push_string(ctx, argv[i]); - duk_safe_call(ctx, eval_raw, 1 /*nargs*/, 1 /*nrets*/); - duk_safe_call(ctx, tostring_raw, 1 /*nargs*/, 1 /*nrets*/); - res = duk_get_string(ctx, -1); - printf("%s\n", res ? res : "null"); - duk_pop(ctx); - } - - duk_destroy_heap(ctx); - - return 0; -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/README.rst b/src/third_party/duktape-1.3.0/examples/eventloop/README.rst deleted file mode 100644 index 5b1b1477..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/README.rst +++ /dev/null @@ -1,76 +0,0 @@ -================== -Eventloop examples -================== - -Overview and usage -================== - -A few examples on how an event loop can be implemented with Duktape, mainly -illlustrating how the Duktape interface works (not how event loops should be -built otherwise). - -To test (Linux only, perhaps other Unix):: - - $ make - $ ./evloop curses-timers.js # run with Ecmascript eventloop - $ ./evloop -c curses-timers.js # run with C eventloop - -Implementation approaches -========================= - -There are several approaches to implementation timers. Here we demonstrate -two main approaches: - -1. Using a C eventloop which calls into Javascript. All the event loop state - like timers, sockets, etc, is held in C structures. - (See ``c_eventloop.c`` and ``c_eventloop.js``.) - -2. Using an Ecmascript eventloop which never returns. All the event loop state - can be managed with Ecmascript code instead of C structures. The Ecmascript - eventloop calls a Duktape/C helper to do the lowest level poll() call. - (See ``ecma_eventloop.js``.) - -Services provided -================= - -The event loop API provided by both examples is the same, and includes: - -* Timers: setTimeout, clearTimeout, setInterval, clearInterval - -* Sockets: simple network sockets - -In addition there are a few synchronous API bindings which are not event loop -related: - -* File I/O - -* Curses, for doing beautiful character graphics - -Limitations -=========== - -This is **not** a production quality event loop. This is on purpose, to -keep the example somewhat simple. Some shortcomings include: - -* A production quality event loop would track its internal state (active - timers and sockets) much more efficiently. In general memory usage and - code footprint can be reduced. - -* Buffer churn caused by allocating a new buffer for every socket read - should be eliminated by reusing buffers where appropriate. Although - churn doesn't increase memory footprint with reference counting, it - is slower than reusing buffers and might increase memory fragmentation. - -* There is no way to suspend reading or writing in the example. Adding - them is straightforward: the poll set needs to be managed dynamically. - -* The example uses poll() while one should use epoll() on Linux, kqueue() - on BSD systems, etc. - -* Timers are not very accurate, e.g. setInterval() does not try to guarantee - a steady schedule. Instead, the next interval is scheduled after the - current callback has finished. This is not the best behavior for some - environments, but avoids bunching callbacks. - -* Error handling is mostly missing. Debug prints don't interact well - with curses. diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/basic-test.js b/src/third_party/duktape-1.3.0/examples/eventloop/basic-test.js deleted file mode 100644 index 04b33927..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/basic-test.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * A few basic tests - */ - -var count = 0; -var intervalId; - -setTimeout(function (x) { print('timer 1', x); }, 1234, 'foo'); -setTimeout('print("timer 2");', 4321); -setTimeout(function () { print('timer 3'); }, 2345); -intervalId = setInterval(function (x, y) { - print('interval', ++count, x, y); - if (count >= 10) { - clearInterval(intervalId); - } -}, 400, 'foo', 'bar'); - diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.c b/src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.c deleted file mode 100644 index 75d768b3..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * C eventloop example. - * - * Timer management is similar to eventloop.js but implemented in C. - * In particular, timer insertion is an O(n) operation; in a real world - * eventloop based on a heap insertion would be O(log N). - */ - -#include -#include -#include -#include -#include -#include - -#include "duktape.h" - -#define MAX_TIMERS 4096 /* this is quite excessive for embedded use, but good for testing */ -#define MIN_DELAY 1.0 -#define MIN_WAIT 1.0 -#define MAX_WAIT 60000.0 -#define MAX_EXPIRYS 10 - -#define MAX_FDS 256 - -typedef struct { - int64_t id; /* numeric ID (returned from e.g. setTimeout); zero if unused */ - double target; /* next target time */ - double delay; /* delay/interval */ - int oneshot; /* oneshot=1 (setTimeout), repeated=0 (setInterval) */ - int removed; /* timer has been requested for removal */ - - /* The callback associated with the timer is held in the "global stash", - * in .eventTimers[String(id)]. The references must be deleted - * when a timer struct is deleted. - */ -} ev_timer; - -/* Active timers. Dense list, terminates to end of list or first unused timer. - * The list is sorted by 'target', with lowest 'target' (earliest expiry) last - * in the list. When a timer's callback is being called, the timer is moved - * to 'timer_expiring' as it needs special handling should the user callback - * delete that particular timer. - */ -static ev_timer timer_list[MAX_TIMERS]; -static ev_timer timer_expiring; -static int timer_count; /* last timer at timer_count - 1 */ -static int64_t timer_next_id = 1; - -/* Socket poll state. */ -static struct pollfd poll_list[MAX_FDS]; -static int poll_count = 0; - -/* Misc */ -static int exit_requested = 0; - -/* Get Javascript compatible 'now' timestamp (millisecs since 1970). */ -static double get_now(void) { - struct timeval tv; - int rc; - - rc = gettimeofday(&tv, NULL); - if (rc != 0) { - /* Should never happen, so return whatever. */ - return 0.0; - } - return ((double) tv.tv_sec) * 1000.0 + ((double) tv.tv_usec) / 1000.0; -} - -static ev_timer *find_nearest_timer(void) { - /* Last timer expires first (list is always kept sorted). */ - if (timer_count <= 0) { - return NULL; - } - return timer_list + timer_count - 1; -} - -/* Bubble last timer on timer list backwards until it has been moved to - * its proper sorted position (based on 'target' time). - */ -static void bubble_last_timer(void) { - int i; - int n = timer_count; - ev_timer *t; - ev_timer tmp; - - for (i = n - 1; i > 0; i--) { - /* Timer to bubble is at index i, timer to compare to is - * at i-1 (both guaranteed to exist). - */ - t = timer_list + i; - if (t->target <= (t-1)->target) { - /* 't' expires earlier than (or same time as) 't-1', so we're done. */ - break; - } else { - /* 't' expires later than 't-1', so swap them and repeat. */ - memcpy((void *) &tmp, (void *) (t - 1), sizeof(ev_timer)); - memcpy((void *) (t - 1), (void *) t, sizeof(ev_timer)); - memcpy((void *) t, (void *) &tmp, sizeof(ev_timer)); - } - } -} - -static void expire_timers(duk_context *ctx) { - ev_timer *t; - int sanity = MAX_EXPIRYS; - double now; - int rc; - - /* Because a user callback can mutate the timer list (by adding or deleting - * a timer), we expire one timer and then rescan from the end again. There - * is a sanity limit on how many times we do this per expiry round. - */ - - duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, "eventTimers"); - - /* [ ... stash eventTimers ] */ - - now = get_now(); - while (sanity-- > 0) { - /* - * If exit has been requested, exit without running further - * callbacks. - */ - - if (exit_requested) { -#if 0 - fprintf(stderr, "exit requested, exiting timer expiry loop\n"); - fflush(stderr); -#endif - break; - } - - /* - * Expired timer(s) still exist? - */ - - if (timer_count <= 0) { - break; - } - t = timer_list + timer_count - 1; - if (t->target > now) { - break; - } - - /* - * Move the timer to 'expiring' for the duration of the callback. - * Mark a one-shot timer deleted, compute a new target for an interval. - */ - - memcpy((void *) &timer_expiring, (void *) t, sizeof(ev_timer)); - memset((void *) t, 0, sizeof(ev_timer)); - timer_count--; - t = &timer_expiring; - - if (t->oneshot) { - t->removed = 1; - } else { - t->target = now + t->delay; /* XXX: or t->target + t->delay? */ - } - - /* - * Call timer callback. The callback can operate on the timer list: - * add new timers, remove timers. The callback can even remove the - * expired timer whose callback we're calling. However, because the - * timer being expired has been moved to 'timer_expiring', we don't - * need to worry about the timer's offset changing on the timer list. - */ - -#if 0 - fprintf(stderr, "calling user callback for timer id %d\n", (int) t->id); - fflush(stderr); -#endif - - duk_push_number(ctx, (double) t->id); - duk_get_prop(ctx, -2); /* -> [ ... stash eventTimers func ] */ - rc = duk_pcall(ctx, 0 /*nargs*/); /* -> [ ... stash eventTimers retval ] */ - if (rc != 0) { -#if 0 - fprintf(stderr, "timer callback failed for timer %d: %s\n", (int) t->id, duk_to_string(ctx, -1)); - fflush(stderr); -#endif - } - duk_pop(ctx); /* ignore errors for now -> [ ... stash eventTimers ] */ - - if (t->removed) { - /* One-shot timer (always removed) or removed by user callback. */ -#if 0 - fprintf(stderr, "deleting callback state for timer %d\n", (int) t->id); - fflush(stderr); -#endif - duk_push_number(ctx, (double) t->id); - duk_del_prop(ctx, -2); - } else { - /* Interval timer, not removed by user callback. Queue back to - * timer list and bubble to its final sorted position. - */ -#if 0 - fprintf(stderr, "queueing timer %d back into active list\n", (int) t->id); - fflush(stderr); -#endif - if (timer_count >= MAX_TIMERS) { - duk_error(ctx, DUK_ERR_RANGE_ERROR, "out of timer slots"); - } - memcpy((void *) (timer_list + timer_count), (void *) t, sizeof(ev_timer)); - timer_count++; - bubble_last_timer(); - } - } - - memset((void *) &timer_expiring, 0, sizeof(ev_timer)); - - duk_pop_2(ctx); /* -> [ ... ] */ -} - -static void compact_poll_list(void) { - int i, j, n; - - /* i = input index - * j = output index (initially same as i) - */ - - n = poll_count; - for (i = 0, j = 0; i < n; i++) { - struct pollfd *pfd = poll_list + i; - if (pfd->fd == 0) { - /* keep output index the same */ -#if 0 - fprintf(stderr, "remove pollfd (index %d): fd=%d, events=%d, revents=%d\n", - i, pfd->fd, pfd->events, pfd->revents), - fflush(stderr); -#endif - - continue; - } -#if 0 - fprintf(stderr, "keep pollfd (index %d -> %d): fd=%d, events=%d, revents=%d\n", - i, j, pfd->fd, pfd->events, pfd->revents), - fflush(stderr); -#endif - if (i != j) { - /* copy only if indices have diverged */ - memcpy((void *) (poll_list + j), (void *) (poll_list + i), sizeof(struct pollfd)); - } - j++; - } - - if (j < poll_count) { - /* zeroize unused entries for sanity */ - memset((void *) (poll_list + j), 0, (poll_count - j) * sizeof(struct pollfd)); - } - - poll_count = j; -} - -int eventloop_run(duk_context *ctx) { - ev_timer *t; - double now; - double diff; - int timeout; - int rc; - int i, n; - int idx_eventloop; - int idx_fd_handler; - - /* The Ecmascript poll handler is passed through EventLoop.fdPollHandler - * which c_eventloop.js sets before we come here. - */ - duk_push_global_object(ctx); - duk_get_prop_string(ctx, -1, "EventLoop"); - duk_get_prop_string(ctx, -1, "fdPollHandler"); /* -> [ global EventLoop fdPollHandler ] */ - idx_fd_handler = duk_get_top_index(ctx); - idx_eventloop = idx_fd_handler - 1; - - for (;;) { - /* - * Expire timers. - */ - - expire_timers(ctx); - - /* - * If exit requested, bail out as fast as possible. - */ - - if (exit_requested) { -#if 0 - fprintf(stderr, "exit requested, exiting event loop\n"); - fflush(stderr); -#endif - break; - } - - /* - * Compact poll list by removing pollfds with fd == 0. - */ - - compact_poll_list(); - - /* - * Determine poll() timeout (as close to poll() as possible as - * the wait is relative). - */ - - now = get_now(); - t = find_nearest_timer(); - if (t) { - diff = t->target - now; - if (diff < MIN_WAIT) { - diff = MIN_WAIT; - } else if (diff > MAX_WAIT) { - diff = MAX_WAIT; - } - timeout = (int) diff; /* clamping ensures that fits */ - } else { - if (poll_count == 0) { -#if 0 - fprintf(stderr, "no timers and no sockets to poll, exiting\n"); - fflush(stderr); -#endif - break; - } - timeout = (int) MAX_WAIT; - } - - /* - * Poll for activity or timeout. - */ - -#if 0 - fprintf(stderr, "going to poll, timeout %d ms, pollfd count %d\n", timeout, poll_count); - fflush(stderr); -#endif - - rc = poll(poll_list, poll_count, timeout); -#if 0 - fprintf(stderr, "poll rc: %d\n", rc); - fflush(stderr); -#endif - if (rc < 0) { - /* error */ - } else if (rc == 0) { - /* timeout */ - } else { - /* 'rc' fds active */ - } - - /* - * Check socket activity, handle all sockets. Handling is offloaded to - * Ecmascript code (fd + revents). - * - * If FDs are removed from the poll list while we're processing callbacks, - * the entries are simply marked unused (fd set to 0) without actually - * removing them from the poll list. This ensures indices are not - * disturbed. The poll list is compacted before next poll(). - */ - - n = (rc == 0 ? 0 : poll_count); /* if timeout, no need to check pollfd */ - for (i = 0; i < n; i++) { - struct pollfd *pfd = poll_list + i; - - if (pfd->fd == 0) { - /* deleted, perhaps by previous callback */ - continue; - } - - if (pfd->revents) { -#if 0 - fprintf(stderr, "fd %d has revents: %d\n", (int) pfd->fd, (int) pfd->revents); - fflush(stderr); -#endif - duk_dup(ctx, idx_fd_handler); - duk_dup(ctx, idx_eventloop); - duk_push_int(ctx, pfd->fd); - duk_push_int(ctx, pfd->revents); - rc = duk_pcall_method(ctx, 2 /*nargs*/); - if (rc) { -#if 0 - fprintf(stderr, "fd callback failed for fd %d: %s\n", (int) pfd->fd, duk_to_string(ctx, -1)); - fflush(stderr); -#endif - } - duk_pop(ctx); - - pfd->revents = 0; - } - - } - } - - duk_pop_n(ctx, 3); - - return 0; -} - -static int create_timer(duk_context *ctx) { - double delay; - int oneshot; - int idx; - int64_t timer_id; - double now; - ev_timer *t; - - now = get_now(); - - /* indexes: - * 0 = function (callback) - * 1 = delay - * 2 = boolean: oneshot - */ - - delay = duk_require_number(ctx, 1); - if (delay < MIN_DELAY) { - delay = MIN_DELAY; - } - oneshot = duk_require_boolean(ctx, 2); - - if (timer_count >= MAX_TIMERS) { - duk_error(ctx, DUK_ERR_RANGE_ERROR, "out of timer slots"); - } - idx = timer_count++; - timer_id = timer_next_id++; - t = timer_list + idx; - - memset((void *) t, 0, sizeof(ev_timer)); - t->id = timer_id; - t->target = now + delay; - t->delay = delay; - t->oneshot = oneshot; - t->removed = 0; - - /* Timer is now at the last position; use swaps to "bubble" it to its - * correct sorted position. - */ - - bubble_last_timer(); - - /* Finally, register the callback to the global stash 'eventTimers' object. */ - - duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, "eventTimers"); /* -> [ func delay oneshot stash eventTimers ] */ - duk_push_number(ctx, (double) timer_id); - duk_dup(ctx, 0); - duk_put_prop(ctx, -3); /* eventTimers[timer_id] = callback */ - - /* Return timer id. */ - - duk_push_number(ctx, (double) timer_id); -#if 0 - fprintf(stderr, "created timer id: %d\n", (int) timer_id); - fflush(stderr); -#endif - return 1; -} - -static int delete_timer(duk_context *ctx) { - int i, n; - int64_t timer_id; - ev_timer *t; - int found = 0; - - /* indexes: - * 0 = timer id - */ - - timer_id = (int64_t) duk_require_number(ctx, 0); - - /* - * Unlike insertion, deletion needs a full scan of the timer list - * and an expensive remove. If no match is found, nothing is deleted. - * Caller gets a boolean return code indicating match. - * - * When a timer is being expired and its user callback is running, - * the timer has been moved to 'timer_expiring' and its deletion - * needs special handling: just mark it to-be-deleted and let the - * expiry code remove it. - */ - - t = &timer_expiring; - if (t->id == timer_id) { - t->removed = 1; - duk_push_true(ctx); -#if 0 - fprintf(stderr, "deleted expiring timer id: %d\n", (int) timer_id); - fflush(stderr); -#endif - return 1; - } - - n = timer_count; - for (i = 0; i < n; i++) { - t = timer_list + i; - if (t->id == timer_id) { - found = 1; - - /* Shift elements downwards to keep the timer list dense - * (no need if last element). - */ - if (i < timer_count - 1) { - memmove((void *) t, (void *) (t + 1), (timer_count - i - 1) * sizeof(ev_timer)); - } - - /* Zero last element for clarity. */ - memset((void *) (timer_list + n - 1), 0, sizeof(ev_timer)); - - /* Update timer_count. */ - timer_count--; - - /* The C state is now up-to-date, but we still need to delete - * the timer callback state from the global 'stash'. - */ - - duk_push_global_stash(ctx); - duk_get_prop_string(ctx, -1, "eventTimers"); /* -> [ timer_id stash eventTimers ] */ - duk_push_number(ctx, (double) timer_id); - duk_del_prop(ctx, -2); /* delete eventTimers[timer_id] */ - -#if 0 - fprintf(stderr, "deleted timer id: %d\n", (int) timer_id); - fflush(stderr); -#endif - break; - } - } - -#if 0 - if (!found) { - fprintf(stderr, "trying to delete timer id %d, but not found; ignoring\n", (int) timer_id); - fflush(stderr); - } -#endif - - duk_push_boolean(ctx, found); - return 1; -} - -static int listen_fd(duk_context *ctx) { - int fd = duk_require_int(ctx, 0); - int events = duk_require_int(ctx, 1); - int i, n; - struct pollfd *pfd; - -#if 0 - fprintf(stderr, "listen_fd: fd=%d, events=%d\n", fd, events); - fflush(stderr); -#endif - /* events == 0 means stop listening to the FD */ - - n = poll_count; - for (i = 0; i < n; i++) { - pfd = poll_list + i; - if (pfd->fd == fd) { -#if 0 - fprintf(stderr, "listen_fd: fd found at index %d\n", i); - fflush(stderr); -#endif - if (events == 0) { - /* mark to-be-deleted, cleaned up by next poll */ - pfd->fd = 0; - } else { - pfd->events = events; - } - return 0; - } - } - - /* not found, append to list */ -#if 0 - fprintf(stderr, "listen_fd: fd not found on list, add new entry\n"); - fflush(stderr); -#endif - - if (poll_count >= MAX_FDS) { - duk_error(ctx, DUK_ERR_ERROR, "out of fd slots"); - } - - pfd = poll_list + poll_count; - pfd->fd = fd; - pfd->events = events; - pfd->revents = 0; - poll_count++; - - return 0; -} - -static int request_exit(duk_context *ctx) { - (void) ctx; - exit_requested = 1; - return 0; -} - -static duk_function_list_entry eventloop_funcs[] = { - { "createTimer", create_timer, 3 }, - { "deleteTimer", delete_timer, 1 }, - { "listenFd", listen_fd, 2 }, - { "requestExit", request_exit, 0 }, - { NULL, NULL, 0 } -}; - -void eventloop_register(duk_context *ctx) { - memset((void *) timer_list, 0, MAX_TIMERS * sizeof(ev_timer)); - memset((void *) &timer_expiring, 0, sizeof(ev_timer)); - memset((void *) poll_list, 0, MAX_FDS * sizeof(struct pollfd)); - - /* Set global 'EventLoop'. */ - duk_push_global_object(ctx); - duk_push_object(ctx); - duk_put_function_list(ctx, -1, eventloop_funcs); - duk_put_prop_string(ctx, -2, "EventLoop"); - duk_pop(ctx); - - /* Initialize global stash 'eventTimers'. */ - duk_push_global_stash(ctx); - duk_push_object(ctx); - duk_put_prop_string(ctx, -2, "eventTimers"); - duk_pop(ctx); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.js b/src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.js deleted file mode 100644 index b9e2d633..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.js +++ /dev/null @@ -1,179 +0,0 @@ -/* - * C eventloop example (c_eventloop.c). - * - * Ecmascript code to initialize the exposed API (setTimeout() etc) when - * using the C eventloop. - * - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Timers - */ - -/* - * Timer API - */ - -function setTimeout(func, delay) { - var cb_func; - var bind_args; - var timer_id; - - if (typeof delay !== 'number') { - throw new TypeError('delay is not a number'); - } - - if (typeof func === 'string') { - // Legacy case: callback is a string. - cb_func = eval.bind(this, func); - } else if (typeof func !== 'function') { - throw new TypeError('callback is not a function/string'); - } else if (arguments.length > 2) { - // Special case: callback arguments are provided. - bind_args = Array.prototype.slice.call(arguments, 2); // [ arg1, arg2, ... ] - bind_args.unshift(this); // [ global(this), arg1, arg2, ... ] - cb_func = func.bind.apply(func, bind_args); - } else { - // Normal case: callback given as a function without arguments. - cb_func = func; - } - - timer_id = EventLoop.createTimer(cb_func, delay, true /*oneshot*/); - - return timer_id; -} - -function clearTimeout(timer_id) { - if (typeof timer_id !== 'number') { - throw new TypeError('timer ID is not a number'); - } - var success = EventLoop.deleteTimer(timer_id); /* retval ignored */ -} - -function setInterval(func, delay) { - var cb_func; - var bind_args; - var timer_id; - - if (typeof delay !== 'number') { - throw new TypeError('delay is not a number'); - } - - if (typeof func === 'string') { - // Legacy case: callback is a string. - cb_func = eval.bind(this, func); - } else if (typeof func !== 'function') { - throw new TypeError('callback is not a function/string'); - } else if (arguments.length > 2) { - // Special case: callback arguments are provided. - bind_args = Array.prototype.slice.call(arguments, 2); // [ arg1, arg2, ... ] - bind_args.unshift(this); // [ global(this), arg1, arg2, ... ] - cb_func = func.bind.apply(func, bind_args); - } else { - // Normal case: callback given as a function without arguments. - cb_func = func; - } - - timer_id = EventLoop.createTimer(cb_func, delay, false /*oneshot*/); - - return timer_id; -} - -function clearInterval(timer_id) { - if (typeof timer_id !== 'number') { - throw new TypeError('timer ID is not a number'); - } - EventLoop.deleteTimer(timer_id); -} - -function requestEventLoopExit() { - EventLoop.requestExit(); -} - -/* - * Socket handling - * - * Ideally this would be implemented more in C than here for more speed - * and smaller footprint: C code would directly maintain the callback state - * and such. - * - * Also for more optimal I/O, the buffer churn caused by allocating and - * freeing a lot of buffer values could be eliminated by reusing buffers. - * Socket reads would then go into a pre-allocated buffer, for instance. - */ - -EventLoop.socketListening = {}; -EventLoop.socketReading = {}; -EventLoop.socketConnecting = {}; - -EventLoop.fdPollHandler = function(fd, revents) { - var data; - var cb; - var rc; - var acc_res; - - //print('activity on fd', fd, 'revents', revents); - - if (revents & Poll.POLLIN) { - cb = this.socketReading[fd]; - if (cb) { - data = Socket.read(fd); // no size control now - //print('READ', Duktape.enc('jx', data)); - if (data.length === 0) { - this.close(fd); - return; - } - cb(fd, data); - } else { - cb = this.socketListening[fd]; - if (cb) { - acc_res = Socket.accept(fd); - //print('ACCEPT:', Duktape.enc('jx', acc_res)); - cb(acc_res.fd, acc_res.addr, acc_res.port); - } else { - //print('UNKNOWN'); - } - } - } - - if (revents & Poll.POLLOUT) { - // Connected - cb = this.socketConnecting[fd]; - if (cb) { - delete this.socketConnecting[fd]; - cb(fd); - } - } - - if ((revents & ~(Poll.POLLIN | Poll.POLLOUT)) !== 0) { - //print('unexpected revents, close fd'); - this.close(fd); - } -} - -EventLoop.server = function(address, port, cb_accepted) { - var fd = Socket.createServerSocket(address, port); - this.socketListening[fd] = cb_accepted; - this.listenFd(fd, Poll.POLLIN); -} - -EventLoop.connect = function(address, port, cb_connected) { - var fd = Socket.connect(address, port); - this.socketConnecting[fd] = cb_connected; - this.listenFd(fd, Poll.POLLOUT); -} - -EventLoop.close = function(fd) { - EventLoop.listenFd(fd, 0); - delete this.socketListening[fd]; - delete this.socketReading[fd]; - delete this.socketConnecting[fd]; - Socket.close(fd); -} - -EventLoop.setReader = function(fd, cb_read) { - this.socketReading[fd] = cb_read; - this.listenFd(fd, Poll.POLLIN); -} - -EventLoop.write = function(fd, data) { - // This simple example doesn't have support for write blocking / draining - var rc = Socket.write(fd, Duktape.Buffer(data)); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/client-socket-test.js b/src/third_party/duktape-1.3.0/examples/eventloop/client-socket-test.js deleted file mode 100644 index ff877848..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/client-socket-test.js +++ /dev/null @@ -1,24 +0,0 @@ - -var HOST = 'localhost'; -var PORT = 80; -var EXIT_TIMEOUT = 300e3; - -print('automatic exit after ' + (EXIT_TIMEOUT / 1e3) + ' seconds'); -setTimeout(function () { - print('exit timer'); - EventLoop.requestExit(); -}, EXIT_TIMEOUT); - -EventLoop.connect(HOST, PORT, function (fd) { - print('connected to ' + HOST + ':' + PORT + ', fd', fd); - EventLoop.setReader(fd, function (fd, data) { - print('read from fd', fd); - print(data); - EventLoop.close(fd); - }); - EventLoop.write(fd, "GET / HTTP/1.1\r\n" + - "Host: " + HOST + "\r\n" + - "User-Agent: client-socket-test.js\r\n" + - "\r\n"); -}); - diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/curses-timers.js b/src/third_party/duktape-1.3.0/examples/eventloop/curses-timers.js deleted file mode 100644 index 45086653..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/curses-timers.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Test using timers and intervals with curses. - */ - -if (typeof Ncurses !== 'object') { - throw new Error('Ncurses required'); -} - -function fillScreen(ch) { - var size, w, h; - var i, j; - - size = Ncurses.getmaxyx(); - h = size[0]; - w = size[1]; - - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - Ncurses.mvprintw(i, j, ch); - } - } - Ncurses.refresh(); -} - -function main() { - var i, j; - var counters = []; - var size, w, h; - - Ncurses.initscr(); - size = Ncurses.getmaxyx(); - h = size[0]; - w = size[1]; - - fillScreen('.'); - - setInterval(function () { - Ncurses.mvprintw(1, 4, new Date().toISOString()); - Ncurses.refresh(); - }, 1000); - - function addCounter(row, index, interval) { - counters[index] = 0; - setInterval(function () { - counters[index]++; - Ncurses.mvprintw(row, 4, '' + Date.now() + ' ' + counters[index]); - Ncurses.refresh(); - }, interval); - } - - function addRandomChar(row, col, interval) { - setTimeout(function () { - Ncurses.mvprintw(row, col, String.fromCharCode(Math.random() * 64 + 0x20)); - Ncurses.refresh(); - }, interval); - } - - for (i = 0; i < h - 5; i++) { - addCounter(3 + i, i, 363 * i + 400); - } - - /* Here the inserts take a lot of time because the underlying timer manager - * data structure has O(n) insertion performance. - */ - for (i = 0; i < h - 5; i++) { - for (j = 0; j < w - 50; j++) { - // Math.exp(0)...Math.exp(8) is an uneven distribution between 1...~2980. - addRandomChar(3 + i, 28 + j, 58000 - Math.exp(Math.random() * 8) * 20); - } - } - - setTimeout(function () { - Ncurses.endwin(); - Ncurses.delscreen(); - requestEventLoopExit(); - }, 120e3); -} - -main(); diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/ecma_eventloop.js b/src/third_party/duktape-1.3.0/examples/eventloop/ecma_eventloop.js deleted file mode 100644 index bad4e4d9..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/ecma_eventloop.js +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Pure Ecmascript eventloop example. - * - * Timer state handling is inefficient in this trivial example. Timers are - * kept in an array sorted by their expiry time which works well for expiring - * timers, but has O(n) insertion performance. A better implementation would - * use a heap or some other efficient structure for managing timers so that - * all operations (insert, remove, get nearest timer) have good performance. - * - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Timers - */ - -/* - * Event loop - * - * Timers are sorted by 'target' property which indicates expiry time of - * the timer. The timer expiring next is last in the array, so that - * removals happen at the end, and inserts for timers expiring in the - * near future displace as few elements in the array as possible. - */ - -EventLoop = { - // timers - timers: [], // active timers, sorted (nearest expiry last) - expiring: null, // set to timer being expired (needs special handling in clearTimeout/clearInterval) - nextTimerId: 1, - minimumDelay: 1, - minimumWait: 1, - maximumWait: 60000, - maxExpirys: 10, - - // sockets - socketListening: {}, // fd -> callback - socketReading: {}, // fd -> callback - socketConnecting: {}, // fd -> callback - - // misc - exitRequested: false -}; - -EventLoop.dumpState = function() { - print('TIMER STATE:'); - this.timers.forEach(function(t) { - print(' ' + Duktape.enc('jx', t)); - }); - if (this.expiring) { - print(' EXPIRING: ' + Duktape.enc('jx', this.expiring)); - } -} - -// Get timer with lowest expiry time. Since the active timers list is -// sorted, it's always the last timer. -EventLoop.getEarliestTimer = function() { - var timers = this.timers; - n = timers.length; - return (n > 0 ? timers[n - 1] : null); -} - -EventLoop.getEarliestWait = function() { - var t = this.getEarliestTimer(); - return (t ? t.target - Date.now() : null); -} - -EventLoop.insertTimer = function(timer) { - var timers = this.timers; - var i, n, t; - - /* - * Find 'i' such that we want to insert *after* timers[i] at index i+1. - * If no such timer, for-loop terminates with i-1, and we insert at -1+1=0. - */ - - n = timers.length; - for (i = n - 1; i >= 0; i--) { - t = timers[i]; - if (timer.target <= t.target) { - // insert after 't', to index i+1 - break; - } - } - - timers.splice(i + 1 /*start*/, 0 /*deleteCount*/, timer); -} - -// Remove timer/interval with a timer ID. The timer/interval can reside -// either on the active list or it may be an expired timer (this.expiring) -// whose user callback we're running when this function gets called. -EventLoop.removeTimerById = function(timer_id) { - var timers = this.timers; - var i, n, t; - - t = this.expiring; - if (t) { - if (t.id === timer_id) { - // Timer has expired and we're processing its callback. User - // callback has requested timer deletion. Mark removed, so - // that the timer is not reinserted back into the active list. - // This is actually a common case because an interval may very - // well cancel itself. - t.removed = true; - return; - } - } - - n = timers.length; - for (i = 0; i < n; i++) { - t = timers[i]; - if (t.id === timer_id) { - // Timer on active list: mark removed (not really necessary, but - // nice for dumping), and remove from active list. - t.removed = true; - this.timers.splice(i /*start*/, 1 /*deleteCount*/); - return; - } - } - - // no such ID, ignore -} - -EventLoop.processTimers = function() { - var now = Date.now(); - var timers = this.timers; - var sanity = this.maxExpirys; - var n, t; - - /* - * Here we must be careful with mutations: user callback may add and - * delete an arbitrary number of timers. - * - * Current solution is simple: check whether the timer at the end of - * the list has expired. If not, we're done. If it has expired, - * remove it from the active list, record it in this.expiring, and call - * the user callback. If user code deletes the this.expiring timer, - * there is special handling which just marks the timer deleted so - * it won't get inserted back into the active list. - * - * This process is repeated at most maxExpirys times to ensure we don't - * get stuck forever; user code could in principle add more and more - * already expired timers. - */ - - while (sanity-- > 0) { - // If exit requested, don't call any more callbacks. This allows - // a callback to do cleanups and request exit, and can be sure that - // no more callbacks are processed. - - if (this.exitRequested) { - //print('exit requested, exit'); - break; - } - - // Timers to expire? - - n = timers.length; - if (n <= 0) { - break; - } - t = timers[n - 1]; - if (now <= t.target) { - // Timer has not expired, and no other timer could have expired - // either because the list is sorted. - break; - } - timers.pop(); - - // Remove the timer from the active list and process it. The user - // callback may add new timers which is not a problem. The callback - // may also delete timers which is not a problem unless the timer - // being deleted is the timer whose callback we're running; this is - // why the timer is recorded in this.expiring so that clearTimeout() - // and clearInterval() can detect this situation. - - if (t.oneshot) { - t.removed = true; // flag for removal - } else { - t.target = now + t.delay; - } - this.expiring = t; - try { - t.cb(); - } catch (e) { - print('timer callback failed, ignored: ' + e); - } - this.expiring = null; - - // If the timer was one-shot, it's marked 'removed'. If the user callback - // requested deletion for the timer, it's also marked 'removed'. If the - // timer is an interval (and is not marked removed), insert it back into - // the timer list. - - if (!t.removed) { - // Reinsert interval timer to correct sorted position. The timer - // must be an interval timer because one-shot timers are marked - // 'removed' above. - this.insertTimer(t); - } - } -} - -EventLoop.run = function() { - var wait; - var POLLIN = Poll.POLLIN; - var POLLOUT = Poll.POLLOUT; - var poll_set; - var poll_count; - var fd; - var t, rev; - var rc; - var acc_res; - - for (;;) { - /* - * Process expired timers. - */ - - this.processTimers(); - //this.dumpState(); - - /* - * Exit check (may be requested by a user callback) - */ - - if (this.exitRequested) { - //print('exit requested, exit'); - break; - } - - /* - * Create poll socket list. This is a very naive approach. - * On Linux, one could use e.g. epoll() and manage socket lists - * incrementally. - */ - - poll_set = {}; - poll_count = 0; - for (fd in this.socketListening) { - poll_set[fd] = { events: POLLIN, revents: 0 }; - poll_count++; - } - for (fd in this.socketReading) { - poll_set[fd] = { events: POLLIN, revents: 0 }; - poll_count++; - } - for (fd in this.socketConnecting) { - poll_set[fd] = { events: POLLOUT, revents: 0 }; - poll_count++; - } - //print(new Date(), 'poll_set IN:', Duktape.enc('jx', poll_set)); - - /* - * Wait timeout for timer closest to expiry. Since the poll - * timeout is relative, get this as close to poll() as possible. - */ - - wait = this.getEarliestWait(); - if (wait === null) { - if (poll_count === 0) { - print('no active timers and no sockets to poll, exit'); - break; - } else { - wait = this.maximumWait; - } - } else { - wait = Math.min(this.maximumWait, Math.max(this.minimumWait, wait)); - } - - /* - * Do the actual poll. - */ - - try { - Poll.poll(poll_set, wait); - } catch (e) { - // Eat errors silently. When resizing curses window an EINTR - // happens now. - } - - /* - * Process all sockets so that nothing is left unhandled for the - * next round. - */ - - //print(new Date(), 'poll_set OUT:', Duktape.enc('jx', poll_set)); - for (fd in poll_set) { - t = poll_set[fd]; - rev = t.revents; - - if (rev & POLLIN) { - cb = this.socketReading[fd]; - if (cb) { - data = Socket.read(fd); // no size control now - //print('READ', Duktape.enc('jx', data)); - if (data.length === 0) { - //print('zero read for fd ' + fd + ', closing forcibly'); - rc = Socket.close(fd); // ignore result - delete this.socketListening[fd]; - delete this.socketReading[fd]; - } else { - cb(fd, data); - } - } else { - cb = this.socketListening[fd]; - if (cb) { - acc_res = Socket.accept(fd); - //print('ACCEPT:', Duktape.enc('jx', acc_res)); - cb(acc_res.fd, acc_res.addr, acc_res.port); - } else { - //print('UNKNOWN'); - } - } - } - - if (rev & POLLOUT) { - cb = this.socketConnecting[fd]; - if (cb) { - delete this.socketConnecting[fd]; - cb(fd); - } else { - //print('UNKNOWN POLLOUT'); - } - } - - if ((rev & ~(POLLIN | POLLOUT)) !== 0) { - //print('revents ' + t.revents + ' for fd ' + fd + ', closing forcibly'); - rc = Socket.close(fd); // ignore result - delete this.socketListening[fd]; - delete this.socketReading[fd]; - } - } - } -} - -EventLoop.requestExit = function() { - this.exitRequested = true; -} - -EventLoop.server = function(address, port, cb_accepted) { - var fd = Socket.createServerSocket(address, port); - this.socketListening[fd] = cb_accepted; -} - -EventLoop.connect = function(address, port, cb_connected) { - var fd = Socket.connect(address, port); - this.socketConnecting[fd] = cb_connected; -} - -EventLoop.close = function(fd) { - delete this.socketReading[fd]; - delete this.socketListening[fd]; -} - -EventLoop.setReader = function(fd, cb_read) { - this.socketReading[fd] = cb_read; -} - -EventLoop.write = function(fd, data) { - // This simple example doesn't have support for write blocking / draining - var rc = Socket.write(fd, Duktape.Buffer(data)); -} - -/* - * Timer API - * - * These interface with the singleton EventLoop. - */ - -function setTimeout(func, delay) { - var cb_func; - var bind_args; - var timer_id; - var evloop = EventLoop; - - if (typeof delay !== 'number') { - throw new TypeError('delay is not a number'); - } - delay = Math.max(evloop.minimumDelay, delay); - - if (typeof func === 'string') { - // Legacy case: callback is a string. - cb_func = eval.bind(this, func); - } else if (typeof func !== 'function') { - throw new TypeError('callback is not a function/string'); - } else if (arguments.length > 2) { - // Special case: callback arguments are provided. - bind_args = Array.prototype.slice.call(arguments, 2); // [ arg1, arg2, ... ] - bind_args.unshift(this); // [ global(this), arg1, arg2, ... ] - cb_func = func.bind.apply(func, bind_args); - } else { - // Normal case: callback given as a function without arguments. - cb_func = func; - } - - timer_id = evloop.nextTimerId++; - - evloop.insertTimer({ - id: timer_id, - oneshot: true, - cb: cb_func, - delay: delay, - target: Date.now() + delay - }); - - return timer_id; -} - -function clearTimeout(timer_id) { - var evloop = EventLoop; - - if (typeof timer_id !== 'number') { - throw new TypeError('timer ID is not a number'); - } - evloop.removeTimerById(timer_id); -} - -function setInterval(func, delay) { - var cb_func; - var bind_args; - var timer_id; - var evloop = EventLoop; - - if (typeof delay !== 'number') { - throw new TypeError('delay is not a number'); - } - delay = Math.max(evloop.minimumDelay, delay); - - if (typeof func === 'string') { - // Legacy case: callback is a string. - cb_func = eval.bind(this, func); - } else if (typeof func !== 'function') { - throw new TypeError('callback is not a function/string'); - } else if (arguments.length > 2) { - // Special case: callback arguments are provided. - bind_args = Array.prototype.slice.call(arguments, 2); // [ arg1, arg2, ... ] - bind_args.unshift(this); // [ global(this), arg1, arg2, ... ] - cb_func = func.bind.apply(func, bind_args); - } else { - // Normal case: callback given as a function without arguments. - cb_func = func; - } - - timer_id = evloop.nextTimerId++; - - evloop.insertTimer({ - id: timer_id, - oneshot: false, - cb: cb_func, - delay: delay, - target: Date.now() + delay - }); - - return timer_id; -} - -function clearInterval(timer_id) { - var evloop = EventLoop; - - if (typeof timer_id !== 'number') { - throw new TypeError('timer ID is not a number'); - } - evloop.removeTimerById(timer_id); -} - -/* custom call */ -function requestEventLoopExit() { - EventLoop.requestExit(); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/fileio.c b/src/third_party/duktape-1.3.0/examples/eventloop/fileio.c deleted file mode 100644 index df94cd43..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/fileio.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * File I/O binding example. - */ - -#include -#include -#include - -#include "duktape.h" - -static int fileio_readfile(duk_context *ctx) { - const char *filename = duk_to_string(ctx, 0); - FILE *f = NULL; - long len; - void *buf; - size_t got; - - if (!filename) { - goto error; - } - - f = fopen(filename, "rb"); - if (!f) { - goto error; - } - - if (fseek(f, 0, SEEK_END) != 0) { - goto error; - } - - len = ftell(f); - - if (fseek(f, 0, SEEK_SET) != 0) { - goto error; - } - - buf = duk_push_fixed_buffer(ctx, (size_t) len); - - got = fread(buf, 1, len, f); - if (got != (size_t) len) { - goto error; - } - - fclose(f); - f = NULL; - - return 1; - - error: - if (f) { - fclose(f); - } - - return DUK_RET_ERROR; -} - -static duk_function_list_entry fileio_funcs[] = { - { "readfile", fileio_readfile, 1 }, - { NULL, NULL, 0 } -}; - -void fileio_register(duk_context *ctx) { - /* Set global 'FileIo'. */ - duk_push_global_object(ctx); - duk_push_object(ctx); - duk_put_function_list(ctx, -1, fileio_funcs); - duk_put_prop_string(ctx, -2, "FileIo"); - duk_pop(ctx); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/main.c b/src/third_party/duktape-1.3.0/examples/eventloop/main.c deleted file mode 100644 index 76279218..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/main.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Main for evloop command line tool. - * - * Runs a given script from file or stdin inside an eventloop. The - * script can then access setTimeout() etc. - */ - -#include -#include -#include -#ifndef NO_SIGNAL -#include -#endif - -#include "duktape.h" - -extern void poll_register(duk_context *ctx); -extern void ncurses_register(duk_context *ctx); -extern void socket_register(duk_context *ctx); -extern void fileio_register(duk_context *ctx); -extern void eventloop_register(duk_context *ctx); -extern int eventloop_run(duk_context *ctx); /* Duktape/C function, safe called */ - -static int c_evloop = 0; - -#ifndef NO_SIGNAL -static void my_sighandler(int x) { - fprintf(stderr, "Got signal %d\n", x); - fflush(stderr); -} -static void set_sigint_handler(void) { - (void) signal(SIGINT, my_sighandler); -} -#endif /* NO_SIGNAL */ - -/* Print error to stderr and pop error. */ -static void print_error(duk_context *ctx, FILE *f) { - if (duk_is_object(ctx, -1) && duk_has_prop_string(ctx, -1, "stack")) { - /* XXX: print error objects specially */ - /* XXX: pcall the string coercion */ - duk_get_prop_string(ctx, -1, "stack"); - if (duk_is_string(ctx, -1)) { - fprintf(f, "%s\n", duk_get_string(ctx, -1)); - fflush(f); - duk_pop_2(ctx); - return; - } else { - duk_pop(ctx); - } - } - duk_to_string(ctx, -1); - fprintf(f, "%s\n", duk_get_string(ctx, -1)); - fflush(f); - duk_pop(ctx); -} - -int wrapped_compile_execute(duk_context *ctx) { - int comp_flags = 0; - int rc; - - /* Compile input and place it into global _USERCODE */ - duk_compile(ctx, comp_flags); - duk_push_global_object(ctx); - duk_insert(ctx, -2); /* [ ... global func ] */ - duk_put_prop_string(ctx, -2, "_USERCODE"); - duk_pop(ctx); -#if 0 - printf("compiled usercode\n"); -#endif - - /* Start a zero timer which will call _USERCODE from within - * the event loop. - */ - fprintf(stderr, "set _USERCODE timer\n"); - fflush(stderr); - duk_eval_string(ctx, "setTimeout(function() { _USERCODE(); }, 0);"); - duk_pop(ctx); - - /* Finally, launch eventloop. This call only returns after the - * eventloop terminates. - */ - if (c_evloop) { - fprintf(stderr, "calling eventloop_run()\n"); - fflush(stderr); - rc = duk_safe_call(ctx, eventloop_run, 0 /*nargs*/, 1 /*nrets*/); - if (rc != 0) { - fprintf(stderr, "eventloop_run() failed: %s\n", duk_to_string(ctx, -1)); - fflush(stderr); - } - duk_pop(ctx); - } else { - fprintf(stderr, "calling EventLoop.run()\n"); - fflush(stderr); - duk_eval_string(ctx, "EventLoop.run();"); - duk_pop(ctx); - } - - return 0; -} - -int handle_fh(duk_context *ctx, FILE *f, const char *filename) { - char *buf = NULL; - int len; - int got; - int rc; - int retval = -1; - - if (fseek(f, 0, SEEK_END) < 0) { - goto error; - } - len = (int) ftell(f); - if (fseek(f, 0, SEEK_SET) < 0) { - goto error; - } - buf = (char *) malloc(len); - if (!buf) { - goto error; - } - - got = fread((void *) buf, (size_t) 1, (size_t) len, f); - - duk_push_lstring(ctx, buf, got); - duk_push_string(ctx, filename); - - free(buf); - buf = NULL; - - rc = duk_safe_call(ctx, wrapped_compile_execute, 2 /*nargs*/, 1 /*nret*/); - if (rc != DUK_EXEC_SUCCESS) { - print_error(ctx, stderr); - goto error; - } else { - duk_pop(ctx); - retval = 0; - } - /* fall thru */ - - error: - if (buf) { - free(buf); - } - return retval; -} - -int handle_file(duk_context *ctx, const char *filename) { - FILE *f = NULL; - int retval; - - f = fopen(filename, "rb"); - if (!f) { - fprintf(stderr, "failed to open source file: %s\n", filename); - fflush(stderr); - goto error; - } - - retval = handle_fh(ctx, f, filename); - - fclose(f); - return retval; - - error: - return -1; -} - -int handle_stdin(duk_context *ctx) { - int retval; - - retval = handle_fh(ctx, stdin, "stdin"); - - return retval; -} - -int main(int argc, char *argv[]) { - duk_context *ctx = NULL; - int retval = 0; - const char *filename = NULL; - int i; - -#ifndef NO_SIGNAL - set_sigint_handler(); - - /* This is useful at the global level; libraries should avoid SIGPIPE though */ - /*signal(SIGPIPE, SIG_IGN);*/ -#endif - - for (i = 1; i < argc; i++) { - char *arg = argv[i]; - if (!arg) { - goto usage; - } - if (strcmp(arg, "-c") == 0) { - c_evloop = 1; - } else if (strlen(arg) > 1 && arg[0] == '-') { - goto usage; - } else { - if (filename) { - goto usage; - } - filename = arg; - } - } - if (!filename) { - goto usage; - } - - ctx = duk_create_heap_default(); - - poll_register(ctx); - ncurses_register(ctx); - socket_register(ctx); - fileio_register(ctx); - - if (c_evloop) { - fprintf(stderr, "Using C based eventloop (omit -c to use Ecmascript based eventloop)\n"); - fflush(stderr); - - eventloop_register(ctx); - duk_eval_file(ctx, "c_eventloop.js"); - } else { - fprintf(stderr, "Using Ecmascript based eventloop (give -c to use C based eventloop)\n"); - fflush(stderr); - - duk_eval_file(ctx, "ecma_eventloop.js"); - } - - fprintf(stderr, "Executing code from: '%s'\n", filename); - fflush(stderr); - - if (strcmp(filename, "-") == 0) { - if (handle_stdin(ctx) != 0) { - retval = 1; - goto cleanup; - } - } else { - if (handle_file(ctx, filename) != 0) { - retval = 1; - goto cleanup; - } - } - - cleanup: - if (ctx) { - duk_destroy_heap(ctx); - } - - return retval; - - usage: - fprintf(stderr, "Usage: evloop [-c] \n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Uses an Ecmascript based eventloop (ecma_eventloop.js) by default.\n"); - fprintf(stderr, "If -c option given, uses a C based eventloop (c_eventloop.{c,js}).\n"); - fprintf(stderr, "If is '-', the entire STDIN executed.\n"); - fflush(stderr); - exit(1); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/ncurses.c b/src/third_party/duktape-1.3.0/examples/eventloop/ncurses.c deleted file mode 100644 index 7734fcc9..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/ncurses.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Ncurses bindings example. - * - * VALGRIND NOTE: when you use ncurses, there seems to be no way to get a - * clean valgrind run. Even if ncurses state is properly shut down, there - * will still be some residual leaks. - * - * Debian: install libncurses5-dev - */ - -#include -#include "duktape.h" - -static int ncurses_initscr(duk_context *ctx) { - WINDOW *win; - - win = initscr(); - duk_push_pointer(ctx, (void *) win); - return 1; -} - -static int ncurses_endwin(duk_context *ctx) { - int rc; - - rc = endwin(); - duk_push_int(ctx, rc); - return 1; -} - -static int ncurses_delscreen(duk_context *ctx) { - /* XXX: no screen management now */ - (void) ctx; - return 0; -} - -static int ncurses_getmaxyx(duk_context *ctx) { - int row, col; - - getmaxyx(stdscr, row, col); - - duk_push_array(ctx); - duk_push_int(ctx, row); - duk_put_prop_index(ctx, -2, 0); - duk_push_int(ctx, col); - duk_put_prop_index(ctx, -2, 1); - return 1; -} - -static int ncurses_printw(duk_context *ctx) { - int rc; - const char *str; - - str = duk_to_string(ctx, 0); - rc = printw("%s", str); - duk_push_int(ctx, rc); - return 1; -} - -static int ncurses_mvprintw(duk_context *ctx) { - int y = duk_to_int(ctx, 0); - int x = duk_to_int(ctx, 1); - const char *str = duk_to_string(ctx, 2); - int rc; - - rc = mvprintw(y, x, "%s", str); - duk_push_int(ctx, rc); - return 1; -} - -static int ncurses_refresh(duk_context *ctx) { - int rc; - - rc = refresh(); - duk_push_int(ctx, rc); - return 1; -} - -static int ncurses_getch(duk_context *ctx) { - int rc; - - rc = getch(); - duk_push_int(ctx, rc); - return 1; -} - -static duk_function_list_entry ncurses_funcs[] = { - { "initscr", ncurses_initscr, 0 }, - { "endwin", ncurses_endwin, 0 }, - { "delscreen", ncurses_delscreen, 0 }, - { "getmaxyx", ncurses_getmaxyx, 0 }, - { "printw", ncurses_printw, 1 }, - { "mvprintw", ncurses_mvprintw, 3 }, - { "refresh", ncurses_refresh, 0 }, - { "getch", ncurses_getch, 0 }, - { NULL, NULL, 0 } -}; - -void ncurses_register(duk_context *ctx) { - /* Set global 'Ncurses'. */ - duk_push_global_object(ctx); - duk_push_object(ctx); - duk_put_function_list(ctx, -1, ncurses_funcs); - duk_put_prop_string(ctx, -2, "Ncurses"); - duk_pop(ctx); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/poll.c b/src/third_party/duktape-1.3.0/examples/eventloop/poll.c deleted file mode 100644 index c78745d2..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/poll.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * C wrapper for poll(). - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -#include "duktape.h" - -static int poll_poll(duk_context *ctx) { - int timeout = duk_to_int(ctx, 1); - int i, n, nchanged; - int fd, rc; - struct pollfd fds[20]; - struct timespec ts; - - memset(fds, 0, sizeof(fds)); - - n = 0; - duk_enum(ctx, 0, 0 /*enum_flags*/); - while (duk_next(ctx, -1, 0)) { - if ((size_t) n >= sizeof(fds) / sizeof(struct pollfd)) { - return -1; - } - - /* [... enum key] */ - duk_dup_top(ctx); /* -> [... enum key key] */ - duk_get_prop(ctx, 0); /* -> [... enum key val] */ - fd = duk_to_int(ctx, -2); - - duk_push_string(ctx, "events"); - duk_get_prop(ctx, -2); /* -> [... enum key val events] */ - - fds[n].fd = fd; - fds[n].events = duk_to_int(ctx, -1); - fds[n].revents = 0; - - duk_pop_n(ctx, 3); /* -> [... enum] */ - - n++; - } - /* leave enum on stack */ - - memset(&ts, 0, sizeof(ts)); - ts.tv_nsec = (timeout % 1000) * 1000000; - ts.tv_sec = timeout / 1000; - - /*rc = ppoll(fds, n, &ts, NULL);*/ - rc = poll(fds, n, timeout); - if (rc < 0) { - duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), errno); - } - - duk_push_array(ctx); - nchanged = 0; - for (i = 0; i < n; i++) { - /* update revents */ - - if (fds[i].revents) { - duk_push_int(ctx, fds[i].fd); /* -> [... retarr fd] */ - duk_put_prop_index(ctx, -2, nchanged); - nchanged++; - } - - duk_push_int(ctx, fds[i].fd); /* -> [... retarr key] */ - duk_get_prop(ctx, 0); /* -> [... retarr val] */ - duk_push_string(ctx, "revents"); - duk_push_int(ctx, fds[i].revents); /* -> [... retarr val "revents" fds[i].revents] */ - duk_put_prop(ctx, -3); /* -> [... retarr val] */ - duk_pop(ctx); - } - - /* [retarr] */ - - return 1; -} - -static duk_function_list_entry poll_funcs[] = { - { "poll", poll_poll, 2 }, - { NULL, NULL, 0 } -}; - -static duk_number_list_entry poll_consts[] = { - { "POLLIN", (double) POLLIN }, - { "POLLPRI", (double) POLLPRI }, - { "POLLOUT", (double) POLLOUT }, -#if 0 - /* Linux 2.6.17 and upwards, requires _GNU_SOURCE etc, not added - * now because we don't use it. - */ - { "POLLRDHUP", (double) POLLRDHUP }, -#endif - { "POLLERR", (double) POLLERR }, - { "POLLHUP", (double) POLLHUP }, - { "POLLNVAL", (double) POLLNVAL }, - { NULL, 0.0 } -}; - -void poll_register(duk_context *ctx) { - /* Set global 'Poll' with functions and constants. */ - duk_push_global_object(ctx); - duk_push_object(ctx); - duk_put_function_list(ctx, -1, poll_funcs); - duk_put_number_list(ctx, -1, poll_consts); - duk_put_prop_string(ctx, -2, "Poll"); - duk_pop(ctx); -} diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/server-socket-test.js b/src/third_party/duktape-1.3.0/examples/eventloop/server-socket-test.js deleted file mode 100644 index 68510af0..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/server-socket-test.js +++ /dev/null @@ -1,34 +0,0 @@ - -var HOST = 'localhost' -var PORT = 12345; -var EXIT_TIMEOUT = 300e3; - -print('automatic exit after ' + (EXIT_TIMEOUT / 1e3) + ' seconds'); -setTimeout(function () { - print('exit timer'); - EventLoop.requestExit(); -}, EXIT_TIMEOUT); - -print('listen on ' + HOST + ':' + PORT); -EventLoop.server(HOST, PORT, function (fd, addr, port) { - print('new connection on fd ' + fd + ' from ' + addr + ':' + port); - EventLoop.setReader(fd, function (fd, data) { - var b, i, n, x; - - // Handle socket data carefully: if you convert it to a string, - // it may not be valid UTF-8 etc. Here we operate on the data - // directly in the buffer. - - b = data.valueOf(); // ensure we get a plain buffer - n = b.length; - for (i = 0; i < n; i++) { - x = b[i]; - if (x >= 0x61 && x <= 0x7a) { - b[i] = x - 0x20; // uppercase - } - } - - print('read data on fd ' + fd + ', length ' + data.length); - EventLoop.write(fd, data); - }); -}); diff --git a/src/third_party/duktape-1.3.0/examples/eventloop/socket.c b/src/third_party/duktape-1.3.0/examples/eventloop/socket.c deleted file mode 100644 index a1587fa3..00000000 --- a/src/third_party/duktape-1.3.0/examples/eventloop/socket.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * TCP sockets binding example. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "duktape.h" - -#define ERROR_FROM_ERRNO(ctx) do { \ - duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), errno); \ - } while (0) - -static void set_nonblocking(duk_context *ctx, int fd) { - int rc; - int flags; - - rc = fcntl(fd, F_GETFL); - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } - flags = rc; - - flags |= O_NONBLOCK; - - rc = fcntl(fd, F_SETFL, flags); - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } -} - -static void set_reuseaddr(duk_context *ctx, int fd) { - int val; - int rc; - - val = 1; - rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &val, sizeof(val)); - if (rc != 0) { - ERROR_FROM_ERRNO(ctx); - } -} - -#ifdef __APPLE__ -static void set_nosigpipe(duk_context *ctx, int fd) { - int val; - int rc; - - val = 1; - rc = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const void *) &val, sizeof(val)); - if (rc != 0) { - ERROR_FROM_ERRNO(ctx); - } -} -#endif - -static int socket_create_server_socket(duk_context *ctx) { - const char *addr = duk_to_string(ctx, 0); - int port = duk_to_int(ctx, 1); - int sock; - struct sockaddr_in sockaddr; - struct hostent *ent; - struct in_addr **addr_list; - struct in_addr *addr_inet; - int i; - int rc; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - ERROR_FROM_ERRNO(ctx); - } - - set_nonblocking(ctx, sock); - set_reuseaddr(ctx, sock); -#ifdef __APPLE__ - set_nosigpipe(ctx, sock); -#endif - - ent = gethostbyname(addr); - if (!ent) { - ERROR_FROM_ERRNO(ctx); - } - - addr_list = (struct in_addr **) ent->h_addr_list; - addr_inet = NULL; - for (i = 0; addr_list[i]; i++) { - addr_inet = addr_list[i]; - break; - } - if (!addr_inet) { - duk_error(ctx, DUK_ERR_ERROR, "cannot resolve %s", addr); - } - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_port = htons(port); - sockaddr.sin_addr = *addr_inet; - - rc = bind(sock, (const struct sockaddr *) &sockaddr, sizeof(sockaddr)); - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } - - rc = listen(sock, 10 /*backlog*/); - if (rc < 0) { - (void) close(sock); - ERROR_FROM_ERRNO(ctx); - } - - duk_push_int(ctx, sock); - return 1; -} - -static int socket_close(duk_context *ctx) { - int sock = duk_to_int(ctx, 0); - int rc; - - rc = close(sock); - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } - return 0; -} - -static int socket_accept(duk_context *ctx) { - int sock = duk_to_int(ctx, 0); - int rc; - struct sockaddr_in addr; - socklen_t addrlen; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addrlen = sizeof(addr); - - rc = accept(sock, (struct sockaddr *) &addr, &addrlen); - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } - - set_nonblocking(ctx, sock); -#ifdef __APPLE__ - set_nosigpipe(ctx, sock); -#endif - - if (addrlen == sizeof(addr)) { - uint32_t tmp = ntohl(addr.sin_addr.s_addr); - - duk_push_object(ctx); - - duk_push_string(ctx, "fd"); - duk_push_int(ctx, rc); - duk_put_prop(ctx, -3); - duk_push_string(ctx, "addr"); - duk_push_sprintf(ctx, "%d.%d.%d.%d", ((tmp >> 24) & 0xff), ((tmp >> 16) & 0xff), ((tmp >> 8) & 0xff), (tmp & 0xff)); - duk_put_prop(ctx, -3); - duk_push_string(ctx, "port"); - duk_push_int(ctx, ntohs(addr.sin_port)); - duk_put_prop(ctx, -3); - - return 1; - } - - return 0; -} - -static int socket_connect(duk_context *ctx) { - const char *addr = duk_to_string(ctx, 0); - int port = duk_to_int(ctx, 1); - int sock; - struct sockaddr_in sockaddr; - struct hostent *ent; - struct in_addr **addr_list; - struct in_addr *addr_inet; - int i; - int rc; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - ERROR_FROM_ERRNO(ctx); - } - - set_nonblocking(ctx, sock); -#ifdef __APPLE__ - set_nosigpipe(ctx, sock); -#endif - - ent = gethostbyname(addr); - if (!ent) { - ERROR_FROM_ERRNO(ctx); - } - - addr_list = (struct in_addr **) ent->h_addr_list; - addr_inet = NULL; - for (i = 0; addr_list[i]; i++) { - addr_inet = addr_list[i]; - break; - } - if (!addr_inet) { - duk_error(ctx, DUK_ERR_ERROR, "cannot resolve %s", addr); - } - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_port = htons(port); - sockaddr.sin_addr = *addr_inet; - - rc = connect(sock, (const struct sockaddr *) &sockaddr, (socklen_t) sizeof(sockaddr)); - if (rc < 0) { - if (errno == EINPROGRESS) { -#if 0 - fprintf(stderr, "connect() returned EINPROGRESS as expected, need to poll writability\n"); - fflush(stderr); -#endif - } else { - ERROR_FROM_ERRNO(ctx); - } - } - - duk_push_int(ctx, sock); - return 1; -} - -static int socket_read(duk_context *ctx) { - int sock = duk_to_int(ctx, 0); - char readbuf[1024]; - int rc; - void *data; - - rc = recvfrom(sock, (void *) readbuf, sizeof(readbuf), 0, NULL, NULL); - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } - - data = duk_push_fixed_buffer(ctx, rc); - memcpy(data, readbuf, rc); - return 1; -} - -static int socket_write(duk_context *ctx) { - int sock = duk_to_int(ctx, 0); - const char *data; - size_t len; - ssize_t rc; - - data = duk_to_buffer(ctx, 1, &len); - - /* MSG_NOSIGNAL: avoid SIGPIPE */ -#ifdef __APPLE__ - rc = sendto(sock, (void *) data, len, 0, NULL, 0); -#else - rc = sendto(sock, (void *) data, len, MSG_NOSIGNAL, NULL, 0); -#endif - if (rc < 0) { - ERROR_FROM_ERRNO(ctx); - } - - duk_push_int(ctx, rc); - return 1; -} - -static duk_function_list_entry socket_funcs[] = { - { "createServerSocket", socket_create_server_socket, 2 }, - { "close", socket_close, 1 }, - { "accept", socket_accept, 1 }, - { "connect", socket_connect, 2 }, - { "read", socket_read, 1 }, - { "write", socket_write, 2 }, - { NULL, NULL, 0 } -}; - -void socket_register(duk_context *ctx) { - /* Set global 'Socket'. */ - duk_push_global_object(ctx); - duk_push_object(ctx); - duk_put_function_list(ctx, -1, socket_funcs); - duk_put_prop_string(ctx, -2, "Socket"); - duk_pop(ctx); -} diff --git a/src/third_party/duktape-1.3.0/examples/guide/README.rst b/src/third_party/duktape-1.3.0/examples/guide/README.rst deleted file mode 100644 index 1933094f..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -=========================== -Duktape guide example files -=========================== - -Examples used in the Duktape guide. diff --git a/src/third_party/duktape-1.3.0/examples/guide/fib.js b/src/third_party/duktape-1.3.0/examples/guide/fib.js deleted file mode 100644 index 2b2982f7..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/fib.js +++ /dev/null @@ -1,16 +0,0 @@ -// fib.js -function fib(n) { - if (n == 0) { return 0; } - if (n == 1) { return 1; } - return fib(n-1) + fib(n-2); -} - -function test() { - var res = []; - for (i = 0; i < 20; i++) { - res.push(fib(i)); - } - print(res.join(' ')); -} - -test(); diff --git a/src/third_party/duktape-1.3.0/examples/guide/prime.js b/src/third_party/duktape-1.3.0/examples/guide/prime.js deleted file mode 100644 index 8959754f..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/prime.js +++ /dev/null @@ -1,32 +0,0 @@ -// prime.js - -// Pure Ecmascript version of low level helper -function primeCheckEcmascript(val, limit) { - for (var i = 2; i <= limit; i++) { - if ((val % i) == 0) { return false; } - } - return true; -} - -// Select available helper at load time -var primeCheckHelper = (this.primeCheckNative || primeCheckEcmascript); - -// Check 'val' for primality -function primeCheck(val) { - if (val == 1 || val == 2) { return true; } - var limit = Math.ceil(Math.sqrt(val)); - while (limit * limit < val) { limit += 1; } - return primeCheckHelper(val, limit); -} - -// Find primes below one million ending in '9999'. -function primeTest() { - var res = []; - - print('Have native helper: ' + (primeCheckHelper !== primeCheckEcmascript)); - for (var i = 1; i < 1000000; i++) { - if (primeCheck(i) && (i % 10000) == 9999) { res.push(i); } - } - print(res.join(' ')); -} - diff --git a/src/third_party/duktape-1.3.0/examples/guide/primecheck.c b/src/third_party/duktape-1.3.0/examples/guide/primecheck.c deleted file mode 100644 index 36fa5d65..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/primecheck.c +++ /dev/null @@ -1,52 +0,0 @@ -/* primecheck.c */ -#include -#include -#include -#include "duktape.h" - -static duk_ret_t native_prime_check(duk_context *ctx) { - int val = duk_require_int(ctx, 0); - int lim = duk_require_int(ctx, 1); - int i; - - for (i = 2; i <= lim; i++) { - if (val % i == 0) { - duk_push_false(ctx); - return 1; - } - } - - duk_push_true(ctx); - return 1; -} - -int main(int argc, const char *argv[]) { - duk_context *ctx = NULL; - - ctx = duk_create_heap_default(); - if (!ctx) { - printf("Failed to create a Duktape heap.\n"); - exit(1); - } - - duk_push_global_object(ctx); - duk_push_c_function(ctx, native_prime_check, 2 /*nargs*/); - duk_put_prop_string(ctx, -2, "primeCheckNative"); - - if (duk_peval_file(ctx, "prime.js") != 0) { - printf("Error: %s\n", duk_safe_to_string(ctx, -1)); - goto finished; - } - duk_pop(ctx); /* ignore result */ - - duk_get_prop_string(ctx, -1, "primeTest"); - if (duk_pcall(ctx, 0) != 0) { - printf("Error: %s\n", duk_safe_to_string(ctx, -1)); - } - duk_pop(ctx); /* ignore result */ - - finished: - duk_destroy_heap(ctx); - - exit(0); -} diff --git a/src/third_party/duktape-1.3.0/examples/guide/process.js b/src/third_party/duktape-1.3.0/examples/guide/process.js deleted file mode 100644 index 62b50117..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/process.js +++ /dev/null @@ -1,12 +0,0 @@ -// process.js -function processLine(line) { - return line.trim() - .replace(/[<>&"'\u0000-\u001F\u007E-\uFFFF]/g, function(x) { - // escape HTML characters - return '&#' + x.charCodeAt(0) + ';' - }) - .replace(/\*(.*?)\*/g, function(x, m) { - // automatically bold text between stars - return '' + m + ''; - }); -} diff --git a/src/third_party/duktape-1.3.0/examples/guide/processlines.c b/src/third_party/duktape-1.3.0/examples/guide/processlines.c deleted file mode 100644 index f91bdffc..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/processlines.c +++ /dev/null @@ -1,59 +0,0 @@ -/* processlines.c */ -#include -#include -#include -#include "duktape.h" - -int main(int argc, const char *argv[]) { - duk_context *ctx = NULL; - char line[4096]; - char idx; - int ch; - - ctx = duk_create_heap_default(); - if (!ctx) { - printf("Failed to create a Duktape heap.\n"); - exit(1); - } - - if (duk_peval_file(ctx, "process.js") != 0) { - printf("Error: %s\n", duk_safe_to_string(ctx, -1)); - goto finished; - } - duk_pop(ctx); /* ignore result */ - - memset(line, 0, sizeof(line)); - idx = 0; - for (;;) { - if (idx >= sizeof(line)) { - printf("Line too long\n"); - exit(1); - } - - ch = fgetc(stdin); - if (ch == 0x0a) { - line[idx++] = '\0'; - - duk_push_global_object(ctx); - duk_get_prop_string(ctx, -1 /*index*/, "processLine"); - duk_push_string(ctx, line); - if (duk_pcall(ctx, 1 /*nargs*/) != 0) { - printf("Error: %s\n", duk_safe_to_string(ctx, -1)); - } else { - printf("%s\n", duk_safe_to_string(ctx, -1)); - } - duk_pop(ctx); /* pop result/error */ - - idx = 0; - } else if (ch == EOF) { - break; - } else { - line[idx++] = (char) ch; - } - } - - finished: - duk_destroy_heap(ctx); - - exit(0); -} diff --git a/src/third_party/duktape-1.3.0/examples/guide/uppercase.c b/src/third_party/duktape-1.3.0/examples/guide/uppercase.c deleted file mode 100644 index 03d08698..00000000 --- a/src/third_party/duktape-1.3.0/examples/guide/uppercase.c +++ /dev/null @@ -1,42 +0,0 @@ -/* uppercase.c */ -#include -#include -#include "duktape.h" - -static int dummy_upper_case(duk_context *ctx) { - size_t sz; - const char *val = duk_require_lstring(ctx, 0, &sz); - size_t i; - - /* We're going to need 'sz' additional entries on the stack. */ - duk_require_stack(ctx, sz); - - for (i = 0; i < sz; i++) { - char ch = val[i]; - if (ch >= 'a' && ch <= 'z') { - ch = ch - 'a' + 'A'; - } - duk_push_lstring(ctx, (const char *) &ch, 1); - } - - duk_concat(ctx, sz); - return 1; -} - -int main(int argc, char *argv[]) { - duk_context *ctx; - - if (argc < 2) { exit(1); } - - ctx = duk_create_heap_default(); - if (!ctx) { exit(1); } - - duk_push_c_function(ctx, dummy_upper_case, 1); - duk_push_string(ctx, argv[1]); - duk_call(ctx, 1); - printf("%s -> %s\n", argv[1], duk_to_string(ctx, -1)); - duk_pop(ctx); - - duk_destroy_heap(ctx); - return 0; -} diff --git a/src/third_party/duktape-1.3.0/examples/hello/README.rst b/src/third_party/duktape-1.3.0/examples/hello/README.rst deleted file mode 100644 index 7afef53e..00000000 --- a/src/third_party/duktape-1.3.0/examples/hello/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -=================== -Hello world example -=================== - -Very simple example, most useful for compilation tests. diff --git a/src/third_party/duktape-1.3.0/examples/hello/hello.c b/src/third_party/duktape-1.3.0/examples/hello/hello.c deleted file mode 100644 index 9113d2fb..00000000 --- a/src/third_party/duktape-1.3.0/examples/hello/hello.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Very simple example program - */ - -#include "duktape.h" - -int adder(duk_context *ctx) { - int i; - int n = duk_get_top(ctx); /* #args */ - double res = 0.0; - - for (i = 0; i < n; i++) { - res += duk_to_number(ctx, i); - } - - duk_push_number(ctx, res); - return 1; /* one return value */ -} - -int main(int argc, char *argv[]) { - duk_context *ctx = duk_create_heap_default(); - - (void) argc; (void) argv; /* suppress warning */ - - duk_eval_string(ctx, "print('Hello world!');"); - - duk_push_global_object(ctx); - duk_push_c_function(ctx, adder, DUK_VARARGS); - duk_put_prop_string(ctx, -2, "adder"); - duk_pop(ctx); /* pop global */ - - duk_eval_string(ctx, "print('2+3=' + adder(2, 3));"); - duk_pop(ctx); /* pop eval result */ - - duk_destroy_heap(ctx); - - return 0; -} diff --git a/src/third_party/duktape-1.3.0/examples/jxpretty/README.rst b/src/third_party/duktape-1.3.0/examples/jxpretty/README.rst deleted file mode 100644 index 5ab43a84..00000000 --- a/src/third_party/duktape-1.3.0/examples/jxpretty/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -================ -Jxpretty example -================ - -Simple command line utility to pretty print JSON in the JX format. diff --git a/src/third_party/duktape-1.3.0/examples/jxpretty/jxpretty.c b/src/third_party/duktape-1.3.0/examples/jxpretty/jxpretty.c deleted file mode 100644 index 1e483efb..00000000 --- a/src/third_party/duktape-1.3.0/examples/jxpretty/jxpretty.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Pretty print JSON from stdin into indented JX. - */ - -#include -#include -#include "duktape.h" - -static duk_ret_t do_jxpretty(duk_context *ctx) { - FILE *f = stdin; - char buf[4096]; - size_t ret; - - for (;;) { - if (ferror(f)) { - duk_error(ctx, DUK_ERR_ERROR, "ferror() on stdin"); - } - if (feof(f)) { - break; - } - - ret = fread(buf, 1, sizeof(buf), f); -#if 0 - fprintf(stderr, "Read: %ld\n", (long) ret); - fflush(stderr); -#endif - if (ret == 0) { - break; - } - - duk_require_stack(ctx, 1); - duk_push_lstring(ctx, (const char *) buf, ret); - } - - duk_concat(ctx, duk_get_top(ctx)); - - duk_eval_string(ctx, "(function (v) { print(Duktape.enc('jx', JSON.parse(v), null, 4)); })"); - duk_insert(ctx, -2); - duk_call(ctx, 1); - - return 0; -} - -int main(int argc, char *argv[]) { - duk_context *ctx; - duk_int_t rc; - - /* suppress warnings */ - (void) argc; - (void) argv; - - ctx = duk_create_heap_default(); - - rc = duk_safe_call(ctx, do_jxpretty, 0 /*nargs*/, 1 /*nrets*/); - if (rc) { - fprintf(stderr, "ERROR: %s\n", duk_safe_to_string(ctx, -1)); - fflush(stderr); - } - - duk_destroy_heap(ctx); - - return 0; -} diff --git a/src/third_party/duktape-1.3.0/examples/sandbox/README.rst b/src/third_party/duktape-1.3.0/examples/sandbox/README.rst deleted file mode 100644 index 24df0a25..00000000 --- a/src/third_party/duktape-1.3.0/examples/sandbox/README.rst +++ /dev/null @@ -1,5 +0,0 @@ -=============== -Sandbox example -=============== - -Very simple, minimal sandboxing example. diff --git a/src/third_party/duktape-1.3.0/examples/sandbox/sandbox.c b/src/third_party/duktape-1.3.0/examples/sandbox/sandbox.c deleted file mode 100644 index 915faa9a..00000000 --- a/src/third_party/duktape-1.3.0/examples/sandbox/sandbox.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Sandboxing example - * - * Uses custom memory allocation functions which keep track of total amount - * of memory allocated, imposing a maximum total allocation size. - */ - -#include -#include -#include "duktape.h" - -/* - * Memory allocator which backs to standard library memory functions but - * keeps a small header to track current allocation size. - * - * Many other sandbox allocation models are useful, e.g. preallocated pools. - */ - -typedef struct { - /* The double value in the union is there to ensure alignment is - * good for IEEE doubles too. In many 32-bit environments 4 bytes - * would be sufficiently aligned and the double value is unnecessary. - */ - union { - size_t sz; - double d; - } u; -} alloc_hdr; - -static size_t total_allocated = 0; -static size_t max_allocated = 256 * 1024; /* 256kB sandbox */ - -static void sandbox_dump_memstate(void) { -#if 0 - fprintf(stderr, "Total allocated: %ld\n", (long) total_allocated); - fflush(stderr); -#endif -} - -static void *sandbox_alloc(void *udata, duk_size_t size) { - alloc_hdr *hdr; - - (void) udata; /* Suppress warning. */ - - if (size == 0) { - return NULL; - } - - if (total_allocated + size > max_allocated) { - fprintf(stderr, "Sandbox maximum allocation size reached, %ld requested in sandbox_alloc\n", - (long) size); - fflush(stderr); - return NULL; - } - - hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr)); - if (!hdr) { - return NULL; - } - hdr->u.sz = size; - total_allocated += size; - sandbox_dump_memstate(); - return (void *) (hdr + 1); -} - -static void *sandbox_realloc(void *udata, void *ptr, duk_size_t size) { - alloc_hdr *hdr; - size_t old_size; - void *t; - - (void) udata; /* Suppress warning. */ - - /* Handle the ptr-NULL vs. size-zero cases explicitly to minimize - * platform assumptions. You can get away with much less in specific - * well-behaving environments. - */ - - if (ptr) { - hdr = (alloc_hdr *) (((char *) ptr) - sizeof(alloc_hdr)); - old_size = hdr->u.sz; - - if (size == 0) { - total_allocated -= old_size; - free((void *) hdr); - sandbox_dump_memstate(); - return NULL; - } else { - if (total_allocated - old_size + size > max_allocated) { - fprintf(stderr, "Sandbox maximum allocation size reached, %ld requested in sandbox_realloc\n", - (long) size); - fflush(stderr); - return NULL; - } - - t = realloc((void *) hdr, size + sizeof(alloc_hdr)); - if (!t) { - return NULL; - } - hdr = (alloc_hdr *) t; - total_allocated -= old_size; - total_allocated += size; - hdr->u.sz = size; - sandbox_dump_memstate(); - return (void *) (hdr + 1); - } - } else { - if (size == 0) { - return NULL; - } else { - if (total_allocated + size > max_allocated) { - fprintf(stderr, "Sandbox maximum allocation size reached, %ld requested in sandbox_realloc\n", - (long) size); - fflush(stderr); - return NULL; - } - - hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr)); - if (!hdr) { - return NULL; - } - hdr->u.sz = size; - total_allocated += size; - sandbox_dump_memstate(); - return (void *) (hdr + 1); - } - } -} - -static void sandbox_free(void *udata, void *ptr) { - alloc_hdr *hdr; - - (void) udata; /* Suppress warning. */ - - if (!ptr) { - return; - } - hdr = (alloc_hdr *) (((char *) ptr) - sizeof(alloc_hdr)); - total_allocated -= hdr->u.sz; - free((void *) hdr); - sandbox_dump_memstate(); -} - -/* - * Sandbox setup and test - */ - -static duk_ret_t do_sandbox_test(duk_context *ctx) { - FILE *f; - char buf[4096]; - size_t ret; - const char *globobj; - - /* - * Setup sandbox - */ - - globobj = - "({\n" - " print: print,\n" - " Math: {\n" - " max: Math.max\n" - " }\n" - "})\n"; -#if 1 - fprintf(stderr, "Sandbox global object:\n----------------\n%s----------------\n", globobj); - fflush(stderr); -#endif - duk_eval_string(ctx, globobj); - duk_set_global_object(ctx); - - /* - * Execute code from specified file - */ - - f = fopen(duk_require_string(ctx, -1), "rb"); - if (!f) { - duk_error(ctx, DUK_ERR_ERROR, "failed to open file"); - } - - for (;;) { - if (ferror(f)) { - fclose(f); - duk_error(ctx, DUK_ERR_ERROR, "ferror when reading file"); - } - if (feof(f)) { - break; - } - - ret = fread(buf, 1, sizeof(buf), f); - if (ret == 0) { - break; - } - - duk_push_lstring(ctx, (const char *) buf, ret); - } - - duk_concat(ctx, duk_get_top(ctx) - 1); /* -1 for filename */ - - /* -> [ ... filename source ] */ - - duk_insert(ctx, -2); - - /* -> [ ... source filename ] */ - - duk_compile(ctx, 0 /*flags*/); /* Compile as program */ - duk_call(ctx, 0 /*nargs*/); - - return 0; -} - -/* - * Main - */ - -static void sandbox_fatal(duk_context *ctx, duk_errcode_t code, const char *msg) { - (void) ctx; /* Suppress warning. */ - fprintf(stderr, "FATAL %ld: %s\n", (long) code, (msg ? msg : "no message")); - fflush(stderr); - exit(1); /* must not return */ -} - -int main(int argc, char *argv[]) { - duk_context *ctx; - duk_int_t rc; - - if (argc < 2) { - fprintf(stderr, "Usage: sandbox \n"); - fflush(stderr); - exit(1); - } - - ctx = duk_create_heap(sandbox_alloc, - sandbox_realloc, - sandbox_free, - NULL, - sandbox_fatal); - - duk_push_string(ctx, argv[1]); - rc = duk_safe_call(ctx, do_sandbox_test, 1 /*nargs*/, 1 /*nrets*/); - if (rc) { - fprintf(stderr, "ERROR: %s\n", duk_safe_to_string(ctx, -1)); - fflush(stderr); - } - - duk_destroy_heap(ctx); - - /* Should be zero. */ - fprintf(stderr, "Final allocation: %ld\n", (long) total_allocated); - fflush(stderr); - - return 1; -} diff --git a/src/third_party/duktape-1.3.0/extras/README.rst b/src/third_party/duktape-1.3.0/extras/README.rst deleted file mode 100644 index 1b701601..00000000 --- a/src/third_party/duktape-1.3.0/extras/README.rst +++ /dev/null @@ -1,13 +0,0 @@ -============== -Duktape extras -============== - -Extra modules and utilities. Extras provide functionality that doesn't -comfortably fit into the main Duktape library, perhaps for footprint or -portability reasons, but are still useful for most users. - -Extras are maintained and will be bug fixed. However, they don't have the -same semantic versioning guarantees like the main Duktape library. Extras -may be dropped without warning as Duktape is versioned. For instance, if -an extra breaks due to Duktape changes and there is no time to fix it, the -missing extra won't block a release and will be dropped. diff --git a/src/third_party/duktape-1.3.0/license.spdx b/src/third_party/duktape-1.3.0/license.spdx deleted file mode 100644 index 535d95f9..00000000 --- a/src/third_party/duktape-1.3.0/license.spdx +++ /dev/null @@ -1,3629 +0,0 @@ - - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/c_eventloop.js - <_3:checksum rdf:nodeID="NukVOfZA86"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/debug-trans-dvalue/duk_trans_dvalue.c - <_3:checksum rdf:nodeID="NukVOfZA160"/> - - - - <_3:checksumValue>215f6fec820889330048f7f2c1b5a220eb963657 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_misc.c - <_3:checksum rdf:nodeID="NukVOfZA192"/> - - - - <_3:checksumValue>50a3349a079123b6bddf3db507df0dd9e877e246 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./debugger/static/webui.js - <_3:checksum rdf:nodeID="NukVOfZA52"/> - - - - <_3:checksumValue>5ebff36a2dd7cb495eed358c59670541c6c8be19 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - <_3:created rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2015-09-12T02:15:22Z - - <_3:licenseListVersion>1.20 - <_3:creator>Organization: duktape.org - - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_proxy.c - <_3:checksum rdf:nodeID="NukVOfZA388"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./polyfills/duktape-isfastint.js - <_3:checksum rdf:nodeID="NukVOfZA432"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_replacements.c - <_3:checksum rdf:nodeID="NukVOfZA410"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_selftest.h - <_3:checksum rdf:nodeID="NukVOfZA286"/> - - - - <_3:checksumValue>92ce3decf72b10b0023116ac727a752e8749aa90 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>a8c0b54002a3a7d8c69d385e7fbcf4b70d1efc70 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>3b8236810650f4e28bd84984b3c7e55029f241b0 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/guide/uppercase.c - <_3:checksum rdf:nodeID="NukVOfZA122"/> - - - <_3:packageVerificationCodeValue>39d0d436fe36ae0901ab8ed9cbdaf379037760fb - <_3:packageVerificationCodeExcludedFile>./license.spdx - - - - <_3:checksumValue>089c395fca3cedceec09fd38d32d0c77dc8658f4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_misc.c - <_3:checksum rdf:nodeID="NukVOfZA218"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/eventloop/README.rst - <_3:checksum rdf:nodeID="NukVOfZA94"/> - - - - <_3:checksumValue>6b98824e13a3d9536542b8da51d012a3d66ceec1 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>6d5f56a1b76f9dcc9bb68d62ad0df958bd4d38ec - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>ddbc206357dd4b97f3630b87bfdac148a5e8b190 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>03cad085177f1e776be90afceef1f2160e6c8bf4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>c2d899e7f2343579f29ad3079fde44eec5d6a544 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hbuffer_alloc.c - <_3:checksum rdf:nodeID="NukVOfZA234"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./debugger/duk_debug.js - <_3:checksum rdf:nodeID="NukVOfZA36"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/codepage-conv/duk_codepage_conv.h - <_3:checksum rdf:nodeID="NukVOfZA78"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/guide/fib.js - <_3:checksum rdf:nodeID="NukVOfZA124"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_executor.c - <_3:checksum rdf:nodeID="NukVOfZA374"/> - - - - <_3:checksumValue>78e85afbf3394e8f79b30bdcbd479faf8781e25d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>afd3e5c9becf5feecaf57e4c5586b83da1ca61c3 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_pc2line.c - <_3:checksum rdf:nodeID="NukVOfZA250"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_function.c - <_3:checksum rdf:nodeID="NukVOfZA202"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_refcount.c - <_3:checksum rdf:nodeID="NukVOfZA310"/> - - - - <_3:checksumValue>7b1e7e495bd7199d2e50c20e672c7fc01fcd3a42 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_duktape.c - <_3:checksum rdf:nodeID="NukVOfZA366"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_compiler.c - <_3:checksum rdf:nodeID="NukVOfZA214"/> - - - - <_3:checksumValue>3d8403c0150e1633ddb87362bc3d85518e26cd6a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>6da918cc81769eeeb7c2fe20b549aebf744f175a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util.h - <_3:checksum rdf:nodeID="NukVOfZA206"/> - - - - <_3:checksumValue>64566ae0bdc1c3e1017604b6b45d515c30d976eb - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>881f1b114c9fbba139044ddcbbc5398243185d10 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:describesPackage rdf:nodeID="NukVOfZA4"/> - <_3:specVersion>SPDX-1.2 - <_3:dataLicense rdf:resource="http://spdx.org/licenses/CC0-1.0"/> - <_3:referencesFile rdf:nodeID="NukVOfZA85"/> - <_3:referencesFile rdf:nodeID="NukVOfZA159"/> - <_3:referencesFile rdf:nodeID="NukVOfZA189"/> - <_3:referencesFile rdf:nodeID="NukVOfZA269"/> - <_3:referencesFile rdf:nodeID="NukVOfZA447"/> - <_3:referencesFile rdf:nodeID="NukVOfZA403"/> - <_3:referencesFile rdf:nodeID="NukVOfZA191"/> - <_3:referencesFile rdf:nodeID="NukVOfZA255"/> - <_3:referencesFile rdf:nodeID="NukVOfZA61"/> - <_3:referencesFile rdf:nodeID="NukVOfZA267"/> - <_3:referencesFile rdf:nodeID="NukVOfZA23"/> - <_3:referencesFile rdf:nodeID="NukVOfZA179"/> - <_3:referencesFile rdf:nodeID="NukVOfZA271"/> - <_3:referencesFile rdf:nodeID="NukVOfZA197"/> - <_3:referencesFile rdf:nodeID="NukVOfZA367"/> - <_3:referencesFile rdf:nodeID="NukVOfZA365"/> - <_3:referencesFile rdf:nodeID="NukVOfZA425"/> - <_3:referencesFile rdf:nodeID="NukVOfZA351"/> - <_3:referencesFile rdf:nodeID="NukVOfZA317"/> - <_3:referencesFile rdf:nodeID="NukVOfZA211"/> - <_3:referencesFile rdf:nodeID="NukVOfZA207"/> - <_3:referencesFile rdf:nodeID="NukVOfZA431"/> - <_3:referencesFile rdf:nodeID="NukVOfZA331"/> - <_3:referencesFile rdf:nodeID="NukVOfZA33"/> - <_3:referencesFile rdf:nodeID="NukVOfZA285"/> - <_3:referencesFile rdf:nodeID="NukVOfZA371"/> - <_3:referencesFile rdf:nodeID="NukVOfZA423"/> - <_3:referencesFile rdf:nodeID="NukVOfZA199"/> - <_3:referencesFile rdf:nodeID="NukVOfZA163"/> - <_3:referencesFile rdf:nodeID="NukVOfZA81"/> - <_3:referencesFile rdf:nodeID="NukVOfZA291"/> - <_3:referencesFile rdf:nodeID="NukVOfZA25"/> - <_3:referencesFile rdf:nodeID="NukVOfZA97"/> - <_3:referencesFile rdf:nodeID="NukVOfZA341"/> - <_3:referencesFile rdf:nodeID="NukVOfZA339"/> - <_3:referencesFile rdf:nodeID="NukVOfZA217"/> - <_3:referencesFile rdf:nodeID="NukVOfZA93"/> - <_3:referencesFile rdf:nodeID="NukVOfZA175"/> - <_3:referencesFile rdf:nodeID="NukVOfZA193"/> - <_3:referencesFile rdf:nodeID="NukVOfZA117"/> - <_3:referencesFile rdf:nodeID="NukVOfZA377"/> - <_3:referencesFile rdf:nodeID="NukVOfZA69"/> - <_3:referencesFile rdf:nodeID="NukVOfZA75"/> - <_3:referencesFile rdf:nodeID="NukVOfZA21"/> - <_3:referencesFile rdf:nodeID="NukVOfZA111"/> - <_3:referencesFile rdf:nodeID="NukVOfZA63"/> - <_3:referencesFile rdf:nodeID="NukVOfZA287"/> - <_3:referencesFile rdf:nodeID="NukVOfZA239"/> - <_3:referencesFile rdf:nodeID="NukVOfZA147"/> - <_3:referencesFile rdf:nodeID="NukVOfZA233"/> - <_3:referencesFile rdf:nodeID="NukVOfZA89"/> - <_3:referencesFile rdf:nodeID="NukVOfZA181"/> - <_3:referencesFile rdf:nodeID="NukVOfZA77"/> - <_3:referencesFile rdf:nodeID="NukVOfZA79"/> - <_3:referencesFile rdf:nodeID="NukVOfZA123"/> - <_3:referencesFile rdf:nodeID="NukVOfZA373"/> - <_3:referencesFile rdf:nodeID="NukVOfZA319"/> - <_3:referencesFile rdf:nodeID="NukVOfZA131"/> - <_3:referencesFile rdf:nodeID="NukVOfZA137"/> - <_3:referencesFile rdf:nodeID="NukVOfZA249"/> - <_3:referencesFile rdf:nodeID="NukVOfZA201"/> - <_3:referencesFile rdf:nodeID="NukVOfZA437"/> - <_3:referencesFile rdf:nodeID="NukVOfZA417"/> - <_3:referencesFile rdf:nodeID="NukVOfZA309"/> - <_3:referencesFile rdf:nodeID="NukVOfZA393"/> - <_3:referencesFile rdf:nodeID="NukVOfZA157"/> - <_3:referencesFile rdf:nodeID="NukVOfZA241"/> - <_3:referencesFile rdf:nodeID="NukVOfZA213"/> - <_3:referencesFile rdf:nodeID="NukVOfZA419"/> - <_3:referencesFile rdf:nodeID="NukVOfZA101"/> - <_3:referencesFile rdf:nodeID="NukVOfZA235"/> - <_3:referencesFile rdf:nodeID="NukVOfZA205"/> - <_3:referencesFile rdf:nodeID="NukVOfZA143"/> - <_3:referencesFile rdf:nodeID="NukVOfZA363"/> - <_3:referencesFile rdf:nodeID="NukVOfZA221"/> - <_3:referencesFile rdf:nodeID="NukVOfZA289"/> - <_3:referencesFile rdf:nodeID="NukVOfZA135"/> - <_3:referencesFile rdf:nodeID="NukVOfZA109"/> - <_3:referencesFile rdf:nodeID="NukVOfZA35"/> - <_3:referencesFile rdf:nodeID="NukVOfZA439"/> - <_3:referencesFile rdf:nodeID="NukVOfZA399"/> - <_3:referencesFile rdf:nodeID="NukVOfZA411"/> - <_3:referencesFile rdf:nodeID="NukVOfZA307"/> - <_3:referencesFile rdf:nodeID="NukVOfZA169"/> - <_3:referencesFile rdf:nodeID="NukVOfZA203"/> - <_3:referencesFile rdf:nodeID="NukVOfZA39"/> - <_3:referencesFile rdf:nodeID="NukVOfZA187"/> - <_3:referencesFile rdf:nodeID="NukVOfZA103"/> - <_3:referencesFile rdf:nodeID="NukVOfZA409"/> - <_3:referencesFile rdf:nodeID="NukVOfZA343"/> - <_3:referencesFile rdf:nodeID="NukVOfZA231"/> - <_3:referencesFile rdf:nodeID="NukVOfZA389"/> - <_3:referencesFile rdf:nodeID="NukVOfZA379"/> - <_3:referencesFile rdf:nodeID="NukVOfZA253"/> - <_3:referencesFile rdf:nodeID="NukVOfZA321"/> - <_3:referencesFile rdf:nodeID="NukVOfZA243"/> - <_3:referencesFile rdf:nodeID="NukVOfZA167"/> - <_3:referencesFile rdf:nodeID="NukVOfZA311"/> - <_3:referencesFile rdf:nodeID="NukVOfZA275"/> - <_3:referencesFile rdf:nodeID="NukVOfZA127"/> - <_3:referencesFile rdf:nodeID="NukVOfZA29"/> - <_3:referencesFile rdf:nodeID="NukVOfZA429"/> - <_3:referencesFile rdf:nodeID="NukVOfZA257"/> - <_3:referencesFile rdf:nodeID="NukVOfZA325"/> - <_3:referencesFile rdf:nodeID="NukVOfZA435"/> - <_3:referencesFile rdf:nodeID="NukVOfZA337"/> - <_3:referencesFile rdf:nodeID="NukVOfZA259"/> - <_3:referencesFile rdf:nodeID="NukVOfZA381"/> - <_3:referencesFile rdf:nodeID="NukVOfZA407"/> - <_3:referencesFile rdf:nodeID="NukVOfZA177"/> - <_3:referencesFile rdf:nodeID="NukVOfZA449"/> - <_3:referencesFile rdf:nodeID="NukVOfZA53"/> - <_3:referencesFile rdf:nodeID="NukVOfZA395"/> - <_3:referencesFile rdf:nodeID="NukVOfZA209"/> - <_3:referencesFile rdf:nodeID="NukVOfZA27"/> - <_3:referencesFile rdf:nodeID="NukVOfZA397"/> - <_3:referencesFile rdf:nodeID="NukVOfZA237"/> - <_3:referencesFile rdf:nodeID="NukVOfZA335"/> - <_3:referencesFile rdf:nodeID="NukVOfZA139"/> - <_3:referencesFile rdf:nodeID="NukVOfZA41"/> - <_3:referencesFile rdf:nodeID="NukVOfZA171"/> - <_3:referencesFile rdf:nodeID="NukVOfZA7"/> - <_3:referencesFile rdf:nodeID="NukVOfZA387"/> - <_3:referencesFile rdf:nodeID="NukVOfZA83"/> - <_3:referencesFile rdf:nodeID="NukVOfZA421"/> - <_3:referencesFile rdf:nodeID="NukVOfZA327"/> - <_3:referencesFile rdf:nodeID="NukVOfZA347"/> - <_3:referencesFile rdf:nodeID="NukVOfZA277"/> - <_3:referencesFile rdf:nodeID="NukVOfZA279"/> - <_3:referencesFile rdf:nodeID="NukVOfZA59"/> - <_3:referencesFile rdf:nodeID="NukVOfZA185"/> - <_3:referencesFile rdf:nodeID="NukVOfZA329"/> - <_3:referencesFile rdf:nodeID="NukVOfZA427"/> - <_3:referencesFile rdf:nodeID="NukVOfZA273"/> - <_3:referencesFile rdf:nodeID="NukVOfZA361"/> - <_3:referencesFile rdf:nodeID="NukVOfZA345"/> - <_3:referencesFile rdf:nodeID="NukVOfZA223"/> - <_3:referencesFile rdf:nodeID="NukVOfZA375"/> - <_3:referencesFile rdf:nodeID="NukVOfZA445"/> - <_3:referencesFile rdf:nodeID="NukVOfZA15"/> - <_3:referencesFile rdf:nodeID="NukVOfZA359"/> - <_3:referencesFile rdf:nodeID="NukVOfZA45"/> - <_3:referencesFile rdf:nodeID="NukVOfZA215"/> - <_3:referencesFile rdf:nodeID="NukVOfZA183"/> - <_3:referencesFile rdf:nodeID="NukVOfZA369"/> - <_3:referencesFile rdf:nodeID="NukVOfZA265"/> - <_3:referencesFile rdf:nodeID="NukVOfZA305"/> - <_3:referencesFile rdf:nodeID="NukVOfZA51"/> - <_3:referencesFile rdf:nodeID="NukVOfZA113"/> - <_3:referencesFile rdf:nodeID="NukVOfZA13"/> - <_3:referencesFile rdf:nodeID="NukVOfZA43"/> - <_3:referencesFile rdf:nodeID="NukVOfZA133"/> - <_3:referencesFile rdf:nodeID="NukVOfZA383"/> - <_3:referencesFile rdf:nodeID="NukVOfZA251"/> - <_3:referencesFile rdf:nodeID="NukVOfZA55"/> - <_3:referencesFile rdf:nodeID="NukVOfZA295"/> - <_3:referencesFile rdf:nodeID="NukVOfZA401"/> - <_3:referencesFile rdf:nodeID="NukVOfZA433"/> - <_3:referencesFile rdf:nodeID="NukVOfZA161"/> - <_3:referencesFile rdf:nodeID="NukVOfZA299"/> - <_3:referencesFile rdf:nodeID="NukVOfZA95"/> - <_3:referencesFile rdf:nodeID="NukVOfZA107"/> - <_3:referencesFile rdf:nodeID="NukVOfZA227"/> - <_3:referencesFile rdf:nodeID="NukVOfZA323"/> - <_3:referencesFile rdf:nodeID="NukVOfZA333"/> - <_3:referencesFile rdf:nodeID="NukVOfZA105"/> - <_3:referencesFile rdf:nodeID="NukVOfZA443"/> - <_3:referencesFile rdf:nodeID="NukVOfZA153"/> - <_3:referencesFile rdf:nodeID="NukVOfZA141"/> - <_3:referencesFile rdf:nodeID="NukVOfZA353"/> - <_3:referencesFile rdf:nodeID="NukVOfZA9"/> - <_3:referencesFile rdf:nodeID="NukVOfZA281"/> - <_3:referencesFile rdf:nodeID="NukVOfZA11"/> - <_3:referencesFile rdf:nodeID="NukVOfZA385"/> - <_3:referencesFile rdf:nodeID="NukVOfZA229"/> - <_3:referencesFile rdf:nodeID="NukVOfZA297"/> - <_3:referencesFile rdf:nodeID="NukVOfZA405"/> - <_3:referencesFile rdf:nodeID="NukVOfZA151"/> - <_3:referencesFile rdf:nodeID="NukVOfZA165"/> - <_3:referencesFile rdf:nodeID="NukVOfZA67"/> - <_3:referencesFile rdf:nodeID="NukVOfZA115"/> - <_3:referencesFile rdf:nodeID="NukVOfZA65"/> - <_3:referencesFile rdf:nodeID="NukVOfZA49"/> - <_3:referencesFile rdf:nodeID="NukVOfZA263"/> - <_3:referencesFile rdf:nodeID="NukVOfZA125"/> - <_3:referencesFile rdf:nodeID="NukVOfZA91"/> - <_3:referencesFile rdf:nodeID="NukVOfZA19"/> - <_3:referencesFile rdf:nodeID="NukVOfZA283"/> - <_3:referencesFile rdf:nodeID="NukVOfZA349"/> - <_3:referencesFile rdf:nodeID="NukVOfZA173"/> - <_3:referencesFile rdf:nodeID="NukVOfZA355"/> - <_3:referencesFile rdf:nodeID="NukVOfZA303"/> - <_3:referencesFile rdf:nodeID="NukVOfZA441"/> - <_3:referencesFile rdf:nodeID="NukVOfZA357"/> - <_3:referencesFile rdf:nodeID="NukVOfZA195"/> - <_3:referencesFile rdf:nodeID="NukVOfZA225"/> - <_3:referencesFile rdf:nodeID="NukVOfZA57"/> - <_3:referencesFile rdf:nodeID="NukVOfZA121"/> - <_3:referencesFile rdf:nodeID="NukVOfZA453"/> - <_3:referencesFile rdf:nodeID="NukVOfZA415"/> - <_3:referencesFile rdf:nodeID="NukVOfZA261"/> - <_3:referencesFile rdf:nodeID="NukVOfZA301"/> - <_3:referencesFile rdf:nodeID="NukVOfZA391"/> - <_3:referencesFile rdf:nodeID="NukVOfZA17"/> - <_3:referencesFile rdf:nodeID="NukVOfZA245"/> - <_3:referencesFile rdf:nodeID="NukVOfZA71"/> - <_3:referencesFile rdf:nodeID="NukVOfZA129"/> - <_3:referencesFile rdf:nodeID="NukVOfZA293"/> - <_3:referencesFile rdf:nodeID="NukVOfZA31"/> - <_3:referencesFile rdf:nodeID="NukVOfZA119"/> - <_3:referencesFile rdf:nodeID="NukVOfZA219"/> - <_3:referencesFile rdf:nodeID="NukVOfZA451"/> - <_3:referencesFile rdf:nodeID="NukVOfZA145"/> - <_3:referencesFile rdf:nodeID="NukVOfZA73"/> - <_3:referencesFile rdf:nodeID="NukVOfZA37"/> - <_3:referencesFile rdf:nodeID="NukVOfZA87"/> - <_3:referencesFile rdf:nodeID="NukVOfZA247"/> - <_3:referencesFile rdf:nodeID="NukVOfZA99"/> - <_3:referencesFile rdf:nodeID="NukVOfZA47"/> - <_3:referencesFile rdf:nodeID="NukVOfZA413"/> - <_3:referencesFile rdf:nodeID="NukVOfZA155"/> - <_3:referencesFile rdf:nodeID="NukVOfZA313"/> - <_3:referencesFile rdf:nodeID="NukVOfZA315"/> - <_3:referencesFile rdf:nodeID="NukVOfZA149"/> - SPDX license for Duktape 1.3.0 - <_3:creationInfo rdf:nodeID="NukVOfZA3"/> - - - - <_3:checksumValue>c14747594add785dd952855071e51077f5152bad - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>cd025a84635e6a1353f756cf9c74c27bfd36862d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_number.c - <_3:checksum rdf:nodeID="NukVOfZA412"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_numconv.h - <_3:checksum rdf:nodeID="NukVOfZA188"/> - - - - <_3:checksumValue>f88d68880f451267e7e2eca4b6c4191e8c3fe011 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>93573df8348a41adb790f59e39bf99d9a7bf3a3d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>75c61dd080cd643b7449f673105b7b7e4bdda0f5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_json.h - <_3:checksum rdf:nodeID="NukVOfZA322"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_call.c - <_3:checksum rdf:nodeID="NukVOfZA244"/> - - - - <_3:checksumValue>de9650befceae510999c0e852a79f994d74fc531 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_markandsweep.c - <_3:checksum rdf:nodeID="NukVOfZA312"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_bitdecoder.c - <_3:checksum rdf:nodeID="NukVOfZA258"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hbuffer.h - <_3:checksum rdf:nodeID="NukVOfZA326"/> - - - - <_3:checksumValue>ce19fb1254e02c8ff3ed8e0737522d6af7b977c5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>82314b509ee3b15b393fefe747c8e0169ab39aaa - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_ops.c - <_3:checksum rdf:nodeID="NukVOfZA396"/> - - - - <_3:checksumValue>a3d2ce3d28d6bb5afd29e35ade770a8ae5f45c3f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>a8f8cf615ef79337a83eb791477dc9ed2c22822c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>7e2674dd72227576375a80f6ddbb11320f5b987a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>37a995b627b3a85cecc2a5851537589d4da3bf63 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>44c9219558aba26dc69982a9f432028290707c36 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_initjs_min.js - <_3:checksum rdf:nodeID="NukVOfZA390"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_selftest.c - <_3:checksum rdf:nodeID="NukVOfZA330"/> - - - - <_3:checksumValue>59d3c2d44ed8707fa6c907a7387ffce611d89e44 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_regexp_compiler.c - <_3:checksum rdf:nodeID="NukVOfZA346"/> - - - - <_3:checksumValue>79f806448cbd4724bf60e0723414b391686be098 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_string.c - <_3:checksum rdf:nodeID="NukVOfZA392"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_misc.c - <_3:checksum rdf:nodeID="NukVOfZA266"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_lexer.h - <_3:checksum rdf:nodeID="NukVOfZA306"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/eval/README.rst - <_3:checksum rdf:nodeID="NukVOfZA114"/> - - - - <_3:checksumValue>11ecfff4142b35382d0aaf80ee6c04ae3dfd0b4c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/package.json - <_3:checksum rdf:nodeID="NukVOfZA44"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_internal.h - <_3:checksum rdf:nodeID="NukVOfZA296"/> - - - - <_3:checksumValue>47e1001460004f53dfc350355e02bf56f18b0398 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/server-socket-test.js - <_3:checksum rdf:nodeID="NukVOfZA108"/> - - - - <_3:checksumValue>43a0dfbf1cb06dbfe3a37959ad1b93bc036f78cb - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/client-socket-test.js - <_3:checksum rdf:nodeID="NukVOfZA106"/> - - - - <_3:checksumValue>b5f54e8a18d5dc9a791cb36976a7d2345d26b549 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./duk_build_meta.json - <_3:checksum rdf:nodeID="NukVOfZA10"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./README.rst - <_3:checksum rdf:nodeID="NukVOfZA12"/> - - - - <_3:checksumValue>a9c998dbedde09cc435eec0ac1a3a428090b37a9 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hbufferobject_misc.c - <_3:checksum rdf:nodeID="NukVOfZA298"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_debug.c - <_3:checksum rdf:nodeID="NukVOfZA196"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/alloc-hybrid/README.rst - <_3:checksum rdf:nodeID="NukVOfZA68"/> - - - - <_3:checksumValue>8d307ae071694f3d2242578c7d88bcae5c2ef7de - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_hashstring.c - <_3:checksum rdf:nodeID="NukVOfZA350"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/alloc-logging/README.rst - <_3:checksum rdf:nodeID="NukVOfZA174"/> - - - - <_3:checksumValue>e5a5f0db067ec56c6d2f7356f412222a8884dc92 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./config/genconfig_metadata.tar.gz - <_3:checksum rdf:nodeID="NukVOfZA442"/> - - - - <_3:checksumValue>d68dbb37b698f98f51a9136d4026b2ac0a2911c4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>6a1500fea27ea278c4f0c64d908e16cc60df684b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:name>Duktape - <_3:originator>Organization: duktape.org - <_3:versionInfo>1.3.0 - <_3:packageVerificationCode rdf:nodeID="NukVOfZA5"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:summary>Duktape Ecmascript interpreter - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:downloadLocation rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://duktape.org/duktape-1.3.0.tar.xz - <_3:homePage rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://duktape.org/ - <_3:licenseDeclared rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:licenseComments>Duktape is copyrighted by its authors and licensed under the MIT license. MurmurHash2 is used internally, it is also under the MIT license. Duktape module loader is based on the CommonJS module loading specification (without sharing any code), CommonJS is under the MIT license. - <_3:supplier>Organization: duktape.org - <_3:sourceInfo>Official duktape.org release built from GitHub repo https://github.com/svaarala/duktape. - <_3:licenseInfoFromFiles rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:packageFileName>duktape-1.3.0.tar.xz - <_3:hasFile rdf:nodeID="NukVOfZA85"/> - <_3:hasFile rdf:nodeID="NukVOfZA159"/> - <_3:hasFile rdf:nodeID="NukVOfZA189"/> - <_3:hasFile rdf:nodeID="NukVOfZA269"/> - <_3:hasFile rdf:nodeID="NukVOfZA447"/> - <_3:hasFile rdf:nodeID="NukVOfZA403"/> - <_3:hasFile rdf:nodeID="NukVOfZA191"/> - <_3:hasFile rdf:nodeID="NukVOfZA255"/> - <_3:hasFile rdf:nodeID="NukVOfZA61"/> - <_3:hasFile rdf:nodeID="NukVOfZA267"/> - <_3:hasFile rdf:nodeID="NukVOfZA23"/> - <_3:hasFile rdf:nodeID="NukVOfZA179"/> - <_3:hasFile rdf:nodeID="NukVOfZA271"/> - <_3:hasFile rdf:nodeID="NukVOfZA197"/> - <_3:hasFile rdf:nodeID="NukVOfZA367"/> - <_3:hasFile rdf:nodeID="NukVOfZA365"/> - <_3:hasFile rdf:nodeID="NukVOfZA425"/> - <_3:hasFile rdf:nodeID="NukVOfZA351"/> - <_3:hasFile rdf:nodeID="NukVOfZA317"/> - <_3:hasFile rdf:nodeID="NukVOfZA211"/> - <_3:hasFile rdf:nodeID="NukVOfZA207"/> - <_3:hasFile rdf:nodeID="NukVOfZA431"/> - <_3:hasFile rdf:nodeID="NukVOfZA331"/> - <_3:hasFile rdf:nodeID="NukVOfZA33"/> - <_3:hasFile rdf:nodeID="NukVOfZA285"/> - <_3:hasFile rdf:nodeID="NukVOfZA371"/> - <_3:hasFile rdf:nodeID="NukVOfZA423"/> - <_3:hasFile rdf:nodeID="NukVOfZA199"/> - <_3:hasFile rdf:nodeID="NukVOfZA163"/> - <_3:hasFile rdf:nodeID="NukVOfZA81"/> - <_3:hasFile rdf:nodeID="NukVOfZA291"/> - <_3:hasFile rdf:nodeID="NukVOfZA25"/> - <_3:hasFile rdf:nodeID="NukVOfZA97"/> - <_3:hasFile rdf:nodeID="NukVOfZA341"/> - <_3:hasFile rdf:nodeID="NukVOfZA339"/> - <_3:hasFile rdf:nodeID="NukVOfZA217"/> - <_3:hasFile rdf:nodeID="NukVOfZA93"/> - <_3:hasFile rdf:nodeID="NukVOfZA175"/> - <_3:hasFile rdf:nodeID="NukVOfZA193"/> - <_3:hasFile rdf:nodeID="NukVOfZA117"/> - <_3:hasFile rdf:nodeID="NukVOfZA377"/> - <_3:hasFile rdf:nodeID="NukVOfZA69"/> - <_3:hasFile rdf:nodeID="NukVOfZA75"/> - <_3:hasFile rdf:nodeID="NukVOfZA21"/> - <_3:hasFile rdf:nodeID="NukVOfZA111"/> - <_3:hasFile rdf:nodeID="NukVOfZA63"/> - <_3:hasFile rdf:nodeID="NukVOfZA287"/> - <_3:hasFile rdf:nodeID="NukVOfZA239"/> - <_3:hasFile rdf:nodeID="NukVOfZA147"/> - <_3:hasFile rdf:nodeID="NukVOfZA233"/> - <_3:hasFile rdf:nodeID="NukVOfZA89"/> - <_3:hasFile rdf:nodeID="NukVOfZA181"/> - <_3:hasFile rdf:nodeID="NukVOfZA77"/> - <_3:hasFile rdf:nodeID="NukVOfZA79"/> - <_3:hasFile rdf:nodeID="NukVOfZA123"/> - <_3:hasFile rdf:nodeID="NukVOfZA373"/> - <_3:hasFile rdf:nodeID="NukVOfZA319"/> - <_3:hasFile rdf:nodeID="NukVOfZA131"/> - <_3:hasFile rdf:nodeID="NukVOfZA137"/> - <_3:hasFile rdf:nodeID="NukVOfZA249"/> - <_3:hasFile rdf:nodeID="NukVOfZA201"/> - <_3:hasFile rdf:nodeID="NukVOfZA437"/> - <_3:hasFile rdf:nodeID="NukVOfZA417"/> - <_3:hasFile rdf:nodeID="NukVOfZA309"/> - <_3:hasFile rdf:nodeID="NukVOfZA393"/> - <_3:hasFile rdf:nodeID="NukVOfZA157"/> - <_3:hasFile rdf:nodeID="NukVOfZA241"/> - <_3:hasFile rdf:nodeID="NukVOfZA213"/> - <_3:hasFile rdf:nodeID="NukVOfZA419"/> - <_3:hasFile rdf:nodeID="NukVOfZA101"/> - <_3:hasFile rdf:nodeID="NukVOfZA235"/> - <_3:hasFile rdf:nodeID="NukVOfZA205"/> - <_3:hasFile rdf:nodeID="NukVOfZA143"/> - <_3:hasFile rdf:nodeID="NukVOfZA363"/> - <_3:hasFile rdf:nodeID="NukVOfZA221"/> - <_3:hasFile rdf:nodeID="NukVOfZA289"/> - <_3:hasFile rdf:nodeID="NukVOfZA135"/> - <_3:hasFile rdf:nodeID="NukVOfZA109"/> - <_3:hasFile rdf:nodeID="NukVOfZA35"/> - <_3:hasFile rdf:nodeID="NukVOfZA439"/> - <_3:hasFile rdf:nodeID="NukVOfZA399"/> - <_3:hasFile rdf:nodeID="NukVOfZA411"/> - <_3:hasFile rdf:nodeID="NukVOfZA307"/> - <_3:hasFile rdf:nodeID="NukVOfZA169"/> - <_3:hasFile rdf:nodeID="NukVOfZA203"/> - <_3:hasFile rdf:nodeID="NukVOfZA39"/> - <_3:hasFile rdf:nodeID="NukVOfZA187"/> - <_3:hasFile rdf:nodeID="NukVOfZA103"/> - <_3:hasFile rdf:nodeID="NukVOfZA409"/> - <_3:hasFile rdf:nodeID="NukVOfZA343"/> - <_3:hasFile rdf:nodeID="NukVOfZA231"/> - <_3:hasFile rdf:nodeID="NukVOfZA389"/> - <_3:hasFile rdf:nodeID="NukVOfZA379"/> - <_3:hasFile rdf:nodeID="NukVOfZA253"/> - <_3:hasFile rdf:nodeID="NukVOfZA321"/> - <_3:hasFile rdf:nodeID="NukVOfZA243"/> - <_3:hasFile rdf:nodeID="NukVOfZA167"/> - <_3:hasFile rdf:nodeID="NukVOfZA311"/> - <_3:hasFile rdf:nodeID="NukVOfZA275"/> - <_3:hasFile rdf:nodeID="NukVOfZA127"/> - <_3:hasFile rdf:nodeID="NukVOfZA29"/> - <_3:hasFile rdf:nodeID="NukVOfZA429"/> - <_3:hasFile rdf:nodeID="NukVOfZA257"/> - <_3:hasFile rdf:nodeID="NukVOfZA325"/> - <_3:hasFile rdf:nodeID="NukVOfZA435"/> - <_3:hasFile rdf:nodeID="NukVOfZA337"/> - <_3:hasFile rdf:nodeID="NukVOfZA259"/> - <_3:hasFile rdf:nodeID="NukVOfZA381"/> - <_3:hasFile rdf:nodeID="NukVOfZA407"/> - <_3:hasFile rdf:nodeID="NukVOfZA177"/> - <_3:hasFile rdf:nodeID="NukVOfZA449"/> - <_3:hasFile rdf:nodeID="NukVOfZA53"/> - <_3:hasFile rdf:nodeID="NukVOfZA395"/> - <_3:hasFile rdf:nodeID="NukVOfZA209"/> - <_3:hasFile rdf:nodeID="NukVOfZA27"/> - <_3:hasFile rdf:nodeID="NukVOfZA397"/> - <_3:hasFile rdf:nodeID="NukVOfZA237"/> - <_3:hasFile rdf:nodeID="NukVOfZA335"/> - <_3:hasFile rdf:nodeID="NukVOfZA139"/> - <_3:hasFile rdf:nodeID="NukVOfZA41"/> - <_3:hasFile rdf:nodeID="NukVOfZA171"/> - <_3:hasFile rdf:nodeID="NukVOfZA7"/> - <_3:hasFile rdf:nodeID="NukVOfZA387"/> - <_3:hasFile rdf:nodeID="NukVOfZA83"/> - <_3:hasFile rdf:nodeID="NukVOfZA421"/> - <_3:hasFile rdf:nodeID="NukVOfZA327"/> - <_3:hasFile rdf:nodeID="NukVOfZA347"/> - <_3:hasFile rdf:nodeID="NukVOfZA277"/> - <_3:hasFile rdf:nodeID="NukVOfZA279"/> - <_3:hasFile rdf:nodeID="NukVOfZA59"/> - <_3:hasFile rdf:nodeID="NukVOfZA185"/> - <_3:hasFile rdf:nodeID="NukVOfZA329"/> - <_3:hasFile rdf:nodeID="NukVOfZA427"/> - <_3:hasFile rdf:nodeID="NukVOfZA273"/> - <_3:hasFile rdf:nodeID="NukVOfZA361"/> - <_3:hasFile rdf:nodeID="NukVOfZA345"/> - <_3:hasFile rdf:nodeID="NukVOfZA223"/> - <_3:hasFile rdf:nodeID="NukVOfZA375"/> - <_3:hasFile rdf:nodeID="NukVOfZA445"/> - <_3:hasFile rdf:nodeID="NukVOfZA15"/> - <_3:hasFile rdf:nodeID="NukVOfZA359"/> - <_3:hasFile rdf:nodeID="NukVOfZA45"/> - <_3:hasFile rdf:nodeID="NukVOfZA215"/> - <_3:hasFile rdf:nodeID="NukVOfZA183"/> - <_3:hasFile rdf:nodeID="NukVOfZA369"/> - <_3:hasFile rdf:nodeID="NukVOfZA265"/> - <_3:hasFile rdf:nodeID="NukVOfZA305"/> - <_3:hasFile rdf:nodeID="NukVOfZA51"/> - <_3:hasFile rdf:nodeID="NukVOfZA113"/> - <_3:hasFile rdf:nodeID="NukVOfZA13"/> - <_3:hasFile rdf:nodeID="NukVOfZA43"/> - <_3:hasFile rdf:nodeID="NukVOfZA133"/> - <_3:hasFile rdf:nodeID="NukVOfZA383"/> - <_3:hasFile rdf:nodeID="NukVOfZA251"/> - <_3:hasFile rdf:nodeID="NukVOfZA55"/> - <_3:hasFile rdf:nodeID="NukVOfZA295"/> - <_3:hasFile rdf:nodeID="NukVOfZA401"/> - <_3:hasFile rdf:nodeID="NukVOfZA433"/> - <_3:hasFile rdf:nodeID="NukVOfZA161"/> - <_3:hasFile rdf:nodeID="NukVOfZA299"/> - <_3:hasFile rdf:nodeID="NukVOfZA95"/> - <_3:hasFile rdf:nodeID="NukVOfZA107"/> - <_3:hasFile rdf:nodeID="NukVOfZA227"/> - <_3:hasFile rdf:nodeID="NukVOfZA323"/> - <_3:hasFile rdf:nodeID="NukVOfZA333"/> - <_3:hasFile rdf:nodeID="NukVOfZA105"/> - <_3:hasFile rdf:nodeID="NukVOfZA443"/> - <_3:hasFile rdf:nodeID="NukVOfZA153"/> - <_3:hasFile rdf:nodeID="NukVOfZA141"/> - <_3:hasFile rdf:nodeID="NukVOfZA353"/> - <_3:hasFile rdf:nodeID="NukVOfZA9"/> - <_3:hasFile rdf:nodeID="NukVOfZA281"/> - <_3:hasFile rdf:nodeID="NukVOfZA11"/> - <_3:hasFile rdf:nodeID="NukVOfZA385"/> - <_3:hasFile rdf:nodeID="NukVOfZA229"/> - <_3:hasFile rdf:nodeID="NukVOfZA297"/> - <_3:hasFile rdf:nodeID="NukVOfZA405"/> - <_3:hasFile rdf:nodeID="NukVOfZA151"/> - <_3:hasFile rdf:nodeID="NukVOfZA165"/> - <_3:hasFile rdf:nodeID="NukVOfZA67"/> - <_3:hasFile rdf:nodeID="NukVOfZA115"/> - <_3:hasFile rdf:nodeID="NukVOfZA65"/> - <_3:hasFile rdf:nodeID="NukVOfZA49"/> - <_3:hasFile rdf:nodeID="NukVOfZA263"/> - <_3:hasFile rdf:nodeID="NukVOfZA125"/> - <_3:hasFile rdf:nodeID="NukVOfZA91"/> - <_3:hasFile rdf:nodeID="NukVOfZA19"/> - <_3:hasFile rdf:nodeID="NukVOfZA283"/> - <_3:hasFile rdf:nodeID="NukVOfZA349"/> - <_3:hasFile rdf:nodeID="NukVOfZA173"/> - <_3:hasFile rdf:nodeID="NukVOfZA355"/> - <_3:hasFile rdf:nodeID="NukVOfZA303"/> - <_3:hasFile rdf:nodeID="NukVOfZA441"/> - <_3:hasFile rdf:nodeID="NukVOfZA357"/> - <_3:hasFile rdf:nodeID="NukVOfZA195"/> - <_3:hasFile rdf:nodeID="NukVOfZA225"/> - <_3:hasFile rdf:nodeID="NukVOfZA57"/> - <_3:hasFile rdf:nodeID="NukVOfZA121"/> - <_3:hasFile rdf:nodeID="NukVOfZA453"/> - <_3:hasFile rdf:nodeID="NukVOfZA415"/> - <_3:hasFile rdf:nodeID="NukVOfZA261"/> - <_3:hasFile rdf:nodeID="NukVOfZA301"/> - <_3:hasFile rdf:nodeID="NukVOfZA391"/> - <_3:hasFile rdf:nodeID="NukVOfZA17"/> - <_3:hasFile rdf:nodeID="NukVOfZA245"/> - <_3:hasFile rdf:nodeID="NukVOfZA71"/> - <_3:hasFile rdf:nodeID="NukVOfZA129"/> - <_3:hasFile rdf:nodeID="NukVOfZA293"/> - <_3:hasFile rdf:nodeID="NukVOfZA31"/> - <_3:hasFile rdf:nodeID="NukVOfZA119"/> - <_3:hasFile rdf:nodeID="NukVOfZA219"/> - <_3:hasFile rdf:nodeID="NukVOfZA451"/> - <_3:hasFile rdf:nodeID="NukVOfZA145"/> - <_3:hasFile rdf:nodeID="NukVOfZA73"/> - <_3:hasFile rdf:nodeID="NukVOfZA37"/> - <_3:hasFile rdf:nodeID="NukVOfZA87"/> - <_3:hasFile rdf:nodeID="NukVOfZA247"/> - <_3:hasFile rdf:nodeID="NukVOfZA99"/> - <_3:hasFile rdf:nodeID="NukVOfZA47"/> - <_3:hasFile rdf:nodeID="NukVOfZA413"/> - <_3:hasFile rdf:nodeID="NukVOfZA155"/> - <_3:hasFile rdf:nodeID="NukVOfZA313"/> - <_3:hasFile rdf:nodeID="NukVOfZA315"/> - <_3:hasFile rdf:nodeID="NukVOfZA149"/> - <_3:description>Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint - - - - <_3:checksumValue>2cdc31948853f9f0bf0d5f726b6034c508ee9d67 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_forwdecl.h - <_3:checksum rdf:nodeID="NukVOfZA240"/> - - - - <_3:checksumValue>e2a167fd8048cbd7c85fd62da70749b2a0109b2a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src/duktape.h - <_3:checksum rdf:nodeID="NukVOfZA454"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eval/eval.c - <_3:checksum rdf:nodeID="NukVOfZA116"/> - - - - <_3:checksumValue>a8e7b9b9bed773ecc7e08f4b73716dad741fd50b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>4ee4843558692861cb91a6c6906539795b639091 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/main.c - <_3:checksum rdf:nodeID="NukVOfZA84"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.eventloop - <_3:checksum rdf:nodeID="NukVOfZA32"/> - - - - <_3:checksumValue>d84a903a426cf3a158072565161c35240a1c68e5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>206ffd13c06208e85baba2b257fe3ddebb56a6c2 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>6b150b9183cc8453536713de0d1e79adc21a3fee - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/curses-timers.js - <_3:checksum rdf:nodeID="NukVOfZA100"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/duk_opcodes.yaml - <_3:checksum rdf:nodeID="NukVOfZA48"/> - - - - <_3:checksumValue>bd2f85dccd23b76b9cf9900b8b2b86f0bf97421b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>e4d3286030d5ef1e74dd07a5b2efa37cd907697e - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>d48fe743ca18b8b3205d6443a08463d6b0334153 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>61043b4a6f3cf86375ea6e34ebf83b550a1935b2 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./polyfills/object-prototype-definegetter.js - <_3:checksum rdf:nodeID="NukVOfZA426"/> - - - - <_3:checksumValue>063133679b6d072efc1c27f3a510101744ffde0c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>ca663612967cb12b33d666180d7bb3008314ca7a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.sandbox - <_3:checksum rdf:nodeID="NukVOfZA24"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_tval.c - <_3:checksum rdf:nodeID="NukVOfZA398"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject.h - <_3:checksum rdf:nodeID="NukVOfZA352"/> - - - - <_3:checksumValue>786369a33cccbadc3d2efba613a43fdd638971fc - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>f5251445a782e4bfac8af043f24ecbac740f67eb - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>1bce4dadb408a2a6a77b366f0ecfc18398cbb722 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>f65888efe272f584113d4df273cc6e7a5c5a43dd - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>df7b9fe732c2bc300d096c06d90bbdc71fada213 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_global.c - <_3:checksum rdf:nodeID="NukVOfZA200"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./AUTHORS.rst - <_3:checksum rdf:nodeID="NukVOfZA26"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/ecma_eventloop.js - <_3:checksum rdf:nodeID="NukVOfZA98"/> - - - - <_3:checksumValue>b54cd58e7947b2899eb8662d2cdaf022dd680ea6 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>ea1ee74bace7e1958d0049c1035b3832ef951e82 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>6d0092ec677f2d4aa5c91cf9f71d8aca5171c8e2 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/alloc-hybrid/duk_alloc_hybrid.c - <_3:checksum rdf:nodeID="NukVOfZA70"/> - - - - <_3:checksumValue>41f24f22ab9039c1f9a548fb75c9639453380065 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>ea413ed7d47cf27c6f3ffe25956b1370b653c200 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>d869c0f8797a659124b3ba31c75f494b15bea5e6 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_call.c - <_3:checksum rdf:nodeID="NukVOfZA226"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/debug-trans-socket/duk_trans_socket.h - <_3:checksum rdf:nodeID="NukVOfZA148"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_builtins.h - <_3:checksum rdf:nodeID="NukVOfZA182"/> - - - - <_3:checksumValue>2c811905f5b8781c8b70d099687773a8d20ce082 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_config.h - <_3:checksum rdf:nodeID="NukVOfZA336"/> - - - - <_3:checksumValue>9bb6ca1fa3ad4c593b000b2de5aca013b95adda0 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>b298f68a888cec4efea00f221053645a59748c18 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>4e5a54de08355669dc98b5d4ad379384b33da4e5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>2878666c896a9a9a4dddefd943c0ddf3a09310a4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>07a167411a356aebfbe987353846a9c711998f20 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_thread.c - <_3:checksum rdf:nodeID="NukVOfZA394"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/debug-trans-dvalue/Makefile - <_3:checksum rdf:nodeID="NukVOfZA158"/> - - - - <_3:checksumValue>27813a75f3f27a0dcdf51e269582a97679585827 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>9a31edd2028d39d24aa9bfdbd2b70ce2a64b8493 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_stack.c - <_3:checksum rdf:nodeID="NukVOfZA404"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_jmpbuf.h - <_3:checksum rdf:nodeID="NukVOfZA190"/> - - - - <_3:checksumValue>5a72a639353c2f9e3bfb1c369246775ecd6f005e - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_unicode.h - <_3:checksum rdf:nodeID="NukVOfZA222"/> - - - - <_3:checksumValue>a2c79a55a60f73e1a1567b96d584399571180ef5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>09ee87b3ae8afe8b7c2295127835b05b00603b25 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/alloc-torture/duk_alloc_torture.h - <_3:checksum rdf:nodeID="NukVOfZA136"/> - - - - <_3:checksumValue>6b097ba4583a27d31c21b60cb15770804dd1ba9d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>29be453689679c9bab977c0b333a4a224d9f02e6 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./config/README.rst - <_3:checksum rdf:nodeID="NukVOfZA440"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debug_vsnprintf.c - <_3:checksum rdf:nodeID="NukVOfZA308"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/alloc-logging/log2gnuplot.py - <_3:checksum rdf:nodeID="NukVOfZA170"/> - - - - <_3:checksumValue>5d56f0bab3e87abdca8da4d6e8580cb9132fd697 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>5f3b6cd81be97aa687fe8b47751e68b5561d7c1b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>b6cf7cd6cdf526aa3cf60144c6a9569e6d112f36 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/alloc-logging/duk_alloc_logging.c - <_3:checksum rdf:nodeID="NukVOfZA168"/> - - - - <_3:checksumValue>7edf7600e1a6f09d1e4a0e2f9be418b59fff7c52 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>16a4c10bea273a74018fa0a7a8889b7b43a3119b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>0053a77d6c3562af6d2238f096f3a9bd4b5a834f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/coffee/hello.coffee - <_3:checksum rdf:nodeID="NukVOfZA60"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.eval - <_3:checksum rdf:nodeID="NukVOfZA30"/> - - - - <_3:checksumValue>b2872f0cbb3cbe10184bbc3a95b1d7c365b8ed32 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>a5afcd26ab65a29d95a6e33bf0f33645ee4fd91b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./polyfills/performance-now.js - <_3:checksum rdf:nodeID="NukVOfZA436"/> - - - - <_3:checksumValue>32a98d7fe78d83f08173234229f862698fce2090 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duktape.h - <_3:checksum rdf:nodeID="NukVOfZA408"/> - - - - <_3:checksumValue>02b01faf5220448b3d678abba34a0a9be96d71ca - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>ff17cbc9cb84b86f83bb104a247e5c265a9fe5b5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.dukdebug - <_3:checksum rdf:nodeID="NukVOfZA28"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/guide/prime.js - <_3:checksum rdf:nodeID="NukVOfZA130"/> - - - - <_3:checksumValue>14ec83aeef66a38c6a4c48a175a544f66d319413 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_pointer.c - <_3:checksum rdf:nodeID="NukVOfZA422"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_unicode_tables.c - <_3:checksum rdf:nodeID="NukVOfZA278"/> - - - - <_3:checksumValue>29b1960bc40607c2cf496465068611b2ffc4de87 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>b398df12e0b18a0e3edca6c4d55f7575cea9a76a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>f437b6a49e9ad85f1bed504b9d7724358eb37ad8 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_var.c - <_3:checksum rdf:nodeID="NukVOfZA402"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_date_windows.c - <_3:checksum rdf:nodeID="NukVOfZA376"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./mandel.js - <_3:checksum rdf:nodeID="NukVOfZA16"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_alloc.c - <_3:checksum rdf:nodeID="NukVOfZA360"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_regexp_executor.c - <_3:checksum rdf:nodeID="NukVOfZA184"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debugger.c - <_3:checksum rdf:nodeID="NukVOfZA384"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_stringtable.c - <_3:checksum rdf:nodeID="NukVOfZA252"/> - - - - <_3:checksumValue>11f16b15a8e52598a078b88a8d0440ff61dd5ba2 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>1eb3bb219637be52abe8a154551ec76bfc5ecf31 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hthread_alloc.c - <_3:checksum rdf:nodeID="NukVOfZA334"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./extras/README.rst - <_3:checksum rdf:nodeID="NukVOfZA444"/> - - - - <_3:checksumValue>58c701ade28ee5a475dede84a6e771893e3fc40f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_array.c - <_3:checksum rdf:nodeID="NukVOfZA354"/> - - - - <_3:checksumValue>6961515d6681b7dfb59d2d080b87cdeb2a673025 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_replacements.h - <_3:checksum rdf:nodeID="NukVOfZA282"/> - - - - <_3:checksumValue>89ce4d46fcef5a35b3b6652d79ebe556b121d2a8 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_bytecode.h - <_3:checksum rdf:nodeID="NukVOfZA230"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_hashbytes.c - <_3:checksum rdf:nodeID="NukVOfZA406"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/static/style.css - <_3:checksum rdf:nodeID="NukVOfZA50"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.coffee - <_3:checksum rdf:nodeID="NukVOfZA20"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src/duk_config.h - <_3:checksum rdf:nodeID="NukVOfZA450"/> - - - - <_3:checksumValue>3948c3f17d6863157361cb817b6bc7bf7799122f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_compile.c - <_3:checksum rdf:nodeID="NukVOfZA358"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/coffee/mandel.coffee - <_3:checksum rdf:nodeID="NukVOfZA58"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debug_fixedbuffer.c - <_3:checksum rdf:nodeID="NukVOfZA416"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_date.c - <_3:checksum rdf:nodeID="NukVOfZA246"/> - - - - <_3:checksumValue>4d3ab8c2d41261b0cae627db9d536d26f72b5f8e - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_bufwriter.c - <_3:checksum rdf:nodeID="NukVOfZA186"/> - - - - <_3:checksumValue>4588ca1842f93e72254f9b428d6d07ad22b57163 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/cmdline/README.rst - <_3:checksum rdf:nodeID="NukVOfZA146"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/ncurses.c - <_3:checksum rdf:nodeID="NukVOfZA88"/> - - - - <_3:checksumValue>d90697f65158589fb137e9a48cbf288bde2ef230 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/debug-trans-dvalue/README.rst - <_3:checksum rdf:nodeID="NukVOfZA156"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hcompiledfunction.h - <_3:checksum rdf:nodeID="NukVOfZA304"/> - - - - <_3:checksumValue>a9db75839022e7dcf7e691ada7480a9b7c2715d0 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>3d700df1f765c39fc63bfd4e31a9d7da8d15c543 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hthread_builtins.c - <_3:checksum rdf:nodeID="NukVOfZA270"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/coffee/README.rst - <_3:checksum rdf:nodeID="NukVOfZA62"/> - - - - <_3:checksumValue>5f89525f75f61dd8c89e010cb62bc071d6d13170 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>7b236da6f48b6f6aef43e6c959b43edaa8120ff4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>ad475950dc26e62ba57f5bfa266687681b09e10f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>fa85ee3394206d18c611b837e700257ba8336250 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debug_macros.c - <_3:checksum rdf:nodeID="NukVOfZA424"/> - - - - <_3:checksumValue>8521b45dcbc72d66c2b4e3f0db9e1dbfb75b45f5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_memory.c - <_3:checksum rdf:nodeID="NukVOfZA318"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hstring_misc.c - <_3:checksum rdf:nodeID="NukVOfZA208"/> - - - - <_3:checksumValue>2c2b647e4cf2c94e91f5193987a01a029bf01690 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.jxpretty - <_3:checksum rdf:nodeID="NukVOfZA34"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_regexp.c - <_3:checksum rdf:nodeID="NukVOfZA372"/> - - - - <_3:checksumValue>484fb41d516abcbe8c97af5aa80b76c67dbfb0cb - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>7108fbe42728e2fe1c2448b119a6a1f52568ce53 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/jxpretty/jxpretty.c - <_3:checksum rdf:nodeID="NukVOfZA82"/> - - - - <_3:checksumValue>3c10dd228daad9be3ea381c2f8b1e07e524fae6f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_boolean.c - <_3:checksum rdf:nodeID="NukVOfZA342"/> - - - - <_3:checksumValue>fb4f806e7282dd3cb2df04e228672d8b0b1b8eb4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_error_misc.c - <_3:checksum rdf:nodeID="NukVOfZA316"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_error.c - <_3:checksum rdf:nodeID="NukVOfZA176"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_enum.c - <_3:checksum rdf:nodeID="NukVOfZA194"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/guide/README.rst - <_3:checksum rdf:nodeID="NukVOfZA118"/> - - - - <_3:checksumValue>2e9dca0919a92c68ed30593292b3fe7140480062 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_strings.h - <_3:checksum rdf:nodeID="NukVOfZA378"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/codepage-conv/test.c - <_3:checksum rdf:nodeID="NukVOfZA76"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.codepage - <_3:checksum rdf:nodeID="NukVOfZA22"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/dummy-date-provider/dummy_date_provider.c - <_3:checksum rdf:nodeID="NukVOfZA112"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./config/genconfig.py - <_3:checksum rdf:nodeID="NukVOfZA438"/> - - - - <_3:checksumValue>dfaa38c7372de482fd12634e4a3507f46e467e0f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>982e40839854be361e3b57b5c07ef4f710ab749b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>0811e545a133c3a62672e239624a0c1f11478b8d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>0fd79121cfa729c2dd3e47632ec46204609013ef - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/jxpretty/README.rst - <_3:checksum rdf:nodeID="NukVOfZA80"/> - - - - <_3:checksumValue>f9072f5c361c86887b57ce662b3cd7211b4ce346 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/alloc-torture/README.rst - <_3:checksum rdf:nodeID="NukVOfZA132"/> - - - - <_3:checksumValue>d49c1cdb51b3a4fdd823c13831617a1f0a93edd1 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_stringcache.c - <_3:checksum rdf:nodeID="NukVOfZA420"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_alloc_default.c - <_3:checksum rdf:nodeID="NukVOfZA418"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/cmdline/duk_cmdline.c - <_3:checksum rdf:nodeID="NukVOfZA144"/> - - - - <_3:checksumValue>506914e460ff9d7536f10efef54b24b83c390410 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debugger.h - <_3:checksum rdf:nodeID="NukVOfZA364"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_heap.c - <_3:checksum rdf:nodeID="NukVOfZA290"/> - - - - <_3:checksumValue>1c45360bd50cff6c2c25087d52136b390179e8fc - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>bf522799f089bf27e5ef2196b73c7e3d294ee5ba - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_object.c - <_3:checksum rdf:nodeID="NukVOfZA400"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/poll.c - <_3:checksum rdf:nodeID="NukVOfZA104"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_buffer.c - <_3:checksum rdf:nodeID="NukVOfZA380"/> - - - - <_3:checksumValue>11a7a5b6b1557adeca8a9def51cb44282f24c853 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_error_longjmp.c - <_3:checksum rdf:nodeID="NukVOfZA254"/> - - - - <_3:checksumValue>8aa63b553757fe1229638e978b540d7116b70274 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>23b6b54a8a35fbec735ffb332f4100a7f00557be - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_lexer.c - <_3:checksum rdf:nodeID="NukVOfZA228"/> - - - - <_3:checksumValue>61c7f89aa56094410418e766c89c1975db021daa - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>bf5a69136d03c3a573822dc1fe6e595a92c5d9b5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>4d3413b7b28775afc4a5be95e91208fab25b02f3 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_thrower.c - <_3:checksum rdf:nodeID="NukVOfZA338"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_internal.h - <_3:checksum rdf:nodeID="NukVOfZA260"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_numconv.c - <_3:checksum rdf:nodeID="NukVOfZA382"/> - - - - <_3:checksumValue>76fafefbb89d1d3561a44bf6c253415ab86633f7 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_error_throw.c - <_3:checksum rdf:nodeID="NukVOfZA178"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/static/index.html - <_3:checksum rdf:nodeID="NukVOfZA54"/> - - - - <_3:checksumValue>d8fe87c8e0d17bd6977bbc34d562e4b79c06f1a3 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>3a4934f863facf317ffcc1a6ce1d8f17ac658f38 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./LICENSE.txt - <_3:checksum rdf:nodeID="NukVOfZA8"/> - - - - <_3:checksumValue>24a2346fa389c2294cc0e96427e0bd206dac10b9 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_tinyrandom.c - <_3:checksum rdf:nodeID="NukVOfZA280"/> - - - - <_3:checksumValue>4239a907720cf3620bd0b03eb43981e7182e305a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>578b63fa72c87e894a47a9f82102ecee895f932f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>628eded8d5c2a48cb32a615bb7f11f164c949540 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heaphdr.h - <_3:checksum rdf:nodeID="NukVOfZA386"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_bytecode.c - <_3:checksum rdf:nodeID="NukVOfZA328"/> - - - - <_3:checksumValue>742635fda10ef9775864077e647b59442768a69c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src/duktape.c - <_3:checksum rdf:nodeID="NukVOfZA452"/> - - - - <_3:checksumValue>533dd2148cf54628be701ce5bbbda88c443244fd - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/alloc-torture/duk_alloc_torture.c - <_3:checksum rdf:nodeID="NukVOfZA134"/> - - - - <_3:checksumValue>439430cb950965d418b5bcb4ca36047f77a26a7c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>925915ad11fea8da4582dbd9bc9e8b5ffbb8994d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_compiler.h - <_3:checksum rdf:nodeID="NukVOfZA300"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/fileio.c - <_3:checksum rdf:nodeID="NukVOfZA96"/> - - - - <_3:checksumValue>c2a8bb08084e49f0e12d31562a90f72046761028 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>bce447cad4609861c4db6edbfe38bf2fa150e651 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>2321e0a68bf940f8346d00adda9e4a58fa51f608 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>839ade6f7b93fd0fc604e3e0934568331eedd648 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>a9206a7b46f8d8319b798475650217f494fa76ab - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/alloc-hybrid/duk_alloc_hybrid.h - <_3:checksum rdf:nodeID="NukVOfZA66"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_strings.c - <_3:checksum rdf:nodeID="NukVOfZA220"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_math.c - <_3:checksum rdf:nodeID="NukVOfZA264"/> - - - - <_3:checksumValue>0125ebcabe62cef4923e75527d3128e8c48cdf1f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>bfbf3b8ea996451740a7ad2d8d1376feca4ca382 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_codec.c - <_3:checksum rdf:nodeID="NukVOfZA356"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./polyfills/object-prototype-definesetter.js - <_3:checksum rdf:nodeID="NukVOfZA430"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/sandbox/sandbox.c - <_3:checksum rdf:nodeID="NukVOfZA164"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/socket.c - <_3:checksum rdf:nodeID="NukVOfZA90"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_buffer.c - <_3:checksum rdf:nodeID="NukVOfZA302"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hthread_stacks.c - <_3:checksum rdf:nodeID="NukVOfZA292"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.cmdline - <_3:checksum rdf:nodeID="NukVOfZA18"/> - - - - <_3:checksumValue>4db4ca2d7ce3f076fd195372d53e8bc5714d2597 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>813eed354904f72d97568c814fbcf5fffbb62d12 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/alloc-logging/duk_alloc_logging.h - <_3:checksum rdf:nodeID="NukVOfZA172"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hnativefunction.h - <_3:checksum rdf:nodeID="NukVOfZA294"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/guide/processlines.c - <_3:checksum rdf:nodeID="NukVOfZA120"/> - - - - <_3:checksumValue>c000aebe8b6794338529fdf6e02c0cfdcf4d2dfc - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>2c508fbc7eb127f6793cfe62bf947879668983a4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/README.rst - <_3:checksum rdf:nodeID="NukVOfZA38"/> - - - - <_3:checksumValue>b4c9666ce152c9a98bf965aae4ef4fe0b36b2130 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>b4d00dadc78f1ac25d87d8d7a48fd67161235d4f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debug_heap.c - <_3:checksum rdf:nodeID="NukVOfZA414"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js_var.c - <_3:checksum rdf:nodeID="NukVOfZA314"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/debug-trans-socket/README.rst - <_3:checksum rdf:nodeID="NukVOfZA150"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_debug.h - <_3:checksum rdf:nodeID="NukVOfZA340"/> - - - - <_3:checksumValue>6988aac432dcc185c2967732e21947ea0696377f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./licenses/commonjs.txt - <_3:checksum rdf:nodeID="NukVOfZA448"/> - - - - <_3:checksumValue>878e91bed3a8756c70aaa43bb1566040fe6e42f0 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hstring.h - <_3:checksum rdf:nodeID="NukVOfZA256"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_json.c - <_3:checksum rdf:nodeID="NukVOfZA268"/> - - - - <_3:checksumValue>e023af5c2fb4b1efab74a230c552f1eb1b37fc10 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>e44b8b092afcfa97e693eb3e0be97d41f8aff301 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>2eadae5af69aec5e3336b6a869fe64771d4db080 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>935644ce5c2bcd1f9b725c742a91dd34ec7c7fc3 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>13d0e469fd05cef5066b33ad1310658e4cf5c7c8 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>f1dee4b05f535519fbf3662469c2ce810b6e2545 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_tval.h - <_3:checksum rdf:nodeID="NukVOfZA332"/> - - - - <_3:checksumValue>635d4642c9ecd5fd9a5346bf9f0e38db102b09b6 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>7502f77b459c82f4e9a45ecdde05125d79153bdf - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>042bfc66d9b0f01ce8075818959c9a72c35b4bb4 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./polyfills/object-assign.js - <_3:checksum rdf:nodeID="NukVOfZA428"/> - - - - <_3:checksumValue>5e8812e8226d2ec0387af6e2ce9565755e274164 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>56a4e5fbd50d1b9917625a0dfcf6e2619b034786 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>8015d14ffbc7a4a4b93d654f093aa48ec17fce4e - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>73ff75213f392b6125c68ab6b430176dfad71269 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>a20231719c1f9b97ea38fbc42dd8af1e21d74879 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap_memory.c - <_3:checksum rdf:nodeID="NukVOfZA368"/> - - - - <_3:checksumValue>949e147e9b5e284590449d0e8f74427c8c12f00f - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hthread_misc.c - <_3:checksum rdf:nodeID="NukVOfZA210"/> - - - - <_3:checksumValue>c1036bb5992816ffb09e8b2ee24f082a881326e9 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_js.h - <_3:checksum rdf:nodeID="NukVOfZA212"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/coffee/globals.coffee - <_3:checksum rdf:nodeID="NukVOfZA64"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_error_augment.c - <_3:checksum rdf:nodeID="NukVOfZA288"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hthread.h - <_3:checksum rdf:nodeID="NukVOfZA320"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/hello/hello.c - <_3:checksum rdf:nodeID="NukVOfZA138"/> - - - - <_3:checksumValue>af6b0cd61c02efa575b9106682606297d26f013b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>57f519aabc8730f19d197bd00fe7e4f592063ddf - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./polyfills/console-minimal.js - <_3:checksum rdf:nodeID="NukVOfZA434"/> - - - - <_3:checksumValue>1e6c5c99fdcef26a561724faa703bf9c53c73bca - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_string.c - <_3:checksum rdf:nodeID="NukVOfZA242"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_logging.c - <_3:checksum rdf:nodeID="NukVOfZA262"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/basic-test.js - <_3:checksum rdf:nodeID="NukVOfZA102"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_regexp.h - <_3:checksum rdf:nodeID="NukVOfZA236"/> - - - - <_3:checksumValue>12da70c807ea25465e5e0191784203ff6a1c7d0c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>10c24a17c2f5f82d8c1a8fab8673c0c9075c1817 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/dummy-date-provider/README.rst - <_3:checksum rdf:nodeID="NukVOfZA110"/> - - - - <_3:checksumValue>b2f66f393c178e011c068b230f17ef8a48b4ee29 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_heap.h - <_3:checksum rdf:nodeID="NukVOfZA232"/> - - - - <_3:checksumValue>0aee8a99ab7468ae7254d0b19f898a7c67f24c4d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>22046b9dfc552ed692193d1bf5e3d0e182111ae5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_date_unix.c - <_3:checksum rdf:nodeID="NukVOfZA204"/> - - - - <_3:checksumValue>149fd21526c90d52b22e77b297f76e6da3e656ff - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/Makefile - <_3:checksum rdf:nodeID="NukVOfZA40"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_error_macros.c - <_3:checksum rdf:nodeID="NukVOfZA344"/> - - - - <_3:checksumValue>c8ae046bda2c920b5d807dfa68c8159b655b0873 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>3e4c09bd49dbe5d8509da6f2387eadfca945126c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>b381ea15009eb8140c0789203345cdcc2c6c1cd6 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/guide/primecheck.c - <_3:checksum rdf:nodeID="NukVOfZA128"/> - - - - <_3:checksumValue>f79f6933571dcdd7108447f6e8e86f4735b30caf - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>5583c0190c2038be60ba2de07d155d5077defb03 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/codepage-conv/README.rst - <_3:checksum rdf:nodeID="NukVOfZA72"/> - - - - <_3:checksumValue>a1b146201fb105044a9922781e22d14bcbd5584c - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>5d593ae6316ed7a3ea6e7ed0a47267745d79d12d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>136f423bdc27f3effc1e45c44327c1d3ef82f0d9 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>bf80565339b6d9eb92f7e8b35420317cf00392f1 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_alloc.c - <_3:checksum rdf:nodeID="NukVOfZA238"/> - - - - <_3:checksumValue>36b07bc32cf613c091d5e4261cbe44b0556704fd - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>01138dd2786346a159c06e43f094d07f002df881 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/hello/README.rst - <_3:checksum rdf:nodeID="NukVOfZA140"/> - - - - <_3:checksumValue>edc510f4b2921d24eb9bc37ee0dd4a3d42743083 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/duk_debugcommands.yaml - <_3:checksum rdf:nodeID="NukVOfZA42"/> - - - - <_3:checksumValue>88ab1d060886393d94b6fb7c6054a0189117340b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hbuffer_ops.c - <_3:checksum rdf:nodeID="NukVOfZA348"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_protos.h - <_3:checksum rdf:nodeID="NukVOfZA274"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_bitencoder.c - <_3:checksum rdf:nodeID="NukVOfZA362"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_props.c - <_3:checksum rdf:nodeID="NukVOfZA224"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./licenses/murmurhash2.txt - <_3:checksum rdf:nodeID="NukVOfZA446"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./debugger/duk_classnames.yaml - <_3:checksum rdf:nodeID="NukVOfZA46"/> - - - - <_3:checksumValue>f396c6aec456b183ef77e33da1dfffc89c417056 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>23575db7cd88e42c0c3fc1630f44bf608fcec76d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>b0916311103fdea3fd5bbf76a99748a3d21a5486 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>1c40a52fd54baf7ac334fce4829892d5d951401a - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>83b27494e6b257ab09828b0a4a1cf907686778a5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./Makefile.hello - <_3:checksum rdf:nodeID="NukVOfZA14"/> - - - - <_3:checksumValue>71d2f9df7bf793f80f3cd6080c986a437f9b2991 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/README.rst - <_3:checksum rdf:nodeID="NukVOfZA56"/> - - - - <_3:checksumValue>c8d7674f8215d515779d2cfaf61105c4d2fd5eb5 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>8c5ee5b508a23ac5089a7e6c76593b6678965869 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/debug-trans-dvalue/test.c - <_3:checksum rdf:nodeID="NukVOfZA162"/> - - - - <_3:checksumValue>d45e3fc443887261ce432a807aaebd2a1812264e - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>57f519aabc8730f19d197bd00fe7e4f592063ddf - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_bi_logger.c - <_3:checksum rdf:nodeID="NukVOfZA276"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/debug-trans-dvalue/duk_trans_dvalue.h - <_3:checksum rdf:nodeID="NukVOfZA154"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/cmdline/duk_cmdline_ajduk.c - <_3:checksum rdf:nodeID="NukVOfZA142"/> - - - - <_3:checksumValue>ba20a4d987de1eef311c99f21db6621cb4b1a5d1 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hbufferobject.h - <_3:checksum rdf:nodeID="NukVOfZA370"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_api_object.c - <_3:checksum rdf:nodeID="NukVOfZA324"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/debug-trans-socket/duk_trans_socket.c - <_3:checksum rdf:nodeID="NukVOfZA152"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/> - <_3:fileName>./examples/sandbox/README.rst - <_3:checksum rdf:nodeID="NukVOfZA166"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_finalizer.c - <_3:checksum rdf:nodeID="NukVOfZA216"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/guide/process.js - <_3:checksum rdf:nodeID="NukVOfZA126"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/eventloop/c_eventloop.c - <_3:checksum rdf:nodeID="NukVOfZA92"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_unicode_support.c - <_3:checksum rdf:nodeID="NukVOfZA180"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_util_hashprime.c - <_3:checksum rdf:nodeID="NukVOfZA284"/> - - - - <_3:checksumValue>37e22b43351b7f0518b7fbb9e5c109d7a53a31e7 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>fb9c2ff459fd84b4587f846fbd36219cf8f06931 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>d529a6faac560def1e5b2cdb991713a6d70b0e26 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>f3ed5c785b60b0f39a74cc3f5b73b0c6e24287c3 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>34b0dc439c1aeb920a1db0ac0ed20ee189069ea1 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>111a7b97b46f038bd7f0f260ef5c9ff66c057217 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_hobject_class.c - <_3:checksum rdf:nodeID="NukVOfZA272"/> - - - - <_3:checksumValue>ed3bd07dbd103d285277ab38c4b4a7dd4a4b654b - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_builtins.c - <_3:checksum rdf:nodeID="NukVOfZA248"/> - - - - <_3:checksumValue>6fec920096ab278342b4832aac85e480f47c3b69 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>767b33200578243befc9b2b6b4a579dc3784f748 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>84b3f74e55ed4d76634e144d668601480573b369 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./examples/codepage-conv/duk_codepage_conv.c - <_3:checksum rdf:nodeID="NukVOfZA74"/> - - - - <_3:checksumValue>6f12665affb325d53ab11c0e40418b2326c1ac17 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>2b7443b734ad4f6e53e2f35e5aff74464410a680 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/> - <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/> - <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable) - <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/> - <_3:fileName>./src-separate/duk_error.h - <_3:checksum rdf:nodeID="NukVOfZA198"/> - - - - <_3:checksumValue>a2896c39c83a21a2f79d0c4babd5012d85873116 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>3c8a488f2b4195d33379874172ae6d8b74beaa58 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>d535c4e27319a5db6026553a801e8a5ef0e6fe88 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>4baffeb2aa785bdc1065eb9ddb8c64c8a028655d - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - - - <_3:checksumValue>0783cf4f48c9baf2b3820a36ab276b01e2102600 - <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/> - - diff --git a/src/third_party/duktape-1.3.0/licenses/commonjs.txt b/src/third_party/duktape-1.3.0/licenses/commonjs.txt deleted file mode 100644 index 54a1cd7b..00000000 --- a/src/third_party/duktape-1.3.0/licenses/commonjs.txt +++ /dev/null @@ -1,2 +0,0 @@ -CommonJS specification snapshots are included in the references/ -directory. CommonJS is under the MIT license: http://www.commonjs.org/. diff --git a/src/third_party/duktape-1.3.0/licenses/murmurhash2.txt b/src/third_party/duktape-1.3.0/licenses/murmurhash2.txt deleted file mode 100644 index 70299256..00000000 --- a/src/third_party/duktape-1.3.0/licenses/murmurhash2.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/third_party/duktape-1.3.0/mandel.js b/src/third_party/duktape-1.3.0/mandel.js deleted file mode 100644 index 79b5195b..00000000 --- a/src/third_party/duktape-1.3.0/mandel.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Mandelbrot example: - * - * $ ./duk mandel.js - * [...] - */ - -function mandel() { - var w = 76, h = 28, iter = 100; - var i, j, k, c; - var x0, y0, xx, yy, xx2, yy2; - var line; - - for (i = 0; i < h; i++) { - y0 = (i / h) * 2.5 - 1.25; - - for (j = 0, line = []; j < w; j++) { - x0 = (j / w) * 3.0 - 2.0; - - for (k = 0, xx = 0, yy = 0, c = '#'; k < iter; k++) { - /* z -> z^2 + c - * -> (xx+i*yy)^2 + (x0+i*y0) - * -> xx*xx+i*2*xx*yy-yy*yy + x0 + i*y0 - * -> (xx*xx - yy*yy + x0) + i*(2*xx*yy + y0) - */ - - xx2 = xx*xx; yy2 = yy*yy; - - if (xx2 + yy2 < 4.0) { - yy = 2*xx*yy + y0; - xx = xx2 - yy2 + x0; - } else { - /* xx^2 + yy^2 >= 4.0 */ - if (k < 3) { c = '.'; } - else if (k < 5) { c = ','; } - else if (k < 10) { c = '-'; } - else { c = '='; } - break; - } - } - - line.push(c); - } - - print(line.join('')); - } -} - -try { - mandel(); -} catch (e) { - print(e.stack || e); -} diff --git a/src/third_party/duktape-1.3.0/polyfills/console-minimal.js b/src/third_party/duktape-1.3.0/polyfills/console-minimal.js deleted file mode 100644 index 1876c5fd..00000000 --- a/src/third_party/duktape-1.3.0/polyfills/console-minimal.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Minimal console.log() polyfill - */ - -if (typeof console === 'undefined') { - Object.defineProperty(this, 'console', { - value: {}, writable: true, enumerable: false, configurable: true - }); -} -if (typeof console.log === 'undefined') { - (function () { - var origPrint = print; // capture in closure in case changed later - Object.defineProperty(this.console, 'log', { - value: function () { - var strArgs = Array.prototype.map.call(arguments, function (v) { return String(v); }); - origPrint(Array.prototype.join.call(strArgs, ' ')); - }, writable: true, enumerable: false, configurable: true - }); - })(); -} diff --git a/src/third_party/duktape-1.3.0/polyfills/duktape-isfastint.js b/src/third_party/duktape-1.3.0/polyfills/duktape-isfastint.js deleted file mode 100644 index dce2d9ed..00000000 --- a/src/third_party/duktape-1.3.0/polyfills/duktape-isfastint.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Helper to check if a number is internally represented as a fastint: - * - * if (Duktape.isFastint(x)) { - * print('fastint'); - * } else { - * print('not a fastint (or not a number)'); - * } - * - * NOTE: This helper depends on the internal tag numbering (defined in - * duk_tval.h) which is both version specific and depends on whether - * duk_tval is packed or not. - */ - -if (typeof Duktape === 'object') { - if (typeof Duktape.fastintTag === 'undefined') { - Object.defineProperty(Duktape, 'fastintTag', { - /* Tag number depends on duk_tval packing. */ - value: (Duktape.info(true)[1] === 0xfff4) ? - 0xfff1 /* tag for packed duk_tval */ : - 1 /* tag for unpacked duk_tval */, - writable: false, - enumerable: false, - configurable: true - }); - } - if (typeof Duktape.isFastint === 'undefined') { - Object.defineProperty(Duktape, 'isFastint', { - value: function (v) { - return Duktape.info(v)[0] === 4 && /* public type is DUK_TYPE_NUMBER */ - Duktape.info(v)[1] === Duktape.fastintTag; /* internal tag is fastint */ - }, - writable: false, - enumerable: false, - configurable: true - }); - } -} diff --git a/src/third_party/duktape-1.3.0/polyfills/object-assign.js b/src/third_party/duktape-1.3.0/polyfills/object-assign.js deleted file mode 100644 index dfa5a44d..00000000 --- a/src/third_party/duktape-1.3.0/polyfills/object-assign.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Object.assign(), described in E6 Section 19.1.2.1 - * - * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.assign - */ - -if (typeof Object.assign === 'undefined') { - Object.defineProperty(Object, 'assign', { - value: function (target) { - var i, n, j, m, k; - var source, keys; - var gotError; - var pendingError; - - if (target == null) { - throw new Exception('target null or undefined'); - } - - for (i = 1, n = arguments.length; i < n; i++) { - source = arguments[i]; - if (source == null) { - continue; // null or undefined - } - source = Object(source); - keys = Object.keys(source); // enumerable own keys - - for (j = 0, m = keys.length; j < m; j++) { - k = keys[j]; - try { - target[k] = source[k]; - } catch (e) { - if (!gotError) { - gotError = true; - pendingError = e; - } - } - } - } - - if (gotError) { - throw pendingError; - } - }, writable: true, enumerable: false, configurable: true - }); -} diff --git a/src/third_party/duktape-1.3.0/polyfills/object-prototype-definegetter.js b/src/third_party/duktape-1.3.0/polyfills/object-prototype-definegetter.js deleted file mode 100644 index 8d8cabb3..00000000 --- a/src/third_party/duktape-1.3.0/polyfills/object-prototype-definegetter.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Object.prototype.__defineGetter__ polyfill - */ - -if (typeof Object.prototype.__defineGetter__ === 'undefined') { - Object.defineProperty(Object.prototype, '__defineGetter__', { - value: function (n, f) { - Object.defineProperty(this, n, { enumerable: true, configurable: true, get: f }); - }, writable: true, enumerable: false, configurable: true - }); -} diff --git a/src/third_party/duktape-1.3.0/polyfills/object-prototype-definesetter.js b/src/third_party/duktape-1.3.0/polyfills/object-prototype-definesetter.js deleted file mode 100644 index 6bd1722f..00000000 --- a/src/third_party/duktape-1.3.0/polyfills/object-prototype-definesetter.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Object.prototype.__defineSetter__ polyfill - */ - -if (typeof Object.prototype.__defineSetter__ === 'undefined') { - Object.defineProperty(Object.prototype, '__defineSetter__', { - value: function (n, f) { - Object.defineProperty(this, n, { enumerable: true, configurable: true, set: f }); - }, writable: true, enumerable: false, configurable: true - }); -} diff --git a/src/third_party/duktape-1.3.0/polyfills/performance-now.js b/src/third_party/duktape-1.3.0/polyfills/performance-now.js deleted file mode 100644 index dfb0a1d6..00000000 --- a/src/third_party/duktape-1.3.0/polyfills/performance-now.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Performance.now() polyfill - * - * http://www.w3.org/TR/hr-time/#sec-high-resolution-time - * - * Dummy implementation which uses the Date built-in and has no higher - * resolution. If/when Duktape has a built-in high resolution timer - * interface, reimplement this. - */ - -var _perfNowZeroTime = Date.now(); - -if (typeof Performance === 'undefined') { - Object.defineProperty(this, 'Performance', { - value: {}, - writable: true, enumerable: false, configurable: true - }); -} -if (typeof Performance.now === 'undefined') { - Object.defineProperty(Performance, 'now', { - value: function () { - return Date.now() - _perfNowZeroTime; - }, writable: true, enumerable: false, configurable: true - }); -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_alloc_default.c b/src/third_party/duktape-1.3.0/src-separate/duk_alloc_default.c deleted file mode 100644 index 970d828e..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_alloc_default.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Default allocation functions. - * - * Assumes behavior such as malloc allowing zero size, yielding - * a NULL or a unique pointer which is a no-op for free. - */ - -#include "duk_internal.h" - -DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) { - void *res; - DUK_UNREF(udata); - res = DUK_ANSI_MALLOC(size); - DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p", - (unsigned long) size, (void *) res)); - return res; -} - -DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) { - void *res; - DUK_UNREF(udata); - res = DUK_ANSI_REALLOC(ptr, newsize); - DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p", - (void *) ptr, (unsigned long) newsize, (void *) res)); - return res; -} - -DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) { - DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr)); - DUK_UNREF(udata); - DUK_ANSI_FREE(ptr); -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_buffer.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_buffer.c deleted file mode 100644 index 98838d2d..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_buffer.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Buffer - */ - -#include "duk_internal.h" - -DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hbuffer_dynamic *h; - - DUK_ASSERT_CTX_VALID(ctx); - - h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index); - DUK_ASSERT(h != NULL); - - if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_WRONG_BUFFER_TYPE); - } - - /* maximum size check is handled by callee */ - duk_hbuffer_resize(thr, h, new_size); - - return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h); -} - -DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hbuffer_dynamic *h; - void *ptr; - duk_size_t sz; - - DUK_ASSERT(ctx != NULL); - - h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index); - DUK_ASSERT(h != NULL); - - if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_WRONG_BUFFER_TYPE); - } - - /* Forget the previous allocation, setting size to 0 and alloc to - * NULL. Caller is responsible for freeing the previous allocation. - * Getting the allocation and clearing it is done in the same API - * call to avoid any chance of a realloc. - */ - ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h); - sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h); - if (out_size) { - *out_size = sz; - } - DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h); - DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0); - - return ptr; -} - -DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t index, void *ptr, duk_size_t len) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hbuffer_external *h; - - DUK_ASSERT(ctx != NULL); - - h = (duk_hbuffer_external *) duk_require_hbuffer(ctx, index); - DUK_ASSERT(h != NULL); - - if (!DUK_HBUFFER_HAS_EXTERNAL(h)) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_WRONG_BUFFER_TYPE); - } - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h)); - - DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr); - DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len); -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_bytecode.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_bytecode.c deleted file mode 100644 index f1bf13d2..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_bytecode.c +++ /dev/null @@ -1,727 +0,0 @@ -/* - * Bytecode dump/load - * - * The bytecode load primitive is more important performance-wise than the - * dump primitive. - * - * Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be - * memory safe for invalid arguments - caller beware! There's little point - * in trying to achieve memory safety unless bytecode instructions are also - * validated which is not easy to do with indirect register references etc. - */ - -#include "duk_internal.h" - -#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT) - -#define DUK__SER_MARKER 0xff -#define DUK__SER_VERSION 0x00 -#define DUK__SER_STRING 0x00 -#define DUK__SER_NUMBER 0x01 -#define DUK__BYTECODE_INITIAL_ALLOC 256 - -/* - * Dump/load helpers, xxx_raw() helpers do no buffer checks - */ - -DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) { - duk_uint32_t len; - - len = DUK_RAW_READ_U32_BE(p); - duk_push_lstring(ctx, (const char *) p, len); - p += len; - return p; -} - -DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) { - duk_uint32_t len; - duk_uint8_t *buf; - - len = DUK_RAW_READ_U32_BE(p); - buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); - DUK_ASSERT(buf != NULL); - DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len); - p += len; - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) { - duk_size_t len; - duk_uint32_t tmp32; - - DUK_ASSERT(h != NULL); - - len = DUK_HSTRING_GET_BYTELEN(h); - DUK_ASSERT(len <= 0xffffffffUL); /* string limits */ - tmp32 = (duk_uint32_t) len; - DUK_RAW_WRITE_U32_BE(p, tmp32); - DUK_MEMCPY((void *) p, - (const void *) DUK_HSTRING_GET_DATA(h), - len); - p += len; - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) { - duk_size_t len; - duk_uint32_t tmp32; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(h != NULL); - DUK_UNREF(thr); - - len = DUK_HBUFFER_GET_SIZE(h); - DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */ - tmp32 = (duk_uint32_t) len; - DUK_RAW_WRITE_U32_BE(p, tmp32); - DUK_MEMCPY((void *) p, - (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h), - len); - p += len; - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) { - duk_hstring *h_str; - duk_tval *tv; - - tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx)); - if (tv != NULL && DUK_TVAL_IS_STRING(tv)) { - h_str = DUK_TVAL_GET_STRING(tv); - DUK_ASSERT(h_str != NULL); - } else { - h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr); - DUK_ASSERT(h_str != NULL); - } - DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p); - p = duk__dump_hstring_raw(p, h_str); - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) { - duk_tval *tv; - - tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx)); - if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h_buf; - h_buf = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p); - p = duk__dump_hbuffer_raw(thr, p, h_buf); - } else { - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); - DUK_RAW_WRITE_U32_BE(p, 0); - } - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value) { - duk_tval *tv; - duk_uint32_t val; - - tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx)); - if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) { - val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv); - } else { - val = def_value; - } - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); - DUK_RAW_WRITE_U32_BE(p, val); - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) { - duk_tval *tv; - - tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr)); - if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) { - duk_hobject *h; - duk_uint_fast32_t i; - - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - /* We know _Varmap only has own properties so walk property - * table directly. We also know _Varmap is dense and all - * values are numbers; assert for these. GC and finalizers - * shouldn't affect _Varmap so side effects should be fine. - */ - for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) { - duk_hstring *key; - duk_tval *tv_val; - duk_uint32_t val; - - key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i); - DUK_ASSERT(key != NULL); /* _Varmap is dense */ - DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)); - tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i); - DUK_ASSERT(tv_val != NULL); - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */ -#if defined(DUK_USE_FASTINT) - DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val)); - DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */ - val = DUK_TVAL_GET_FASTINT_U32(tv_val); -#else - val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val); -#endif - - DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p); - p = duk__dump_hstring_raw(p, key); - DUK_RAW_WRITE_U32_BE(p, val); - } - } - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); - DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Varmap */ - return p; -} - -DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) { - duk_tval *tv; - - tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr)); - if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) { - duk_hobject *h; - duk_uint_fast32_t i; - - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - /* We know _Formals is dense and all entries will be in the - * array part. GC and finalizers shouldn't affect _Formals - * so side effects should be fine. - */ - for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) { - duk_tval *tv_val; - duk_hstring *varname; - - tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i); - DUK_ASSERT(tv_val != NULL); - if (DUK_TVAL_IS_STRING(tv_val)) { - /* Array is dense and contains only strings, but ASIZE may - * be larger than used part and there are UNUSED entries. - */ - varname = DUK_TVAL_GET_STRING(tv_val); - DUK_ASSERT(varname != NULL); - - DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p); - p = duk__dump_hstring_raw(p, varname); - } - } - } - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); - DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Formals */ - return p; -} - -static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) { - duk_hthread *thr; - duk_tval *tv, *tv_end; - duk_instr_t *ins, *ins_end; - duk_hobject **fn, **fn_end; - duk_hstring *h_str; - duk_uint32_t count_instr; - duk_uint32_t tmp32; - duk_uint16_t tmp16; - duk_double_t d; - - thr = (duk_hthread *) ctx; - DUK_UNREF(ctx); - DUK_UNREF(thr); - - DUK_DD(DUK_DDPRINT("dumping function %p to %p: " - "consts=[%p,%p[ (%ld bytes, %ld items), " - "funcs=[%p,%p[ (%ld bytes, %ld items), " - "code=[%p,%p[ (%ld bytes, %ld items)", - (void *) func, - (void *) p, - (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func), - (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func), - (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(thr->heap, func), - (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func), - (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func), - (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func), - (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func), - (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func), - (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func), - (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func), - (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func), - (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func))); - - DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */ - count_instr = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func); - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p); - - /* Fixed header info. */ - tmp32 = count_instr; - DUK_RAW_WRITE_U32_BE(p, tmp32); - tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func); - DUK_RAW_WRITE_U32_BE(p, tmp32); - tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func); - DUK_RAW_WRITE_U32_BE(p, tmp32); - tmp16 = func->nregs; - DUK_RAW_WRITE_U16_BE(p, tmp16); - tmp16 = func->nargs; - DUK_RAW_WRITE_U16_BE(p, tmp16); -#if defined(DUK_USE_DEBUGGER_SUPPORT) - tmp32 = func->start_line; - DUK_RAW_WRITE_U32_BE(p, tmp32); - tmp32 = func->end_line; - DUK_RAW_WRITE_U32_BE(p, tmp32); -#else - DUK_RAW_WRITE_U32_BE(p, 0); - DUK_RAW_WRITE_U32_BE(p, 0); -#endif - tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK; - DUK_RAW_WRITE_U32_BE(p, tmp32); - - /* Bytecode instructions: endian conversion needed unless - * platform is big endian. - */ - ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func); - ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func); - DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr); -#if defined(DUK_USE_INTEGER_BE) - DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins)); - p += (size_t) (ins_end - ins); -#else - while (ins != ins_end) { - tmp32 = (duk_uint32_t) (*ins); - DUK_RAW_WRITE_U32_BE(p, tmp32); - ins++; - } -#endif - - /* Constants: variable size encoding. */ - tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func); - tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func); - while (tv != tv_end) { - /* constants are strings or numbers now */ - DUK_ASSERT(DUK_TVAL_IS_STRING(tv) || - DUK_TVAL_IS_NUMBER(tv)); - - if (DUK_TVAL_IS_STRING(tv)) { - h_str = DUK_TVAL_GET_STRING(tv); - DUK_ASSERT(h_str != NULL); - DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p), - *p++ = DUK__SER_STRING; - p = duk__dump_hstring_raw(p, h_str); - } else { - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); - p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p); - *p++ = DUK__SER_NUMBER; - d = DUK_TVAL_GET_NUMBER(tv); - DUK_RAW_WRITE_DOUBLE_BE(p, d); - } - tv++; - } - - /* Inner functions recursively. */ - fn = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func); - fn_end = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func); - while (fn != fn_end) { - /* XXX: This causes recursion up to inner function depth - * which is normally not an issue, e.g. mark-and-sweep uses - * a recursion limiter to avoid C stack issues. Avoiding - * this would mean some sort of a work list or just refusing - * to serialize deep functions. - */ - DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(*fn)); - p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, p); - fn++; - } - - /* Object extra properties. - * - * There are some difference between function templates and functions. - * For example, function templates don't have .length and nargs is - * normally used to instantiate the functions. - */ - - p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs); - p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME); - p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME); - p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE); - p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func); - p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func); - - DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p)); - - return p; -} - -/* Load a function from bytecode. The function object returned here must - * match what is created by duk_js_push_closure() with respect to its flags, - * properties, etc. - * - * NOTE: there are intentionally no input buffer length / bound checks. - * Adding them would be easy but wouldn't ensure memory safety as untrusted - * or broken bytecode is unsafe during execution unless the opcodes themselves - * are validated (which is quite complex, especially for indirect opcodes). - */ - -#define DUK__ASSERT_LEFT(n) do { \ - DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \ - } while (0) - -static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) { - duk_hthread *thr; - duk_hcompiledfunction *h_fun; - duk_hbuffer *h_data; - duk_size_t data_size; - duk_uint32_t count_instr, count_const, count_funcs; - duk_uint32_t n; - duk_uint32_t tmp32; - duk_small_uint_t const_type; - duk_uint8_t *fun_data; - duk_uint8_t *q; - duk_idx_t idx_base; - duk_tval *tv1; - duk_uarridx_t arr_idx; - - /* XXX: There's some overlap with duk_js_closure() here, but - * seems difficult to share code. Ensure that the final function - * looks the same as created by duk_js_closure(). - */ - - DUK_ASSERT(ctx != NULL); - thr = (duk_hthread *) ctx; - - DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end)); - - DUK__ASSERT_LEFT(3 * 4); - count_instr = DUK_RAW_READ_U32_BE(p); - count_const = DUK_RAW_READ_U32_BE(p); - count_funcs = DUK_RAW_READ_U32_BE(p); - - data_size = sizeof(duk_tval) * count_const + - sizeof(duk_hobject *) * count_funcs + - sizeof(duk_instr_t) * count_instr; - - DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld", - (long) count_instr, (long) count_const, - (long) count_const, (long) data_size)); - - /* Value stack is used to ensure reachability of constants and - * inner functions being loaded. Require enough space to handle - * large functions correctly. - */ - duk_require_stack(ctx, 2 + count_const + count_funcs); - idx_base = duk_get_top(ctx); - - /* Push function object, init flags etc. This must match - * duk_js_push_closure() quite carefully. - */ - duk_push_compiledfunction(ctx); - h_fun = duk_get_hcompiledfunction(ctx, -1); - DUK_ASSERT(h_fun != NULL); - DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) h_fun)); - DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun) == NULL); - DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, h_fun) == NULL); - DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, h_fun) == NULL); - - h_fun->nregs = DUK_RAW_READ_U16_BE(p); - h_fun->nargs = DUK_RAW_READ_U16_BE(p); -#if defined(DUK_USE_DEBUGGER_SUPPORT) - h_fun->start_line = DUK_RAW_READ_U32_BE(p); - h_fun->end_line = DUK_RAW_READ_U32_BE(p); -#else - p += 8; /* skip line info */ -#endif - - /* duk_hcompiledfunction flags; quite version specific */ - tmp32 = DUK_RAW_READ_U32_BE(p); - DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32); - - /* standard prototype */ - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]); - - /* assert just a few critical flags */ - DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT); - DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&h_fun->obj)); - DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(&h_fun->obj)); - DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(&h_fun->obj)); - DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&h_fun->obj)); - DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj)); - DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj)); - DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj)); - - /* Create function 'data' buffer but don't attach it yet. */ - fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size); - DUK_ASSERT(fun_data != NULL); - - /* Load bytecode instructions. */ - DUK_ASSERT(sizeof(duk_instr_t) == 4); - DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t)); -#if defined(DUK_USE_INTEGER_BE) - q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs; - DUK_MEMCPY((void *) q, - (const void *) p, - sizeof(duk_instr_t) * count_instr); - p += sizeof(duk_instr_t) * count_instr; -#else - q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs; - for (n = count_instr; n > 0; n--) { - *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p); - q += sizeof(duk_instr_t); - } -#endif - - /* Load constants onto value stack but don't yet copy to buffer. */ - for (n = count_const; n > 0; n--) { - DUK__ASSERT_LEFT(1); - const_type = DUK_RAW_READ_U8(p); - switch (const_type) { - case DUK__SER_STRING: { - p = duk__load_string_raw(ctx, p); - break; - } - case DUK__SER_NUMBER: { - /* Important to do a fastint check so that constants are - * properly read back as fastints. - */ - duk_tval tv_tmp; - duk_double_t val; - DUK__ASSERT_LEFT(8); - val = DUK_RAW_READ_DOUBLE_BE(p); - DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val); - duk_push_tval(ctx, &tv_tmp); - break; - } - default: { - goto format_error; - } - } - } - - /* Load inner functions to value stack, but don't yet copy to buffer. */ - for (n = count_funcs; n > 0; n--) { - p = duk__load_func(ctx, p, p_end); - if (p == NULL) { - goto format_error; - } - } - - /* With constants and inner functions on value stack, we can now - * atomically finish the function 'data' buffer, bump refcounts, - * etc. - * - * Here we take advantage of the value stack being just a duk_tval - * array: we can just memcpy() the constants as long as we incref - * them afterwards. - */ - - h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1); - DUK_ASSERT(h_data != NULL); - DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data)); - DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data); - DUK_HBUFFER_INCREF(thr, h_data); - - tv1 = duk_get_tval(ctx, idx_base + 2); /* may be NULL if no constants or inner funcs */ - DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL); - - q = fun_data; - if (count_const > 0) { - /* Explicit zero size check to avoid NULL 'tv1'. */ - DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const); - for (n = count_const; n > 0; n--) { - DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */ - q += sizeof(duk_tval); - } - tv1 += count_const; - } - - DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q); - for (n = count_funcs; n > 0; n--) { - duk_hobject *h_obj; - - DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1)); - h_obj = DUK_TVAL_GET_OBJECT(tv1); - DUK_ASSERT(h_obj != NULL); - tv1++; - DUK_HOBJECT_INCREF(thr, h_obj); - - *((duk_hobject **) (void *) q) = h_obj; - q += sizeof(duk_hobject *); - } - - DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q); - - /* The function object is now reachable and refcounts are fine, - * so we can pop off all the temporaries. - */ - DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base))); - duk_set_top(ctx, idx_base + 1); - - /* Setup function properties. */ - tmp32 = DUK_RAW_READ_U32_BE(p); - duk_push_u32(ctx, tmp32); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); - - p = duk__load_string_raw(ctx, p); - if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) { - /* Original function instance/template had NAMEBINDING. - * Must create a lexical environment on loading to allow - * recursive functions like 'function foo() { foo(); }'. - */ - duk_hobject *proto; - - proto = thr->builtins[DUK_BIDX_GLOBAL_ENV]; - (void) duk_push_object_helper_proto(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV), - proto); - duk_dup(ctx, -2); /* -> [ func funcname env funcname ] */ - duk_dup(ctx, idx_base); /* -> [ func funcname env funcname func ] */ - duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */ - duk_xdef_prop_stridx(ctx, idx_base, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC); - /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it - * will be ignored anyway - */ - } - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); - - p = duk__load_string_raw(ctx, p); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC); - - duk_push_object(ctx); - duk_dup(ctx, -2); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */ - duk_compact(ctx, -1); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); - - p = duk__load_buffer_raw(ctx, p); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC); - - duk_push_object(ctx); /* _Varmap */ - for (;;) { - /* XXX: awkward */ - p = duk__load_string_raw(ctx, p); - if (duk_get_length(ctx, -1) == 0) { - duk_pop(ctx); - break; - } - tmp32 = DUK_RAW_READ_U32_BE(p); - duk_push_u32(ctx, tmp32); - duk_put_prop(ctx, -3); - } - duk_compact(ctx, -1); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE); - - duk_push_array(ctx); /* _Formals */ - for (arr_idx = 0; ; arr_idx++) { - /* XXX: awkward */ - p = duk__load_string_raw(ctx, p); - if (duk_get_length(ctx, -1) == 0) { - duk_pop(ctx); - break; - } - duk_put_prop_index(ctx, -2, arr_idx); - } - duk_compact(ctx, -1); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE); - - /* Return with final function pushed on stack top. */ - DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1))); - DUK_ASSERT_TOP(ctx, idx_base + 1); - return p; - - format_error: - return NULL; -} - -DUK_EXTERNAL void duk_dump_function(duk_context *ctx) { - duk_hthread *thr; - duk_hcompiledfunction *func; - duk_bufwriter_ctx bw_ctx_alloc; - duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc; - duk_uint8_t *p; - - DUK_ASSERT(ctx != NULL); - thr = (duk_hthread *) ctx; - - /* Bound functions don't have all properties so we'd either need to - * lookup the non-bound target function or reject bound functions. - * For now, bound functions are rejected. - */ - func = duk_require_hcompiledfunction(ctx, -1); - DUK_ASSERT(func != NULL); - DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&func->obj)); - - /* Estimating the result size beforehand would be costly, so - * start with a reasonable size and extend as needed. - */ - DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC); - p = DUK_BW_GET_PTR(thr, bw_ctx); - *p++ = DUK__SER_MARKER; - *p++ = DUK__SER_VERSION; - p = duk__dump_func(ctx, func, bw_ctx, p); - DUK_BW_SET_PTR(thr, bw_ctx, p); - DUK_BW_COMPACT(thr, bw_ctx); - - DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1))); - - duk_remove(ctx, -2); /* [ ... func buf ] -> [ ... buf ] */ -} - -DUK_EXTERNAL void duk_load_function(duk_context *ctx) { - duk_hthread *thr; - duk_uint8_t *p_buf, *p, *p_end; - duk_size_t sz; - - DUK_ASSERT(ctx != NULL); - thr = (duk_hthread *) ctx; - DUK_UNREF(ctx); - - p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz); - DUK_ASSERT(p_buf != NULL); - - /* The caller is responsible for being sure that bytecode being loaded - * is valid and trusted. Invalid bytecode can cause memory unsafe - * behavior directly during loading or later during bytecode execution - * (instruction validation would be quite complex to implement). - * - * This signature check is the only sanity check for detecting - * accidental invalid inputs. The initial 0xFF byte ensures no - * ordinary string will be accepted by accident. - */ - p = p_buf; - p_end = p_buf + sz; - if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) { - goto format_error; - } - p += 2; - - p = duk__load_func(ctx, p, p_end); - if (p == NULL) { - goto format_error; - } - - duk_remove(ctx, -2); /* [ ... buf func ] -> [ ... func ] */ - return; - - format_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED); -} - -#undef DUK__SER_MARKER -#undef DUK__SER_VERSION -#undef DUK__SER_STRING -#undef DUK__SER_NUMBER -#undef DUK__BYTECODE_INITIAL_ALLOC - -#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */ - -DUK_EXTERNAL void duk_dump_function(duk_context *ctx) { - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); -} - -DUK_EXTERNAL void duk_load_function(duk_context *ctx) { - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); -} - -#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */ diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_call.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_call.c deleted file mode 100644 index a33fd54b..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_call.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Calls. - * - * Protected variants should avoid ever throwing an error. - */ - -#include "duk_internal.h" - -/* Prepare value stack for a method call through an object property. - * May currently throw an error e.g. when getting the property. - */ -DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) { - DUK_ASSERT_CTX_VALID(ctx); - - DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld", - (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx))); - - /* [... key arg1 ... argN] */ - - /* duplicate key */ - duk_dup(ctx, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */ - duk_get_prop(ctx, normalized_obj_index); - - DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1))); - - /* [... key arg1 ... argN func] */ - - duk_replace(ctx, -nargs - 2); - - /* [... func arg1 ... argN] */ - - duk_dup(ctx, normalized_obj_index); - duk_insert(ctx, -nargs - 1); - - /* [... func this arg1 ... argN] */ -} - -DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_small_uint_t call_flags; - duk_idx_t idx_func; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - idx_func = duk_get_top(ctx) - nargs - 1; - if (idx_func < 0 || nargs < 0) { - /* note that we can't reliably pop anything here */ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - } - - /* XXX: awkward; we assume there is space for this, overwrite - * directly instead? - */ - duk_push_undefined(ctx); - duk_insert(ctx, idx_func + 1); - - call_flags = 0; /* not protected, respect reclimit, not constructor */ - - rc = duk_handle_call(thr, /* thread */ - nargs, /* num_stack_args */ - call_flags); /* call_flags */ - DUK_UNREF(rc); -} - -DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_small_uint_t call_flags; - duk_idx_t idx_func; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */ - if (idx_func < 0 || nargs < 0) { - /* note that we can't reliably pop anything here */ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - } - - call_flags = 0; /* not protected, respect reclimit, not constructor */ - - rc = duk_handle_call(thr, /* thread */ - nargs, /* num_stack_args */ - call_flags); /* call_flags */ - DUK_UNREF(rc); -} - -DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) { - /* - * XXX: if duk_handle_call() took values through indices, this could be - * made much more sensible. However, duk_handle_call() needs to fudge - * the 'this' and 'func' values to handle bound function chains, which - * is now done "in-place", so this is not a trivial change. - */ - - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */ - - duk__call_prop_prep_stack(ctx, obj_index, nargs); - - duk_call_method(ctx, nargs); -} - -DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_small_uint_t call_flags; - duk_idx_t idx_func; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - idx_func = duk_get_top(ctx) - nargs - 1; /* must work for nargs <= 0 */ - if (idx_func < 0 || nargs < 0) { - /* We can't reliably pop anything here because the stack input - * shape is incorrect. So we throw an error; if the caller has - * no catch point for this, a fatal error will occur. Another - * alternative would be to just return an error. But then the - * stack would be in an unknown state which might cause some - * very hard to diagnose problems later on. Also note that even - * if we did not throw an error here, the underlying call handler - * might STILL throw an out-of-memory error or some other internal - * fatal error. - */ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - return DUK_EXEC_ERROR; /* unreachable */ - } - - /* awkward; we assume there is space for this */ - duk_push_undefined(ctx); - duk_insert(ctx, idx_func + 1); - - call_flags = DUK_CALL_FLAG_PROTECTED; /* protected, respect reclimit, not constructor */ - - rc = duk_handle_call(thr, /* thread */ - nargs, /* num_stack_args */ - call_flags); /* call_flags */ - - return rc; -} - -DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_small_uint_t call_flags; - duk_idx_t idx_func; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */ - if (idx_func < 0 || nargs < 0) { - /* See comments in duk_pcall(). */ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - return DUK_EXEC_ERROR; /* unreachable */ - } - - call_flags = DUK_CALL_FLAG_PROTECTED; /* protected, respect reclimit, not constructor */ - - rc = duk_handle_call(thr, /* thread */ - nargs, /* num_stack_args */ - call_flags); /* call_flags */ - - return rc; -} - -DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx) { - duk_idx_t obj_index; - duk_idx_t nargs; - - /* Get the original arguments. Note that obj_index may be a relative - * index so the stack must have the same top when we use it. - */ - - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = (duk_idx_t) duk_get_int(ctx, -2); - nargs = (duk_idx_t) duk_get_int(ctx, -1); - duk_pop_2(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */ - duk__call_prop_prep_stack(ctx, obj_index, nargs); - duk_call_method(ctx, nargs); - return 1; -} - -DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) { - /* - * Must be careful to catch errors related to value stack manipulation - * and property lookup, not just the call itself. - */ - - DUK_ASSERT_CTX_VALID(ctx); - - duk_push_idx(ctx, obj_index); - duk_push_idx(ctx, nargs); - - /* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing. - * If the value stack does not contain enough args, an error is thrown; this matches - * behavior of the other protected call API functions. - */ - return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/); -} - -DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - if (duk_get_top(ctx) < nargs || nrets < 0) { - /* See comments in duk_pcall(). */ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - return DUK_EXEC_ERROR; /* unreachable */ - } - - rc = duk_handle_safe_call(thr, /* thread */ - func, /* func */ - nargs, /* num_stack_args */ - nrets); /* num_stack_res */ - - return rc; -} - -DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) { - /* - * There are two [[Construct]] operations in the specification: - * - * - E5 Section 13.2.2: for Function objects - * - E5 Section 15.3.4.5.2: for "bound" Function objects - * - * The chain of bound functions is resolved in Section 15.3.4.5.2, - * with arguments "piling up" until the [[Construct]] internal - * method is called on the final, actual Function object. Note - * that the "prototype" property is looked up *only* from the - * final object, *before* calling the constructor. - * - * Currently we follow the bound function chain here to get the - * "prototype" property value from the final, non-bound function. - * However, we let duk_handle_call() handle the argument "piling" - * when the constructor is called. The bound function chain is - * thus now processed twice. - * - * When constructing new Array instances, an unnecessary object is - * created and discarded now: the standard [[Construct]] creates an - * object, and calls the Array constructor. The Array constructor - * returns an Array instance, which is used as the result value for - * the "new" operation; the object created before the Array constructor - * call is discarded. - * - * This would be easy to fix, e.g. by knowing that the Array constructor - * will always create a replacement object and skip creating the fallback - * object in that case. - * - * Note: functions called via "new" need to know they are called as a - * constructor. For instance, built-in constructors behave differently - * depending on how they are called. - */ - - /* XXX: merge this with duk_js_call.c, as this function implements - * core semantics (or perhaps merge the two files altogether). - */ - - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *proto; - duk_hobject *cons; - duk_hobject *fallback; - duk_idx_t idx_cons; - duk_small_uint_t call_flags; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* [... constructor arg1 ... argN] */ - - idx_cons = duk_require_normalize_index(ctx, -nargs - 1); - - DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld", - (long) duk_get_top(ctx), (long) nargs, (long) idx_cons)); - - /* XXX: code duplication */ - - /* - * Figure out the final, non-bound constructor, to get "prototype" - * property. - */ - - duk_dup(ctx, idx_cons); - for (;;) { - cons = duk_get_hobject(ctx, -1); - if (cons == NULL || !DUK_HOBJECT_HAS_CONSTRUCTABLE(cons)) { - /* Checking constructability from anything else than the - * initial constructor is not strictly necessary, but a - * nice sanity check. - */ - goto not_constructable; - } - if (!DUK_HOBJECT_HAS_BOUND(cons)) { - break; - } - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [... cons target] */ - duk_remove(ctx, -2); /* -> [... target] */ - } - DUK_ASSERT(cons != NULL && !DUK_HOBJECT_HAS_BOUND(cons)); - - /* [... constructor arg1 ... argN final_cons] */ - - /* - * Create "fallback" object to be used as the object instance, - * unless the constructor returns a replacement value. - * Its internal prototype needs to be set based on "prototype" - * property of the constructor. - */ - - duk_push_object(ctx); /* class Object, extensible */ - - /* [... constructor arg1 ... argN final_cons fallback] */ - - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE); - proto = duk_get_hobject(ctx, -1); - if (!proto) { - DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object " - "-> leave standard Object prototype as fallback prototype")); - } else { - DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value " - "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto)); - fallback = duk_get_hobject(ctx, -2); - DUK_ASSERT(fallback != NULL); - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto); - } - duk_pop(ctx); - - /* [... constructor arg1 ... argN final_cons fallback] */ - - /* - * Manipulate callstack for the call. - */ - - duk_dup_top(ctx); - duk_insert(ctx, idx_cons + 1); /* use fallback as 'this' value */ - duk_insert(ctx, idx_cons); /* also stash it before constructor, - * in case we need it (as the fallback value) - */ - duk_pop(ctx); /* pop final_cons */ - - - /* [... fallback constructor fallback(this) arg1 ... argN]; - * Note: idx_cons points to first 'fallback', not 'constructor'. - */ - - DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, " - "nargs=%ld, top=%ld", - (duk_tval *) duk_get_tval(ctx, idx_cons + 1), - (duk_tval *) duk_get_tval(ctx, idx_cons + 2), - (long) nargs, - (long) duk_get_top(ctx))); - - /* - * Call the constructor function (called in "constructor mode"). - */ - - call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL; /* not protected, respect reclimit, is a constructor call */ - - rc = duk_handle_call(thr, /* thread */ - nargs, /* num_stack_args */ - call_flags); /* call_flags */ - DUK_UNREF(rc); - - /* [... fallback retval] */ - - DUK_DDD(DUK_DDDPRINT("constructor call finished, rc=%ld, fallback=%!iT, retval=%!iT", - (long) rc, - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - - /* - * Determine whether to use the constructor return value as the created - * object instance or not. - */ - - if (duk_is_object(ctx, -1)) { - duk_remove(ctx, -2); - } else { - duk_pop(ctx); - } - - /* - * Augment created errors upon creation (not when they are thrown or - * rethrown). __FILE__ and __LINE__ are not desirable here; the call - * stack reflects the caller which is correct. - */ - -#ifdef DUK_USE_AUGMENT_ERROR_CREATE - duk_hthread_sync_currpc(thr); - duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/); -#endif - - /* [... retval] */ - - return; - - not_constructable: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CONSTRUCTABLE); -} - -DUK_LOCAL duk_ret_t duk__pnew_helper(duk_context *ctx) { - duk_uint_t nargs; - - nargs = duk_to_uint(ctx, -1); - duk_pop(ctx); - - duk_new(ctx, nargs); - return 1; -} - -DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs) { - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* For now, just use duk_safe_call() to wrap duk_new(). We can't - * simply use a protected duk_handle_call() because there's post - * processing which might throw. It should be possible to ensure - * the post processing never throws (except in internal errors and - * out of memory etc which are always allowed) and then remove this - * wrapper. - */ - - duk_push_uint(ctx, nargs); - rc = duk_safe_call(ctx, duk__pnew_helper, nargs + 2 /*nargs*/, 1 /*nrets*/); - return rc; -} - -DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT_DISABLE(thr->callstack_top >= 0); - - act = duk_hthread_get_current_activation(thr); - DUK_ASSERT(act != NULL); /* because callstack_top > 0 */ - return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0); -} - -DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - - /* For user code this could just return 1 (strict) always - * because all Duktape/C functions are considered strict, - * and strict is also the default when nothing is running. - * However, Duktape may call this function internally when - * the current activation is an Ecmascript function, so - * this cannot be replaced by a 'return 1' without fixing - * the internal call sites. - */ - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT_DISABLE(thr->callstack_top >= 0); - - act = duk_hthread_get_current_activation(thr); - if (act == NULL) { - /* Strict by default. */ - return 1; - } - return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0); -} - -/* - * Duktape/C function magic - */ - -DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - duk_hobject *func; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT_DISABLE(thr->callstack_top >= 0); - - act = duk_hthread_get_current_activation(thr); - if (act) { - func = DUK_ACT_GET_FUNC(act); - if (!func) { - duk_tval *tv = &act->tv_func; - duk_small_uint_t lf_flags; - lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv); - return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags); - } - DUK_ASSERT(func != NULL); - - if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) { - duk_hnativefunction *nf = (duk_hnativefunction *) func; - return (duk_int_t) nf->magic; - } - } - return 0; -} - -DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_hobject *h; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - if (DUK_TVAL_IS_OBJECT(tv)) { - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - if (!DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) { - goto type_error; - } - return (duk_int_t) ((duk_hnativefunction *) h)->magic; - } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) { - duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv); - return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags); - } - - /* fall through */ - type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE); - return 0; -} - -DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic) { - duk_hnativefunction *nf; - - DUK_ASSERT_CTX_VALID(ctx); - - nf = duk_require_hnativefunction(ctx, index); - DUK_ASSERT(nf != NULL); - nf->magic = (duk_int16_t) magic; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_codec.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_codec.c deleted file mode 100644 index ad5e00d0..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_codec.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Encoding and decoding basic formats: hex, base64. - * - * These are in-place operations which may allow an optimized implementation. - */ - -#include "duk_internal.h" - -/* dst length must be exactly ceil(len/3)*4 */ -DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, const duk_uint8_t *src_end, - duk_uint8_t *dst, duk_uint8_t *dst_end) { - duk_small_uint_t i, snip; - duk_uint_fast32_t t; - duk_uint_fast8_t x, y; - - DUK_UNREF(dst_end); - - while (src < src_end) { - /* read 3 bytes into 't', padded by zero */ - snip = 4; - t = 0; - for (i = 0; i < 3; i++) { - t = t << 8; - if (src >= src_end) { - snip--; - } else { - t += (duk_uint_fast32_t) (*src++); - } - } - - /* - * Missing bytes snip base64 example - * 0 4 XXXX - * 1 3 XXX= - * 2 2 XX== - */ - - DUK_ASSERT(snip >= 2 && snip <= 4); - - for (i = 0; i < 4; i++) { - x = (duk_uint_fast8_t) ((t >> 18) & 0x3f); - t = t << 6; - - /* A straightforward 64-byte lookup would be faster - * and cleaner, but this is shorter. - */ - if (i >= snip) { - y = '='; - } else if (x <= 25) { - y = x + 'A'; - } else if (x <= 51) { - y = x - 26 + 'a'; - } else if (x <= 61) { - y = x - 52 + '0'; - } else if (x == 62) { - y = '+'; - } else { - y = '/'; - } - - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) y; - } - } -} - -DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, const duk_uint8_t *src_end, - duk_uint8_t *dst, duk_uint8_t *dst_end, duk_uint8_t **out_dst_final) { - duk_uint_fast32_t t; - duk_uint_fast8_t x, y; - duk_small_uint_t group_idx; - - DUK_UNREF(dst_end); - - t = 0; - group_idx = 0; - - while (src < src_end) { - x = *src++; - - if (x >= 'A' && x <= 'Z') { - y = x - 'A' + 0; - } else if (x >= 'a' && x <= 'z') { - y = x - 'a' + 26; - } else if (x >= '0' && x <= '9') { - y = x - '0' + 52; - } else if (x == '+') { - y = 62; - } else if (x == '/') { - y = 63; - } else if (x == '=') { - /* We don't check the zero padding bytes here right now. - * This seems to be common behavior for base-64 decoders. - */ - - if (group_idx == 2) { - /* xx== -> 1 byte, t contains 12 bits, 4 on right are zero */ - t = t >> 4; - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) t; - - if (src >= src_end) { - goto error; - } - x = *src++; - if (x != '=') { - goto error; - } - } else if (group_idx == 3) { - /* xxx= -> 2 bytes, t contains 18 bits, 2 on right are zero */ - t = t >> 2; - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) ((t >> 8) & 0xff); - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) (t & 0xff); - } else { - goto error; - } - - /* Here we can choose either to end parsing and ignore - * whatever follows, or to continue parsing in case - * multiple (possibly padded) base64 strings have been - * concatenated. Currently, keep on parsing. - */ - t = 0; - group_idx = 0; - continue; - } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) { - /* allow basic ASCII whitespace */ - continue; - } else { - goto error; - } - - t = (t << 6) + y; - - if (group_idx == 3) { - /* output 3 bytes from 't' */ - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) ((t >> 16) & 0xff); - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) ((t >> 8) & 0xff); - DUK_ASSERT(dst < dst_end); - *dst++ = (duk_uint8_t) (t & 0xff); - t = 0; - group_idx = 0; - } else { - group_idx++; - } - } - - if (group_idx != 0) { - /* Here we'd have the option of decoding unpadded base64 - * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not - * accepted. - */ - goto error; - } - - *out_dst_final = dst; - return 1; - - error: - return 0; -} - -/* Shared handling for encode/decode argument. Fast path handling for - * buffer and string values because they're the most common. In particular, - * avoid creating a temporary string or buffer when possible. - */ -DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { - DUK_ASSERT(duk_is_valid_index(ctx, index)); /* checked by caller */ - if (duk_is_buffer(ctx, index)) { - return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len); - } else { - return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len); - } -} - -DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_uint8_t *src; - duk_size_t srclen; - duk_size_t dstlen; - duk_uint8_t *dst; - const char *ret; - - DUK_ASSERT_CTX_VALID(ctx); - - /* XXX: optimize for string inputs: no need to coerce to a buffer - * which makes a copy of the input. - */ - - index = duk_require_normalize_index(ctx, index); - src = (duk_uint8_t *) duk_to_buffer(ctx, index, &srclen); - /* Note: for srclen=0, src may be NULL */ - - /* Computation must not wrap; this limit works for 32-bit size_t: - * >>> srclen = 3221225469 - * >>> '%x' % ((srclen + 2) / 3 * 4) - * 'fffffffc' - */ - if (srclen > 3221225469UL) { - goto type_error; - } - dstlen = (srclen + 2) / 3 * 4; - dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen); - - duk__base64_encode_helper((const duk_uint8_t *) src, (const duk_uint8_t *) (src + srclen), - dst, (dst + dstlen)); - - ret = duk_to_string(ctx, -1); - duk_replace(ctx, index); - return ret; - - type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_ENCODE_FAILED); - return NULL; /* never here */ -} - -DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - const duk_uint8_t *src; - duk_size_t srclen; - duk_size_t dstlen; - duk_uint8_t *dst; - duk_uint8_t *dst_final; - duk_bool_t retval; - - DUK_ASSERT_CTX_VALID(ctx); - - /* XXX: optimize for buffer inputs: no need to coerce to a string - * which causes an unnecessary interning. - */ - - index = duk_require_normalize_index(ctx, index); - src = (const duk_uint8_t *) duk_to_lstring(ctx, index, &srclen); - - /* Computation must not wrap, only srclen + 3 is at risk of - * wrapping because after that the number gets smaller. - * This limit works for 32-bit size_t: - * 0x100000000 - 3 - 1 = 4294967292 - */ - if (srclen > 4294967292UL) { - goto type_error; - } - dstlen = (srclen + 3) / 4 * 3; /* upper limit */ - dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen); - /* Note: for dstlen=0, dst may be NULL */ - - retval = duk__base64_decode_helper((const duk_uint8_t *) src, (const duk_uint8_t *) (src + srclen), - dst, dst + dstlen, &dst_final); - if (!retval) { - goto type_error; - } - - /* XXX: convert to fixed buffer? */ - (void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst)); - duk_replace(ctx, index); - return; - - type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED); -} - -DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) { - const duk_uint8_t *inp; - duk_size_t len; - duk_size_t i; - duk_small_uint_t t; - duk_uint8_t *buf; - const char *ret; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - inp = duk__prep_codec_arg(ctx, index, &len); - DUK_ASSERT(inp != NULL || len == 0); - - /* Fixed buffer, no zeroing because we'll fill all the data. */ - buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, DUK_BUF_FLAG_NOZERO /*flags*/); - DUK_ASSERT(buf != NULL); - - for (i = 0; i < len; i++) { - /* XXX: by using two 256-entry tables could avoid shifting and masking. */ - t = (duk_small_uint_t) inp[i]; - buf[i*2 + 0] = duk_lc_digits[t >> 4]; - buf[i*2 + 1] = duk_lc_digits[t & 0x0f]; - } - - /* XXX: Using a string return value forces a string intern which is - * not always necessary. As a rough performance measure, hex encode - * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s - * without string coercion. Change to returning a buffer and let the - * caller coerce to string if necessary? - */ - - ret = duk_to_string(ctx, -1); - duk_replace(ctx, index); - return ret; -} - -DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - const duk_uint8_t *inp; - duk_size_t len; - duk_size_t i; - duk_small_int_t t; - duk_uint8_t *buf; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - inp = duk__prep_codec_arg(ctx, index, &len); - DUK_ASSERT(inp != NULL || len == 0); - - if (len & 0x01) { - goto type_error; - } - - /* Fixed buffer, no zeroing because we'll fill all the data. */ - buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, DUK_BUF_FLAG_NOZERO /*flags*/); - DUK_ASSERT(buf != NULL); - - for (i = 0; i < len; i += 2) { - /* For invalid characters the value -1 gets extended to - * at least 16 bits. If either nybble is invalid, the - * resulting 't' will be < 0. - */ - t = (((duk_small_int_t) duk_hex_dectab[inp[i]]) << 4) | - ((duk_small_int_t) duk_hex_dectab[inp[i + 1]]); - if (DUK_UNLIKELY(t < 0)) { - goto type_error; - } - buf[i >> 1] = (duk_uint8_t) t; - } - - duk_replace(ctx, index); - return; - - type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED); -} - -DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t index) { -#ifdef DUK_USE_ASSERTIONS - duk_idx_t top_at_entry; -#endif - const char *ret; - - DUK_ASSERT_CTX_VALID(ctx); -#ifdef DUK_USE_ASSERTIONS - top_at_entry = duk_get_top(ctx); -#endif - - index = duk_require_normalize_index(ctx, index); - duk_bi_json_stringify_helper(ctx, - index /*idx_value*/, - DUK_INVALID_INDEX /*idx_replacer*/, - DUK_INVALID_INDEX /*idx_space*/, - 0 /*flags*/); - DUK_ASSERT(duk_is_string(ctx, -1)); - duk_replace(ctx, index); - ret = duk_get_string(ctx, index); - - DUK_ASSERT(duk_get_top(ctx) == top_at_entry); - - return ret; -} - -DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index) { -#ifdef DUK_USE_ASSERTIONS - duk_idx_t top_at_entry; -#endif - - DUK_ASSERT_CTX_VALID(ctx); -#ifdef DUK_USE_ASSERTIONS - top_at_entry = duk_get_top(ctx); -#endif - - index = duk_require_normalize_index(ctx, index); - duk_bi_json_parse_helper(ctx, - index /*idx_value*/, - DUK_INVALID_INDEX /*idx_reviver*/, - 0 /*flags*/); - duk_replace(ctx, index); - - DUK_ASSERT(duk_get_top(ctx) == top_at_entry); -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_compile.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_compile.c deleted file mode 100644 index 60967e1b..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_compile.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Compilation and evaluation - */ - -#include "duk_internal.h" - -typedef struct duk__compile_raw_args duk__compile_raw_args; -struct duk__compile_raw_args { - duk_size_t src_length; /* should be first on 64-bit platforms */ - const duk_uint8_t *src_buffer; - duk_uint_t flags; -}; - -/* Eval is just a wrapper now. */ -DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) { - duk_uint_t comp_flags; - duk_int_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: strictness is *not* inherited from the current Duktape/C. - * This would be confusing because the current strictness state - * depends on whether we're running inside a Duktape/C activation - * (= strict mode) or outside of any activation (= non-strict mode). - * See tests/api/test-eval-strictness.c for more discussion. - */ - - /* [ ... source? filename ] (depends on flags) */ - - comp_flags = flags; - comp_flags |= DUK_COMPILE_EVAL; - rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags); /* may be safe, or non-safe depending on flags */ - - /* [ ... closure/error ] */ - - if (rc != DUK_EXEC_SUCCESS) { - rc = DUK_EXEC_ERROR; - goto got_rc; - } - - duk_push_global_object(ctx); /* explicit 'this' binding, see GH-164 */ - - if (flags & DUK_COMPILE_SAFE) { - rc = duk_pcall_method(ctx, 0); - } else { - duk_call_method(ctx, 0); - rc = DUK_EXEC_SUCCESS; - } - - /* [ ... result/error ] */ - - got_rc: - if (flags & DUK_COMPILE_NORESULT) { - duk_pop(ctx); - } - - return rc; -} - -/* Helper which can be called both directly and with duk_safe_call(). */ -DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk__compile_raw_args *comp_args; - duk_uint_t flags; - duk_small_uint_t comp_flags; - duk_hcompiledfunction *h_templ; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: strictness is not inherited from the current Duktape/C - * context. Otherwise it would not be possible to compile - * non-strict code inside a Duktape/C activation (which is - * always strict now). See tests/api/test-eval-strictness.c - * for discussion. - */ - - /* [ ... source? filename &comp_args ] (depends on flags) */ - - comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1); - flags = comp_args->flags; - duk_pop(ctx); - - /* [ ... source? filename ] */ - - if (!comp_args->src_buffer) { - duk_hstring *h_sourcecode; - - h_sourcecode = duk_get_hstring(ctx, -2); - if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */ - (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */ - /* XXX: when this error is caused by a nonexistent - * file given to duk_peval_file() or similar, the - * error message is not the best possible. - */ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_NO_SOURCECODE); - } - DUK_ASSERT(h_sourcecode != NULL); - comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode); - comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode); - } - DUK_ASSERT(comp_args->src_buffer != NULL); - - /* XXX: unnecessary translation of flags */ - comp_flags = 0; - if (flags & DUK_COMPILE_EVAL) { - comp_flags |= DUK_JS_COMPILE_FLAG_EVAL; - } - if (flags & DUK_COMPILE_FUNCTION) { - comp_flags |= DUK_JS_COMPILE_FLAG_EVAL | - DUK_JS_COMPILE_FLAG_FUNCEXPR; - } - if (flags & DUK_COMPILE_STRICT) { - comp_flags |= DUK_JS_COMPILE_FLAG_STRICT; - } - - /* [ ... source? filename ] */ - - duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags); - - /* [ ... source? func_template ] */ - - if (flags & DUK_COMPILE_NOSOURCE) { - ; - } else { - duk_remove(ctx, -2); - } - - /* [ ... func_template ] */ - - h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1); - DUK_ASSERT(h_templ != NULL); - duk_js_push_closure(thr, - h_templ, - thr->builtins[DUK_BIDX_GLOBAL_ENV], - thr->builtins[DUK_BIDX_GLOBAL_ENV]); - duk_remove(ctx, -2); /* -> [ ... closure ] */ - - /* [ ... closure ] */ - - return 1; -} - -DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) { - duk__compile_raw_args comp_args_alloc; - duk__compile_raw_args *comp_args = &comp_args_alloc; - - DUK_ASSERT_CTX_VALID(ctx); - - if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) { - /* String length is computed here to avoid multiple evaluation - * of a macro argument in the calling side. - */ - src_length = DUK_STRLEN(src_buffer); - } - - comp_args->src_buffer = (const duk_uint8_t *) src_buffer; - comp_args->src_length = src_length; - comp_args->flags = flags; - duk_push_pointer(ctx, (void *) comp_args); - - /* [ ... source? filename &comp_args ] (depends on flags) */ - - if (flags & DUK_COMPILE_SAFE) { - duk_int_t rc; - duk_int_t nargs; - duk_int_t nrets = 1; - - /* Arguments are either: [ filename &comp_args ] or [ source filename &comp_args ] */ - nargs = (flags & DUK_COMPILE_NOSOURCE) ? 2 : 3; - rc = duk_safe_call(ctx, duk__do_compile, nargs, nrets); - - /* [ ... closure ] */ - return rc; - } - - (void) duk__do_compile(ctx); - - /* [ ... closure ] */ - return DUK_EXEC_SUCCESS; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_debug.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_debug.c deleted file mode 100644 index 0765a66b..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_debug.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Debugging related API calls - */ - -#include "duk_internal.h" - -DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) { - duk_idx_t idx; - duk_idx_t top; - - DUK_ASSERT_CTX_VALID(ctx); - - /* We don't duk_require_stack() here now, but rely on the caller having - * enough space. - */ - - top = duk_get_top(ctx); - duk_push_array(ctx); - for (idx = 0; idx < top; idx++) { - duk_dup(ctx, idx); - duk_put_prop_index(ctx, -2, idx); - } - - /* XXX: conversion errors should not propagate outwards. - * Perhaps values need to be coerced individually? - */ - duk_bi_json_stringify_helper(ctx, - duk_get_top_index(ctx), /*idx_value*/ - DUK_INVALID_INDEX, /*idx_replacer*/ - DUK_INVALID_INDEX, /*idx_space*/ - DUK_JSON_FLAG_EXT_CUSTOM | - DUK_JSON_FLAG_ASCII_ONLY | - DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/); - - duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1)); - duk_replace(ctx, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */ - duk_pop(ctx); - DUK_ASSERT(duk_is_string(ctx, -1)); -} - -#if defined(DUK_USE_DEBUGGER_SUPPORT) - -DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx, - duk_debug_read_function read_cb, - duk_debug_write_function write_cb, - duk_debug_peek_function peek_cb, - duk_debug_read_flush_function read_flush_cb, - duk_debug_write_flush_function write_flush_cb, - duk_debug_detached_function detached_cb, - void *udata) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_heap *heap; - const char *str; - duk_size_t len; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(read_cb != NULL); - DUK_ASSERT(write_cb != NULL); - /* Other callbacks are optional. */ - - heap = thr->heap; - heap->dbg_read_cb = read_cb; - heap->dbg_write_cb = write_cb; - heap->dbg_peek_cb = peek_cb; - heap->dbg_read_flush_cb = read_flush_cb; - heap->dbg_write_flush_cb = write_flush_cb; - heap->dbg_detached_cb = detached_cb; - heap->dbg_udata = udata; - - /* Start in paused state. */ - heap->dbg_processing = 0; - heap->dbg_paused = 1; - heap->dbg_state_dirty = 1; - heap->dbg_force_restart = 0; - heap->dbg_step_type = 0; - heap->dbg_step_thread = NULL; - heap->dbg_step_csindex = 0; - heap->dbg_step_startline = 0; - heap->dbg_exec_counter = 0; - heap->dbg_last_counter = 0; - heap->dbg_last_time = 0.0; - - /* Send version identification and flush right afterwards. Note that - * we must write raw, unframed bytes here. - */ - duk_push_sprintf(ctx, "%ld %ld %s %s\n", - (long) DUK_DEBUG_PROTOCOL_VERSION, - (long) DUK_VERSION, - (const char *) DUK_GIT_DESCRIBE, - (const char *) DUK_USE_TARGET_INFO); - str = duk_get_lstring(ctx, -1, &len); - DUK_ASSERT(str != NULL); - duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len); - duk_debug_write_flush(thr); - duk_pop(ctx); -} - -DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) { - duk_hthread *thr; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->heap != NULL); - - /* Can be called muliple times with no harm. */ - duk_debug_do_detach(thr->heap); -} - -DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) { - duk_hthread *thr; - duk_bool_t processed_messages; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->heap != NULL); - - if (!DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) { - return; - } - if (thr->callstack_top > 0 || thr->heap->dbg_processing) { - /* Calling duk_debugger_cooperate() while Duktape is being - * called into is not supported. This is not a 100% check - * but prevents any damage in most cases. - */ - return; - } - - thr->heap->dbg_processing = 1; - processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/); - thr->heap->dbg_processing = 0; - DUK_UNREF(processed_messages); -} - -#else /* DUK_USE_DEBUGGER_SUPPORT */ - -DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx, - duk_debug_read_function read_cb, - duk_debug_write_function write_cb, - duk_debug_peek_function peek_cb, - duk_debug_read_flush_function read_flush_cb, - duk_debug_write_flush_function write_flush_cb, - duk_debug_detached_function detached_cb, - void *udata) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(read_cb); - DUK_UNREF(write_cb); - DUK_UNREF(peek_cb); - DUK_UNREF(read_flush_cb); - DUK_UNREF(write_flush_cb); - DUK_UNREF(detached_cb); - DUK_UNREF(udata); - duk_error(ctx, DUK_ERR_API_ERROR, "no debugger support"); -} - -DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - duk_error(ctx, DUK_ERR_API_ERROR, "no debugger support"); -} - -DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) { - /* nop */ - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(ctx); -} - -#endif /* DUK_USE_DEBUGGER_SUPPORT */ diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_heap.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_heap.c deleted file mode 100644 index 8e5936a6..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_heap.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Heap creation and destruction - */ - -#include "duk_internal.h" - -DUK_EXTERNAL -duk_context *duk_create_heap(duk_alloc_function alloc_func, - duk_realloc_function realloc_func, - duk_free_function free_func, - void *heap_udata, - duk_fatal_function fatal_handler) { - duk_heap *heap = NULL; - duk_context *ctx; - - /* Assume that either all memory funcs are NULL or non-NULL, mixed - * cases will now be unsafe. - */ - - /* XXX: just assert non-NULL values here and make caller arguments - * do the defaulting to the default implementations (smaller code)? - */ - - if (!alloc_func) { - DUK_ASSERT(realloc_func == NULL); - DUK_ASSERT(free_func == NULL); - alloc_func = duk_default_alloc_function; - realloc_func = duk_default_realloc_function; - free_func = duk_default_free_function; - } else { - DUK_ASSERT(realloc_func != NULL); - DUK_ASSERT(free_func != NULL); - } - - if (!fatal_handler) { - fatal_handler = duk_default_fatal_handler; - } - - DUK_ASSERT(alloc_func != NULL); - DUK_ASSERT(realloc_func != NULL); - DUK_ASSERT(free_func != NULL); - DUK_ASSERT(fatal_handler != NULL); - - heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler); - if (!heap) { - return NULL; - } - ctx = (duk_context *) heap->heap_thread; - DUK_ASSERT(ctx != NULL); - DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL); - return ctx; -} - -DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_heap *heap; - - if (!ctx) { - return; - } - heap = thr->heap; - DUK_ASSERT(heap != NULL); - - duk_heap_free(heap); -} - -/* XXX: better place for this */ -DUK_EXTERNAL void duk_set_global_object(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h_glob; - duk_hobject *h_prev_glob; - duk_hobject *h_env; - duk_hobject *h_prev_env; - - DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(ctx, -1))); - - h_glob = duk_require_hobject(ctx, -1); - DUK_ASSERT(h_glob != NULL); - - /* - * Replace global object. - */ - - h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL]; - thr->builtins[DUK_BIDX_GLOBAL] = h_glob; - DUK_HOBJECT_INCREF(thr, h_glob); - DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */ - - /* - * Replace lexical environment for global scope - * - * Create a new object environment for the global lexical scope. - * We can't just reset the _Target property of the current one, - * because the lexical scope is shared by other threads with the - * same (initial) built-ins. - */ - - (void) duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV), - -1); /* no prototype, updated below */ - - duk_dup(ctx, -2); - duk_dup(ctx, -3); - - /* [ ... new_glob new_env new_glob new_glob ] */ - - duk_xdef_prop_stridx(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); - duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); - - /* [ ... new_glob new_env ] */ - - h_env = duk_get_hobject(ctx, -1); - DUK_ASSERT(h_env != NULL); - - h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV]; - thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_env; - DUK_HOBJECT_INCREF(thr, h_env); - DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */ - DUK_UNREF(h_env); /* without refcounts */ - DUK_UNREF(h_prev_env); - - /* [ ... new_glob new_env ] */ - - duk_pop_2(ctx); - - /* [ ... ] */ -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_internal.h b/src/third_party/duktape-1.3.0/src-separate/duk_api_internal.h deleted file mode 100644 index 57e60228..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_internal.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Internal API calls which have (stack and other) semantics similar - * to the public API. - */ - -#ifndef DUK_API_INTERNAL_H_INCLUDED -#define DUK_API_INTERNAL_H_INCLUDED - -/* duk_push_sprintf constants */ -#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L -#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L) - -/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not - * blamed as source of error for error fileName / lineNumber. - */ -#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24) - -/* Valstack resize flags */ -#define DUK_VSRESIZE_FLAG_SHRINK (1 << 0) -#define DUK_VSRESIZE_FLAG_COMPACT (1 << 1) -#define DUK_VSRESIZE_FLAG_THROW (1 << 2) - -/* Current convention is to use duk_size_t for value stack sizes and global indices, - * and duk_idx_t for local frame indices. - */ -DUK_INTERNAL_DECL -duk_bool_t duk_valstack_resize_raw(duk_context *ctx, - duk_size_t min_new_size, - duk_small_uint_t flags); - -DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv); - -/* Push the current 'this' binding; throw TypeError if binding is not object - * coercible (CheckObjectCoercible). - */ -DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_context *ctx); - -/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */ -DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx); - -/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */ -DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx); - -/* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must - * make sure there's an active callstack entry. Note that the returned pointer - * is unstable with regards to side effects. - */ -DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx); - -/* XXX: add fastint support? */ -#define duk_push_u64(ctx,val) \ - duk_push_number((ctx), (duk_double_t) (val)) -#define duk_push_i64(ctx,val) \ - duk_push_number((ctx), (duk_double_t) (val)) - -/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */ -#define duk_push_u32(ctx,val) \ - duk_push_uint((ctx), (duk_uint_t) (val)) -#define duk_push_i32(ctx,val) \ - duk_push_int((ctx), (duk_int_t) (val)) - -/* sometimes stack and array indices need to go on the stack */ -#define duk_push_idx(ctx,val) \ - duk_push_int((ctx), (duk_int_t) (val)) -#define duk_push_uarridx(ctx,val) \ - duk_push_uint((ctx), (duk_uint_t) (val)) -#define duk_push_size_t(ctx,val) \ - duk_push_uint((ctx), (duk_uint_t) (val)) /* XXX: assumed to fit for now */ - -/* internal helper for looking up a tagged type */ -#define DUK_GETTAGGED_FLAG_ALLOW_NULL (1L << 24) -#define DUK_GETTAGGED_FLAG_CHECK_CLASS (1L << 25) -#define DUK_GETTAGGED_CLASS_SHIFT 16 - -DUK_INTERNAL_DECL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag); - -DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index); - -#define duk_get_hobject_with_class(ctx,index,classnum) \ - ((duk_hobject *) duk_get_tagged_heaphdr_raw((ctx), (index), \ - DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL | \ - DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT))) - -#if 0 /* This would be pointless: unexpected type and lightfunc would both return NULL */ -DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index); -#endif -DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index); - -#if 0 /*unused*/ -DUK_INTERNAL_DECL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index); -#endif - -DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */ -DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval); -DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval); -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index); -#endif - -DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index); - -#define duk_require_hobject_with_class(ctx,index,classnum) \ - ((duk_hobject *) duk_get_tagged_heaphdr_raw((ctx), (index), \ - DUK_TAG_OBJECT | \ - DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT))) - -DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index); -DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index); - -#if defined(DUK_USE_DEBUGGER_SUPPORT) -DUK_INTERNAL_DECL void duk_push_unused(duk_context *ctx); -#endif -DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h); -DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx); -DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h); -DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h); -#define duk_push_hthread(ctx,h) \ - duk_push_hobject((ctx), (duk_hobject *) (h)) -#define duk_push_hcompiledfunction(ctx,h) \ - duk_push_hobject((ctx), (duk_hobject *) (h)) -#define duk_push_hnativefunction(ctx,h) \ - duk_push_hobject((ctx), (duk_hobject *) (h)) -DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx); -DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx); -DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto); -DUK_INTERNAL_DECL duk_idx_t duk_push_object_internal(duk_context *ctx); -DUK_INTERNAL_DECL duk_idx_t duk_push_compiledfunction(duk_context *ctx); -DUK_INTERNAL_DECL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs); -DUK_INTERNAL_DECL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs); - -DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz); -DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv); -DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv); -DUK_INTERNAL_DECL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx); - -DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [val] */ -DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [val] -> [] */ -DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [] */ -DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [] */ - -DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop); /* [] -> [] */ - -DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags); /* [key val] -> [] */ -DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags); /* [val] -> [] */ -DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags); /* [val] -> [] */ -DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags); /* [] -> [] */ -DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags); /* [] -> [] */ - -/* These are macros for now, but could be separate functions to reduce code - * footprint (check call site count before refactoring). - */ -#define duk_xdef_prop_wec(ctx,obj_index) \ - duk_xdef_prop((ctx), (obj_index), DUK_PROPDESC_FLAGS_WEC) -#define duk_xdef_prop_index_wec(ctx,obj_index,arr_index) \ - duk_xdef_prop_index((ctx), (obj_index), (arr_index), DUK_PROPDESC_FLAGS_WEC) -#define duk_xdef_prop_stridx_wec(ctx,obj_index,stridx) \ - duk_xdef_prop_stridx((ctx), (obj_index), (stridx), DUK_PROPDESC_FLAGS_WEC) - -/* Set object 'length'. */ -DUK_INTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length); - -#endif /* DUK_API_INTERNAL_H_INCLUDED */ diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_logging.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_logging.c deleted file mode 100644 index aa9784f3..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_logging.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Logging - * - * Current logging primitive is a sprintf-style log which is convenient - * for most C code. Another useful primitive would be to log N arguments - * from value stack (like the Ecmascript binding does). - */ - -#include "duk_internal.h" - -DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap) { - /* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */ - static const duk_uint16_t stridx_logfunc[6] = { - DUK_STRIDX_LC_TRACE, DUK_STRIDX_LC_DEBUG, DUK_STRIDX_LC_INFO, - DUK_STRIDX_LC_WARN, DUK_STRIDX_LC_ERROR, DUK_STRIDX_LC_FATAL - }; - - DUK_ASSERT_CTX_VALID(ctx); - - if (level < 0) { - level = 0; - } else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) { - level = (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1; - } - - duk_push_hobject_bidx(ctx, DUK_BIDX_LOGGER_CONSTRUCTOR); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_CLOG); - duk_get_prop_stridx(ctx, -1, stridx_logfunc[level]); - duk_dup(ctx, -2); - - /* [ ... Logger clog logfunc clog ] */ - - duk_push_vsprintf(ctx, fmt, ap); - - /* [ ... Logger clog logfunc clog(=this) msg ] */ - - duk_call_method(ctx, 1 /*nargs*/); - - /* [ ... Logger clog res ] */ - - duk_pop_3(ctx); -} - -DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) { - va_list ap; - - DUK_ASSERT_CTX_VALID(ctx); - - va_start(ap, fmt); - duk_log_va(ctx, level, fmt, ap); - va_end(ap); -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_memory.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_memory.c deleted file mode 100644 index f3e5b8eb..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_memory.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Memory calls. - */ - -#include "duk_internal.h" - -DUK_EXTERNAL void *duk_alloc_raw(duk_context *ctx, duk_size_t size) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - return DUK_ALLOC_RAW(thr->heap, size); -} - -DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - DUK_FREE_RAW(thr->heap, ptr); -} - -DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - return DUK_REALLOC_RAW(thr->heap, ptr, size); -} - -DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - return DUK_ALLOC(thr->heap, size); -} - -DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - DUK_FREE(thr->heap, ptr); -} - -DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - /* - * Note: since this is an exposed API call, there should be - * no way a mark-and-sweep could have a side effect on the - * memory allocation behind 'ptr'; the pointer should never - * be something that Duktape wants to change. - * - * Thus, no need to use DUK_REALLOC_INDIRECT (and we don't - * have the storage location here anyway). - */ - - return DUK_REALLOC(thr->heap, ptr, size); -} - -DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_heap *heap; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(out_funcs != NULL); - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->heap != NULL); - - heap = thr->heap; - out_funcs->alloc_func = heap->alloc_func; - out_funcs->realloc_func = heap->realloc_func; - out_funcs->free_func = heap->free_func; - out_funcs->udata = heap->heap_udata; -} - -DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) { -#ifdef DUK_USE_MARK_AND_SWEEP - duk_hthread *thr = (duk_hthread *) ctx; - duk_heap *heap; - - DUK_UNREF(flags); - - /* NULL accepted */ - if (!ctx) { - return; - } - DUK_ASSERT_CTX_VALID(ctx); - heap = thr->heap; - DUK_ASSERT(heap != NULL); - - DUK_D(DUK_DPRINT("mark-and-sweep requested by application")); - duk_heap_mark_and_sweep(heap, 0); -#else - DUK_D(DUK_DPRINT("mark-and-sweep requested by application but mark-and-sweep not enabled, ignoring")); - DUK_UNREF(ctx); - DUK_UNREF(flags); -#endif -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_object.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_object.c deleted file mode 100644 index e482eb6c..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_object.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Object handling: property access and other support functions. - */ - -#include "duk_internal.h" - -/* - * Property handling - * - * The API exposes only the most common property handling functions. - * The caller can invoke Ecmascript built-ins for full control (e.g. - * defineProperty, getOwnPropertyDescriptor). - */ - -DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv_obj; - duk_tval *tv_key; - duk_bool_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: copying tv_obj and tv_key to locals to shield against a valstack - * resize is not necessary for a property get right now. - */ - - tv_obj = duk_require_tval(ctx, obj_index); - tv_key = duk_require_tval(ctx, -1); - - rc = duk_hobject_getprop(thr, tv_obj, tv_key); - DUK_ASSERT(rc == 0 || rc == 1); - /* a value is left on stack regardless of rc */ - - duk_remove(ctx, -2); /* remove key */ - return rc; /* 1 if property found, 0 otherwise */ -} - -DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(key != NULL); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_string(ctx, key); - return duk_get_prop(ctx, obj_index); -} - -DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_uarridx(ctx, arr_index); - return duk_get_prop(ctx, obj_index); -} - -DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx)); - return duk_get_prop(ctx, obj_index); -} - -DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop) { - duk_bool_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - - rc = duk_get_prop_stridx(ctx, obj_index, stridx); - if (out_has_prop) { - *out_has_prop = rc; - } - rc = duk_to_boolean(ctx, -1); - DUK_ASSERT(rc == 0 || rc == 1); - duk_pop(ctx); - return rc; -} - -DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv_obj; - duk_tval *tv_key; - duk_tval *tv_val; - duk_small_int_t throw_flag; - duk_bool_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: copying tv_obj and tv_key to locals to shield against a valstack - * resize is not necessary for a property put right now (putprop protects - * against it internally). - */ - - tv_obj = duk_require_tval(ctx, obj_index); - tv_key = duk_require_tval(ctx, -2); - tv_val = duk_require_tval(ctx, -1); - throw_flag = duk_is_strict_call(ctx); - - rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag); - DUK_ASSERT(rc == 0 || rc == 1); - - duk_pop_2(ctx); /* remove key and value */ - return rc; /* 1 if property found, 0 otherwise */ -} - -DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(key != NULL); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_string(ctx, key); - duk_swap_top(ctx, -2); /* [val key] -> [key val] */ - return duk_put_prop(ctx, obj_index); -} - -DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_uarridx(ctx, arr_index); - duk_swap_top(ctx, -2); /* [val key] -> [key val] */ - return duk_put_prop(ctx, obj_index); -} - -DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx)); - duk_swap_top(ctx, -2); /* [val key] -> [key val] */ - return duk_put_prop(ctx, obj_index); -} - -DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv_obj; - duk_tval *tv_key; - duk_small_int_t throw_flag; - duk_bool_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: copying tv_obj and tv_key to locals to shield against a valstack - * resize is not necessary for a property delete right now. - */ - - tv_obj = duk_require_tval(ctx, obj_index); - tv_key = duk_require_tval(ctx, -1); - throw_flag = duk_is_strict_call(ctx); - - rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag); - DUK_ASSERT(rc == 0 || rc == 1); - - duk_pop(ctx); /* remove key */ - return rc; -} - -DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(key != NULL); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_string(ctx, key); - return duk_del_prop(ctx, obj_index); -} - -DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_uarridx(ctx, arr_index); - return duk_del_prop(ctx, obj_index); -} - -DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx)); - return duk_del_prop(ctx, obj_index); -} - -DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv_obj; - duk_tval *tv_key; - duk_bool_t rc; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: copying tv_obj and tv_key to locals to shield against a valstack - * resize is not necessary for a property existence check right now. - */ - - tv_obj = duk_require_tval(ctx, obj_index); - tv_key = duk_require_tval(ctx, -1); - - rc = duk_hobject_hasprop(thr, tv_obj, tv_key); - DUK_ASSERT(rc == 0 || rc == 1); - - duk_pop(ctx); /* remove key */ - return rc; /* 1 if property found, 0 otherwise */ -} - -DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(key != NULL); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_string(ctx, key); - return duk_has_prop(ctx, obj_index); -} - -DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_uarridx(ctx, arr_index); - return duk_has_prop(ctx, obj_index); -} - -DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - - obj_index = duk_require_normalize_index(ctx, obj_index); - duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx)); - return duk_has_prop(ctx, obj_index); -} - -/* Define own property without inheritance looks and such. This differs from - * [[DefineOwnProperty]] because special behaviors (like Array 'length') are - * not invoked by this method. The caller must be careful to invoke any such - * behaviors if necessary. - */ -DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - duk_hstring *key; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_require_hobject(ctx, obj_index); - DUK_ASSERT(obj != NULL); - key = duk_to_hstring(ctx, -2); - DUK_ASSERT(key != NULL); - DUK_ASSERT(duk_require_tval(ctx, -1) != NULL); - - duk_hobject_define_property_internal(thr, obj, key, desc_flags); - - duk_pop(ctx); /* pop key */ -} - -DUK_INTERNAL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_require_hobject(ctx, obj_index); - DUK_ASSERT(obj != NULL); - - duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags); - /* value popped by call */ -} - -DUK_INTERNAL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - duk_hstring *key; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - - obj = duk_require_hobject(ctx, obj_index); - DUK_ASSERT(obj != NULL); - key = DUK_HTHREAD_GET_STRING(thr, stridx); - DUK_ASSERT(key != NULL); - DUK_ASSERT(duk_require_tval(ctx, -1) != NULL); - - duk_hobject_define_property_internal(thr, obj, key, desc_flags); - /* value popped by call */ -} - -DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - duk_hstring *key; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(stridx >= 0); - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - DUK_ASSERT_DISABLE(builtin_idx >= 0); - DUK_ASSERT(builtin_idx < DUK_NUM_BUILTINS); - - obj = duk_require_hobject(ctx, obj_index); - DUK_ASSERT(obj != NULL); - key = DUK_HTHREAD_GET_STRING(thr, stridx); - DUK_ASSERT(key != NULL); - - duk_push_hobject(ctx, thr->builtins[builtin_idx]); - duk_hobject_define_property_internal(thr, obj, key, desc_flags); - /* value popped by call */ -} - -/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3) - * setter/getter into an object property. This is needed by the 'arguments' - * object creation code, function instance creation code, and Function.prototype.bind(). - */ - -DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj = duk_require_hobject(ctx, obj_index); - duk_hobject *thrower = thr->builtins[DUK_BIDX_TYPE_ERROR_THROWER]; - duk_hobject_define_accessor_internal(thr, obj, DUK_HTHREAD_GET_STRING(thr, stridx), thrower, thrower, desc_flags); -} - -/* Object.defineProperty() equivalent C binding. */ -DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t idx_base; - duk_hobject *obj; - duk_hstring *key; - duk_idx_t idx_value; - duk_hobject *get; - duk_hobject *set; - duk_uint_t is_data_desc; - duk_uint_t is_acc_desc; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_require_hobject(ctx, obj_index); - - is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE); - is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER); - if (is_data_desc && is_acc_desc) { - /* "Have" flags must not be conflicting so that they would - * apply to both a plain property and an accessor at the same - * time. - */ - goto fail_invalid_desc; - } - - idx_base = duk_get_top_index(ctx); - if (flags & DUK_DEFPROP_HAVE_SETTER) { - duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED | - DUK_TYPE_MASK_OBJECT | - DUK_TYPE_MASK_LIGHTFUNC); - set = duk_get_hobject_or_lfunc_coerce(ctx, idx_base); - if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) { - goto fail_not_callable; - } - idx_base--; - } else { - set = NULL; - } - if (flags & DUK_DEFPROP_HAVE_GETTER) { - duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED | - DUK_TYPE_MASK_OBJECT | - DUK_TYPE_MASK_LIGHTFUNC); - get = duk_get_hobject_or_lfunc_coerce(ctx, idx_base); - if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) { - goto fail_not_callable; - } - idx_base--; - } else { - get = NULL; - } - if (flags & DUK_DEFPROP_HAVE_VALUE) { - idx_value = idx_base; - idx_base--; - } else { - idx_value = (duk_idx_t) -1; - } - key = duk_require_hstring(ctx, idx_base); - - duk_require_valid_index(ctx, idx_base); - - duk_hobject_define_property_helper(ctx, - flags /*defprop_flags*/, - obj, - key, - idx_value, - get, - set); - - /* Clean up stack */ - - duk_set_top(ctx, idx_base); - - /* [ ... obj ... ] */ - - return; - - fail_invalid_desc: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_DESCRIPTOR); - return; - - fail_not_callable: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE); - return; -} - -/* - * Object related - * - * Note: seal() and freeze() are accessible through Ecmascript bindings, - * and are not exposed through the API. - */ - -DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_get_hobject(ctx, obj_index); - if (obj) { - /* Note: this may fail, caller should protect the call if necessary */ - duk_hobject_compact_props(thr, obj); - } -} - -/* XXX: the duk_hobject_enum.c stack APIs should be reworked */ - -DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_dup(ctx, obj_index); - duk_require_hobject_or_lfunc_coerce(ctx, -1); - duk_hobject_enumerator_create(ctx, enum_flags); /* [target] -> [enum] */ -} - -DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_require_hobject(ctx, enum_index); - duk_dup(ctx, enum_index); - return duk_hobject_enumerator_next(ctx, get_value); -} - -/* - * Helpers for writing multiple properties - */ - -DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs) { - const duk_function_list_entry *ent = funcs; - - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); - if (ent != NULL) { - while (ent->key != NULL) { - duk_push_c_function(ctx, ent->value, ent->nargs); - duk_put_prop_string(ctx, obj_index, ent->key); - ent++; - } - } -} - -DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) { - const duk_number_list_entry *ent = numbers; - - DUK_ASSERT_CTX_VALID(ctx); - - obj_index = duk_require_normalize_index(ctx, obj_index); - if (ent != NULL) { - while (ent->key != NULL) { - duk_push_number(ctx, ent->value); - duk_put_prop_string(ctx, obj_index, ent->key); - ent++; - } - } -} - -/* - * Shortcut for accessing global object properties - */ - -DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_bool_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); - - /* XXX: direct implementation */ - - duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]); - ret = duk_get_prop_string(ctx, -1, key); - duk_remove(ctx, -2); - return ret; -} - -DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_bool_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); - - /* XXX: direct implementation */ - - duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]); - duk_insert(ctx, -2); - ret = duk_put_prop_string(ctx, -2, key); /* [ ... global val ] -> [ ... global ] */ - duk_pop(ctx); - return ret; -} - -/* - * Object prototype - */ - -DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - duk_hobject *proto; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - obj = duk_require_hobject(ctx, index); - DUK_ASSERT(obj != NULL); - - /* XXX: shared helper for duk_push_hobject_or_undefined()? */ - proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj); - if (proto) { - duk_push_hobject(ctx, proto); - } else { - duk_push_undefined(ctx); - } -} - -DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - duk_hobject *proto; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_require_hobject(ctx, index); - DUK_ASSERT(obj != NULL); - duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_UNDEFINED | - DUK_TYPE_MASK_OBJECT); - proto = duk_get_hobject(ctx, -1); - /* proto can also be NULL here (allowed explicitly) */ - - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto); - - duk_pop(ctx); -} - -/* - * Object finalizer - */ - -/* XXX: these could be implemented as macros calling an internal function - * directly. - * XXX: same issue as with Duktape.fin: there's no way to delete the property - * now (just set it to undefined). - */ -DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_get_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER); -} - -DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_put_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER); -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_stack.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_stack.c deleted file mode 100644 index 671d2b51..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_stack.c +++ /dev/null @@ -1,4459 +0,0 @@ -/* - * API calls related to general value stack manipulation: resizing the value - * stack, pushing and popping values, type checking and reading values, - * coercing values, etc. - * - * Also contains internal functions (such as duk_get_tval()), defined - * in duk_api_internal.h, with semantics similar to the public API. - */ - -/* XXX: repetition of stack pre-checks -> helper or macro or inline */ -/* XXX: shared api error strings, and perhaps even throw code for rare cases? */ - -#include "duk_internal.h" - -/* - * Forward declarations - */ - -DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags); - -/* - * Global state for working around missing variadic macros - */ - -#ifndef DUK_USE_VARIADIC_MACROS -DUK_EXTERNAL const char *duk_api_global_filename = NULL; -DUK_EXTERNAL duk_int_t duk_api_global_line = 0; -#endif - -/* - * Helpers - */ - -#if defined(DUK_USE_VALSTACK_UNSAFE) -/* Faster but value stack overruns are memory unsafe. */ -#define DUK__CHECK_SPACE() do { \ - DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \ - } while (0) -#else -#define DUK__CHECK_SPACE() do { \ - if (thr->valstack_top >= thr->valstack_end) { \ - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \ - } \ - } while (0) -#endif - -DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_bool_t require) { - duk_hthread *thr; - duk_tval *tv; - duk_small_int_t c; - duk_double_t d; - - thr = (duk_hthread *) ctx; - - tv = duk_get_tval(ctx, index); - if (tv == NULL) { - goto error_notnumber; - } - - /* - * Special cases like NaN and +/- Infinity are handled explicitly - * because a plain C coercion from double to int handles these cases - * in undesirable ways. For instance, NaN may coerce to INT_MIN - * (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX). - * - * This double-to-int coercion differs from ToInteger() because it - * has a finite range (ToInteger() allows e.g. +/- Infinity). It - * also differs from ToInt32() because the INT_MIN/INT_MAX clamping - * depends on the size of the int type on the platform. In particular, - * on platforms with a 64-bit int type, the full range is allowed. - */ - -#if defined(DUK_USE_FASTINT) - if (DUK_TVAL_IS_FASTINT(tv)) { - duk_int64_t t = DUK_TVAL_GET_FASTINT(tv); -#if (DUK_INT_MAX <= 0x7fffffffL) - /* Clamping only necessary for 32-bit ints. */ - if (t < DUK_INT_MIN) { - t = DUK_INT_MIN; - } else if (t > DUK_INT_MAX) { - t = DUK_INT_MAX; - } -#endif - return (duk_int_t) t; - } -#endif - - if (DUK_TVAL_IS_NUMBER(tv)) { - d = DUK_TVAL_GET_NUMBER(tv); - c = (duk_small_int_t) DUK_FPCLASSIFY(d); - if (c == DUK_FP_NAN) { - return 0; - } else if (d < (duk_double_t) DUK_INT_MIN) { - /* covers -Infinity */ - return DUK_INT_MIN; - } else if (d > (duk_double_t) DUK_INT_MAX) { - /* covers +Infinity */ - return DUK_INT_MAX; - } else { - /* coerce towards zero */ - return (duk_int_t) d; - } - } - - error_notnumber: - - if (require) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER); - /* not reachable */ - } - return 0; -} - -DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t index, duk_bool_t require) { - duk_hthread *thr; - duk_tval *tv; - duk_small_int_t c; - duk_double_t d; - - /* Same as above but for unsigned int range. */ - - thr = (duk_hthread *) ctx; - - tv = duk_get_tval(ctx, index); - if (tv == NULL) { - goto error_notnumber; - } - -#if defined(DUK_USE_FASTINT) - if (DUK_TVAL_IS_FASTINT(tv)) { - duk_int64_t t = DUK_TVAL_GET_FASTINT(tv); - if (t < 0) { - t = 0; - } -#if (DUK_UINT_MAX <= 0xffffffffUL) - /* Clamping only necessary for 32-bit ints. */ - else if (t > DUK_UINT_MAX) { - t = DUK_UINT_MAX; - } -#endif - return (duk_uint_t) t; - } -#endif - - if (DUK_TVAL_IS_NUMBER(tv)) { - d = DUK_TVAL_GET_NUMBER(tv); - c = (duk_small_int_t) DUK_FPCLASSIFY(d); - if (c == DUK_FP_NAN) { - return 0; - } else if (d < 0.0) { - /* covers -Infinity */ - return (duk_uint_t) 0; - } else if (d > (duk_double_t) DUK_UINT_MAX) { - /* covers +Infinity */ - return (duk_uint_t) DUK_UINT_MAX; - } else { - /* coerce towards zero */ - return (duk_uint_t) d; - } - } - - error_notnumber: - - if (require) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER); - /* not reachable */ - } - return 0; -} - -/* - * Stack index validation/normalization and getting a stack duk_tval ptr. - * - * These are called by many API entrypoints so the implementations must be - * fast and "inlined". - * - * There's some repetition because of this; keep the functions in sync. - */ - -DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t vs_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - /* Care must be taken to avoid pointer wrapping in the index - * validation. For instance, on a 32-bit platform with 8-byte - * duk_tval the index 0x20000000UL would wrap the memory space - * once. - */ - - /* Assume value stack sizes (in elements) fits into duk_idx_t. */ - vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - DUK_ASSERT(vs_size >= 0); - - if (index < 0) { - index = vs_size + index; - if (DUK_UNLIKELY(index < 0)) { - /* Also catches index == DUK_INVALID_INDEX: vs_size >= 0 - * so that vs_size + DUK_INVALID_INDEX cannot underflow - * and will always be negative. - */ - return DUK_INVALID_INDEX; - } - } else { - /* since index non-negative */ - DUK_ASSERT(index != DUK_INVALID_INDEX); - - if (DUK_UNLIKELY(index >= vs_size)) { - return DUK_INVALID_INDEX; - } - } - - DUK_ASSERT(index >= 0); - DUK_ASSERT(index < vs_size); - return index; -} - -DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t vs_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - DUK_ASSERT(vs_size >= 0); - - if (index < 0) { - index = vs_size + index; - if (DUK_UNLIKELY(index < 0)) { - goto invalid_index; - } - } else { - DUK_ASSERT(index != DUK_INVALID_INDEX); - if (DUK_UNLIKELY(index >= vs_size)) { - goto invalid_index; - } - } - - DUK_ASSERT(index >= 0); - DUK_ASSERT(index < vs_size); - return index; - - invalid_index: - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX); - return 0; /* unreachable */ -} - -DUK_INTERNAL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t vs_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - DUK_ASSERT(vs_size >= 0); - - if (index < 0) { - index = vs_size + index; - if (DUK_UNLIKELY(index < 0)) { - return NULL; - } - } else { - DUK_ASSERT(index != DUK_INVALID_INDEX); - if (DUK_UNLIKELY(index >= vs_size)) { - return NULL; - } - } - - DUK_ASSERT(index >= 0); - DUK_ASSERT(index < vs_size); - return thr->valstack_bottom + index; -} - -DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t vs_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - DUK_ASSERT(vs_size >= 0); - - if (index < 0) { - index = vs_size + index; - if (DUK_UNLIKELY(index < 0)) { - goto invalid_index; - } - } else { - DUK_ASSERT(index != DUK_INVALID_INDEX); - if (DUK_UNLIKELY(index >= vs_size)) { - goto invalid_index; - } - } - - DUK_ASSERT(index >= 0); - DUK_ASSERT(index < vs_size); - return thr->valstack_bottom + index; - - invalid_index: - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX); - return NULL; -} - -/* Non-critical. */ -DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - return (duk_normalize_index(ctx, index) >= 0); -} - -/* Non-critical. */ -DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - if (duk_normalize_index(ctx, index) < 0) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX); - } -} - -/* - * Value stack top handling - */ - -DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); -} - -/* set stack top within currently allocated range, but don't reallocate */ -DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t vs_size; - duk_idx_t vs_limit; - duk_idx_t count; - duk_tval tv_tmp; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(DUK_INVALID_INDEX < 0); - - vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - vs_limit = (duk_idx_t) (thr->valstack_end - thr->valstack_bottom); - - if (index < 0) { - /* Negative indices are always within allocated stack but - * must not go below zero index. - */ - index = vs_size + index; - if (index < 0) { - /* Also catches index == DUK_INVALID_INDEX. */ - goto invalid_index; - } - } else { - /* Positive index can be higher than valstack top but must - * not go above allocated stack (equality is OK). - */ - if (index > vs_limit) { - goto invalid_index; - } - } - DUK_ASSERT(index >= 0); - DUK_ASSERT(index <= vs_limit); - - if (index >= vs_size) { - /* Stack size increases or stays the same. Fill the new - * entries (if any) with undefined. No pointer stability - * issues here so we can use a running pointer. - */ - - tv = thr->valstack_top; - count = index - vs_size; - DUK_ASSERT(count >= 0); - while (count > 0) { - /* no need to decref previous or new value */ - count--; - DUK_ASSERT(DUK_TVAL_IS_UNDEFINED_UNUSED(tv)); - DUK_TVAL_SET_UNDEFINED_ACTUAL(tv); - tv++; - } - thr->valstack_top = tv; - } else { - /* Stack size decreases, DECREF entries which are above the - * new top. Each DECREF potentially invalidates valstack - * pointers, so don't hold on to pointers. The valstack top - * must also be updated on every loop in case a GC is triggered. - */ - - /* XXX: Here it would be useful to have a DECREF macro which - * doesn't need a NULL check, and does refzero queueing without - * running the refzero algorithm. There would be no pointer - * instability in this case, and code could be inlined. After - * the loop, one call to refzero would be needed. - */ - - count = vs_size - index; - DUK_ASSERT(count > 0); - - while (count > 0) { - count--; - tv = --thr->valstack_top; /* tv -> value just before prev top value */ - DUK_ASSERT(tv >= thr->valstack_bottom); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_UNDEFINED_UNUSED(tv); - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - - /* XXX: fast primitive to set a bunch of values to UNDEFINED_UNUSED */ - - } - } - return; - - invalid_index: - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX); -} - -DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1; - if (DUK_UNLIKELY(ret < 0)) { - /* Return invalid index; if caller uses this without checking - * in another API call, the index won't map to a valid stack - * entry. - */ - return DUK_INVALID_INDEX; - } - return ret; -} - -DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1; - if (DUK_UNLIKELY(ret < 0)) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX); - } - return ret; -} - -/* - * Value stack resizing. - * - * This resizing happens above the current "top": the value stack can be - * grown or shrunk, but the "top" is not affected. The value stack cannot - * be resized to a size below the current "top". - * - * The low level reallocation primitive must carefully recompute all value - * stack pointers, and must also work if ALL pointers are NULL. The resize - * is quite tricky because the valstack realloc may cause a mark-and-sweep, - * which may run finalizers. Running finalizers may resize the valstack - * recursively (the same value stack we're working on). So, after realloc - * returns, we know that the valstack "top" should still be the same (there - * should not be live values above the "top"), but its underlying size and - * pointer may have changed. - */ - -/* XXX: perhaps refactor this to allow caller to specify some parameters, or - * at least a 'compact' flag which skips any spare or round-up .. useful for - * emergency gc. - */ - -DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_ptrdiff_t old_bottom_offset; - duk_ptrdiff_t old_top_offset; - duk_ptrdiff_t old_end_offset_post; -#ifdef DUK_USE_DEBUG - duk_ptrdiff_t old_end_offset_pre; - duk_tval *old_valstack_pre; - duk_tval *old_valstack_post; -#endif - duk_tval *new_valstack; - duk_tval *p; - duk_size_t new_alloc_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->valstack_bottom >= thr->valstack); - DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); - DUK_ASSERT(thr->valstack_end >= thr->valstack_top); - DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */ - DUK_ASSERT(new_size <= thr->valstack_max); /* valstack limit caller has check, prevents wrapping */ - DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */ - - /* get pointer offsets for tweaking below */ - old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack)); - old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack)); -#ifdef DUK_USE_DEBUG - old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* not very useful, used for debugging */ - old_valstack_pre = thr->valstack; -#endif - - /* Allocate a new valstack. - * - * Note: cannot use a plain DUK_REALLOC() because a mark-and-sweep may - * invalidate the original thr->valstack base pointer inside the realloc - * process. See doc/memory-management.rst. - */ - - new_alloc_size = sizeof(duk_tval) * new_size; - new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size); - if (!new_valstack) { - /* Because new_size != 0, if condition doesn't need to be - * (new_valstack != NULL || new_size == 0). - */ - DUK_ASSERT(new_size != 0); - DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)", - (unsigned long) new_size, (unsigned long) new_alloc_size)); - return 0; - } - - /* Note: the realloc may have triggered a mark-and-sweep which may - * have resized our valstack internally. However, the mark-and-sweep - * MUST NOT leave the stack bottom/top in a different state. Particular - * assumptions and facts: - * - * - The thr->valstack pointer may be different after realloc, - * and the offset between thr->valstack_end <-> thr->valstack - * may have changed. - * - The offset between thr->valstack_bottom <-> thr->valstack - * and thr->valstack_top <-> thr->valstack MUST NOT have changed, - * because mark-and-sweep must adhere to a strict stack policy. - * In other words, logical bottom and top MUST NOT have changed. - * - All values above the top are unreachable but are initialized - * to UNDEFINED_UNUSED, up to the post-realloc valstack_end. - * - 'old_end_offset' must be computed after realloc to be correct. - */ - - DUK_ASSERT((((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack)) == old_bottom_offset); - DUK_ASSERT((((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack)) == old_top_offset); - - /* success, fixup pointers */ - old_end_offset_post = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* must be computed after realloc */ -#ifdef DUK_USE_DEBUG - old_valstack_post = thr->valstack; -#endif - thr->valstack = new_valstack; - thr->valstack_end = new_valstack + new_size; - thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset); - thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset); - - DUK_ASSERT(thr->valstack_bottom >= thr->valstack); - DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); - DUK_ASSERT(thr->valstack_end >= thr->valstack_top); - - /* useful for debugging */ -#ifdef DUK_USE_DEBUG - if (old_end_offset_pre != old_end_offset_post) { - DUK_D(DUK_DPRINT("valstack was resized during valstack_resize(), probably by mark-and-sweep; " - "end offset changed: %lu -> %lu", - (unsigned long) old_end_offset_pre, - (unsigned long) old_end_offset_post)); - } - if (old_valstack_pre != old_valstack_post) { - DUK_D(DUK_DPRINT("valstack pointer changed during valstack_resize(), probably by mark-and-sweep: %p -> %p", - (void *) old_valstack_pre, - (void *) old_valstack_post)); - } -#endif - - DUK_DD(DUK_DDPRINT("resized valstack to %lu elements (%lu bytes), bottom=%ld, top=%ld, " - "new pointers: start=%p end=%p bottom=%p top=%p", - (unsigned long) new_size, (unsigned long) new_alloc_size, - (long) (thr->valstack_bottom - thr->valstack), - (long) (thr->valstack_top - thr->valstack), - (void *) thr->valstack, (void *) thr->valstack_end, - (void *) thr->valstack_bottom, (void *) thr->valstack_top)); - - /* init newly allocated slots (only) */ - p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post); - while (p < thr->valstack_end) { - /* never executed if new size is smaller */ - DUK_TVAL_SET_UNDEFINED_UNUSED(p); - p++; - } - - /* assertion check: we maintain elements above top in known state */ -#ifdef DUK_USE_ASSERTIONS - p = thr->valstack_top; - while (p < thr->valstack_end) { - /* everything above old valstack top should be preinitialized now */ - DUK_ASSERT(DUK_TVAL_IS_UNDEFINED_UNUSED(p)); - p++; - } -#endif - return 1; -} - -DUK_INTERNAL -duk_bool_t duk_valstack_resize_raw(duk_context *ctx, - duk_size_t min_new_size, - duk_small_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_size_t old_size; - duk_size_t new_size; - duk_bool_t is_shrink = 0; - duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK); - duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT); - duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW); - - DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, " - "curr_bottom=%ld, shrink=%d, compact=%d, throw=%d", - (unsigned long) min_new_size, - (long) (thr->valstack_end - thr->valstack), - (long) (thr->valstack_top - thr->valstack), - (long) (thr->valstack_bottom - thr->valstack), - (int) shrink_flag, (int) compact_flag, (int) throw_flag)); - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->valstack_bottom >= thr->valstack); - DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); - DUK_ASSERT(thr->valstack_end >= thr->valstack_top); - - old_size = (duk_size_t) (thr->valstack_end - thr->valstack); - - if (min_new_size <= old_size) { - is_shrink = 1; - if (!shrink_flag || - old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD) { - DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack")); - return 1; - } - } - - new_size = min_new_size; - if (!compact_flag) { - if (is_shrink) { - /* shrink case; leave some spare */ - new_size += DUK_VALSTACK_SHRINK_SPARE; - } - - /* round up roughly to next 'grow step' */ - new_size = (new_size / DUK_VALSTACK_GROW_STEP + 1) * DUK_VALSTACK_GROW_STEP; - } - - DUK_DD(DUK_DDPRINT("want to %s valstack: %lu -> %lu elements (min_new_size %lu)", - (const char *) (new_size > old_size ? "grow" : "shrink"), - (unsigned long) old_size, (unsigned long) new_size, - (unsigned long) min_new_size)); - - if (new_size > thr->valstack_max) { - /* Note: may be triggered even if minimal new_size would not reach the limit, - * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account). - */ - if (throw_flag) { - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_VALSTACK_LIMIT); - } else { - return 0; - } - } - - /* - * When resizing the valstack, a mark-and-sweep may be triggered for - * the allocation of the new valstack. If the mark-and-sweep needs - * to use our thread for something, it may cause *the same valstack* - * to be resized recursively. This happens e.g. when mark-and-sweep - * finalizers are called. This is taken into account carefully in - * duk__resize_valstack(). - * - * 'new_size' is known to be <= valstack_max, which ensures that - * size_t and pointer arithmetic won't wrap in duk__resize_valstack(). - */ - - if (!duk__resize_valstack(ctx, new_size)) { - if (is_shrink) { - DUK_DD(DUK_DDPRINT("valstack resize failed, but is a shrink, ignore")); - return 1; - } - - DUK_DD(DUK_DDPRINT("valstack resize failed")); - - if (throw_flag) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_FAILED_TO_EXTEND_VALSTACK); - } else { - return 0; - } - } - - DUK_DDD(DUK_DDDPRINT("valstack resize successful")); - return 1; -} - -DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_size_t min_new_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - if (DUK_UNLIKELY(extra < 0)) { - /* Clamping to zero makes the API more robust to calling code - * calculation errors. - */ - extra = 0; - } - - min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA; - return duk_valstack_resize_raw(ctx, - min_new_size, /* min_new_size */ - 0 /* no shrink */ | /* flags */ - 0 /* no compact */ | - 0 /* no throw */); -} - -DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_size_t min_new_size; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - if (DUK_UNLIKELY(extra < 0)) { - /* Clamping to zero makes the API more robust to calling code - * calculation errors. - */ - extra = 0; - } - - min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA; - (void) duk_valstack_resize_raw(ctx, - min_new_size, /* min_new_size */ - 0 /* no shrink */ | /* flags */ - 0 /* no compact */ | - DUK_VSRESIZE_FLAG_THROW); -} - -DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) { - duk_size_t min_new_size; - - DUK_ASSERT_CTX_VALID(ctx); - - if (DUK_UNLIKELY(top < 0)) { - /* Clamping to zero makes the API more robust to calling code - * calculation errors. - */ - top = 0; - } - - min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA; - return duk_valstack_resize_raw(ctx, - min_new_size, /* min_new_size */ - 0 /* no shrink */ | /* flags */ - 0 /* no compact */ | - 0 /* no throw */); -} - -DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top) { - duk_size_t min_new_size; - - DUK_ASSERT_CTX_VALID(ctx); - - if (DUK_UNLIKELY(top < 0)) { - /* Clamping to zero makes the API more robust to calling code - * calculation errors. - */ - top = 0; - } - - min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA; - (void) duk_valstack_resize_raw(ctx, - min_new_size, /* min_new_size */ - 0 /* no shrink */ | /* flags */ - 0 /* no compact */ | - DUK_VSRESIZE_FLAG_THROW); -} - -/* - * Basic stack manipulation: swap, dup, insert, replace, etc - */ - -DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) { - duk_tval *tv1; - duk_tval *tv2; - duk_tval tv_tmp; - - DUK_ASSERT_CTX_VALID(ctx); - - tv1 = duk_require_tval(ctx, index1); - DUK_ASSERT(tv1 != NULL); - tv2 = duk_require_tval(ctx, index2); - DUK_ASSERT(tv2 != NULL); - - /* If tv1==tv2 this is a NOP, no check is needed */ - DUK_TVAL_SET_TVAL(&tv_tmp, tv1); - DUK_TVAL_SET_TVAL(tv1, tv2); - DUK_TVAL_SET_TVAL(tv2, &tv_tmp); -} - -DUK_EXTERNAL void duk_swap_top(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_swap(ctx, index, -1); -} - -DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index) { - duk_hthread *thr; - duk_tval *tv_from; - duk_tval *tv_to; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - - tv_from = duk_require_tval(ctx, from_index); - tv_to = thr->valstack_top++; - DUK_ASSERT(tv_from != NULL); - DUK_ASSERT(tv_to != NULL); - DUK_TVAL_SET_TVAL(tv_to, tv_from); - DUK_TVAL_INCREF(thr, tv_to); /* no side effects */ -} - -DUK_EXTERNAL void duk_dup_top(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_from; - duk_tval *tv_to; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - - if (thr->valstack_top - thr->valstack_bottom <= 0) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX); - } - tv_from = thr->valstack_top - 1; - tv_to = thr->valstack_top++; - DUK_ASSERT(tv_from != NULL); - DUK_ASSERT(tv_to != NULL); - DUK_TVAL_SET_TVAL(tv_to, tv_from); - DUK_TVAL_INCREF(thr, tv_to); /* no side effects */ -} - -DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) { - duk_tval *p; - duk_tval *q; - duk_tval tv_tmp; - duk_size_t nbytes; - - DUK_ASSERT_CTX_VALID(ctx); - - p = duk_require_tval(ctx, to_index); - DUK_ASSERT(p != NULL); - q = duk_require_tval(ctx, -1); - DUK_ASSERT(q != NULL); - - DUK_ASSERT(q >= p); - - /* nbytes - * <---------> - * [ ... | p | x | x | q ] - * => [ ... | q | p | x | x ] - */ - - nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */ - - DUK_DDD(DUK_DDDPRINT("duk_insert: to_index=%ld, p=%p, q=%p, nbytes=%lu", - (long) to_index, (void *) p, (void *) q, (unsigned long) nbytes)); - - /* No net refcount changes. */ - - if (nbytes > 0) { - DUK_TVAL_SET_TVAL(&tv_tmp, q); - DUK_ASSERT(nbytes > 0); - DUK_MEMMOVE((void *) (p + 1), (void *) p, nbytes); - DUK_TVAL_SET_TVAL(p, &tv_tmp); - } else { - /* nop: insert top to top */ - DUK_ASSERT(nbytes == 0); - DUK_ASSERT(p == q); - } -} - -DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv1; - duk_tval *tv2; - duk_tval tv_tmp; - - DUK_ASSERT_CTX_VALID(ctx); - - tv1 = duk_require_tval(ctx, -1); - DUK_ASSERT(tv1 != NULL); - tv2 = duk_require_tval(ctx, to_index); - DUK_ASSERT(tv2 != NULL); - - /* For tv1 == tv2, both pointing to stack top, the end result - * is same as duk_pop(ctx). - */ - - DUK_TVAL_SET_TVAL(&tv_tmp, tv2); - DUK_TVAL_SET_TVAL(tv2, tv1); - DUK_TVAL_SET_UNDEFINED_UNUSED(tv1); - thr->valstack_top--; - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -} - -DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv1; - duk_tval *tv2; - duk_tval tv_tmp; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); /* w/o refcounting */ - - tv1 = duk_require_tval(ctx, from_index); - DUK_ASSERT(tv1 != NULL); - tv2 = duk_require_tval(ctx, to_index); - DUK_ASSERT(tv2 != NULL); - - /* For tv1 == tv2, this is a no-op (no explicit check needed). */ - - DUK_TVAL_SET_TVAL(&tv_tmp, tv2); - DUK_TVAL_SET_TVAL(tv2, tv1); - DUK_TVAL_INCREF(thr, tv2); /* no side effects */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -} - -DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *p; - duk_tval *q; -#ifdef DUK_USE_REFERENCE_COUNTING - duk_tval tv_tmp; -#endif - duk_size_t nbytes; - - DUK_ASSERT_CTX_VALID(ctx); - - p = duk_require_tval(ctx, index); - DUK_ASSERT(p != NULL); - q = duk_require_tval(ctx, -1); - DUK_ASSERT(q != NULL); - - DUK_ASSERT(q >= p); - - /* nbytes zero size case - * <---------> - * [ ... | p | x | x | q ] [ ... | p==q ] - * => [ ... | x | x | q ] [ ... ] - */ - -#ifdef DUK_USE_REFERENCE_COUNTING - /* use a temp: decref only when valstack reachable values are correct */ - DUK_TVAL_SET_TVAL(&tv_tmp, p); -#endif - - nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */ - DUK_MEMMOVE(p, p + 1, nbytes); /* zero size not an issue: pointers are valid */ - - DUK_TVAL_SET_UNDEFINED_UNUSED(q); - thr->valstack_top--; - -#ifdef DUK_USE_REFERENCE_COUNTING - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -#endif -} - -/* - * Stack slice primitives - */ - -DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) { - duk_hthread *to_thr = (duk_hthread *) to_ctx; - duk_hthread *from_thr = (duk_hthread *) from_ctx; - void *src; - duk_size_t nbytes; - duk_tval *p; - duk_tval *q; - - /* XXX: several pointer comparison issues here */ - - DUK_ASSERT_CTX_VALID(to_ctx); - DUK_ASSERT_CTX_VALID(from_ctx); - DUK_ASSERT(to_ctx != NULL); - DUK_ASSERT(from_ctx != NULL); - - if (to_ctx == from_ctx) { - DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CONTEXT); - return; - } - if ((count < 0) || - (count > (duk_idx_t) to_thr->valstack_max)) { - /* Maximum value check ensures 'nbytes' won't wrap below. */ - DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT); - return; - } - - nbytes = sizeof(duk_tval) * count; - if (nbytes == 0) { - return; - } - DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end); - if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) { - DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes); - if (src < (void *) from_thr->valstack_bottom) { - DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT); - } - - /* copy values (no overlap even if to_ctx == from_ctx; that's not - * allowed now anyway) - */ - DUK_ASSERT(nbytes > 0); - DUK_MEMCPY((void *) to_thr->valstack_top, src, nbytes); - - p = to_thr->valstack_top; - to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes); - - if (is_copy) { - /* incref copies, keep originals */ - q = to_thr->valstack_top; - while (p < q) { - DUK_TVAL_INCREF(to_thr, p); /* no side effects */ - p++; - } - } else { - /* no net refcount change */ - p = from_thr->valstack_top; - q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes); - from_thr->valstack_top = q; - - /* elements above stack top are kept UNUSED */ - while (p > q) { - p--; - DUK_TVAL_SET_UNDEFINED_UNUSED(p); - - /* XXX: fast primitive to set a bunch of values to UNDEFINED_UNUSED */ - } - } -} - -/* - * Get/require - */ - -DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_UNDEFINED(tv)) { - /* Note: accept both 'actual' and 'unused' undefined */ - return; - } - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_UNDEFINED); -} - -DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_NULL(tv)) { - return; - } - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NULL); - return; /* not reachable */ -} - -DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index) { - duk_bool_t ret = 0; /* default: false */ - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BOOLEAN(tv)) { - ret = DUK_TVAL_GET_BOOLEAN(tv); - } - - DUK_ASSERT(ret == 0 || ret == 1); - return ret; -} - -DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BOOLEAN(tv)) { - duk_bool_t ret = DUK_TVAL_GET_BOOLEAN(tv); - DUK_ASSERT(ret == 0 || ret == 1); - return ret; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BOOLEAN); - return 0; /* not reachable */ -} - -DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index) { - duk_double_union ret; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - ret.d = DUK_DOUBLE_NAN; /* default: NaN */ - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_NUMBER(tv)) { - ret.d = DUK_TVAL_GET_NUMBER(tv); - } - - /* - * Number should already be in NaN-normalized form, but let's - * normalize anyway. - */ - - DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret); - return ret.d; -} - -DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_NUMBER(tv)) { - duk_double_union ret; - ret.d = DUK_TVAL_GET_NUMBER(tv); - - /* - * Number should already be in NaN-normalized form, - * but let's normalize anyway. - */ - - DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret); - return ret.d; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER); - return DUK_DOUBLE_NAN; /* not reachable */ -} - -DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index) { - /* Custom coercion for API */ - DUK_ASSERT_CTX_VALID(ctx); - return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/); -} - -DUK_EXTERNAL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index) { - /* Custom coercion for API */ - DUK_ASSERT_CTX_VALID(ctx); - return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/); -} - -DUK_EXTERNAL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index) { - /* Custom coercion for API */ - DUK_ASSERT_CTX_VALID(ctx); - return (duk_int_t) duk__api_coerce_d2i(ctx, index, 1 /*require*/); -} - -DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index) { - /* Custom coercion for API */ - DUK_ASSERT_CTX_VALID(ctx); - return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 1 /*require*/); -} - -DUK_EXTERNAL const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { - const char *ret; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - /* default: NULL, length 0 */ - ret = NULL; - if (out_len) { - *out_len = 0; - } - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_STRING(tv)) { - /* Here we rely on duk_hstring instances always being zero - * terminated even if the actual string is not. - */ - duk_hstring *h = DUK_TVAL_GET_STRING(tv); - DUK_ASSERT(h != NULL); - ret = (const char *) DUK_HSTRING_GET_DATA(h); - if (out_len) { - *out_len = DUK_HSTRING_GET_BYTELEN(h); - } - } - - return ret; -} - -DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { - duk_hthread *thr = (duk_hthread *) ctx; - const char *ret; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: this check relies on the fact that even a zero-size string - * has a non-NULL pointer. - */ - ret = duk_get_lstring(ctx, index, out_len); - if (ret) { - return ret; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_STRING); - return NULL; /* not reachable */ -} - -DUK_EXTERNAL const char *duk_get_string(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - return duk_get_lstring(ctx, index, NULL); -} - -DUK_EXTERNAL const char *duk_require_string(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - return duk_require_lstring(ctx, index, NULL); -} - -DUK_EXTERNAL void *duk_get_pointer(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_POINTER(tv)) { - void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */ - return (void *) p; - } - - return NULL; -} - -DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Note: here we must be wary of the fact that a pointer may be - * valid and be a NULL. - */ - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_POINTER(tv)) { - void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */ - return (void *) p; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_POINTER); - return NULL; /* not reachable */ -} - -#if 0 /*unused*/ -DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) { - duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv); - DUK_ASSERT(h != NULL); - return (void *) h; - } - - return NULL; -} -#endif - -DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - if (out_size != NULL) { - *out_size = 0; - } - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - if (out_size) { - *out_size = DUK_HBUFFER_GET_SIZE(h); - } - return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */ - } - - if (throw_flag) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); - } - return NULL; -} - -DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { - return duk__get_buffer_helper(ctx, index, out_size, 0 /*throw_flag*/); -} - -DUK_EXTERNAL void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { - return duk__get_buffer_helper(ctx, index, out_size, 1 /*throw_flag*/); -} - -DUK_LOCAL void *duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - if (out_size != NULL) { - *out_size = 0; - } - - tv = duk_get_tval(ctx, index); - if (tv == NULL) { - goto fail; - } - - if (DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - if (out_size) { - *out_size = DUK_HBUFFER_GET_SIZE(h); - } - return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */ - } else if (DUK_TVAL_IS_OBJECT(tv)) { - duk_hobject *h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { - /* XXX: this is probably a useful shared helper: for a - * duk_hbufferobject, get a validated buffer pointer/length. - */ - duk_hbufferobject *h_bufobj = (duk_hbufferobject *) h; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - if (h_bufobj->buf != NULL && - DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) { - duk_uint8_t *p; - - p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf); - if (out_size != NULL) { - *out_size = (duk_size_t) h_bufobj->length; - } - return (void *) (p + h_bufobj->offset); - } - /* if slice not fully valid, treat as error */ - } - } - - fail: - if (throw_flag) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); - } - return NULL; -} - -DUK_EXTERNAL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { - return duk__get_buffer_data_helper(ctx, index, out_size, 0 /*throw_flag*/); -} - -DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { - return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/); -} - -/* Raw helper for getting a value from the stack, checking its tag, and possible its object class. - * The tag cannot be a number because numbers don't have an internal tag in the packed representation. - */ -DUK_INTERNAL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_small_uint_t tag = flags_and_tag & 0xffffU; /* tags can be up to 16 bits */ - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) { - duk_heaphdr *ret; - - /* Note: tag comparison in general doesn't work for numbers, - * but it does work for everything else (heap objects here). - */ - ret = DUK_TVAL_GET_HEAPHDR(tv); - DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */ - - /* If class check has been requested, tag must also be DUK_TAG_OBJECT. - * This allows us to just check the class check flag without checking - * the tag also. - */ - DUK_ASSERT((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 || - tag == DUK_TAG_OBJECT); - - if ((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 || /* no class check */ - (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) ret) == /* or class check matches */ - (duk_int_t) ((flags_and_tag >> DUK_GETTAGGED_CLASS_SHIFT) & 0xff)) { - return ret; - } - } - - if (flags_and_tag & DUK_GETTAGGED_FLAG_ALLOW_NULL) { - return (duk_heaphdr *) NULL; - } - - /* Formatting the tag number here is not very useful: the tag value - * is Duktape internal (not the same as DUK_TYPE_xxx) and even depends - * on the duk_tval layout. If anything, add a human readable type here. - */ - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE); - return NULL; /* not reachable */ -} - -DUK_INTERNAL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index) { - return (duk_hstring *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING | DUK_GETTAGGED_FLAG_ALLOW_NULL); -} - -DUK_INTERNAL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index) { - return (duk_hstring *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING); -} - -DUK_INTERNAL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index) { - return (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL); -} - -DUK_INTERNAL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index) { - return (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT); -} - -DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index) { - return (duk_hbuffer *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER | DUK_GETTAGGED_FLAG_ALLOW_NULL); -} - -DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index) { - return (duk_hbuffer *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER); -} - -DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) { - duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL); - if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) { - h = NULL; - } - return (duk_hthread *) h; -} - -DUK_INTERNAL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT); - DUK_ASSERT(h != NULL); - if (!DUK_HOBJECT_IS_THREAD(h)) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_THREAD); - } - return (duk_hthread *) h; -} - -DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index) { - duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL); - if (h != NULL && !DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) { - h = NULL; - } - return (duk_hcompiledfunction *) h; -} - -DUK_INTERNAL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT); - DUK_ASSERT(h != NULL); - if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_COMPILEDFUNCTION); - } - return (duk_hcompiledfunction *) h; -} - -DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index) { - duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL); - if (h != NULL && !DUK_HOBJECT_IS_NATIVEFUNCTION(h)) { - h = NULL; - } - return (duk_hnativefunction *) h; -} - -DUK_INTERNAL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT); - DUK_ASSERT(h != NULL); - if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NATIVEFUNCTION); - } - return (duk_hnativefunction *) h; -} - -DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - duk_hobject *h; - duk_hnativefunction *f; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (!tv) { - return NULL; - } - if (!DUK_TVAL_IS_OBJECT(tv)) { - return NULL; - } - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) { - return NULL; - } - DUK_ASSERT(DUK_HOBJECT_HAS_NATIVEFUNCTION(h)); - f = (duk_hnativefunction *) h; - - return f->func; -} - -DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_c_function ret; - - DUK_ASSERT_CTX_VALID(ctx); - - ret = duk_get_c_function(ctx, index); - if (!ret) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_C_FUNCTION); - } - return ret; -} - -DUK_EXTERNAL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - return (duk_context *) duk_get_hthread(ctx, index); -} - -DUK_EXTERNAL duk_context *duk_require_context(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - - return (duk_context *) duk_require_hthread(ctx, index); -} - -DUK_EXTERNAL void *duk_get_heapptr(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - void *ret; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) { - ret = (void *) DUK_TVAL_GET_HEAPHDR(tv); - DUK_ASSERT(ret != NULL); - return ret; - } - - return (void *) NULL; -} - -DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - void *ret; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) { - ret = (void *) DUK_TVAL_GET_HEAPHDR(tv); - DUK_ASSERT(ret != NULL); - return ret; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE); - return (void *) NULL; /* not reachable */ -} - -#if 0 -/* This would be pointless: we'd return NULL for both lightfuncs and - * unexpected types. - */ -duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) { -} -#endif - -/* Useful for internal call sites where we either expect an object (function) - * or a lightfunc. Accepts an object (returned as is) or a lightfunc (coerced - * to an object). Return value is NULL if value is neither an object nor a - * lightfunc. - */ -duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_OBJECT(tv)) { - return DUK_TVAL_GET_OBJECT(tv); - } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) { - duk_to_object(ctx, index); - return duk_require_hobject(ctx, index); - } - - return NULL; -} - -/* Useful for internal call sites where we either expect an object (function) - * or a lightfunc. Returns NULL for a lightfunc. - */ -DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_OBJECT(tv)) { - return DUK_TVAL_GET_OBJECT(tv); - } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) { - return NULL; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE); - return NULL; /* not reachable */ -} - -/* Useful for internal call sites where we either expect an object (function) - * or a lightfunc. Accepts an object (returned as is) or a lightfunc (coerced - * to an object). Return value is never NULL. - */ -DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - if (DUK_TVAL_IS_OBJECT(tv)) { - return DUK_TVAL_GET_OBJECT(tv); - } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) { - duk_to_object(ctx, index); - return duk_require_hobject(ctx, index); - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE); - return NULL; /* not reachable */ -} - -DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (!tv) { - return 0; - } - - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: - case DUK_TAG_NULL: - case DUK_TAG_BOOLEAN: - case DUK_TAG_POINTER: - return 0; - case DUK_TAG_STRING: { - duk_hstring *h = DUK_TVAL_GET_STRING(tv); - DUK_ASSERT(h != NULL); - return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h); - } - case DUK_TAG_OBJECT: { - duk_hobject *h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - return (duk_size_t) duk_hobject_get_length((duk_hthread *) ctx, h); - } - case DUK_TAG_BUFFER: { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - return (duk_size_t) DUK_HBUFFER_GET_SIZE(h); - } - case DUK_TAG_LIGHTFUNC: { - duk_small_uint_t lf_flags; - lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv); - return (duk_size_t) DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags); - } -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: -#endif - default: - /* number */ - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); - return 0; - } - - DUK_UNREACHABLE(); -} - -DUK_INTERNAL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h; - - DUK_ASSERT_CTX_VALID(ctx); - - h = duk_get_hobject(ctx, index); - if (!h) { - return; - } - - duk_hobject_set_length(thr, h, (duk_uint32_t) length); /* XXX: typing */ -} - -/* - * Conversions and coercions - * - * The conversion/coercions are in-place operations on the value stack. - * Some operations are implemented here directly, while others call a - * helper in duk_js_ops.c after validating arguments. - */ - -/* E5 Section 8.12.8 */ - -DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t index, duk_small_int_t func_stridx) { - if (duk_get_prop_stridx(ctx, index, func_stridx)) { - /* [ ... func ] */ - if (duk_is_callable(ctx, -1)) { - duk_dup(ctx, index); /* -> [ ... func this ] */ - duk_call_method(ctx, 0); /* -> [ ... retval ] */ - if (duk_is_primitive(ctx, -1)) { - duk_replace(ctx, index); - return 1; - } - /* [ ... retval ]; popped below */ - } - } - duk_pop(ctx); /* [ ... func/retval ] -> [ ... ] */ - return 0; -} - -DUK_EXTERNAL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - /* inline initializer for coercers[] is not allowed by old compilers like BCC */ - duk_small_int_t coercers[2]; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - coercers[0] = DUK_STRIDX_VALUE_OF; - coercers[1] = DUK_STRIDX_TO_STRING; - - index = duk_require_normalize_index(ctx, index); - obj = duk_require_hobject_or_lfunc(ctx, index); - - if (hint == DUK_HINT_NONE) { - if (obj != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_DATE) { - hint = DUK_HINT_STRING; - } else { - hint = DUK_HINT_NUMBER; - } - } - - if (hint == DUK_HINT_STRING) { - coercers[0] = DUK_STRIDX_TO_STRING; - coercers[1] = DUK_STRIDX_VALUE_OF; - } - - if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[0])) { - return; - } - - if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[1])) { - return; - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DEFAULTVALUE_COERCE_FAILED); -} - -DUK_EXTERNAL void duk_to_undefined(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_UNDEFINED_ACTUAL(tv); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -} - -DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_NULL(tv); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -} - -/* E5 Section 9.1 */ -DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint) { - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING); - - index = duk_require_normalize_index(ctx, index); - - if (!duk_check_type_mask(ctx, index, DUK_TYPE_MASK_OBJECT | - DUK_TYPE_MASK_LIGHTFUNC)) { - /* everything except object stay as is */ - return; - } - duk_to_defaultvalue(ctx, index, hint); -} - -/* E5 Section 9.2 */ -DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_bool_t val; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - index = duk_require_normalize_index(ctx, index); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - - val = duk_js_toboolean(tv); - DUK_ASSERT(val == 0 || val == 1); - - /* Note: no need to re-lookup tv, conversion is side effect free */ - DUK_ASSERT(tv != NULL); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_BOOLEAN(tv, val); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return val; -} - -DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_double_t d; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - /* XXX: fastint? */ - d = duk_js_tonumber(thr, tv); - - /* Note: need to re-lookup because ToNumber() may have side effects */ - tv = duk_require_tval(ctx, index); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return d; -} - -/* XXX: combine all the integer conversions: they share everything - * but the helper function for coercion. - */ - -typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv); - -DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t index, duk__toint_coercer coerce_func) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_double_t d; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - d = coerce_func(thr, tv); - - /* XXX: fastint? */ - - /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */ - tv = duk_require_tval(ctx, index); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return d; -} - -DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index) { - /* Value coercion (in stack): ToInteger(), E5 Section 9.4 - * API return value coercion: custom - */ - DUK_ASSERT_CTX_VALID(ctx); - (void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger); - return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/); -} - -DUK_EXTERNAL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index) { - /* Value coercion (in stack): ToInteger(), E5 Section 9.4 - * API return value coercion: custom - */ - DUK_ASSERT_CTX_VALID(ctx); - (void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger); - return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/); -} - -DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_int32_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - ret = duk_js_toint32(thr, tv); - - /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */ - tv = duk_require_tval(ctx, index); -#if defined(DUK_USE_FASTINT) - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_FASTINT_I32(tv, ret); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return ret; -#else - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_NUMBER(tv, (duk_double_t) ret); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return ret; -#endif -} - -DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_uint32_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - ret = duk_js_touint32(thr, tv); - - /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */ - tv = duk_require_tval(ctx, index); -#if defined(DUK_USE_FASTINT) - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_FASTINT_U32(tv, ret); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return ret; -#else - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_NUMBER(tv, (duk_double_t) ret); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -#endif - return ret; -} - -DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_uint16_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - ret = duk_js_touint16(thr, tv); - - /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */ - tv = duk_require_tval(ctx, index); -#if defined(DUK_USE_FASTINT) - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_FASTINT_U32(tv, ret); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - return ret; -#else - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_NUMBER(tv, (duk_double_t) ret); /* no need to incref */ - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ -#endif - return ret; -} - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Special coercion for Uint8ClampedArray. */ -DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index) { - duk_double_t d; - duk_double_t t; - duk_uint8_t ret; - - /* XXX: Simplify this algorithm, should be possible to come up with - * a shorter and faster algorithm by inspecting IEEE representation - * directly. - */ - - d = duk_to_number(ctx, index); - if (d <= 0.0) { - return 0; - } else if (d >= 255) { - return 255; - } else if (DUK_ISNAN(d)) { - /* Avoid NaN-to-integer coercion as it is compiler specific. */ - return 0; - } - - t = d - DUK_FLOOR(d); - if (t == 0.5) { - /* Exact halfway, round to even. */ - ret = (duk_uint8_t) d; - ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4 - * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4 - */ - } else { - /* Not halfway, round to nearest. */ - ret = (duk_uint8_t) (d + 0.5); - } - return ret; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { - DUK_ASSERT_CTX_VALID(ctx); - - (void) duk_to_string(ctx, index); - return duk_require_lstring(ctx, index, out_len); -} - -DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_to_string(ctx, -1); - return 1; -} - -DUK_EXTERNAL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - - /* We intentionally ignore the duk_safe_call() return value and only - * check the output type. This way we don't also need to check that - * the returned value is indeed a string in the success case. - */ - - duk_dup(ctx, index); - (void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/); - if (!duk_is_string(ctx, -1)) { - /* Error: try coercing error to string once. */ - (void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/); - if (!duk_is_string(ctx, -1)) { - /* Double error */ - duk_pop(ctx); - duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_ERROR); - } else { - ; - } - } else { - ; - } - DUK_ASSERT(duk_is_string(ctx, -1)); - - duk_replace(ctx, index); - return duk_require_lstring(ctx, index, out_len); -} - -/* XXX: other variants like uint, u32 etc */ -DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_tval tv_tmp; - duk_double_t d, dmin, dmax; - duk_int_t res; - duk_bool_t clamped = 0; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */ - - dmin = (duk_double_t) minval; - dmax = (duk_double_t) maxval; - - if (d < dmin) { - clamped = 1; - res = minval; - d = dmin; - } else if (d > dmax) { - clamped = 1; - res = maxval; - d = dmax; - } else { - res = (duk_int_t) d; - } - /* 'd' and 'res' agree here */ - - /* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */ - tv = duk_require_tval(ctx, index); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); -#if defined(DUK_USE_FASTINT) -#if (DUK_INT_MAX <= 0x7fffffffL) - DUK_TVAL_SET_FASTINT_I32(tv, res); -#else - /* Clamping needed if duk_int_t is 64 bits. */ - if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) { - DUK_TVAL_SET_FASTINT(tv, res); - } else { - DUK_TVAL_SET_NUMBER(tv, d); - } -#endif -#else - DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */ -#endif - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - - if (out_clamped) { - *out_clamped = clamped; - } else { - /* coerced value is updated to value stack even when RangeError thrown */ - if (clamped) { - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_NUMBER_OUTSIDE_RANGE); - } - } - - return res; -} - -DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_idx_t minval, duk_idx_t maxval) { - duk_bool_t dummy; - return duk_to_int_clamped_raw(ctx, index, minval, maxval, &dummy); -} - -DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval) { - return duk_to_int_clamped_raw(ctx, index, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */ -} - -DUK_EXTERNAL const char *duk_to_string(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - index = duk_require_normalize_index(ctx, index); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: { - duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_UNDEFINED); - break; - } - case DUK_TAG_NULL: { - duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_NULL); - break; - } - case DUK_TAG_BOOLEAN: { - if (DUK_TVAL_GET_BOOLEAN(tv)) { - duk_push_hstring_stridx(ctx, DUK_STRIDX_TRUE); - } else { - duk_push_hstring_stridx(ctx, DUK_STRIDX_FALSE); - } - break; - } - case DUK_TAG_STRING: { - /* nop */ - goto skip_replace; - } - case DUK_TAG_OBJECT: { - duk_to_primitive(ctx, index, DUK_HINT_STRING); - return duk_to_string(ctx, index); /* Note: recursive call */ - } - case DUK_TAG_BUFFER: { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - - /* Note: this allows creation of internal strings. */ - - DUK_ASSERT(h != NULL); - duk_push_lstring(ctx, - (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h), - (duk_size_t) DUK_HBUFFER_GET_SIZE(h)); - break; - } - case DUK_TAG_POINTER: { - void *ptr = DUK_TVAL_GET_POINTER(tv); - if (ptr != NULL) { - duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) ptr); - } else { - /* Represent a null pointer as 'null' to be consistent with - * the JX format variant. Native '%p' format for a NULL - * pointer may be e.g. '(nil)'. - */ - duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_NULL); - } - break; - } - case DUK_TAG_LIGHTFUNC: { - /* Should match Function.prototype.toString() */ - duk_push_lightfunc_tostring(ctx, tv); - break; - } -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: -#endif - default: { - /* number */ - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); - duk_push_tval(ctx, tv); - duk_numconv_stringify(ctx, - 10 /*radix*/, - 0 /*precision:shortest*/, - 0 /*force_exponential*/); - break; - } - } - - duk_replace(ctx, index); - - skip_replace: - return duk_require_string(ctx, index); -} - -DUK_INTERNAL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index) { - duk_hstring *ret; - DUK_ASSERT_CTX_VALID(ctx); - duk_to_string(ctx, index); - ret = duk_get_hstring(ctx, index); - DUK_ASSERT(ret != NULL); - return ret; -} - -DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_uint_t mode) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hbuffer *h_buf; - const duk_uint8_t *src_data; - duk_size_t src_size; - duk_uint8_t *dst_data; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(thr); - - index = duk_require_normalize_index(ctx, index); - - h_buf = duk_get_hbuffer(ctx, index); - if (h_buf != NULL) { - /* Buffer is kept as is, with the fixed/dynamic nature of the - * buffer only changed if requested. An external buffer - * is converted into a non-external dynamic buffer in a - * duk_to_dynamic_buffer() call. - */ - duk_uint_t tmp; - - src_data = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf); - src_size = DUK_HBUFFER_GET_SIZE(h_buf); - - tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED); - if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) || - mode == DUK_BUF_MODE_DONTCARE) { - /* Note: src_data may be NULL if input is a zero-size - * dynamic buffer. - */ - dst_data = (duk_uint8_t *) src_data; - goto skip_copy; - } - } else { - /* Non-buffer value is first ToString() coerced, then converted - * to a buffer (fixed buffer is used unless a dynamic buffer is - * explicitly requested). - */ - - src_data = (const duk_uint8_t *) duk_to_lstring(ctx, index, &src_size); - } - - dst_data = (duk_uint8_t *) duk_push_buffer(ctx, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/); - if (DUK_LIKELY(src_size > 0)) { - /* When src_size == 0, src_data may be NULL (if source - * buffer is dynamic), and dst_data may be NULL (if - * target buffer is dynamic). Avoid zero-size memcpy() - * with an invalid pointer. - */ - DUK_MEMCPY(dst_data, src_data, src_size); - } - duk_replace(ctx, index); - skip_copy: - - if (out_size) { - *out_size = src_size; - } - return dst_data; -} - -DUK_EXTERNAL void *duk_to_pointer(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - void *res; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: - case DUK_TAG_NULL: - case DUK_TAG_BOOLEAN: - res = NULL; - break; - case DUK_TAG_POINTER: - res = DUK_TVAL_GET_POINTER(tv); - break; - case DUK_TAG_STRING: - case DUK_TAG_OBJECT: - case DUK_TAG_BUFFER: - /* Heap allocated: return heap pointer which is NOT useful - * for the caller, except for debugging. - */ - res = (void *) DUK_TVAL_GET_HEAPHDR(tv); - break; - case DUK_TAG_LIGHTFUNC: - /* Function pointers do not always cast correctly to void * - * (depends on memory and segmentation model for instance), - * so they coerce to NULL. - */ - res = NULL; - break; -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: -#endif - default: - /* number */ - res = NULL; - break; - } - - duk_push_pointer(ctx, res); - duk_replace(ctx, index); - return res; -} - -DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_uint_t flags = 0; /* shared flags for a subset of types */ - duk_small_int_t proto = 0; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: - case DUK_TAG_NULL: { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_OBJECT_COERCIBLE); - break; - } - case DUK_TAG_BOOLEAN: { - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN); - proto = DUK_BIDX_BOOLEAN_PROTOTYPE; - goto create_object; - } - case DUK_TAG_STRING: { - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING); - proto = DUK_BIDX_STRING_PROTOTYPE; - goto create_object; - } - case DUK_TAG_OBJECT: { - /* nop */ - break; - } - case DUK_TAG_BUFFER: { - /* A plain buffer coerces to a Duktape.Buffer because it's the - * object counterpart of the plain buffer value. But it might - * still make more sense to produce an ArrayBuffer here? - */ - - duk_hbufferobject *h_bufobj; - duk_hbuffer *h_val; - - h_val = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h_val != NULL); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), - DUK_BIDX_BUFFER_PROTOTYPE); - DUK_ASSERT(h_bufobj != NULL); - DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE((duk_hobject *) h_bufobj)); - DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)); - - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - DUK_ASSERT(h_bufobj->offset == 0); - h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val); - DUK_ASSERT(h_bufobj->shift == 0); - DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); - - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - goto replace_value; - } - case DUK_TAG_POINTER: { - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER); - proto = DUK_BIDX_POINTER_PROTOTYPE; - goto create_object; - } - case DUK_TAG_LIGHTFUNC: { - /* Lightfunc coerces to a Function instance with concrete - * properties. Since 'length' is virtual for Duktape/C - * functions, don't need to define that. - * - * The result is made extensible to mimic what happens to - * strings: - * > Object.isExtensible(Object('foo')) - * true - */ - duk_small_uint_t lf_flags; - duk_small_uint_t nargs; - duk_small_uint_t lf_len; - duk_c_function func; - duk_hnativefunction *nf; - - DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags); - - nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags); - if (nargs == DUK_LFUNC_NARGS_VARARGS) { - nargs = DUK_VARARGS; - } - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_CONSTRUCTABLE | - DUK_HOBJECT_FLAG_NATIVEFUNCTION | - DUK_HOBJECT_FLAG_NEWENV | - DUK_HOBJECT_FLAG_STRICT | - DUK_HOBJECT_FLAG_NOTAIL | - /* DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC: omitted here intentionally */ - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION); - (void) duk__push_c_function_raw(ctx, func, (duk_idx_t) nargs, flags); - - lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags); - if (lf_len != nargs) { - /* Explicit length is only needed if it differs from 'nargs'. */ - duk_push_int(ctx, (duk_int_t) lf_len); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); - } - duk_push_lightfunc_name(ctx, tv); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); - - nf = duk_get_hnativefunction(ctx, -1); - DUK_ASSERT(nf != NULL); - nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags); - - /* Enable DUKFUNC exotic behavior once properties are set up. */ - DUK_HOBJECT_SET_EXOTIC_DUKFUNC((duk_hobject *) nf); - goto replace_value; - } -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: -#endif - default: { - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER); - proto = DUK_BIDX_NUMBER_PROTOTYPE; - goto create_object; - } - } - return; - - create_object: - (void) duk_push_object_helper(ctx, flags, proto); - - /* Note: Boolean prototype's internal value property is not writable, - * but duk_xdef_prop_stridx() disregards the write protection. Boolean - * instances are immutable. - * - * String and buffer special behaviors are already enabled which is not - * ideal, but a write to the internal value is not affected by them. - */ - duk_dup(ctx, index); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); - - replace_value: - duk_replace(ctx, index); -} - -/* - * Type checking - */ - -DUK_LOCAL duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small_uint_t tag) { - duk_tval *tv; - - tv = duk_get_tval(ctx, index); - if (!tv) { - return 0; - } - return (DUK_TVAL_GET_TAG(tv) == tag); -} - -DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t index, duk_uint_t flag_mask) { - duk_hobject *obj; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_get_hobject(ctx, index); - if (obj) { - return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0); - } - return 0; -} - -DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (!tv) { - return DUK_TYPE_NONE; - } - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: - return DUK_TYPE_UNDEFINED; - case DUK_TAG_NULL: - return DUK_TYPE_NULL; - case DUK_TAG_BOOLEAN: - return DUK_TYPE_BOOLEAN; - case DUK_TAG_STRING: - return DUK_TYPE_STRING; - case DUK_TAG_OBJECT: - return DUK_TYPE_OBJECT; - case DUK_TAG_BUFFER: - return DUK_TYPE_BUFFER; - case DUK_TAG_POINTER: - return DUK_TYPE_POINTER; - case DUK_TAG_LIGHTFUNC: - return DUK_TYPE_LIGHTFUNC; -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: -#endif - default: - /* Note: number has no explicit tag (in 8-byte representation) */ - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); - return DUK_TYPE_NUMBER; - } - DUK_UNREACHABLE(); -} - -DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) { - DUK_ASSERT_CTX_VALID(ctx); - - return (duk_get_type(ctx, index) == type) ? 1 : 0; -} - -DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (!tv) { - return DUK_TYPE_MASK_NONE; - } - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: - return DUK_TYPE_MASK_UNDEFINED; - case DUK_TAG_NULL: - return DUK_TYPE_MASK_NULL; - case DUK_TAG_BOOLEAN: - return DUK_TYPE_MASK_BOOLEAN; - case DUK_TAG_STRING: - return DUK_TYPE_MASK_STRING; - case DUK_TAG_OBJECT: - return DUK_TYPE_MASK_OBJECT; - case DUK_TAG_BUFFER: - return DUK_TYPE_MASK_BUFFER; - case DUK_TAG_POINTER: - return DUK_TYPE_MASK_POINTER; - case DUK_TAG_LIGHTFUNC: - return DUK_TYPE_MASK_LIGHTFUNC; -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: -#endif - default: - /* Note: number has no explicit tag (in 8-byte representation) */ - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); - return DUK_TYPE_MASK_NUMBER; - } - DUK_UNREACHABLE(); -} - -DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - if (duk_get_type_mask(ctx, index) & mask) { - return 1; - } - if (mask & DUK_TYPE_MASK_THROW) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE); - DUK_UNREACHABLE(); - } - return 0; -} - -DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_UNDEFINED); -} - -DUK_EXTERNAL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_NULL); -} - -DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - duk_small_uint_t tag; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (!tv) { - return 0; - } - tag = DUK_TVAL_GET_TAG(tv); - return (tag == DUK_TAG_UNDEFINED) || (tag == DUK_TAG_NULL); -} - -DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_BOOLEAN); -} - -DUK_EXTERNAL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - /* - * Number is special because it doesn't have a specific - * tag in the 8-byte representation. - */ - - /* XXX: shorter version for 12-byte representation? */ - - tv = duk_get_tval(ctx, index); - if (!tv) { - return 0; - } - return DUK_TVAL_IS_NUMBER(tv); -} - -DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) { - /* XXX: This will now return false for non-numbers, even though they would - * coerce to NaN (as a general rule). In particular, duk_get_number() - * returns a NaN for non-numbers, so should this function also return - * true for non-numbers? - */ - - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (!tv || !DUK_TVAL_IS_NUMBER(tv)) { - return 0; - } - return DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv)); -} - -DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_STRING); -} - -DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_OBJECT); -} - -DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_BUFFER); -} - -DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_POINTER); -} - -DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__tag_check(ctx, index, DUK_TAG_LIGHTFUNC); -} - -DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) { - duk_hobject *obj; - - DUK_ASSERT_CTX_VALID(ctx); - - obj = duk_get_hobject(ctx, index); - if (obj) { - return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0); - } - return 0; -} - -DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_LIGHTFUNC(tv)) { - return 1; - } - return duk__obj_flag_any_default_false(ctx, - index, - DUK_HOBJECT_FLAG_COMPILEDFUNCTION | - DUK_HOBJECT_FLAG_NATIVEFUNCTION | - DUK_HOBJECT_FLAG_BOUND); -} - -DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__obj_flag_any_default_false(ctx, - index, - DUK_HOBJECT_FLAG_NATIVEFUNCTION); -} - -DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__obj_flag_any_default_false(ctx, - index, - DUK_HOBJECT_FLAG_COMPILEDFUNCTION); -} - -DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__obj_flag_any_default_false(ctx, - index, - DUK_HOBJECT_FLAG_BOUND); -} - -DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT_CTX_VALID(ctx); - return duk__obj_flag_any_default_false(ctx, - index, - DUK_HOBJECT_FLAG_THREAD); -} - -DUK_EXTERNAL duk_bool_t duk_is_callable(duk_context *ctx, duk_idx_t index) { - /* XXX: currently same as duk_is_function() */ - DUK_ASSERT_CTX_VALID(ctx); - return duk_is_function(ctx, index); -} - -DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1); - } - return 0; -} - -DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0); - } - return 0; -} - -DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t index) { - duk_tval *tv; - - DUK_ASSERT_CTX_VALID(ctx); - - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0); - } - return 0; -} - -DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h; - duk_uint_t sanity; - - DUK_ASSERT_CTX_VALID(ctx); - - h = duk_get_hobject(ctx, index); - - sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY; - do { - if (!h) { - return DUK_ERR_NONE; - } - if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) { - return DUK_ERR_EVAL_ERROR; - } - if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) { - return DUK_ERR_RANGE_ERROR; - } - if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) { - return DUK_ERR_REFERENCE_ERROR; - } - if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) { - return DUK_ERR_SYNTAX_ERROR; - } - if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) { - return DUK_ERR_TYPE_ERROR; - } - if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) { - return DUK_ERR_URI_ERROR; - } - if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) { - return DUK_ERR_ERROR; - } - - h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h); - } while (--sanity > 0); - - return DUK_ERR_NONE; -} - -/* - * Pushers - */ - -DUK_INTERNAL void duk_push_tval(duk_context *ctx, duk_tval *tv) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(tv != NULL); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_TVAL(tv_slot, tv); - DUK_TVAL_INCREF(thr, tv); /* no side effects */ -} - -#if defined(DUK_USE_DEBUGGER_SUPPORT) -/* Right now only needed by the debugger. */ -DUK_INTERNAL void duk_push_unused(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_UNDEFINED_UNUSED(tv_slot); -} -#endif - -DUK_EXTERNAL void duk_push_undefined(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_UNDEFINED_ACTUAL(tv_slot); -} - -DUK_EXTERNAL void duk_push_null(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_NULL(tv_slot); -} - -DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val) { - duk_hthread *thr; - duk_tval *tv_slot; - duk_small_int_t b; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */ - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_BOOLEAN(tv_slot, b); -} - -DUK_EXTERNAL void duk_push_true(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot); -} - -DUK_EXTERNAL void duk_push_false(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot); -} - -/* normalize NaN which may not match our canonical internal NaN */ -DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val) { - duk_hthread *thr; - duk_tval *tv_slot; - duk_double_union du; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - du.d = val; - DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_NUMBER(tv_slot, du.d); -} - -DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val) { -#if defined(DUK_USE_FASTINT) - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; -#if DUK_INT_MAX <= 0x7fffffffL - DUK_TVAL_SET_FASTINT_I32(tv_slot, (duk_int32_t) val); -#else - if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) { - DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val); - } else { - duk_double_t = (duk_double_t) val; - DUK_TVAL_SET_NUMBER(tv_slot, d); - } -#endif -#else /* DUK_USE_FASTINT */ - duk_hthread *thr; - duk_tval *tv_slot; - duk_double_t d; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - d = (duk_double_t) val; - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_NUMBER(tv_slot, d); -#endif /* DUK_USE_FASTINT */ -} - -DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val) { -#if defined(DUK_USE_FASTINT) - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; -#if DUK_UINT_MAX <= 0xffffffffUL - DUK_TVAL_SET_FASTINT_U32(tv_slot, (duk_uint32_t) val); -#else - if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */ - /* XXX: take advantage of val being unsigned, no need to mask */ - DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val); - } else { - duk_double_t = (duk_double_t) val; - DUK_TVAL_SET_NUMBER(tv_slot, d); - } -#endif -#else /* DUK_USE_FASTINT */ - duk_hthread *thr; - duk_tval *tv_slot; - duk_double_t d; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - d = (duk_double_t) val; - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_NUMBER(tv_slot, d); -#endif /* DUK_USE_FASTINT */ -} - -DUK_EXTERNAL void duk_push_nan(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv_slot; - duk_double_union du; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - DUK_DBLUNION_SET_NAN(&du); - DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du)); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_NUMBER(tv_slot, du.d); -} - -DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - - /* check stack before interning (avoid hanging temp) */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - /* NULL with zero length represents an empty string; NULL with higher - * length is also now trated like an empty string although it is - * a bit dubious. This is unlike duk_push_string() which pushes a - * 'null' if the input string is a NULL. - */ - if (!str) { - len = 0; - } - - /* Check for maximum string length */ - if (len > DUK_HSTRING_MAX_BYTELEN) { - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_STRING_TOO_LONG); - } - - h = duk_heap_string_intern_checked(thr, (duk_uint8_t *) str, (duk_uint32_t) len); - DUK_ASSERT(h != NULL); - - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_STRING(tv_slot, h); - DUK_HSTRING_INCREF(thr, h); /* no side effects */ - - return (const char *) DUK_HSTRING_GET_DATA(h); -} - -DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) { - DUK_ASSERT_CTX_VALID(ctx); - - if (str) { - return duk_push_lstring(ctx, str, DUK_STRLEN(str)); - } else { - duk_push_null(ctx); - return NULL; - } -} - -#ifdef DUK_USE_FILE_IO -/* This is a bit clunky because it is ANSI C portable. Should perhaps - * relocate to another file because this is potentially platform - * dependent. - */ -DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_file *f = NULL; - char *buf; - long sz; /* ANSI C typing */ - - DUK_ASSERT_CTX_VALID(ctx); - - if (!path) { - goto fail; - } - f = DUK_FOPEN(path, "rb"); - if (!f) { - goto fail; - } - if (DUK_FSEEK(f, 0, SEEK_END) < 0) { - goto fail; - } - sz = DUK_FTELL(f); - if (sz < 0) { - goto fail; - } - if (DUK_FSEEK(f, 0, SEEK_SET) < 0) { - goto fail; - } - buf = (char *) duk_push_fixed_buffer(ctx, (duk_size_t) sz); - DUK_ASSERT(buf != NULL); - if ((duk_size_t) DUK_FREAD(buf, 1, (size_t) sz, f) != (duk_size_t) sz) { - goto fail; - } - (void) DUK_FCLOSE(f); /* ignore fclose() error */ - f = NULL; - return duk_to_string(ctx, -1); - - fail: - if (f) { - DUK_FCLOSE(f); - } - - if (flags != 0) { - DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE); /* only flag now */ - duk_push_undefined(ctx); - } else { - /* XXX: string not shared because it is conditional */ - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "read file error"); - } - return NULL; -} -#else -DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(path); - - if (flags != 0) { - DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE); /* only flag now */ - duk_push_undefined(ctx); - } else { - /* XXX: string not shared because it is conditional */ - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "file I/O disabled"); - } - return NULL; -} -#endif /* DUK_USE_FILE_IO */ - -DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) { - duk_hthread *thr; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK__CHECK_SPACE(); - tv_slot = thr->valstack_top++; - DUK_TVAL_SET_POINTER(tv_slot, val); -} - -#define DUK__PUSH_THIS_FLAG_CHECK_COERC (1 << 0) -#define DUK__PUSH_THIS_FLAG_TO_OBJECT (1 << 1) -#define DUK__PUSH_THIS_FLAG_TO_STRING (1 << 2) - -DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */ - DUK_ASSERT(thr->callstack_top <= thr->callstack_size); - - if (thr->callstack_top == 0) { - if (flags & DUK__PUSH_THIS_FLAG_CHECK_COERC) { - goto type_error; - } - duk_push_undefined(ctx); - } else { - duk_tval tv_tmp; - duk_tval *tv; - - /* 'this' binding is just before current activation's bottom */ - DUK_ASSERT(thr->valstack_bottom > thr->valstack); - tv = thr->valstack_bottom - 1; - if (flags & DUK__PUSH_THIS_FLAG_CHECK_COERC) { - if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) { - goto type_error; - } - } - - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - duk_push_tval(ctx, &tv_tmp); - } - - if (flags & DUK__PUSH_THIS_FLAG_TO_OBJECT) { - duk_to_object(ctx, -1); - } else if (flags & DUK__PUSH_THIS_FLAG_TO_STRING) { - duk_to_string(ctx, -1); - } - - return; - - type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_OBJECT_COERCIBLE); -} - -DUK_EXTERNAL void duk_push_this(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - duk__push_this_helper(ctx, 0 /*flags*/); -} - -DUK_INTERNAL void duk_push_this_check_object_coercible(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC /*flags*/); -} - -DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) { - duk_hobject *h; - - DUK_ASSERT_CTX_VALID(ctx); - - duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC | - DUK__PUSH_THIS_FLAG_TO_OBJECT /*flags*/); - h = duk_get_hobject(ctx, -1); - DUK_ASSERT(h != NULL); - return h; -} - -DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) { - duk_hstring *h; - - DUK_ASSERT_CTX_VALID(ctx); - - duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC | - DUK__PUSH_THIS_FLAG_TO_STRING /*flags*/); - h = duk_get_hstring(ctx, -1); - DUK_ASSERT(h != NULL); - return h; -} - -DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx) { - duk_hthread *thr; - - DUK_ASSERT(ctx != NULL); - thr = (duk_hthread *) ctx; - - DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */ - DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */ - DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */ - - return thr->valstack_bottom - 1; -} - -DUK_EXTERNAL void duk_push_current_function(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT_DISABLE(thr->callstack_top >= 0); - DUK_ASSERT(thr->callstack_top <= thr->callstack_size); - - act = duk_hthread_get_current_activation(thr); - if (act) { - duk_push_tval(ctx, &act->tv_func); - } else { - duk_push_undefined(ctx); - } -} - -DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - - if (thr->heap->curr_thread) { - duk_push_hobject(ctx, (duk_hobject *) thr->heap->curr_thread); - } else { - duk_push_undefined(ctx); - } -} - -DUK_EXTERNAL void duk_push_global_object(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL); -} - -/* XXX: size optimize */ -DUK_LOCAL void duk__push_stash(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE)) { - DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use")); - duk_pop(ctx); - duk_push_object_internal(ctx); - duk_dup_top(ctx); - duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */ - } - duk_remove(ctx, -2); -} - -DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_heap *heap; - DUK_ASSERT_CTX_VALID(ctx); - heap = thr->heap; - DUK_ASSERT(heap->heap_object != NULL); - duk_push_hobject(ctx, heap->heap_object); - duk__push_stash(ctx); -} - -DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - duk_push_global_object(ctx); - duk__push_stash(ctx); -} - -DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT_CTX_VALID(ctx); - if (!target_ctx) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - return; /* not reached */ - } - duk_push_hobject(ctx, (duk_hobject *) target_ctx); - duk__push_stash(ctx); -} - -/* XXX: duk_ssize_t would be useful here */ -DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) { - duk_int_t len; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_UNREF(ctx); - - /* NUL terminator handling doesn't matter here */ - len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap); - if (len < (duk_int_t) sz) { - /* Return value of 'sz' or more indicates output was (potentially) - * truncated. - */ - return (duk_int_t) len; - } - return -1; -} - -DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE]; - duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE; - duk_bool_t pushed_buf = 0; - void *buf; - duk_int_t len; /* XXX: duk_ssize_t */ - const char *res; - - DUK_ASSERT_CTX_VALID(ctx); - - /* special handling of fmt==NULL */ - if (!fmt) { - duk_hstring *h_str; - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); - h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr); /* rely on interning, must be this string */ - return (const char *) DUK_HSTRING_GET_DATA(h_str); - } - - /* initial estimate based on format string */ - sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */ - if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) { - sz = DUK_PUSH_SPRINTF_INITIAL_SIZE; - } - DUK_ASSERT(sz > 0); - - /* Try to make do with a stack buffer to avoid allocating a temporary buffer. - * This works 99% of the time which is quite nice. - */ - for (;;) { - va_list ap_copy; /* copied so that 'ap' can be reused */ - - if (sz <= sizeof(stack_buf)) { - buf = stack_buf; - } else if (!pushed_buf) { - pushed_buf = 1; - buf = duk_push_dynamic_buffer(ctx, sz); - } else { - buf = duk_resize_buffer(ctx, -1, sz); - } - DUK_ASSERT(buf != NULL); - - DUK_VA_COPY(ap_copy, ap); - len = duk__try_push_vsprintf(ctx, buf, sz, fmt, ap_copy); - va_end(ap_copy); - if (len >= 0) { - break; - } - - /* failed, resize and try again */ - sz = sz * 2; - if (sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_SPRINTF_TOO_LONG); - } - } - - /* Cannot use duk_to_string() on the buffer because it is usually - * larger than 'len'. Also, 'buf' is usually a stack buffer. - */ - res = duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */ - if (pushed_buf) { - duk_remove(ctx, -2); - } - return res; -} - -DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) { - va_list ap; - const char *ret; - - DUK_ASSERT_CTX_VALID(ctx); - - /* allow fmt==NULL */ - va_start(ap, fmt); - ret = duk_push_vsprintf(ctx, fmt, ap); - va_end(ap); - - return ret; -} - -DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv_slot; - duk_hobject *h; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(prototype_bidx == -1 || - (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS)); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - h = duk_hobject_alloc(thr->heap, hobject_flags_and_class); - if (!h) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - - DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags)); - - tv_slot = thr->valstack_top; - DUK_TVAL_SET_OBJECT(tv_slot, h); - DUK_HOBJECT_INCREF(thr, h); /* no side effects */ - ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - thr->valstack_top++; - - /* object is now reachable */ - - if (prototype_bidx >= 0) { - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[prototype_bidx]); - } else { - DUK_ASSERT(prototype_bidx == -1); - DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL); - } - - return ret; -} - -DUK_INTERNAL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t ret; - duk_hobject *h; - - DUK_ASSERT_CTX_VALID(ctx); - - ret = duk_push_object_helper(ctx, hobject_flags_and_class, -1); - h = duk_get_hobject(ctx, -1); - DUK_ASSERT(h != NULL); - DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL); - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, proto); - return ret; -} - -DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - return duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT), - DUK_BIDX_OBJECT_PROTOTYPE); -} - -DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *obj; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - ret = duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_ARRAY_PART | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY), - DUK_BIDX_ARRAY_PROTOTYPE); - - obj = duk_require_hobject(ctx, ret); - - /* - * An array must have a 'length' property (E5 Section 15.4.5.2). - * The special array behavior flag must only be enabled once the - * length property has been added. - * - * The internal property must be a number (and preferably a - * fastint if fastint support is enabled). - */ - - duk_push_int(ctx, 0); -#if defined(DUK_USE_FASTINT) - DUK_ASSERT(DUK_TVAL_IS_FASTINT(duk_require_tval(ctx, -1))); -#endif - - duk_hobject_define_property_internal(thr, - obj, - DUK_HTHREAD_STRING_LENGTH(thr), - DUK_PROPDESC_FLAGS_W); - DUK_HOBJECT_SET_EXOTIC_ARRAY(obj); - - return ret; -} - -DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hthread *obj; - duk_idx_t ret; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - obj = duk_hthread_alloc(thr->heap, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_THREAD | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD)); - if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - obj->state = DUK_HTHREAD_STATE_INACTIVE; -#if defined(DUK_USE_HEAPPTR16) - obj->strs16 = thr->strs16; -#else - obj->strs = thr->strs; -#endif - DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags)); - - /* make the new thread reachable */ - tv_slot = thr->valstack_top; - DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj); - DUK_HTHREAD_INCREF(thr, obj); - ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - thr->valstack_top++; - - /* important to do this *after* pushing, to make the thread reachable for gc */ - if (!duk_hthread_init_stacks(thr->heap, obj)) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - - /* initialize built-ins - either by copying or creating new ones */ - if (flags & DUK_THREAD_NEW_GLOBAL_ENV) { - duk_hthread_create_builtin_objects(obj); - } else { - duk_hthread_copy_builtin_objects(thr, obj); - } - - /* default prototype (Note: 'obj' must be reachable) */ - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]); - - /* Initial stack size satisfies the stack spare constraints so there - * is no need to require stack here. - */ - DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >= - DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA); - - return ret; -} - -DUK_INTERNAL duk_idx_t duk_push_compiledfunction(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hcompiledfunction *obj; - duk_idx_t ret; - duk_tval *tv_slot; - - DUK_ASSERT_CTX_VALID(ctx); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - /* Template functions are not strictly constructable (they don't - * have a "prototype" property for instance), so leave the - * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here. - */ - - obj = duk_hcompiledfunction_alloc(thr->heap, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_COMPILEDFUNCTION | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION)); - if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - - DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags)); - - tv_slot = thr->valstack_top; - DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj); - DUK_HOBJECT_INCREF(thr, obj); - ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - thr->valstack_top++; - - /* default prototype (Note: 'obj' must be reachable) */ - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]); - - return ret; -} - -DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hnativefunction *obj; - duk_idx_t ret; - duk_tval *tv_slot; - duk_uint16_t func_nargs; - - DUK_ASSERT_CTX_VALID(ctx); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - if (func == NULL) { - goto api_error; - } - if (nargs >= 0 && nargs < DUK_HNATIVEFUNCTION_NARGS_MAX) { - func_nargs = (duk_uint16_t) nargs; - } else if (nargs == DUK_VARARGS) { - func_nargs = DUK_HNATIVEFUNCTION_NARGS_VARARGS; - } else { - goto api_error; - } - - obj = duk_hnativefunction_alloc(thr->heap, flags); - if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - - obj->func = func; - obj->nargs = func_nargs; - - DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld", - (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs)); - - tv_slot = thr->valstack_top; - DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj); - DUK_HOBJECT_INCREF(thr, obj); - ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - thr->valstack_top++; - - /* default prototype (Note: 'obj' must be reachable) */ - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]); - - return ret; - - api_error: - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - return 0; /* not reached */ -} - -DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs) { - duk_uint_t flags; - - DUK_ASSERT_CTX_VALID(ctx); - - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_CONSTRUCTABLE | - DUK_HOBJECT_FLAG_NATIVEFUNCTION | - DUK_HOBJECT_FLAG_NEWENV | - DUK_HOBJECT_FLAG_STRICT | - DUK_HOBJECT_FLAG_NOTAIL | - DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION); - - return duk__push_c_function_raw(ctx, func, nargs, flags); -} - -DUK_INTERNAL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) { - duk_uint_t flags; - - DUK_ASSERT_CTX_VALID(ctx); - - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_CONSTRUCTABLE | - DUK_HOBJECT_FLAG_NATIVEFUNCTION | - DUK_HOBJECT_FLAG_NEWENV | - DUK_HOBJECT_FLAG_STRICT | - DUK_HOBJECT_FLAG_NOTAIL | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION); - - (void) duk__push_c_function_raw(ctx, func, nargs, flags); -} - -DUK_INTERNAL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) { - duk_uint_t flags; - - DUK_ASSERT_CTX_VALID(ctx); - - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_NATIVEFUNCTION | - DUK_HOBJECT_FLAG_NEWENV | - DUK_HOBJECT_FLAG_STRICT | - DUK_HOBJECT_FLAG_NOTAIL | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION); - - (void) duk__push_c_function_raw(ctx, func, nargs, flags); -} - -DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval tv_tmp; - duk_small_uint_t lf_flags; - - DUK_ASSERT_CTX_VALID(ctx); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) { - /* as is */ - } else if (nargs == DUK_VARARGS) { - nargs = DUK_LFUNC_NARGS_VARARGS; - } else { - goto api_error; - } - if (!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX)) { - goto api_error; - } - if (!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX)) { - goto api_error; - } - - lf_flags = DUK_LFUNC_FLAGS_PACK(magic, length, nargs); - DUK_TVAL_SET_LIGHTFUNC(&tv_tmp, func, lf_flags); - duk_push_tval(ctx, &tv_tmp); /* XXX: direct valstack write */ - DUK_ASSERT(thr->valstack_top != thr->valstack_bottom); - return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1; - - api_error: - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - return 0; /* not reached */ -} - -DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hbufferobject *obj; - duk_tval *tv_slot; - - DUK_ASSERT(ctx != NULL); - DUK_ASSERT(prototype_bidx >= 0); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class); - if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]); - DUK_ASSERT_HBUFFEROBJECT_VALID(obj); - - tv_slot = thr->valstack_top; - DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj); - DUK_HOBJECT_INCREF(thr, obj); - thr->valstack_top++; - - return obj; -} - -/* XXX: There's quite a bit of overlap with buffer creation handling in - * duk_bi_buffer.c. Look for overlap and refactor. - */ -#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,isview) \ - (((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (isview)) - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -static const duk_uint32_t duk__bufobj_flags_lookup[] = { - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER, DUK_BIDX_BUFFER_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_DUKTAPE_BUFFER */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_NODEJS_BUFFER */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER, DUK_BIDX_ARRAYBUFFER_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_ARRAYBUFFER */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW, DUK_BIDX_DATAVIEW_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8, 0, 1), /* DUK_BUFOBJ_DATAVIEW */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY, DUK_BIDX_INT8ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_INT8, 0, 1), /* DUK_BUFOBJ_INT8ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY, DUK_BIDX_UINT8ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8, 0, 1), /* DUK_BUFOBJ_UINT8ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED, 0, 1), /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY, DUK_BIDX_INT16ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_INT16, 1, 1), /* DUK_BUFOBJ_INT16ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY, DUK_BIDX_UINT16ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT16, 1, 1), /* DUK_BUFOBJ_UINT16ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY, DUK_BIDX_INT32ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_INT32, 2, 1), /* DUK_BUFOBJ_INT32ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY, DUK_BIDX_UINT32ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT32, 2, 1), /* DUK_BUFOBJ_UINT32ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY, DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_FLOAT32, 2, 1), /* DUK_BUFOBJ_FLOAT32ARRAY */ - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY, DUK_BIDX_FLOAT64ARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_FLOAT64, 3, 1) /* DUK_BUFOBJ_FLOAT64ARRAY */ -}; -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -/* Only allow Duktape.Buffer when support disabled. */ -static const duk_uint32_t duk__bufobj_flags_lookup[] = { - DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER, DUK_BIDX_BUFFER_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8, 0, 0) /* DUK_BUFOBJ_DUKTAPE_BUFFER */ -}; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ -#undef DUK__PACK_ARGS - -DUK_EXTERNAL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) { - duk_hthread *thr; - duk_hbufferobject *h_bufobj; - duk_hbuffer *h_val; - duk_uint32_t tmp; - duk_uint_t classnum; - duk_uint_t protobidx; - duk_uint_t lookupidx; - duk_uint_t uint_offset, uint_length, uint_added; - - DUK_ASSERT_CTX_VALID(ctx); - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - /* The underlying types for offset/length in duk_hbufferobject is - * duk_uint_t; make sure argument values fit and that offset + length - * does not wrap. - */ - uint_offset = (duk_uint_t) byte_offset; - uint_length = (duk_uint_t) byte_length; - if (sizeof(duk_size_t) != sizeof(duk_uint_t)) { - if ((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length) { - goto range_error; - } - } - uint_added = uint_offset + uint_length; - if (uint_added < uint_offset) { - goto range_error; - } - DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length); - - DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */ - lookupidx = flags & 0x0f; /* 4 low bits */ - if (lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t)) { - goto arg_error; - } - tmp = duk__bufobj_flags_lookup[lookupidx]; - classnum = tmp >> 24; - protobidx = (tmp >> 16) & 0xff; - - h_val = duk_require_hbuffer(ctx, idx_buffer); - DUK_ASSERT(h_val != NULL); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(classnum), - protobidx); - DUK_ASSERT(h_bufobj != NULL); - - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - h_bufobj->offset = uint_offset; - h_bufobj->length = uint_length; - h_bufobj->shift = (tmp >> 4) & 0x0f; - h_bufobj->elem_type = (tmp >> 8) & 0xff; - h_bufobj->is_view = tmp & 0x0f; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) - /* TypedArray views need an automatic ArrayBuffer which must be - * provided as .buffer property of the view. Just create a new - * ArrayBuffer sharing the same underlying buffer. - */ - if (flags & DUK_BUFOBJ_CREATE_ARRBUF) { - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER), - DUK_BIDX_ARRAYBUFFER_PROTOTYPE); - - DUK_ASSERT(h_bufobj != NULL); - - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - h_bufobj->offset = uint_offset; - h_bufobj->length = uint_length; - DUK_ASSERT(h_bufobj->shift == 0); - h_bufobj->elem_type = DUK_HBUFFEROBJECT_ELEM_UINT8; - DUK_ASSERT(h_bufobj->is_view == 0); - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); - duk_compact(ctx, -1); - } -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - - return; - - range_error: - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_INVALID_CALL_ARGS); - return; /* not reached */ - - arg_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_CALL_ARGS); - return; /* not reached */ -} - -DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t ret; - duk_hobject *proto; -#ifdef DUK_USE_AUGMENT_ERROR_CREATE - duk_bool_t noblame_fileline; -#endif - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_UNREF(filename); - DUK_UNREF(line); - - /* Error code also packs a tracedata related flag. */ -#ifdef DUK_USE_AUGMENT_ERROR_CREATE - noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE; -#endif - err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE); - - /* error gets its 'name' from the prototype */ - proto = duk_error_prototype_from_code(thr, err_code); - ret = duk_push_object_helper_proto(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR), - proto); - - /* ... and its 'message' from an instance property */ - if (fmt) { - duk_push_vsprintf(ctx, fmt, ap); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC); - } else { - /* If no explicit message given, put error code into message field - * (as a number). This is not fully in keeping with the Ecmascript - * error model because messages are supposed to be strings (Error - * constructors use ToString() on their argument). However, it's - * probably more useful than having a separate 'code' property. - */ - duk_push_int(ctx, err_code); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC); - } - -#if 0 - /* Disabled for now, not sure this is a useful property */ - duk_push_int(ctx, err_code); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CODE, DUK_PROPDESC_FLAGS_WC); -#endif - - /* Creation time error augmentation */ -#ifdef DUK_USE_AUGMENT_ERROR_CREATE - /* filename may be NULL in which case file/line is not recorded */ - duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline); /* may throw an error */ -#endif - - return ret; -} - -DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) { - va_list ap; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - va_start(ap, fmt); - ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); - va_end(ap); - return ret; -} - -#if !defined(DUK_USE_VARIADIC_MACROS) -DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) { - const char *filename = duk_api_global_filename; - duk_int_t line = duk_api_global_line; - va_list ap; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - duk_api_global_filename = NULL; - duk_api_global_line = 0; - va_start(ap, fmt); - ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); - va_end(ap); - return ret; -} -#endif /* DUK_USE_VARIADIC_MACROS */ - -DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv_slot; - duk_hbuffer *h; - void *buf_data; - - DUK_ASSERT_CTX_VALID(ctx); - - /* check stack first */ - if (thr->valstack_top >= thr->valstack_end) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); - } - - /* Check for maximum buffer length. */ - if (size > DUK_HBUFFER_MAX_BYTELEN) { - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_BUFFER_TOO_LONG); - } - - h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data); - if (!h) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); - } - - tv_slot = thr->valstack_top; - DUK_TVAL_SET_BUFFER(tv_slot, h); - DUK_HBUFFER_INCREF(thr, h); - thr->valstack_top++; - - return (void *) buf_data; -} - -DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t ret; - - DUK_ASSERT_CTX_VALID(ctx); - - ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); - - if (ptr == NULL) { - goto push_undefined; - } - - switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) { - case DUK_HTYPE_STRING: - duk_push_hstring(ctx, (duk_hstring *) ptr); - break; - case DUK_HTYPE_OBJECT: - duk_push_hobject(ctx, (duk_hobject *) ptr); - break; - case DUK_HTYPE_BUFFER: - duk_push_hbuffer(ctx, (duk_hbuffer *) ptr); - break; - default: - goto push_undefined; - } - return ret; - - push_undefined: - duk_push_undefined(ctx); - return ret; -} - -DUK_INTERNAL duk_idx_t duk_push_object_internal(duk_context *ctx) { - return duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT), - -1); /* no prototype */ -} - -DUK_INTERNAL void duk_push_hstring(duk_context *ctx, duk_hstring *h) { - duk_tval tv; - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(h != NULL); - DUK_TVAL_SET_STRING(&tv, h); - duk_push_tval(ctx, &tv); -} - -DUK_INTERNAL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx) { - duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS); - duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx)); -} - -DUK_INTERNAL void duk_push_hobject(duk_context *ctx, duk_hobject *h) { - duk_tval tv; - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(h != NULL); - DUK_TVAL_SET_OBJECT(&tv, h); - duk_push_tval(ctx, &tv); -} - -DUK_INTERNAL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) { - duk_tval tv; - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(h != NULL); - DUK_TVAL_SET_BUFFER(&tv, h); - duk_push_tval(ctx, &tv); -} - -DUK_INTERNAL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx) { - duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS); - DUK_ASSERT(thr->builtins[builtin_idx] != NULL); - duk_push_hobject(ctx, thr->builtins[builtin_idx]); -} - -/* - * Poppers - */ - -DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - - if (count < 0) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT); - return; - } - - DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); - if ((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_POP_TOO_MANY); - } - - /* - * Must be very careful here, every DECREF may cause reallocation - * of our valstack. - */ - - /* XXX: inlined DECREF macro would be nice here: no NULL check, - * refzero queueing but no refzero algorithm run (= no pointer - * instability), inline code. - */ - -#ifdef DUK_USE_REFERENCE_COUNTING - while (count > 0) { - duk_tval tv_tmp; - duk_tval *tv; - - tv = --thr->valstack_top; /* tv points to element just below prev top */ - DUK_ASSERT(tv >= thr->valstack_bottom); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_UNDEFINED_UNUSED(tv); - DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */ - count--; - } -#else - while (count > 0) { - duk_tval *tv; - - tv = --thr->valstack_top; - DUK_ASSERT(tv >= thr->valstack_bottom); - DUK_TVAL_SET_UNDEFINED_UNUSED(tv); - count--; - } -#endif - - DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); -} - -DUK_EXTERNAL void duk_pop(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - duk_pop_n(ctx, 1); -} - -DUK_EXTERNAL void duk_pop_2(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - duk_pop_n(ctx, 2); -} - -DUK_EXTERNAL void duk_pop_3(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - duk_pop_n(ctx, 3); -} - -/* - * Error throwing - */ - -DUK_EXTERNAL void duk_throw(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT(thr->valstack_bottom >= thr->valstack); - DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); - DUK_ASSERT(thr->valstack_end >= thr->valstack_top); - - if (thr->valstack_top == thr->valstack_bottom) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); - } - - /* Errors are augmented when they are created, not when they are - * thrown or re-thrown. The current error handler, however, runs - * just before an error is thrown. - */ - - /* Sync so that augmentation sees up-to-date activations, NULL - * thr->ptr_curr_pc so that it's not used if side effects occur - * in augmentation or longjmp handling. - */ - duk_hthread_sync_and_null_currpc(thr); - -#if defined(DUK_USE_AUGMENT_ERROR_THROW) - DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1))); - duk_err_augment_error_throw(thr); -#endif - DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1))); - - duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW); - - /* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't - * need to check that here. If the value is NULL, a panic occurs because - * we can't return. - */ - - duk_err_longjmp(thr); - DUK_UNREACHABLE(); -} - -DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) { - duk_hthread *thr = (duk_hthread *) ctx; - - DUK_ASSERT_CTX_VALID(ctx); - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->heap != NULL); - DUK_ASSERT(thr->heap->fatal_func != NULL); - - DUK_D(DUK_DPRINT("fatal error occurred, code %ld, message %s", - (long) err_code, (const char *) err_msg)); - - /* fatal_func should be noreturn, but noreturn declarations on function - * pointers has a very spotty support apparently so it's not currently - * done. - */ - thr->heap->fatal_func(ctx, err_code, err_msg); - - DUK_PANIC(DUK_ERR_API_ERROR, "fatal handler returned"); -} - -DUK_EXTERNAL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) { - DUK_ASSERT_CTX_VALID(ctx); - - duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); - duk_throw(ctx); -} - -DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) { - va_list ap; - - DUK_ASSERT_CTX_VALID(ctx); - - va_start(ap, fmt); - duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); - va_end(ap); - duk_throw(ctx); -} - -#if !defined(DUK_USE_VARIADIC_MACROS) -DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) { - const char *filename; - duk_int_t line; - va_list ap; - - DUK_ASSERT_CTX_VALID(ctx); - - filename = duk_api_global_filename; - line = duk_api_global_line; - duk_api_global_filename = NULL; - duk_api_global_line = 0; - - va_start(ap, fmt); - duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); - va_end(ap); - duk_throw(ctx); -} -#endif /* DUK_USE_VARIADIC_MACROS */ - -/* - * Comparison - */ - -DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv1, *tv2; - - DUK_ASSERT_CTX_VALID(ctx); - - tv1 = duk_get_tval(ctx, index1); - tv2 = duk_get_tval(ctx, index2); - if ((tv1 == NULL) || (tv2 == NULL)) { - return 0; - } - - /* Coercion may be needed, the helper handles that by pushing the - * tagged values to the stack. - */ - return duk_js_equals(thr, tv1, tv2); -} - -DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) { - duk_tval *tv1, *tv2; - - DUK_ASSERT_CTX_VALID(ctx); - - tv1 = duk_get_tval(ctx, index1); - tv2 = duk_get_tval(ctx, index2); - if ((tv1 == NULL) || (tv2 == NULL)) { - return 0; - } - - /* No coercions or other side effects, so safe */ - return duk_js_strict_equals(tv1, tv2); -} - -/* - * instanceof - */ - -DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) { - duk_tval *tv1, *tv2; - - DUK_ASSERT_CTX_VALID(ctx); - - /* Index validation is strict, which differs from duk_equals(). - * The strict behavior mimics how instanceof itself works, e.g. - * it is a TypeError if rval is not a -callable- object. It would - * be somewhat inconsistent if rval would be allowed to be - * non-existent without a TypeError. - */ - tv1 = duk_require_tval(ctx, index1); - DUK_ASSERT(tv1 != NULL); - tv2 = duk_require_tval(ctx, index2); - DUK_ASSERT(tv2 != NULL); - - return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2); -} - -/* - * Lightfunc - */ - -DUK_INTERNAL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv) { - duk_c_function func; - - DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv)); - - /* Lightfunc name, includes Duktape/C native function pointer, which - * can often be used to locate the function from a symbol table. - * The name also includes the 16-bit duk_tval flags field because it - * includes the magic value. Because a single native function often - * provides different functionality depending on the magic value, it - * seems reasonably to include it in the name. - * - * On the other hand, a complicated name increases string table - * pressure in low memory environments (but only when function name - * is accessed). - */ - - func = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv); - duk_push_sprintf(ctx, "light_"); - duk_push_string_funcptr(ctx, (duk_uint8_t *) &func, sizeof(func)); - duk_push_sprintf(ctx, "_%04x", (unsigned int) DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)); - duk_concat(ctx, 3); -} - -DUK_INTERNAL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv) { - DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv)); - - duk_push_string(ctx, "function "); - duk_push_lightfunc_name(ctx, tv); - duk_push_string(ctx, "() {/* light */}"); - duk_concat(ctx, 3); -} - -/* - * Function pointers - * - * Printing function pointers is non-portable, so we do that by hex printing - * bytes from memory. - */ - -DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz) { - duk_uint8_t buf[32 * 2]; - duk_uint8_t *p, *q; - duk_small_uint_t i; - duk_small_uint_t t; - - DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */ - - p = buf; -#if defined(DUK_USE_INTEGER_LE) - q = ptr + sz; -#else - q = ptr; -#endif - for (i = 0; i < sz; i++) { -#if defined(DUK_USE_INTEGER_LE) - t = *(--q); -#else - t = *(q++); -#endif - *p++ = duk_lc_digits[t >> 4]; - *p++ = duk_lc_digits[t & 0x0f]; - } - - duk_push_lstring(ctx, (const char *) buf, sz * 2); -} - -#undef DUK__CHECK_SPACE diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_string.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_string.c deleted file mode 100644 index 4d23c932..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_string.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * String manipulation - */ - -#include "duk_internal.h" - -DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_uint_t count; - duk_uint_t i; - duk_size_t idx; - duk_size_t len; - duk_hstring *h; - duk_uint8_t *buf; - - DUK_ASSERT_CTX_VALID(ctx); - - if (DUK_UNLIKELY(count_in <= 0)) { - if (count_in < 0) { - DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT); - return; - } - DUK_ASSERT(count_in == 0); - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); - return; - } - count = (duk_uint_t) count_in; - - if (is_join) { - duk_size_t t1, t2, limit; - h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1); - DUK_ASSERT(h != NULL); - - /* A bit tricky overflow test, see doc/code-issues.rst. */ - t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h); - t2 = (duk_size_t) (count - 1); - limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN; - if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) { - /* Combined size of separators already overflows */ - goto error_overflow; - } - len = (duk_size_t) (t1 * t2); - } else { - len = (duk_size_t) 0; - } - - for (i = count; i >= 1; i--) { - duk_size_t new_len; - duk_to_string(ctx, -((duk_idx_t) i)); - h = duk_require_hstring(ctx, -((duk_idx_t) i)); - new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h); - - /* Impose a string maximum length, need to handle overflow - * correctly. - */ - if (new_len < len || /* wrapped */ - new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) { - goto error_overflow; - } - len = new_len; - } - - DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes", - (unsigned long) count, (unsigned long) len)); - - /* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */ - buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len); - DUK_ASSERT(buf != NULL); - - /* [... (sep) str1 str2 ... strN buf] */ - - idx = 0; - for (i = count; i >= 1; i--) { - if (is_join && i != count) { - h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2); /* extra -1 for buffer */ - DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); - idx += DUK_HSTRING_GET_BYTELEN(h); - } - h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1); /* extra -1 for buffer */ - DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h)); - idx += DUK_HSTRING_GET_BYTELEN(h); - } - - DUK_ASSERT(idx == len); - - /* [... (sep) str1 str2 ... strN buf] */ - - /* get rid of the strings early to minimize memory use before intern */ - - if (is_join) { - duk_replace(ctx, -((duk_idx_t) count) - 2); /* overwrite sep */ - duk_pop_n(ctx, count); - } else { - duk_replace(ctx, -((duk_idx_t) count) - 1); /* overwrite str1 */ - duk_pop_n(ctx, count-1); - } - - /* [... buf] */ - - (void) duk_to_string(ctx, -1); - - /* [... res] */ - return; - - error_overflow: - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_CONCAT_RESULT_TOO_LONG); -} - -DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) { - DUK_ASSERT_CTX_VALID(ctx); - - duk__concat_and_join_helper(ctx, count, 0 /*is_join*/); -} - -DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) { - DUK_ASSERT_CTX_VALID(ctx); - - duk__concat_and_join_helper(ctx, count, 1 /*is_join*/); -} - -/* XXX: could map/decode be unified with duk_unicode_support.c code? - * Case conversion needs also the character surroundings though. - */ - -DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_input; - const duk_uint8_t *p, *p_start, *p_end; - duk_codepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - h_input = duk_require_hstring(ctx, index); - DUK_ASSERT(h_input != NULL); - - p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); - p = p_start; - - for (;;) { - if (p >= p_end) { - break; - } - cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end); - callback(udata, cp); - } -} - -DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_input; - duk_bufwriter_ctx bw_alloc; - duk_bufwriter_ctx *bw; - const duk_uint8_t *p, *p_start, *p_end; - duk_codepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_normalize_index(ctx, index); - - h_input = duk_require_hstring(ctx, index); - DUK_ASSERT(h_input != NULL); - - bw = &bw_alloc; - DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* reasonable output estimate */ - - p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); - p = p_start; - - for (;;) { - /* XXX: could write output in chunks with fewer ensure calls, - * but relative benefit would be small here. - */ - - if (p >= p_end) { - break; - } - cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end); - cp = callback(udata, cp); - - DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp); - } - - DUK_BW_COMPACT(thr, bw); - duk_to_string(ctx, -1); - duk_replace(ctx, index); -} - -DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - duk_hstring *res; - duk_size_t start_byte_offset; - duk_size_t end_byte_offset; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - h = duk_require_hstring(ctx, index); - DUK_ASSERT(h != NULL); - - if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) { - end_offset = DUK_HSTRING_GET_CHARLEN(h); - } - if (start_offset > end_offset) { - start_offset = end_offset; - } - - DUK_ASSERT_DISABLE(start_offset >= 0); - DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h)); - DUK_ASSERT_DISABLE(end_offset >= 0); - DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h)); - - /* guaranteed by string limits */ - DUK_ASSERT(start_offset <= DUK_UINT32_MAX); - DUK_ASSERT(end_offset <= DUK_UINT32_MAX); - - start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset); - end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset); - - DUK_ASSERT(end_byte_offset >= start_byte_offset); - DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* guaranteed by string limits */ - - /* no size check is necessary */ - res = duk_heap_string_intern_checked(thr, - DUK_HSTRING_GET_DATA(h) + start_byte_offset, - (duk_uint32_t) (end_byte_offset - start_byte_offset)); - - duk_push_hstring(ctx, res); - duk_replace(ctx, index); -} - -/* XXX: this is quite clunky. Add Unicode helpers to scan backwards and - * forwards with a callback to process codepoints? - */ -DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */ - const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */ - duk_codepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - index = duk_require_normalize_index(ctx, index); - h = duk_require_hstring(ctx, index); - DUK_ASSERT(h != NULL); - - p_start = DUK_HSTRING_GET_DATA(h); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h); - - p = p_start; - while (p < p_end) { - p_tmp1 = p; - cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end); - if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) { - break; - } - p = p_tmp1; - } - q_start = p; - if (p == p_end) { - /* entire string is whitespace */ - q_end = p; - goto scan_done; - } - - p = p_end; - while (p > p_start) { - p_tmp1 = p; - while (p > p_start) { - p--; - if (((*p) & 0xc0) != 0x80) { - break; - } - } - p_tmp2 = p; - - cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end); - if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) { - p = p_tmp1; - break; - } - } - q_end = p; - - scan_done: - /* This may happen when forward and backward scanning disagree - * (possible for non-extended-UTF-8 strings). - */ - if (q_end < q_start) { - q_end = q_start; - } - - DUK_ASSERT(q_start >= p_start && q_start <= p_end); - DUK_ASSERT(q_end >= p_start && q_end <= p_end); - DUK_ASSERT(q_end >= q_start); - - DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p", - (void *) p_start, (void *) p_end, (void *) q_start, (void *) q_end)); - - if (q_start == p_start && q_end == p_end) { - DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)")); - return; - } - - duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start)); - duk_replace(ctx, index); -} - -DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - duk_ucodepoint_t cp; - - DUK_ASSERT_CTX_VALID(ctx); - - h = duk_require_hstring(ctx, index); - DUK_ASSERT(h != NULL); - - DUK_ASSERT_DISABLE(char_offset >= 0); /* always true, arg is unsigned */ - if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) { - return 0; - } - - DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* guaranteed by string limits */ - cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset); - return (duk_codepoint_t) cp; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_api_var.c b/src/third_party/duktape-1.3.0/src-separate/duk_api_var.c deleted file mode 100644 index 23629d84..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_api_var.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Variable access - */ - -#include "duk_internal.h" - -DUK_EXTERNAL void duk_get_var(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - duk_hstring *h_varname; - duk_small_int_t throw_flag = 1; /* always throw ReferenceError for unresolvable */ - - DUK_ASSERT_CTX_VALID(ctx); - - h_varname = duk_require_hstring(ctx, -1); /* XXX: tostring? */ - DUK_ASSERT(h_varname != NULL); - - act = duk_hthread_get_current_activation(thr); - if (act) { - (void) duk_js_getvar_activation(thr, act, h_varname, throw_flag); /* -> [ ... varname val this ] */ - } else { - /* Outside any activation -> look up from global. */ - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL); - (void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag); - } - - /* [ ... varname val this ] (because throw_flag == 1, always resolved) */ - - duk_pop(ctx); - duk_remove(ctx, -2); - - /* [ ... val ] */ - - /* Return value would be pointless: because throw_flag==1, we always - * throw if the identifier doesn't resolve. - */ - return; -} - -DUK_EXTERNAL void duk_put_var(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - duk_hstring *h_varname; - duk_tval *tv_val; - duk_small_int_t throw_flag; - - DUK_ASSERT_CTX_VALID(ctx); - - h_varname = duk_require_hstring(ctx, -2); /* XXX: tostring? */ - DUK_ASSERT(h_varname != NULL); - - tv_val = duk_require_tval(ctx, -1); - - throw_flag = duk_is_strict_call(ctx); - - act = duk_hthread_get_current_activation(thr); - if (act) { - duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag); /* -> [ ... varname val this ] */ - } else { - /* Outside any activation -> put to global. */ - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL); - duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag); - } - - /* [ ... varname val ] */ - - duk_pop_2(ctx); - - /* [ ... ] */ - - return; -} - -DUK_EXTERNAL duk_bool_t duk_del_var(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED); - return 0; -} - -DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx) { - DUK_ASSERT_CTX_VALID(ctx); - - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED); - return 0; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_array.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_array.c deleted file mode 100644 index 10c201dd..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_array.c +++ /dev/null @@ -1,1450 +0,0 @@ -/* - * Array built-ins - * - * Note that most Array built-ins are intentionally generic and work even - * when the 'this' binding is not an Array instance. To ensure this, - * Array algorithms do not assume "magical" Array behavior for the "length" - * property, for instance. - * - * XXX: the "Throw" flag should be set for (almost?) all [[Put]] and - * [[Delete]] operations, but it's currently false throughout. Go through - * all put/delete cases and check throw flag use. Need a new API primitive - * which allows throws flag to be specified. - * - * XXX: array lengths above 2G won't work reliably. There are many places - * where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff], - * i.e. -33- bits). Although array 'length' cannot be written to be outside - * the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so) - * some intermediate values may be above 0xffffffff and this may not be always - * correctly handled now (duk_uint32_t is not enough for all algorithms). - * - * For instance, push() can legitimately write entries beyond length 0xffffffff - * and cause a RangeError only at the end. To do this properly, the current - * push() implementation tracks the array index using a 'double' instead of a - * duk_uint32_t (which is somewhat awkward). See test-bi-array-push-maxlen.js. - * - * On using "put" vs. "def" prop - * ============================= - * - * Code below must be careful to use the appropriate primitive as it matters - * for compliance. When using "put" there may be inherited properties in - * Array.prototype which cause side effects when values are written. When - * using "define" there are no such side effects, and many test262 test cases - * check for this (for real world code, such side effects are very rare). - * Both "put" and "define" are used in the E5.1 specification; as a rule, - * "put" is used when modifying an existing array (or a non-array 'this' - * binding) and "define" for setting values into a fresh result array. - * - * Also note that Array instance 'length' should be writable, but not - * enumerable and definitely not configurable: even Duktape code internally - * assumes that an Array instance will always have a 'length' property. - * Preventing deletion of the property is critical. - */ - -#include "duk_internal.h" - -/* Perform an intermediate join when this many elements have been pushed - * on the value stack. - */ -#define DUK__ARRAY_MID_JOIN_LIMIT 4096 - -/* Shared entry code for many Array built-ins. Note that length is left - * on stack (it could be popped, but that's not necessary). - */ -DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) { - duk_uint32_t len; - - (void) duk_push_this_coercible_to_object(ctx); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH); - len = duk_to_uint32(ctx, -1); - - /* -> [ ... ToObject(this) ToUint32(length) ] */ - return len; -} - -DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx) { - /* Range limited to [0, 0x7fffffff] range, i.e. range that can be - * represented with duk_int32_t. Use this when the method doesn't - * handle the full 32-bit unsigned range correctly. - */ - duk_uint32_t ret = duk__push_this_obj_len_u32(ctx); - if (DUK_UNLIKELY(ret >= 0x80000000UL)) { - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_INTERNAL_ERROR, DUK_STR_ARRAY_LENGTH_OVER_2G); - } - return ret; -} - -/* - * Constructor - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_context *ctx) { - duk_idx_t nargs; - duk_double_t d; - duk_uint32_t len; - duk_idx_t i; - - nargs = duk_get_top(ctx); - duk_push_array(ctx); - - if (nargs == 1 && duk_is_number(ctx, 0)) { - /* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */ - d = duk_get_number(ctx, 0); - len = duk_to_uint32(ctx, 0); - if (((duk_double_t) len) != d) { - return DUK_RET_RANGE_ERROR; - } - - /* XXX: if 'len' is low, may want to ensure array part is kept: - * the caller is likely to want a dense array. - */ - duk_push_u32(ctx, len); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */ - return 1; - } - - /* XXX: optimize by creating array into correct size directly, and - * operating on the array part directly; values can be memcpy()'d from - * value stack directly as long as refcounts are increased. - */ - for (i = 0; i < nargs; i++) { - duk_dup(ctx, i); - duk_xdef_prop_index_wec(ctx, -2, (duk_uarridx_t) i); - } - - duk_push_u32(ctx, (duk_uint32_t) nargs); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - return 1; -} - -/* - * isArray() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx) { - duk_hobject *h; - - h = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_ARRAY); - duk_push_boolean(ctx, (h != NULL)); - return 1; -} - -/* - * toString() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) { - (void) duk_push_this_coercible_to_object(ctx); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN); - - /* [ ... this func ] */ - if (!duk_is_callable(ctx, -1)) { - /* Fall back to the initial (original) Object.toString(). We don't - * currently have pointers to the built-in functions, only the top - * level global objects (like "Array") so this is now done in a bit - * of a hacky manner. It would be cleaner to push the (original) - * function and use duk_call_method(). - */ - - /* XXX: 'this' will be ToObject() coerced twice, which is incorrect - * but should have no visible side effects. - */ - DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString")); - duk_set_top(ctx, 0); - return duk_bi_object_prototype_to_string(ctx); /* has access to 'this' binding */ - } - - /* [ ... this func ] */ - - duk_insert(ctx, -2); - - /* [ ... func this ] */ - - DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT", - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - duk_call_method(ctx, 0); - - return 1; -} - -/* - * concat() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) { - duk_idx_t i, n; - duk_uarridx_t idx, idx_last; - duk_uarridx_t j, len; - duk_hobject *h; - - /* XXX: the insert here is a bit expensive if there are a lot of items. - * It could also be special cased in the outermost for loop quite easily - * (as the element is dup()'d anyway). - */ - - (void) duk_push_this_coercible_to_object(ctx); - duk_insert(ctx, 0); - n = duk_get_top(ctx); - duk_push_array(ctx); /* -> [ ToObject(this) item1 ... itemN arr ] */ - - /* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index() - * (which differs from the official algorithm). If no error is thrown, this - * doesn't matter as the length is updated at the end. However, if an error - * is thrown, the length will be unset. That shouldn't matter because the - * caller won't get a reference to the intermediate value. - */ - - idx = 0; - idx_last = 0; - for (i = 0; i < n; i++) { - DUK_ASSERT_TOP(ctx, n + 1); - - /* [ ToObject(this) item1 ... itemN arr ] */ - - duk_dup(ctx, i); - h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY); - if (!h) { - duk_xdef_prop_index_wec(ctx, -2, idx++); - idx_last = idx; - continue; - } - - /* [ ToObject(this) item1 ... itemN arr item(i) ] */ - - /* XXX: an array can have length higher than 32 bits; this is not handled - * correctly now. - */ - len = (duk_uarridx_t) duk_get_length(ctx, -1); - for (j = 0; j < len; j++) { - if (duk_get_prop_index(ctx, -1, j)) { - /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */ - duk_xdef_prop_index_wec(ctx, -3, idx++); - idx_last = idx; - } else { - idx++; - duk_pop(ctx); -#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER) - /* According to E5.1 Section 15.4.4.4 nonexistent trailing - * elements do not affect 'length' of the result. Test262 - * and other engines disagree, so update idx_last here too. - */ - idx_last = idx; -#else - /* Strict standard behavior, ignore trailing elements for - * result 'length'. - */ -#endif - } - } - duk_pop(ctx); - } - - /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly - * in the end, but because we're operating with an internal value which - * is known to be an array, this should be equivalent. - */ - duk_push_uarridx(ctx, idx_last); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - - DUK_ASSERT_TOP(ctx, n + 1); - return 1; -} - -/* - * join(), toLocaleString() - * - * Note: checking valstack is necessary, but only in the per-element loop. - * - * Note: the trivial approach of pushing all the elements on the value stack - * and then calling duk_join() fails when the array contains a large number - * of elements. This problem can't be offloaded to duk_join() because the - * elements to join must be handled here and have special handling. Current - * approach is to do intermediate joins with very large number of elements. - * There is no fancy handling; the prefix gets re-joined multiple times. - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx) { - duk_uint32_t len, count; - duk_uint32_t idx; - duk_small_int_t to_locale_string = duk_get_current_magic(ctx); - duk_idx_t valstack_required; - - /* For join(), nargs is 1. For toLocaleString(), nargs is 0 and - * setting the top essentially pushes an undefined to the stack, - * thus defaulting to a comma separator. - */ - duk_set_top(ctx, 1); - if (duk_is_undefined(ctx, 0)) { - duk_pop(ctx); - duk_push_hstring_stridx(ctx, DUK_STRIDX_COMMA); - } else { - duk_to_string(ctx, 0); - } - - len = duk__push_this_obj_len_u32(ctx); - - /* [ sep ToObject(this) len ] */ - - DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 1), - (unsigned long) len)); - - /* The extra (+4) is tight. */ - valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ? - DUK__ARRAY_MID_JOIN_LIMIT : len) + 4; - duk_require_stack(ctx, valstack_required); - - duk_dup(ctx, 0); - - /* [ sep ToObject(this) len sep ] */ - - count = 0; - idx = 0; - for (;;) { - if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */ - idx >= len) { /* end of loop (careful with len==0) */ - /* [ sep ToObject(this) len sep str0 ... str(count-1) ] */ - DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld", - (long) count, (long) idx, (long) len)); - duk_join(ctx, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */ - duk_dup(ctx, 0); /* -> [ sep ToObject(this) len str sep ] */ - duk_insert(ctx, -2); /* -> [ sep ToObject(this) len sep str ] */ - count = 1; - } - if (idx >= len) { - /* if true, the stack already contains the final result */ - break; - } - - duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx); - if (duk_is_null_or_undefined(ctx, -1)) { - duk_pop(ctx); - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); - } else { - if (to_locale_string) { - duk_to_object(ctx, -1); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_LOCALE_STRING); - duk_insert(ctx, -2); /* -> [ ... toLocaleString ToObject(val) ] */ - duk_call_method(ctx, 0); - duk_to_string(ctx, -1); - } else { - duk_to_string(ctx, -1); - } - } - - count++; - idx++; - } - - /* [ sep ToObject(this) len sep result ] */ - - return 1; -} - -/* - * pop(), push() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx) { - duk_uint32_t len; - duk_uint32_t idx; - - DUK_ASSERT_TOP(ctx, 0); - len = duk__push_this_obj_len_u32(ctx); - if (len == 0) { - duk_push_int(ctx, 0); - duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); - return 0; - } - idx = len - 1; - - duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx); - duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx); - duk_push_u32(ctx, idx); - duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx) { - /* Note: 'this' is not necessarily an Array object. The push() - * algorithm is supposed to work for other kinds of objects too, - * so the algorithm has e.g. an explicit update for the 'length' - * property which is normally "magical" in arrays. - */ - - duk_uint32_t len; - duk_idx_t i, n; - - n = duk_get_top(ctx); - len = duk__push_this_obj_len_u32(ctx); - - /* [ arg1 ... argN obj length ] */ - - /* Technically Array.prototype.push() can create an Array with length - * longer than 2^32-1, i.e. outside the 32-bit range. The final length - * is *not* wrapped to 32 bits in the specification. - * - * This implementation tracks length with a uint32 because it's much - * more practical. - * - * See: test-bi-array-push-maxlen.js. - */ - - if (len + (duk_uint32_t) n < len) { - DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw")); - return DUK_RET_RANGE_ERROR; - } - - for (i = 0; i < n; i++) { - duk_dup(ctx, i); - duk_put_prop_index(ctx, -3, len + i); - } - len += n; - - duk_push_u32(ctx, len); - duk_dup_top(ctx); - duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); - - /* [ arg1 ... argN obj length new_length ] */ - return 1; -} - -/* - * sort() - * - * Currently qsort with random pivot. This is now really, really slow, - * because there is no fast path for array parts. - * - * Signed indices are used because qsort() leaves and degenerate cases - * may use a negative offset. - */ - -DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2) { - duk_bool_t have1, have2; - duk_bool_t undef1, undef2; - duk_small_int_t ret; - duk_idx_t idx_obj = 1; /* fixed offsets in valstack */ - duk_idx_t idx_fn = 0; - duk_hstring *h1, *h2; - - /* Fast exit if indices are identical. This is valid for a non-existent property, - * for an undefined value, and almost always for ToString() coerced comparison of - * arbitrary values (corner cases where this is not the case include e.g. a an - * object with varying ToString() coercion). - * - * The specification does not prohibit "caching" of values read from the array, so - * assuming equality for comparing an index with itself falls into the category of - * "caching". - * - * Also, compareFn may be inconsistent, so skipping a call to compareFn here may - * have an effect on the final result. The specification does not require any - * specific behavior for inconsistent compare functions, so again, this fast path - * is OK. - */ - - if (idx1 == idx2) { - DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit", - (long) idx1, (long) idx2)); - return 0; - } - - have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1); - have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2); - - DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T", - (long) idx1, (long) idx2, (long) have1, (long) have2, - (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1))); - - if (have1) { - if (have2) { - ; - } else { - ret = -1; - goto pop_ret; - } - } else { - if (have2) { - ret = 1; - goto pop_ret; - } else { - ret = 0; - goto pop_ret; - } - } - - undef1 = duk_is_undefined(ctx, -2); - undef2 = duk_is_undefined(ctx, -1); - if (undef1) { - if (undef2) { - ret = 0; - goto pop_ret; - } else { - ret = 1; - goto pop_ret; - } - } else { - if (undef2) { - ret = -1; - goto pop_ret; - } else { - ; - } - } - - if (!duk_is_undefined(ctx, idx_fn)) { - duk_double_t d; - - /* no need to check callable; duk_call() will do that */ - duk_dup(ctx, idx_fn); /* -> [ ... x y fn ] */ - duk_insert(ctx, -3); /* -> [ ... fn x y ] */ - duk_call(ctx, 2); /* -> [ ... res ] */ - - /* The specification is a bit vague what to do if the return - * value is not a number. Other implementations seem to - * tolerate non-numbers but e.g. V8 won't apparently do a - * ToNumber(). - */ - - /* XXX: best behavior for real world compatibility? */ - - d = duk_to_number(ctx, -1); - if (d < 0.0) { - ret = -1; - } else if (d > 0.0) { - ret = 1; - } else { - ret = 0; - } - - duk_pop(ctx); - DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret)); - return ret; - } - - /* string compare is the default (a bit oddly) */ - - h1 = duk_to_hstring(ctx, -2); - h2 = duk_to_hstring(ctx, -1); - DUK_ASSERT(h1 != NULL); - DUK_ASSERT(h2 != NULL); - - ret = duk_js_string_compare(h1, h2); /* retval is directly usable */ - goto pop_ret; - - pop_ret: - duk_pop_2(ctx); - DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret)); - return ret; -} - -DUK_LOCAL void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r) { - duk_bool_t have_l, have_r; - duk_idx_t idx_obj = 1; /* fixed offset in valstack */ - - if (l == r) { - return; - } - - /* swap elements; deal with non-existent elements correctly */ - have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l); - have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r); - - if (have_r) { - /* right exists, [[Put]] regardless whether or not left exists */ - duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l); - } else { - duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l); - duk_pop(ctx); - } - - if (have_l) { - duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r); - } else { - duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r); - duk_pop(ctx); - } -} - -#if defined(DUK_USE_DDDPRINT) -/* Debug print which visualizes the qsort partitioning process. */ -DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) { - char buf[4096]; - char *ptr = buf; - duk_int_t i, n; - n = (duk_int_t) duk_get_length(ctx, 1); - if (n > 4000) { - n = 4000; - } - *ptr++ = '['; - for (i = 0; i < n; i++) { - if (i == pivot) { - *ptr++ = '|'; - } else if (i == lo) { - *ptr++ = '<'; - } else if (i == hi) { - *ptr++ = '>'; - } else if (i >= lo && i <= hi) { - *ptr++ = '-'; - } else { - *ptr++ = ' '; - } - } - *ptr++ = ']'; - *ptr++ = '\0'; - - DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)", - (const char *) buf, (long) lo, (long) hi, (long) pivot)); -} -#endif - -DUK_LOCAL void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_int_t p, l, r; - - /* The lo/hi indices may be crossed and hi < 0 is possible at entry. */ - - DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T", - (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1))); - - DUK_ASSERT_TOP(ctx, 3); - - /* In some cases it may be that lo > hi, or hi < 0; these - * degenerate cases happen e.g. for empty arrays, and in - * recursion leaves. - */ - - /* trivial cases */ - if (hi - lo < 1) { - DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately")); - return; - } - DUK_ASSERT(hi > lo); - DUK_ASSERT(hi - lo + 1 >= 2); - - /* randomized pivot selection */ - p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1)); /* rnd in [lo,hi] */ - DUK_ASSERT(p >= lo && p <= hi); - DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", - (long) lo, (long) hi, (long) p)); - - /* move pivot out of the way */ - duk__array_sort_swap(ctx, p, lo); - p = lo; - DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1))); - - l = lo + 1; - r = hi; - for (;;) { - /* find elements to swap */ - for (;;) { - DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld", - (long) l, (long) r, (long) p)); - if (l >= hi) { - break; - } - if (duk__array_sort_compare(ctx, l, p) >= 0) { /* !(l < p) */ - break; - } - l++; - } - for (;;) { - DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld", - (long) l, (long) r, (long) p)); - if (r <= lo) { - break; - } - if (duk__array_sort_compare(ctx, p, r) >= 0) { /* !(p < r) */ - break; - } - r--; - } - if (l >= r) { - goto done; - } - DUK_ASSERT(l < r); - - DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r)); - - duk__array_sort_swap(ctx, l, r); - - DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1))); - l++; - r--; - } - done: - /* Note that 'l' and 'r' may cross, i.e. r < l */ - DUK_ASSERT(l >= lo && l <= hi); - DUK_ASSERT(r >= lo && r <= hi); - - /* XXX: there's no explicit recursion bound here now. For the average - * qsort recursion depth O(log n) that's not really necessary: e.g. for - * 2**32 recursion depth would be about 32 which is OK. However, qsort - * worst case recursion depth is O(n) which may be a problem. - */ - - /* move pivot to its final place */ - DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1))); - duk__array_sort_swap(ctx, lo, r); - -#if defined(DUK_USE_DDDPRINT) - duk__debuglog_qsort_state(ctx, lo, hi, r); -#endif - - DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1))); - duk__array_qsort(ctx, lo, r - 1); - duk__array_qsort(ctx, r + 1, hi); -} - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx) { - duk_uint32_t len; - - /* XXX: len >= 0x80000000 won't work below because a signed type - * is needed by qsort. - */ - len = duk__push_this_obj_len_u32_limited(ctx); - - /* stack[0] = compareFn - * stack[1] = ToObject(this) - * stack[2] = ToUint32(length) - */ - - if (len > 0) { - /* avoid degenerate cases, so that (len - 1) won't underflow */ - duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1)); - } - - DUK_ASSERT_TOP(ctx, 3); - duk_pop(ctx); - return 1; /* return ToObject(this) */ -} - -/* - * splice() - */ - -/* XXX: this compiles to over 500 bytes now, even without special handling - * for an array part. Uses signed ints so does not handle full array range correctly. - */ - -/* XXX: can shift() / unshift() use the same helper? - * shift() is (close to?) <--> splice(0, 1) - * unshift is (close to?) <--> splice(0, 0, [items])? - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx) { - duk_idx_t nargs; - duk_uint32_t len; - duk_bool_t have_delcount; - duk_int_t item_count; - duk_int_t act_start; - duk_int_t del_count; - duk_int_t i, n; - - DUK_UNREF(have_delcount); - - nargs = duk_get_top(ctx); - if (nargs < 2) { - duk_set_top(ctx, 2); - nargs = 2; - have_delcount = 0; - } else { - have_delcount = 1; - } - - /* XXX: len >= 0x80000000 won't work below because we need to be - * able to represent -len. - */ - len = duk__push_this_obj_len_u32_limited(ctx); - - act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len); - if (act_start < 0) { - act_start = len + act_start; - } - DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len); - -#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT - if (have_delcount) { -#endif - del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start); -#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT - } else { - /* E5.1 standard behavior when deleteCount is not given would be - * to treat it just like if 'undefined' was given, which coerces - * ultimately to 0. Real world behavior is to splice to the end - * of array, see test-bi-array-proto-splice-no-delcount.js. - */ - del_count = len - act_start; - } -#endif - - DUK_ASSERT(nargs >= 2); - item_count = (duk_int_t) (nargs - 2); - - DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start); - DUK_ASSERT(del_count + act_start <= (duk_int_t) len); - - /* For now, restrict result array into 32-bit length range. */ - if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) { - DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw")); - return DUK_RET_RANGE_ERROR; - } - - duk_push_array(ctx); - - /* stack[0] = start - * stack[1] = deleteCount - * stack[2...nargs-1] = items - * stack[nargs] = ToObject(this) -3 - * stack[nargs+1] = ToUint32(length) -2 - * stack[nargs+2] = result array -1 - */ - - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* Step 9: copy elements-to-be-deleted into the result array */ - - for (i = 0; i < del_count; i++) { - if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) { - duk_xdef_prop_index_wec(ctx, -2, i); /* throw flag irrelevant (false in std alg) */ - } else { - duk_pop(ctx); - } - } - duk_push_u32(ctx, (duk_uint32_t) del_count); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - - /* Steps 12 and 13: reorganize elements to make room for itemCount elements */ - - if (item_count < del_count) { - /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 1 - * -> [ A B F G H ] (conceptual intermediate step) - * -> [ A B . F G H ] (placeholder marked) - * [ A B C F G H ] (actual result at this point, C will be replaced) - */ - - DUK_ASSERT_TOP(ctx, nargs + 3); - - n = len - del_count; - for (i = act_start; i < n; i++) { - if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) { - duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count)); - } else { - duk_pop(ctx); - duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count)); - } - } - - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* loop iterator init and limit changed from standard algorithm */ - n = len - del_count + item_count; - for (i = len - 1; i >= n; i--) { - duk_del_prop_index(ctx, -3, (duk_uarridx_t) i); - } - - DUK_ASSERT_TOP(ctx, nargs + 3); - } else if (item_count > del_count) { - /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 4 - * -> [ A B F G H ] (conceptual intermediate step) - * -> [ A B . . . . F G H ] (placeholder marked) - * [ A B C D E F F G H ] (actual result at this point) - */ - - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* loop iterator init and limit changed from standard algorithm */ - for (i = len - del_count - 1; i >= act_start; i--) { - if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) { - duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count)); - } else { - duk_pop(ctx); - duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count)); - } - } - - DUK_ASSERT_TOP(ctx, nargs + 3); - } else { - /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 3 - * -> [ A B F G H ] (conceptual intermediate step) - * -> [ A B . . . F G H ] (placeholder marked) - * [ A B C D E F G H ] (actual result at this point) - */ - } - DUK_ASSERT_TOP(ctx, nargs + 3); - - /* Step 15: insert itemCount elements into the hole made above */ - - for (i = 0; i < item_count; i++) { - duk_dup(ctx, i + 2); /* args start at index 2 */ - duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i)); - } - - /* Step 16: update length; note that the final length may be above 32 bit range - * (but we checked above that this isn't the case here) - */ - - duk_push_u32(ctx, len - del_count + item_count); - duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); - - /* result array is already at the top of stack */ - DUK_ASSERT_TOP(ctx, nargs + 3); - return 1; -} - -/* - * reverse() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx) { - duk_uint32_t len; - duk_uint32_t middle; - duk_uint32_t lower, upper; - duk_bool_t have_lower, have_upper; - - len = duk__push_this_obj_len_u32(ctx); - middle = len / 2; - - /* If len <= 1, middle will be 0 and for-loop bails out - * immediately (0 < 0 -> false). - */ - - for (lower = 0; lower < middle; lower++) { - DUK_ASSERT(len >= 2); - DUK_ASSERT_TOP(ctx, 2); - - DUK_ASSERT(len >= lower + 1); - upper = len - lower - 1; - - have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower); - have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper); - - /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */ - - if (have_upper) { - duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower); - } else { - duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower); - duk_pop(ctx); - } - - if (have_lower) { - duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper); - } else { - duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper); - duk_pop(ctx); - } - - DUK_ASSERT_TOP(ctx, 2); - } - - DUK_ASSERT_TOP(ctx, 2); - duk_pop(ctx); /* -> [ ToObject(this) ] */ - return 1; -} - -/* - * slice() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx) { - duk_uint32_t len; - duk_int_t start, end; - duk_int_t i; - duk_uarridx_t idx; - duk_uint32_t res_length = 0; - - /* XXX: len >= 0x80000000 won't work below because we need to be - * able to represent -len. - */ - len = duk__push_this_obj_len_u32_limited(ctx); - duk_push_array(ctx); - - /* stack[0] = start - * stack[1] = end - * stack[2] = ToObject(this) - * stack[3] = ToUint32(length) - * stack[4] = result array - */ - - start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len); - if (start < 0) { - start = len + start; - } - /* XXX: could duk_is_undefined() provide defaulting undefined to 'len' - * (the upper limit)? - */ - if (duk_is_undefined(ctx, 1)) { - end = len; - } else { - end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len); - if (end < 0) { - end = len + end; - } - } - DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len); - DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len); - - idx = 0; - for (i = start; i < end; i++) { - DUK_ASSERT_TOP(ctx, 5); - if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) { - duk_xdef_prop_index_wec(ctx, 4, idx); - res_length = idx + 1; - } else { - duk_pop(ctx); - } - idx++; - DUK_ASSERT_TOP(ctx, 5); - } - - duk_push_u32(ctx, res_length); - duk_xdef_prop_stridx(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - - DUK_ASSERT_TOP(ctx, 5); - return 1; -} - -/* - * shift() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx) { - duk_uint32_t len; - duk_uint32_t i; - - len = duk__push_this_obj_len_u32(ctx); - if (len == 0) { - duk_push_int(ctx, 0); - duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); - return 0; - } - - duk_get_prop_index(ctx, 0, 0); - - /* stack[0] = object (this) - * stack[1] = ToUint32(length) - * stack[2] = elem at index 0 (retval) - */ - - for (i = 1; i < len; i++) { - DUK_ASSERT_TOP(ctx, 3); - if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) { - /* fromPresent = true */ - duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1)); - } else { - /* fromPresent = false */ - duk_del_prop_index(ctx, 0, (duk_uarridx_t) (i - 1)); - duk_pop(ctx); - } - } - duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1)); - - duk_push_u32(ctx, (duk_uint32_t) (len - 1)); - duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH); - - DUK_ASSERT_TOP(ctx, 3); - return 1; -} - -/* - * unshift() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx) { - duk_idx_t nargs; - duk_uint32_t len; - duk_uint32_t i; - - nargs = duk_get_top(ctx); - len = duk__push_this_obj_len_u32(ctx); - - /* stack[0...nargs-1] = unshift args (vararg) - * stack[nargs] = ToObject(this) - * stack[nargs+1] = ToUint32(length) - */ - - DUK_ASSERT_TOP(ctx, nargs + 2); - - /* Note: unshift() may operate on indices above unsigned 32-bit range - * and the final length may be >= 2**32. However, we restrict the - * final result to 32-bit range for practicality. - */ - - if (len + (duk_uint32_t) nargs < len) { - DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw")); - return DUK_RET_RANGE_ERROR; - } - - i = len; - while (i > 0) { - DUK_ASSERT_TOP(ctx, nargs + 2); - i--; - /* k+argCount-1; note that may be above 32-bit range */ - - if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) { - /* fromPresent = true */ - /* [ ... ToObject(this) ToUint32(length) val ] */ - duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */ - } else { - /* fromPresent = false */ - /* [ ... ToObject(this) ToUint32(length) val ] */ - duk_pop(ctx); - duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */ - } - DUK_ASSERT_TOP(ctx, nargs + 2); - } - - for (i = 0; i < (duk_uint32_t) nargs; i++) { - DUK_ASSERT_TOP(ctx, nargs + 2); - duk_dup(ctx, i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */ - duk_put_prop_index(ctx, -3, (duk_uarridx_t) i); - DUK_ASSERT_TOP(ctx, nargs + 2); - } - - DUK_ASSERT_TOP(ctx, nargs + 2); - duk_push_u32(ctx, len + nargs); - duk_dup_top(ctx); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */ - duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH); - return 1; -} - -/* - * indexOf(), lastIndexOf() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx) { - duk_idx_t nargs; - duk_int_t i, len; - duk_int_t from_index; - duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for indexOf, -1 for lastIndexOf */ - - /* lastIndexOf() needs to be a vararg function because we must distinguish - * between an undefined fromIndex and a "not given" fromIndex; indexOf() is - * made vararg for symmetry although it doesn't strictly need to be. - */ - - nargs = duk_get_top(ctx); - duk_set_top(ctx, 2); - - /* XXX: must be able to represent -len */ - len = (duk_int_t) duk__push_this_obj_len_u32_limited(ctx); - if (len == 0) { - goto not_found; - } - - /* Index clamping is a bit tricky, we must ensure that we'll only iterate - * through elements that exist and that the specific requirements from E5.1 - * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially: - * - * - indexOf: clamp to [-len,len], negative handling -> [0,len], - * if clamped result is len, for-loop bails out immediately - * - * - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1], - * if clamped result is -1, for-loop bails out immediately - * - * If fromIndex is not given, ToInteger(undefined) = 0, which is correct - * for indexOf() but incorrect for lastIndexOf(). Hence special handling, - * and why lastIndexOf() needs to be a vararg function. - */ - - if (nargs >= 2) { - /* indexOf: clamp fromIndex to [-len, len] - * (if fromIndex == len, for-loop terminates directly) - * - * lastIndexOf: clamp fromIndex to [-len - 1, len - 1] - * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly) - */ - from_index = duk_to_int_clamped(ctx, - 1, - (idx_step > 0 ? -len : -len - 1), - (idx_step > 0 ? len : len - 1)); - if (from_index < 0) { - /* for lastIndexOf, result may be -1 (mark immediate termination) */ - from_index = len + from_index; - } - } else { - /* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but - * handle both indexOf and lastIndexOf specially here. - */ - if (idx_step > 0) { - from_index = 0; - } else { - from_index = len - 1; - } - } - - /* stack[0] = searchElement - * stack[1] = fromIndex - * stack[2] = object - * stack[3] = length (not needed, but not popped above) - */ - - for (i = from_index; i >= 0 && i < len; i += idx_step) { - DUK_ASSERT_TOP(ctx, 4); - - if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) { - DUK_ASSERT_TOP(ctx, 5); - if (duk_strict_equals(ctx, 0, 4)) { - duk_push_int(ctx, i); - return 1; - } - } - - duk_pop(ctx); - } - - not_found: - duk_push_int(ctx, -1); - return 1; -} - -/* - * every(), some(), forEach(), map(), filter() - */ - -#define DUK__ITER_EVERY 0 -#define DUK__ITER_SOME 1 -#define DUK__ITER_FOREACH 2 -#define DUK__ITER_MAP 3 -#define DUK__ITER_FILTER 4 - -/* XXX: This helper is a bit awkward because the handling for the different iteration - * callers is quite different. This now compiles to a bit less than 500 bytes, so with - * 5 callers the net result is about 100 bytes / caller. - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) { - duk_uint32_t len; - duk_uint32_t i; - duk_uarridx_t k; - duk_bool_t bval; - duk_small_int_t iter_type = duk_get_current_magic(ctx); - duk_uint32_t res_length = 0; - - /* each call this helper serves has nargs==2 */ - DUK_ASSERT_TOP(ctx, 2); - - len = duk__push_this_obj_len_u32(ctx); - if (!duk_is_callable(ctx, 0)) { - goto type_error; - } - /* if thisArg not supplied, behave as if undefined was supplied */ - - if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) { - duk_push_array(ctx); - } else { - duk_push_undefined(ctx); - } - - /* stack[0] = callback - * stack[1] = thisArg - * stack[2] = object - * stack[3] = ToUint32(length) (unused, but avoid unnecessary pop) - * stack[4] = result array (or undefined) - */ - - k = 0; /* result index for filter() */ - for (i = 0; i < len; i++) { - DUK_ASSERT_TOP(ctx, 5); - - if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) { -#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER) - /* Real world behavior for map(): trailing non-existent - * elements don't invoke the user callback, but are still - * counted towards result 'length'. - */ - if (iter_type == DUK__ITER_MAP) { - res_length = i + 1; - } -#else - /* Standard behavior for map(): trailing non-existent - * elements don't invoke the user callback and are not - * counted towards result 'length'. - */ -#endif - duk_pop(ctx); - continue; - } - - /* The original value needs to be preserved for filter(), hence - * this funny order. We can't re-get the value because of side - * effects. - */ - - duk_dup(ctx, 0); - duk_dup(ctx, 1); - duk_dup(ctx, -3); - duk_push_u32(ctx, i); - duk_dup(ctx, 2); /* [ ... val callback thisArg val i obj ] */ - duk_call_method(ctx, 3); /* -> [ ... val retval ] */ - - switch (iter_type) { - case DUK__ITER_EVERY: - bval = duk_to_boolean(ctx, -1); - if (!bval) { - /* stack top contains 'false' */ - return 1; - } - break; - case DUK__ITER_SOME: - bval = duk_to_boolean(ctx, -1); - if (bval) { - /* stack top contains 'true' */ - return 1; - } - break; - case DUK__ITER_FOREACH: - /* nop */ - break; - case DUK__ITER_MAP: - duk_dup(ctx, -1); - duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i); /* retval to result[i] */ - res_length = i + 1; - break; - case DUK__ITER_FILTER: - bval = duk_to_boolean(ctx, -1); - if (bval) { - duk_dup(ctx, -2); /* orig value */ - duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) k); - k++; - res_length = k; - } - break; - default: - DUK_UNREACHABLE(); - break; - } - duk_pop_2(ctx); - - DUK_ASSERT_TOP(ctx, 5); - } - - switch (iter_type) { - case DUK__ITER_EVERY: - duk_push_true(ctx); - break; - case DUK__ITER_SOME: - duk_push_false(ctx); - break; - case DUK__ITER_FOREACH: - duk_push_undefined(ctx); - break; - case DUK__ITER_MAP: - case DUK__ITER_FILTER: - DUK_ASSERT_TOP(ctx, 5); - DUK_ASSERT(duk_is_array(ctx, -1)); /* topmost element is the result array already */ - duk_push_u32(ctx, res_length); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); - break; - default: - DUK_UNREACHABLE(); - break; - } - - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} - -/* - * reduce(), reduceRight() - */ - -DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) { - duk_idx_t nargs; - duk_bool_t have_acc; - duk_uint32_t i, len; - duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for reduce, -1 for reduceRight */ - - /* We're a varargs function because we need to detect whether - * initialValue was given or not. - */ - nargs = duk_get_top(ctx); - DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs)); - - duk_set_top(ctx, 2); - len = duk__push_this_obj_len_u32(ctx); - if (!duk_is_callable(ctx, 0)) { - goto type_error; - } - - /* stack[0] = callback fn - * stack[1] = initialValue - * stack[2] = object (coerced this) - * stack[3] = length (not needed, but not popped above) - * stack[4] = accumulator - */ - - have_acc = 0; - if (nargs >= 2) { - duk_dup(ctx, 1); - have_acc = 1; - } - DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T", - (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3))); - - /* For len == 0, i is initialized to len - 1 which underflows. - * The condition (i < len) will then exit the for-loop on the - * first round which is correct. Similarly, loop termination - * happens by i underflowing. - */ - - for (i = (idx_step >= 0 ? 0 : len - 1); - i < len; /* i >= 0 would always be true */ - i += idx_step) { - DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T", - (long) i, (long) len, (long) have_acc, - (long) duk_get_top(ctx), - (duk_tval *) duk_get_tval(ctx, 4))); - - DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) || - (!have_acc && duk_get_top(ctx) == 4)); - - if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) { - continue; - } - - if (!have_acc) { - DUK_ASSERT_TOP(ctx, 4); - duk_get_prop_index(ctx, 2, (duk_uarridx_t) i); - have_acc = 1; - DUK_ASSERT_TOP(ctx, 5); - } else { - DUK_ASSERT_TOP(ctx, 5); - duk_dup(ctx, 0); - duk_dup(ctx, 4); - duk_get_prop_index(ctx, 2, (duk_uarridx_t) i); - duk_push_u32(ctx, i); - duk_dup(ctx, 2); - DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T", - (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4), - (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - duk_call(ctx, 4); - DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1))); - duk_replace(ctx, 4); - DUK_ASSERT_TOP(ctx, 5); - } - } - - if (!have_acc) { - goto type_error; - } - - DUK_ASSERT_TOP(ctx, 5); - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} - -#undef DUK__ARRAY_MID_JOIN_LIMIT - -#undef DUK__ITER_EVERY -#undef DUK__ITER_SOME -#undef DUK__ITER_FOREACH -#undef DUK__ITER_MAP -#undef DUK__ITER_FILTER diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_boolean.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_boolean.c deleted file mode 100644 index 5acea6d8..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_boolean.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Boolean built-ins - */ - -#include "duk_internal.h" - -/* Shared helper to provide toString() and valueOf(). Checks 'this', gets - * the primitive value to stack top, and optionally coerces with ToString(). - */ -DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx) { - duk_tval *tv; - duk_hobject *h; - duk_small_int_t coerce_tostring = duk_get_current_magic(ctx); - - /* XXX: there is room to use a shared helper here, many built-ins - * check the 'this' type, and if it's an object, check its class, - * then get its internal value, etc. - */ - - duk_push_this(ctx); - tv = duk_get_tval(ctx, -1); - DUK_ASSERT(tv != NULL); - - if (DUK_TVAL_IS_BOOLEAN(tv)) { - goto type_ok; - } else if (DUK_TVAL_IS_OBJECT(tv)) { - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) { - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); - DUK_ASSERT(duk_is_boolean(ctx, -1)); - goto type_ok; - } - } - - return DUK_RET_TYPE_ERROR; - - type_ok: - if (coerce_tostring) { - duk_to_string(ctx, -1); - } - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h_this; - - DUK_UNREF(thr); - - duk_to_boolean(ctx, 0); - - if (duk_is_constructor_call(ctx)) { - /* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */ - duk_push_this(ctx); - h_this = duk_get_hobject(ctx, -1); - DUK_ASSERT(h_this != NULL); - DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]); - - DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN); - - duk_dup(ctx, 0); /* -> [ val obj val ] */ - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */ - } /* unbalanced stack */ - - return 1; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_buffer.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_buffer.c deleted file mode 100644 index 37e9680e..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_buffer.c +++ /dev/null @@ -1,2842 +0,0 @@ -/* - * Duktape.Buffer, Node.js Buffer, and Khronos/ES6 TypedArray built-ins - */ - -#include "duk_internal.h" - -/* - * Misc helpers - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Map DUK_HBUFFEROBJECT_ELEM_xxx to duk_hobject class number. - * Sync with duk_hbufferobject.h and duk_hobject.h. - */ -static const duk_uint8_t duk__buffer_class_from_elemtype[9] = { - DUK_HOBJECT_CLASS_UINT8ARRAY, - DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, - DUK_HOBJECT_CLASS_INT8ARRAY, - DUK_HOBJECT_CLASS_UINT16ARRAY, - DUK_HOBJECT_CLASS_INT16ARRAY, - DUK_HOBJECT_CLASS_UINT32ARRAY, - DUK_HOBJECT_CLASS_INT32ARRAY, - DUK_HOBJECT_CLASS_FLOAT32ARRAY, - DUK_HOBJECT_CLASS_FLOAT64ARRAY -}; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Map DUK_HBUFFEROBJECT_ELEM_xxx to prototype object built-in index. - * Sync with duk_hbufferobject.h. - */ -static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = { - DUK_BIDX_UINT8ARRAY_PROTOTYPE, - DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, - DUK_BIDX_INT8ARRAY_PROTOTYPE, - DUK_BIDX_UINT16ARRAY_PROTOTYPE, - DUK_BIDX_INT16ARRAY_PROTOTYPE, - DUK_BIDX_UINT32ARRAY_PROTOTYPE, - DUK_BIDX_INT32ARRAY_PROTOTYPE, - DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, - DUK_BIDX_FLOAT64ARRAY_PROTOTYPE -}; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Map DUK__FLX_xxx to byte size. - */ -static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = { - 1, /* DUK__FLD_8BIT */ - 2, /* DUK__FLD_16BIT */ - 4, /* DUK__FLD_32BIT */ - 4, /* DUK__FLD_FLOAT */ - 8, /* DUK__FLD_DOUBLE */ - 0 /* DUK__FLD_VARINT; not relevant here */ -}; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Bitfield for each DUK_HBUFFEROBJECT_ELEM_xxx indicating which element types - * are compatible with a blind byte copy for the TypedArray set() method (also - * used for TypedArray constructor). Array index is target buffer elem type, - * bitfield indicates compatible source types. The types must have same byte - * size and they must be coercion compatible. - */ -static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = { - /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8 */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT8) | - (1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) | - (1U << DUK_HBUFFEROBJECT_ELEM_INT8), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED - * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00. - */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT8) | - (1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT8 */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT8) | - (1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) | - (1U << DUK_HBUFFEROBJECT_ELEM_INT8), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT16 */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT16) | - (1U << DUK_HBUFFEROBJECT_ELEM_INT16), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT16 */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT16) | - (1U << DUK_HBUFFEROBJECT_ELEM_INT16), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT32 */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT32) | - (1U << DUK_HBUFFEROBJECT_ELEM_INT32), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT32 */ - (1U << DUK_HBUFFEROBJECT_ELEM_UINT32) | - (1U << DUK_HBUFFEROBJECT_ELEM_INT32), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT32 */ - (1U << DUK_HBUFFEROBJECT_ELEM_FLOAT32), - - /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT64 */ - (1U << DUK_HBUFFEROBJECT_ELEM_FLOAT64) -}; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Shared helper. */ -DUK_LOCAL duk_hbufferobject *duk__getrequire_bufobj_this(duk_context *ctx, duk_bool_t throw_flag) { - duk_hthread *thr; - duk_tval *tv; - duk_hbufferobject *h_this; - - DUK_ASSERT(ctx != NULL); - thr = (duk_hthread *) ctx; - - tv = duk_get_borrowed_this_tval(ctx); - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_OBJECT(tv)) { - h_this = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h_this != NULL); - if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_this)) { - DUK_ASSERT_HBUFFEROBJECT_VALID(h_this); - return h_this; - } - } - - if (throw_flag) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); - } - return NULL; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Check that 'this' is a duk_hbufferobject and return a pointer to it. */ -DUK_LOCAL duk_hbufferobject *duk__get_bufobj_this(duk_context *ctx) { - return duk__getrequire_bufobj_this(ctx, 0); -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Check that 'this' is a duk_hbufferobject and return a pointer to it - * (NULL if not). - */ -DUK_LOCAL duk_hbufferobject *duk__require_bufobj_this(duk_context *ctx) { - return duk__getrequire_bufobj_this(ctx, 1); -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Check that value is a duk_hbufferobject and return a pointer to it. */ -DUK_LOCAL duk_hbufferobject *duk__require_bufobj_value(duk_context *ctx, duk_idx_t index) { - duk_hthread *thr; - duk_tval *tv; - duk_hbufferobject *h_obj; - - thr = (duk_hthread *) ctx; - - /* Don't accept relative indices now. */ - DUK_ASSERT(index >= 0); - - tv = duk_require_tval(ctx, index); - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_OBJECT(tv)) { - h_obj = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h_obj != NULL); - if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_obj)) { - DUK_ASSERT_HBUFFEROBJECT_VALID(h_obj); - return h_obj; - } - } - - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); - return NULL; /* not reachable */ -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -DUK_LOCAL void duk__set_bufobj_buffer(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_hbuffer *h_val) { - duk_hthread *thr; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - DUK_ASSERT(ctx != NULL); - DUK_ASSERT(h_bufobj != NULL); - DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */ - DUK_ASSERT(h_val != NULL); - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val); - DUK_ASSERT(h_bufobj->shift == 0); - DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); - - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); -} - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_LOCAL duk_hbufferobject *duk__push_arraybuffer_with_length(duk_context *ctx, duk_uint_t len) { - duk_hbuffer *h_val; - duk_hbufferobject *h_bufobj; - - (void) duk_push_fixed_buffer(ctx, (duk_size_t) len); - h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_val != NULL); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER), - DUK_BIDX_ARRAYBUFFER_PROTOTYPE); - DUK_ASSERT(h_bufobj != NULL); - - duk__set_bufobj_buffer(ctx, h_bufobj, h_val); - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - return h_bufobj; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Shared offset/length coercion helper. */ -DUK_LOCAL void duk__resolve_offset_opt_length(duk_context *ctx, - duk_hbufferobject *h_bufarg, - duk_idx_t idx_offset, - duk_idx_t idx_length, - duk_uint_t *out_offset, - duk_uint_t *out_length, - duk_bool_t throw_flag) { - duk_hthread *thr; - duk_int_t offset_signed; - duk_int_t length_signed; - duk_uint_t offset; - duk_uint_t length; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - offset_signed = duk_to_int(ctx, idx_offset); - if (offset_signed < 0) { - goto fail_range; - } - offset = (duk_uint_t) offset_signed; - if (offset > h_bufarg->length) { - goto fail_range; - } - DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */ - DUK_ASSERT(offset <= h_bufarg->length); - - if (duk_is_undefined(ctx, idx_length)) { - DUK_ASSERT(h_bufarg->length >= offset); - length = h_bufarg->length - offset; /* >= 0 */ - } else { - length_signed = duk_to_int(ctx, idx_length); - if (length_signed < 0) { - goto fail_range; - } - length = (duk_uint_t) length_signed; - DUK_ASSERT(h_bufarg->length >= offset); - if (length > h_bufarg->length - offset) { - /* Unlike for negative arguments, some call sites - * want length to be clamped if it's positive. - */ - if (throw_flag) { - goto fail_range; - } else { - length = h_bufarg->length - offset; - } - } - } - DUK_ASSERT_DISABLE(length >= 0); /* unsigned */ - DUK_ASSERT(offset + length <= h_bufarg->length); - - *out_offset = offset; - *out_length = length; - return; - - fail_range: - duk_error(thr, DUK_ERR_RANGE_ERROR, DUK_STR_INVALID_CALL_ARGS); -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Shared lenient buffer length clamping helper. No negative indices, no - * element/byte shifting. - */ -DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_context *ctx, - duk_hbufferobject *h_bufobj, - duk_idx_t idx_start, - duk_idx_t idx_end, - duk_int_t *out_start_offset, - duk_int_t *out_end_offset) { - duk_int_t buffer_length; - duk_int_t start_offset; - duk_int_t end_offset; - - DUK_ASSERT(out_start_offset != NULL); - DUK_ASSERT(out_end_offset != NULL); - - buffer_length = (duk_int_t) h_bufobj->length; - - /* undefined coerces to zero which is correct */ - start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length); - if (duk_is_undefined(ctx, idx_end)) { - end_offset = buffer_length; - } else { - end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length); - } - - DUK_ASSERT(start_offset >= 0); - DUK_ASSERT(start_offset <= buffer_length); - DUK_ASSERT(end_offset >= 0); - DUK_ASSERT(end_offset <= buffer_length); - DUK_ASSERT(start_offset <= end_offset); - - *out_start_offset = start_offset; - *out_end_offset = end_offset; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Shared lenient buffer length clamping helper. Indices are treated as - * element indices (though output values are byte offsets) which only - * really matters for TypedArray views as other buffer object have a zero - * shift. Negative indices are counted from end of input slice; crossed - * indices are clamped to zero length; and final indices are clamped - * against input slice. Used for e.g. ArrayBuffer slice(). - */ -DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx, - duk_hbufferobject *h_bufobj, - duk_idx_t idx_start, - duk_idx_t idx_end, - duk_int_t *out_start_offset, - duk_int_t *out_end_offset) { - duk_int_t buffer_length; - duk_int_t start_offset; - duk_int_t end_offset; - - DUK_ASSERT(out_start_offset != NULL); - DUK_ASSERT(out_end_offset != NULL); - - buffer_length = (duk_int_t) h_bufobj->length; - buffer_length >>= h_bufobj->shift; /* as elements */ - - /* Resolve start/end offset as element indices first; arguments - * at idx_start/idx_end are element offsets. Working with element - * indices first also avoids potential for wrapping. - */ - - start_offset = duk_to_int(ctx, idx_start); - if (start_offset < 0) { - start_offset = buffer_length + start_offset; - } - if (duk_is_undefined(ctx, idx_end)) { - end_offset = buffer_length; - } else { - end_offset = duk_to_int(ctx, idx_end); - if (end_offset < 0) { - end_offset = buffer_length + end_offset; - } - } - /* Note: start_offset/end_offset can still be < 0 here. */ - - if (start_offset < 0) { - start_offset = 0; - } else if (start_offset > buffer_length) { - start_offset = buffer_length; - } - if (end_offset < start_offset) { - end_offset = start_offset; - } else if (end_offset > buffer_length) { - end_offset = buffer_length; - } - DUK_ASSERT(start_offset >= 0); - DUK_ASSERT(start_offset <= buffer_length); - DUK_ASSERT(end_offset >= 0); - DUK_ASSERT(end_offset <= buffer_length); - DUK_ASSERT(start_offset <= end_offset); - - /* Convert indices to byte offsets. */ - start_offset <<= h_bufobj->shift; - end_offset <<= h_bufobj->shift; - - *out_start_offset = start_offset; - *out_end_offset = end_offset; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Indexed read/write helpers (also used from outside this file) - */ - -DUK_INTERNAL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) { - duk_double_union du; - - DUK_MEMCPY((void *) du.uc, (const void *) p, elem_size); - - switch (h_bufobj->elem_type) { - case DUK_HBUFFEROBJECT_ELEM_UINT8: -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) - case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED: -#endif - duk_push_uint(ctx, (duk_uint_t) du.uc[0]); - break; -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) - /* These are not needed when only Duktape.Buffer is supported. */ - case DUK_HBUFFEROBJECT_ELEM_INT8: - duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]); - break; - case DUK_HBUFFEROBJECT_ELEM_UINT16: - duk_push_uint(ctx, (duk_uint_t) du.us[0]); - break; - case DUK_HBUFFEROBJECT_ELEM_INT16: - duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]); - break; - case DUK_HBUFFEROBJECT_ELEM_UINT32: - duk_push_uint(ctx, (duk_uint_t) du.ui[0]); - break; - case DUK_HBUFFEROBJECT_ELEM_INT32: - duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]); - break; - case DUK_HBUFFEROBJECT_ELEM_FLOAT32: - duk_push_number(ctx, (duk_double_t) du.f[0]); - break; - case DUK_HBUFFEROBJECT_ELEM_FLOAT64: - duk_push_number(ctx, (duk_double_t) du.d); - break; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - default: - DUK_UNREACHABLE(); - } -} - -DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) { - duk_double_union du; - - /* NOTE! Caller must ensure that any side effects from the - * coercions below are safe. If that cannot be guaranteed - * (which is normally the case), caller must coerce the - * argument using duk_to_number() before any pointer - * validations; the result of duk_to_number() always coerces - * without side effects here. - */ - - switch (h_bufobj->elem_type) { - case DUK_HBUFFEROBJECT_ELEM_UINT8: - du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1); - break; -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) - /* These are not needed when only Duktape.Buffer is supported. */ - case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED: - du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_INT8: - du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_UINT16: - du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_INT16: - du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_UINT32: - du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_INT32: - du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_FLOAT32: - du.f[0] = (duk_float_t) duk_to_number(ctx, -1); - break; - case DUK_HBUFFEROBJECT_ELEM_FLOAT64: - du.d = (duk_double_t) duk_to_number(ctx, -1); - break; -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - default: - DUK_UNREACHABLE(); - } - - DUK_MEMCPY((void *) p, (const void *) du.uc, elem_size); -} - -/* - * Duktape.Buffer: constructor - */ - -DUK_INTERNAL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) { - duk_hthread *thr; - duk_size_t buf_size; - duk_small_int_t buf_dynamic; - duk_uint8_t *buf_data; - const duk_uint8_t *src_data; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - /* - * Constructor arguments are currently somewhat compatible with - * (keep it that way if possible): - * - * http://nodejs.org/api/buffer.html - * - * Note that the ToBuffer() coercion (duk_to_buffer()) does NOT match - * the constructor behavior. - */ - - buf_dynamic = duk_get_boolean(ctx, 1); /* default to false */ - - switch (duk_get_type(ctx, 0)) { - case DUK_TYPE_NUMBER: { - /* new buffer of specified size */ - buf_size = (duk_size_t) duk_to_int(ctx, 0); - (void) duk_push_buffer(ctx, buf_size, buf_dynamic); - break; - } - case DUK_TYPE_BUFFER: { - /* return input buffer, converted to a Duktape.Buffer object - * if called as a constructor (no change if called as a - * function). - */ - duk_set_top(ctx, 1); - break; - } - case DUK_TYPE_STRING: { - /* new buffer with string contents */ - src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size); - DUK_ASSERT(src_data != NULL); /* even for zero-length string */ - buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic); - DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size); - break; - } - case DUK_TYPE_OBJECT: { - /* For all duk_hbufferobjects, get the plain buffer inside - * without making a copy. This is compatible with Duktape 1.2 - * but means that a slice/view information is ignored and the - * full underlying buffer is returned. - * - * If called as a constructor, a new Duktape.Buffer object - * pointing to the same plain buffer is created below. - */ - duk_hbufferobject *h_bufobj; - h_bufobj = (duk_hbufferobject *) duk_get_hobject(ctx, 0); - DUK_ASSERT(h_bufobj != NULL); - if (!DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)) { - return DUK_RET_TYPE_ERROR; - } - if (h_bufobj->buf == NULL) { - return DUK_RET_TYPE_ERROR; - } - duk_push_hbuffer(ctx, h_bufobj->buf); - break; - } - case DUK_TYPE_NONE: - default: { - return DUK_RET_TYPE_ERROR; - } - } - DUK_ASSERT(duk_is_buffer(ctx, -1)); - - /* stack is unbalanced, but: [ buf ] */ - - if (duk_is_constructor_call(ctx)) { - duk_hbufferobject *h_bufobj; - duk_hbuffer *h_val; - - h_val = duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_val != NULL); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), - DUK_BIDX_BUFFER_PROTOTYPE); - DUK_ASSERT(h_bufobj != NULL); - - duk__set_bufobj_buffer(ctx, h_bufobj, h_val); - - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - } - /* Note: unbalanced stack on purpose */ - - return 1; -} - -/* - * Node.js Buffer: constructor - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) { - /* Internal class is Object: Object.prototype.toString.call(new Buffer(0)) - * prints "[object Object]". - */ - duk_int_t len; - duk_int_t i; - duk_uint8_t *buf; - duk_hbuffer *h_buf; - duk_hbufferobject *h_bufobj; - duk_size_t buf_size; - - switch (duk_get_type(ctx, 0)) { - case DUK_TYPE_BUFFER: { - /* Custom behavior: plain buffer is used as internal buffer - * without making a copy (matches Duktape.Buffer). - */ - duk_set_top(ctx, 1); /* -> [ buffer ] */ - break; - } - case DUK_TYPE_NUMBER: { - len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX); - buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); - break; - } - case DUK_TYPE_OBJECT: { - (void) duk_get_prop_string(ctx, 0, "length"); - len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX); - duk_pop(ctx); - buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); - for (i = 0; i < len; i++) { - /* XXX: fast path for array arguments? */ - duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); - buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU); - duk_pop(ctx); - } - break; - } - case DUK_TYPE_STRING: { - /* ignore encoding for now */ - duk_dup(ctx, 0); - buf = (duk_uint8_t *) duk_to_buffer(ctx, -1, &buf_size); - break; - } - default: - return DUK_RET_TYPE_ERROR; - } - - DUK_ASSERT(duk_is_buffer(ctx, -1)); - h_buf = duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_buf != NULL); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), - DUK_BIDX_NODEJS_BUFFER_PROTOTYPE); - DUK_ASSERT(h_bufobj != NULL); - - h_bufobj->buf = h_buf; - DUK_HBUFFER_INCREF(thr, h_buf); - DUK_ASSERT(h_bufobj->offset == 0); - h_bufobj->length = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_buf); - DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); - - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * ArrayBuffer, DataView, and TypedArray constructors - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) { - duk_hbufferobject *h_bufobj; - duk_hbuffer *h_val; - - /* XXX: function flag to make this automatic? */ - if (!duk_is_constructor_call(ctx)) { - return DUK_RET_TYPE_ERROR; - } - - if (duk_is_buffer(ctx, 0)) { - /* Custom behavior: plain buffer is used as internal buffer - * without making a copy (matches Duktape.Buffer). - */ - - h_val = duk_get_hbuffer(ctx, 0); - DUK_ASSERT(h_val != NULL); - - /* XXX: accept any duk_hbufferobject type as an input also? */ - } else { - duk_int_t len; - len = duk_to_int(ctx, 0); - if (len < 0) { - goto fail_length; - } - (void) duk_push_fixed_buffer(ctx, (duk_size_t) len); - h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_val != NULL); - } - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER), - DUK_BIDX_ARRAYBUFFER_PROTOTYPE); - DUK_ASSERT(h_bufobj != NULL); - - duk__set_bufobj_buffer(ctx, h_bufobj, h_val); - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - return 1; - - fail_length: - return DUK_RET_RANGE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - - -/* Format of magic, bits: - * 0...1: elem size shift (0-3) - * 2...5: elem type (DUK_HBUFFEROBJECT_ELEM_xxx) - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv; - duk_hobject *h_obj; - duk_hbufferobject *h_bufobj = NULL; - duk_hbufferobject *h_bufarr = NULL; - duk_hbufferobject *h_bufarg = NULL; - duk_hbuffer *h_val; - duk_small_uint_t magic; - duk_small_uint_t shift; - duk_small_uint_t elem_type; - duk_small_uint_t elem_size; - duk_small_uint_t class_num; - duk_small_uint_t proto_bidx; - duk_uint_t align_mask; - duk_uint_t elem_length; - duk_int_t elem_length_signed; - duk_uint_t byte_length; - duk_small_uint_t copy_mode; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - /* XXX: function flag to make this automatic? */ - if (!duk_is_constructor_call(ctx)) { - return DUK_RET_TYPE_ERROR; - } - - /* We could fit built-in index into magic but that'd make the magic - * number dependent on built-in numbering (genbuiltins.py doesn't - * handle that yet). So map both class and prototype from the - * element type. - */ - magic = duk_get_current_magic(ctx); - shift = magic & 0x03; /* bits 0...1: shift */ - elem_type = (magic >> 2) & 0x0f; /* bits 2...5: type */ - elem_size = 1 << shift; - align_mask = elem_size - 1; - DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t)); - proto_bidx = duk__buffer_proto_from_elemtype[elem_type]; - DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS); - DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t)); - class_num = duk__buffer_class_from_elemtype[elem_type]; - - DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, " - "elem_size=%d, proto_bidx=%d, class_num=%d", - (int) magic, (int) shift, (int) elem_type, (int) elem_size, - (int) proto_bidx, (int) class_num)); - - /* Argument variants. When the argument is an ArrayBuffer a view to - * the same buffer is created; otherwise a new ArrayBuffer is always - * created. - */ - - tv = duk_get_tval(ctx, 0); - DUK_ASSERT(tv != NULL); /* arg count */ - if (DUK_TVAL_IS_OBJECT(tv)) { - h_obj = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h_obj != NULL); - - if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) { - /* ArrayBuffer: unlike any other argument variant, create - * a view into the existing buffer. - */ - - duk_int_t byte_offset_signed; - duk_uint_t byte_offset; - - h_bufarg = (duk_hbufferobject *) h_obj; - - byte_offset_signed = duk_to_int(ctx, 1); - if (byte_offset_signed < 0) { - goto fail_arguments; - } - byte_offset = (duk_uint_t) byte_offset_signed; - if (byte_offset > h_bufarg->length || - (byte_offset & align_mask) != 0) { - /* Must be >= 0 and multiple of element size. */ - goto fail_arguments; - } - if (duk_is_undefined(ctx, 2)) { - DUK_ASSERT(h_bufarg->length >= byte_offset); - byte_length = h_bufarg->length - byte_offset; - if ((byte_length & align_mask) != 0) { - /* Must be element size multiple from - * start offset to end of buffer. - */ - goto fail_arguments; - } - elem_length = (byte_length >> shift); - } else { - elem_length_signed = duk_to_int(ctx, 2); - if (elem_length_signed < 0) { - goto fail_arguments; - } - elem_length = (duk_uint_t) elem_length_signed; - byte_length = elem_length << shift; - if ((byte_length >> shift) != elem_length) { - /* Byte length would overflow. */ - /* XXX: easier check with less code? */ - goto fail_arguments; - } - DUK_ASSERT(h_bufarg->length >= byte_offset); - if (byte_length > h_bufarg->length - byte_offset) { - /* Not enough data. */ - goto fail_arguments; - } - } - DUK_ASSERT_DISABLE(byte_offset >= 0); - DUK_ASSERT(byte_offset <= h_bufarg->length); - DUK_ASSERT_DISABLE(byte_length >= 0); - DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length); - DUK_ASSERT((elem_length << shift) == byte_length); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(class_num), - proto_bidx); - h_val = h_bufarg->buf; - if (h_val == NULL) { - return DUK_RET_TYPE_ERROR; - } - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - h_bufobj->offset = h_bufarg->offset + byte_offset; - h_bufobj->length = byte_length; - h_bufobj->shift = shift; - h_bufobj->elem_type = elem_type; - h_bufobj->is_view = 1; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - /* Set .buffer to the argument ArrayBuffer. */ - duk_dup(ctx, 0); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); - duk_compact(ctx, -1); - return 1; - } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) { - /* TypedArray (or other non-ArrayBuffer duk_hbufferobject). - * Conceptually same behavior as for an Array-like argument, - * with a few fast paths. - */ - - h_bufarg = (duk_hbufferobject *) h_obj; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg); - elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift); - if (h_bufarg->buf == NULL) { - return DUK_RET_TYPE_ERROR; - } - - /* Select copy mode. Must take into account element - * compatibility and validity of the underlying source - * buffer. - */ - - DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, " - "src byte_length=%ld, src shift=%d, " - "src/dst elem_length=%ld; " - "dst shift=%d -> dst byte_length=%ld", - (long) h_bufarg->length, (int) h_bufarg->shift, - (long) elem_length_signed, (int) shift, - (long) (elem_length_signed << shift))); - - copy_mode = 2; /* default is explicit index read/write copy */ - DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t)); - if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) { - if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) { - DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy")); - DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */ - copy_mode = 0; - } else { - DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy")); - copy_mode = 1; - } - } - } else { - /* Array or Array-like */ - elem_length_signed = (duk_int_t) duk_get_length(ctx, 0); - copy_mode = 2; - } - } else { - /* Non-object argument is simply int coerced, matches - * V8 behavior (except for "null", which we coerce to - * 0 but V8 TypeErrors). - */ - elem_length_signed = duk_to_int(ctx, 0); - copy_mode = 3; - } - if (elem_length_signed < 0) { - goto fail_arguments; - } - elem_length = (duk_uint_t) elem_length_signed; - byte_length = (duk_uint_t) (elem_length << shift); - if ((byte_length >> shift) != elem_length) { - /* Byte length would overflow. */ - /* XXX: easier check with less code? */ - goto fail_arguments; - } - - DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld", - (long) elem_length, (long) byte_length)); - - /* ArrayBuffer argument is handled specially above; the rest of the - * argument variants are handled by shared code below. - */ - - /* Push a new ArrayBuffer (becomes view .buffer) */ - h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length); - DUK_ASSERT(h_bufarr != NULL); - h_val = h_bufarr->buf; - DUK_ASSERT(h_val != NULL); - - /* Push the resulting view object and attach the ArrayBuffer. */ - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(class_num), - proto_bidx); - - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - DUK_ASSERT(h_bufobj->offset == 0); - h_bufobj->length = byte_length; - h_bufobj->shift = shift; - h_bufobj->elem_type = elem_type; - h_bufobj->is_view = 1; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - /* Set .buffer */ - duk_dup(ctx, -2); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); - duk_compact(ctx, -1); - - /* Copy values, the copy method depends on the arguments. - * - * Copy mode decision may depend on the validity of the underlying - * buffer of the source argument; there must be no harmful side effects - * from there to here for copy_mode to still be valid. - */ - DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode)); - switch (copy_mode) { - case 0: { - /* Use byte copy. */ - - duk_uint8_t *p_src; - duk_uint8_t *p_dst; - - DUK_ASSERT(h_bufobj != NULL); - DUK_ASSERT(h_bufobj->buf != NULL); - DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)); - DUK_ASSERT(h_bufarg != NULL); - DUK_ASSERT(h_bufarg->buf != NULL); - DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)); - - p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj); - p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg); - - DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld", - (void *) p_src, (void *) p_dst, (long) byte_length)); - - DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length); - break; - } - case 1: { - /* Copy values through direct validated reads and writes. */ - - duk_small_uint_t src_elem_size; - duk_small_uint_t dst_elem_size; - duk_uint8_t *p_src; - duk_uint8_t *p_src_end; - duk_uint8_t *p_dst; - - DUK_ASSERT(h_bufobj != NULL); - DUK_ASSERT(h_bufobj->buf != NULL); - DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)); - DUK_ASSERT(h_bufarg != NULL); - DUK_ASSERT(h_bufarg->buf != NULL); - DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)); - - src_elem_size = 1 << h_bufarg->shift; - dst_elem_size = elem_size; - - p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg); - p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj); - p_src_end = p_src + h_bufarg->length; - - DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, " - "src_elem_size=%d, dst_elem_size=%d", - (void *) p_src, (void *) p_src_end, (void *) p_dst, - (int) src_elem_size, (int) dst_elem_size)); - - while (p_src != p_src_end) { - DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: " - "p_src=%p, p_src_end=%p, p_dst=%p", - (void *) p_src, (void *) p_src_end, (void *) p_dst)); - /* A validated read() is always a number, so it's write coercion - * is always side effect free an won't invalidate pointers etc. - */ - duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size); - duk_hbufferobject_validated_write(ctx, h_bufobj, p_dst, dst_elem_size); - duk_pop(ctx); - p_src += src_elem_size; - p_dst += dst_elem_size; - } - break; - } - case 2: { - /* Copy values by index reads and writes. Let virtual - * property handling take care of coercion. - */ - duk_uint_t i; - - DUK_DDD(DUK_DDDPRINT("using slow copy")); - - for (i = 0; i < elem_length; i++) { - duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); - duk_put_prop_index(ctx, -2, (duk_uarridx_t) i); - } - break; - } - default: - case 3: { - /* No copy, leave zero bytes in the buffer. There's no - * ambiguity with Float32/Float64 because zero bytes also - * represent 0.0. - */ - - DUK_DDD(DUK_DDDPRINT("using no copy")); - break; - } - } - - return 1; - - fail_arguments: - return DUK_RET_RANGE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) { - duk_hbufferobject *h_bufarg; - duk_hbufferobject *h_bufobj; - duk_hbuffer *h_val; - duk_uint_t offset; - duk_uint_t length; - - /* XXX: function flag to make this automatic? */ - if (!duk_is_constructor_call(ctx)) { - return DUK_RET_TYPE_ERROR; - } - - h_bufarg = duk__require_bufobj_value(ctx, 0); - DUK_ASSERT(h_bufarg != NULL); - - duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/); - DUK_ASSERT(offset <= h_bufarg->length); - DUK_ASSERT(offset + length <= h_bufarg->length); - - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW), - DUK_BIDX_DATAVIEW_PROTOTYPE); - - h_val = h_bufarg->buf; - if (h_val == NULL) { - return DUK_RET_TYPE_ERROR; - } - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - h_bufobj->offset = h_bufarg->offset + offset; - h_bufobj->length = length; - DUK_ASSERT(h_bufobj->shift == 0); - DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); - h_bufobj->is_view = 1; - - /* The DataView .buffer property is ordinarily set to the argument - * which is an ArrayBuffer. We accept any duk_hbufferobject as - * an argument and .buffer will be set to the argument regardless - * of what it is. This may be a bit confusing if the argument - * is e.g. a DataView or another TypedArray view. - * - * XXX: Copy .buffer property from a DataView/TypedArray argument? - * Create a fresh ArrayBuffer for Duktape.Buffer and Node.js Buffer - * arguments? See: test-bug-dataview-buffer-prop.js. - */ - - duk_dup(ctx, 0); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); - duk_compact(ctx, -1); - - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * ArrayBuffer.isView() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) { - duk_hobject *h_obj; - duk_bool_t ret = 0; - - h_obj = duk_get_hobject(ctx, 0); - if (h_obj != NULL && DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) { - ret = ((duk_hbufferobject *) h_obj)->is_view; - } - duk_push_boolean(ctx, ret); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer: toString([encoding], [start], [end]) - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) { - duk_hthread *thr; - duk_hbufferobject *h_this; - duk_int_t start_offset, end_offset; - duk_uint8_t *buf_slice; - duk_size_t slice_length; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - h_this = duk__get_bufobj_this(ctx); - if (h_this == NULL) { - /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */ - duk_push_string(ctx, "[object Object]"); - return 1; - } - DUK_ASSERT_HBUFFEROBJECT_VALID(h_this); - - /* ignore encoding for now */ - - duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &start_offset, &end_offset); - - slice_length = (duk_size_t) (end_offset - start_offset); - buf_slice = (duk_uint8_t *) duk_push_fixed_buffer(ctx, slice_length); - DUK_ASSERT(buf_slice != NULL); - - if (h_this->buf == NULL) { - goto type_error; - } - - if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) { - DUK_MEMCPY((void *) buf_slice, - (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset), - slice_length); - } else { - /* not covered, return all zeroes */ - ; - } - - duk_to_string(ctx, -1); - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Duktape.Buffer: toString(), valueOf() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv; - duk_small_int_t to_string = duk_get_current_magic(ctx); - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - tv = duk_get_borrowed_this_tval(ctx); - DUK_ASSERT(tv != NULL); - - if (DUK_TVAL_IS_BUFFER(tv)) { - duk_hbuffer *h_buf; - h_buf = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h_buf != NULL); - duk_push_hbuffer(ctx, h_buf); - } else if (DUK_TVAL_IS_OBJECT(tv)) { - duk_hobject *h; - duk_hbufferobject *h_bufobj; - - /* Accept any duk_hbufferobject, though we're only normally - * called for Duktape.Buffer values. - */ - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - if (!DUK_HOBJECT_IS_BUFFEROBJECT(h)) { - DUK_DD(DUK_DDPRINT("toString/valueOf() called for a non-bufferobject object")); - goto type_error; - } - h_bufobj = (duk_hbufferobject *) h; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - - if (h_bufobj->buf == NULL) { - DUK_DD(DUK_DDPRINT("toString/valueOf() called for a bufferobject with NULL buf")); - goto type_error; - } - duk_push_hbuffer(ctx, h_bufobj->buf); - } else { - goto type_error; - } - - if (to_string) { - duk_to_string(ctx, -1); - } - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.prototype: toJSON() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) { - duk_hthread *thr; - duk_hbufferobject *h_this; - duk_uint8_t *buf; - duk_uint_t i; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - h_this = duk__require_bufobj_this(ctx); - DUK_ASSERT(h_this != NULL); - - if (h_this->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) { - /* Serialize uncovered backing buffer as a null; doesn't - * really matter as long we're memory safe. - */ - duk_push_null(ctx); - return 1; - } - - duk_push_object(ctx); - duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_BUFFER); - duk_put_prop_stridx(ctx, -2, DUK_STRIDX_TYPE); - - duk_push_array(ctx); - for (i = 0; i < h_this->length; i++) { - /* XXX: regetting the pointer may be overkill - we're writing - * to a side-effect free array here. - */ - DUK_ASSERT(h_this->buf != NULL); - buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this); - duk_push_uint(ctx, (duk_uint_t) buf[i]); - duk_put_prop_index(ctx, -2, (duk_idx_t) i); - } - duk_put_prop_stridx(ctx, -2, DUK_STRIDX_DATA); - - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.prototype.equals() - * Node.js Buffer.prototype.compare() - * Node.js Buffer.compare() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) { - duk_hthread *thr; - duk_small_uint_t magic; - duk_hbufferobject *h_bufarg1; - duk_hbufferobject *h_bufarg2; - duk_small_int_t comp_res; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - magic = duk_get_current_magic(ctx); - if (magic & 0x02) { - /* Static call style. */ - h_bufarg1 = duk__require_bufobj_value(ctx, 0); - h_bufarg2 = duk__require_bufobj_value(ctx, 1); - } else { - h_bufarg1 = duk__require_bufobj_this(ctx); - h_bufarg2 = duk__require_bufobj_value(ctx, 0); - } - DUK_ASSERT(h_bufarg1 != NULL); - DUK_ASSERT(h_bufarg2 != NULL); - - /* We want to compare the slice/view areas of the arguments. - * If either slice/view is invalid (underlying buffer is shorter) - * ensure equals() is false, but otherwise the only thing that - * matters is to be memory safe. - */ - - if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg1) && - DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg2)) { - comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset, - (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset, - (duk_size_t) h_bufarg1->length, - (duk_size_t) h_bufarg2->length); - } else { - comp_res = -1; /* either nonzero value is ok */ - } - - if (magic & 0x01) { - /* compare: similar to string comparison but for buffer data. */ - duk_push_int(ctx, comp_res); - } else { - /* equals */ - duk_push_boolean(ctx, (comp_res == 0)); - } - - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.prototype.fill() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) { - duk_hthread *thr; - duk_hbufferobject *h_this; - const duk_uint8_t *fill_str_ptr; - duk_size_t fill_str_len; - duk_uint8_t fill_value; - duk_int_t fill_offset; - duk_int_t fill_end; - duk_size_t fill_length; - duk_uint8_t *p; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - h_this = duk__require_bufobj_this(ctx); - DUK_ASSERT(h_this != NULL); - if (h_this->buf == NULL) { - return DUK_RET_TYPE_ERROR; - } - - /* [ value offset end ] */ - - if (duk_is_string(ctx, 0)) { - fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len); - DUK_ASSERT(fill_str_ptr != NULL); - } else { - fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0); - fill_str_ptr = (const duk_uint8_t *) &fill_value; - fill_str_len = 1; - } - - /* Fill offset handling is more lenient than in Node.js. */ - - duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &fill_offset, &fill_end); - - DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld", - (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length)); - - DUK_ASSERT(fill_end - fill_offset >= 0); - DUK_ASSERT(h_this->buf != NULL); - - p = (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + fill_offset); - fill_length = (duk_size_t) (fill_end - fill_offset); - if (fill_str_len == 1) { - /* Handle single character fills as memset() even when - * the fill data comes from a one-char argument. - */ - DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length); - } else if (fill_str_len > 1) { - duk_size_t i, n, t; - - for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) { - p[i] = fill_str_ptr[t++]; - if (t >= fill_str_len) { - t = 0; - } - } - } else { - DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently")); - } - - /* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */ - duk_push_this(ctx); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.prototype.write(string, [offset], [length], [encoding]) - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) { - duk_hthread *thr; - duk_hbufferobject *h_this; - duk_uint_t offset; - duk_uint_t length; - const duk_uint8_t *str_data; - duk_size_t str_len; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - h_this = duk__require_bufobj_this(ctx); - DUK_ASSERT(h_this != NULL); - - /* Argument must be a string, e.g. a buffer is not allowed. */ - str_data = (const duk_uint8_t *) duk_require_lstring(ctx, 0, &str_len); - - duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/); - DUK_ASSERT(offset <= h_this->length); - DUK_ASSERT(offset + length <= h_this->length); - - /* XXX: encoding is ignored now. */ - - if (length > str_len) { - length = (duk_uint_t) str_len; - } - - if (DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) { - /* Cannot overlap. */ - DUK_MEMCPY((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset), - (const void *) str_data, - (size_t) length); - } else { - DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore")); - } - - duk_push_uint(ctx, length); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.prototype.copy() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) { - duk_hthread *thr; - duk_hbufferobject *h_this; - duk_hbufferobject *h_bufarg; - duk_int_t source_length; - duk_int_t target_length; - duk_int_t target_start, source_start, source_end; - duk_uint_t target_ustart, source_ustart, source_uend; - duk_uint_t copy_size = 0; - - /* [ targetBuffer targetStart sourceStart sourceEnd ] */ - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - h_this = duk__require_bufobj_this(ctx); - h_bufarg = duk__require_bufobj_value(ctx, 0); - DUK_ASSERT(h_this != NULL); - DUK_ASSERT(h_bufarg != NULL); - source_length = (duk_int_t) h_this->length; - target_length = (duk_int_t) h_bufarg->length; - - target_start = duk_to_int(ctx, 1); - source_start = duk_to_int(ctx, 2); - if (duk_is_undefined(ctx, 3)) { - source_end = source_length; - } else { - source_end = duk_to_int(ctx, 3); - } - - DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, " - "source_start=%ld, source_end=%ld, source_length=%ld", - (long) target_start, (long) h_bufarg->length, - (long) source_start, (long) source_end, (long) source_length)); - - /* This behavior mostly mimics Node.js now. */ - - if (source_start < 0 || source_end < 0 || target_start < 0) { - /* Negative offsets cause a RangeError. */ - goto fail_bounds; - } - source_ustart = (duk_uint_t) source_start; - source_uend = (duk_uint_t) source_end; - target_ustart = (duk_uint_t) target_start; - if (source_ustart >= source_uend || /* crossed offsets or zero size */ - source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */ - target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */ - goto silent_ignore; - } - if (source_uend >= (duk_uint_t) source_length) { - /* Source end clamped silently to available length. */ - source_uend = source_length; - } - copy_size = source_uend - source_ustart; - if (target_ustart + copy_size > (duk_uint_t) target_length) { - /* Clamp to target's end if too long. - * - * NOTE: there's no overflow possibility in the comparison; - * both target_ustart and copy_size are >= 0 and based on - * values in duk_int_t range. Adding them as duk_uint_t - * values is then guaranteed not to overflow. - */ - DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */ - DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */ - copy_size = (duk_uint_t) target_length - target_ustart; - } - - DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu", - (unsigned long) target_ustart, (unsigned long) source_ustart, - (unsigned long) copy_size)); - - DUK_ASSERT(copy_size >= 1); - DUK_ASSERT(source_ustart <= (duk_uint_t) source_length); - DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length); - DUK_ASSERT(target_ustart <= (duk_uint_t) target_length); - DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length); - - /* Ensure copy is covered by underlying buffers. */ - DUK_ASSERT(h_bufarg->buf != NULL); /* length check */ - DUK_ASSERT(h_this->buf != NULL); /* length check */ - if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) && - DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) { - /* Must use memmove() because copy area may overlap (source and target - * buffer may be the same, or from different slices. - */ - DUK_MEMMOVE((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart), - (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + source_ustart), - (size_t) copy_size); - } else { - DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring")); - } - - silent_ignore: - /* Return value is like write(), number of bytes written. - * The return value matters because of code like: - * "off += buf.copy(...)". - */ - duk_push_uint(ctx, copy_size); - return 1; - - fail_bounds: - return DUK_RET_RANGE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * TypedArray.prototype.set() - * - * TypedArray set() is pretty interesting to implement because: - * - * - The source argument may be a plain array or a typedarray. If the - * source is a TypedArray, values are decoded and re-encoded into the - * target (not as a plain byte copy). This may happen even when the - * element byte size is the same, e.g. integer values may be re-encoded - * into floats. - * - * - Source and target may refer to the same underlying buffer, so that - * the set() operation may overlap. The specification requires that this - * must work as if a copy was made before the operation. Note that this - * is NOT a simple memmove() situation because the source and target - * byte sizes may be different -- e.g. a 4-byte source (Int8Array) may - * expand to a 16-byte target (Uint32Array) so that the target overlaps - * the source both from beginning and the end (unlike in typical memmove). - * - * - Even if 'buf' pointers of the source and target differ, there's no - * guarantee that their memory areas don't overlap. This may be the - * case with external buffers. - * - * Even so, it is nice to optimize for the common case: - * - * - Source and target separate buffers or non-overlapping. - * - * - Source and target have a compatible type so that a plain byte copy - * is possible. Note that while e.g. uint8 and int8 are compatible - * (coercion one way or another doesn't change the byte representation), - * e.g. int8 and uint8clamped are NOT compatible when writing int8 - * values into uint8clamped typedarray (-1 would clamp to 0 for instance). - * - * See test-bi-typedarray-proto-set.js. - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) { - duk_hthread *thr; - duk_hbufferobject *h_this; - duk_hobject *h_obj; - duk_uarridx_t i, n; - duk_int_t offset_signed; - duk_uint_t offset_elems; - duk_uint_t offset_bytes; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - h_this = duk__require_bufobj_this(ctx); - DUK_ASSERT(h_this != NULL); - DUK_ASSERT_HBUFFEROBJECT_VALID(h_this); - - if (h_this->buf == NULL) { - DUK_DDD(DUK_DDDPRINT("source neutered, skip copy")); - return 0; - } - - h_obj = duk_require_hobject(ctx, 0); - DUK_ASSERT(h_obj != NULL); - - /* XXX: V8 throws a TypeError for negative values. Would it - * be more useful to interpret negative offsets here from the - * end of the buffer too? - */ - offset_signed = duk_to_int(ctx, 1); - if (offset_signed < 0) { - return DUK_RET_TYPE_ERROR; - } - offset_elems = (duk_uint_t) offset_signed; - offset_bytes = offset_elems << h_this->shift; - if ((offset_bytes >> h_this->shift) != offset_elems) { - /* Byte length would overflow. */ - /* XXX: easier check with less code? */ - return DUK_RET_RANGE_ERROR; - } - if (offset_bytes > h_this->length) { - /* Equality may be OK but >length not. Checking - * this explicitly avoids some overflow cases - * below. - */ - return DUK_RET_RANGE_ERROR; - } - DUK_ASSERT(offset_bytes <= h_this->length); - - /* Fast path: source is a TypedArray (or any bufferobject). */ - - if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) { - duk_hbufferobject *h_bufarg; - duk_uint16_t comp_mask; - duk_small_int_t no_overlap = 0; - duk_uint_t src_length; - duk_uint_t dst_length; - duk_uint_t dst_length_elems; - duk_uint8_t *p_src_base; - duk_uint8_t *p_src_end; - duk_uint8_t *p_src; - duk_uint8_t *p_dst_base; - duk_uint8_t *p_dst; - duk_small_uint_t src_elem_size; - duk_small_uint_t dst_elem_size; - - h_bufarg = (duk_hbufferobject *) h_obj; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg); - - if (h_bufarg->buf == NULL) { - DUK_DDD(DUK_DDDPRINT("target neutered, skip copy")); - return 0; - } - - /* Nominal size check. */ - src_length = h_bufarg->length; /* bytes in source */ - dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */ - dst_length = dst_length_elems << h_this->shift; /* bytes in dest */ - if ((dst_length >> h_this->shift) != dst_length_elems) { - /* Byte length would overflow. */ - /* XXX: easier check with less code? */ - return DUK_RET_RANGE_ERROR; - } - DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld", - (long) src_length, (long) dst_length)); - DUK_ASSERT(offset_bytes <= h_this->length); - if (dst_length > h_this->length - offset_bytes) { - /* Overflow not an issue because subtraction is used on the right - * side and guaranteed to be >= 0. - */ - DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length")); - return DUK_RET_RANGE_ERROR; - } - if (!DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) { - DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore")); - return 0; - } - - p_src_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg); - p_dst_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes; - - /* Check actual underlying buffers for validity and that they - * cover the copy. No side effects are allowed after the check - * so that the validity status doesn't change. - */ - if (!DUK_HBUFFEROBJECT_VALID_SLICE(h_this) || - !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) { - /* The condition could be more narrow and check for the - * copy area only, but there's no need for fine grained - * behavior when the underlying buffer is misconfigured. - */ - DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy")); - return 0; - } - - /* We want to do a straight memory copy if possible: this is - * an important operation because .set() is the TypedArray - * way to copy chunks of memory. However, because set() - * conceptually works in terms of elements, not all views are - * compatible with direct byte copying. - * - * If we do manage a direct copy, the "overlap issue" handled - * below can just be solved using memmove() because the source - * and destination element sizes are necessarily equal. - */ - - DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t)); - comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type]; - if (comp_mask & (1 << h_bufarg->elem_type)) { - DUK_ASSERT(src_length == dst_length); - - DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible")); - DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length); - return 0; - } - DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item")); - - /* We want to avoid making a copy to process set() but that's - * not always possible: the source and the target may overlap - * and because element sizes are different, the overlap cannot - * always be handled with a memmove() or choosing the copy - * direction in a certain way. For example, if source type is - * uint8 and target type is uint32, the target area may exceed - * the source area from both ends! - * - * Note that because external buffers may point to the same - * memory areas, we must ultimately make this check using - * pointers. - * - * NOTE: careful with side effects: any side effect may cause - * a buffer resize (or external buffer pointer/length update)! - */ - - DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, " - "p_dst_base=%p, dst_length=%ld", - (void *) p_src_base, (long) src_length, - (void *) p_dst_base, (long) dst_length)); - - if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */ - p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */ - no_overlap = 1; - } - - if (!no_overlap) { - /* There's overlap: the desired end result is that - * conceptually a copy is made to avoid "trampling" - * of source data by destination writes. We make - * an actual temporary copy to handle this case. - */ - duk_uint8_t *p_src_copy; - - DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source")); - p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_length); - DUK_ASSERT(p_src_copy != NULL); - DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length); - - p_src_base = p_src_copy; /* use p_src_base from now on */ - } - /* Value stack intentionally mixed size here. */ - - DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, " - "p_dst_base=%p, dst_length=%ld, valstack top=%ld", - (void *) p_src_base, (long) src_length, - (void *) p_dst_base, (long) dst_length, - (long) duk_get_top(ctx))); - - /* Ready to make the copy. We must proceed element by element - * and must avoid any side effects that might cause the buffer - * validity check above to become invalid. - * - * Although we work through the value stack here, only plain - * numbers are handled which should be side effect safe. - */ - - src_elem_size = 1 << h_bufarg->shift; - dst_elem_size = 1 << h_this->shift; - p_src = p_src_base; - p_dst = p_dst_base; - p_src_end = p_src_base + src_length; - - while (p_src != p_src_end) { - DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: " - "p_src=%p, p_src_end=%p, p_dst=%p", - (void *) p_src, (void *) p_src_end, (void *) p_dst)); - /* A validated read() is always a number, so it's write coercion - * is always side effect free an won't invalidate pointers etc. - */ - duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size); - duk_hbufferobject_validated_write(ctx, h_this, p_dst, dst_elem_size); - duk_pop(ctx); - p_src += src_elem_size; - p_dst += dst_elem_size; - } - - return 0; - } else { - /* Slow path: quite slow, but we save space by using the property code - * to write coerce target values. We don't need to worry about overlap - * here because the source is not a TypedArray. - * - * We could use the bufferobject write coercion helper but since the - * property read may have arbitrary side effects, full validity checks - * would be needed for every element anyway. - */ - - n = (duk_uarridx_t) duk_get_length(ctx, 0); - DUK_ASSERT(offset_bytes <= h_this->length); - if ((n << h_this->shift) > h_this->length - offset_bytes) { - /* Overflow not an issue because subtraction is used on the right - * side and guaranteed to be >= 0. - */ - DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length")); - return DUK_RET_RANGE_ERROR; - } - - /* There's no need to check for buffer validity status for the - * target here: the property access code will do that for each - * element. Moreover, if we did check the validity here, side - * effects from reading the source argument might invalidate - * the results anyway. - */ - - DUK_ASSERT_TOP(ctx, 2); - duk_push_this(ctx); - - for (i = 0; i < n; i++) { - duk_get_prop_index(ctx, 0, i); - duk_put_prop_index(ctx, 2, offset_elems + i); - } - } - - return 0; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.prototype.slice([start], [end]) - * ArrayBuffer.prototype.slice(begin, [end]) - * TypedArray.prototype.slice(begin, [end]) - * - * The API calls are almost identical; negative indices are counted from end - * of buffer, and final indices are clamped (allowing crossed indices). Main - * differences: - * - * - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create - * views, ArrayBuffer .slice() creates a copy - * - * - Resulting object has a different class and prototype depending on the - * call (or 'this' argument) - * - * - TypedArray .subarray() arguments are element indices, not byte offsets - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) { - duk_hthread *thr; - duk_small_int_t magic; - duk_small_uint_t res_class_num; - duk_hobject *res_proto; - duk_hbufferobject *h_this; - duk_hbufferobject *h_bufobj; - duk_hbuffer *h_val; - duk_int_t start_offset, end_offset; - duk_uint_t slice_length; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - /* [ start end ] */ - - magic = duk_get_current_magic(ctx); - h_this = duk__require_bufobj_this(ctx); - - /* Slice offsets are element (not byte) offsets, which only matters - * for TypedArray views, Node.js Buffer and ArrayBuffer have shift - * zero so byte and element offsets are the same. Negative indices - * are counted from end of slice, crossed indices are allowed (and - * result in zero length result), and final values are clamped - * against the current slice. There's intentionally no check - * against the underlying buffer here. - */ - - duk__clamp_startend_negidx_shifted(ctx, h_this, 0 /*idx_start*/, 1 /*idx_end*/, &start_offset, &end_offset); - DUK_ASSERT(end_offset >= start_offset); - slice_length = (duk_uint_t) (end_offset - start_offset); - - /* The resulting buffer object gets the same class and prototype as - * the buffer in 'this', e.g. if the input is a Node.js Buffer the - * result is a Node.js Buffer; if the input is a Float32Array, the - * result is a Float32Array. - * - * For the class number this seems correct. The internal prototype - * is not so clear: if 'this' is a bufferobject with a non-standard - * prototype object, that value gets copied over into the result - * (instead of using the standard prototype for that object type). - */ - - res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this); - h_bufobj = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num), - DUK_BIDX_OBJECT_PROTOTYPE); /* replaced */ - DUK_ASSERT(h_bufobj != NULL); - res_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_this); /* may be NULL */ - DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_bufobj, res_proto); - - h_bufobj->length = slice_length; - h_bufobj->shift = h_this->shift; /* inherit */ - h_bufobj->elem_type = h_this->elem_type; /* inherit */ - h_bufobj->is_view = magic & 0x01; - DUK_ASSERT(h_bufobj->is_view == 0 || h_bufobj->is_view == 1); - - h_val = h_this->buf; - if (h_val == NULL) { - return DUK_RET_TYPE_ERROR; - } - - if (magic & 0x02) { - /* non-zero: make copy */ - duk_uint8_t *p_copy; - duk_size_t copy_length; - - p_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) slice_length); - DUK_ASSERT(p_copy != NULL); - - /* Copy slice, respecting underlying buffer limits; remainder - * is left as zero. - */ - copy_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, slice_length); - DUK_MEMCPY((void *) p_copy, - (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset), - copy_length); - - h_val = duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_val != NULL); - - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - DUK_ASSERT(h_bufobj->offset == 0); - - duk_pop(ctx); /* reachable so pop OK */ - } else { - h_bufobj->buf = h_val; - DUK_HBUFFER_INCREF(thr, h_val); - h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset); - - /* Copy the .buffer property, needed for TypedArray.prototype.subarray(). - * - * XXX: limit copy only for TypedArray classes specifically? - */ - - duk_push_this(ctx); - if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LC_BUFFER)) { - duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); - duk_pop(ctx); - } else { - duk_pop_2(ctx); - } - } - /* unbalanced stack on purpose */ - - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.isEncoding() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) { - const char *encoding; - - /* only accept lowercase 'utf8' now. */ - - encoding = duk_to_string(ctx, 0); - DUK_ASSERT(duk_is_string(ctx, 0)); /* guaranteed by duk_to_string() */ - duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.isBuffer() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) { - duk_hthread *thr; - duk_tval *tv; - duk_hobject *h; - duk_hobject *h_proto; - duk_bool_t ret = 0; - - thr = (duk_hthread *) ctx; - - DUK_ASSERT(duk_get_top(ctx) >= 1); /* nargs */ - tv = duk_get_tval(ctx, 0); - DUK_ASSERT(tv != NULL); - - if (DUK_TVAL_IS_OBJECT(tv)) { - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE]; - DUK_ASSERT(h_proto != NULL); - - h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h); - if (h) { - ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/); - } - } - - duk_push_boolean(ctx, ret); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.byteLength() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) { - const char *str; - duk_size_t len; - - /* At the moment Buffer() will just use the string bytes as - * is (ignoring encoding), so we return the string length here - * unconditionally. - */ - - str = duk_to_lstring(ctx, 0, &len); - DUK_UNREF(str); - duk_push_size_t(ctx, len); - return 1; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Node.js Buffer.concat() - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) { - duk_hthread *thr; - duk_hobject *h_arg; - duk_int_t total_length = 0; - duk_hbufferobject *h_bufobj; - duk_hbufferobject *h_bufres; - duk_hbuffer *h_val; - duk_uint_t i, n; - duk_uint8_t *p; - duk_size_t space_left; - duk_size_t copy_size; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - /* Node.js accepts only actual Arrays. */ - h_arg = duk_require_hobject(ctx, 0); - if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) { - return DUK_RET_TYPE_ERROR; - } - - /* Compute result length and validate argument buffers. */ - n = (duk_uint_t) duk_get_length(ctx, 0); - for (i = 0; i < n; i++) { - /* Neutered checks not necessary here: neutered buffers have - * zero 'length' so we'll effectively skip them. - */ - DUK_ASSERT_TOP(ctx, 2); /* [ array totalLength ] */ - duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */ - h_bufobj = duk__require_bufobj_value(ctx, 2); - DUK_ASSERT(h_bufobj != NULL); - total_length += h_bufobj->length; - duk_pop(ctx); - } - if (n == 1) { - /* For the case n==1 Node.js doesn't seem to type check - * the sole member but we do it before returning it. - * For this case only the original buffer object is - * returned (not a copy). - */ - duk_get_prop_index(ctx, 0, 0); - return 1; - } - - /* User totalLength overrides a computed length, but we'll check - * every copy in the copy loop. Note that duk_to_uint() can - * technically have arbitrary side effects so we need to recheck - * the buffers in the copy loop. - */ - if (!duk_is_undefined(ctx, 1) && n > 0) { - /* For n == 0, Node.js ignores totalLength argument and - * returns a zero length buffer. - */ - total_length = duk_to_int(ctx, 1); - } - if (total_length < 0) { - return DUK_RET_RANGE_ERROR; - } - - h_bufres = duk_push_bufferobject_raw(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BUFFEROBJECT | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), - DUK_BIDX_NODEJS_BUFFER_PROTOTYPE); - DUK_ASSERT(h_bufres != NULL); - - p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, total_length); - DUK_ASSERT(p != NULL); - space_left = total_length; - - for (i = 0; i < n; i++) { - DUK_ASSERT_TOP(ctx, 4); /* [ array totalLength bufres buf ] */ - - duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); - h_bufobj = duk__require_bufobj_value(ctx, 4); - DUK_ASSERT(h_bufobj != NULL); - - copy_size = h_bufobj->length; - if (copy_size > space_left) { - copy_size = space_left; - } - - if (h_bufobj->buf != NULL && - DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) { - DUK_MEMCPY((void *) p, - (const void *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj), - copy_size); - } else { - /* Just skip, leaving zeroes in the result. */ - ; - } - p += copy_size; - space_left -= copy_size; - - duk_pop(ctx); - } - - h_val = duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_val != NULL); - - duk__set_bufobj_buffer(ctx, h_bufres, h_val); - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufres); - - duk_pop(ctx); /* pop plain buffer, now reachable through h_bufres */ - - return 1; /* return h_bufres */ -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -/* - * Shared readfield and writefield methods - * - * The readfield/writefield methods need support for endianness and field - * types. All offsets are byte based so no offset shifting is needed. - */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* Format of magic, bits: - * 0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused - * 3: endianness: 0=little, 1=big - * 4: signed: 1=yes, 0=no - * 5: typedarray: 1=yes, 0=no - */ -#define DUK__FLD_8BIT 0 -#define DUK__FLD_16BIT 1 -#define DUK__FLD_32BIT 2 -#define DUK__FLD_FLOAT 3 -#define DUK__FLD_DOUBLE 4 -#define DUK__FLD_VARINT 5 -#define DUK__FLD_BIGENDIAN (1 << 3) -#define DUK__FLD_SIGNED (1 << 4) -#define DUK__FLD_TYPEDARRAY (1 << 5) - -/* XXX: split into separate functions for each field type? */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) { - duk_hthread *thr; - duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx); - duk_small_int_t magic_ftype; - duk_small_int_t magic_bigendian; - duk_small_int_t magic_signed; - duk_small_int_t magic_typedarray; - duk_small_int_t endswap; - duk_hbufferobject *h_this; - duk_bool_t no_assert; - duk_int_t offset_signed; - duk_uint_t offset; - duk_uint_t buffer_length; - duk_uint_t check_length; - duk_uint8_t *buf; - duk_double_union du; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - magic_ftype = magic & 0x0007; - magic_bigendian = magic & 0x0008; - magic_signed = magic & 0x0010; - magic_typedarray = magic & 0x0020; - - h_this = duk__require_bufobj_this(ctx); - DUK_ASSERT(h_this != NULL); - buffer_length = h_this->length; - - /* [ offset noAssert ], when ftype != DUK__FLD_VARINT */ - /* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */ - /* [ offset littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */ - - /* Handle TypedArray vs. Node.js Buffer arg differences */ - if (magic_typedarray) { - no_assert = 0; -#if defined(DUK_USE_INTEGER_LE) - endswap = !duk_to_boolean(ctx, 1); /* 1=little endian */ -#else - endswap = duk_to_boolean(ctx, 1); /* 1=little endian */ -#endif - } else { - no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1); -#if defined(DUK_USE_INTEGER_LE) - endswap = magic_bigendian; -#else - endswap = !magic_bigendian; -#endif - } - - /* Offset is coerced first to signed integer range and then to unsigned. - * This ensures we can add a small byte length (1-8) to the offset in - * bound checks and not wrap. - */ - offset_signed = duk_to_int(ctx, 0); - offset = (duk_uint_t) offset_signed; - if (offset_signed < 0) { - goto fail_bounds; - } - - DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, " - "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, " - "endswap=%d", - (long) buffer_length, (long) offset, (int) no_assert, - (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3), - (int) (magic_signed >> 4), (int) endswap)); - - /* Update 'buffer_length' to be the effective, safe limit which - * takes into account the underlying buffer. This value will be - * potentially invalidated by any side effect. - */ - check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length); - DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", - (long) buffer_length, (long) check_length)); - - if (h_this->buf) { - buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this); - } else { - /* neutered, value doesn't matter because check_length is 0. */ - DUK_ASSERT(check_length == 0); - buf = NULL; - } - - switch (magic_ftype) { - case DUK__FLD_8BIT: { - duk_uint8_t tmp; - if (offset + 1U > check_length) { - goto fail_bounds; - } - tmp = buf[offset]; - if (magic_signed) { - duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp)); - } else { - duk_push_uint(ctx, (duk_uint_t) tmp); - } - break; - } - case DUK__FLD_16BIT: { - duk_uint16_t tmp; - if (offset + 2U > check_length) { - goto fail_bounds; - } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2); - tmp = du.us[0]; - if (endswap) { - tmp = DUK_BSWAP16(tmp); - } - if (magic_signed) { - duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp)); - } else { - duk_push_uint(ctx, (duk_uint_t) tmp); - } - break; - } - case DUK__FLD_32BIT: { - duk_uint32_t tmp; - if (offset + 4U > check_length) { - goto fail_bounds; - } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4); - tmp = du.ui[0]; - if (endswap) { - tmp = DUK_BSWAP32(tmp); - } - if (magic_signed) { - duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp)); - } else { - duk_push_uint(ctx, (duk_uint_t) tmp); - } - break; - } - case DUK__FLD_FLOAT: { - duk_uint32_t tmp; - if (offset + 4U > check_length) { - goto fail_bounds; - } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4); - if (endswap) { - tmp = du.ui[0]; - tmp = DUK_BSWAP32(tmp); - du.ui[0] = tmp; - } - duk_push_number(ctx, (duk_double_t) du.f[0]); - break; - } - case DUK__FLD_DOUBLE: { - if (offset + 8U > check_length) { - goto fail_bounds; - } - DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8); - if (endswap) { - DUK_DBLUNION_BSWAP64(&du); - } - duk_push_number(ctx, (duk_double_t) du.d); - break; - } - case DUK__FLD_VARINT: { - /* Node.js Buffer variable width integer field. We don't really - * care about speed here, so aim for shortest algorithm. - */ - duk_int_t field_bytelen; - duk_int_t i, i_step, i_end; -#if defined(DUK_USE_64BIT_OPS) - duk_int64_t tmp; - duk_small_uint_t shift_tmp; -#else - duk_double_t tmp; - duk_small_int_t highbyte; -#endif - const duk_uint8_t *p; - - field_bytelen = duk_get_int(ctx, 1); /* avoid side effects! */ - if (field_bytelen < 1 || field_bytelen > 6) { - goto fail_field_length; - } - if (offset + (duk_uint_t) field_bytelen > check_length) { - goto fail_bounds; - } - p = (const duk_uint8_t *) (buf + offset); - - /* Slow gathering of value using either 64-bit arithmetic - * or IEEE doubles if 64-bit types not available. Handling - * of negative numbers is a bit non-obvious in both cases. - */ - - if (magic_bigendian) { - /* Gather in big endian */ - i = 0; - i_step = 1; - i_end = field_bytelen; /* one i_step over */ - } else { - /* Gather in little endian */ - i = field_bytelen - 1; - i_step = -1; - i_end = -1; /* one i_step over */ - } - -#if defined(DUK_USE_64BIT_OPS) - tmp = 0; - do { - DUK_ASSERT(i >= 0 && i < field_bytelen); - tmp = (tmp << 8) + (duk_int64_t) p[i]; - i += i_step; - } while (i != i_end); - - if (magic_signed) { - /* Shift to sign extend. */ - shift_tmp = 64 - (field_bytelen * 8); - tmp = (tmp << shift_tmp) >> shift_tmp; - } - - duk_push_i64(ctx, tmp); -#else - highbyte = p[i]; - if (magic_signed && (highbyte & 0x80) != 0) { - /* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */ - tmp = (duk_double_t) (highbyte - 256); - } else { - tmp = (duk_double_t) highbyte; - } - for (;;) { - i += i_step; - if (i == i_end) { - break; - } - DUK_ASSERT(i >= 0 && i < field_bytelen); - tmp = (tmp * 256.0) + (duk_double_t) p[i]; - } - - duk_push_number(ctx, tmp); -#endif - break; - } - default: { /* should never happen but default here */ - goto fail_bounds; - } - } - - return 1; - - fail_field_length: - fail_bounds: - if (no_assert) { - /* Node.js return value for noAssert out-of-bounds reads is - * usually (but not always) NaN. Return NaN consistently. - */ - duk_push_nan(ctx); - return 1; - } - - return DUK_RET_RANGE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#if defined(DUK_USE_BUFFEROBJECT_SUPPORT) -/* XXX: split into separate functions for each field type? */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) { - duk_hthread *thr; - duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx); - duk_small_int_t magic_ftype; - duk_small_int_t magic_bigendian; - duk_small_int_t magic_signed; - duk_small_int_t magic_typedarray; - duk_small_int_t endswap; - duk_hbufferobject *h_this; - duk_bool_t no_assert; - duk_int_t offset_signed; - duk_uint_t offset; - duk_uint_t buffer_length; - duk_uint_t check_length; - duk_uint8_t *buf; - duk_double_union du; - duk_int_t nbytes = 0; - - thr = (duk_hthread *) ctx; - DUK_UNREF(thr); - - magic_ftype = magic & 0x0007; - magic_bigendian = magic & 0x0008; - magic_signed = magic & 0x0010; - magic_typedarray = magic & 0x0020; - DUK_UNREF(magic_signed); - - h_this = duk__require_bufobj_this(ctx); - DUK_ASSERT(h_this != NULL); - buffer_length = h_this->length; - - /* [ value offset noAssert ], when ftype != DUK__FLD_VARINT */ - /* [ value offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */ - /* [ offset value littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */ - - /* Handle TypedArray vs. Node.js Buffer arg differences */ - if (magic_typedarray) { - no_assert = 0; -#if defined(DUK_USE_INTEGER_LE) - endswap = !duk_to_boolean(ctx, 2); /* 1=little endian */ -#else - endswap = duk_to_boolean(ctx, 2); /* 1=little endian */ -#endif - duk_swap(ctx, 0, 1); /* offset/value order different from Node.js */ - } else { - no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2); -#if defined(DUK_USE_INTEGER_LE) - endswap = magic_bigendian; -#else - endswap = !magic_bigendian; -#endif - } - - /* Offset is coerced first to signed integer range and then to unsigned. - * This ensures we can add a small byte length (1-8) to the offset in - * bound checks and not wrap. - */ - offset_signed = duk_to_int(ctx, 1); - offset = (duk_uint_t) offset_signed; - - /* We need 'nbytes' even for a failed offset; return value must be - * (offset + nbytes) even when write fails due to invalid offset. - */ - if (magic_ftype != DUK__FLD_VARINT) { - DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t))); - nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype]; - } else { - nbytes = duk_get_int(ctx, 2); - if (nbytes < 1 || nbytes > 6) { - goto fail_field_length; - } - } - DUK_ASSERT(nbytes >= 1 && nbytes <= 8); - - /* Now we can check offset validity. */ - if (offset_signed < 0) { - goto fail_bounds; - } - - DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, " - "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, " - "endswap=%d", - duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert, - (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3), - (int) (magic_signed >> 4), (int) endswap)); - - /* Coerce value to a number before computing check_length, so that - * the field type specific coercion below can't have side effects - * that would invalidate check_length. - */ - duk_to_number(ctx, 0); - - /* Update 'buffer_length' to be the effective, safe limit which - * takes into account the underlying buffer. This value will be - * potentially invalidated by any side effect. - */ - check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length); - DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", - (long) buffer_length, (long) check_length)); - - if (h_this->buf) { - buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this); - } else { - /* neutered, value doesn't matter because check_length is 0. */ - DUK_ASSERT(check_length == 0); - buf = NULL; - } - - switch (magic_ftype) { - case DUK__FLD_8BIT: { - if (offset + 1U > check_length) { - goto fail_bounds; - } - /* sign doesn't matter when writing */ - buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0); - break; - } - case DUK__FLD_16BIT: { - duk_uint16_t tmp; - if (offset + 2U > check_length) { - goto fail_bounds; - } - tmp = (duk_uint16_t) duk_to_uint32(ctx, 0); - if (endswap) { - tmp = DUK_BSWAP16(tmp); - } - du.us[0] = tmp; - /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2); - break; - } - case DUK__FLD_32BIT: { - duk_uint32_t tmp; - if (offset + 4U > check_length) { - goto fail_bounds; - } - tmp = (duk_uint32_t) duk_to_uint32(ctx, 0); - if (endswap) { - tmp = DUK_BSWAP32(tmp); - } - du.ui[0] = tmp; - /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4); - break; - } - case DUK__FLD_FLOAT: { - duk_uint32_t tmp; - if (offset + 4U > check_length) { - goto fail_bounds; - } - du.f[0] = (duk_float_t) duk_to_number(ctx, 0); - if (endswap) { - tmp = du.ui[0]; - tmp = DUK_BSWAP32(tmp); - du.ui[0] = tmp; - } - /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4); - break; - } - case DUK__FLD_DOUBLE: { - if (offset + 8U > check_length) { - goto fail_bounds; - } - du.d = (duk_double_t) duk_to_number(ctx, 0); - if (endswap) { - DUK_DBLUNION_BSWAP64(&du); - } - /* sign doesn't matter when writing */ - DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8); - break; - } - case DUK__FLD_VARINT: { - /* Node.js Buffer variable width integer field. We don't really - * care about speed here, so aim for shortest algorithm. - */ - duk_int_t field_bytelen; - duk_int_t i, i_step, i_end; -#if defined(DUK_USE_64BIT_OPS) - duk_int64_t tmp; -#else - duk_double_t tmp; -#endif - duk_uint8_t *p; - - field_bytelen = (duk_int_t) nbytes; - if (offset + (duk_uint_t) field_bytelen > check_length) { - goto fail_bounds; - } - - /* Slow writing of value using either 64-bit arithmetic - * or IEEE doubles if 64-bit types not available. There's - * no special sign handling when writing varints. - */ - - if (magic_bigendian) { - /* Write in big endian */ - i = field_bytelen; /* one i_step added at top of loop */ - i_step = -1; - i_end = 0; - } else { - /* Write in little endian */ - i = -1; /* one i_step added at top of loop */ - i_step = 1; - i_end = field_bytelen - 1; - } - - /* XXX: The duk_to_number() cast followed by integer coercion - * is platform specific so NaN, +/- Infinity, and out-of-bounds - * values result in platform specific output now. - * See: test-bi-nodejs-buffer-proto-varint-special.js - */ - -#if defined(DUK_USE_64BIT_OPS) - tmp = (duk_int64_t) duk_to_number(ctx, 0); - p = (duk_uint8_t *) (buf + offset); - do { - i += i_step; - DUK_ASSERT(i >= 0 && i < field_bytelen); - p[i] = (duk_uint8_t) (tmp & 0xff); - tmp = tmp >> 8; /* unnecessary shift for last byte */ - } while (i != i_end); -#else - tmp = duk_to_number(ctx, 0); - p = (duk_uint8_t *) (buf + offset); - do { - i += i_step; - tmp = DUK_FLOOR(tmp); - DUK_ASSERT(i >= 0 && i < field_bytelen); - p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0)); - tmp = tmp / 256.0; /* unnecessary div for last byte */ - } while (i != i_end); -#endif - break; - } - default: { /* should never happen but default here */ - goto fail_bounds; - } - } - - /* Node.js Buffer: return offset + #bytes written (i.e. next - * write offset). - */ - if (magic_typedarray) { - /* For TypedArrays 'undefined' return value is specified - * by ES6 (matches V8). - */ - return 0; - } - duk_push_uint(ctx, offset + nbytes); - return 1; - - fail_field_length: - fail_bounds: - if (no_assert) { - /* Node.js return value for failed writes is offset + #bytes - * that would have been written. - */ - /* XXX: for negative input offsets, 'offset' will be a large - * positive value so the result here is confusing. - */ - if (magic_typedarray) { - return 0; - } - duk_push_uint(ctx, offset + nbytes); - return 1; - } - return DUK_RET_RANGE_ERROR; -} -#else /* DUK_USE_BUFFEROBJECT_SUPPORT */ -DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */ - -#undef DUK__FLD_8BIT -#undef DUK__FLD_16BIT -#undef DUK__FLD_32BIT -#undef DUK__FLD_FLOAT -#undef DUK__FLD_DOUBLE -#undef DUK__FLD_VARINT -#undef DUK__FLD_BIGENDIAN -#undef DUK__FLD_SIGNED -#undef DUK__FLD_TYPEDARRAY diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_date.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_date.c deleted file mode 100644 index d2928476..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_date.c +++ /dev/null @@ -1,1730 +0,0 @@ -/* - * Date built-ins - * - * Unlike most built-ins, Date has some platform dependencies for getting - * UTC time, converting between UTC and local time, and parsing and - * formatting time values. These are all abstracted behind DUK_USE_xxx - * config options. There are built-in platform specific providers for - * POSIX and Windows, but external providers can also be used. - * - * See doc/datetime.rst. - * - */ - -#include "duk_internal.h" - -/* - * Forward declarations - */ - -DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset); -DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags); -DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val); -DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags); - -/* - * Other file level defines - */ - -/* Debug macro to print all parts and dparts (used manually because of debug level). */ -#define DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts) do { \ - DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \ - (long) (parts)[0], (long) (parts)[1], \ - (long) (parts)[2], (long) (parts)[3], \ - (long) (parts)[4], (long) (parts)[5], \ - (long) (parts)[6], (long) (parts)[7], \ - (double) (dparts)[0], (double) (dparts)[1], \ - (double) (dparts)[2], (double) (dparts)[3], \ - (double) (dparts)[4], (double) (dparts)[5], \ - (double) (dparts)[6], (double) (dparts)[7])); \ - } while (0) -#define DUK__DPRINT_PARTS(parts) do { \ - DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \ - (long) (parts)[0], (long) (parts)[1], \ - (long) (parts)[2], (long) (parts)[3], \ - (long) (parts)[4], (long) (parts)[5], \ - (long) (parts)[6], (long) (parts)[7])); \ - } while (0) -#define DUK__DPRINT_DPARTS(dparts) do { \ - DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \ - (double) (dparts)[0], (double) (dparts)[1], \ - (double) (dparts)[2], (double) (dparts)[3], \ - (double) (dparts)[4], (double) (dparts)[5], \ - (double) (dparts)[6], (double) (dparts)[7])); \ - } while (0) - -/* Equivalent year for DST calculations outside [1970,2038[ range, see - * E5 Section 15.9.1.8. Equivalent year has the same leap-year-ness and - * starts with the same weekday on Jan 1. - * https://bugzilla.mozilla.org/show_bug.cgi?id=351066 - */ -#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970)) -DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = { -#if 1 - /* This is based on V8 EquivalentYear() algorithm (see src/genequivyear.py): - * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146 - */ - - /* non-leap year: sunday, monday, ... */ - DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031), - DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011), - - /* leap year: sunday, monday, ... */ - DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020), - DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028) -#endif - -#if 0 - /* This is based on Rhino EquivalentYear() algorithm: - * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java - */ - - /* non-leap year: sunday, monday, ... */ - DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986), - DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977), - - /* leap year: sunday, monday, ... */ - DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992), - DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972) -#endif -}; -#undef DUK__YEAR - -/* - * ISO 8601 subset parser. - */ - -/* Parser part count. */ -#define DUK__NUM_ISO8601_PARSER_PARTS 9 - -/* Parser part indices. */ -#define DUK__PI_YEAR 0 -#define DUK__PI_MONTH 1 -#define DUK__PI_DAY 2 -#define DUK__PI_HOUR 3 -#define DUK__PI_MINUTE 4 -#define DUK__PI_SECOND 5 -#define DUK__PI_MILLISECOND 6 -#define DUK__PI_TZHOUR 7 -#define DUK__PI_TZMINUTE 8 - -/* Parser part masks. */ -#define DUK__PM_YEAR (1 << DUK__PI_YEAR) -#define DUK__PM_MONTH (1 << DUK__PI_MONTH) -#define DUK__PM_DAY (1 << DUK__PI_DAY) -#define DUK__PM_HOUR (1 << DUK__PI_HOUR) -#define DUK__PM_MINUTE (1 << DUK__PI_MINUTE) -#define DUK__PM_SECOND (1 << DUK__PI_SECOND) -#define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND) -#define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR) -#define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE) - -/* Parser separator indices. */ -#define DUK__SI_PLUS 0 -#define DUK__SI_MINUS 1 -#define DUK__SI_T 2 -#define DUK__SI_SPACE 3 -#define DUK__SI_COLON 4 -#define DUK__SI_PERIOD 5 -#define DUK__SI_Z 6 -#define DUK__SI_NUL 7 - -/* Parser separator masks. */ -#define DUK__SM_PLUS (1 << DUK__SI_PLUS) -#define DUK__SM_MINUS (1 << DUK__SI_MINUS) -#define DUK__SM_T (1 << DUK__SI_T) -#define DUK__SM_SPACE (1 << DUK__SI_SPACE) -#define DUK__SM_COLON (1 << DUK__SI_COLON) -#define DUK__SM_PERIOD (1 << DUK__SI_PERIOD) -#define DUK__SM_Z (1 << DUK__SI_Z) -#define DUK__SM_NUL (1 << DUK__SI_NUL) - -/* Rule control flags. */ -#define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */ -#define DUK__CF_ACCEPT (1 << 1) /* accept string */ -#define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */ - -#define DUK__PACK_RULE(partmask,sepmask,nextpart,flags) \ - ((duk_uint32_t) (partmask) + \ - (((duk_uint32_t) (sepmask)) << 9) + \ - (((duk_uint32_t) (nextpart)) << 17) + \ - (((duk_uint32_t) (flags)) << 21)) - -#define DUK__UNPACK_RULE(rule,var_nextidx,var_flags) do { \ - (var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \ - (var_flags) = (duk_small_uint_t) ((rule) >> 21); \ - } while (0) - -#define DUK__RULE_MASK_PART_SEP 0x1ffffUL - -/* Matching separator index is used in the control table */ -DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = { - DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/, - DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/ -}; - -/* Rule table: first matching rule is used to determine what to do next. */ -DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = { - DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0), - DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0), - DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0), - DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0), - DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0), - DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0), - DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0), - DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_PLUS, DUK__PI_TZHOUR, 0), - DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_MINUS, DUK__PI_TZHOUR, DUK__CF_NEG), - DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_Z, 0, DUK__CF_ACCEPT_NUL), - DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND | DUK__PM_TZHOUR /*Note2*/ | DUK__PM_TZMINUTE, DUK__SM_NUL, 0, DUK__CF_ACCEPT) - - /* Note1: the specification doesn't require matching a time form with - * just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z". - * - * Note2: the specification doesn't require matching a timezone offset - * with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02" - */ -}; - -DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str) { - duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS]; - duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; - duk_double_t d; - const duk_uint8_t *p; - duk_small_uint_t part_idx = 0; - duk_int_t accum = 0; - duk_small_uint_t ndigits = 0; - duk_bool_t neg_year = 0; - duk_bool_t neg_tzoffset = 0; - duk_uint_fast8_t ch; - duk_small_uint_t i; - - /* During parsing, month and day are one-based; set defaults here. */ - DUK_MEMZERO(parts, sizeof(parts)); - DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */ - parts[DUK_DATE_IDX_MONTH] = 1; - parts[DUK_DATE_IDX_DAY] = 1; - - /* Special handling for year sign. */ - p = (const duk_uint8_t *) str; - ch = p[0]; - if (ch == DUK_ASC_PLUS) { - p++; - } else if (ch == DUK_ASC_MINUS) { - neg_year = 1; - p++; - } - - for (;;) { - ch = *p++; - DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')", - (long) part_idx, (long) ch, - (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION))); - - if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) { - if (ndigits >= 9) { - DUK_DDD(DUK_DDDPRINT("too many digits -> reject")); - goto reject; - } - if (part_idx == DUK__PI_MILLISECOND /*msec*/ && ndigits >= 3) { - /* ignore millisecond fractions after 3 */ - } else { - accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00; - ndigits++; - } - } else { - duk_uint_fast32_t match_val; - duk_small_int_t sep_idx; - - if (ndigits <= 0) { - goto reject; - } - if (part_idx == DUK__PI_MILLISECOND) { - /* complete the millisecond field */ - while (ndigits < 3) { - accum *= 10; - ndigits++; - } - } - parts[part_idx] = accum; - DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum)); - - accum = 0; - ndigits = 0; - - for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) { - if (duk__parse_iso8601_seps[i] == ch) { - break; - } - } - if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) { - DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject")); - goto reject; - } - - sep_idx = i; - match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */ - - for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) { - duk_uint_fast32_t rule = duk__parse_iso8601_control[i]; - duk_small_uint_t nextpart; - duk_small_uint_t cflags; - - DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx", - (long) part_idx, (long) sep_idx, - (unsigned long) match_val, (unsigned long) rule)); - - if ((rule & match_val) != match_val) { - continue; - } - - DUK__UNPACK_RULE(rule, nextpart, cflags); - - DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, " - "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx", - (long) part_idx, (long) sep_idx, - (unsigned long) match_val, (unsigned long) rule, - (long) nextpart, (unsigned long) cflags)); - - if (cflags & DUK__CF_NEG) { - neg_tzoffset = 1; - } - - if (cflags & DUK__CF_ACCEPT) { - goto accept; - } - - if (cflags & DUK__CF_ACCEPT_NUL) { - DUK_ASSERT(*(p - 1) != (char) 0); - if (*p == DUK_ASC_NUL) { - goto accept; - } - goto reject; - } - - part_idx = nextpart; - break; - } /* rule match */ - - if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) { - DUK_DDD(DUK_DDDPRINT("no rule matches -> reject")); - goto reject; - } - - if (ch == 0) { - /* This shouldn't be necessary, but check just in case - * to avoid any chance of overruns. - */ - DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject")); - goto reject; - } - } /* if-digit-else-ctrl */ - } /* char loop */ - - /* We should never exit the loop above, but if we do, reject - * by falling through. - */ - DUK_DDD(DUK_DDDPRINT("fell out of char loop without explicit accept/reject -> reject")); - - reject: - DUK_DDD(DUK_DDDPRINT("reject")); - return 0; - - accept: - DUK_DDD(DUK_DDDPRINT("accept")); - - /* Apply timezone offset to get the main parts in UTC */ - if (neg_year) { - parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR]; - } - if (neg_tzoffset) { - parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR]; - parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE]; - } else { - parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR]; - parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE]; - } - parts[DUK__PI_MONTH] -= 1; /* zero-based month */ - parts[DUK__PI_DAY] -= 1; /* zero-based day */ - - /* Use double parts, they tolerate unnormalized time. - * - * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR) - * on purpose. It won't be actually used by duk_bi_date_get_timeval_from_dparts(), - * but will make the value initialized just in case, and avoid any - * potential for Valgrind issues. - */ - for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) { - DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i])); - dparts[i] = parts[i]; - } - - d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/); - duk_push_number(ctx, d); - return 1; -} - -/* - * Date/time parsing helper. - * - * Parse a datetime string into a time value. We must first try to parse - * the input according to the standard format in E5.1 Section 15.9.1.15. - * If that fails, we can try to parse using custom parsing, which can - * either be platform neutral (custom code) or platform specific (using - * existing platform API calls). - * - * Note in particular that we must parse whatever toString(), toUTCString(), - * and toISOString() can produce; see E5.1 Section 15.9.4.2. - * - * Returns 1 to allow tail calling. - * - * There is much room for improvement here with respect to supporting - * alternative datetime formats. For instance, V8 parses '2012-01-01' as - * UTC and '2012/01/01' as local time. - */ - -DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) { - /* XXX: there is a small risk here: because the ISO 8601 parser is - * very loose, it may end up parsing some datetime values which - * would be better parsed with a platform specific parser. - */ - - DUK_ASSERT(str != NULL); - DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str)); - - if (duk__parse_string_iso8601_subset(ctx, str) != 0) { - return 1; - } - -#if defined(DUK_USE_DATE_PARSE_STRING) - /* Contract, either: - * - Push value on stack and return 1 - * - Don't push anything on stack and return 0 - */ - - if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) { - return 1; - } -#else - /* No platform-specific parsing, this is not an error. */ -#endif - - duk_push_nan(ctx); - return 1; -} - -/* - * Calendar helpers - * - * Some helpers are used for getters and can operate on normalized values - * which can be represented with 32-bit signed integers. Other helpers are - * needed by setters and operate on un-normalized double values, must watch - * out for non-finite numbers etc. - */ - -DUK_LOCAL duk_uint8_t duk__days_in_month[12] = { - (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30, - (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31, - (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31 -}; - -/* Maximum iteration count for computing UTC-to-local time offset when - * creating an Ecmascript time value from local parts. - */ -#define DUK__LOCAL_TZOFFSET_MAXITER 4 - -/* Because 'day since epoch' can be negative and is used to compute weekday - * using a modulo operation, add this multiple of 7 to avoid negative values - * when year is below 1970 epoch. Ecmascript time values are restricted to - * +/- 100 million days from epoch, so this adder fits nicely into 32 bits. - * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin. - */ -#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */ - -DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) { - if ((year % 4) != 0) { - return 0; - } - if ((year % 100) != 0) { - return 1; - } - if ((year % 400) != 0) { - return 0; - } - return 1; -} - -DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) { - return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS); -} - -DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) { - return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY); -} - -DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) { - return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR); -} - -DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) { - if (!DUK_ISFINITE(x)) { - return DUK_DOUBLE_NAN; - } - - if (!duk_bi_date_timeval_in_valid_range(x)) { - return DUK_DOUBLE_NAN; - } - - x = duk_js_tointeger_number(x); - - /* Here we'd have the option to normalize -0 to +0. */ - return x; -} - -/* Integer division which floors also negative values correctly. */ -DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) { - DUK_ASSERT(b > 0); - if (a >= 0) { - return a / b; - } else { - /* e.g. a = -4, b = 5 --> -4 - 5 + 1 / 5 --> -8 / 5 --> -1 - * a = -5, b = 5 --> -5 - 5 + 1 / 5 --> -9 / 5 --> -1 - * a = -6, b = 5 --> -6 - 5 + 1 / 5 --> -10 / 5 --> -2 - */ - return (a - b + 1) / b; - } -} - -/* Compute day number of the first day of a given year. */ -DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) { - /* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative - * values, but is incorrect for negative ones. - */ - return 365 * (year - 1970) - + duk__div_floor(year - 1969, 4) - - duk__div_floor(year - 1901, 100) - + duk__div_floor(year - 1601, 400); -} - -/* Given a day number, determine year and day-within-year. */ -DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) { - duk_int_t year; - duk_int_t diff_days; - - /* estimate year upwards (towards positive infinity), then back down; - * two iterations should be enough - */ - - if (day >= 0) { - year = 1970 + day / 365; - } else { - year = 1970 + day / 366; - } - - for (;;) { - diff_days = duk__day_from_year(year) - day; - DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days)); - if (diff_days <= 0) { - DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */ - *out_day_within_year = -diff_days; - DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld", - (long) year, (long) *out_day_within_year)); - DUK_ASSERT(*out_day_within_year >= 0); - DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365)); - return year; - } - - /* Note: this is very tricky; we must never 'overshoot' the - * correction downwards. - */ - year -= 1 + (diff_days - 1) / 366; /* conservative */ - } -} - -/* Given a (year, month, day-within-month) triple, compute day number. - * The input triple is un-normalized and may contain non-finite values. - */ -DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) { - duk_int_t day_num; - duk_bool_t is_leap; - duk_small_int_t i, n; - - /* Assume that year, month, day are all coerced to whole numbers. - * They may also be NaN or infinity, in which case this function - * must return NaN or infinity to ensure time value becomes NaN. - * If 'day' is NaN, the final return will end up returning a NaN, - * so it doesn't need to be checked here. - */ - - if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) { - return DUK_DOUBLE_NAN; - } - - year += DUK_FLOOR(month / 12.0); - - month = DUK_FMOD(month, 12.0); - if (month < 0.0) { - /* handle negative values */ - month += 12.0; - } - - /* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but - * does not normalize the day-of-month (nor check whether or not - * it is finite) because it's not necessary for finding the day - * number which matches the (year,month) pair. - * - * We assume that duk__day_from_year() is exact here. - * - * Without an explicit infinity / NaN check in the beginning, - * day_num would be a bogus integer here. - * - * It's possible for 'year' to be out of integer range here. - * If so, we need to return NaN without integer overflow. - * This fixes test-bug-setyear-overflow.js. - */ - - if (!duk_bi_date_year_in_valid_range(year)) { - DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year)); - return DUK_DOUBLE_NAN; - } - day_num = duk__day_from_year((duk_int_t) year); - is_leap = duk_bi_date_is_leap_year((duk_int_t) year); - - n = (duk_small_int_t) month; - for (i = 0; i < n; i++) { - day_num += duk__days_in_month[i]; - if (i == 1 && is_leap) { - day_num++; - } - } - - /* If 'day' is NaN, returns NaN. */ - return (duk_double_t) day_num + day; -} - -/* Split time value into parts. The time value is assumed to be an internal - * one, i.e. finite, no fractions. Possible local time adjustment has already - * been applied when reading the time value. - */ -DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) { - duk_double_t d1, d2; - duk_int_t t1, t2; - duk_int_t day_since_epoch; - duk_int_t year; /* does not fit into 16 bits */ - duk_small_int_t day_in_year; - duk_small_int_t month; - duk_small_int_t day; - duk_small_int_t dim; - duk_int_t jan1_since_epoch; - duk_small_int_t jan1_weekday; - duk_int_t equiv_year; - duk_small_uint_t i; - duk_bool_t is_leap; - duk_small_int_t arridx; - - DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */ - DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions in internal time */ - - /* The timevalue must be in valid Ecmascript range, but since a local - * time offset can be applied, we need to allow a +/- 24h leeway to - * the value. In other words, although the UTC time is within the - * Ecmascript range, the local part values can be just outside of it. - */ - DUK_UNREF(duk_bi_date_timeval_in_leeway_range); - DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d)); - - /* these computations are guaranteed to be exact for the valid - * E5 time value range, assuming milliseconds without fractions. - */ - d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY); - if (d1 < 0.0) { - /* deal with negative values */ - d1 += (duk_double_t) DUK_DATE_MSEC_DAY; - } - d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY)); - DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d); - /* now expected to fit into a 32-bit integer */ - t1 = (duk_int_t) d1; - t2 = (duk_int_t) d2; - day_since_epoch = t2; - DUK_ASSERT((duk_double_t) t1 == d1); - DUK_ASSERT((duk_double_t) t2 == d2); - - /* t1 = milliseconds within day (fits 32 bit) - * t2 = day number from epoch (fits 32 bit, may be negative) - */ - - parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000; - parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60; - parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60; - parts[DUK_DATE_IDX_HOUR] = t1; - DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999); - DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59); - DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59); - DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23); - - DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld", - (double) d, (double) d1, (double) d2, (long) t1, (long) t2, - (long) parts[DUK_DATE_IDX_HOUR], - (long) parts[DUK_DATE_IDX_MINUTE], - (long) parts[DUK_DATE_IDX_SECOND], - (long) parts[DUK_DATE_IDX_MILLISECOND])); - - /* This assert depends on the input parts representing time inside - * the Ecmascript range. - */ - DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0); - parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */ - DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6); - - year = duk__year_from_day(t2, &day_in_year); - day = day_in_year; - is_leap = duk_bi_date_is_leap_year(year); - for (month = 0; month < 12; month++) { - dim = duk__days_in_month[month]; - if (month == 1 && is_leap) { - dim++; - } - DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld", - (long) month, (long) dim, (long) day)); - if (day < dim) { - break; - } - day -= dim; - } - DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month)); - DUK_ASSERT(month >= 0 && month <= 11); - DUK_ASSERT(day >= 0 && day <= 31); - - /* Equivalent year mapping, used to avoid DST trouble when platform - * may fail to provide reasonable DST answers for dates outside the - * ordinary range (e.g. 1970-2038). An equivalent year has the same - * leap-year-ness as the original year and begins on the same weekday - * (Jan 1). - * - * The year 2038 is avoided because there seem to be problems with it - * on some platforms. The year 1970 is also avoided as there were - * practical problems with it; an equivalent year is used for it too, - * which breaks some DST computations for 1970 right now, see e.g. - * test-bi-date-tzoffset-brute-fi.js. - */ - if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) { - DUK_ASSERT(is_leap == 0 || is_leap == 1); - - jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */ - DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0); - jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */ - DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6); - arridx = jan1_weekday; - if (is_leap) { - arridx += 7; - } - DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t))); - - equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970; - year = equiv_year; - DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, " - "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld", - (long) year, (long) day_in_year, (long) day_since_epoch, - (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year)); - } - - parts[DUK_DATE_IDX_YEAR] = year; - parts[DUK_DATE_IDX_MONTH] = month; - parts[DUK_DATE_IDX_DAY] = day; - - if (flags & DUK_DATE_FLAG_ONEBASED) { - parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */ - parts[DUK_DATE_IDX_DAY]++; /* -""- */ - } - - if (dparts != NULL) { - for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) { - dparts[i] = (duk_double_t) parts[i]; - } - } -} - -/* Compute time value from (double) parts. The parts can be either UTC - * or local time; if local, they need to be (conceptually) converted into - * UTC time. The parts may represent valid or invalid time, and may be - * wildly out of range (but may cancel each other and still come out in - * the valid Date range). - */ -DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) { -#if defined(DUK_USE_PARANOID_DATE_COMPUTATION) - /* See comments below on MakeTime why these are volatile. */ - volatile duk_double_t tmp_time; - volatile duk_double_t tmp_day; - volatile duk_double_t d; -#else - duk_double_t tmp_time; - duk_double_t tmp_day; - duk_double_t d; -#endif - duk_small_uint_t i; - duk_int_t tzoff, tzoffprev1, tzoffprev2; - - /* Expects 'this' at top of stack on entry. */ - - /* Coerce all finite parts with ToInteger(). ToInteger() must not - * be called for NaN/Infinity because it will convert e.g. NaN to - * zero. If ToInteger() has already been called, this has no side - * effects and is idempotent. - * - * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind - * issues if the value is uninitialized. - */ - for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) { - /* SCANBUILD: scan-build complains here about assigned value - * being garbage or undefined. This is correct but operating - * on undefined values has no ill effect and is ignored by the - * caller in the case where this happens. - */ - d = dparts[i]; - if (DUK_ISFINITE(d)) { - dparts[i] = duk_js_tointeger_number(d); - } - } - - /* Use explicit steps in computation to try to ensure that - * computation happens with intermediate results coerced to - * double values (instead of using something more accurate). - * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754 - * rules (= Ecmascript '+' and '*' operators). - * - * Without 'volatile' even this approach fails on some platform - * and compiler combinations. For instance, gcc 4.8.1 on Ubuntu - * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js - * would fail because of some optimizations when computing tmp_time - * (MakeTime below). Adding 'volatile' to tmp_time solved this - * particular problem (annoyingly, also adding debug prints or - * running the executable under valgrind hides it). - */ - - /* MakeTime */ - tmp_time = 0.0; - tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR); - tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE); - tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND); - tmp_time += dparts[DUK_DATE_IDX_MILLISECOND]; - - /* MakeDay */ - tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]); - - /* MakeDate */ - d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time; - - DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf", - (double) tmp_time, (double) tmp_day, (double) d)); - - /* Optional UTC conversion. */ - if (flags & DUK_DATE_FLAG_LOCALTIME) { - /* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a - * time value computed from UTC parts. At this point we only - * have 'd' which is a time value computed from local parts, so - * it is off by the UTC-to-local time offset which we don't know - * yet. The current solution for computing the UTC-to-local - * time offset is to iterate a few times and detect a fixed - * point or a two-cycle loop (or a sanity iteration limit), - * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js. - * - * E5.1 Section 15.9.1.9: - * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA) - * - * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0. - */ - -#if 0 - /* Old solution: don't iterate, incorrect */ - tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); - DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff)); - d -= tzoff * 1000L; - DUK_UNREF(tzoffprev1); - DUK_UNREF(tzoffprev2); -#endif - - /* Iteration solution */ - tzoff = 0; - tzoffprev1 = 999999999L; /* invalid value which never matches */ - for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) { - tzoffprev2 = tzoffprev1; - tzoffprev1 = tzoff; - tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L); - DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld", - (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2)); - if (tzoff == tzoffprev1) { - DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld", - (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2)); - break; - } else if (tzoff == tzoffprev2) { - /* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js. - * In these cases, favor a higher tzoffset to get a consistent - * result which is independent of iteration count. Not sure if - * this is a generically correct solution. - */ - DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld", - (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2)); - if (tzoffprev1 > tzoff) { - tzoff = tzoffprev1; - } - break; - } - } - DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff)); - d -= tzoff * 1000L; - } - - /* TimeClip(), which also handles Infinity -> NaN conversion */ - d = duk__timeclip(d); - - return d; -} - -/* - * API oriented helpers - */ - -/* Push 'this' binding, check that it is a Date object; then push the - * internal time value. At the end, stack is: [ ... this timeval ]. - * Returns the time value. Local time adjustment is done if requested. - */ -DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h; - duk_double_t d; - duk_int_t tzoffset = 0; - - duk_push_this(ctx); - h = duk_get_hobject(ctx, -1); /* XXX: getter with class check, useful in built-ins */ - if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) { - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "expected Date"); - } - - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); - d = duk_to_number(ctx, -1); - duk_pop(ctx); - - if (DUK_ISNAN(d)) { - if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) { - d = 0.0; - } - if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) { - DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "Invalid Date"); - } - } - /* if no NaN handling flag, may still be NaN here, but not Inf */ - DUK_ASSERT(!DUK_ISINF(d)); - - if (flags & DUK_DATE_FLAG_LOCALTIME) { - /* Note: DST adjustment is determined using UTC time. - * If 'd' is NaN, tzoffset will be 0. - */ - tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */ - d += tzoffset * 1000L; - } - if (out_tzoffset) { - *out_tzoffset = tzoffset; - } - - /* [ ... this ] */ - return d; -} - -DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags) { - return duk__push_this_get_timeval_tzoffset(ctx, flags, NULL); -} - -/* Set timeval to 'this' from dparts, push the new time value onto the - * value stack and return 1 (caller can then tail call us). Expects - * the value stack to contain 'this' on the stack top. - */ -DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags) { - duk_double_t d; - - /* [ ... this ] */ - - d = duk_bi_date_get_timeval_from_dparts(dparts, flags); - duk_push_number(ctx, d); /* -> [ ... this timeval_new ] */ - duk_dup_top(ctx); /* -> [ ... this timeval_new timeval_new ] */ - duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE); - - /* stack top: new time value, return 1 to allow tail calls */ - return 1; -} - -/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */ -DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) { - char yearstr[8]; /* "-123456\0" */ - char tzstr[8]; /* "+11:22\0" */ - char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE; - - DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12); - DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31); - DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999); - - /* Note: %06d for positive value, %07d for negative value to include - * sign and 6 digits. - */ - DUK_SNPRINTF(yearstr, - sizeof(yearstr), - (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" : - ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"), - (long) parts[DUK_DATE_IDX_YEAR]); - yearstr[sizeof(yearstr) - 1] = (char) 0; - - if (flags & DUK_DATE_FLAG_LOCALTIME) { - /* tzoffset seconds are dropped; 16 bits suffice for - * time offset in minutes - */ - if (tzoffset >= 0) { - duk_small_int_t tmp = tzoffset / 60; - DUK_SNPRINTF(tzstr, sizeof(tzstr), "+%02d:%02d", (int) (tmp / 60), (int) (tmp % 60)); - } else { - duk_small_int_t tmp = -tzoffset / 60; - DUK_SNPRINTF(tzstr, sizeof(tzstr), "-%02d:%02d", (int) (tmp / 60), (int) (tmp % 60)); - } - tzstr[sizeof(tzstr) - 1] = (char) 0; - } else { - tzstr[0] = DUK_ASC_UC_Z; - tzstr[1] = (char) 0; - } - - /* Unlike year, the other parts fit into 16 bits so %d format - * is portable. - */ - if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) { - DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s", - (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep, - (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE], - (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr); - } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) { - DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d", - (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]); - } else { - DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME); - DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s", - (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE], - (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], - (const char *) tzstr); - } -} - -/* Helper for string conversion calls: check 'this' binding, get the - * internal time value, and format date and/or time in a few formats. - * Return value allows tail calls. - */ -DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags) { - duk_double_t d; - duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; - duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */ - duk_bool_t rc; - duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE]; - - DUK_UNREF(rc); /* unreferenced with some options */ - - d = duk__push_this_get_timeval_tzoffset(ctx, flags, &tzoffset); - if (DUK_ISNAN(d)) { - duk_push_hstring_stridx(ctx, DUK_STRIDX_INVALID_DATE); - return 1; - } - DUK_ASSERT(DUK_ISFINITE(d)); - - /* formatters always get one-based month/day-of-month */ - duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED); - DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12); - DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31); - - if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) { - /* try locale specific formatter; if it refuses to format the - * string, fall back to an ISO 8601 formatted value in local - * time. - */ -#if defined(DUK_USE_DATE_FORMAT_STRING) - /* Contract, either: - * - Push string to value stack and return 1 - * - Don't push anything and return 0 - */ - - rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags); - if (rc != 0) { - return 1; - } -#else - /* No locale specific formatter; this is OK, we fall back - * to ISO 8601. - */ -#endif - } - - /* Different calling convention than above used because the helper - * is shared. - */ - duk__format_parts_iso8601(parts, tzoffset, flags, buf); - duk_push_string(ctx, (const char *) buf); - return 1; -} - -/* Helper for component getter calls: check 'this' binding, get the - * internal time value, split it into parts (either as UTC time or - * local time), push a specified component as a return value to the - * value stack and return 1 (caller can then tail call us). - */ -DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) { - duk_double_t d; - duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; - duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */ - - DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */ - DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS); - - d = duk__push_this_get_timeval(ctx, flags_and_idx); - if (DUK_ISNAN(d)) { - duk_push_nan(ctx); - return 1; - } - DUK_ASSERT(DUK_ISFINITE(d)); - - duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */ - - /* Setter APIs detect special year numbers (0...99) and apply a +1900 - * only in certain cases. The legacy getYear() getter applies -1900 - * unconditionally. - */ - duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]); - return 1; -} - -/* Helper for component setter calls: check 'this' binding, get the - * internal time value, split it into parts (either as UTC time or - * local time), modify one or more components as specified, recompute - * the time value, set it as the internal value. Finally, push the - * new time value as a return value to the value stack and return 1 - * (caller can then tail call us). - */ -DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs) { - duk_double_t d; - duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; - duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; - duk_idx_t nargs; - duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */ - duk_small_uint_t idx_first, idx; - duk_small_uint_t i; - - nargs = duk_get_top(ctx); - d = duk__push_this_get_timeval(ctx, flags_and_maxnargs); - DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d)); - - if (DUK_ISFINITE(d)) { - duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs); - } else { - /* NaN timevalue: we need to coerce the arguments, but - * the resulting internal timestamp needs to remain NaN. - * This works but is not pretty: parts and dparts will - * be partially uninitialized, but we only write to them. - */ - } - - /* - * Determining which datetime components to overwrite based on - * stack arguments is a bit complicated, but important to factor - * out from setters themselves for compactness. - * - * If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type: - * - * 1 -> millisecond - * 2 -> second, [millisecond] - * 3 -> minute, [second], [millisecond] - * 4 -> hour, [minute], [second], [millisecond] - * - * Else: - * - * 1 -> date - * 2 -> month, [date] - * 3 -> year, [month], [date] - * - * By comparing nargs and maxnargs (and flags) we know which - * components to override. We rely on part index ordering. - */ - - if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) { - DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4); - idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1); - } else { - DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3); - idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1); - } - DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */ - DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS); - - for (i = 0; i < maxnargs; i++) { - if ((duk_idx_t) i >= nargs) { - /* no argument given -> leave components untouched */ - break; - } - idx = idx_first + i; - DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */ - DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS); - - if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) { - duk__twodigit_year_fixup(ctx, (duk_idx_t) i); - } - - dparts[idx] = duk_to_number(ctx, i); - - if (idx == DUK_DATE_IDX_DAY) { - /* Day-of-month is one-based in the API, but zero-based - * internally, so fix here. Note that month is zero-based - * both in the API and internally. - */ - /* SCANBUILD: complains about use of uninitialized values. - * The complaint is correct, but operating in undefined - * values here is intentional in some cases and the caller - * ignores the results. - */ - dparts[idx] -= 1.0; - } - } - - /* Leaves new timevalue on stack top and returns 1, which is correct - * for part setters. - */ - if (DUK_ISFINITE(d)) { - return duk__set_this_timeval_from_dparts(ctx, dparts, flags_and_maxnargs); - } else { - /* Internal timevalue is already NaN, so don't touch it. */ - duk_push_nan(ctx); - return 1; - } -} - -/* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add - * 1900 and replace value at idx_val. - */ -DUK_LOCAL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val) { - duk_double_t d; - - /* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t - * might not generate better code due to casting. - */ - - /* E5 Sections 15.9.3.1, B.2.4, B.2.5 */ - duk_to_number(ctx, idx_val); - if (duk_is_nan(ctx, idx_val)) { - return; - } - duk_dup(ctx, idx_val); - duk_to_int(ctx, -1); - d = duk_get_number(ctx, -1); /* get as double to handle huge numbers correctly */ - if (d >= 0.0 && d <= 99.0) { - d += 1900.0; - duk_push_number(ctx, d); - duk_replace(ctx, idx_val); - } - duk_pop(ctx); -} - -/* Set datetime parts from stack arguments, defaulting any missing values. - * Day-of-week is not set; it is not required when setting the time value. - */ -DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs) { - duk_double_t d; - duk_small_uint_t i; - duk_small_uint_t idx; - - /* Causes a ToNumber() coercion, but doesn't break coercion order since - * year is coerced first anyway. - */ - duk__twodigit_year_fixup(ctx, 0); - - /* There are at most 7 args, but we use 8 here so that also - * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential - * for any Valgrind gripes later. - */ - for (i = 0; i < 8; i++) { - /* Note: rely on index ordering */ - idx = DUK_DATE_IDX_YEAR + i; - if ((duk_idx_t) i < nargs) { - d = duk_to_number(ctx, (duk_idx_t) i); - if (idx == DUK_DATE_IDX_DAY) { - /* Convert day from one-based to zero-based (internal). This may - * cause the day part to be negative, which is OK. - */ - d -= 1.0; - } - } else { - /* All components default to 0 except day-of-month which defaults - * to 1. However, because our internal day-of-month is zero-based, - * it also defaults to zero here. - */ - d = 0.0; - } - dparts[idx] = d; - } - - DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf", - (double) dparts[0], (double) dparts[1], - (double) dparts[2], (double) dparts[3], - (double) dparts[4], (double) dparts[5], - (double) dparts[6], (double) dparts[7])); -} - -/* - * Helper to format a time value into caller buffer, used by logging. - * 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. - */ - -DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) { - duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; - - duk_bi_date_timeval_to_parts(timeval, - parts, - NULL, - DUK_DATE_FLAG_ONEBASED); - - duk__format_parts_iso8601(parts, - 0 /*tzoffset*/, - DUK_DATE_FLAG_TOSTRING_DATE | - DUK_DATE_FLAG_TOSTRING_TIME | - DUK_DATE_FLAG_SEP_T /*flags*/, - out_buf); -} - -/* - * Indirect magic value lookup for Date methods. - * - * Date methods don't put their control flags into the function magic value - * because they wouldn't fit into a LIGHTFUNC's magic field. Instead, the - * magic value is set to an index pointing to the array of control flags - * below. - * - * This must be kept in strict sync with genbuiltins.py! - */ - -static duk_uint16_t duk__date_magics[] = { - /* 0: toString */ - DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME, - - /* 1: toDateString */ - DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME, - - /* 2: toTimeString */ - DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME, - - /* 3: toLocaleString */ - DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME, - - /* 4: toLocaleDateString */ - DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME, - - /* 5: toLocaleTimeString */ - DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME, - - /* 6: toUTCString */ - DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME, - - /* 7: toISOString */ - DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T, - - /* 8: getFullYear */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 9: getUTCFullYear */ - 0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 10: getMonth */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 11: getUTCMonth */ - 0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 12: getDate */ - DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 13: getUTCDate */ - DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 14: getDay */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 15: getUTCDay */ - 0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 16: getHours */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 17: getUTCHours */ - 0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 18: getMinutes */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 19: getUTCMinutes */ - 0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 20: getSeconds */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 21: getUTCSeconds */ - 0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 22: getMilliseconds */ - DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 23: getUTCMilliseconds */ - 0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 24: setMilliseconds */ - DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 25: setUTCMilliseconds */ - DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 26: setSeconds */ - DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 27: setUTCSeconds */ - DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 28: setMinutes */ - DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 29: setUTCMinutes */ - DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 30: setHours */ - DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 31: setUTCHours */ - DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 32: setDate */ - DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 33: setUTCDate */ - 0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 34: setMonth */ - DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 35: setUTCMonth */ - 0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 36: setFullYear */ - DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 37: setUTCFullYear */ - DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 38: getYear */ - DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT), - - /* 39: setYear */ - DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT), -}; - -DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx) { - duk_small_int_t magicidx = (duk_small_uint_t) duk_get_current_magic(ctx); - DUK_ASSERT(magicidx >= 0 && magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t))); - return (duk_small_uint_t) duk__date_magics[magicidx]; -} - -/* - * Constructor calls - */ - -DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) { - duk_idx_t nargs = duk_get_top(ctx); - duk_bool_t is_cons = duk_is_constructor_call(ctx); - duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; - duk_double_t d; - - DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons)); - - duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE), - DUK_BIDX_DATE_PROTOTYPE); - - /* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date - * is mutable. - */ - - if (nargs == 0 || !is_cons) { - d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx)); - duk_push_number(ctx, d); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W); - if (!is_cons) { - /* called as a normal function: return new Date().toString() */ - duk_to_string(ctx, -1); - } - return 1; - } else if (nargs == 1) { - duk_to_primitive(ctx, 0, DUK_HINT_NONE); - if (duk_is_string(ctx, 0)) { - duk__parse_string(ctx, duk_to_string(ctx, 0)); - duk_replace(ctx, 0); /* may be NaN */ - } - d = duk__timeclip(duk_to_number(ctx, 0)); - duk_push_number(ctx, d); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W); - return 1; - } - - duk__set_parts_from_args(ctx, dparts, nargs); - - /* Parts are in local time, convert when setting. */ - - (void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */ - duk_pop(ctx); /* -> [ ... this ] */ - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx) { - return duk__parse_string(ctx, duk_to_string(ctx, 0)); -} - -DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) { - duk_idx_t nargs = duk_get_top(ctx); - duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; - duk_double_t d; - - /* Behavior for nargs < 2 is implementation dependent: currently we'll - * set a NaN time value (matching V8 behavior) in this case. - */ - - if (nargs < 2) { - duk_push_nan(ctx); - } else { - duk__set_parts_from_args(ctx, dparts, nargs); - d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/); - duk_push_number(ctx, d); - } - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) { - duk_double_t d; - - d = DUK_USE_DATE_GET_NOW(ctx); - DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */ - duk_push_number(ctx, d); - return 1; -} - -/* - * String/JSON conversions - * - * Human readable conversions are now basically ISO 8601 with a space - * (instead of 'T') as the date/time separator. This is a good baseline - * and is platform independent. - * - * A shared native helper to provide many conversions. Magic value contains - * a set of flags. The helper provides: - * - * toString() - * toDateString() - * toTimeString() - * toLocaleString() - * toLocaleDateString() - * toLocaleTimeString() - * toUTCString() - * toISOString() - * - * Notes: - * - * - Date.prototype.toGMTString() and Date.prototype.toUTCString() are - * required to be the same Ecmascript function object (!), so it is - * omitted from here. - * - * - Date.prototype.toUTCString(): E5.1 specification does not require a - * specific format, but result should be human readable. The - * specification suggests using ISO 8601 format with a space (instead - * of 'T') separator if a more human readable format is not available. - * - * - Date.prototype.toISOString(): unlike other conversion functions, - * toISOString() requires a RangeError for invalid date values. - */ - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx) { - duk_small_uint_t flags = duk__date_get_indirect_magic(ctx); - return duk__to_string_helper(ctx, flags); -} - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx) { - /* This native function is also used for Date.prototype.getTime() - * as their behavior is identical. - */ - - duk_double_t d = duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ this ] */ - DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d)); - duk_push_number(ctx, d); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx) { - /* Note: toJSON() is a generic function which works even if 'this' - * is not a Date. The sole argument is ignored. - */ - - duk_push_this(ctx); - duk_to_object(ctx, -1); - - duk_dup_top(ctx); - duk_to_primitive(ctx, -1, DUK_HINT_NUMBER); - if (duk_is_number(ctx, -1)) { - duk_double_t d = duk_get_number(ctx, -1); - if (!DUK_ISFINITE(d)) { - duk_push_null(ctx); - return 1; - } - } - duk_pop(ctx); - - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_ISO_STRING); - duk_dup(ctx, -2); /* -> [ O toIsoString O ] */ - duk_call_method(ctx, 0); - return 1; -} - -/* - * Getters. - * - * Implementing getters is quite easy. The internal time value is either - * NaN, or represents milliseconds (without fractions) from Jan 1, 1970. - * The internal time value can be converted to integer parts, and each - * part will be normalized and will fit into a 32-bit signed integer. - * - * A shared native helper to provide all getters. Magic value contains - * a set of flags and also packs the date component index argument. The - * helper provides: - * - * getFullYear() - * getUTCFullYear() - * getMonth() - * getUTCMonth() - * getDate() - * getUTCDate() - * getDay() - * getUTCDay() - * getHours() - * getUTCHours() - * getMinutes() - * getUTCMinutes() - * getSeconds() - * getUTCSeconds() - * getMilliseconds() - * getUTCMilliseconds() - * getYear() - * - * Notes: - * - * - Date.prototype.getDate(): 'date' means day-of-month, and is - * zero-based in internal calculations but public API expects it to - * be one-based. - * - * - Date.prototype.getTime() and Date.prototype.valueOf() have identical - * behavior. They have separate function objects, but share the same C - * function (duk_bi_date_prototype_value_of). - */ - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx) { - duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(ctx); - return duk__get_part_helper(ctx, flags_and_idx); -} - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) { - /* - * Return (t - LocalTime(t)) in minutes: - * - * t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t)) - * = -(LocalTZA + DaylightSavingTA(t)) - * - * where DaylightSavingTA() is checked for time 't'. - * - * Note that the sign of the result is opposite to common usage, - * e.g. for EE(S)T which normally is +2h or +3h from UTC, this - * function returns -120 or -180. - * - */ - - duk_double_t d; - duk_int_t tzoffset; - - /* Note: DST adjustment is determined using UTC time. */ - d = duk__push_this_get_timeval(ctx, 0 /*flags*/); - DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d)); - if (DUK_ISNAN(d)) { - duk_push_nan(ctx); - } else { - DUK_ASSERT(DUK_ISFINITE(d)); - tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); - duk_push_int(ctx, -tzoffset / 60); - } - return 1; -} - -/* - * Setters. - * - * Setters are a bit more complicated than getters. Component setters - * break down the current time value into its (normalized) component - * parts, replace one or more components with -unnormalized- new values, - * and the components are then converted back into a time value. As an - * example of using unnormalized values: - * - * var d = new Date(1234567890); - * - * is equivalent to: - * - * var d = new Date(0); - * d.setUTCMilliseconds(1234567890); - * - * A shared native helper to provide almost all setters. Magic value - * contains a set of flags and also packs the "maxnargs" argument. The - * helper provides: - * - * setMilliseconds() - * setUTCMilliseconds() - * setSeconds() - * setUTCSeconds() - * setMinutes() - * setUTCMinutes() - * setHours() - * setUTCHours() - * setDate() - * setUTCDate() - * setMonth() - * setUTCMonth() - * setFullYear() - * setUTCFullYear() - * setYear() - * - * Notes: - * - * - Date.prototype.setYear() (Section B addition): special year check - * is omitted. NaN / Infinity will just flow through and ultimately - * result in a NaN internal time value. - * - * - Date.prototype.setYear() does not have optional arguments for - * setting month and day-in-month (like setFullYear()), but we indicate - * 'maxnargs' to be 3 to get the year written to the correct component - * index in duk__set_part_helper(). The function has nargs == 1, so only - * the year will be set regardless of actual argument count. - */ - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx) { - duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(ctx); - return duk__set_part_helper(ctx, flags_and_maxnargs); -} - -DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) { - duk_double_t d; - - (void) duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ timeval this ] */ - d = duk__timeclip(duk_to_number(ctx, 0)); - duk_push_number(ctx, d); - duk_dup_top(ctx); - duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */ - - return 1; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_date_unix.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_date_unix.c deleted file mode 100644 index 2b9690eb..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_date_unix.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Unix-like Date providers - * - * Generally useful Unix / POSIX / ANSI Date providers. - */ - -#include "duk_internal.h" - -/* The necessary #includes are in place in duk_config.h. */ - -/* Buffer sizes for some UNIX calls. Larger than strictly necessary - * to avoid Valgrind errors. - */ -#define DUK__STRPTIME_BUF_SIZE 64 -#define DUK__STRFTIME_BUF_SIZE 64 - -#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY) -/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */ -DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - struct timeval tv; - duk_double_t d; - - if (gettimeofday(&tv, NULL) != 0) { - DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "gettimeofday failed"); - } - - d = ((duk_double_t) tv.tv_sec) * 1000.0 + - ((duk_double_t) (tv.tv_usec / 1000)); - DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions */ - - return d; -} -#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */ - -#if defined(DUK_USE_DATE_NOW_TIME) -/* Not a very good provider: only full seconds are available. */ -DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(duk_context *ctx) { - time_t t = time(NULL); - return ((duk_double_t) t) * 1000.0; -} -#endif /* DUK_USE_DATE_NOW_TIME */ - -#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) -/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */ -DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) { - time_t t, t1, t2; - duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; - duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; - struct tm tms[2]; -#ifdef DUK_USE_DATE_TZO_GMTIME - struct tm *tm_ptr; -#endif - - /* For NaN/inf, the return value doesn't matter. */ - if (!DUK_ISFINITE(d)) { - return 0; - } - - /* If not within Ecmascript range, some integer time calculations - * won't work correctly (and some asserts will fail), so bail out - * if so. This fixes test-bug-date-insane-setyear.js. There is - * a +/- 24h leeway in this range check to avoid a test262 corner - * case documented in test-bug-date-timeval-edges.js. - */ - if (!duk_bi_date_timeval_in_leeway_range(d)) { - DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows")); - return 0; - } - - /* - * This is a bit tricky to implement portably. The result depends - * on the timestamp (specifically, DST depends on the timestamp). - * If e.g. UNIX APIs are used, they'll have portability issues with - * very small and very large years. - * - * Current approach: - * - * - Stay within portable UNIX limits by using equivalent year mapping. - * Avoid year 1970 and 2038 as some conversions start to fail, at - * least on some platforms. Avoiding 1970 means that there are - * currently DST discrepancies for 1970. - * - * - Create a UTC and local time breakdowns from 't'. Then create - * a time_t using gmtime() and localtime() and compute the time - * difference between the two. - * - * Equivalent year mapping (E5 Section 15.9.1.8): - * - * If the host environment provides functionality for determining - * daylight saving time, the implementation of ECMAScript is free - * to map the year in question to an equivalent year (same - * leap-year-ness and same starting week day for the year) for which - * the host environment provides daylight saving time information. - * The only restriction is that all equivalent years should produce - * the same result. - * - * This approach is quite reasonable but not entirely correct, e.g. - * the specification also states (E5 Section 15.9.1.8): - * - * The implementation of ECMAScript should not try to determine - * whether the exact time was subject to daylight saving time, but - * just whether daylight saving time would have been in effect if - * the _current daylight saving time algorithm_ had been used at the - * time. This avoids complications such as taking into account the - * years that the locale observed daylight saving time year round. - * - * Since we rely on the platform APIs for conversions between local - * time and UTC, we can't guarantee the above. Rather, if the platform - * has historical DST rules they will be applied. This seems to be the - * general preferred direction in Ecmascript standardization (or at least - * implementations) anyway, and even the equivalent year mapping should - * be disabled if the platform is known to handle DST properly for the - * full Ecmascript range. - * - * The following has useful discussion and links: - * - * https://bugzilla.mozilla.org/show_bug.cgi?id=351066 - */ - - duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/); - DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038); - - d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/); - DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */ - t = (time_t) (d / 1000.0); - DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t)); - - t1 = t; - - DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2); - -#if defined(DUK_USE_DATE_TZO_GMTIME_R) - (void) gmtime_r(&t, &tms[0]); - (void) localtime_r(&t, &tms[1]); -#elif defined(DUK_USE_DATE_TZO_GMTIME) - tm_ptr = gmtime(&t); - DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm)); - tm_ptr = localtime(&t); - DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm)); -#else -#error internal error -#endif - DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," - "wday:%ld,yday:%ld,isdst:%ld}", - (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour, - (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year, - (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst)); - DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," - "wday:%ld,yday:%ld,isdst:%ld}", - (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour, - (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year, - (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst)); - - t1 = mktime(&tms[0]); /* UTC */ - t2 = mktime(&tms[1]); /* local */ - if (t1 == (time_t) -1 || t2 == (time_t) -1) { - /* This check used to be for (t < 0) but on some platforms - * time_t is unsigned and apparently the proper way to detect - * an mktime() error return is the cast above. See e.g.: - * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html - */ - goto error; - } - if (tms[1].tm_isdst > 0) { - t2 += 3600; - } else if (tms[1].tm_isdst < 0) { - DUK_D(DUK_DPRINT("tm_isdst is negative: %d", (int) tms[1].tm_isdst)); - } - DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2)); - - /* Compute final offset in seconds, positive if local time ahead of - * UTC (returned value is UTC-to-local offset). - * - * difftime() returns a double, so coercion to int generates quite - * a lot of code. Direct subtraction is not portable, however. - * XXX: allow direct subtraction on known platforms. - */ -#if 0 - return (duk_int_t) (t2 - t1); -#endif - return (duk_int_t) difftime(t2, t1); - - error: - /* XXX: return something more useful, so that caller can throw? */ - DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d)); - return 0; -} -#endif /* DUK_USE_DATE_TZO_GMTIME */ - -#if defined(DUK_USE_DATE_PRS_STRPTIME) -DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) { - struct tm tm; - time_t t; - char buf[DUK__STRPTIME_BUF_SIZE]; - - /* copy to buffer with spare to avoid Valgrind gripes from strptime */ - DUK_ASSERT(str != NULL); - DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */ - DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str); - buf[sizeof(buf) - 1] = (char) 0; - - DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf)); - - DUK_MEMZERO(&tm, sizeof(tm)); - if (strptime((const char *) buf, "%c", &tm) != NULL) { - DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," - "wday:%ld,yday:%ld,isdst:%ld}", - (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour, - (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year, - (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst)); - tm.tm_isdst = -1; /* negative: dst info not available */ - - t = mktime(&tm); - DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t)); - if (t >= 0) { - duk_push_number(ctx, ((duk_double_t) t) * 1000.0); - return 1; - } - } - - return 0; -} -#endif /* DUK_USE_DATE_PRS_STRPTIME */ - -#if defined(DUK_USE_DATE_PRS_GETDATE) -DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) { - struct tm tm; - duk_small_int_t rc; - time_t t; - - /* For this to work, DATEMSK must be set, so this is not very - * convenient for an embeddable interpreter. - */ - - DUK_MEMZERO(&tm, sizeof(struct tm)); - rc = (duk_small_int_t) getdate_r(str, &tm); - DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc)); - - if (rc == 0) { - t = mktime(&tm); - DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t)); - if (t >= 0) { - duk_push_number(ctx, (duk_double_t) t); - return 1; - } - } - - return 0; -} -#endif /* DUK_USE_DATE_PRS_GETDATE */ - -#if defined(DUK_USE_DATE_FMT_STRFTIME) -DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) { - char buf[DUK__STRFTIME_BUF_SIZE]; - struct tm tm; - const char *fmt; - - DUK_UNREF(tzoffset); - - /* If the platform doesn't support the entire Ecmascript range, we need - * to return 0 so that the caller can fall back to the default formatter. - * - * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript - * range is supported. For smaller time_t values (4 bytes in practice), - * assumes that the signed 32-bit range is supported. - * - * XXX: detect this more correctly per platform. The size of time_t is - * probably not an accurate guarantee of strftime() supporting or not - * supporting a large time range (the full Ecmascript range). - */ - if (sizeof(time_t) < 8 && - (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) { - /* be paranoid for 32-bit time values (even avoiding negative ones) */ - return 0; - } - - DUK_MEMZERO(&tm, sizeof(tm)); - tm.tm_sec = parts[DUK_DATE_IDX_SECOND]; - tm.tm_min = parts[DUK_DATE_IDX_MINUTE]; - tm.tm_hour = parts[DUK_DATE_IDX_HOUR]; - tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */ - tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */ - tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900; - tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY]; - tm.tm_isdst = 0; - - DUK_MEMZERO(buf, sizeof(buf)); - if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) { - fmt = "%c"; - } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) { - fmt = "%x"; - } else { - DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME); - fmt = "%X"; - } - (void) strftime(buf, sizeof(buf) - 1, fmt, &tm); - DUK_ASSERT(buf[sizeof(buf) - 1] == 0); - - duk_push_string(ctx, buf); - return 1; -} -#endif /* DUK_USE_DATE_FMT_STRFTIME */ - -#undef DUK__STRPTIME_BUF_SIZE -#undef DUK__STRFTIME_BUF_SIZE diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_date_windows.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_date_windows.c deleted file mode 100644 index c131d227..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_date_windows.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Windows Date providers - * - * Platform specific links: - * - * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx - */ - -#include "duk_internal.h" - -/* The necessary #includes are in place in duk_config.h. */ - -#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) -/* Shared Windows helpers. */ -DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) { - FILETIME ft; - if (SystemTimeToFileTime(st, &ft) == 0) { - DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0")); - res->QuadPart = 0; - } else { - res->LowPart = ft.dwLowDateTime; - res->HighPart = ft.dwHighDateTime; - } -} -DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) { - DUK_MEMZERO((void *) st, sizeof(*st)); - st->wYear = 1970; - st->wMonth = 1; - st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */ - st->wDay = 1; - DUK_ASSERT(st->wHour == 0); - DUK_ASSERT(st->wMinute == 0); - DUK_ASSERT(st->wSecond == 0); - DUK_ASSERT(st->wMilliseconds == 0); -} -#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */ - -#ifdef DUK_USE_DATE_NOW_WINDOWS -DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) { - /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx - */ - SYSTEMTIME st1, st2; - ULARGE_INTEGER tmp1, tmp2; - - DUK_UNREF(ctx); - - GetSystemTime(&st1); - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1); - - duk__set_systime_jan1970(&st2); - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2); - - /* Difference is in 100ns units, convert to milliseconds w/o fractions */ - return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL); -} -#endif /* DUK_USE_DATE_NOW_WINDOWS */ - - -#if defined(DUK_USE_DATE_TZO_WINDOWS) -DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) { - SYSTEMTIME st1; - SYSTEMTIME st2; - SYSTEMTIME st3; - ULARGE_INTEGER tmp1; - ULARGE_INTEGER tmp2; - ULARGE_INTEGER tmp3; - FILETIME ft1; - - /* XXX: handling of timestamps outside Windows supported range. - * How does Windows deal with dates before 1600? Does windows - * support all Ecmascript years (like -200000 and +200000)? - * Should equivalent year mapping be used here too? If so, use - * a shared helper (currently integrated into timeval-to-parts). - */ - - /* Use the approach described in "Remarks" of FileTimeToLocalFileTime: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx - */ - - duk__set_systime_jan1970(&st1); - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1); - tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */ - tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */ - - ft1.dwLowDateTime = tmp2.LowPart; - ft1.dwHighDateTime = tmp2.HighPart; - FileTimeToSystemTime((const FILETIME *) &ft1, &st2); - if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) { - DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0")); - return 0; - } - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3); - - /* Positive if local time ahead of UTC. */ - return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */ -} -#endif /* DUK_USE_DATE_TZO_WINDOWS */ diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_duktape.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_duktape.c deleted file mode 100644 index 44b47a2d..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_duktape.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Duktape built-ins - * - * Size optimization note: it might seem that vararg multipurpose functions - * like fin(), enc(), and dec() are not very size optimal, but using a single - * user-visible Ecmascript function saves a lot of run-time footprint; each - * Function instance takes >100 bytes. Using a shared native helper and a - * 'magic' value won't save much if there are multiple Function instances - * anyway. - */ - -#include "duk_internal.h" - -/* Raw helper to extract internal information / statistics about a value. - * The return values are version specific and must not expose anything - * that would lead to security issues (e.g. exposing compiled function - * 'data' buffer might be an issue). Currently only counts and sizes and - * such are given so there should not be a security impact. - */ -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - duk_heaphdr *h; - duk_int_t i, n; - - DUK_UNREF(thr); - - /* result array */ - duk_push_array(ctx); /* -> [ val arr ] */ - - /* type tag (public) */ - duk_push_int(ctx, duk_get_type(ctx, 0)); - - /* address */ - tv = duk_get_tval(ctx, 0); - DUK_ASSERT(tv != NULL); /* because arg count is 1 */ - if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) { - h = DUK_TVAL_GET_HEAPHDR(tv); - duk_push_pointer(ctx, (void *) h); - } else { - /* internal type tag */ - duk_push_int(ctx, (duk_int_t) DUK_TVAL_GET_TAG(tv)); - goto done; - } - DUK_ASSERT(h != NULL); - - /* refcount */ -#ifdef DUK_USE_REFERENCE_COUNTING - duk_push_size_t(ctx, DUK_HEAPHDR_GET_REFCOUNT(h)); -#else - duk_push_undefined(ctx); -#endif - - /* heaphdr size and additional allocation size, followed by - * type specific stuff (with varying value count) - */ - switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) { - case DUK_HTYPE_STRING: { - duk_hstring *h_str = (duk_hstring *) h; - duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1)); - break; - } - case DUK_HTYPE_OBJECT: { - duk_hobject *h_obj = (duk_hobject *) h; - duk_small_uint_t hdr_size; - if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) { - hdr_size = (duk_small_uint_t) sizeof(duk_hcompiledfunction); - } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) { - hdr_size = (duk_small_uint_t) sizeof(duk_hnativefunction); - } else if (DUK_HOBJECT_IS_THREAD(h_obj)) { - hdr_size = (duk_small_uint_t) sizeof(duk_hthread); - } else { - hdr_size = (duk_small_uint_t) sizeof(duk_hobject); - } - duk_push_uint(ctx, (duk_uint_t) hdr_size); - duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_E_ALLOC_SIZE(h_obj)); - duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj)); - /* Note: e_next indicates the number of gc-reachable entries - * in the entry part, and also indicates the index where the - * next new property would be inserted. It does *not* indicate - * the number of non-NULL keys present in the object. That - * value could be counted separately but requires a pass through - * the key list. - */ - duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj)); - duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj)); - duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj)); - if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) { - duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, (duk_hcompiledfunction *) h_obj); - if (h_data) { - duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_data)); - } else { - duk_push_uint(ctx, 0); - } - } - break; - } - case DUK_HTYPE_BUFFER: { - duk_hbuffer *h_buf = (duk_hbuffer *) h; - if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) { - if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) { - duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_external))); - } else { - /* When alloc_size == 0 the second allocation may not - * actually exist. - */ - duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_dynamic))); - } - duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_GET_SIZE(h_buf))); - } else { - duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1)); - } - break; - - } - } - - done: - /* set values into ret array */ - /* XXX: primitive to make array from valstack slice */ - n = duk_get_top(ctx); - for (i = 2; i < n; i++) { - duk_dup(ctx, i); - duk_put_prop_index(ctx, 1, i - 2); - } - duk_dup(ctx, 1); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_activation *act; - duk_uint_fast32_t pc; - duk_uint_fast32_t line; - duk_int_t level; - - /* -1 = top callstack entry, callstack[callstack_top - 1] - * -callstack_top = bottom callstack entry, callstack[0] - */ - level = duk_to_int(ctx, 0); - if (level >= 0 || -level > (duk_int_t) thr->callstack_top) { - return 0; - } - DUK_ASSERT(level >= -((duk_int_t) thr->callstack_top) && level <= -1); - act = thr->callstack + thr->callstack_top + level; - - duk_push_object(ctx); - - duk_push_tval(ctx, &act->tv_func); - - /* Relevant PC is just before current one because PC is - * post-incremented. This should match what error augment - * code does. - */ - pc = duk_hthread_get_act_prev_pc(thr, act); - duk_push_uint(ctx, (duk_uint_t) pc); - -#if defined(DUK_USE_PC2LINE) - line = duk_hobject_pc2line_query(ctx, -2, pc); -#else - line = 0; -#endif - duk_push_uint(ctx, (duk_uint_t) line); - - /* Providing access to e.g. act->lex_env would be dangerous: these - * internal structures must never be accessible to the application. - * Duktape relies on them having consistent data, and this consistency - * is only asserted for, not checked for. - */ - - /* [ level obj func pc line ] */ - - /* XXX: version specific array format instead? */ - duk_xdef_prop_stridx_wec(ctx, -4, DUK_STRIDX_LINE_NUMBER); - duk_xdef_prop_stridx_wec(ctx, -3, DUK_STRIDX_PC); - duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_LC_FUNCTION); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) { -#ifdef DUK_USE_MARK_AND_SWEEP - duk_hthread *thr = (duk_hthread *) ctx; - duk_small_uint_t flags; - duk_bool_t rc; - - flags = (duk_small_uint_t) duk_get_uint(ctx, 0); - rc = duk_heap_mark_and_sweep(thr->heap, flags); - - /* XXX: Not sure what the best return value would be in the API. - * Return a boolean for now. Note that rc == 0 is success (true). - */ - duk_push_boolean(ctx, !rc); - return 1; -#else - DUK_UNREF(ctx); - return 0; -#endif -} - -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx) { - (void) duk_require_hobject(ctx, 0); - if (duk_get_top(ctx) >= 2) { - /* Set: currently a finalizer is disabled by setting it to - * undefined; this does not remove the property at the moment. - * The value could be type checked to be either a function - * or something else; if something else, the property could - * be deleted. - */ - duk_set_top(ctx, 2); - (void) duk_put_prop_stridx(ctx, 0, DUK_STRIDX_INT_FINALIZER); - return 0; - } else { - /* Get. */ - DUK_ASSERT(duk_get_top(ctx) == 1); - duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_FINALIZER); - return 1; - } -} - -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_str; - - /* Vararg function: must be careful to check/require arguments. - * The JSON helpers accept invalid indices and treat them like - * non-existent optional parameters. - */ - - h_str = duk_require_hstring(ctx, 0); - duk_require_valid_index(ctx, 1); - - if (h_str == DUK_HTHREAD_STRING_HEX(thr)) { - duk_set_top(ctx, 2); - duk_hex_encode(ctx, 1); - DUK_ASSERT_TOP(ctx, 2); - } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) { - duk_set_top(ctx, 2); - duk_base64_encode(ctx, 1); - DUK_ASSERT_TOP(ctx, 2); -#ifdef DUK_USE_JX - } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) { - duk_bi_json_stringify_helper(ctx, - 1 /*idx_value*/, - 2 /*idx_replacer*/, - 3 /*idx_space*/, - DUK_JSON_FLAG_EXT_CUSTOM | - DUK_JSON_FLAG_ASCII_ONLY | - DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/); -#endif -#ifdef DUK_USE_JC - } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) { - duk_bi_json_stringify_helper(ctx, - 1 /*idx_value*/, - 2 /*idx_replacer*/, - 3 /*idx_space*/, - DUK_JSON_FLAG_EXT_COMPATIBLE | - DUK_JSON_FLAG_ASCII_ONLY /*flags*/); -#endif - } else { - return DUK_RET_TYPE_ERROR; - } - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_str; - - /* Vararg function: must be careful to check/require arguments. - * The JSON helpers accept invalid indices and treat them like - * non-existent optional parameters. - */ - - h_str = duk_require_hstring(ctx, 0); - duk_require_valid_index(ctx, 1); - - if (h_str == DUK_HTHREAD_STRING_HEX(thr)) { - duk_set_top(ctx, 2); - duk_hex_decode(ctx, 1); - DUK_ASSERT_TOP(ctx, 2); - } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) { - duk_set_top(ctx, 2); - duk_base64_decode(ctx, 1); - DUK_ASSERT_TOP(ctx, 2); -#ifdef DUK_USE_JX - } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) { - duk_bi_json_parse_helper(ctx, - 1 /*idx_value*/, - 2 /*idx_replacer*/, - DUK_JSON_FLAG_EXT_CUSTOM /*flags*/); -#endif -#ifdef DUK_USE_JC - } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) { - duk_bi_json_parse_helper(ctx, - 1 /*idx_value*/, - 2 /*idx_replacer*/, - DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/); -#endif - } else { - return DUK_RET_TYPE_ERROR; - } - return 1; -} - -/* - * Compact an object - */ - -DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx) { - DUK_ASSERT_TOP(ctx, 1); - duk_compact(ctx, 0); - return 1; /* return the argument object */ -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_error.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_error.c deleted file mode 100644 index fadc26ab..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_error.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Error built-ins - */ - -#include "duk_internal.h" - -DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) { - /* Behavior for constructor and non-constructor call is - * the same except for augmenting the created error. When - * called as a constructor, the caller (duk_new()) will handle - * augmentation; when called as normal function, we need to do - * it here. - */ - - duk_hthread *thr = (duk_hthread *) ctx; - duk_small_int_t bidx_prototype = duk_get_current_magic(ctx); - - /* same for both error and each subclass like TypeError */ - duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR); - - DUK_UNREF(thr); - - duk_push_object_helper(ctx, flags_and_class, bidx_prototype); - - /* If message is undefined, the own property 'message' is not set at - * all to save property space. An empty message is inherited anyway. - */ - if (!duk_is_undefined(ctx, 0)) { - duk_to_string(ctx, 0); - duk_dup(ctx, 0); /* [ message error message ] */ - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC); - } - - /* Augment the error if called as a normal function. __FILE__ and __LINE__ - * are not desirable in this case. - */ - -#ifdef DUK_USE_AUGMENT_ERROR_CREATE - if (!duk_is_constructor_call(ctx)) { - duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/); - } -#endif - - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) { - /* XXX: optimize with more direct internal access */ - - duk_push_this(ctx); - (void) duk_require_hobject_or_lfunc_coerce(ctx, -1); - - /* [ ... this ] */ - - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME); - if (duk_is_undefined(ctx, -1)) { - duk_pop(ctx); - duk_push_string(ctx, "Error"); - } else { - duk_to_string(ctx, -1); - } - - /* [ ... this name ] */ - - /* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by - * accident or are they actually needed? The first ToString() - * could conceivably return 'undefined'. - */ - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE); - if (duk_is_undefined(ctx, -1)) { - duk_pop(ctx); - duk_push_string(ctx, ""); - } else { - duk_to_string(ctx, -1); - } - - /* [ ... this name message ] */ - - if (duk_get_length(ctx, -2) == 0) { - /* name is empty -> return message */ - return 1; - } - if (duk_get_length(ctx, -1) == 0) { - /* message is empty -> return name */ - duk_pop(ctx); - return 1; - } - duk_push_string(ctx, ": "); - duk_insert(ctx, -2); /* ... name ': ' message */ - duk_concat(ctx, 3); - - return 1; -} - -#ifdef DUK_USE_TRACEBACKS - -/* - * Traceback handling - * - * The unified helper decodes the traceback and produces various requested - * outputs. It should be optimized for size, and may leave garbage on stack, - * only the topmost return value matters. For instance, traceback separator - * and decoded strings are pushed even when looking for filename only. - * - * NOTE: although _Tracedata is an internal property, user code can currently - * write to the array (or replace it with something other than an array). - * The code below must tolerate arbitrary _Tracedata. It can throw errors - * etc, but cannot cause a segfault or memory unsafe behavior. - */ - -/* constants arbitrary, chosen for small loads */ -#define DUK__OUTPUT_TYPE_TRACEBACK (-1) -#define DUK__OUTPUT_TYPE_FILENAME 0 -#define DUK__OUTPUT_TYPE_LINENUMBER 1 - -DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t output_type) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t idx_td; - duk_small_int_t i; /* traceback depth fits into 16 bits */ - duk_small_int_t t; /* stack type fits into 16 bits */ - const char *str_tailcalled = " tailcalled"; - const char *str_strict = " strict"; - const char *str_construct = " construct"; - const char *str_prevyield = " preventsyield"; - const char *str_directeval = " directeval"; - const char *str_empty = ""; - - DUK_ASSERT_TOP(ctx, 0); /* fixed arg count */ - - duk_push_this(ctx); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TRACEDATA); - idx_td = duk_get_top_index(ctx); - - duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_TAB); - duk_push_this(ctx); - - /* [ ... this tracedata sep this ] */ - - /* XXX: skip null filename? */ - - if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) { - /* Current tracedata contains 2 entries per callstack entry. */ - for (i = 0; ; i += 2) { - duk_int_t pc; - duk_int_t line; - duk_int_t flags; - duk_double_t d; - const char *funcname; - const char *filename; - duk_hobject *h_func; - duk_hstring *h_name; - - duk_require_stack(ctx, 5); - duk_get_prop_index(ctx, idx_td, i); - duk_get_prop_index(ctx, idx_td, i + 1); - d = duk_to_number(ctx, -1); - pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32); - flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32); - t = (duk_small_int_t) duk_get_type(ctx, -2); - - if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) { - /* - * Ecmascript/native function call or lightfunc call - */ - - /* [ ... v1(func) v2(pc+flags) ] */ - - h_func = duk_get_hobject(ctx, -2); /* NULL for lightfunc */ - - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME); - duk_get_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME); - -#if defined(DUK_USE_PC2LINE) - line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc); -#else - line = 0; -#endif - - /* [ ... v1 v2 name filename ] */ - - if (output_type == DUK__OUTPUT_TYPE_FILENAME) { - return 1; - } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) { - duk_push_int(ctx, line); - return 1; - } - - h_name = duk_get_hstring(ctx, -2); /* may be NULL */ - funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ? - "anon" : (const char *) DUK_HSTRING_GET_DATA(h_name); - filename = duk_get_string(ctx, -1); - filename = filename ? filename : ""; - DUK_ASSERT(funcname != NULL); - DUK_ASSERT(filename != NULL); - - if (h_func == NULL) { - duk_push_sprintf(ctx, "%s light%s%s%s%s%s", - (const char *) funcname, - (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcalled : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty)); - } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) { - duk_push_sprintf(ctx, "%s %s native%s%s%s%s%s", - (const char *) funcname, - (const char *) filename, - (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcalled : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty)); - } else { - duk_push_sprintf(ctx, "%s %s:%ld%s%s%s%s%s", - (const char *) funcname, - (const char *) filename, - (long) line, - (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcalled : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty), - (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty)); - } - duk_replace(ctx, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */ - duk_pop_n(ctx, 3); /* -> [ ... str ] */ - } else if (t == DUK_TYPE_STRING) { - /* - * __FILE__ / __LINE__ entry, here 'pc' is line number directly. - * Sometimes __FILE__ / __LINE__ is reported as the source for - * the error (fileName, lineNumber), sometimes not. - */ - - /* [ ... v1(filename) v2(line+flags) ] */ - - if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) { - if (output_type == DUK__OUTPUT_TYPE_FILENAME) { - duk_pop(ctx); - return 1; - } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) { - duk_push_int(ctx, pc); - return 1; - } - } - - duk_push_sprintf(ctx, "%s:%ld", - (const char *) duk_get_string(ctx, -2), (long) pc); - duk_replace(ctx, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */ - duk_pop(ctx); /* -> [ ... str ] */ - } else { - /* unknown, ignore */ - duk_pop_2(ctx); - break; - } - } - - if (i >= DUK_USE_TRACEBACK_DEPTH * 2) { - /* Possibly truncated; there is no explicit truncation - * marker so this is the best we can do. - */ - - duk_push_hstring_stridx(ctx, DUK_STRIDX_BRACKETED_ELLIPSIS); - } - } - - /* [ ... this tracedata sep this str1 ... strN ] */ - - if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) { - return 0; - } else { - /* The 'this' after 'sep' will get ToString() coerced by - * duk_join() automatically. We don't want to do that - * coercion when providing .fileName or .lineNumber (GH-254). - */ - duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/); - return 1; - } -} - -/* XXX: output type could be encoded into native function 'magic' value to - * save space. - */ - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) { - return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK); -} - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) { - return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME); -} - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) { - return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER); -} - -#undef DUK__OUTPUT_TYPE_TRACEBACK -#undef DUK__OUTPUT_TYPE_FILENAME -#undef DUK__OUTPUT_TYPE_LINENUMBER - -#else /* DUK_USE_TRACEBACKS */ - -/* - * Traceback handling when tracebacks disabled. - * - * The fileName / lineNumber stubs are now necessary because built-in - * data will include the accessor properties in Error.prototype. If those - * are removed for builds without tracebacks, these can also be removed. - * 'stack' should still be present and produce a ToString() equivalent: - * this is useful for user code which prints a stacktrace and expects to - * see something useful. A normal stacktrace also begins with a ToString() - * of the error so this makes sense. - */ - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) { - /* XXX: remove this native function and map 'stack' accessor - * to the toString() implementation directly. - */ - return duk_bi_error_prototype_to_string(ctx); -} - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) { - DUK_UNREF(ctx); - return 0; -} - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) { - DUK_UNREF(ctx); - return 0; -} - -#endif /* DUK_USE_TRACEBACKS */ - -DUK_INTERNAL duk_ret_t duk_bi_error_prototype_nop_setter(duk_context *ctx) { - /* Attempt to write 'stack', 'fileName', 'lineNumber' is a silent no-op. - * User can use Object.defineProperty() to override this behavior. - */ - DUK_ASSERT_TOP(ctx, 1); /* fixed arg count */ - DUK_UNREF(ctx); - return 0; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_function.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_function.c deleted file mode 100644 index e91d129c..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_function.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Function built-ins - */ - -#include "duk_internal.h" - -DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h_sourcecode; - duk_idx_t nargs; - duk_idx_t i; - duk_small_uint_t comp_flags; - duk_hcompiledfunction *func; - duk_hobject *outer_lex_env; - duk_hobject *outer_var_env; - - /* normal and constructor calls have identical semantics */ - - nargs = duk_get_top(ctx); - for (i = 0; i < nargs; i++) { - duk_to_string(ctx, i); - } - - if (nargs == 0) { - duk_push_string(ctx, ""); - duk_push_string(ctx, ""); - } else if (nargs == 1) { - /* XXX: cover this with the generic >1 case? */ - duk_push_string(ctx, ""); - } else { - duk_insert(ctx, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */ - duk_push_string(ctx, ","); - duk_insert(ctx, 1); - duk_join(ctx, nargs - 1); - } - - /* [ body formals ], formals is comma separated list that needs to be parsed */ - - DUK_ASSERT_TOP(ctx, 2); - - /* XXX: this placeholder is not always correct, but use for now. - * It will fail in corner cases; see test-dev-func-cons-args.js. - */ - duk_push_string(ctx, "function("); - duk_dup(ctx, 1); - duk_push_string(ctx, "){"); - duk_dup(ctx, 0); - duk_push_string(ctx, "}"); - duk_concat(ctx, 5); - - /* [ body formals source ] */ - - DUK_ASSERT_TOP(ctx, 3); - - /* strictness is not inherited, intentional */ - comp_flags = DUK_JS_COMPILE_FLAG_FUNCEXPR; - - duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */ - h_sourcecode = duk_require_hstring(ctx, -2); - duk_js_compile(thr, - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode), - (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode), - comp_flags); - func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1); - DUK_ASSERT(func != NULL); - DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) func)); - - /* [ body formals source template ] */ - - /* only outer_lex_env matters, as functions always get a new - * variable declaration environment. - */ - - outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV]; - outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV]; - - duk_js_push_closure(thr, func, outer_var_env, outer_lex_env); - - /* [ body formals source template closure ] */ - - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_context *ctx) { - /* ignore arguments, return undefined (E5 Section 15.3.4) */ - DUK_UNREF(ctx); - return 0; -} - -DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) { - duk_tval *tv; - - /* - * E5 Section 15.3.4.2 places few requirements on the output of - * this function: - * - * - The result is an implementation dependent representation - * of the function; in particular - * - * - The result must follow the syntax of a FunctionDeclaration. - * In particular, the function must have a name (even in the - * case of an anonymous function or a function with an empty - * name). - * - * - Note in particular that the output does NOT need to compile - * into anything useful. - */ - - - /* XXX: faster internal way to get this */ - duk_push_this(ctx); - tv = duk_get_tval(ctx, -1); - DUK_ASSERT(tv != NULL); - - if (DUK_TVAL_IS_OBJECT(tv)) { - duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv); - const char *func_name = DUK_STR_ANON; - - /* XXX: rework, it would be nice to avoid C formatting functions to - * ensure there are no Unicode issues. - */ - - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME); - if (!duk_is_undefined(ctx, -1)) { - func_name = duk_to_string(ctx, -1); - DUK_ASSERT(func_name != NULL); - - if (func_name[0] == (char) 0) { - func_name = DUK_STR_ANON; - } - } - - if (DUK_HOBJECT_HAS_COMPILEDFUNCTION(obj)) { - /* XXX: actual source, if available */ - duk_push_sprintf(ctx, "function %s() {/* ecmascript */}", (const char *) func_name); - } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) { - duk_push_sprintf(ctx, "function %s() {/* native */}", (const char *) func_name); - } else if (DUK_HOBJECT_HAS_BOUND(obj)) { - duk_push_sprintf(ctx, "function %s() {/* bound */}", (const char *) func_name); - } else { - goto type_error; - } - } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) { - duk_push_lightfunc_tostring(ctx, tv); - } else { - goto type_error; - } - - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} - -DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) { - duk_idx_t len; - duk_idx_t i; - - DUK_ASSERT_TOP(ctx, 2); /* not a vararg function */ - - duk_push_this(ctx); - if (!duk_is_callable(ctx, -1)) { - DUK_DDD(DUK_DDDPRINT("func is not callable")); - goto type_error; - } - duk_insert(ctx, 0); - DUK_ASSERT_TOP(ctx, 3); - - DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 1), - (duk_tval *) duk_get_tval(ctx, 2))); - - /* [ func thisArg argArray ] */ - - if (duk_is_null_or_undefined(ctx, 2)) { - DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args")); - len = 0; - } else if (!duk_is_object(ctx, 2)) { - goto type_error; - } else { - DUK_DDD(DUK_DDDPRINT("argArray is an object")); - - /* XXX: make this an internal helper */ - duk_get_prop_stridx(ctx, 2, DUK_STRIDX_LENGTH); - len = (duk_idx_t) duk_to_uint32(ctx, -1); /* ToUint32() coercion required */ - duk_pop(ctx); - - duk_require_stack(ctx, len); - - DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len)); - for (i = 0; i < len; i++) { - duk_get_prop_index(ctx, 2, i); - } - } - duk_remove(ctx, 2); - DUK_ASSERT_TOP(ctx, 2 + len); - - /* [ func thisArg arg1 ... argN ] */ - - DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 1), - (long) len)); - duk_call_method(ctx, len); - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} - -DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) { - duk_idx_t nargs; - - /* Step 1 is not necessary because duk_call_method() will take - * care of it. - */ - - /* vararg function, thisArg needs special handling */ - nargs = duk_get_top(ctx); /* = 1 + arg count */ - if (nargs == 0) { - duk_push_undefined(ctx); - nargs++; - } - DUK_ASSERT(nargs >= 1); - - /* [ thisArg arg1 ... argN ] */ - - duk_push_this(ctx); /* 'func' in the algorithm */ - duk_insert(ctx, 0); - - /* [ func thisArg arg1 ... argN ] */ - - DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 1), - (long) (nargs - 1), - (long) duk_get_top(ctx))); - duk_call_method(ctx, nargs - 1); - return 1; -} - -/* XXX: the implementation now assumes "chained" bound functions, - * whereas "collapsed" bound functions (where there is ever only - * one bound function which directly points to a non-bound, final - * function) would require a "collapsing" implementation which - * merges argument lists etc here. - */ -DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) { - duk_hobject *h_bound; - duk_hobject *h_target; - duk_idx_t nargs; - duk_idx_t i; - - /* vararg function, careful arg handling (e.g. thisArg may not be present) */ - nargs = duk_get_top(ctx); /* = 1 + arg count */ - if (nargs == 0) { - duk_push_undefined(ctx); - nargs++; - } - DUK_ASSERT(nargs >= 1); - - duk_push_this(ctx); - if (!duk_is_callable(ctx, -1)) { - DUK_DDD(DUK_DDDPRINT("func is not callable")); - goto type_error; - } - - /* [ thisArg arg1 ... argN func ] (thisArg+args == nargs total) */ - DUK_ASSERT_TOP(ctx, nargs + 1); - - /* create bound function object */ - duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_BOUND | - DUK_HOBJECT_FLAG_CONSTRUCTABLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION), - DUK_BIDX_FUNCTION_PROTOTYPE); - h_bound = duk_get_hobject(ctx, -1); - DUK_ASSERT(h_bound != NULL); - - /* [ thisArg arg1 ... argN func boundFunc ] */ - duk_dup(ctx, -2); /* func */ - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); - - duk_dup(ctx, 0); /* thisArg */ - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); - - duk_push_array(ctx); - - /* [ thisArg arg1 ... argN func boundFunc argArray ] */ - - for (i = 0; i < nargs - 1; i++) { - duk_dup(ctx, 1 + i); - duk_put_prop_index(ctx, -2, i); - } - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_ARGS, DUK_PROPDESC_FLAGS_NONE); - - /* [ thisArg arg1 ... argN func boundFunc ] */ - - /* bound function 'length' property is interesting */ - h_target = duk_get_hobject(ctx, -2); - if (h_target == NULL || /* lightfunc */ - DUK_HOBJECT_GET_CLASS_NUMBER(h_target) == DUK_HOBJECT_CLASS_FUNCTION) { - /* For lightfuncs, simply read the virtual property. */ - duk_int_t tmp; - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH); - tmp = duk_to_int(ctx, -1) - (nargs - 1); /* step 15.a */ - duk_pop(ctx); - duk_push_int(ctx, (tmp < 0 ? 0 : tmp)); - } else { - duk_push_int(ctx, 0); - } - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); /* attrs in E5 Section 15.3.5.1 */ - - /* caller and arguments must use the same thrower, [[ThrowTypeError]] */ - duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE); - duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE); - - /* these non-standard properties are copied for convenience */ - /* XXX: 'copy properties' API call? */ - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_WC); - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC); - - /* The 'strict' flag is copied to get the special [[Get]] of E5.1 - * Section 15.3.5.4 to apply when a 'caller' value is a strict bound - * function. Not sure if this is correct, because the specification - * is a bit ambiguous on this point but it would make sense. - */ - if (h_target == NULL) { - /* Lightfuncs are always strict. */ - DUK_HOBJECT_SET_STRICT(h_bound); - } else if (DUK_HOBJECT_HAS_STRICT(h_target)) { - DUK_HOBJECT_SET_STRICT(h_bound); - } - DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1))); - - return 1; - - type_error: - return DUK_RET_TYPE_ERROR; -} diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_global.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_global.c deleted file mode 100644 index bec82f88..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_global.c +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * Global object built-ins - */ - -#include "duk_internal.h" - -/* - * Encoding/decoding helpers - */ - -/* XXX: Could add fast path (for each transform callback) with direct byte - * lookups (no shifting) and no explicit check for x < 0x80 before table - * lookup. - */ - -/* Macros for creating and checking bitmasks for character encoding. - * Bit number is a bit counterintuitive, but minimizes code size. - */ -#define DUK__MKBITS(a,b,c,d,e,f,g,h) ((duk_uint8_t) ( \ - ((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \ - ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \ - )) -#define DUK__CHECK_BITMASK(table,cp) ((table)[(cp) >> 3] & (1 << ((cp) & 0x07))) - -/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */ -DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = { - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */ - DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */ - DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */ -}; - -/* E5.1 Section 15.1.3.4: uriUnescaped */ -DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = { - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */ - DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */ - DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */ - DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */ -}; - -/* E5.1 Section 15.1.3.1: uriReserved + '#' */ -DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = { - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */ - DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */ - DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */ -}; - -/* E5.1 Section 15.1.3.2: empty */ -DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = { - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */ -}; - -#ifdef DUK_USE_SECTION_B -/* E5.1 Section B.2.2, step 7. */ -DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = { - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */ - DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */ - DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */ - DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */ -}; -#endif /* DUK_USE_SECTION_B */ - -#undef DUK__MKBITS - -typedef struct { - duk_hthread *thr; - duk_hstring *h_str; - duk_bufwriter_ctx bw; - const duk_uint8_t *p; - const duk_uint8_t *p_start; - const duk_uint8_t *p_end; -} duk__transform_context; - -typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp); - -/* XXX: refactor and share with other code */ -DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) { - duk_small_int_t ch; - duk_small_int_t t = 0; - - while (n > 0) { - t = t * 16; - ch = (duk_small_int_t) duk_hex_dectab[*p++]; - if (DUK_LIKELY(ch >= 0)) { - t += ch; - } else { - return -1; - } - n--; - } - return t; -} - -DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, void *udata) { - duk_hthread *thr = (duk_hthread *) ctx; - duk__transform_context tfm_ctx_alloc; - duk__transform_context *tfm_ctx = &tfm_ctx_alloc; - duk_codepoint_t cp; - - tfm_ctx->thr = thr; - - tfm_ctx->h_str = duk_to_hstring(ctx, 0); - DUK_ASSERT(tfm_ctx->h_str != NULL); - - DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */ - - tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str); - tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str); - tfm_ctx->p = tfm_ctx->p_start; - - while (tfm_ctx->p < tfm_ctx->p_end) { - cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end); - callback(tfm_ctx, udata, cp); - } - - DUK_BW_COMPACT(thr, &tfm_ctx->bw); - - duk_to_string(ctx, -1); - return 1; -} - -DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) { - duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH]; - duk_small_int_t len; - duk_codepoint_t cp1, cp2; - duk_small_int_t i, t; - const duk_uint8_t *unescaped_table = (duk_uint8_t *) udata; - - /* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes. - * Codepoint range is restricted so this is a slightly too large - * but doesn't matter. - */ - DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH); - - if (cp < 0) { - goto uri_error; - } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) { - DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp); - return; - } else if (cp >= 0xdc00L && cp <= 0xdfffL) { - goto uri_error; - } else if (cp >= 0xd800L && cp <= 0xdbffL) { - /* Needs lookahead */ - if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) { - goto uri_error; - } - if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) { - goto uri_error; - } - cp1 = cp; - cp = ((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L; - } else if (cp > 0x10ffffL) { - /* Although we can allow non-BMP characters (they'll decode - * back into surrogate pairs), we don't allow extended UTF-8 - * characters; they would encode to URIs which won't decode - * back because of strict UTF-8 checks in URI decoding. - * (However, we could just as well allow them here.) - */ - goto uri_error; - } else { - /* Non-BMP characters within valid UTF-8 range: encode as is. - * They'll decode back into surrogate pairs if the escaped - * output is decoded. - */ - ; - } - - len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf); - for (i = 0; i < len; i++) { - t = (int) xutf8_buf[i]; - DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, - &tfm_ctx->bw, - DUK_ASC_PERCENT, - (duk_uint8_t) duk_uc_nybbles[t >> 4], - (duk_uint8_t) duk_uc_nybbles[t & 0x0f]); - } - - return; - - uri_error: - DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input"); -} - -DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) { - const duk_uint8_t *reserved_table = (duk_uint8_t *) udata; - duk_small_uint_t utf8_blen; - duk_codepoint_t min_cp; - duk_small_int_t t; /* must be signed */ - duk_small_uint_t i; - - /* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH, - * percent escape path writes max two times CESU-8 encoded BMP length. - */ - DUK_BW_ENSURE(tfm_ctx->thr, - &tfm_ctx->bw, - (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ? - DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH)); - - if (cp == (duk_codepoint_t) '%') { - const duk_uint8_t *p = tfm_ctx->p; - duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */ - - DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left)); - - if (left < 2) { - goto uri_error; - } - - t = duk__decode_hex_escape(p, 2); - DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t)); - if (t < 0) { - goto uri_error; - } - - if (t < 0x80) { - if (DUK__CHECK_BITMASK(reserved_table, t)) { - /* decode '%xx' to '%xx' if decoded char in reserved set */ - DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start); - DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, - &tfm_ctx->bw, - DUK_ASC_PERCENT, - p[0], - p[1]); - } else { - DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t); - } - tfm_ctx->p += 2; - return; - } - - /* Decode UTF-8 codepoint from a sequence of hex escapes. The - * first byte of the sequence has been decoded to 't'. - * - * Note that UTF-8 validation must be strict according to the - * specification: E5.1 Section 15.1.3, decode algorithm step - * 4.d.vii.8. URIError from non-shortest encodings is also - * specifically noted in the spec. - */ - - DUK_ASSERT(t >= 0x80); - if (t < 0xc0) { - /* continuation byte */ - goto uri_error; - } else if (t < 0xe0) { - /* 110x xxxx; 2 bytes */ - utf8_blen = 2; - min_cp = 0x80L; - cp = t & 0x1f; - } else if (t < 0xf0) { - /* 1110 xxxx; 3 bytes */ - utf8_blen = 3; - min_cp = 0x800L; - cp = t & 0x0f; - } else if (t < 0xf8) { - /* 1111 0xxx; 4 bytes */ - utf8_blen = 4; - min_cp = 0x10000L; - cp = t & 0x07; - } else { - /* extended utf-8 not allowed for URIs */ - goto uri_error; - } - - if (left < utf8_blen * 3 - 1) { - /* '%xx%xx...%xx', p points to char after first '%' */ - goto uri_error; - } - - p += 3; - for (i = 1; i < utf8_blen; i++) { - /* p points to digit part ('%xy', p points to 'x') */ - t = duk__decode_hex_escape(p, 2); - DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx", - (long) i, (long) utf8_blen, (long) cp, (unsigned long) t)); - if (t < 0) { - goto uri_error; - } - if ((t & 0xc0) != 0x80) { - goto uri_error; - } - cp = (cp << 6) + (t & 0x3f); - p += 3; - } - p--; /* p overshoots */ - tfm_ctx->p = p; - - DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp)); - - if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) { - goto uri_error; - } - - /* The E5.1 algorithm checks whether or not a decoded codepoint - * is below 0x80 and perhaps may be in the "reserved" set. - * This seems pointless because the single byte UTF-8 case is - * handled separately, and non-shortest encodings are rejected. - * So, 'cp' cannot be below 0x80 here, and thus cannot be in - * the reserved set. - */ - - /* utf-8 validation ensures these */ - DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL); - - if (cp >= 0x10000L) { - cp -= 0x10000L; - DUK_ASSERT(cp < 0x100000L); - - DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L)); - DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L)); - } else { - DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp); - } - } else { - DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp); - } - return; - - uri_error: - DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input"); -} - -#ifdef DUK_USE_SECTION_B -DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) { - DUK_UNREF(udata); - - DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6); - - if (cp < 0) { - goto esc_error; - } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) { - DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp); - } else if (cp < 0x100L) { - DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, - &tfm_ctx->bw, - (duk_uint8_t) DUK_ASC_PERCENT, - (duk_uint8_t) duk_uc_nybbles[cp >> 4], - (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]); - } else if (cp < 0x10000L) { - DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr, - &tfm_ctx->bw, - (duk_uint8_t) DUK_ASC_PERCENT, - (duk_uint8_t) DUK_ASC_LC_U, - (duk_uint8_t) duk_uc_nybbles[cp >> 12], - (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f], - (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f], - (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]); - } else { - /* Characters outside BMP cannot be escape()'d. We could - * encode them as surrogate pairs (for codepoints inside - * valid UTF-8 range, but not extended UTF-8). Because - * escape() and unescape() are legacy functions, we don't. - */ - goto esc_error; - } - - return; - - esc_error: - DUK_ERROR(tfm_ctx->thr, DUK_ERR_TYPE_ERROR, "invalid input"); -} - -DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) { - duk_small_int_t t; - - DUK_UNREF(udata); - - if (cp == (duk_codepoint_t) '%') { - const duk_uint8_t *p = tfm_ctx->p; - duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */ - - if (left >= 5 && p[0] == 'u' && - ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) { - cp = (duk_codepoint_t) t; - tfm_ctx->p += 5; - } else if (left >= 2 && - ((t = duk__decode_hex_escape(p, 2)) >= 0)) { - cp = (duk_codepoint_t) t; - tfm_ctx->p += 2; - } - } - - DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp); -} -#endif /* DUK_USE_SECTION_B */ - -/* - * Eval - * - * Eval needs to handle both a "direct eval" and an "indirect eval". - * Direct eval handling needs access to the caller's activation so that its - * lexical environment can be accessed. A direct eval is only possible from - * Ecmascript code; an indirect eval call is possible also from C code. - * When an indirect eval call is made from C code, there may not be a - * calling activation at all which needs careful handling. - */ - -DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_hstring *h; - duk_activation *act_caller; - duk_activation *act_eval; - duk_activation *act; - duk_hcompiledfunction *func; - duk_hobject *outer_lex_env; - duk_hobject *outer_var_env; - duk_bool_t this_to_global = 1; - duk_small_uint_t comp_flags; - - DUK_ASSERT_TOP(ctx, 1); - DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */ - DUK_ASSERT(((thr->callstack + thr->callstack_top - 1)->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */ - (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */ - - /* - * callstack_top - 1 --> this function - * callstack_top - 2 --> caller (may not exist) - * - * If called directly from C, callstack_top might be 1. If calling - * activation doesn't exist, call must be indirect. - */ - - h = duk_get_hstring(ctx, 0); - if (!h) { - return 1; /* return arg as-is */ - } - - /* [ source ] */ - - comp_flags = DUK_JS_COMPILE_FLAG_EVAL; - act_eval = thr->callstack + thr->callstack_top - 1; /* this function */ - if (thr->callstack_top >= 2) { - /* Have a calling activation, check for direct eval (otherwise - * assume indirect eval. - */ - act_caller = thr->callstack + thr->callstack_top - 2; /* caller */ - if ((act_caller->flags & DUK_ACT_FLAG_STRICT) && - (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) { - /* Only direct eval inherits strictness from calling code - * (E5.1 Section 10.1.1). - */ - comp_flags |= DUK_JS_COMPILE_FLAG_STRICT; - } - } else { - DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0); - } - act_caller = NULL; /* avoid dereference after potential callstack realloc */ - act_eval = NULL; - - duk_push_hstring_stridx(ctx, DUK_STRIDX_INPUT); /* XXX: copy from caller? */ - duk_js_compile(thr, - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), - (duk_size_t) DUK_HSTRING_GET_BYTELEN(h), - comp_flags); - func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1); - DUK_ASSERT(func != NULL); - DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) func)); - - /* [ source template ] */ - - /* E5 Section 10.4.2 */ - DUK_ASSERT(thr->callstack_top >= 1); - act = thr->callstack + thr->callstack_top - 1; /* this function */ - if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) { - DUK_ASSERT(thr->callstack_top >= 2); - act = thr->callstack + thr->callstack_top - 2; /* caller */ - if (act->lex_env == NULL) { - DUK_ASSERT(act->var_env == NULL); - DUK_DDD(DUK_DDDPRINT("delayed environment initialization")); - - /* this may have side effects, so re-lookup act */ - duk_js_init_activation_environment_records_delayed(thr, act); - act = thr->callstack + thr->callstack_top - 2; - } - DUK_ASSERT(act->lex_env != NULL); - DUK_ASSERT(act->var_env != NULL); - - this_to_global = 0; - - if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) { - duk_hobject *new_env; - duk_hobject *act_lex_env; - - DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> " - "var_env and lex_env to a fresh env, " - "this_binding to caller's this_binding")); - - act = thr->callstack + thr->callstack_top - 2; /* caller */ - act_lex_env = act->lex_env; - act = NULL; /* invalidated */ - - (void) duk_push_object_helper_proto(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV), - act_lex_env); - new_env = duk_require_hobject(ctx, -1); - DUK_ASSERT(new_env != NULL); - DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", - (duk_heaphdr *) new_env)); - - outer_lex_env = new_env; - outer_var_env = new_env; - - duk_insert(ctx, 0); /* stash to bottom of value stack to keep new_env reachable */ - - /* compiler's responsibility */ - DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func)); - } else { - DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> " - "var_env and lex_env to caller's envs, " - "this_binding to caller's this_binding")); - - outer_lex_env = act->lex_env; - outer_var_env = act->var_env; - - /* compiler's responsibility */ - DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func)); - } - } else { - DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to " - "global object, this_binding to global object")); - - this_to_global = 1; - outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV]; - outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV]; - } - act = NULL; - - duk_js_push_closure(thr, func, outer_var_env, outer_lex_env); - - /* [ source template closure ] */ - - if (this_to_global) { - DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); - duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL); - } else { - duk_tval *tv; - DUK_ASSERT(thr->callstack_top >= 2); - act = thr->callstack + thr->callstack_top - 2; /* caller */ - tv = thr->valstack + act->idx_bottom - 1; /* this is just beneath bottom */ - DUK_ASSERT(tv >= thr->valstack); - duk_push_tval(ctx, tv); - } - - DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T", - (duk_heaphdr *) outer_lex_env, - (duk_heaphdr *) outer_var_env, - (duk_tval *) duk_get_tval(ctx, -1))); - - /* [ source template closure this ] */ - - duk_call_method(ctx, 0); - - /* [ source template result ] */ - - return 1; -} - -/* - * Parsing of ints and floats - */ - -DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) { - duk_bool_t strip_prefix; - duk_int32_t radix; - duk_small_uint_t s2n_flags; - - DUK_ASSERT_TOP(ctx, 2); - duk_to_string(ctx, 0); - - strip_prefix = 1; - radix = duk_to_int32(ctx, 1); - if (radix != 0) { - if (radix < 2 || radix > 36) { - goto ret_nan; - } - /* For octal, setting strip_prefix=0 is not necessary, as zero - * is tolerated anyway: - * - * parseInt('123', 8) === parseInt('0123', 8) with or without strip_prefix - * parseInt('123', 16) === parseInt('0x123', 16) requires strip_prefix = 1 - */ - if (radix != 16) { - strip_prefix = 0; - } - } else { - radix = 10; - } - - s2n_flags = DUK_S2N_FLAG_TRIM_WHITE | - DUK_S2N_FLAG_ALLOW_GARBAGE | - DUK_S2N_FLAG_ALLOW_PLUS | - DUK_S2N_FLAG_ALLOW_MINUS | - DUK_S2N_FLAG_ALLOW_LEADING_ZERO | -#ifdef DUK_USE_OCTAL_SUPPORT - (strip_prefix ? (DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT | DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) : 0) -#else - (strip_prefix ? DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT : 0) -#endif - ; - - duk_dup(ctx, 0); - duk_numconv_parse(ctx, radix, s2n_flags); - return 1; - - ret_nan: - duk_push_nan(ctx); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx) { - duk_small_uint_t s2n_flags; - duk_int32_t radix; - - DUK_ASSERT_TOP(ctx, 1); - duk_to_string(ctx, 0); - - radix = 10; - - /* XXX: check flags */ - s2n_flags = DUK_S2N_FLAG_TRIM_WHITE | - DUK_S2N_FLAG_ALLOW_EXP | - DUK_S2N_FLAG_ALLOW_GARBAGE | - DUK_S2N_FLAG_ALLOW_PLUS | - DUK_S2N_FLAG_ALLOW_MINUS | - DUK_S2N_FLAG_ALLOW_INF | - DUK_S2N_FLAG_ALLOW_FRAC | - DUK_S2N_FLAG_ALLOW_NAKED_FRAC | - DUK_S2N_FLAG_ALLOW_EMPTY_FRAC | - DUK_S2N_FLAG_ALLOW_LEADING_ZERO; - - duk_numconv_parse(ctx, radix, s2n_flags); - return 1; -} - -/* - * Number checkers - */ - -DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx) { - duk_double_t d = duk_to_number(ctx, 0); - duk_push_boolean(ctx, DUK_ISNAN(d)); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) { - duk_double_t d = duk_to_number(ctx, 0); - duk_push_boolean(ctx, DUK_ISFINITE(d)); - return 1; -} - -/* - * URI handling - */ - -DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx) { - return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (void *) duk__decode_uri_reserved_table); -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx) { - return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (void *) duk__decode_uri_component_reserved_table); -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx) { - return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (void *) duk__encode_uriunescaped_table); -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx) { - return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (void *) duk__encode_uricomponent_unescaped_table); -} - -#ifdef DUK_USE_SECTION_B -DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) { - return duk__transform_helper(ctx, duk__transform_callback_escape, (void *) NULL); -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) { - return duk__transform_helper(ctx, duk__transform_callback_unescape, (void *) NULL); -} -#else /* DUK_USE_SECTION_B */ -DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} - -DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_SECTION_B */ - -#if defined(DUK_USE_BROWSER_LIKE) && (defined(DUK_USE_FILE_IO) || defined(DUK_USE_DEBUGGER_SUPPORT)) -DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_int_t magic; - duk_idx_t nargs; - const duk_uint8_t *buf; - duk_size_t sz_buf; - const char nl = (const char) DUK_ASC_LF; -#ifndef DUK_USE_PREFER_SIZE - duk_uint8_t buf_stack[256]; -#endif -#ifdef DUK_USE_FILE_IO - duk_file *f_out; -#endif - - magic = duk_get_current_magic(ctx); - DUK_UNREF(magic); - - nargs = duk_get_top(ctx); - - /* If argument count is 1 and first argument is a buffer, write the buffer - * as raw data into the file without a newline; this allows exact control - * over stdout/stderr without an additional entrypoint (useful for now). - * - * Otherwise current print/alert semantics are to ToString() coerce - * arguments, join them with a single space, and append a newline. - */ - - if (nargs == 1 && duk_is_buffer(ctx, 0)) { - buf = (const duk_uint8_t *) duk_get_buffer(ctx, 0, &sz_buf); - DUK_ASSERT(buf != NULL); - } else if (nargs > 0) { -#ifdef DUK_USE_PREFER_SIZE - /* Compact but lots of churn. */ - duk_push_hstring_stridx(thr, DUK_STRIDX_SPACE); - duk_insert(ctx, 0); - duk_join(ctx, nargs); - duk_push_string(thr, "\n"); - duk_concat(ctx, 2); - buf = (const duk_uint8_t *) duk_get_lstring(ctx, -1, &sz_buf); - DUK_ASSERT(buf != NULL); -#else /* DUK_USE_PREFER_SIZE */ - /* Higher footprint, less churn. */ - duk_idx_t i; - duk_size_t sz_str; - const duk_uint8_t *p_str; - duk_uint8_t *p; - - sz_buf = (duk_size_t) nargs; /* spaces (nargs - 1) + newline */ - for (i = 0; i < nargs; i++) { - (void) duk_to_lstring(ctx, i, &sz_str); - sz_buf += sz_str; - } - - if (sz_buf <= sizeof(buf_stack)) { - buf = (const duk_uint8_t *) buf_stack; - } else { - buf = (const duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf); - DUK_ASSERT(buf != NULL); - } - - p = (duk_uint8_t *) buf; - for (i = 0; i < nargs; i++) { - p_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &sz_str); - DUK_ASSERT(p_str != NULL); - DUK_MEMCPY((void *) p, (const void *) p_str, sz_str); - p += sz_str; - *p++ = (duk_uint8_t) (i == nargs - 1 ? DUK_ASC_LF : DUK_ASC_SPACE); - } - DUK_ASSERT((const duk_uint8_t *) p == buf + sz_total); -#endif /* DUK_USE_PREFER_SIZE */ - } else { - buf = (const duk_uint8_t *) &nl; - sz_buf = 1; - } - - /* 'buf' contains the string to write, 'sz_buf' contains the length - * (which may be zero). - */ - DUK_ASSERT(buf != NULL); - - if (sz_buf == 0) { - return 0; - } - -#ifdef DUK_USE_FILE_IO - f_out = (magic ? DUK_STDERR : DUK_STDOUT); - DUK_FWRITE((const void *) buf, 1, (size_t) sz_buf, f_out); - DUK_FFLUSH(f_out); -#endif - -#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_PRINTALERT) - if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) { - duk_debug_write_notify(thr, magic ? DUK_DBG_CMD_ALERT : DUK_DBG_CMD_PRINT); - duk_debug_write_string(thr, (const char *) buf, sz_buf); - duk_debug_write_eom(thr); - } -#endif - return 0; -} -#elif defined(DUK_USE_BROWSER_LIKE) /* print provider */ -DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) { - DUK_UNREF(ctx); - return 0; -} -#else /* print provider */ -DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* print provider */ - -/* - * CommonJS require() and modules support - */ - -#if defined(DUK_USE_COMMONJS_MODULES) -DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_size_t mod_id_len; - duk_size_t req_id_len; - duk_uint8_t buf_in[DUK_BI_COMMONJS_MODULE_ID_LIMIT]; - duk_uint8_t buf_out[DUK_BI_COMMONJS_MODULE_ID_LIMIT]; - duk_uint8_t *p; - duk_uint8_t *q; - - DUK_ASSERT(req_id != NULL); - /* mod_id may be NULL */ - DUK_ASSERT(sizeof(buf_out) >= sizeof(buf_in)); /* bound checking requires this */ - - /* - * A few notes on the algorithm: - * - * - Terms are not allowed to begin with a period unless the term - * is either '.' or '..'. This simplifies implementation (and - * is within CommonJS modules specification). - * - * - There are few output bound checks here. This is on purpose: - * we check the input length and rely on the output never being - * longer than the input, so we cannot run out of output space. - * - * - Non-ASCII characters are processed as individual bytes and - * need no special treatment. However, U+0000 terminates the - * algorithm; this is not an issue because U+0000 is not a - * desirable term character anyway. - */ - - /* - * Set up the resolution input which is the requested ID directly - * (if absolute or no current module path) or with current module - * ID prepended (if relative and current module path exists). - * - * Suppose current module is 'foo/bar' and relative path is './quux'. - * The 'bar' component must be replaced so the initial input here is - * 'foo/bar/.././quux'. - */ - - req_id_len = DUK_STRLEN(req_id); - if (mod_id != NULL && req_id[0] == '.') { - mod_id_len = DUK_STRLEN(mod_id); - if (mod_id_len + 4 + req_id_len + 1 >= sizeof(buf_in)) { - DUK_DD(DUK_DDPRINT("resolve error: current and requested module ID don't fit into resolve input buffer")); - goto resolve_error; - } - (void) DUK_SNPRINTF((char *) buf_in, sizeof(buf_in), "%s/../%s", (const char *) mod_id, (const char *) req_id); - } else { - if (req_id_len + 1 >= sizeof(buf_in)) { - DUK_DD(DUK_DDPRINT("resolve error: requested module ID doesn't fit into resolve input buffer")); - goto resolve_error; - } - (void) DUK_SNPRINTF((char *) buf_in, sizeof(buf_in), "%s", (const char *) req_id); - } - buf_in[sizeof(buf_in) - 1] = (duk_uint8_t) 0; - - DUK_DDD(DUK_DDDPRINT("input module id: '%s'", (const char *) buf_in)); - - /* - * Resolution loop. At the top of the loop we're expecting a valid - * term: '.', '..', or a non-empty identifier not starting with a period. - */ - - p = buf_in; - q = buf_out; - for (;;) { - duk_uint_fast8_t c; - - /* Here 'p' always points to the start of a term. */ - DUK_DDD(DUK_DDDPRINT("resolve loop top: p -> '%s', q=%p, buf_out=%p", - (const char *) p, (void *) q, (void *) buf_out)); - - c = *p++; - if (DUK_UNLIKELY(c == 0)) { - DUK_DD(DUK_DDPRINT("resolve error: requested ID must end with a non-empty term")); - goto resolve_error; - } else if (DUK_UNLIKELY(c == '.')) { - c = *p++; - if (c == '/') { - /* Term was '.' and is eaten entirely (including dup slashes). */ - goto eat_dup_slashes; - } - if (c == '.' && *p == '/') { - /* Term was '..', backtrack resolved name by one component. - * q[-1] = previous slash (or beyond start of buffer) - * q[-2] = last char of previous component (or beyond start of buffer) - */ - p++; /* eat (first) input slash */ - DUK_ASSERT(q >= buf_out); - if (q == buf_out) { - DUK_DD(DUK_DDPRINT("resolve error: term was '..' but nothing to backtrack")); - goto resolve_error; - } - DUK_ASSERT(*(q - 1) == '/'); - q--; /* backtrack to last output slash */ - for (;;) { - /* Backtrack to previous slash or start of buffer. */ - DUK_ASSERT(q >= buf_out); - if (q == buf_out) { - break; - } - if (*(q - 1) == '/') { - break; - } - q--; - } - goto eat_dup_slashes; - } - DUK_DD(DUK_DDPRINT("resolve error: term begins with '.' but is not '.' or '..' (not allowed now)")); - goto resolve_error; - } else if (DUK_UNLIKELY(c == '/')) { - /* e.g. require('/foo'), empty terms not allowed */ - DUK_DD(DUK_DDPRINT("resolve error: empty term (not allowed now)")); - goto resolve_error; - } else { - for (;;) { - /* Copy term name until end or '/'. */ - *q++ = c; - c = *p++; - if (DUK_UNLIKELY(c == 0)) { - goto loop_done; - } else if (DUK_UNLIKELY(c == '/')) { - *q++ = '/'; - break; - } else { - /* write on next loop */ - } - } - } - - eat_dup_slashes: - for (;;) { - /* eat dup slashes */ - c = *p; - if (DUK_LIKELY(c != '/')) { - break; - } - p++; - } - } - loop_done: - - duk_push_lstring(ctx, (const char *) buf_out, (size_t) (q - buf_out)); - return; - - resolve_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot resolve module id: %s", (const char *) req_id); -} -#endif /* DUK_USE_COMMONJS_MODULES */ - -#if defined(DUK_USE_COMMONJS_MODULES) -DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { - const char *str_req_id; /* requested identifier */ - const char *str_mod_id; /* require.id of current module */ - duk_int_t pcall_rc; - - /* NOTE: we try to minimize code size by avoiding unnecessary pops, - * so the stack looks a bit cluttered in this function. DUK_ASSERT_TOP() - * assertions are used to ensure stack configuration is correct at each - * step. - */ - - /* - * Resolve module identifier into canonical absolute form. - */ - - str_req_id = duk_require_string(ctx, 0); - duk_push_current_function(ctx); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_ID); - str_mod_id = duk_get_string(ctx, 2); /* ignore non-strings */ - DUK_DDD(DUK_DDDPRINT("resolve module id: requested=%!T, currentmodule=%!T", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 2))); - duk__bi_global_resolve_module_id(ctx, str_req_id, str_mod_id); - str_req_id = NULL; - str_mod_id = NULL; - DUK_DDD(DUK_DDDPRINT("resolved module id: requested=%!T, currentmodule=%!T, result=%!T", - (duk_tval *) duk_get_tval(ctx, 0), - (duk_tval *) duk_get_tval(ctx, 2), - (duk_tval *) duk_get_tval(ctx, 3))); - - /* [ requested_id require require.id resolved_id ] */ - DUK_ASSERT_TOP(ctx, 4); - - /* - * Cached module check. - * - * If module has been loaded or its loading has already begun without - * finishing, return the same cached value ('exports'). The value is - * registered when module load starts so that circular references can - * be supported to some extent. - */ - - /* [ requested_id require require.id resolved_id ] */ - DUK_ASSERT_TOP(ctx, 4); - - duk_push_hobject_bidx(ctx, DUK_BIDX_DUKTAPE); - duk_get_prop_stridx(ctx, 4, DUK_STRIDX_MOD_LOADED); /* Duktape.modLoaded */ - (void) duk_require_hobject(ctx, 5); - - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded ] */ - DUK_ASSERT_TOP(ctx, 6); - - duk_dup(ctx, 3); - if (duk_get_prop(ctx, 5)) { - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */ - DUK_DD(DUK_DDPRINT("module already loaded: %!T", - (duk_tval *) duk_get_tval(ctx, 3))); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_EXPORTS); /* return module.exports */ - return 1; - } - - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined ] */ - DUK_ASSERT_TOP(ctx, 7); - - /* - * Module not loaded (and loading not started previously). - * - * Create a new require() function with 'id' set to resolved ID - * of module being loaded. Also create 'exports' and 'module' - * tables but don't register exports to the loaded table yet. - * We don't want to do that unless the user module search callbacks - * succeeds in finding the module. - */ - - DUK_DD(DUK_DDPRINT("module not yet loaded: %!T", - (duk_tval *) duk_get_tval(ctx, 3))); - - /* Fresh require: require.id is left configurable (but not writable) - * so that is not easy to accidentally tweak it, but it can still be - * done with Object.defineProperty(). - * - * XXX: require.id could also be just made non-configurable, as there - * is no practical reason to touch it. - */ - duk_push_c_function(ctx, duk_bi_global_object_require, 1 /*nargs*/); - duk_dup(ctx, 3); - duk_xdef_prop_stridx(ctx, 7, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_C); /* a fresh require() with require.id = resolved target module id */ - - /* Module table: - * - module.exports: initial exports table (may be replaced by user) - * - module.id is non-writable and non-configurable, as the CommonJS - * spec suggests this if possible. - */ - duk_push_object(ctx); /* exports */ - duk_push_object(ctx); /* module */ - duk_dup(ctx, -2); - duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS, DUK_PROPDESC_FLAGS_WC); /* module.exports = exports */ - duk_dup(ctx, 3); /* resolved id: require(id) must return this same module */ - duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE); /* module.id = resolved_id */ - duk_compact(ctx, 9); /* module table remains registered to modLoaded, minimize its size */ - - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module ] */ - DUK_ASSERT_TOP(ctx, 10); - - /* Register the module table early to modLoaded[] so that we can - * support circular references even in modSearch(). If an error - * is thrown, we'll delete the reference. - */ - duk_dup(ctx, 3); - duk_dup(ctx, 9); - duk_put_prop(ctx, 5); /* Duktape.modLoaded[resolved_id] = module */ - - /* - * Call user provided module search function and build the wrapped - * module source code (if necessary). The module search function - * can be used to implement pure Ecmacsript, pure C, and mixed - * Ecmascript/C modules. - * - * The module search function can operate on the exports table directly - * (e.g. DLL code can register values to it). It can also return a - * string which is interpreted as module source code (if a non-string - * is returned the module is assumed to be a pure C one). If a module - * cannot be found, an error must be thrown by the user callback. - * - * Because Duktape.modLoaded[] already contains the module being - * loaded, circular references for C modules should also work - * (although expected to be quite rare). - */ - - duk_push_string(ctx, "(function(require,exports,module){"); - - /* Duktape.modSearch(resolved_id, fresh_require, exports, module). */ - duk_get_prop_stridx(ctx, 4, DUK_STRIDX_MOD_SEARCH); /* Duktape.modSearch */ - duk_dup(ctx, 3); - duk_dup(ctx, 7); - duk_dup(ctx, 8); - duk_dup(ctx, 9); /* [ ... Duktape.modSearch resolved_id fresh_require exports module ] */ - pcall_rc = duk_pcall(ctx, 4 /*nargs*/); /* -> [ ... source ] */ - DUK_ASSERT_TOP(ctx, 12); - - if (pcall_rc != DUK_EXEC_SUCCESS) { - /* Delete entry in Duktape.modLoaded[] and rethrow. */ - goto delete_rethrow; - } - - /* If user callback did not return source code, module loading - * is finished (user callback initialized exports table directly). - */ - if (!duk_is_string(ctx, 11)) { - /* User callback did not return source code, so module loading - * is finished: just update modLoaded with final module.exports - * and we're done. - */ - goto return_exports; - } - - /* Finish the wrapped module source. Force resolved module ID as the - * fileName so it gets set for functions defined within a module. This - * also ensures loggers created within the module get the module ID as - * their default logger name. - */ - duk_push_string(ctx, "})"); - duk_concat(ctx, 3); - duk_dup(ctx, 3); /* resolved module ID for fileName */ - duk_eval_raw(ctx, NULL, 0, DUK_COMPILE_EVAL); - - /* XXX: The module wrapper function is currently anonymous and is shown - * in stack traces. It would be nice to force it to match the module - * name (perhaps just the cleaned up last term). At the moment 'name' - * is write protected so we can't change it directly. Note that we must - * not introduce an actual name binding into the function scope (which - * is usually the case with a named function) because it would affect - * the scope seen by the module and shadow accesses to globals of the - * same name. - */ - - /* - * Call the wrapped module function. - * - * Use a protected call so that we can update Duktape.modLoaded[resolved_id] - * even if the module throws an error. - */ - - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */ - DUK_ASSERT_TOP(ctx, 11); - - duk_dup(ctx, 8); /* exports (this binding) */ - duk_dup(ctx, 7); /* fresh require (argument) */ - duk_get_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS); /* relookup exports from module.exports in case it was changed by modSearch */ - duk_dup(ctx, 9); /* module (argument) */ - - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */ - DUK_ASSERT_TOP(ctx, 15); - - pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/); - if (pcall_rc != DUK_EXEC_SUCCESS) { - /* Module loading failed. Node.js will forget the module - * registration so that another require() will try to load - * the module again. Mimic that behavior. - */ - goto delete_rethrow; - } - - /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */ - DUK_ASSERT_TOP(ctx, 11); - - /* fall through */ - - return_exports: - duk_get_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS); - return 1; /* return module.exports */ - - delete_rethrow: - duk_dup(ctx, 3); - duk_del_prop(ctx, 5); /* delete Duktape.modLoaded[resolved_id] */ - duk_throw(ctx); /* rethrow original error */ - return 0; /* not reachable */ -} -#else -DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { - DUK_UNREF(ctx); - return DUK_RET_UNSUPPORTED_ERROR; -} -#endif /* DUK_USE_COMMONJS_MODULES */ diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_json.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_json.c deleted file mode 100644 index f93e457b..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_json.c +++ /dev/null @@ -1,2896 +0,0 @@ -/* - * JSON built-ins. - * - * See doc/json.rst. - * - * Codepoints are handled as duk_uint_fast32_t to ensure that the full - * unsigned 32-bit range is supported. This matters to e.g. JX. - * - * Input parsing doesn't do an explicit end-of-input check at all. This is - * safe: input string data is always NUL-terminated (0x00) and valid JSON - * inputs never contain plain NUL characters, so that as long as syntax checks - * are correct, we'll never read past the NUL. This approach reduces code size - * and improves parsing performance, but it's critical that syntax checks are - * indeed correct! - */ - -#include "duk_internal.h" - -/* - * Local defines and forward declarations. - */ - -#define DUK__JSON_DECSTR_BUFSIZE 128 -#define DUK__JSON_DECSTR_CHUNKSIZE 64 -#define DUK__JSON_ENCSTR_CHUNKSIZE 64 -#define DUK__JSON_STRINGIFY_BUFSIZE 128 -#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */ - -DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n); -DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx); -DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx); -#ifdef DUK_USE_JX -DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx); -#endif -DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx); - -DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch); -DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2); -#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) -DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx); -#endif -DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h); -#if defined(DUK_USE_FASTINT) -DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p); -#endif -DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx); -DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q); -DUK_LOCAL_DECL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key); -DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str); -DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top); -DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top); -DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx); -DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx); -DUK_LOCAL_DECL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder); -DUK_LOCAL_DECL void duk__enc_value2(duk_json_enc_ctx *js_ctx); -DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv); -DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx); -#if defined(DUK_USE_FASTINT) -DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv); -#endif - -/* - * Helper tables - */ - -#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH) -DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = { - /* 0x00 ... 0x7f: as is - * 0x80: escape generically - * 0x81: slow path - * 0xa0 ... 0xff: backslash + one char - */ - - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81 -}; -#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ -DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = { - DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, - DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, - DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL, - DUK_ASC_LC_F, DUK_ASC_LC_R -}; -#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ - -#if defined(DUK_USE_JSON_DECSTRING_FASTPATH) -DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = { - /* 0x00: slow path - * other: as is - */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; -#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */ - -#if defined(DUK_USE_JSON_EATWHITE_FASTPATH) -DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = { - /* 0x00: finish (non-white) - * 0x01: continue - */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */ - -#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH) -DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = { - /* 0x00: finish (not part of number) - * 0x01: continue - */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */ - -/* - * Parsing implementation. - * - * JSON lexer is now separate from duk_lexer.c because there are numerous - * small differences making it difficult to share the lexer. - * - * The parser here works with raw bytes directly; this works because all - * JSON delimiters are ASCII characters. Invalid xUTF-8 encoded values - * inside strings will be passed on without normalization; this is not a - * compliance concern because compliant inputs will always be valid - * CESU-8 encodings. - */ - -DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) { - /* Shared handler to minimize parser size. Cause will be - * hidden, unfortunately, but we'll have an offset which - * is often quite enough. - */ - DUK_ERROR(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON, - (long) (js_ctx->p - js_ctx->p_start)); -} - -DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) { - const duk_uint8_t *p; - duk_uint8_t t; - - p = js_ctx->p; - for (;;) { - DUK_ASSERT(p <= js_ctx->p_end); - t = *p; - -#if defined(DUK_USE_JSON_EATWHITE_FASTPATH) - /* This fast path is pretty marginal in practice. - * XXX: candidate for removal. - */ - DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */ - if (duk__json_eatwhite_lookup[t] == 0) { - break; - } -#else /* DUK_USE_JSON_EATWHITE_FASTPATH */ - if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) { - /* NUL also comes here. Comparison order matters, 0x20 - * is most common whitespace. - */ - break; - } -#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */ - p++; - } - js_ctx->p = p; -} - -DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) { - DUK_ASSERT(js_ctx->p <= js_ctx->p_end); - return *js_ctx->p; -} - -DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) { - DUK_ASSERT(js_ctx->p <= js_ctx->p_end); - return *js_ctx->p++; -} - -DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) { - duk__dec_eat_white(js_ctx); - return duk__dec_get(js_ctx); -} - -/* For JX, expressing the whole unsigned 32-bit range matters. */ -DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) { - duk_small_uint_t i; - duk_uint_fast32_t res = 0; - duk_uint8_t x; - duk_small_int_t t; - - for (i = 0; i < n; i++) { - /* XXX: share helper from lexer; duk_lexer.c / hexval(). */ - - x = duk__dec_get(js_ctx); - DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld", - (long) i, (long) n, (long) res, (long) x)); - - /* x == 0x00 (EOF) causes syntax_error */ - DUK_ASSERT(duk_hex_dectab[0] == -1); - t = duk_hex_dectab[x & 0xff]; - if (DUK_LIKELY(t >= 0)) { - res = (res * 16) + t; - } else { - /* catches EOF and invalid digits */ - goto syntax_error; - } - } - - DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res)); - return res; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); - return 0; -} - -DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) { - duk_hstring *h; - duk_uint8_t *p; - duk_uint8_t x, y; - - /* First character has already been eaten and checked by the caller. - * We can scan until a NUL in stridx string because no built-in strings - * have internal NULs. - */ - - DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */ - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx); - DUK_ASSERT(h != NULL); - - p = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1; - DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */ - - for (;;) { - x = *p; - if (x == 0) { - break; - } - y = duk__dec_get(js_ctx); - if (x != y) { - /* Catches EOF of JSON input. */ - goto syntax_error; - } - p++; - } - - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} - -DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) { - duk_uint_fast32_t cp; - - /* EOF (-1) will be cast to an unsigned value first - * and then re-cast for the switch. In any case, it - * will match the default case (syntax error). - */ - cp = (duk_uint_fast32_t) duk__dec_get(js_ctx); - switch ((int) cp) { - case DUK_ASC_BACKSLASH: break; - case DUK_ASC_DOUBLEQUOTE: break; - case DUK_ASC_SLASH: break; - case DUK_ASC_LC_T: cp = 0x09; break; - case DUK_ASC_LC_N: cp = 0x0a; break; - case DUK_ASC_LC_R: cp = 0x0d; break; - case DUK_ASC_LC_F: cp = 0x0c; break; - case DUK_ASC_LC_B: cp = 0x08; break; - case DUK_ASC_LC_U: { - cp = duk__dec_decode_hex_escape(js_ctx, 4); - break; - } -#ifdef DUK_USE_JX - case DUK_ASC_UC_U: { - if (js_ctx->flag_ext_custom) { - cp = duk__dec_decode_hex_escape(js_ctx, 8); - } else { - return 1; /* syntax error */ - } - break; - } - case DUK_ASC_LC_X: { - if (js_ctx->flag_ext_custom) { - cp = duk__dec_decode_hex_escape(js_ctx, 2); - } else { - return 1; /* syntax error */ - } - break; - } -#endif /* DUK_USE_JX */ - default: - /* catches EOF (0x00) */ - return 1; /* syntax error */ - } - - DUK_RAW_WRITE_XUTF8(*ext_p, cp); - - return 0; -} - -DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { - duk_hthread *thr = js_ctx->thr; - duk_context *ctx = (duk_context *) thr; - duk_bufwriter_ctx bw_alloc; - duk_bufwriter_ctx *bw; - duk_uint8_t *q; - - /* '"' was eaten by caller */ - - /* Note that we currently parse -bytes-, not codepoints. - * All non-ASCII extended UTF-8 will encode to bytes >= 0x80, - * so they'll simply pass through (valid UTF-8 or not). - */ - - bw = &bw_alloc; - DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE); - q = DUK_BW_GET_PTR(js_ctx->thr, bw); - -#if defined(DUK_USE_JSON_DECSTRING_FASTPATH) - for (;;) { - duk_small_uint_t safe; - duk_uint8_t b, x; - const duk_uint8_t *p; - - /* Select a safe loop count where no output checks are - * needed assuming we won't encounter escapes. Input - * bound checks are not necessary as a NUL (guaranteed) - * will cause a SyntaxError before we read out of bounds. - */ - - safe = DUK__JSON_DECSTR_CHUNKSIZE; - - /* Ensure space for 1:1 output plus one escape. */ - q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q); - - p = js_ctx->p; /* temp copy, write back for next loop */ - for (;;) { - if (safe == 0) { - js_ctx->p = p; - break; - } - safe--; - - /* End of input (NUL) goes through slow path and causes SyntaxError. */ - DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00); - - b = *p++; - x = (duk_small_int_t) duk__json_decstr_lookup[b]; - if (DUK_LIKELY(x != 0)) { - /* Fast path, decode as is. */ - *q++ = b; - } else if (b == DUK_ASC_DOUBLEQUOTE) { - js_ctx->p = p; - goto found_quote; - } else if (b == DUK_ASC_BACKSLASH) { - /* We've ensured space for one escaped input; then - * bail out and recheck (this makes escape handling - * quite slow but it's uncommon). - */ - js_ctx->p = p; - if (duk__dec_string_escape(js_ctx, &q) != 0) { - goto syntax_error; - } - break; - } else { - js_ctx->p = p; - goto syntax_error; - } - } - } - found_quote: -#else /* DUK_USE_JSON_DECSTRING_FASTPATH */ - for (;;) { - duk_uint8_t x; - - q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q); - - x = duk__dec_get(js_ctx); - - if (x == DUK_ASC_DOUBLEQUOTE) { - break; - } else if (x == DUK_ASC_BACKSLASH) { - if (duk__dec_string_escape(js_ctx, &q) != 0) { - goto syntax_error; - } - } else if (x < 0x20) { - /* catches EOF (NUL) */ - goto syntax_error; - } else { - *q++ = (duk_uint8_t) x; - } - } -#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */ - - DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q); - duk_to_string(ctx, -1); - - /* [ ... str ] */ - - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} - -#ifdef DUK_USE_JX -/* Decode a plain string consisting entirely of identifier characters. - * Used to parse plain keys (e.g. "foo: 123"). - */ -DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) { - duk_hthread *thr = js_ctx->thr; - duk_context *ctx = (duk_context *) thr; - const duk_uint8_t *p; - duk_small_int_t x; - - /* Caller has already eaten the first char so backtrack one byte. */ - - js_ctx->p--; /* safe */ - p = js_ctx->p; - - /* Here again we parse bytes, and non-ASCII UTF-8 will cause end of - * parsing (which is correct except if there are non-shortest encodings). - * There is also no need to check explicitly for end of input buffer as - * the input is NUL padded and NUL will exit the parsing loop. - * - * Because no unescaping takes place, we can just scan to the end of the - * plain string and intern from the input buffer. - */ - - for (;;) { - x = *p; - - /* There is no need to check the first character specially here - * (i.e. reject digits): the caller only accepts valid initial - * characters and won't call us if the first character is a digit. - * This also ensures that the plain string won't be empty. - */ - - if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) { - break; - } - p++; - } - - duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p)); - js_ctx->p = p; - - /* [ ... str ] */ -} -#endif /* DUK_USE_JX */ - -#ifdef DUK_USE_JX -DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { - duk_hthread *thr = js_ctx->thr; - duk_context *ctx = (duk_context *) thr; - const duk_uint8_t *p; - duk_small_int_t x; - void *voidptr; - - /* Caller has already eaten the first character ('(') which we don't need. */ - - p = js_ctx->p; - - for (;;) { - x = *p; - - /* Assume that the native representation never contains a closing - * parenthesis. - */ - - if (x == DUK_ASC_RPAREN) { - break; - } else if (x <= 0) { - /* NUL term or -1 (EOF), NUL check would suffice */ - goto syntax_error; - } - p++; - } - - /* There is no need to NUL delimit the sscanf() call: trailing garbage is - * ignored and there is always a NUL terminator which will force an error - * if no error is encountered before it. It's possible that the scan - * would scan further than between [js_ctx->p,p[ though and we'd advance - * by less than the scanned value. - * - * Because pointers are platform specific, a failure to scan a pointer - * results in a null pointer which is a better placeholder than a missing - * value or an error. - */ - - voidptr = NULL; - (void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr); - duk_push_pointer(ctx, voidptr); - js_ctx->p = p + 1; /* skip ')' */ - - /* [ ... ptr ] */ - - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} -#endif /* DUK_USE_JX */ - -#ifdef DUK_USE_JX -DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) { - duk_hthread *thr = js_ctx->thr; - duk_context *ctx = (duk_context *) thr; - const duk_uint8_t *p; - duk_small_int_t x; - - /* Caller has already eaten the first character ('|') which we don't need. */ - - p = js_ctx->p; - - for (;;) { - x = *p; - - /* This loop intentionally does not ensure characters are valid - * ([0-9a-fA-F]) because the hex decode call below will do that. - */ - if (x == DUK_ASC_PIPE) { - break; - } else if (x <= 0) { - /* NUL term or -1 (EOF), NUL check would suffice */ - goto syntax_error; - } - p++; - } - - duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p)); - duk_hex_decode(ctx, -1); - js_ctx->p = p + 1; /* skip '|' */ - - /* [ ... buf ] */ - - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} -#endif /* DUK_USE_JX */ - -/* Parse a number, other than NaN or +/- Infinity */ -DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - const duk_uint8_t *p_start; - const duk_uint8_t *p; - duk_uint8_t x; - duk_small_uint_t s2n_flags; - - DUK_DDD(DUK_DDDPRINT("parse_number")); - - p_start = js_ctx->p; - - /* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a - * string for strict number parsing. - */ - - p = js_ctx->p; - for (;;) { - x = *p; - - DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld", - (void *) p_start, (void *) p, - (void *) js_ctx->p_end, (long) x)); - -#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH) - /* This fast path is pretty marginal in practice. - * XXX: candidate for removal. - */ - DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */ - if (duk__json_decnumber_lookup[x] == 0) { - break; - } -#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */ - if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) || - (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E || - x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) { - /* Plus sign must be accepted for positive exponents - * (e.g. '1.5e+2'). This clause catches NULs. - */ - break; - } -#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */ - p++; /* safe, because matched (NUL causes a break) */ - } - js_ctx->p = p; - - DUK_ASSERT(js_ctx->p > p_start); - duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start)); - - s2n_flags = DUK_S2N_FLAG_ALLOW_EXP | - DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */ - DUK_S2N_FLAG_ALLOW_FRAC; - - DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T", - (duk_tval *) duk_get_tval(ctx, -1))); - duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags); - if (duk_is_nan(ctx, -1)) { - duk__dec_syntax_error(js_ctx); - } - DUK_ASSERT(duk_is_number(ctx, -1)); - DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T", - (duk_tval *) duk_get_tval(ctx, -1))); - - /* [ ... num ] */ -} - -DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_require_stack(ctx, DUK_JSON_DEC_REQSTACK); - - /* c recursion check */ - - DUK_ASSERT(js_ctx->recursion_depth >= 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_RANGE_ERROR, DUK_STR_JSONDEC_RECLIMIT); - } - js_ctx->recursion_depth++; -} - -DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) { - /* c recursion check */ - - DUK_ASSERT(js_ctx->recursion_depth > 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - js_ctx->recursion_depth--; -} - -DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_int_t key_count; /* XXX: a "first" flag would suffice */ - duk_uint8_t x; - - DUK_DDD(DUK_DDDPRINT("parse_object")); - - duk__dec_objarr_entry(js_ctx); - - duk_push_object(ctx); - - /* Initial '{' has been checked and eaten by caller. */ - - key_count = 0; - for (;;) { - x = duk__dec_get_nonwhite(js_ctx); - - DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld", - (duk_tval *) duk_get_tval(ctx, -1), - (long) x, (long) key_count)); - - /* handle comma and closing brace */ - - if (x == DUK_ASC_COMMA && key_count > 0) { - /* accept comma, expect new value */ - x = duk__dec_get_nonwhite(js_ctx); - } else if (x == DUK_ASC_RCURLY) { - /* eat closing brace */ - break; - } else if (key_count == 0) { - /* accept anything, expect first value (EOF will be - * caught by key parsing below. - */ - ; - } else { - /* catches EOF (NUL) and initial comma */ - goto syntax_error; - } - - /* parse key and value */ - - if (x == DUK_ASC_DOUBLEQUOTE) { - duk__dec_string(js_ctx); -#ifdef DUK_USE_JX - } else if (js_ctx->flag_ext_custom && - duk_unicode_is_identifier_start((duk_codepoint_t) x)) { - duk__dec_plain_string(js_ctx); -#endif - } else { - goto syntax_error; - } - - /* [ ... obj key ] */ - - x = duk__dec_get_nonwhite(js_ctx); - if (x != DUK_ASC_COLON) { - goto syntax_error; - } - - duk__dec_value(js_ctx); - - /* [ ... obj key val ] */ - - duk_xdef_prop_wec(ctx, -3); - - /* [ ... obj ] */ - - key_count++; - } - - /* [ ... obj ] */ - - DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T", - (duk_tval *) duk_get_tval(ctx, -1))); - - duk__dec_objarr_exit(js_ctx); - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} - -DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_uarridx_t arr_idx; - duk_uint8_t x; - - DUK_DDD(DUK_DDDPRINT("parse_array")); - - duk__dec_objarr_entry(js_ctx); - - duk_push_array(ctx); - - /* Initial '[' has been checked and eaten by caller. */ - - arr_idx = 0; - for (;;) { - x = duk__dec_get_nonwhite(js_ctx); - - DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld", - (duk_tval *) duk_get_tval(ctx, -1), - (long) x, (long) arr_idx)); - - /* handle comma and closing bracket */ - - if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) { - /* accept comma, expect new value */ - ; - } else if (x == DUK_ASC_RBRACKET) { - /* eat closing bracket */ - break; - } else if (arr_idx == 0) { - /* accept anything, expect first value (EOF will be - * caught by duk__dec_value() below. - */ - js_ctx->p--; /* backtrack (safe) */ - } else { - /* catches EOF (NUL) and initial comma */ - goto syntax_error; - } - - /* parse value */ - - duk__dec_value(js_ctx); - - /* [ ... arr val ] */ - - duk_xdef_prop_index_wec(ctx, -2, arr_idx); - arr_idx++; - } - - /* Must set 'length' explicitly when using duk_xdef_prop_xxx() to - * set the values. - */ - - duk_set_length(ctx, -1, arr_idx); - - /* [ ... arr ] */ - - DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T", - (duk_tval *) duk_get_tval(ctx, -1))); - - duk__dec_objarr_exit(js_ctx); - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} - -DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_uint8_t x; - - x = duk__dec_get_nonwhite(js_ctx); - - DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x)); - - /* Note: duk__dec_req_stridx() backtracks one char */ - - if (x == DUK_ASC_DOUBLEQUOTE) { - duk__dec_string(js_ctx); - } else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) { -#ifdef DUK_USE_JX - if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */ - duk_push_number(ctx, -DUK_DOUBLE_INFINITY); - } else { -#else - { /* unconditional block */ -#endif - /* We already ate 'x', so backup one byte. */ - js_ctx->p--; /* safe */ - duk__dec_number(js_ctx); - } - } else if (x == DUK_ASC_LC_T) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE); - duk_push_true(ctx); - } else if (x == DUK_ASC_LC_F) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE); - duk_push_false(ctx); - } else if (x == DUK_ASC_LC_N) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL); - duk_push_null(ctx); -#ifdef DUK_USE_JX - } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED); - duk_push_undefined(ctx); - } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN); - duk_push_nan(ctx); - } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) { - duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY); - duk_push_number(ctx, DUK_DOUBLE_INFINITY); - } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) { - duk__dec_pointer(js_ctx); - } else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) { - duk__dec_buffer(js_ctx); -#endif - } else if (x == DUK_ASC_LCURLY) { - duk__dec_object(js_ctx); - } else if (x == DUK_ASC_LBRACKET) { - duk__dec_array(js_ctx); - } else { - /* catches EOF (NUL) */ - goto syntax_error; - } - - duk__dec_eat_white(js_ctx); - - /* [ ... val ] */ - return; - - syntax_error: - duk__dec_syntax_error(js_ctx); - DUK_UNREACHABLE(); -} - -/* Recursive value reviver, implements the Walk() algorithm. No C recursion - * check is done here because the initial parsing step will already ensure - * there is a reasonable limit on C recursion depth and hence object depth. - */ -DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hobject *h; - duk_uarridx_t i, arr_len; - - DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T", - (long) duk_get_top(ctx), - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - - duk_dup_top(ctx); - duk_get_prop(ctx, -3); /* -> [ ... holder name val ] */ - - h = duk_get_hobject(ctx, -1); - if (h != NULL) { - if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) { - arr_len = (duk_uarridx_t) duk_get_length(ctx, -1); - for (i = 0; i < arr_len; i++) { - /* [ ... holder name val ] */ - - DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T", - (long) duk_get_top(ctx), (long) i, (long) arr_len, - (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - - /* XXX: push_uint_string / push_u32_string */ - duk_dup_top(ctx); - duk_push_uint(ctx, (duk_uint_t) i); - duk_to_string(ctx, -1); /* -> [ ... holder name val val ToString(i) ] */ - duk__dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */ - - if (duk_is_undefined(ctx, -1)) { - duk_pop(ctx); - duk_del_prop_index(ctx, -1, i); - } else { - /* XXX: duk_xdef_prop_index_wec() would be more appropriate - * here but it currently makes some assumptions that might - * not hold (e.g. that previous property is not an accessor). - */ - duk_put_prop_index(ctx, -2, i); - } - } - } else { - /* [ ... holder name val ] */ - duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); - while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) { - DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T", - (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -5), - (duk_tval *) duk_get_tval(ctx, -4), (duk_tval *) duk_get_tval(ctx, -3), - (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1))); - - /* [ ... holder name val enum obj_key ] */ - duk_dup(ctx, -3); - duk_dup(ctx, -2); - - /* [ ... holder name val enum obj_key val obj_key ] */ - duk__dec_reviver_walk(js_ctx); - - /* [ ... holder name val enum obj_key new_elem ] */ - if (duk_is_undefined(ctx, -1)) { - duk_pop(ctx); - duk_del_prop(ctx, -3); - } else { - /* XXX: duk_xdef_prop_index_wec() would be more appropriate - * here but it currently makes some assumptions that might - * not hold (e.g. that previous property is not an accessor). - * - * Using duk_put_prop() works incorrectly with '__proto__' - * if the own property with that name has been deleted. This - * does not happen normally, but a clever reviver can trigger - * that, see complex reviver case in: test-bug-json-parse-__proto__.js. - */ - duk_put_prop(ctx, -4); - } - } - duk_pop(ctx); /* pop enum */ - } - } - - /* [ ... holder name val ] */ - - duk_dup(ctx, js_ctx->idx_reviver); - duk_insert(ctx, -4); /* -> [ ... reviver holder name val ] */ - duk_call_method(ctx, 2); /* -> [ ... res ] */ - - DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T", - (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -1))); -} - -/* - * Stringify implementation. - */ - -#define DUK__EMIT_1(js_ctx,ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch)) -#define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2)) -#define DUK__EMIT_HSTR(js_ctx,h) duk__emit_hstring((js_ctx), (h)) -#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC) -#define DUK__EMIT_CSTR(js_ctx,p) duk__emit_cstring((js_ctx), (p)) -#endif -#define DUK__EMIT_STRIDX(js_ctx,i) duk__emit_stridx((js_ctx), (i)) -#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) -#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx)) -#endif - -DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) { - DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch); -} - -DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) { - DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2); -} - -DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) { - DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h); -} - -#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC) -DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) { - DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str); -} -#endif - -DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) { - duk_hstring *h; - - DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */ - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx); - DUK_ASSERT(h != NULL); - - DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h); -} - -#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) -DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) { - DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1); - DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1); -} -#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */ - -#define DUK__MKESC(nybbles,esc1,esc2) \ - (((duk_uint_fast32_t) (nybbles)) << 16) | \ - (((duk_uint_fast32_t) (esc1)) << 8) | \ - ((duk_uint_fast32_t) (esc2)) - -DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) { - duk_uint_fast32_t tmp; - duk_small_uint_t dig; - - DUK_UNREF(js_ctx); - - /* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */ - - /* Select appropriate escape format automatically, and set 'tmp' to a - * value encoding both the escape format character and the nybble count: - * - * (nybble_count << 16) | (escape_char1) | (escape_char2) - */ - -#ifdef DUK_USE_JX - if (DUK_LIKELY(cp < 0x100UL)) { - if (DUK_UNLIKELY(js_ctx->flag_ext_custom)) { - tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X); - } else { - tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U); - } - } else -#endif - if (DUK_LIKELY(cp < 0x10000UL)) { - tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U); - } else { -#ifdef DUK_USE_JX - if (DUK_LIKELY(js_ctx->flag_ext_custom)) { - tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U); - } else -#endif - { - /* In compatible mode and standard JSON mode, output - * something useful for non-BMP characters. This won't - * roundtrip but will still be more or less readable and - * more useful than an error. - */ - tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS); - } - } - - *q++ = (duk_uint8_t) ((tmp >> 8) & 0xff); - *q++ = (duk_uint8_t) (tmp & 0xff); - - tmp = tmp >> 16; - while (tmp > 0) { - tmp--; - dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f); - *q++ = duk_lc_digits[dig]; - } - - return q; -} - -/* Check whether key quotes would be needed (custom encoding). */ -DUK_LOCAL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) { - const duk_uint8_t *p, *p_start, *p_end; - duk_small_uint_t ch; - - DUK_ASSERT(h_key != NULL); - p_start = DUK_HSTRING_GET_DATA(h_key); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_key); - p = p_start; - - DUK_DDD(DUK_DDDPRINT("duk__enc_key_quotes_needed: h_key=%!O, p_start=%p, p_end=%p, p=%p", - (duk_heaphdr *) h_key, (void *) p_start, (void *) p_end, (void *) p)); - - /* Since we only accept ASCII characters, there is no need for - * actual decoding. A non-ASCII character will be >= 0x80 which - * causes a false return value immediately. - */ - - if (p == p_end) { - /* Zero length string is not accepted without quotes */ - return 1; - } - - while (p < p_end) { - ch = (duk_small_uint_t) (*p); - - /* Accept ASCII IdentifierStart and IdentifierPart if not first char. - * Function selection is a bit uncommon. - */ - if ((p > p_start ? duk_unicode_is_identifier_part : - duk_unicode_is_identifier_start) ((duk_codepoint_t) ch)) { - p++; - continue; - } - - /* all non-ASCII characters also come here (first byte >= 0x80) */ - return 1; - } - - return 0; -} - -/* The Quote(value) operation: quote a string. - * - * Stack policy: [ ] -> [ ]. - */ - -DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) { - duk_hthread *thr = js_ctx->thr; - const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp; - duk_uint8_t *q; - duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */ - - DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str)); - - DUK_ASSERT(h_str != NULL); - p_start = DUK_HSTRING_GET_DATA(h_str); - p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str); - p = p_start; - - DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE); - - /* Encode string in small chunks, estimating the maximum expansion so that - * there's no need to ensure space while processing the chunk. - */ - - while (p < p_end) { - duk_size_t left, now, space; - - left = (duk_size_t) (p_end - p); - now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ? - DUK__JSON_ENCSTR_CHUNKSIZE : left); - - /* Maximum expansion per input byte is 6: - * - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6). - * - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3). - * - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5). - */ - space = now * 6; - q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space); - - p_now = p + now; - - while (p < p_now) { -#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH) - duk_uint8_t b; - - b = duk__json_quotestr_lookup[*p++]; - if (DUK_LIKELY(b < 0x80)) { - /* Most input bytes go through here. */ - *q++ = b; - } else if (b >= 0xa0) { - *q++ = DUK_ASC_BACKSLASH; - *q++ = (duk_uint8_t) (b - 0x80); - } else if (b == 0x80) { - cp = (duk_ucodepoint_t) (*(p - 1)); - q = duk__emit_esc_auto_fast(js_ctx, cp, q); - } else if (b == 0x7f && js_ctx->flag_ascii_only) { - /* 0x7F is special */ - DUK_ASSERT(b == 0x81); - cp = (duk_ucodepoint_t) 0x7f; - q = duk__emit_esc_auto_fast(js_ctx, cp, q); - } else { - DUK_ASSERT(b == 0x81); - p--; - - /* slow path is shared */ -#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ - cp = *p; - - if (DUK_LIKELY(cp <= 0x7f)) { - /* ascii fast path: avoid decoding utf-8 */ - p++; - if (cp == 0x22 || cp == 0x5c) { - /* double quote or backslash */ - *q++ = DUK_ASC_BACKSLASH; - *q++ = (duk_uint8_t) cp; - } else if (cp < 0x20) { - duk_uint_fast8_t esc_char; - - /* This approach is a bit shorter than a straight - * if-else-ladder and also a bit faster. - */ - if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) && - (esc_char = duk__json_quotestr_esc[cp]) != 0) { - *q++ = DUK_ASC_BACKSLASH; - *q++ = (duk_uint8_t) esc_char; - } else { - q = duk__emit_esc_auto_fast(js_ctx, cp, q); - } - } else if (cp == 0x7f && js_ctx->flag_ascii_only) { - q = duk__emit_esc_auto_fast(js_ctx, cp, q); - } else { - /* any other printable -> as is */ - *q++ = (duk_uint8_t) cp; - } - } else { - /* slow path is shared */ -#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ - - /* slow path decode */ - - /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly - * and go forward one byte. This is of course very lossy, but allows some kind - * of output to be produced even for internal strings which don't conform to - * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior - * does not violate the Ecmascript specification. The behavior is applied to - * all modes, including Ecmascript standard JSON. Because the current XUTF-8 - * decoding is not very strict, this behavior only really affects initial bytes - * and truncated codepoints. - * - * Another alternative would be to scan forwards to start of next codepoint - * (or end of input) and emit just one replacement codepoint. - */ - - p_tmp = p; - if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) { - /* Decode failed. */ - cp = *p_tmp; - p = p_tmp + 1; - } - -#ifdef DUK_USE_NONSTD_JSON_ESC_U2028_U2029 - if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) { -#else - if (js_ctx->flag_ascii_only) { -#endif - q = duk__emit_esc_auto_fast(js_ctx, cp, q); - } else { - /* as is */ - DUK_RAW_WRITE_XUTF8(q, cp); - } - } - } - - DUK_BW_SET_PTR(thr, &js_ctx->bw, q); - } - - DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE); -} - -/* Encode a double (checked by caller) from stack top. Stack top may be - * replaced by serialized string but is not popped (caller does that). - */ -DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) { - duk_context *ctx; - duk_tval *tv; - duk_double_t d; - duk_small_int_t c; - duk_small_int_t s; - duk_small_uint_t stridx; - duk_small_uint_t n2s_flags; - duk_hstring *h_str; - - DUK_ASSERT(js_ctx != NULL); - ctx = (duk_context *) js_ctx->thr; - DUK_ASSERT(ctx != NULL); - - /* Caller must ensure 'tv' is indeed a double and not a fastint! */ - tv = duk_get_tval(ctx, -1); - DUK_ASSERT(tv != NULL); - DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv)); - d = DUK_TVAL_GET_DOUBLE(tv); - - c = (duk_small_int_t) DUK_FPCLASSIFY(d); - s = (duk_small_int_t) DUK_SIGNBIT(d); - DUK_UNREF(s); - - if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) { - DUK_ASSERT(DUK_ISFINITE(d)); - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - /* Negative zero needs special handling in JX/JC because - * it would otherwise serialize to '0', not '-0'. - */ - if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 && - (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible))) { - duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO); /* '-0' */ - } else -#endif /* DUK_USE_JX || DUK_USE_JC */ - { - n2s_flags = 0; - /* [ ... number ] -> [ ... string ] */ - duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags); - } - h_str = duk_to_hstring(ctx, -1); - DUK_ASSERT(h_str != NULL); - DUK__EMIT_HSTR(js_ctx, h_str); - return; - } - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | - DUK_JSON_FLAG_EXT_COMPATIBLE))) { - stridx = DUK_STRIDX_LC_NULL; - } else if (c == DUK_FP_NAN) { - stridx = js_ctx->stridx_custom_nan; - } else if (s == 0) { - stridx = js_ctx->stridx_custom_posinf; - } else { - stridx = js_ctx->stridx_custom_neginf; - } -#else - stridx = DUK_STRIDX_LC_NULL; -#endif - DUK__EMIT_STRIDX(js_ctx, stridx); -} - -#if defined(DUK_USE_FASTINT) -/* Encode a fastint from duk_tval ptr, no value stack effects. */ -DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) { - duk_int64_t v; - - /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328 - * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808 - * (20 chars long). Alloc space for 64-bit range to be safe. - */ - duk_uint8_t buf[20 + 1]; - - /* Caller must ensure 'tv' is indeed a fastint! */ - DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv)); - v = DUK_TVAL_GET_FASTINT(tv); - - /* XXX: There are no format strings in duk_config.h yet, could add - * one for formatting duk_int64_t. For now, assumes "%lld" and that - * "long long" type exists. Could also rely on C99 directly but that - * won't work for older MSVC. - */ - DUK_SPRINTF((char *) buf, "%lld", (long long) v); - DUK__EMIT_CSTR(js_ctx, (const char *) buf); -} -#endif - -/* Shared entry handling for object/array serialization: indent/stepback, - * loop detection. - */ -DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hobject *h_target; - - *entry_top = duk_get_top(ctx); - - duk_require_stack(ctx, DUK_JSON_ENC_REQSTACK); - - /* loop check */ - - h_target = duk_get_hobject(ctx, -1); /* object or array */ - DUK_ASSERT(h_target != NULL); - - /* XXX: this check is very expensive, perhaps use a small - * array to make it faster for at least reasonably shallow - * objects? - */ - duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target); - duk_dup_top(ctx); /* -> [ ... voidp voidp ] */ - if (duk_has_prop(ctx, js_ctx->idx_loop)) { - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT); - } - duk_push_true(ctx); /* -> [ ... voidp true ] */ - duk_put_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */ - - /* c recursion check */ - - DUK_ASSERT(js_ctx->recursion_depth >= 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { - DUK_ERROR((duk_hthread *) ctx, DUK_ERR_RANGE_ERROR, DUK_STR_JSONENC_RECLIMIT); - } - js_ctx->recursion_depth++; - - /* figure out indent and stepback */ - - *h_indent = NULL; - *h_stepback = NULL; - if (js_ctx->h_gap != NULL) { - DUK_ASSERT(js_ctx->h_indent != NULL); - - *h_stepback = js_ctx->h_indent; - duk_push_hstring(ctx, js_ctx->h_indent); - duk_push_hstring(ctx, js_ctx->h_gap); - duk_concat(ctx, 2); - js_ctx->h_indent = duk_get_hstring(ctx, -1); - *h_indent = js_ctx->h_indent; - DUK_ASSERT(js_ctx->h_indent != NULL); - - /* The new indent string is left at value stack top, and will - * be popped by the shared exit handler. - */ - } else { - DUK_ASSERT(js_ctx->h_indent == NULL); - } - - DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T", - (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop))); -} - -/* Shared exit handling for object/array serialization. */ -DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hobject *h_target; - - DUK_UNREF(h_indent); - - if (js_ctx->h_gap != NULL) { - DUK_ASSERT(js_ctx->h_indent != NULL); - DUK_ASSERT(*h_stepback != NULL); - DUK_ASSERT(*h_indent != NULL); - - js_ctx->h_indent = *h_stepback; /* previous js_ctx->h_indent */ - - /* Note: we don't need to pop anything because the duk_set_top() - * at the end will take care of it. - */ - } else { - DUK_ASSERT(js_ctx->h_indent == NULL); - DUK_ASSERT(*h_stepback == NULL); - DUK_ASSERT(*h_indent == NULL); - } - - /* c recursion check */ - - DUK_ASSERT(js_ctx->recursion_depth > 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - js_ctx->recursion_depth--; - - /* loop check */ - - h_target = duk_get_hobject(ctx, *entry_top - 1); /* original target at entry_top - 1 */ - DUK_ASSERT(h_target != NULL); - - /* XXX: this check is very expensive */ - duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target); - duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */ - - /* restore stack top after unbalanced code paths */ - duk_set_top(ctx, *entry_top); - - DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T", - (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop))); -} - -/* The JO(value) operation: encode object. - * - * Stack policy: [ object ] -> [ object ]. - */ -DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hstring *h_stepback; - duk_hstring *h_indent; - duk_hstring *h_key; - duk_idx_t entry_top; - duk_idx_t idx_obj; - duk_idx_t idx_keys; - duk_bool_t first; - duk_bool_t undef; - duk_uarridx_t arr_len, i; - - DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1))); - - duk__enc_objarr_entry(js_ctx, &h_stepback, &h_indent, &entry_top); - - idx_obj = entry_top - 1; - - if (js_ctx->idx_proplist >= 0) { - idx_keys = js_ctx->idx_proplist; - } else { - /* XXX: would be nice to enumerate an object at specified index */ - duk_dup(ctx, idx_obj); - (void) duk_hobject_get_enumerated_keys(ctx, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */ - idx_keys = duk_require_normalize_index(ctx, -1); - /* leave stack unbalanced on purpose */ - } - - DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T", - (long) idx_keys, (duk_tval *) duk_get_tval(ctx, idx_keys))); - - /* Steps 8-10 have been merged to avoid a "partial" variable. */ - - DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY); - - /* XXX: keys is an internal object with all keys to be processed - * in its (gapless) array part. Because nobody can touch the keys - * object, we could iterate its array part directly (keeping in mind - * that it can be reallocated). - */ - - arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_keys); - first = 1; - for (i = 0; i < arr_len; i++) { - duk_get_prop_index(ctx, idx_keys, i); /* -> [ ... key ] */ - - DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T", - (duk_tval *) duk_get_tval(ctx, idx_obj), - (duk_tval *) duk_get_tval(ctx, -1))); - - undef = duk__enc_value1(js_ctx, idx_obj); - if (undef) { - /* Value would yield 'undefined', so skip key altogether. - * Side effects have already happened. - */ - continue; - } - - /* [ ... key val ] */ - - if (first) { - first = 0; - } else { - DUK__EMIT_1(js_ctx, DUK_ASC_COMMA); - } - if (h_indent != NULL) { - DUK__EMIT_1(js_ctx, 0x0a); - DUK__EMIT_HSTR(js_ctx, h_indent); - } - - h_key = duk_get_hstring(ctx, -2); - DUK_ASSERT(h_key != NULL); - if (js_ctx->flag_avoid_key_quotes && !duk__enc_key_quotes_needed(h_key)) { - /* emit key as is */ - DUK__EMIT_HSTR(js_ctx, h_key); - } else { - duk__enc_quote_string(js_ctx, h_key); - } - - if (h_indent != NULL) { - DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE); - } else { - DUK__EMIT_1(js_ctx, DUK_ASC_COLON); - } - - /* [ ... key val ] */ - - duk__enc_value2(js_ctx); /* -> [ ... ] */ - } - - if (!first) { - if (h_stepback != NULL) { - DUK_ASSERT(h_indent != NULL); - DUK__EMIT_1(js_ctx, 0x0a); - DUK__EMIT_HSTR(js_ctx, h_stepback); - } - } - DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); - - duk__enc_objarr_exit(js_ctx, &h_stepback, &h_indent, &entry_top); - - DUK_ASSERT_TOP(ctx, entry_top); -} - -/* The JA(value) operation: encode array. - * - * Stack policy: [ array ] -> [ array ]. - */ -DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hstring *h_stepback; - duk_hstring *h_indent; - duk_idx_t entry_top; - duk_idx_t idx_arr; - duk_bool_t undef; - duk_uarridx_t i, arr_len; - - DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T", - (duk_tval *) duk_get_tval(ctx, -1))); - - duk__enc_objarr_entry(js_ctx, &h_stepback, &h_indent, &entry_top); - - idx_arr = entry_top - 1; - - /* Steps 8-10 have been merged to avoid a "partial" variable. */ - - DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET); - - arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr); - for (i = 0; i < arr_len; i++) { - DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, h_indent=%!O, h_stepback=%!O, index=%ld, arr_len=%ld", - (duk_tval *) duk_get_tval(ctx, idx_arr), (duk_heaphdr *) h_indent, - (duk_heaphdr *) h_stepback, (long) i, (long) arr_len)); - - if (i > 0) { - DUK__EMIT_1(js_ctx, DUK_ASC_COMMA); - } - if (h_indent != NULL) { - DUK__EMIT_1(js_ctx, 0x0a); - DUK__EMIT_HSTR(js_ctx, h_indent); - } - - /* XXX: duk_push_uint_string() */ - duk_push_uint(ctx, (duk_uint_t) i); - duk_to_string(ctx, -1); /* -> [ ... key ] */ - undef = duk__enc_value1(js_ctx, idx_arr); - - if (undef) { - DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); - } else { - /* [ ... key val ] */ - duk__enc_value2(js_ctx); - } - } - - if (arr_len > 0) { - if (h_stepback != NULL) { - DUK_ASSERT(h_indent != NULL); - DUK__EMIT_1(js_ctx, 0x0a); - DUK__EMIT_HSTR(js_ctx, h_stepback); - } - } - DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET); - - duk__enc_objarr_exit(js_ctx, &h_stepback, &h_indent, &entry_top); - - DUK_ASSERT_TOP(ctx, entry_top); -} - -/* The Str(key, holder) operation: encode value, steps 1-4. - * - * Returns non-zero if the value between steps 4 and 5 would yield an - * 'undefined' final result. This is useful in JO() because we need to - * get the side effects out, but need to know whether or not a key will - * be omitted from the serialization. - * - * Stack policy: [ ... key ] -> [ ... key val ] if retval == 0. - * -> [ ... ] if retval != 0. - */ -DUK_LOCAL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hthread *thr = (duk_hthread *) ctx; - duk_hobject *h; - duk_tval *tv; - duk_small_int_t c; - - DUK_DDD(DUK_DDDPRINT("duk__enc_value1: idx_holder=%ld, holder=%!T, key=%!T", - (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder), - (duk_tval *) duk_get_tval(ctx, -1))); - - DUK_UNREF(thr); - - duk_dup_top(ctx); /* -> [ ... key key ] */ - duk_get_prop(ctx, idx_holder); /* -> [ ... key val ] */ - - DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1))); - - h = duk_get_hobject_or_lfunc_coerce(ctx, -1); - if (h != NULL) { - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_JSON); - h = duk_get_hobject_or_lfunc_coerce(ctx, -1); /* toJSON() can also be a lightfunc */ - - if (h != NULL && DUK_HOBJECT_IS_CALLABLE(h)) { - DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it")); - duk_dup(ctx, -2); /* -> [ ... key val toJSON val ] */ - duk_dup(ctx, -4); /* -> [ ... key val toJSON val key ] */ - duk_call_method(ctx, 1); /* -> [ ... key val val' ] */ - duk_remove(ctx, -2); /* -> [ ... key val' ] */ - } else { - duk_pop(ctx); - } - } - - /* [ ... key val ] */ - - DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1))); - - if (js_ctx->h_replacer) { - /* XXX: here a "slice copy" would be useful */ - DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer")); - duk_push_hobject(ctx, js_ctx->h_replacer); /* -> [ ... key val replacer ] */ - duk_dup(ctx, idx_holder); /* -> [ ... key val replacer holder ] */ - duk_dup(ctx, -4); /* -> [ ... key val replacer holder key ] */ - duk_dup(ctx, -4); /* -> [ ... key val replacer holder key val ] */ - duk_call_method(ctx, 2); /* -> [ ... key val val' ] */ - duk_remove(ctx, -2); /* -> [ ... key val' ] */ - } - - /* [ ... key val ] */ - - DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1))); - - tv = duk_get_tval(ctx, -1); - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_OBJECT(tv)) { - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - - if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { - duk_hbufferobject *h_bufobj; - h_bufobj = (duk_hbufferobject *) h; - DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) { - duk_push_null(ctx); - } else if (DUK_HBUFFEROBJECT_FULL_SLICE(h_bufobj)) { - duk_push_hbuffer(ctx, h_bufobj->buf); - } else { - /* This is not very good because we're making a copy - * for serialization, but only for proper views. - * Better support would be to serialize slices - * directly but since we only push a raw buffer - * here we can't convey the slice offset/length. - */ - duk_uint8_t *p_buf; - - p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, h_bufobj->length); - DUK_MEMCPY((void *) p_buf, - (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj)), - h_bufobj->length); - } - duk_remove(ctx, -2); - } else { - c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h); - switch ((int) c) { - case DUK_HOBJECT_CLASS_NUMBER: { - DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()")); - duk_to_number(ctx, -1); - break; - } - case DUK_HOBJECT_CLASS_STRING: { - DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()")); - duk_to_string(ctx, -1); - break; - } -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - case DUK_HOBJECT_CLASS_POINTER: -#endif - case DUK_HOBJECT_CLASS_BOOLEAN: { - DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value")); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); - duk_remove(ctx, -2); - break; - } - } /* end switch */ - } - } - - /* [ ... key val ] */ - - DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1))); - - if (duk_check_type_mask(ctx, -1, js_ctx->mask_for_undefined)) { - /* will result in undefined */ - DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)")); - goto undef; - } - - /* functions are detected specially */ - h = duk_get_hobject(ctx, -1); - if (h != NULL && DUK_HOBJECT_IS_CALLABLE(h)) { - if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | - DUK_JSON_FLAG_EXT_COMPATIBLE)) { - /* function will be serialized to custom format */ - } else { - /* functions are not serialized, results in undefined */ - DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)")); - goto undef; - } - } - - DUK_DDD(DUK_DDDPRINT("-> will not result in undefined")); - return 0; - - undef: - duk_pop_2(ctx); - return 1; -} - -/* The Str(key, holder) operation: encode value, steps 5-10. - * - * This must not be called unless duk__enc_value1() returns non-zero. - * If so, this is guaranteed to produce a non-undefined result. - * Non-standard encodings (e.g. for undefined) are only used if - * duk__enc_value1() indicates they are accepted; they're not - * checked or asserted here again. - * - * Stack policy: [ ... key val ] -> [ ... ]. - */ -DUK_LOCAL void duk__enc_value2(duk_json_enc_ctx *js_ctx) { - duk_context *ctx = (duk_context *) js_ctx->thr; - duk_hthread *thr = (duk_hthread *) ctx; - duk_tval *tv; - - DUK_UNREF(thr); - - DUK_DDD(DUK_DDDPRINT("duk__enc_value2: key=%!T, val=%!T", - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - - /* [ ... key val ] */ - - tv = duk_get_tval(ctx, -1); - DUK_ASSERT(tv != NULL); - - switch (DUK_TVAL_GET_TAG(tv)) { -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - /* When JX/JC not in use, duk__enc_value1 will block undefined values. */ - case DUK_TAG_UNDEFINED: { - DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined); - break; - } -#endif - case DUK_TAG_NULL: { - DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); - break; - } - case DUK_TAG_BOOLEAN: { - DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ? - DUK_STRIDX_TRUE : DUK_STRIDX_FALSE); - break; - } -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - /* When JX/JC not in use, duk__enc_value1 will block pointer values. */ - case DUK_TAG_POINTER: { - char buf[64]; /* XXX: how to figure correct size? */ - const char *fmt; - void *ptr = DUK_TVAL_GET_POINTER(tv); - - DUK_MEMZERO(buf, sizeof(buf)); - - /* The #ifdef clutter here needs to handle the three cases: - * (1) JX+JC, (2) JX only, (3) JC only. - */ -#if defined(DUK_USE_JX) && defined(DUK_USE_JC) - if (js_ctx->flag_ext_custom) -#endif -#if defined(DUK_USE_JX) - { - fmt = ptr ? "(%p)" : "(null)"; - } -#endif -#if defined(DUK_USE_JX) && defined(DUK_USE_JC) - else -#endif -#if defined(DUK_USE_JC) - { - fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}"; - } -#endif - - /* When ptr == NULL, the format argument is unused. */ - DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */ - DUK__EMIT_CSTR(js_ctx, buf); - break; - } -#endif /* DUK_USE_JX || DUK_USE_JC */ - case DUK_TAG_STRING: { - duk_hstring *h = DUK_TVAL_GET_STRING(tv); - DUK_ASSERT(h != NULL); - - duk__enc_quote_string(js_ctx, h); - break; - } - case DUK_TAG_OBJECT: { - duk_hobject *h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - if (DUK_HOBJECT_IS_CALLABLE(h)) { - /* We only get here when doing non-standard JSON encoding */ - DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); - DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function); - } else /* continues below */ -#endif - if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) { - duk__enc_array(js_ctx); - } else { - duk__enc_object(js_ctx); - } - break; - } -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - /* When JX/JC not in use, duk__enc_value1 will block buffer values. */ - case DUK_TAG_BUFFER: { - /* Buffer values are encoded in (lowercase) hex to make the - * binary data readable. Base64 or similar would be more - * compact but less readable, and the point of JX/JC - * variants is to be as useful to a programmer as possible. - */ - - /* The #ifdef clutter here needs to handle the three cases: - * (1) JX+JC, (2) JX only, (3) JC only. - */ -#if defined(DUK_USE_JX) && defined(DUK_USE_JC) - if (js_ctx->flag_ext_custom) -#endif -#if defined(DUK_USE_JX) - { - duk_uint8_t *p, *p_end; - duk_small_uint_t x; - duk_hbuffer *h; - duk_uint8_t *q; - duk_size_t space; - - h = DUK_TVAL_GET_BUFFER(tv); - DUK_ASSERT(h != NULL); - p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); - p_end = p + DUK_HBUFFER_GET_SIZE(h); - - space = 1 + DUK_HBUFFER_GET_SIZE(h) * 2 + 1; - DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL); - DUK_ASSERT((space - 2) / 2 == DUK_HBUFFER_GET_SIZE(h)); /* overflow not possible, buffer limits */ - q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space); - - *q++ = DUK_ASC_PIPE; - while (p < p_end) { - x = *p++; - *q++ = duk_lc_digits[(x >> 4) & 0x0f]; - *q++ = duk_lc_digits[x & 0x0f]; - } - *q++ = DUK_ASC_PIPE; - - DUK_BW_SET_PTR(thr, &js_ctx->bw, q); - } -#endif -#if defined(DUK_USE_JX) && defined(DUK_USE_JC) - else -#endif -#if defined(DUK_USE_JC) - { - DUK_ASSERT(js_ctx->flag_ext_compatible); - duk_hex_encode(ctx, -1); - DUK__EMIT_CSTR(js_ctx, "{\"_buf\":"); - duk__enc_quote_string(js_ctx, duk_require_hstring(ctx, -1)); - DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); - } -#endif - break; - } -#endif /* DUK_USE_JX || DUK_USE_JC */ - case DUK_TAG_LIGHTFUNC: { -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - /* We only get here when doing non-standard JSON encoding */ - DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); - DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function); -#else - /* Standard JSON omits functions */ - DUK_UNREACHABLE(); -#endif - break; - } -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: - /* Number serialization has a significant impact relative to - * other fast path code, so careful fast path for fastints. - */ - duk__enc_fastint_tval(js_ctx, tv); - break; -#endif - default: { - /* number */ - /* XXX: A fast path for usual integers would be useful when - * fastint support is not enabled. - */ - duk__enc_double(js_ctx); - break; - } - } - - /* [ ... key val ] -> [ ... ] */ - - duk_pop_2(ctx); -} - -/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */ -DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) { - duk_hobject *h; - duk_small_int_t c; - - DUK_ASSERT(tv != NULL); - if (DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv)) { - return 1; - } else if (DUK_TVAL_IS_OBJECT(tv)) { - h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); - c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h); - if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) { - return 1; - } - } - - return 0; -} - -/* - * JSON.stringify() fast path - */ - -#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) -DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) { - duk_uint_fast32_t i, n; - - DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv)); - - DUK_ASSERT(js_ctx != NULL); - DUK_ASSERT(js_ctx->thr != NULL); -#if defined(DUK_USE_JX) - DUK_ASSERT(js_ctx->flag_ext_custom == 0); -#endif -#if defined(DUK_USE_JC) - DUK_ASSERT(js_ctx->flag_ext_compatible == 0); -#endif - - restart_match: - DUK_ASSERT(tv != NULL); - - switch (DUK_TVAL_GET_TAG(tv)) { - case DUK_TAG_UNDEFINED: { - goto emit_undefined; - } - case DUK_TAG_NULL: { - DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); - break; - } - case DUK_TAG_BOOLEAN: { - DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ? - DUK_STRIDX_TRUE : DUK_STRIDX_FALSE); - break; - } - case DUK_TAG_STRING: { - duk_hstring *h; - - h = DUK_TVAL_GET_STRING(tv); - DUK_ASSERT(h != NULL); - duk__enc_quote_string(js_ctx, h); - break; - } - case DUK_TAG_OBJECT: { - duk_hobject *obj; - duk_tval *tv_val; - duk_bool_t emitted = 0; - duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef, c_object; - - /* For objects JSON.stringify() only looks for own, enumerable - * properties which is nice for the fast path here. - * - * For arrays JSON.stringify() uses [[Get]] so it will actually - * inherit properties during serialization! This fast path - * supports gappy arrays as long as there's no actual inherited - * property (which might be a getter etc). - * - * Since recursion only happens for objects, we can have both - * recursion and loop checks here. We use a simple, depth-limited - * loop check in the fast path because the object-based tracking - * is very slow (when tested, it accounted for 50% of fast path - * execution time for input data with a lot of small objects!). - */ - - obj = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(obj != NULL); - - /* We rely on a few object flag / class number relationships here, - * assert for them. - */ - DUK_ASSERT_HOBJECT_VALID(obj); - - /* Once recursion depth is increased, exit path must decrease - * it (though it's OK to abort the fast path). - */ - - DUK_ASSERT(js_ctx->recursion_depth >= 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { - DUK_DD(DUK_DDPRINT("fast path recursion limit")); - DUK_ERROR(js_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_JSONDEC_RECLIMIT); - } - - for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) { - if (js_ctx->visiting[i] == obj) { - DUK_DD(DUK_DDPRINT("fast path loop detect")); - DUK_ERROR(js_ctx->thr, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT); - } - } - - /* Guaranteed by recursion_limit setup so we don't have to - * check twice. - */ - DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY); - js_ctx->visiting[js_ctx->recursion_depth] = obj; - js_ctx->recursion_depth++; - - /* If object has a .toJSON() property, we can't be certain - * that it wouldn't mutate any value arbitrarily, so bail - * out of the fast path. - * - * If an object is a Proxy we also can't avoid side effects - * so abandon. - */ - if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) || - DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) { - DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path")); - goto abort_fastpath; - } - - /* We could use a switch-case for the class number but it turns out - * a small if-else ladder on class masks is better. The if-ladder - * should be in order of relevancy. - */ - - DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31); - c_all = DUK_HOBJECT_CMASK_ALL; - c_array = DUK_HOBJECT_CMASK_ARRAY; - c_unbox = DUK_HOBJECT_CMASK_NUMBER | - DUK_HOBJECT_CMASK_STRING | - DUK_HOBJECT_CMASK_BOOLEAN; - c_undef = DUK_HOBJECT_CMASK_FUNCTION | - DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS; - c_object = c_all & ~(c_array | c_unbox | c_undef); - - c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj); - if (c_bit & c_object) { - /* All other object types. */ - DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY); - - /* A non-Array object should not have an array part in practice. - * But since it is supported internally (and perhaps used at some - * point), check and abandon if that's the case. - */ - if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) { - DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path")); - goto abort_fastpath; - } - - for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) { - duk_hstring *k; - duk_size_t prev_size; - - k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i); - if (!k) { - continue; - } - if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) { - continue; - } - if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) { - /* Getter might have arbitrary side effects, - * so bail out. - */ - DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path")); - goto abort_fastpath; - } - if (DUK_HSTRING_HAS_INTERNAL(k)) { - continue; - } - - tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i); - - prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw); - duk__enc_quote_string(js_ctx, k); - DUK__EMIT_1(js_ctx, DUK_ASC_COLON); - if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) { - DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon")); - DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size); - } else { - DUK__EMIT_1(js_ctx, DUK_ASC_COMMA); - emitted = 1; - } - } - - /* If any non-Array value had enumerable virtual own - * properties, they should be serialized here. Standard - * types don't. - */ - - if (emitted) { - DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ - } - DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); - } else if (c_bit & c_array) { - duk_uint_fast32_t arr_len; - duk_uint_fast32_t asize; - - DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET); - - /* Assume arrays are dense in the fast path. */ - if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) { - DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path")); - goto abort_fastpath; - } - - arr_len = (duk_uint_fast32_t) duk_hobject_get_length(js_ctx->thr, obj); - asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj); - if (arr_len > asize) { - /* Array length is larger than 'asize'. This shouldn't - * happen in practice. Bail out just in case. - */ - DUK_DD(DUK_DDPRINT("arr_len > asize, abort fast path")); - goto abort_fastpath; - } - /* Array part may be larger than 'length'; if so, iterate - * only up to array 'length'. - */ - for (i = 0; i < arr_len; i++) { - DUK_ASSERT(i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj)); - - tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i); - - if (DUK_UNLIKELY(DUK_TVAL_IS_UNDEFINED_UNUSED(tv_val))) { - /* Gap in array; check for inherited property, - * bail out if one exists. This should be enough - * to support gappy arrays for all practical code. - */ - duk_hstring *h_tmp; - duk_bool_t has_inherited; - - /* XXX: refactor into an internal helper, pretty awkward */ - duk_push_uint((duk_context *) js_ctx->thr, (duk_uint_t) i); - h_tmp = duk_to_hstring((duk_context *) js_ctx->thr, -1); - DUK_ASSERT(h_tmp != NULL); - has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp); - duk_pop((duk_context *) js_ctx->thr); - - if (has_inherited) { - DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path")); - goto abort_fastpath; - } - - /* Ordinary gap, undefined encodes to 'null' in - * standard JSON (and no JX/JC support here now). - */ - DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path")); - DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); - } else { - if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) { - DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); - } - } - DUK__EMIT_1(js_ctx, DUK_ASC_COMMA); - emitted = 1; - } - - if (emitted) { - DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ - } - DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET); - } else if (c_bit & c_unbox) { - /* These three boxed types are required to go through - * automatic unboxing. Rely on internal value being - * sane (to avoid infinite recursion). - */ - duk_tval *tv_internal; - - DUK_DD(DUK_DDPRINT("auto unboxing in fast path")); - - tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj); - DUK_ASSERT(tv_internal != NULL); - DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) || - DUK_TVAL_IS_NUMBER(tv_internal) || - DUK_TVAL_IS_BOOLEAN(tv_internal)); - - /* XXX: for JX/JC, special handling for Pointer, and Buffer? */ - tv = tv_internal; - goto restart_match; - } else { - DUK_ASSERT((c_bit & c_undef) != 0); - - /* Function objects are treated as "undefined" by JSON. - * - * The slow path replaces a buffer object automatically with - * the binary data which then gets treated like "undefined". - * Since we don't support buffers here now, treat as "undefined". - */ - - /* Must decrease recursion depth before returning. */ - DUK_ASSERT(js_ctx->recursion_depth > 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - js_ctx->recursion_depth--; - goto emit_undefined; - } - - DUK_ASSERT(js_ctx->recursion_depth > 0); - DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); - js_ctx->recursion_depth--; - break; - } - case DUK_TAG_BUFFER: { - goto emit_undefined; - } - case DUK_TAG_POINTER: { - goto emit_undefined; - } - case DUK_TAG_LIGHTFUNC: { - /* A lightfunc might also inherit a .toJSON() so just bail out. */ - DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path")); - goto abort_fastpath; - } -#if defined(DUK_USE_FASTINT) - case DUK_TAG_FASTINT: { - /* Number serialization has a significant impact relative to - * other fast path code, so careful fast path for fastints. - */ - duk__enc_fastint_tval(js_ctx, tv); - break; - } -#endif - default: { - /* XXX: A fast path for usual integers would be useful when - * fastint support is not enabled. - */ - /* XXX: Stack discipline is annoying, could be changed in numconv. */ - duk_push_tval((duk_context *) js_ctx->thr, tv); - duk__enc_double(js_ctx); - duk_pop((duk_context *) js_ctx->thr); - -#if 0 - /* Could also rely on native sprintf(), but it will handle - * values like NaN, Infinity, -0, exponent notation etc in - * a JSON-incompatible way. - */ - duk_double_t d; - char buf[64]; - - DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv)); - d = DUK_TVAL_GET_DOUBLE(tv); - DUK_SPRINTF(buf, "%lg", d); - DUK__EMIT_CSTR(js_ctx, buf); -#endif - } - } - return 1; /* not undefined */ - - emit_undefined: - return 0; /* value was undefined/unsupported */ - - abort_fastpath: - /* Error message doesn't matter: the error is ignored anyway. */ - DUK_DD(DUK_DDPRINT("aborting fast path")); - DUK_ERROR(js_ctx->thr, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR); - return 0; /* unreachable */ -} - -DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx) { - duk_json_enc_ctx *js_ctx; - - DUK_ASSERT(ctx != NULL); - js_ctx = (duk_json_enc_ctx *) duk_get_pointer(ctx, -2); - DUK_ASSERT(js_ctx != NULL); - - if (duk__json_stringify_fast_value(js_ctx, duk_get_tval((duk_context *) (js_ctx->thr), -1)) == 0) { - DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path")); - return DUK_RET_ERROR; /* error message doesn't matter, ignored anyway */ - } - - return 0; -} -#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */ - -/* - * Top level wrappers - */ - -DUK_INTERNAL -void duk_bi_json_parse_helper(duk_context *ctx, - duk_idx_t idx_value, - duk_idx_t idx_reviver, - duk_small_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_json_dec_ctx js_ctx_alloc; - duk_json_dec_ctx *js_ctx = &js_ctx_alloc; - duk_hstring *h_text; -#ifdef DUK_USE_ASSERTIONS - duk_idx_t entry_top = duk_get_top(ctx); -#endif - - /* negative top-relative indices not allowed now */ - DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0); - DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0); - - DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld", - (duk_tval *) duk_get_tval(ctx, idx_value), - (duk_tval *) duk_get_tval(ctx, idx_reviver), - (unsigned long) flags, - (long) duk_get_top(ctx))); - - DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc)); - js_ctx->thr = thr; -#ifdef DUK_USE_EXPLICIT_NULL_INIT - /* nothing now */ -#endif - js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT; - DUK_ASSERT(js_ctx->recursion_depth == 0); - - /* Flag handling currently assumes that flags are consistent. This is OK - * because the call sites are now strictly controlled. - */ - - js_ctx->flags = flags; -#ifdef DUK_USE_JX - js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM; -#endif -#ifdef DUK_USE_JC - js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE; -#endif - - h_text = duk_to_hstring(ctx, idx_value); /* coerce in-place */ - DUK_ASSERT(h_text != NULL); - - /* JSON parsing code is allowed to read [p_start,p_end]: p_end is - * valid and points to the string NUL terminator (which is always - * guaranteed for duk_hstrings. - */ - js_ctx->p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text); - js_ctx->p = js_ctx->p_start; - js_ctx->p_end = ((duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) + - DUK_HSTRING_GET_BYTELEN(h_text); - DUK_ASSERT(*(js_ctx->p_end) == 0x00); - - duk__dec_value(js_ctx); /* -> [ ... value ] */ - - /* Trailing whitespace has been eaten by duk__dec_value(), so if - * we're not at end of input here, it's a SyntaxError. - */ - - if (js_ctx->p != js_ctx->p_end) { - duk__dec_syntax_error(js_ctx); - } - - if (duk_is_callable(ctx, idx_reviver)) { - DUK_DDD(DUK_DDDPRINT("applying reviver: %!T", - (duk_tval *) duk_get_tval(ctx, idx_reviver))); - - js_ctx->idx_reviver = idx_reviver; - - duk_push_object(ctx); - duk_dup(ctx, -2); /* -> [ ... val root val ] */ - duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */ - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */ - - DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T", - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - - duk__dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */ - duk_remove(ctx, -2); /* -> [ ... val' ] */ - } else { - DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T", - (duk_tval *) duk_get_tval(ctx, idx_reviver))); - } - - /* Final result is at stack top. */ - - DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld", - (duk_tval *) duk_get_tval(ctx, idx_value), - (duk_tval *) duk_get_tval(ctx, idx_reviver), - (unsigned long) flags, - (duk_tval *) duk_get_tval(ctx, -1), - (long) duk_get_top(ctx))); - - DUK_ASSERT(duk_get_top(ctx) == entry_top + 1); -} - -DUK_INTERNAL -void duk_bi_json_stringify_helper(duk_context *ctx, - duk_idx_t idx_value, - duk_idx_t idx_replacer, - duk_idx_t idx_space, - duk_small_uint_t flags) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_json_enc_ctx js_ctx_alloc; - duk_json_enc_ctx *js_ctx = &js_ctx_alloc; - duk_hobject *h; - duk_bool_t undef; - duk_idx_t idx_holder; - duk_idx_t entry_top; - - /* negative top-relative indices not allowed now */ - DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0); - DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0); - DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0); - - DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld", - (duk_tval *) duk_get_tval(ctx, idx_value), - (duk_tval *) duk_get_tval(ctx, idx_replacer), - (duk_tval *) duk_get_tval(ctx, idx_space), - (unsigned long) flags, - (long) duk_get_top(ctx))); - - entry_top = duk_get_top(ctx); - - /* - * Context init - */ - - DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc)); - js_ctx->thr = thr; -#ifdef DUK_USE_EXPLICIT_NULL_INIT - js_ctx->h_replacer = NULL; - js_ctx->h_gap = NULL; - js_ctx->h_indent = NULL; -#endif - js_ctx->idx_proplist = -1; - - /* Flag handling currently assumes that flags are consistent. This is OK - * because the call sites are now strictly controlled. - */ - - js_ctx->flags = flags; - js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY; - js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES; -#ifdef DUK_USE_JX - js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM; -#endif -#ifdef DUK_USE_JC - js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE; -#endif - - /* The #ifdef clutter here handles the JX/JC enable/disable - * combinations properly. - */ -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) -#if defined(DUK_USE_JX) - if (flags & DUK_JSON_FLAG_EXT_CUSTOM) { - js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED; - js_ctx->stridx_custom_nan = DUK_STRIDX_NAN; - js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY; - js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY; - js_ctx->stridx_custom_function = - (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ? - DUK_STRIDX_JSON_EXT_FUNCTION2 : - DUK_STRIDX_JSON_EXT_FUNCTION1; - } -#endif /* DUK_USE_JX */ -#if defined(DUK_USE_JX) && defined(DUK_USE_JC) - else -#endif /* DUK_USE_JX && DUK_USE_JC */ -#if defined(DUK_USE_JC) - if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) { - js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED; - js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN; - js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF; - js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF; - js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1; - } -#endif /* DUK_USE_JC */ -#endif /* DUK_USE_JX || DUK_USE_JC */ - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | - DUK_JSON_FLAG_EXT_COMPATIBLE)) { - DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */ - } - else -#endif /* DUK_USE_JX || DUK_USE_JC */ - { - js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED | - DUK_TYPE_MASK_POINTER | - DUK_TYPE_MASK_BUFFER | - DUK_TYPE_MASK_LIGHTFUNC; - } - - DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE); - - js_ctx->idx_loop = duk_push_object_internal(ctx); - DUK_ASSERT(js_ctx->idx_loop >= 0); - - /* [ ... buf loop ] */ - - /* - * Process replacer/proplist (2nd argument to JSON.stringify) - */ - - h = duk_get_hobject(ctx, idx_replacer); - if (h != NULL) { - if (DUK_HOBJECT_IS_CALLABLE(h)) { - js_ctx->h_replacer = h; - } else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) { - /* Here the specification requires correct array index enumeration - * which is a bit tricky for sparse arrays (it is handled by the - * enum setup code). We now enumerate ancestors too, although the - * specification is not very clear on whether that is required. - */ - - duk_uarridx_t plist_idx = 0; - duk_small_uint_t enum_flags; - - js_ctx->idx_proplist = duk_push_array(ctx); /* XXX: array internal? */ - - enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY | - DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */ - duk_enum(ctx, idx_replacer, enum_flags); - while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) { - /* [ ... proplist enum_obj key val ] */ - if (duk__enc_allow_into_proplist(duk_get_tval(ctx, -1))) { - /* XXX: duplicates should be eliminated here */ - DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept", - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - duk_to_string(ctx, -1); /* extra coercion of strings is OK */ - duk_put_prop_index(ctx, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */ - plist_idx++; - duk_pop(ctx); - } else { - DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject", - (duk_tval *) duk_get_tval(ctx, -2), - (duk_tval *) duk_get_tval(ctx, -1))); - duk_pop_2(ctx); - } - } - duk_pop(ctx); /* pop enum */ - - /* [ ... proplist ] */ - } - } - - /* [ ... buf loop (proplist) ] */ - - /* - * Process space (3rd argument to JSON.stringify) - */ - - h = duk_get_hobject(ctx, idx_space); - if (h != NULL) { - int c = DUK_HOBJECT_GET_CLASS_NUMBER(h); - if (c == DUK_HOBJECT_CLASS_NUMBER) { - duk_to_number(ctx, idx_space); - } else if (c == DUK_HOBJECT_CLASS_STRING) { - duk_to_string(ctx, idx_space); - } - } - - if (duk_is_number(ctx, idx_space)) { - duk_small_int_t nspace; - /* spaces[] must be static to allow initializer with old compilers like BCC */ - static const char spaces[10] = { - DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, - DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, - DUK_ASC_SPACE, DUK_ASC_SPACE - }; /* XXX: helper */ - - /* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */ - nspace = (duk_small_int_t) duk_to_int_clamped(ctx, idx_space, 0 /*minval*/, 10 /*maxval*/); - DUK_ASSERT(nspace >= 0 && nspace <= 10); - - duk_push_lstring(ctx, spaces, (duk_size_t) nspace); - js_ctx->h_gap = duk_get_hstring(ctx, -1); - DUK_ASSERT(js_ctx->h_gap != NULL); - } else if (duk_is_string(ctx, idx_space)) { - /* XXX: substring in-place at idx_place? */ - duk_dup(ctx, idx_space); - duk_substring(ctx, -1, 0, 10); /* clamp to 10 chars */ - js_ctx->h_gap = duk_get_hstring(ctx, -1); - DUK_ASSERT(js_ctx->h_gap != NULL); - } else { - /* nop */ - } - - if (js_ctx->h_gap != NULL) { - /* if gap is empty, behave as if not given at all */ - if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) { - js_ctx->h_gap = NULL; - } else { - /* set 'indent' only if it will actually increase */ - js_ctx->h_indent = DUK_HTHREAD_STRING_EMPTY_STRING(thr); - } - } - - DUK_ASSERT((js_ctx->h_gap == NULL && js_ctx->h_indent == NULL) || - (js_ctx->h_gap != NULL && js_ctx->h_indent != NULL)); - - /* [ ... buf loop (proplist) (gap) ] */ - - /* - * Fast path: assume no mutation, iterate object property tables - * directly; bail out if that assumption doesn't hold. - */ - -#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) - /* For now fast path is limited to plain JSON (no JX/JC). This would - * be easy to fix but must go through value type handling in the fast - * path. - */ - if (flags == 0 && - js_ctx->h_replacer == NULL && - js_ctx->idx_proplist == -1 && - js_ctx->h_gap == NULL && - js_ctx->h_indent == NULL) { - duk_int_t pcall_rc; -#ifdef DUK_USE_MARK_AND_SWEEP - duk_small_uint_t prev_mark_and_sweep_base_flags; -#endif - - DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path")); - - /* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[] - * array so we don't need two counter checks in the fast path. The - * slow path has a much larger recursion limit which we'll use if - * necessary. - */ - DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY); - js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY; - DUK_ASSERT(js_ctx->recursion_depth == 0); - - /* Execute the fast path in a protected call. If any error is thrown, - * fall back to the slow path. This includes e.g. recursion limit - * because the fast path has a smaller recursion limit (and simpler, - * limited loop detection). - */ - - duk_push_pointer(ctx, (void *) js_ctx); - duk_dup(ctx, idx_value); - -#if defined(DUK_USE_MARK_AND_SWEEP) - /* Must prevent finalizers which may have arbitrary side effects. */ - prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags; - thr->heap->mark_and_sweep_base_flags |= - DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */ - DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact any objects */ -#endif - - pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, 2 /*nargs*/, 0 /*nret*/); - -#if defined(DUK_USE_MARK_AND_SWEEP) - thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags; -#endif - if (pcall_rc == DUK_EXEC_SUCCESS) { - DUK_DD(DUK_DDPRINT("fast path successful")); - DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw); - goto replace_finished; - } - - /* We come here for actual aborts (like encountering .toJSON()) - * but also for recursion/loop errors. Bufwriter size can be - * kept because we'll probably need at least as much as we've - * allocated so far. - */ - DUK_DD(DUK_DDPRINT("fast path failed, serialize using slow path instead")); - DUK_BW_RESET_SIZE(thr, &js_ctx->bw); - js_ctx->recursion_depth = 0; - } -#endif - - /* - * Create wrapper object and serialize - */ - - idx_holder = duk_push_object(ctx); - duk_dup(ctx, idx_value); - duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING); - - DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, " - "proplist=%!T, gap=%!O, indent=%!O, holder=%!T", - (unsigned long) js_ctx->flags, - (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop), - (duk_heaphdr *) js_ctx->h_replacer, - (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL), - (duk_heaphdr *) js_ctx->h_gap, - (duk_heaphdr *) js_ctx->h_indent, - (duk_tval *) duk_get_tval(ctx, -1))); - - /* serialize the wrapper with empty string key */ - - duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); - - /* [ ... buf loop (proplist) (gap) holder "" ] */ - - js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT; - DUK_ASSERT(js_ctx->recursion_depth == 0); - undef = duk__enc_value1(js_ctx, idx_holder); /* [ ... holder key ] -> [ ... holder key val ] */ - - DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, " - "proplist=%!T, gap=%!O, indent=%!O, holder=%!T", - (unsigned long) js_ctx->flags, - (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop), - (duk_heaphdr *) js_ctx->h_replacer, - (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL), - (duk_heaphdr *) js_ctx->h_gap, - (duk_heaphdr *) js_ctx->h_indent, - (duk_tval *) duk_get_tval(ctx, -3))); - - if (undef) { - /* - * Result is undefined - */ - - duk_push_undefined(ctx); - } else { - /* - * Finish and convert buffer to result string - */ - - duk__enc_value2(js_ctx); /* [ ... key val ] -> [ ... ] */ - - DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw); - } - - /* The stack has a variable shape here, so force it to the - * desired one explicitly. - */ - -#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) - replace_finished: -#endif - duk_replace(ctx, entry_top); - duk_set_top(ctx, entry_top + 1); - - DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, " - "flags=0x%08lx, result=%!T, stack_top=%ld", - (duk_tval *) duk_get_tval(ctx, idx_value), - (duk_tval *) duk_get_tval(ctx, idx_replacer), - (duk_tval *) duk_get_tval(ctx, idx_space), - (unsigned long) flags, - (duk_tval *) duk_get_tval(ctx, -1), - (long) duk_get_top(ctx))); - - DUK_ASSERT(duk_get_top(ctx) == entry_top + 1); -} - -/* - * Entry points - */ - -DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_context *ctx) { - duk_bi_json_parse_helper(ctx, - 0 /*idx_value*/, - 1 /*idx_replacer*/, - 0 /*flags*/); - return 1; -} - -DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) { - duk_bi_json_stringify_helper(ctx, - 0 /*idx_value*/, - 1 /*idx_replacer*/, - 2 /*idx_space*/, - 0 /*flags*/); - return 1; -} - -#undef DUK__JSON_DECSTR_BUFSIZE -#undef DUK__JSON_DECSTR_CHUNKSIZE -#undef DUK__JSON_ENCSTR_CHUNKSIZE -#undef DUK__JSON_STRINGIFY_BUFSIZE -#undef DUK__JSON_MAX_ESC_LEN diff --git a/src/third_party/duktape-1.3.0/src-separate/duk_bi_logger.c b/src/third_party/duktape-1.3.0/src-separate/duk_bi_logger.c deleted file mode 100644 index 8be5feac..00000000 --- a/src/third_party/duktape-1.3.0/src-separate/duk_bi_logger.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Logging support - */ - -#include "duk_internal.h" - -/* 3-letter log level strings */ -DUK_LOCAL const duk_uint8_t duk__log_level_strings[] = { - (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_C, - (duk_uint8_t) DUK_ASC_UC_D, (duk_uint8_t) DUK_ASC_UC_B, (duk_uint8_t) DUK_ASC_UC_G, - (duk_uint8_t) DUK_ASC_UC_I, (duk_uint8_t) DUK_ASC_UC_N, (duk_uint8_t) DUK_ASC_UC_F, - (duk_uint8_t) DUK_ASC_UC_W, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_N, - (duk_uint8_t) DUK_ASC_UC_E, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_R, - (duk_uint8_t) DUK_ASC_UC_F, (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_L -}; - -/* Constructor */ -DUK_INTERNAL duk_ret_t duk_bi_logger_constructor(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_idx_t nargs; - - /* Calling as a non-constructor is not meaningful. */ - if (!duk_is_constructor_call(ctx)) { - return DUK_RET_TYPE_ERROR; - } - - nargs = duk_get_top(ctx); - duk_set_top(ctx, 1); - - duk_push_this(ctx); - - /* [ name this ] */ - - if (nargs == 0) { - /* Automatic defaulting of logger name from caller. This would - * work poorly with tail calls, but constructor calls are currently - * never tail calls, so tail calls are not an issue now. - */ - - if (thr->callstack_top >= 2) { - duk_activation *act_caller = thr->callstack + thr->callstack_top - 2; - duk_hobject *func_caller; - - func_caller = DUK_ACT_GET_FUNC(act_caller); - if (func_caller) { - /* Stripping the filename might be a good idea - * ("/foo/bar/quux.js" -> logger name "quux"), - * but now used verbatim. - */ - duk_push_hobject(ctx, func_caller); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME); - duk_replace(ctx, 0); - } - } - } - /* the stack is unbalanced here on purpose; we only rely on the - * initial two values: [ name this ]. - */ - - if (duk_is_string(ctx, 0)) { - duk_dup(ctx, 0); - duk_put_prop_stridx(ctx, 1, DUK_STRIDX_LC_N); - } else { - /* don't set 'n' at all, inherited value is used as name */ - } - - duk_compact(ctx, 1); - - return 0; /* keep default instance */ -} - -/* Default function to format objects. Tries to use toLogString() but falls - * back to toString(). Any errors are propagated out without catching. - */ -DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx) { - if (duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_LOG_STRING)) { - /* [ arg toLogString ] */ - - duk_dup(ctx, 0); - duk_call_method(ctx, 0); - - /* [ arg result ] */ - return 1; - } - - /* [ arg undefined ] */ - duk_pop(ctx); - duk_to_string(ctx, 0); - return 1; -} - -/* Default function to write a formatted log line. Writes to stderr, - * appending a newline to the log line. - * - * The argument is a buffer whose visible size contains the log message. - * This function should avoid coercing the buffer to a string to avoid - * string table traffic. - */ -DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx) { - const char *data; - duk_size_t data_len; - - DUK_UNREF(ctx); - DUK_UNREF(data); - DUK_UNREF(data_len); - -#ifdef DUK_USE_FILE_IO - data = (const char *) duk_require_buffer(ctx, 0, &data_len); - DUK_FWRITE((const void *) data, 1, data_len, DUK_STDERR); - DUK_FPUTC((int) '\n', DUK_STDERR); - DUK_FFLUSH(DUK_STDERR); -#else - /* nop */ -#endif - return 0; -} - -/* Log frontend shared helper, magic value indicates log level. Provides - * frontend functions: trace(), debug(), info(), warn(), error(), fatal(). - * This needs to have small footprint, reasonable performance, minimal - * memory churn, etc. - */ -DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - duk_double_t now; - duk_small_int_t entry_lev = duk_get_current_magic(ctx); - duk_small_int_t logger_lev; - duk_int_t nargs; - duk_int_t i; - duk_size_t tot_len; - const duk_uint8_t *arg_str; - duk_size_t arg_len; - duk_uint8_t *buf, *p; - const duk_uint8_t *q; - duk_uint8_t date_buf[DUK_BI_DATE_ISO8601_BUFSIZE]; - duk_size_t date_len; - duk_small_int_t rc; - - DUK_ASSERT(entry_lev >= 0 && entry_lev <= 5); - DUK_UNREF(thr); - - /* XXX: sanitize to printable (and maybe ASCII) */ - /* XXX: better multiline */ - - /* - * Logger arguments are: - * - * magic: log level (0-5) - * this: logger - * stack: plain log args - * - * We want to minimize memory churn so a two-pass approach - * is used: first pass formats arguments and computes final - * string length, second pass copies strings either into a - * pre-allocated and reused buffer (short messages) or into a - * newly allocated fixed buffer. If the backend function plays - * nice, it won't coerce the buffer to a string (and thus - * intern it). - */ - - nargs = duk_get_top(ctx); - - /* [ arg1 ... argN this ] */ - - /* - * Log level check - */ - - duk_push_this(ctx); - - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LC_L); - logger_lev = (duk_small_int_t) duk_get_int(ctx, -1); - if (entry_lev < logger_lev) { - return 0; - } - /* log level could be popped but that's not necessary */ - - now = DUK_USE_DATE_GET_NOW(ctx); - duk_bi_date_format_timeval(now, date_buf); - date_len = DUK_STRLEN((const char *) date_buf); - - duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LC_N); - duk_to_string(ctx, -1); - DUK_ASSERT(duk_is_string(ctx, -1)); - - /* [ arg1 ... argN this loggerLevel loggerName ] */ - - /* - * Pass 1 - */ - - /* Line format: