فهرست منبع

Update to Duktape 1.5.2

bel 8 سال پیش
والد
کامیت
95aeb2705b
100فایلهای تغییر یافته به همراه31120 افزوده شده و 9 حذف شده
  1. 9 9
      resources/Makefile.in-duktape
  2. 72 0
      src/third_party/duktape-1.5.2/AUTHORS.rst
  3. 25 0
      src/third_party/duktape-1.5.2/LICENSE.txt
  4. 34 0
      src/third_party/duktape-1.5.2/Makefile.cmdline
  5. 4 0
      src/third_party/duktape-1.5.2/Makefile.codepage
  6. 4 0
      src/third_party/duktape-1.5.2/Makefile.coffee
  7. 26 0
      src/third_party/duktape-1.5.2/Makefile.dukdebug
  8. 7 0
      src/third_party/duktape-1.5.2/Makefile.eval
  9. 22 0
      src/third_party/duktape-1.5.2/Makefile.eventloop
  10. 35 0
      src/third_party/duktape-1.5.2/Makefile.hello
  11. 8 0
      src/third_party/duktape-1.5.2/Makefile.jxpretty
  12. 7 0
      src/third_party/duktape-1.5.2/Makefile.sandbox
  13. 71 0
      src/third_party/duktape-1.5.2/Makefile.sharedlibrary
  14. 110 0
      src/third_party/duktape-1.5.2/README.rst
  15. 39 0
      src/third_party/duktape-1.5.2/config/README.rst
  16. 3415 0
      src/third_party/duktape-1.5.2/config/duk_config.h-modular-dll
  17. 3415 0
      src/third_party/duktape-1.5.2/config/duk_config.h-modular-static
  18. 1537 0
      src/third_party/duktape-1.5.2/config/genconfig.py
  19. BIN
      src/third_party/duktape-1.5.2/config/genconfig_metadata.tar.gz
  20. 101 0
      src/third_party/duktape-1.5.2/debugger/Makefile
  21. 384 0
      src/third_party/duktape-1.5.2/debugger/README.rst
  22. 32 0
      src/third_party/duktape-1.5.2/debugger/duk_classnames.yaml
  23. 2473 0
      src/third_party/duktape-1.5.2/debugger/duk_debug.js
  24. 1497 0
      src/third_party/duktape-1.5.2/debugger/duk_debug_meta.json
  25. 1029 0
      src/third_party/duktape-1.5.2/debugger/duk_debug_proxy.js
  26. 52 0
      src/third_party/duktape-1.5.2/debugger/duk_debugcommands.yaml
  27. 6 0
      src/third_party/duktape-1.5.2/debugger/duk_debugerrors.yaml
  28. 658 0
      src/third_party/duktape-1.5.2/debugger/duk_opcodes.yaml
  29. 32 0
      src/third_party/duktape-1.5.2/debugger/merge_debug_meta.py
  30. 27 0
      src/third_party/duktape-1.5.2/debugger/package.json
  31. 96 0
      src/third_party/duktape-1.5.2/debugger/static/index.html
  32. 516 0
      src/third_party/duktape-1.5.2/debugger/static/style.css
  33. 785 0
      src/third_party/duktape-1.5.2/debugger/static/webui.js
  34. 1349 0
      src/third_party/duktape-1.5.2/duk_build_meta.json
  35. 10 0
      src/third_party/duktape-1.5.2/examples/README.rst
  36. 10 0
      src/third_party/duktape-1.5.2/examples/alloc-hybrid/README.rst
  37. 293 0
      src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.c
  38. 11 0
      src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.h
  39. 7 0
      src/third_party/duktape-1.5.2/examples/alloc-logging/README.rst
  40. 138 0
      src/third_party/duktape-1.5.2/examples/alloc-logging/duk_alloc_logging.c
  41. 10 0
      src/third_party/duktape-1.5.2/examples/alloc-logging/duk_alloc_logging.h
  42. 41 0
      src/third_party/duktape-1.5.2/examples/alloc-logging/log2gnuplot.py
  43. 10 0
      src/third_party/duktape-1.5.2/examples/alloc-torture/README.rst
  44. 182 0
      src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.c
  45. 10 0
      src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.h
  46. 6 0
      src/third_party/duktape-1.5.2/examples/cmdline/README.rst
  47. 1463 0
      src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline.c
  48. 1008 0
      src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline_ajduk.c
  49. 8 0
      src/third_party/duktape-1.5.2/examples/codepage-conv/README.rst
  50. 54 0
      src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.c
  51. 8 0
      src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.h
  52. 286 0
      src/third_party/duktape-1.5.2/examples/codepage-conv/test.c
  53. 10 0
      src/third_party/duktape-1.5.2/examples/coffee/README.rst
  54. 7 0
      src/third_party/duktape-1.5.2/examples/coffee/globals.coffee
  55. 2 0
      src/third_party/duktape-1.5.2/examples/coffee/hello.coffee
  56. 28 0
      src/third_party/duktape-1.5.2/examples/coffee/mandel.coffee
  57. 29 0
      src/third_party/duktape-1.5.2/examples/cpp-exceptions/README.rst
  58. 274 0
      src/third_party/duktape-1.5.2/examples/cpp-exceptions/cpp_exceptions.cpp
  59. 17 0
      src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/Makefile
  60. 8 0
      src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/README.rst
  61. 1239 0
      src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.c
  62. 113 0
      src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.h
  63. 236 0
      src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/test.c
  64. 17 0
      src/third_party/duktape-1.5.2/examples/debug-trans-socket/README.rst
  65. 15 0
      src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket.h
  66. 340 0
      src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_unix.c
  67. 414 0
      src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_windows.c
  68. 5 0
      src/third_party/duktape-1.5.2/examples/dummy-date-provider/README.rst
  69. 27 0
      src/third_party/duktape-1.5.2/examples/dummy-date-provider/dummy_date_provider.c
  70. 5 0
      src/third_party/duktape-1.5.2/examples/eval/README.rst
  71. 48 0
      src/third_party/duktape-1.5.2/examples/eval/eval.c
  72. 76 0
      src/third_party/duktape-1.5.2/examples/eventloop/README.rst
  73. 17 0
      src/third_party/duktape-1.5.2/examples/eventloop/basic-test.js
  74. 618 0
      src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.c
  75. 179 0
      src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.js
  76. 24 0
      src/third_party/duktape-1.5.2/examples/eventloop/client-socket-test.js
  77. 79 0
      src/third_party/duktape-1.5.2/examples/eventloop/curses-timers.js
  78. 466 0
      src/third_party/duktape-1.5.2/examples/eventloop/ecma_eventloop.js
  79. 69 0
      src/third_party/duktape-1.5.2/examples/eventloop/fileio.c
  80. 256 0
      src/third_party/duktape-1.5.2/examples/eventloop/main.c
  81. 105 0
      src/third_party/duktape-1.5.2/examples/eventloop/ncurses.c
  82. 111 0
      src/third_party/duktape-1.5.2/examples/eventloop/poll.c
  83. 34 0
      src/third_party/duktape-1.5.2/examples/eventloop/server-socket-test.js
  84. 286 0
      src/third_party/duktape-1.5.2/examples/eventloop/socket.c
  85. 5 0
      src/third_party/duktape-1.5.2/examples/guide/README.rst
  86. 16 0
      src/third_party/duktape-1.5.2/examples/guide/fib.js
  87. 32 0
      src/third_party/duktape-1.5.2/examples/guide/prime.js
  88. 52 0
      src/third_party/duktape-1.5.2/examples/guide/primecheck.c
  89. 12 0
      src/third_party/duktape-1.5.2/examples/guide/process.js
  90. 59 0
      src/third_party/duktape-1.5.2/examples/guide/processlines.c
  91. 42 0
      src/third_party/duktape-1.5.2/examples/guide/uppercase.c
  92. 5 0
      src/third_party/duktape-1.5.2/examples/hello/README.rst
  93. 38 0
      src/third_party/duktape-1.5.2/examples/hello/hello.c
  94. 5 0
      src/third_party/duktape-1.5.2/examples/jxpretty/README.rst
  95. 63 0
      src/third_party/duktape-1.5.2/examples/jxpretty/jxpretty.c
  96. 5 0
      src/third_party/duktape-1.5.2/examples/sandbox/README.rst
  97. 252 0
      src/third_party/duktape-1.5.2/examples/sandbox/sandbox.c
  98. 13 0
      src/third_party/duktape-1.5.2/extras/README.rst
  99. 3933 0
      src/third_party/duktape-1.5.2/license.spdx
  100. 2 0
      src/third_party/duktape-1.5.2/licenses/commonjs.txt

+ 9 - 9
resources/Makefile.in-duktape

@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015 the Civetweb developers
+# Copyright (c) 2015-2016 the Civetweb developers
 #
 # License http://opensource.org/licenses/mit-license.php MIT License
 #
@@ -8,16 +8,16 @@ ifndef WITH_DUKTAPE
   $(error WITH_DUKTAPE is not defined)
 endif
 
-# Duktape default version is 1.3.0 (103)
-WITH_DUKTAPE_VERSION ?= 103
+# Duktape default version is 1.5.2 (105)
+WITH_DUKTAPE_VERSION ?= 105
 DUKTAPE_VERSION_KNOWN = 0
 
 # Select src and header according to the Duktape version
-ifeq ($(WITH_DUKTAPE_VERSION), 103)
-  $(info Duktape: Using version 1.3.0)
-  DUKTAPE_DIR = src/third_party/duktape-1.3.0/src
-  DUKTAPE_SHARED_LIB_FLAG = -lduktape1.3
-  DUKTAPE_CFLAGS = -DDUKTAPE_VERSION_MAKEFILE=501
+ifeq ($(WITH_DUKTAPE_VERSION), 105)
+  $(info Duktape: Using version 1.5.2)
+  DUKTAPE_DIR = src/third_party/duktape-1.5.2/src
+  DUKTAPE_SHARED_LIB_FLAG = -lduktape1.5
+  DUKTAPE_CFLAGS = -DDUKTAPE_VERSION_MAKEFILE=105
   DUKTAPE_VERSION_KNOWN = 1
 endif
 
@@ -44,7 +44,7 @@ else
   DUKTAPE_SOURCE_FILES = duktape.c
 
 ifeq ($(WITH_DUKTAPE_VERSION), 104)
-#    DUKTAPE_SOURCE_FILES +=
+#    DUKTAPE_SOURCE_FILES += ... TODO ...
 endif
 
   $(info Duktape: using static library)

+ 72 - 0
src/third_party/duktape-1.5.2/AUTHORS.rst

@@ -0,0 +1,72 @@
+===============
+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 <sami.vaarala@iki.fi>
+* Niki Dobrev
+* Andreas Öman <andreas@lonelycoder.com>
+* László Langó <llango.u-szeged@partner.samsung.com>
+* Legimet <legimet.calc@gmail.com>
+* Karl Skomski <karl@skomski.com>
+* Bruce Pascoe <fatcerberus1@gmail.com>
+* René Hollander <rene@rene8888.at>
+* Julien Hamaide (https://github.com/crazyjul)
+* Sebastian Götte (https://github.com/jaseg)
+
+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
+* Laurent Zubiaur (https://github.com/lzubiaur)
+* Ole André Vadla Ravnås (https://github.com/oleavr)
+
+If you are accidentally missing from this list, send me an e-mail
+(``sami.vaarala@iki.fi``) and I'll fix the omission.

+ 25 - 0
src/third_party/duktape-1.5.2/LICENSE.txt

@@ -0,0 +1,25 @@
+===============
+Duktape license
+===============
+
+(http://opensource.org/licenses/MIT)
+
+Copyright (c) 2013-2016 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.

+ 34 - 0
src/third_party/duktape-1.5.2/Makefile.cmdline

@@ -0,0 +1,34 @@
+#
+#  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 want linenoise, you can enable these.  At the moment linenoise
+# will cause some harmless compilation warnings.
+#CCOPTS += -DDUK_CMDLINE_FANCY
+#DUKTAPE_CMDLINE_SOURCES += linenoise/linenoise.c
+#CCOPTS += -I./linenoise
+#duk:	linenoise
+
+# 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)
+
+linenoise/linenoise.c: linenoise
+linenoise:
+	git clone https://github.com/antirez/linenoise.git

+ 4 - 0
src/third_party/duktape-1.5.2/Makefile.codepage

@@ -0,0 +1,4 @@
+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

+ 4 - 0
src/third_party/duktape-1.5.2/Makefile.coffee

@@ -0,0 +1,4 @@
+dummy:
+	coffee -c examples/coffee/globals.coffee
+	coffee -c examples/coffee/hello.coffee
+	coffee -c examples/coffee/mandel.coffee

+ 26 - 0
src/third_party/duktape-1.5.2/Makefile.dukdebug

@@ -0,0 +1,26 @@
+#
+#  Duktape command line tool with debugger support.
+#
+
+DUKTAPE_SOURCES = src/duktape.c
+
+# Windows (MinGW): use examples/debug-trans-socket/duk_trans_socket_windows.c
+# and link with -lws2_32.
+DUKTAPE_CMDLINE_SOURCES = \
+	examples/cmdline/duk_cmdline.c \
+	examples/debug-trans-socket/duk_trans_socket_unix.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
+CCOPTS += -DDUK_OPT_DEBUGGER_INSPECT
+CCLIBS	= -lm
+
+duk:	$(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES)
+	$(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS)

+ 7 - 0
src/third_party/duktape-1.5.2/Makefile.eval

@@ -0,0 +1,7 @@
+#
+#  Example Makefile for building the eval example
+#
+
+eval:
+	gcc -o $@ -std=c99 -O2 -Wall -Wextra -Isrc/ \
+		src/duktape.c examples/eval/eval.c -lm

+ 22 - 0
src/third_party/duktape-1.5.2/Makefile.eventloop

@@ -0,0 +1,22 @@
+#
+#  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"

+ 35 - 0
src/third_party/duktape-1.5.2/Makefile.hello

@@ -0,0 +1,35 @@
+#
+#  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)

+ 8 - 0
src/third_party/duktape-1.5.2/Makefile.jxpretty

@@ -0,0 +1,8 @@
+#
+#  Example Makefile for building the jxpretty example
+#
+
+jxpretty:
+	gcc -o $@ -std=c99 -Wall -Wextra -O2 -Isrc \
+		src/duktape.c examples/jxpretty/jxpretty.c \
+		-lm

+ 7 - 0
src/third_party/duktape-1.5.2/Makefile.sandbox

@@ -0,0 +1,7 @@
+#
+#  Example Makefile for building the sandbox example
+#
+
+sandbox:
+	gcc -o $@ -std=c99 -O2 -Wall -Wextra -Isrc/ \
+		src/duktape.c examples/sandbox/sandbox.c -lm

+ 71 - 0
src/third_party/duktape-1.5.2/Makefile.sharedlibrary

@@ -0,0 +1,71 @@
+#
+#  Example of how to build and install locally as a shared library
+#
+#  Usage:
+#
+#    $ make -f Makefile.sharedlibrary
+#    $ sudo make -f Makefile.sharedlibrary install
+#    $ make -f Makefile.sharedlibrary duk  # --> example 'duk' linked to shared libduktape
+#
+#    $ ls -l duk
+#    -rwxrwxr-x 1 duktape duktape 19407 Nov 30 15:48 duk
+#
+#    $ ldd ./duk
+#            linux-vdso.so.1 =>  (0x00007ffd5ed3c000)
+#            libduktape.so.104 => /usr/local/lib/libduktape.so.104 (0x00007fb2f9753000)
+#            libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb2f944d000)
+#            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb2f9088000)
+#            /lib64/ld-linux-x86-64.so.2 (0x00007fb2f9991000)
+#
+#  Based on: http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
+
+# Soname version must be bumped whenever a binary compatibility change occurs
+# (and should not be bumped when the library is compatible).  A simple Duktape
+# convention is to set soname version to (100*MAJOR + MINOR), e.g. 104 for
+# Duktape 1.4.x, so that it gets automatically bumped for major and minor
+# releases (potentially binary incompatible), but not for patch releases.
+DUK_VERSION=10502
+SONAME_VERSION=105
+REAL_VERSION=$(SONAME_VERSION).$(DUK_VERSION)
+
+# Change to actual path for actual distribution packaging.
+INSTALL_PREFIX=/usr/local
+
+# The 'noline' variant may be more appropriate for some distributions; it
+# doesn't have #line directives in the combined source.
+DUKTAPE_SRCDIR=./src
+#DUKTAPE_SRCDIR=./src-noline
+
+.PHONY: all
+all: libduktape.so.$(REAL_VERSION) libduktaped.so.$(REAL_VERSION)
+
+# If the default duk_config.h is not suitable for the distribution, modify it
+# before compiling the shared library and copy the same, edited duk_config.h
+# to $INSTALL_PREFIX/include on installation.
+
+libduktape.so.$(REAL_VERSION):
+	gcc -shared -fPIC -Wall -Wextra -Os -Wl,-soname,libduktape.so.$(SONAME_VERSION) \
+		-o $@ $(DUKTAPE_SRCDIR)/duktape.c
+
+libduktaped.so.$(REAL_VERSION):
+	gcc -shared -fPIC -g -Wall -Wextra -Os -Wl,-soname,libduktaped.so.$(SONAME_VERSION) \
+		-o $@ $(DUKTAPE_SRCDIR)/duktape.c
+
+# Symlinks depend on platform conventions.
+.PHONY: install
+install: libduktape.so.$(REAL_VERSION) libduktaped.so.$(REAL_VERSION)
+	cp $+ $(INSTALL_PREFIX)/lib/
+	rm -f $(INSTALL_PREFIX)/lib/libduktape.so $(INSTALL_PREFIX)/lib/libduktape.so.$(SONAME_VERSION)
+	ln -s libduktape.so.$(REAL_VERSION) $(INSTALL_PREFIX)/lib/libduktape.so
+	ln -s libduktape.so.$(REAL_VERSION) $(INSTALL_PREFIX)/lib/libduktape.so.$(SONAME_VERSION)
+	rm -f $(INSTALL_PREFIX)/lib/libduktaped.so $(INSTALL_PREFIX)/lib/libduktaped.so.$(SONAME_VERSION)
+	ln -s libduktaped.so.$(REAL_VERSION) $(INSTALL_PREFIX)/lib/libduktaped.so
+	ln -s libduktaped.so.$(REAL_VERSION) $(INSTALL_PREFIX)/lib/libduktaped.so.$(SONAME_VERSION)
+	cp $(DUKTAPE_SRCDIR)/duktape.h $(DUKTAPE_SRCDIR)/duk_config.h $(INSTALL_PREFIX)/include/
+
+# Note: assumes /usr/local/include/ and /usr/local/lib/ are in include/link
+# path which may not be the case for all distributions.
+#CCOPTS=-I/usr/local/include -L/usr/local/lib
+CCOPTS=
+duk:
+	gcc $(CCOPTS) -Wall -Wextra -Os -o $@ ./examples/cmdline/duk_cmdline.c -lduktape -lm

+ 110 - 0
src/third_party/duktape-1.5.2/README.rst

@@ -0,0 +1,110 @@
+=======
+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 <dist_root>
+  $ make -f Makefile.hello
+  [...]
+  $ ./hello
+  Hello world!
+  2+3=5
+
+To build an example command line tool, use the following::
+
+  $ cd <dist_root>
+  $ 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-noline/``: contains a variant of ``src/duktape.c`` with no ``#line``
+  directives which is preferable for some users.  See discussion in
+  https://github.com/svaarala/duktape/pull/363.
+
+* ``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.  Also contains a JSON debug proxy
+  (one written in Node.js and another in DukLuv) to make talking to the
+  debug target easier.
+
+* ``licenses/``: licensing information.
+
+You can find release notes at:
+
+* https://github.com/svaarala/duktape/blob/master/RELEASES.rst
+
+This distributable contains Duktape version 1.5.2, created from git
+commit cad34ae155acb0846545ca6bf2d29f9463b22bbb (v1.5.2).
+
+Duktape is copyrighted by its authors (see ``AUTHORS.rst``) and licensed
+under the MIT license (see ``LICENSE.txt``).  String hashing algorithms are
+based on the algorithm from Lua (MIT license), djb2 hash, and Murmurhash2
+(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)

+ 39 - 0
src/third_party/duktape-1.5.2/config/README.rst

@@ -0,0 +1,39 @@
+=================
+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.

+ 3415 - 0
src/third_party/duktape-1.5.2/config/duk_config.h-modular-dll

@@ -0,0 +1,3415 @@
+/*
+ *  duk_config.h configuration header generated by genconfig.py.
+ *
+ *  Git commit: cad34ae155acb0846545ca6bf2d29f9463b22bbb
+ *  Git describe: v1.5.2
+ *  Git branch: HEAD
+ *
+ *  Supported platforms:
+ *      - Mac OSX, iPhone, Darwin
+ *      - OpenBSD
+ *      - Generic BSD
+ *      - Atari ST TOS
+ *      - AmigaOS
+ *      - Windows
+ *      - Flashplayer (Crossbridge)
+ *      - QNX
+ *      - TI-Nspire
+ *      - Emscripten
+ *      - Linux
+ *      - Solaris
+ *      - Generic POSIX
+ *      - Cygwin
+ *      - Generic UNIX
+ *      - Generic fallback
+ *
+ *  Supported architectures:
+ *      - x86
+ *      - x64
+ *      - x32
+ *      - ARM 32-bit
+ *      - ARM 64-bit
+ *      - MIPS 32-bit
+ *      - MIPS 64-bit
+ *      - PowerPC 32-bit
+ *      - PowerPC 64-bit
+ *      - SPARC 32-bit
+ *      - SPARC 64-bit
+ *      - SuperH
+ *      - Motorola 68k
+ *      - Emscripten
+ *      - Generic
+ *
+ *  Supported compilers:
+ *      - Clang
+ *      - GCC
+ *      - MSVC
+ *      - Emscripten
+ *      - TinyC
+ *      - VBCC
+ *      - Bruce's C compiler
+ *      - Generic
+ *
+ */
+
+#if !defined(DUK_CONFIG_H_INCLUDED)
+#define DUK_CONFIG_H_INCLUDED
+
+/*
+ *  Intermediate helper defines
+ */
+
+/* DLL build detection */
+#if defined(DUK_OPT_DLL_BUILD)
+#define DUK_F_DLL_BUILD
+#elif defined(DUK_OPT_NO_DLL_BUILD)
+#undef DUK_F_DLL_BUILD
+#else
+/* configured for DLL build */
+#define DUK_F_DLL_BUILD
+#endif
+
+/* Apple OSX, iOS */
+#if defined(__APPLE__)
+#define DUK_F_APPLE
+#endif
+
+/* OpenBSD */
+#if defined(__OpenBSD__) || defined(__OpenBSD)
+#define DUK_F_OPENBSD
+#endif
+
+/* NetBSD */
+#if defined(__NetBSD__) || defined(__NetBSD)
+#define DUK_F_NETBSD
+#endif
+
+/* FreeBSD */
+#if defined(__FreeBSD__) || defined(__FreeBSD)
+#define DUK_F_FREEBSD
+#endif
+
+/* BSD variant */
+#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \
+    defined(__bsdi__) || defined(__DragonFly__)
+#define DUK_F_BSD
+#endif
+
+/* Atari ST TOS.  __TOS__ defined by PureC.  No platform define in VBCC
+ * apparently, so to use with VBCC user must define __TOS__ manually.
+  */
+#if defined(__TOS__)
+#define DUK_F_TOS
+#endif
+
+/* Motorola 68K.  Not defined by VBCC, so user must define one of these
+ * manually when using VBCC.
+ */
+#if defined(__m68k__) || defined(M68000) || defined(__MC68K__)
+#define DUK_F_M68K
+#endif
+
+/* AmigaOS.  Neither AMIGA nor __amigaos__ is defined on VBCC, so user must
+ * define 'AMIGA' manually when using VBCC.
+ */
+#if defined(AMIGA) || defined(__amigaos__)
+#define DUK_F_AMIGAOS
+#endif
+
+/* PowerPC */
+#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__)
+#define DUK_F_PPC
+#if defined(__PPC64__) || defined(__LP64__) || defined(_LP64)
+#define DUK_F_PPC64
+#else
+#define DUK_F_PPC32
+#endif
+#endif
+
+/* Windows, both 32-bit and 64-bit */
+#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \
+    defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
+#define DUK_F_WINDOWS
+#if defined(_WIN64) || defined(WIN64)
+#define DUK_F_WIN64
+#else
+#define DUK_F_WIN32
+#endif
+#endif
+
+/* Flash player (e.g. Crossbridge) */
+#if defined(__FLASHPLAYER__)
+#define DUK_F_FLASHPLAYER
+#endif
+
+/* QNX */
+#if defined(__QNX__)
+#define DUK_F_QNX
+#endif
+
+/* TI-Nspire (using Ndless) */
+#if defined(_TINSPIRE)
+#define DUK_F_TINSPIRE
+#endif
+
+/* Emscripten (provided explicitly by user), improve if possible */
+#if defined(EMSCRIPTEN)
+#define DUK_F_EMSCRIPTEN
+#endif
+
+/* BCC (Bruce's C compiler): this is a "torture target" for compilation */
+#if defined(__BCC__) || defined(__BCC_VERSION__)
+#define DUK_F_BCC
+#endif
+
+/* Linux */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+#define DUK_F_LINUX
+#endif
+
+/* illumos / Solaris */
+#if defined(__sun) && defined(__SVR4)
+#define DUK_F_SUN
+#endif
+
+/* POSIX */
+#if defined(__posix)
+#define DUK_F_POSIX
+#endif
+
+/* Cygwin */
+#if defined(__CYGWIN__)
+#define DUK_F_CYGWIN
+#endif
+
+/* Generic Unix (includes Cygwin) */
+#if defined(__unix) || defined(__unix__) || defined(unix) || \
+    defined(DUK_F_LINUX) || defined(DUK_F_BSD)
+#define DUK_F_UNIX
+#endif
+
+/* stdint.h not available */
+#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
+#if (_MSC_VER < 1700)
+/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
+#define DUK_F_NO_STDINT_H
+#endif
+#endif
+#if !defined(DUK_F_NO_STDINT_H) && (defined(DUK_F_TOS) || defined(DUK_F_BCC))
+#define DUK_F_NO_STDINT_H
+#endif
+
+/* C++ */
+#undef DUK_F_CPP
+#if defined(__cplusplus)
+#define DUK_F_CPP
+#endif
+
+/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),
+ * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.
+ * https://sites.google.com/site/x32abi/
+ */
+#if defined(__amd64__) || defined(__amd64) || \
+    defined(__x86_64__) || defined(__x86_64) || \
+    defined(_M_X64) || defined(_M_AMD64)
+#if defined(__ILP32__) || defined(_ILP32)
+#define DUK_F_X32
+#else
+#define DUK_F_X64
+#endif
+#elif defined(i386) || defined(__i386) || defined(__i386__) || \
+      defined(__i486__) || defined(__i586__) || defined(__i686__) || \
+      defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \
+      defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)
+#if defined(__LP64__) || defined(_LP64)
+/* This should not really happen, but would indicate x64. */
+#define DUK_F_X64
+#else
+#define DUK_F_X86
+#endif
+#endif
+
+/* ARM */
+#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM)
+#define DUK_F_ARM
+#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__)
+#define DUK_F_ARM64
+#else
+#define DUK_F_ARM32
+#endif
+#endif
+
+/* MIPS.  Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */
+#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \
+    defined(_R3000) || defined(_R4000) || defined(_R5900) || \
+    defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \
+    defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \
+    defined(__mips) || defined(__MIPS__)
+#define DUK_F_MIPS
+#if defined(__LP64__) || defined(_LP64) || defined(__mips64) || \
+    defined(__mips64__) || defined(__mips_n64)
+#define DUK_F_MIPS64
+#else
+#define DUK_F_MIPS32
+#endif
+#endif
+
+/* SPARC */
+#if defined(sparc) || defined(__sparc) || defined(__sparc__)
+#define DUK_F_SPARC
+#if defined(__LP64__) || defined(_LP64)
+#define DUK_F_SPARC64
+#else
+#define DUK_F_SPARC32
+#endif
+#endif
+
+/* SuperH */
+#if defined(__sh__) || \
+    defined(__sh1__) || defined(__SH1__) || \
+    defined(__sh2__) || defined(__SH2__) || \
+    defined(__sh3__) || defined(__SH3__) || \
+    defined(__sh4__) || defined(__SH4__) || \
+    defined(__sh5__) || defined(__SH5__)
+#define DUK_F_SUPERH
+#endif
+
+/* Clang */
+#if defined(__clang__)
+#define DUK_F_CLANG
+#endif
+
+/* C99 or above */
+#undef DUK_F_C99
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define DUK_F_C99
+#endif
+
+/* C++11 or above */
+#undef DUK_F_CPP11
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+#define DUK_F_CPP11
+#endif
+
+/* GCC.  Clang also defines __GNUC__ so don't detect GCC if using Clang. */
+#if defined(__GNUC__) && !defined(__clang__) && !defined(DUK_F_CLANG)
+#define DUK_F_GCC
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */
+#define DUK_F_GCC_VERSION  (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
+#else
+#error cannot figure out gcc version
+#endif
+#endif
+
+/* MinGW.  Also GCC flags (DUK_F_GCC) are enabled now. */
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define DUK_F_MINGW
+#endif
+
+/* MSVC */
+#if defined(_MSC_VER)
+/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+ * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g.
+ * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp
+ */
+#define DUK_F_MSVC
+#if defined(_MSC_FULL_VER)
+#if (_MSC_FULL_VER > 100000000)
+#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER
+#else
+#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10)
+#endif
+#endif
+#endif  /* _MSC_VER */
+
+/* TinyC */
+#if defined(__TINYC__)
+/* http://bellard.org/tcc/tcc-doc.html#SEC9 */
+#define DUK_F_TINYC
+#endif
+
+/* VBCC */
+#if defined(__VBCC__)
+#define DUK_F_VBCC
+#endif
+
+/* Atari Mint */
+#if defined(__MINT__)
+#define DUK_F_MINT
+#endif
+
+/*
+ *  Platform autodetection
+ */
+
+/* Workaround for older C++ compilers before including <inttypes.h>,
+ * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366
+ */
+#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
+#define __STDC_LIMIT_MACROS
+#endif
+#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined(DUK_F_APPLE)
+/* --- Mac OSX, iPhone, Darwin --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <TargetConditionals.h>
+#include <architecture/byte_order.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */
+#if TARGET_IPHONE_SIMULATOR
+#define DUK_USE_OS_STRING "iphone-sim"
+#elif TARGET_OS_IPHONE
+#define DUK_USE_OS_STRING "iphone"
+#elif TARGET_OS_MAC
+#define DUK_USE_OS_STRING "osx"
+#else
+#define DUK_USE_OS_STRING "osx-unknown"
+#endif
+
+/* Use _setjmp() on Apple by default, see GH-55. */
+#define DUK_JMPBUF_TYPE       jmp_buf
+#define DUK_SETJMP(jb)        _setjmp((jb))
+#define DUK_LONGJMP(jb)       _longjmp((jb), 1)
+#elif defined(DUK_F_OPENBSD)
+/* --- OpenBSD --- */
+/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "openbsd"
+#elif defined(DUK_F_BSD)
+/* --- Generic BSD --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "bsd"
+#elif defined(DUK_F_TOS)
+/* --- Atari ST TOS --- */
+#define DUK_USE_DATE_NOW_TIME
+#define DUK_USE_DATE_TZO_GMTIME
+/* no parsing (not an error) */
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "tos"
+
+/* TOS on M68K is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_M68K)
+#define DUK_USE_BYTEORDER 3
+#endif
+#elif defined(DUK_F_AMIGAOS)
+/* --- AmigaOS --- */
+#if defined(DUK_F_M68K)
+/* AmigaOS on M68k */
+#define DUK_USE_DATE_NOW_TIME
+#define DUK_USE_DATE_TZO_GMTIME
+/* no parsing (not an error) */
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#elif defined(DUK_F_PPC)
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#ifndef UINTPTR_MAX
+#define UINTPTR_MAX UINT_MAX
+#endif
+#else
+#error AmigaOS but not M68K/PPC, not supported now
+#endif
+
+#define DUK_USE_OS_STRING "amigaos"
+
+/* AmigaOS on M68K or PPC is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && (defined(DUK_F_M68K) || defined(DUK_F_PPC))
+#define DUK_USE_BYTEORDER 3
+#endif
+#elif defined(DUK_F_WINDOWS)
+/* --- Windows --- */
+/* Initial fix: disable secure CRT related warnings when compiling Duktape
+ * itself (must be defined before including Windows headers).  Don't define
+ * for user code including duktape.h.
+ */
+#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Windows 32-bit and 64-bit are currently the same. */
+/* MSVC does not have sys/param.h */
+#define DUK_USE_DATE_NOW_WINDOWS
+#define DUK_USE_DATE_TZO_WINDOWS
+/* Note: PRS and FMT are intentionally left undefined for now.  This means
+ * there is no platform specific date parsing/formatting but there is still
+ * the ISO 8601 standard format.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+/* Only include when compiling Duktape to avoid polluting application build
+ * with a lot of unnecessary defines.
+ */
+#include <windows.h>
+#endif
+
+#define DUK_USE_OS_STRING "windows"
+
+/* On Windows, assume we're little endian.  Even Itanium which has a
+ * configurable endianness runs little endian in Windows.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#elif defined(DUK_F_FLASHPLAYER)
+/* --- Flashplayer (Crossbridge) --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "flashplayer"
+
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_FLASHPLAYER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#elif defined(DUK_F_QNX)
+/* --- QNX --- */
+#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)
+/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */
+#define _XOPEN_SOURCE    600
+#define _POSIX_C_SOURCE  200112L
+#endif
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "qnx"
+#elif defined(DUK_F_TINSPIRE)
+/* --- TI-Nspire --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "tinspire"
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE  200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h */
+#else
+#include <endian.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdint.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "emscripten"
+#elif defined(DUK_F_LINUX)
+/* --- Linux --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE  200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h or stdint.h */
+#else
+#include <endian.h>
+#include <stdint.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "linux"
+#elif defined(DUK_F_SUN)
+/* --- Solaris --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#include <sys/types.h>
+#include <ast/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "solaris"
+#elif defined(DUK_F_POSIX)
+/* --- Generic POSIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "posix"
+#elif defined(DUK_F_CYGWIN)
+/* --- Cygwin --- */
+/* don't use strptime() for now */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_JMPBUF_TYPE       jmp_buf
+#define DUK_SETJMP(jb)        _setjmp((jb))
+#define DUK_LONGJMP(jb)       _longjmp((jb), 1)
+
+#define DUK_USE_OS_STRING "windows"
+#elif defined(DUK_F_UNIX)
+/* --- Generic UNIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#include <sys/time.h>
+#define DUK_USE_OS_STRING "unknown"
+#else
+/* --- Generic fallback --- */
+/* The most portable current time provider is time(), but it only has a
+ * one second resolution.
+ */
+#define DUK_USE_DATE_NOW_TIME
+
+/* The most portable way to figure out local time offset is gmtime(),
+ * but it's not thread safe so use with caution.
+ */
+#define DUK_USE_DATE_TZO_GMTIME
+
+/* Avoid custom date parsing and formatting for portability. */
+#undef DUK_USE_DATE_PRS_STRPTIME
+#undef DUK_USE_DATE_FMT_STRFTIME
+
+/* Rely on C89 headers only; time.h must be here. */
+#include <time.h>
+
+#define DUK_USE_OS_STRING "unknown"
+#endif  /* autodetect platform */
+
+/* Shared includes: C89 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>  /* varargs */
+#include <setjmp.h>
+#include <stddef.h>  /* e.g. ptrdiff_t */
+#include <math.h>
+#include <limits.h>
+
+/* date.h is omitted, and included per platform */
+
+/* Shared includes: stdint.h is C99 */
+#if defined(DUK_F_NO_STDINT_H)
+/* stdint.h not available */
+#else
+/* Technically C99 (C++11) but found in many systems.  On some systems
+ * __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS must be defined before
+ * including stdint.h (see above).
+ */
+#include <stdint.h>
+#endif
+
+#if defined(DUK_F_CPP)
+#include <exception>  /* std::exception */
+#endif
+
+/*
+ *  Architecture autodetection
+ */
+
+#if defined(DUK_F_X86)
+/* --- x86 --- */
+#define DUK_USE_ARCH_STRING "x86"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X64)
+/* --- x64 --- */
+#define DUK_USE_ARCH_STRING "x64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X32)
+/* --- x32 --- */
+#define DUK_USE_ARCH_STRING "x32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM32)
+/* --- ARM 32-bit --- */
+#define DUK_USE_ARCH_STRING "arm32"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM64)
+/* --- ARM 64-bit --- */
+#define DUK_USE_ARCH_STRING "arm64"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS32)
+/* --- MIPS 32-bit --- */
+#define DUK_USE_ARCH_STRING "mips32"
+/* MIPS byte order varies so rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux MIPS except for doubles, which need align by 4.  Alignment
+ * requirements vary based on target though.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS64)
+/* --- MIPS 64-bit --- */
+#define DUK_USE_ARCH_STRING "mips64"
+/* MIPS byte order varies so rely on autodetection. */
+/* Good default is a bit arbitrary because alignment requirements
+ * depend on target.  See https://github.com/svaarala/duktape/issues/102.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC32)
+/* --- PowerPC 32-bit --- */
+#define DUK_USE_ARCH_STRING "ppc32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC64)
+/* --- PowerPC 64-bit --- */
+#define DUK_USE_ARCH_STRING "ppc64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC32)
+/* --- SPARC 32-bit --- */
+#define DUK_USE_ARCH_STRING "sparc32"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC64)
+/* --- SPARC 64-bit --- */
+#define DUK_USE_ARCH_STRING "sparc64"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SUPERH)
+/* --- SuperH --- */
+#define DUK_USE_ARCH_STRING "sh"
+/* Byte order varies, rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux SH4, but align by 4 is probably a good basic default.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_M68K)
+/* --- Motorola 68k --- */
+#define DUK_USE_ARCH_STRING "m68k"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_USE_ARCH_STRING "emscripten"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#else
+/* --- Generic --- */
+/* These are necessary wild guesses. */
+#define DUK_USE_ARCH_STRING "generic"
+/* Rely on autodetection for byte order, alignment, and packed tval. */
+#endif  /* autodetect architecture */
+
+/*
+ *  Compiler autodetection
+ */
+
+#if defined(DUK_F_CLANG)
+/* --- Clang --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Clang: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#else
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and
+ * Clang.  Based on documentation it should suffice to have the attribute
+ * in the declaration only, but in practice some warnings are generated unless
+ * the attribute is also applied to the definition.
+ */
+#define DUK_INTERNAL_DECL  static __attribute__ ((unused))
+#define DUK_INTERNAL       static __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#endif
+#else
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden"))) __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "clang"
+#else
+#define DUK_USE_COMPILER_STRING "clang"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_UNION_INITIALIZERS
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#elif defined(DUK_F_GCC)
+/* --- GCC --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* GCC: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
+/* since gcc-2.5 */
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* since gcc-4.5 */
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* GCC: test not very accurate; enable only in relatively recent builds
+ * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
+ */
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+#endif
+
+#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \
+    defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 30101)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#elif defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40000)
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and
+ * Clang.  Based on documentation it should suffice to have the attribute
+ * in the declaration only, but in practice some warnings are generated unless
+ * the attribute is also applied to the definition.
+ */
+#define DUK_INTERNAL_DECL  static __attribute__ ((unused))
+#define DUK_INTERNAL       static __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#endif
+#else
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden"))) __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_MINGW)
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "mingw++"
+#else
+#define DUK_USE_COMPILER_STRING "mingw"
+#endif
+#else
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "g++"
+#else
+#define DUK_USE_COMPILER_STRING "gcc"
+#endif
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_UNION_INITIALIZERS
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)
+#define DUK_USE_GCC_PRAGMAS
+#else
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+#define DUK_USE_PACK_GCC_ATTR
+#elif defined(DUK_F_MSVC)
+/* --- MSVC --- */
+/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
+#define DUK_NORETURN(decl)  __declspec(noreturn) decl
+
+/* XXX: DUK_UNREACHABLE for msvc? */
+
+#undef DUK_USE_BRANCH_HINTS
+
+/* XXX: DUK_LIKELY, DUK_UNLIKELY for msvc? */
+/* XXX: DUK_NOINLINE, DUK_INLINE, DUK_ALWAYS_INLINE for msvc? */
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "msvc++"
+#else
+#define DUK_USE_COMPILER_STRING "msvc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99)
+#define DUK_USE_VARIADIC_MACROS
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+/* VS2005+ should have variadic macros even when they're not C99. */
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_UNION_INITIALIZERS
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+/* VS2013+ supports union initializers but there's a bug involving union-inside-struct:
+ * https://connect.microsoft.com/VisualStudio/feedback/details/805981
+ * The bug was fixed (at least) in VS2015 so check for VS2015 for now:
+ * https://blogs.msdn.microsoft.com/vcblog/2015/07/01/c-compiler-front-end-fixes-in-vs2015/
+ * Manually tested using VS2013, CL reports 18.00.31101, so enable for VS2013 too.
+ */
+#define DUK_USE_UNION_INITIALIZERS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+
+#define DUK_USE_PACK_MSVC_PRAGMA
+
+/* These have been tested from VS2008 onwards; may work in older VS versions
+ * too but not enabled by default.
+ */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+#define DUK_NOINLINE        __declspec(noinline)
+#define DUK_INLINE          __inline
+#define DUK_ALWAYS_INLINE   __forceinline
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define DUK_SNPRINTF     snprintf
+#define DUK_VSNPRINTF    vsnprintf
+#else
+/* (v)snprintf() is missing before MSVC 2015.  Note that _(v)snprintf() does
+ * NOT NUL terminate on truncation, but Duktape code never assumes that.
+ * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+ */
+#define DUK_SNPRINTF     _snprintf
+#define DUK_VSNPRINTF    _vsnprintf
+#endif
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and
+ * Clang.  Based on documentation it should suffice to have the attribute
+ * in the declaration only, but in practice some warnings are generated unless
+ * the attribute is also applied to the definition.
+ */
+#define DUK_INTERNAL_DECL  static __attribute__ ((unused))
+#define DUK_INTERNAL       static __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#endif
+#else
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden"))) __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+
+#define DUK_USE_COMPILER_STRING "emscripten"
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_UNION_INITIALIZERS
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#elif defined(DUK_F_TINYC)
+/* --- TinyC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "tinyc++"
+#else
+#define DUK_USE_COMPILER_STRING "tinyc"
+#endif
+
+/* http://bellard.org/tcc/tcc-doc.html#SEC7 */
+#define DUK_USE_VARIADIC_MACROS
+
+#define DUK_USE_UNION_INITIALIZERS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#elif defined(DUK_F_VBCC)
+/* --- VBCC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "vbcc-c++"
+#else
+#define DUK_USE_COMPILER_STRING "vbcc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+/* VBCC supports C99 so check only for C99 for union initializer support.
+ * Designated union initializers would possibly work even without a C99 check.
+ */
+#undef DUK_USE_UNION_INITIALIZERS
+#if defined(DUK_F_C99)
+#define DUK_USE_UNION_INITIALIZERS
+#endif
+
+#define DUK_USE_FLEX_ZEROSIZE
+#define DUK_USE_PACK_DUMMY_MEMBER
+#elif defined(DUK_F_BCC)
+/* --- Bruce's C compiler --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "bcc++"
+#else
+#define DUK_USE_COMPILER_STRING "bcc"
+#endif
+
+/* Most portable */
+#undef DUK_USE_VARIADIC_MACROS
+
+/* Most portable, wastes space */
+#undef DUK_USE_UNION_INITIALIZERS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+
+/* BCC, assume we're on x86. */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#else
+/* --- Generic --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "generic-c++"
+#else
+#define DUK_USE_COMPILER_STRING "generic"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+/* C++ doesn't have standard designated union initializers ({ .foo = 1 }). */
+#undef DUK_USE_UNION_INITIALIZERS
+#if defined(DUK_F_C99)
+#define DUK_USE_UNION_INITIALIZERS
+#endif
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif  /* autodetect compiler */
+
+/* uclibc */
+#if defined(__UCLIBC__)
+#define DUK_F_UCLIBC
+#endif
+
+/*
+ *  Wrapper typedefs and constants for integer types, also sanity check types.
+ *
+ *  C99 typedefs are quite good but not always available, and we want to avoid
+ *  forcibly redefining the C99 typedefs.  So, there are Duktape wrappers for
+ *  all C99 typedefs and Duktape code should only use these typedefs.  Type
+ *  detection when C99 is not supported is best effort and may end up detecting
+ *  some types incorrectly.
+ *
+ *  Pointer sizes are a portability problem: pointers to different types may
+ *  have a different size and function pointers are very difficult to manage
+ *  portably.
+ *
+ *  http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types
+ *
+ *  Note: there's an interesting corner case when trying to define minimum
+ *  signed integer value constants which leads to the current workaround of
+ *  defining e.g. -0x80000000 as (-0x7fffffffL - 1L).  See doc/code-issues.txt
+ *  for a longer discussion.
+ *
+ *  Note: avoid typecasts and computations in macro integer constants as they
+ *  can then no longer be used in macro relational expressions (such as
+ *  #if DUK_SIZE_MAX < 0xffffffffUL).  There is internal code which relies on
+ *  being able to compare DUK_SIZE_MAX against a limit.
+ */
+
+/* XXX: add feature options to force basic types from outside? */
+
+#if !defined(INT_MAX)
+#error INT_MAX not defined
+#endif
+
+/* Check that architecture is two's complement, standard C allows e.g.
+ * INT_MIN to be -2**31+1 (instead of -2**31).
+ */
+#if defined(INT_MAX) && defined(INT_MIN)
+#if INT_MAX != -(INT_MIN + 1)
+#error platform does not seem complement of two
+#endif
+#else
+#error cannot check complement of two
+#endif
+
+/* Pointer size determination based on __WORDSIZE or architecture when
+ * that's not available.
+ */
+#if defined(DUK_F_X86) || defined(DUK_F_X32) || \
+    defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \
+    defined(DUK_F_BCC) || \
+    (defined(__WORDSIZE) && (__WORDSIZE == 32))
+#define DUK_F_32BIT_PTRS
+#elif defined(DUK_F_X64) || \
+      (defined(__WORDSIZE) && (__WORDSIZE == 64))
+#define DUK_F_64BIT_PTRS
+#else
+/* not sure, not needed with C99 anyway */
+#endif
+
+/* Intermediate define for 'have inttypes.h' */
+#undef DUK_F_HAVE_INTTYPES
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+    !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC))
+/* vbcc + AmigaOS has C99 but no inttypes.h */
+#define DUK_F_HAVE_INTTYPES
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+/* C++11 apparently ratified stdint.h */
+#define DUK_F_HAVE_INTTYPES
+#endif
+
+/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise
+ * through automatic detection.
+ */
+#if defined(DUK_F_HAVE_INTTYPES)
+/* C99 or compatible */
+
+#define DUK_F_HAVE_64BIT
+#include <inttypes.h>
+
+typedef uint8_t duk_uint8_t;
+typedef int8_t duk_int8_t;
+typedef uint16_t duk_uint16_t;
+typedef int16_t duk_int16_t;
+typedef uint32_t duk_uint32_t;
+typedef int32_t duk_int32_t;
+typedef uint64_t duk_uint64_t;
+typedef int64_t duk_int64_t;
+typedef uint_least8_t duk_uint_least8_t;
+typedef int_least8_t duk_int_least8_t;
+typedef uint_least16_t duk_uint_least16_t;
+typedef int_least16_t duk_int_least16_t;
+typedef uint_least32_t duk_uint_least32_t;
+typedef int_least32_t duk_int_least32_t;
+typedef uint_least64_t duk_uint_least64_t;
+typedef int_least64_t duk_int_least64_t;
+typedef uint_fast8_t duk_uint_fast8_t;
+typedef int_fast8_t duk_int_fast8_t;
+typedef uint_fast16_t duk_uint_fast16_t;
+typedef int_fast16_t duk_int_fast16_t;
+typedef uint_fast32_t duk_uint_fast32_t;
+typedef int_fast32_t duk_int_fast32_t;
+typedef uint_fast64_t duk_uint_fast64_t;
+typedef int_fast64_t duk_int_fast64_t;
+typedef uintptr_t duk_uintptr_t;
+typedef intptr_t duk_intptr_t;
+typedef uintmax_t duk_uintmax_t;
+typedef intmax_t duk_intmax_t;
+
+#define DUK_UINT8_MIN         0
+#define DUK_UINT8_MAX         UINT8_MAX
+#define DUK_INT8_MIN          INT8_MIN
+#define DUK_INT8_MAX          INT8_MAX
+#define DUK_UINT_LEAST8_MIN   0
+#define DUK_UINT_LEAST8_MAX   UINT_LEAST8_MAX
+#define DUK_INT_LEAST8_MIN    INT_LEAST8_MIN
+#define DUK_INT_LEAST8_MAX    INT_LEAST8_MAX
+#define DUK_UINT_FAST8_MIN    0
+#define DUK_UINT_FAST8_MAX    UINT_FAST8_MAX
+#define DUK_INT_FAST8_MIN     INT_FAST8_MIN
+#define DUK_INT_FAST8_MAX     INT_FAST8_MAX
+#define DUK_UINT16_MIN        0
+#define DUK_UINT16_MAX        UINT16_MAX
+#define DUK_INT16_MIN         INT16_MIN
+#define DUK_INT16_MAX         INT16_MAX
+#define DUK_UINT_LEAST16_MIN  0
+#define DUK_UINT_LEAST16_MAX  UINT_LEAST16_MAX
+#define DUK_INT_LEAST16_MIN   INT_LEAST16_MIN
+#define DUK_INT_LEAST16_MAX   INT_LEAST16_MAX
+#define DUK_UINT_FAST16_MIN   0
+#define DUK_UINT_FAST16_MAX   UINT_FAST16_MAX
+#define DUK_INT_FAST16_MIN    INT_FAST16_MIN
+#define DUK_INT_FAST16_MAX    INT_FAST16_MAX
+#define DUK_UINT32_MIN        0
+#define DUK_UINT32_MAX        UINT32_MAX
+#define DUK_INT32_MIN         INT32_MIN
+#define DUK_INT32_MAX         INT32_MAX
+#define DUK_UINT_LEAST32_MIN  0
+#define DUK_UINT_LEAST32_MAX  UINT_LEAST32_MAX
+#define DUK_INT_LEAST32_MIN   INT_LEAST32_MIN
+#define DUK_INT_LEAST32_MAX   INT_LEAST32_MAX
+#define DUK_UINT_FAST32_MIN   0
+#define DUK_UINT_FAST32_MAX   UINT_FAST32_MAX
+#define DUK_INT_FAST32_MIN    INT_FAST32_MIN
+#define DUK_INT_FAST32_MAX    INT_FAST32_MAX
+#define DUK_UINT64_MIN        0
+#define DUK_UINT64_MAX        UINT64_MAX
+#define DUK_INT64_MIN         INT64_MIN
+#define DUK_INT64_MAX         INT64_MAX
+#define DUK_UINT_LEAST64_MIN  0
+#define DUK_UINT_LEAST64_MAX  UINT_LEAST64_MAX
+#define DUK_INT_LEAST64_MIN   INT_LEAST64_MIN
+#define DUK_INT_LEAST64_MAX   INT_LEAST64_MAX
+#define DUK_UINT_FAST64_MIN   0
+#define DUK_UINT_FAST64_MAX   UINT_FAST64_MAX
+#define DUK_INT_FAST64_MIN    INT_FAST64_MIN
+#define DUK_INT_FAST64_MAX    INT_FAST64_MAX
+
+#define DUK_UINTPTR_MIN       0
+#define DUK_UINTPTR_MAX       UINTPTR_MAX
+#define DUK_INTPTR_MIN        INTPTR_MIN
+#define DUK_INTPTR_MAX        INTPTR_MAX
+
+#define DUK_UINTMAX_MIN       0
+#define DUK_UINTMAX_MAX       UINTMAX_MAX
+#define DUK_INTMAX_MIN        INTMAX_MIN
+#define DUK_INTMAX_MAX        INTMAX_MAX
+
+#define DUK_SIZE_MIN          0
+#define DUK_SIZE_MAX          SIZE_MAX
+#undef DUK_SIZE_MAX_COMPUTED
+
+#else  /* C99 types */
+
+/* When C99 types are not available, we use heuristic detection to get
+ * the basic 8, 16, 32, and (possibly) 64 bit types.  The fast/least
+ * types are then assumed to be exactly the same for now: these could
+ * be improved per platform but C99 types are very often now available.
+ * 64-bit types are not available on all platforms; this is OK at least
+ * on 32-bit platforms.
+ *
+ * This detection code is necessarily a bit hacky and can provide typedefs
+ * and defines that won't work correctly on some exotic platform.
+ */
+
+#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \
+    (defined(UCHAR_MAX) && (UCHAR_MAX == 255))
+typedef unsigned char duk_uint8_t;
+typedef signed char duk_int8_t;
+#else
+#error cannot detect 8-bit type
+#endif
+
+#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL)
+typedef unsigned short duk_uint16_t;
+typedef signed short duk_int16_t;
+#elif defined(UINT_MAX) && (UINT_MAX == 65535UL)
+/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
+typedef unsigned int duk_uint16_t;
+typedef signed int duk_int16_t;
+#else
+#error cannot detect 16-bit type
+#endif
+
+#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL)
+typedef unsigned int duk_uint32_t;
+typedef signed int duk_int32_t;
+#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL)
+/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
+typedef unsigned long duk_uint32_t;
+typedef signed long duk_int32_t;
+#else
+#error cannot detect 32-bit type
+#endif
+
+/* 64-bit type detection is a bit tricky.
+ *
+ * ULLONG_MAX is a standard define.  __LONG_LONG_MAX__ and __ULONG_LONG_MAX__
+ * are used by at least GCC (even if system headers don't provide ULLONG_MAX).
+ * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__.
+ *
+ * ULL / LL constants are rejected / warned about by some compilers, even if
+ * the compiler has a 64-bit type and the compiler/system headers provide an
+ * unsupported constant (ULL/LL)!  Try to avoid using ULL / LL constants.
+ * As a side effect we can only check that e.g. ULONG_MAX is larger than 32
+ * bits but can't be sure it is exactly 64 bits.  Self tests will catch such
+ * cases.
+ */
+#undef DUK_F_HAVE_64BIT
+#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX)
+#if (ULONG_MAX > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long duk_uint64_t;
+typedef signed long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX)
+#if (ULLONG_MAX > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__)
+#if (__ULONG_LONG_MAX__ > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__)
+#if (__LONG_LONG_MAX__ > 2147483647L)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && \
+    (defined(DUK_F_MINGW) || defined(DUK_F_MSVC))
+/* Both MinGW and MSVC have a 64-bit type. */
+#define DUK_F_HAVE_64BIT
+typedef unsigned long duk_uint64_t;
+typedef signed long duk_int64_t;
+#endif
+#if !defined(DUK_F_HAVE_64BIT)
+/* cannot detect 64-bit type, not always needed so don't error */
+#endif
+
+typedef duk_uint8_t duk_uint_least8_t;
+typedef duk_int8_t duk_int_least8_t;
+typedef duk_uint16_t duk_uint_least16_t;
+typedef duk_int16_t duk_int_least16_t;
+typedef duk_uint32_t duk_uint_least32_t;
+typedef duk_int32_t duk_int_least32_t;
+typedef duk_uint8_t duk_uint_fast8_t;
+typedef duk_int8_t duk_int_fast8_t;
+typedef duk_uint16_t duk_uint_fast16_t;
+typedef duk_int16_t duk_int_fast16_t;
+typedef duk_uint32_t duk_uint_fast32_t;
+typedef duk_int32_t duk_int_fast32_t;
+#if defined(DUK_F_HAVE_64BIT)
+typedef duk_uint64_t duk_uint_least64_t;
+typedef duk_int64_t duk_int_least64_t;
+typedef duk_uint64_t duk_uint_fast64_t;
+typedef duk_int64_t duk_int_fast64_t;
+#endif
+#if defined(DUK_F_HAVE_64BIT)
+typedef duk_uint64_t duk_uintmax_t;
+typedef duk_int64_t duk_intmax_t;
+#else
+typedef duk_uint32_t duk_uintmax_t;
+typedef duk_int32_t duk_intmax_t;
+#endif
+
+/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and
+ * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are
+ * -not- portable.  See code-issues.txt for a detailed discussion.
+ */
+#define DUK_UINT8_MIN         0UL
+#define DUK_UINT8_MAX         0xffUL
+#define DUK_INT8_MIN          (-0x80L)
+#define DUK_INT8_MAX          0x7fL
+#define DUK_UINT_LEAST8_MIN   0UL
+#define DUK_UINT_LEAST8_MAX   0xffUL
+#define DUK_INT_LEAST8_MIN    (-0x80L)
+#define DUK_INT_LEAST8_MAX    0x7fL
+#define DUK_UINT_FAST8_MIN    0UL
+#define DUK_UINT_FAST8_MAX    0xffUL
+#define DUK_INT_FAST8_MIN     (-0x80L)
+#define DUK_INT_FAST8_MAX     0x7fL
+#define DUK_UINT16_MIN        0UL
+#define DUK_UINT16_MAX        0xffffUL
+#define DUK_INT16_MIN         (-0x7fffL - 1L)
+#define DUK_INT16_MAX         0x7fffL
+#define DUK_UINT_LEAST16_MIN  0UL
+#define DUK_UINT_LEAST16_MAX  0xffffUL
+#define DUK_INT_LEAST16_MIN   (-0x7fffL - 1L)
+#define DUK_INT_LEAST16_MAX   0x7fffL
+#define DUK_UINT_FAST16_MIN   0UL
+#define DUK_UINT_FAST16_MAX   0xffffUL
+#define DUK_INT_FAST16_MIN    (-0x7fffL - 1L)
+#define DUK_INT_FAST16_MAX    0x7fffL
+#define DUK_UINT32_MIN        0UL
+#define DUK_UINT32_MAX        0xffffffffUL
+#define DUK_INT32_MIN         (-0x7fffffffL - 1L)
+#define DUK_INT32_MAX         0x7fffffffL
+#define DUK_UINT_LEAST32_MIN  0UL
+#define DUK_UINT_LEAST32_MAX  0xffffffffUL
+#define DUK_INT_LEAST32_MIN   (-0x7fffffffL - 1L)
+#define DUK_INT_LEAST32_MAX   0x7fffffffL
+#define DUK_UINT_FAST32_MIN   0UL
+#define DUK_UINT_FAST32_MAX   0xffffffffUL
+#define DUK_INT_FAST32_MIN    (-0x7fffffffL - 1L)
+#define DUK_INT_FAST32_MAX    0x7fffffffL
+
+/* 64-bit constants.  Since LL / ULL constants are not always available,
+ * use computed values.  These values can't be used in preprocessor
+ * comparisons; flag them as such.
+ */
+#if defined(DUK_F_HAVE_64BIT)
+#define DUK_UINT64_MIN        ((duk_uint64_t) 0)
+#define DUK_UINT64_MAX        ((duk_uint64_t) -1)
+#define DUK_INT64_MIN         ((duk_int64_t) (~(DUK_UINT64_MAX >> 1)))
+#define DUK_INT64_MAX         ((duk_int64_t) (DUK_UINT64_MAX >> 1))
+#define DUK_UINT_LEAST64_MIN  DUK_UINT64_MIN
+#define DUK_UINT_LEAST64_MAX  DUK_UINT64_MAX
+#define DUK_INT_LEAST64_MIN   DUK_INT64_MIN
+#define DUK_INT_LEAST64_MAX   DUK_INT64_MAX
+#define DUK_UINT_FAST64_MIN   DUK_UINT64_MIN
+#define DUK_UINT_FAST64_MAX   DUK_UINT64_MAX
+#define DUK_INT_FAST64_MIN    DUK_INT64_MIN
+#define DUK_INT_FAST64_MAX    DUK_INT64_MAX
+#define DUK_UINT64_MIN_COMPUTED
+#define DUK_UINT64_MAX_COMPUTED
+#define DUK_INT64_MIN_COMPUTED
+#define DUK_INT64_MAX_COMPUTED
+#define DUK_UINT_LEAST64_MIN_COMPUTED
+#define DUK_UINT_LEAST64_MAX_COMPUTED
+#define DUK_INT_LEAST64_MIN_COMPUTED
+#define DUK_INT_LEAST64_MAX_COMPUTED
+#define DUK_UINT_FAST64_MIN_COMPUTED
+#define DUK_UINT_FAST64_MAX_COMPUTED
+#define DUK_INT_FAST64_MIN_COMPUTED
+#define DUK_INT_FAST64_MAX_COMPUTED
+#endif
+
+#if defined(DUK_F_HAVE_64BIT)
+#define DUK_UINTMAX_MIN       DUK_UINT64_MIN
+#define DUK_UINTMAX_MAX       DUK_UINT64_MAX
+#define DUK_INTMAX_MIN        DUK_INT64_MIN
+#define DUK_INTMAX_MAX        DUK_INT64_MAX
+#define DUK_UINTMAX_MIN_COMPUTED
+#define DUK_UINTMAX_MAX_COMPUTED
+#define DUK_INTMAX_MIN_COMPUTED
+#define DUK_INTMAX_MAX_COMPUTED
+#else
+#define DUK_UINTMAX_MIN       0UL
+#define DUK_UINTMAX_MAX       0xffffffffUL
+#define DUK_INTMAX_MIN        (-0x7fffffffL - 1L)
+#define DUK_INTMAX_MAX        0x7fffffffL
+#endif
+
+/* This detection is not very reliable. */
+#if defined(DUK_F_32BIT_PTRS)
+typedef duk_int32_t duk_intptr_t;
+typedef duk_uint32_t duk_uintptr_t;
+#define DUK_UINTPTR_MIN       DUK_UINT32_MIN
+#define DUK_UINTPTR_MAX       DUK_UINT32_MAX
+#define DUK_INTPTR_MIN        DUK_INT32_MIN
+#define DUK_INTPTR_MAX        DUK_INT32_MAX
+#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT)
+typedef duk_int64_t duk_intptr_t;
+typedef duk_uint64_t duk_uintptr_t;
+#define DUK_UINTPTR_MIN       DUK_UINT64_MIN
+#define DUK_UINTPTR_MAX       DUK_UINT64_MAX
+#define DUK_INTPTR_MIN        DUK_INT64_MIN
+#define DUK_INTPTR_MAX        DUK_INT64_MAX
+#define DUK_UINTPTR_MIN_COMPUTED
+#define DUK_UINTPTR_MAX_COMPUTED
+#define DUK_INTPTR_MIN_COMPUTED
+#define DUK_INTPTR_MAX_COMPUTED
+#else
+#error cannot determine intptr type
+#endif
+
+/* SIZE_MAX may be missing so use an approximate value for it. */
+#undef DUK_SIZE_MAX_COMPUTED
+#if !defined(SIZE_MAX)
+#define DUK_SIZE_MAX_COMPUTED
+#define SIZE_MAX              ((size_t) (-1))
+#endif
+#define DUK_SIZE_MIN          0
+#define DUK_SIZE_MAX          SIZE_MAX
+
+#endif  /* C99 types */
+
+/* A few types are assumed to always exist. */
+typedef size_t duk_size_t;
+typedef ptrdiff_t duk_ptrdiff_t;
+
+/* The best type for an "all around int" in Duktape internals is "at least
+ * 32 bit signed integer" which is most convenient.  Same for unsigned type.
+ * Prefer 'int' when large enough, as it is almost always a convenient type.
+ */
+#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL)
+typedef int duk_int_t;
+typedef unsigned int duk_uint_t;
+#define DUK_INT_MIN           INT_MIN
+#define DUK_INT_MAX           INT_MAX
+#define DUK_UINT_MIN          0
+#define DUK_UINT_MAX          UINT_MAX
+#else
+typedef duk_int_fast32_t duk_int_t;
+typedef duk_uint_fast32_t duk_uint_t;
+#define DUK_INT_MIN           DUK_INT_FAST32_MIN
+#define DUK_INT_MAX           DUK_INT_FAST32_MAX
+#define DUK_UINT_MIN          DUK_UINT_FAST32_MIN
+#define DUK_UINT_MAX          DUK_UINT_FAST32_MAX
+#endif
+
+/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this
+ * distinction matters for the CPU.  These types are used mainly in the
+ * executor where it might really matter.
+ */
+typedef duk_int_fast32_t duk_int_fast_t;
+typedef duk_uint_fast32_t duk_uint_fast_t;
+#define DUK_INT_FAST_MIN      DUK_INT_FAST32_MIN
+#define DUK_INT_FAST_MAX      DUK_INT_FAST32_MAX
+#define DUK_UINT_FAST_MIN     DUK_UINT_FAST32_MIN
+#define DUK_UINT_FAST_MAX     DUK_UINT_FAST32_MAX
+
+/* Small integers (16 bits or more) can fall back to the 'int' type, but
+ * have a typedef so they are marked "small" explicitly.
+ */
+typedef int duk_small_int_t;
+typedef unsigned int duk_small_uint_t;
+#define DUK_SMALL_INT_MIN     INT_MIN
+#define DUK_SMALL_INT_MAX     INT_MAX
+#define DUK_SMALL_UINT_MIN    0
+#define DUK_SMALL_UINT_MAX    UINT_MAX
+
+/* Fast variants of small integers, again for really fast paths like the
+ * executor.
+ */
+typedef duk_int_fast16_t duk_small_int_fast_t;
+typedef duk_uint_fast16_t duk_small_uint_fast_t;
+#define DUK_SMALL_INT_FAST_MIN    DUK_INT_FAST16_MIN
+#define DUK_SMALL_INT_FAST_MAX    DUK_INT_FAST16_MAX
+#define DUK_SMALL_UINT_FAST_MIN   DUK_UINT_FAST16_MIN
+#define DUK_SMALL_UINT_FAST_MAX   DUK_UINT_FAST16_MAX
+
+/* Boolean values are represented with the platform 'int'. */
+typedef duk_small_int_t duk_bool_t;
+#define DUK_BOOL_MIN              DUK_SMALL_INT_MIN
+#define DUK_BOOL_MAX              DUK_SMALL_INT_MAX
+
+/* Index values must have at least 32-bit signed range. */
+typedef duk_int_t duk_idx_t;
+#define DUK_IDX_MIN               DUK_INT_MIN
+#define DUK_IDX_MAX               DUK_INT_MAX
+
+/* Unsigned index variant. */
+typedef duk_uint_t duk_uidx_t;
+#define DUK_UIDX_MIN              DUK_UINT_MIN
+#define DUK_UIDX_MAX              DUK_UINT_MAX
+
+/* Array index values, could be exact 32 bits.
+ * Currently no need for signed duk_arridx_t.
+ */
+typedef duk_uint_t duk_uarridx_t;
+#define DUK_UARRIDX_MIN           DUK_UINT_MIN
+#define DUK_UARRIDX_MAX           DUK_UINT_MAX
+
+/* Duktape/C function return value, platform int is enough for now to
+ * represent 0, 1, or negative error code.  Must be compatible with
+ * assigning truth values (e.g. duk_ret_t rc = (foo == bar);).
+ */
+typedef duk_small_int_t duk_ret_t;
+#define DUK_RET_MIN               DUK_SMALL_INT_MIN
+#define DUK_RET_MAX               DUK_SMALL_INT_MAX
+
+/* Error codes are represented with platform int.  High bits are used
+ * for flags and such, so 32 bits are needed.
+ */
+typedef duk_int_t duk_errcode_t;
+#define DUK_ERRCODE_MIN           DUK_INT_MIN
+#define DUK_ERRCODE_MAX           DUK_INT_MAX
+
+/* Codepoint type.  Must be 32 bits or more because it is used also for
+ * internal codepoints.  The type is signed because negative codepoints
+ * are used as internal markers (e.g. to mark EOF or missing argument).
+ * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to
+ * ensure duk_uint32_t casts back and forth nicely.  Almost everything
+ * else uses the signed one.
+ */
+typedef duk_int_t duk_codepoint_t;
+typedef duk_uint_t duk_ucodepoint_t;
+#define DUK_CODEPOINT_MIN         DUK_INT_MIN
+#define DUK_CODEPOINT_MAX         DUK_INT_MAX
+#define DUK_UCODEPOINT_MIN        DUK_UINT_MIN
+#define DUK_UCODEPOINT_MAX        DUK_UINT_MAX
+
+/* IEEE float/double typedef. */
+typedef float duk_float_t;
+typedef double duk_double_t;
+
+/* We're generally assuming that we're working on a platform with a 32-bit
+ * address space.  If DUK_SIZE_MAX is a typecast value (which is necessary
+ * if SIZE_MAX is missing), the check must be avoided because the
+ * preprocessor can't do a comparison.
+ */
+#if !defined(DUK_SIZE_MAX)
+#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX
+#elif !defined(DUK_SIZE_MAX_COMPUTED)
+#if DUK_SIZE_MAX < 0xffffffffUL
+/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value
+ * which seems incorrect if size_t is (at least) an unsigned 32-bit type.
+ * However, it doesn't seem useful to error out compilation if this is the
+ * case.
+ */
+#endif
+#endif
+
+/* Type for public API calls. */
+typedef struct duk_hthread duk_context;
+
+/* Check whether we should use 64-bit integers or not.
+ *
+ * Quite incomplete now.  Use 64-bit types if detected (C99 or other detection)
+ * unless they are known to be unreliable.  For instance, 64-bit types are
+ * available on VBCC but seem to misbehave.
+ */
+#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC)
+#define DUK_USE_64BIT_OPS
+#else
+#undef DUK_USE_64BIT_OPS
+#endif
+
+/*
+ *  Fill-ins for platform, architecture, and compiler
+ */
+
+#if !defined(DUK_SETJMP)
+#define DUK_JMPBUF_TYPE       jmp_buf
+#define DUK_SETJMP(jb)        setjmp((jb))
+#define DUK_LONGJMP(jb)       longjmp((jb), 1)
+#endif
+
+#if 0
+/* sigsetjmp() alternative */
+#define DUK_JMPBUF_TYPE       sigjmp_buf
+#define DUK_SETJMP(jb)        sigsetjmp((jb))
+#define DUK_LONGJMP(jb)       siglongjmp((jb), 1)
+#endif
+
+typedef FILE duk_file;
+#if !defined(DUK_STDIN)
+#define DUK_STDIN       stdin
+#endif
+#if !defined(DUK_STDOUT)
+#define DUK_STDOUT      stdout
+#endif
+#if !defined(DUK_STDERR)
+#define DUK_STDERR      stderr
+#endif
+
+/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h
+ * (which is unfortunately named).  May sometimes need replacement, e.g.
+ * some compilers don't handle zero length or NULL correctly in realloc().
+ */
+#if !defined(DUK_ANSI_MALLOC)
+#define DUK_ANSI_MALLOC      malloc
+#endif
+#if !defined(DUK_ANSI_REALLOC)
+#define DUK_ANSI_REALLOC     realloc
+#endif
+#if !defined(DUK_ANSI_CALLOC)
+#define DUK_ANSI_CALLOC      calloc
+#endif
+#if !defined(DUK_ANSI_FREE)
+#define DUK_ANSI_FREE        free
+#endif
+
+/* ANSI C (various versions) and some implementations require that the
+ * pointer arguments to memset(), memcpy(), and memmove() be valid values
+ * even when byte size is 0 (even a NULL pointer is considered invalid in
+ * this context).  Zero-size operations as such are allowed, as long as their
+ * pointer arguments point to a valid memory area.  The DUK_MEMSET(),
+ * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:
+ * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be
+ * allowed.  If these are not fulfilled, a macro wrapper is needed.
+ *
+ *   http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
+ *   http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html
+ *
+ * Not sure what's the required behavior when a pointer points just past the
+ * end of a buffer, which often happens in practice (e.g. zero size memmoves).
+ * For example, if allocation size is 3, the following pointer would not
+ * technically point to a valid memory byte:
+ *
+ *   <-- alloc -->
+ *   | 0 | 1 | 2 | .....
+ *                 ^-- p=3, points after last valid byte (2)
+ */
+#if !defined(DUK_MEMCPY)
+#if defined(DUK_F_UCLIBC)
+/* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide
+ * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html
+ */
+#define DUK_MEMCPY       memmove
+#else
+#define DUK_MEMCPY       memcpy
+#endif
+#endif
+#if !defined(DUK_MEMMOVE)
+#define DUK_MEMMOVE      memmove
+#endif
+#if !defined(DUK_MEMCMP)
+#define DUK_MEMCMP       memcmp
+#endif
+#if !defined(DUK_MEMSET)
+#define DUK_MEMSET       memset
+#endif
+#if !defined(DUK_STRLEN)
+#define DUK_STRLEN       strlen
+#endif
+#if !defined(DUK_STRCMP)
+#define DUK_STRCMP       strcmp
+#endif
+#if !defined(DUK_STRNCMP)
+#define DUK_STRNCMP      strncmp
+#endif
+#if !defined(DUK_PRINTF)
+#define DUK_PRINTF       printf
+#endif
+#if !defined(DUK_FPRINTF)
+#define DUK_FPRINTF      fprintf
+#endif
+#if !defined(DUK_SPRINTF)
+#define DUK_SPRINTF      sprintf
+#endif
+#if !defined(DUK_SNPRINTF)
+/* snprintf() is technically not part of C89 but usually available. */
+#define DUK_SNPRINTF     snprintf
+#endif
+#if !defined(DUK_VSPRINTF)
+#define DUK_VSPRINTF     vsprintf
+#endif
+#if !defined(DUK_VSNPRINTF)
+/* vsnprintf() is technically not part of C89 but usually available. */
+#define DUK_VSNPRINTF    vsnprintf
+#endif
+#if !defined(DUK_SSCANF)
+#define DUK_SSCANF       sscanf
+#endif
+#if !defined(DUK_VSSCANF)
+#define DUK_VSSCANF      vsscanf
+#endif
+#if !defined(DUK_FOPEN)
+#define DUK_FOPEN        fopen
+#endif
+#if !defined(DUK_FCLOSE)
+#define DUK_FCLOSE       fclose
+#endif
+#if !defined(DUK_FREAD)
+#define DUK_FREAD        fread
+#endif
+#if !defined(DUK_FWRITE)
+#define DUK_FWRITE       fwrite
+#endif
+#if !defined(DUK_FSEEK)
+#define DUK_FSEEK        fseek
+#endif
+#if !defined(DUK_FTELL)
+#define DUK_FTELL        ftell
+#endif
+#if !defined(DUK_FFLUSH)
+#define DUK_FFLUSH       fflush
+#endif
+#if !defined(DUK_FPUTC)
+#define DUK_FPUTC        fputc
+#endif
+#if !defined(DUK_MEMZERO)
+#define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n))
+#endif
+#if !defined(DUK_ABORT)
+#define DUK_ABORT        abort
+#endif
+#if !defined(DUK_EXIT)
+#define DUK_EXIT         exit
+#endif
+
+#if !defined(DUK_DOUBLE_2TO32)
+#define DUK_DOUBLE_2TO32     4294967296.0
+#endif
+#if !defined(DUK_DOUBLE_2TO31)
+#define DUK_DOUBLE_2TO31     2147483648.0
+#endif
+
+#if !defined(DUK_DOUBLE_INFINITY)
+#undef DUK_USE_COMPUTED_INFINITY
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600)
+/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */
+#define DUK_DOUBLE_INFINITY  (__builtin_inf())
+#elif defined(INFINITY)
+#define DUK_DOUBLE_INFINITY  ((double) INFINITY)
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#define DUK_DOUBLE_INFINITY  (1.0 / 0.0)
+#else
+/* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity.
+ * Use a computed infinity (initialized when a heap is created at the
+ * latest).
+ */
+#define DUK_USE_COMPUTED_INFINITY
+#define DUK_DOUBLE_INFINITY  duk_computed_infinity
+#endif
+#endif
+
+#if !defined(DUK_DOUBLE_NAN)
+#undef DUK_USE_COMPUTED_NAN
+#if defined(NAN)
+#define DUK_DOUBLE_NAN       NAN
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#define DUK_DOUBLE_NAN       (0.0 / 0.0)
+#else
+/* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN.
+ * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error.
+ * Use a computed NaN (initialized when a heap is created at the
+ * latest).
+ */
+#define DUK_USE_COMPUTED_NAN
+#define DUK_DOUBLE_NAN       duk_computed_nan
+#endif
+#endif
+
+/* Many platforms are missing fpclassify() and friends, so use replacements
+ * if necessary.  The replacement constants (FP_NAN etc) can be anything but
+ * match Linux constants now.
+ */
+#undef DUK_USE_REPL_FPCLASSIFY
+#undef DUK_USE_REPL_SIGNBIT
+#undef DUK_USE_REPL_ISFINITE
+#undef DUK_USE_REPL_ISNAN
+#undef DUK_USE_REPL_ISINF
+
+/* Complex condition broken into separate parts. */
+#undef DUK_F_USE_REPL_ALL
+#if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \
+      defined(FP_SUBNORMAL) && defined(FP_NORMAL))
+/* Missing some obvious constants. */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
+/* VBCC is missing the built-ins even in C99 mode (perhaps a header issue). */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_M68K)
+/* AmigaOS + M68K seems to have math issues even when using GCC cross
+ * compilation.  Use replacements for all AmigaOS versions on M68K
+ * regardless of compiler.
+ */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG)
+/* Placeholder fix for (detection is wider than necessary):
+ * http://llvm.org/bugs/show_bug.cgi?id=17788
+ */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_UCLIBC)
+/* At least some uclibc versions have broken floating point math.  For
+ * example, fpclassify() can incorrectly classify certain NaN formats.
+ * To be safe, use replacements.
+ */
+#define DUK_F_USE_REPL_ALL
+#endif
+
+#if defined(DUK_F_USE_REPL_ALL)
+#define DUK_USE_REPL_FPCLASSIFY
+#define DUK_USE_REPL_SIGNBIT
+#define DUK_USE_REPL_ISFINITE
+#define DUK_USE_REPL_ISNAN
+#define DUK_USE_REPL_ISINF
+#define DUK_FPCLASSIFY       duk_repl_fpclassify
+#define DUK_SIGNBIT          duk_repl_signbit
+#define DUK_ISFINITE         duk_repl_isfinite
+#define DUK_ISNAN            duk_repl_isnan
+#define DUK_ISINF            duk_repl_isinf
+#define DUK_FP_NAN           0
+#define DUK_FP_INFINITE      1
+#define DUK_FP_ZERO          2
+#define DUK_FP_SUBNORMAL     3
+#define DUK_FP_NORMAL        4
+#else
+#define DUK_FPCLASSIFY       fpclassify
+#define DUK_SIGNBIT          signbit
+#define DUK_ISFINITE         isfinite
+#define DUK_ISNAN            isnan
+#define DUK_ISINF            isinf
+#define DUK_FP_NAN           FP_NAN
+#define DUK_FP_INFINITE      FP_INFINITE
+#define DUK_FP_ZERO          FP_ZERO
+#define DUK_FP_SUBNORMAL     FP_SUBNORMAL
+#define DUK_FP_NORMAL        FP_NORMAL
+#endif
+
+#if defined(DUK_F_USE_REPL_ALL)
+#undef DUK_F_USE_REPL_ALL
+#endif
+
+/* Some math functions are C99 only.  This is also an issue with some
+ * embedded environments using uclibc where uclibc has been configured
+ * not to provide some functions.  For now, use replacements whenever
+ * using uclibc.
+ */
+#undef DUK_USE_MATH_FMIN
+#undef DUK_USE_MATH_FMAX
+#undef DUK_USE_MATH_ROUND
+#if defined(DUK_F_UCLIBC)
+/* uclibc may be missing these */
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
+/* vbcc + AmigaOS may be missing these */
+#elif defined(DUK_F_MINT)
+/* mint clib is missing these */
+#elif !defined(DUK_F_C99) && !defined(DUK_F_CPP11)
+/* build is not C99 or C++11, play it safe */
+#else
+/* C99 or C++11, no known issues */
+#define DUK_USE_MATH_FMIN
+#define DUK_USE_MATH_FMAX
+#define DUK_USE_MATH_ROUND
+#endif
+
+/* These functions don't currently need replacement but are wrapped for
+ * completeness.  Because these are used as function pointers, they need
+ * to be defined as concrete C functions (not macros).
+ */
+#if !defined(DUK_FABS)
+#define DUK_FABS             fabs
+#endif
+#if !defined(DUK_FMIN)
+#define DUK_FMIN             fmin
+#endif
+#if !defined(DUK_FMAX)
+#define DUK_FMAX             fmax
+#endif
+#if !defined(DUK_FLOOR)
+#define DUK_FLOOR            floor
+#endif
+#if !defined(DUK_CEIL)
+#define DUK_CEIL             ceil
+#endif
+#if !defined(DUK_FMOD)
+#define DUK_FMOD             fmod
+#endif
+#if !defined(DUK_POW)
+#define DUK_POW              pow
+#endif
+#if !defined(DUK_ACOS)
+#define DUK_ACOS             acos
+#endif
+#if !defined(DUK_ASIN)
+#define DUK_ASIN             asin
+#endif
+#if !defined(DUK_ATAN)
+#define DUK_ATAN             atan
+#endif
+#if !defined(DUK_ATAN2)
+#define DUK_ATAN2            atan2
+#endif
+#if !defined(DUK_SIN)
+#define DUK_SIN              sin
+#endif
+#if !defined(DUK_COS)
+#define DUK_COS              cos
+#endif
+#if !defined(DUK_TAN)
+#define DUK_TAN              tan
+#endif
+#if !defined(DUK_EXP)
+#define DUK_EXP              exp
+#endif
+#if !defined(DUK_LOG)
+#define DUK_LOG              log
+#endif
+#if !defined(DUK_SQRT)
+#define DUK_SQRT             sqrt
+#endif
+
+/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,
+ * see test-bug-netbsd-math-pow.js.  Use NetBSD specific workaround.
+ * (This might be a wider problem; if so, generalize the define name.)
+ */
+#undef DUK_USE_POW_NETBSD_WORKAROUND
+#if defined(DUK_F_NETBSD)
+#define DUK_USE_POW_NETBSD_WORKAROUND
+#endif
+
+/* Rely as little as possible on compiler behavior for NaN comparison,
+ * signed zero handling, etc.  Currently never activated but may be needed
+ * for broken compilers.
+ */
+#undef DUK_USE_PARANOID_MATH
+
+/* There was a curious bug where test-bi-date-canceling.js would fail e.g.
+ * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99.  Some date computations
+ * using doubles would be optimized which then broke some corner case tests.
+ * The problem goes away by adding 'volatile' to the datetime computations.
+ * Not sure what the actual triggering conditions are, but using this on
+ * non-C99 systems solves the known issues and has relatively little cost
+ * on other platforms.
+ */
+#undef DUK_USE_PARANOID_DATE_COMPUTATION
+#if !defined(DUK_F_C99)
+#define DUK_USE_PARANOID_DATE_COMPUTATION
+#endif
+
+/*
+ *  Byte order and double memory layout detection
+ *
+ *  Endianness detection is a major portability hassle because the macros
+ *  and headers are not standardized.  There's even variance across UNIX
+ *  platforms.  Even with "standard" headers, details like underscore count
+ *  varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used
+ *  (Crossbridge has a single underscore, for instance).
+ *
+ *  The checks below are structured with this in mind: several approaches are
+ *  used, and at the end we check if any of them worked.  This allows generic
+ *  approaches to be tried first, and platform/compiler specific hacks tried
+ *  last.  As a last resort, the user can force a specific endianness, as it's
+ *  not likely that automatic detection will work on the most exotic platforms.
+ *
+ *  Duktape supports little and big endian machines.  There's also support
+ *  for a hybrid used by some ARM machines where integers are little endian
+ *  but IEEE double values use a mixed order (12345678 -> 43218765).  This
+ *  byte order for doubles is referred to as "mixed endian".
+ */
+
+/* For custom platforms allow user to define byteorder explicitly.
+ * Since endianness headers are not standardized, this is a useful
+ * workaround for custom platforms for which endianness detection
+ * is not directly supported.  Perhaps custom hardware is used and
+ * user cannot submit upstream patches.
+ */
+#if defined(DUK_OPT_FORCE_BYTEORDER)
+#undef DUK_USE_BYTEORDER
+#if (DUK_OPT_FORCE_BYTEORDER == 1)
+#define DUK_USE_BYTEORDER 1
+#elif (DUK_OPT_FORCE_BYTEORDER == 2)
+#define DUK_USE_BYTEORDER 2
+#elif (DUK_OPT_FORCE_BYTEORDER == 3)
+#define DUK_USE_BYTEORDER 3
+#else
+#error invalid DUK_OPT_FORCE_BYTEORDER value
+#endif
+#endif  /* DUK_OPT_FORCE_BYTEORDER */
+
+/* GCC and Clang provide endianness defines as built-in predefines, with
+ * leading and trailing double underscores (e.g. __BYTE_ORDER__).  See
+ * output of "make gccpredefs" and "make clangpredefs".  Clang doesn't
+ * seem to provide __FLOAT_WORD_ORDER__; assume not mixed endian for clang.
+ * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+ */
+#if !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__)
+#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#else
+/* Cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit
+ * integer ordering and is not relevant.
+ */
+#endif  /* integer byte order */
+#endif  /* !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) */
+
+/* More or less standard endianness predefines provided by header files.
+ * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER
+ * will be big endian, see: http://lists.mysql.com/internals/443.
+ * On some platforms some defines may be present with an empty value which
+ * causes comparisons to fail: https://github.com/svaarala/duktape/issues/453.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \
+    defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \
+    defined(__LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \
+    defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+      defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \
+      defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \
+      defined(__BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+    defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#else
+/* Cannot determine byte order. */
+#endif  /* integer byte order */
+#endif  /* !defined(DUK_USE_BYTEORDER) */
+
+/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  67:#define __LITTLEENDIAN__ 1
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  81:#define __BIGENDIAN__ 1
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  70:#define __LITTLEENDIAN__ 1
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__LITTLEENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__BIGENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#endif
+#endif
+
+/*
+ *  Alignment requirement and support for unaligned accesses
+ *
+ *  Assume unaligned accesses are not supported unless specifically allowed
+ *  in the target platform.  Some platforms may support unaligned accesses
+ *  but alignment to 4 or 8 may still be desirable.
+ */
+
+/* If not provided, use safe default for alignment. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+
+/* User forced alignment to 4 or 8. */
+#if defined(DUK_OPT_FORCE_ALIGN)
+#undef DUK_USE_ALIGN_BY
+#if (DUK_OPT_FORCE_ALIGN == 4)
+#define DUK_USE_ALIGN_BY 4
+#elif (DUK_OPT_FORCE_ALIGN == 8)
+#define DUK_USE_ALIGN_BY 8
+#else
+#error invalid DUK_OPT_FORCE_ALIGN value
+#endif
+#endif
+
+/* Compiler specific hackery needed to force struct size to match aligment,
+ * see e.g. duk_hbuffer.h.
+ *
+ * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
+ * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
+ */
+#if !(defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_GCC_ATTR) || \
+      defined(DUK_USE_PACK_CLANG_ATTR) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+
+#if !defined(DUK_VA_COPY)
+/* We need va_copy() which is defined in C99 / C++11, so an awkward
+ * replacement is needed for pre-C99 / pre-C++11 environments.  This
+ * will quite likely need portability hacks for some non-C99
+ * environments.
+ */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required.
+ * Omit parenthesis on macro right side on purpose to minimize differences
+ * to direct use.
+ */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Pre-C99: va_list type is implementation dependent.  This replacement
+ * assumes it is a plain value so that a simple assignment will work.
+ * This is not the case on all platforms (it may be a single-array element,
+ * for instance).
+ */
+#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0)
+#endif
+#endif
+
+#if !defined(DUK_MACRO_STRINGIFY)
+/* Macro hackery to convert e.g. __LINE__ to a string without formatting,
+ * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
+ */
+#define DUK_MACRO_STRINGIFY_HELPER(x)  #x
+#define DUK_MACRO_STRINGIFY(x)  DUK_MACRO_STRINGIFY_HELPER(x)
+#endif
+
+#if !defined(DUK_CAUSE_SEGFAULT)
+/* This is optionally used by panic handling to cause the program to segfault
+ * (instead of e.g. abort()) on panic.  Valgrind will then indicate the C
+ * call stack leading to the panic.
+ */
+#define DUK_CAUSE_SEGFAULT()  do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0)
+#endif
+#if !defined(DUK_UNREF)
+/* Macro for suppressing warnings for potentially unreferenced variables.
+ * The variables can be actually unreferenced or unreferenced in some
+ * specific cases only; for instance, if a variable is only debug printed,
+ * it is unreferenced when debug printing is disabled.
+ */
+#define DUK_UNREF(x)  do { (void) (x); } while (0)
+#endif
+#if !defined(DUK_NORETURN)
+#define DUK_NORETURN(decl)  decl
+#endif
+#if !defined(DUK_UNREACHABLE)
+/* Don't know how to declare unreachable point, so don't do it; this
+ * may cause some spurious compilation warnings (e.g. "variable used
+ * uninitialized").
+ */
+#define DUK_UNREACHABLE()  do { } while (0)
+#endif
+#if !defined(DUK_LOSE_CONST)
+/* Convert any input pointer into a "void *", losing a const qualifier.
+ * This is not fully portable because casting through duk_uintptr_t may
+ * not work on all architectures (e.g. those with long, segmented pointers).
+ */
+#define DUK_LOSE_CONST(src) ((void *) (duk_uintptr_t) (src))
+#endif
+
+#if !defined(DUK_LIKELY)
+#define DUK_LIKELY(x)    (x)
+#endif
+#if !defined(DUK_UNLIKELY)
+#define DUK_UNLIKELY(x)  (x)
+#endif
+
+#if !defined(DUK_NOINLINE)
+#define DUK_NOINLINE       /*nop*/
+#endif
+#if !defined(DUK_INLINE)
+#define DUK_INLINE         /*nop*/
+#endif
+#if !defined(DUK_ALWAYS_INLINE)
+#define DUK_ALWAYS_INLINE  /*nop*/
+#endif
+
+#if !defined(DUK_EXTERNAL_DECL)
+#define DUK_EXTERNAL_DECL  extern
+#endif
+#if !defined(DUK_EXTERNAL)
+#define DUK_EXTERNAL       /*empty*/
+#endif
+#if !defined(DUK_INTERNAL_DECL)
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#else
+#define DUK_INTERNAL_DECL  extern
+#endif
+#endif
+#if !defined(DUK_INTERNAL)
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL       /*empty*/
+#endif
+#endif
+#if !defined(DUK_LOCAL_DECL)
+#define DUK_LOCAL_DECL     static
+#endif
+#if !defined(DUK_LOCAL)
+#define DUK_LOCAL          static
+#endif
+
+#if !defined(DUK_FILE_MACRO)
+#define DUK_FILE_MACRO  __FILE__
+#endif
+#if !defined(DUK_LINE_MACRO)
+#define DUK_LINE_MACRO  __LINE__
+#endif
+#if !defined(DUK_FUNC_MACRO)
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_FUNC_MACRO  __func__
+#elif defined(__FUNCTION__)
+#define DUK_FUNC_MACRO  __FUNCTION__
+#else
+#define DUK_FUNC_MACRO  "unknown"
+#endif
+#endif
+
+#if !defined(DUK_BSWAP32)
+#define DUK_BSWAP32(x) \
+	((((duk_uint32_t) (x)) >> 24) | \
+	 ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
+	 ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
+	 (((duk_uint32_t) (x)) << 24))
+#endif
+#if !defined(DUK_BSWAP16)
+#define DUK_BSWAP16(x) \
+	((duk_uint16_t) (x) >> 8) | \
+	((duk_uint16_t) (x) << 8)
+#endif
+
+/* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */
+/* DUK_USE_UNION_INITIALIZERS: required from compilers, so no fill-in. */
+
+#if !(defined(DUK_USE_FLEX_C99) || defined(DUK_USE_FLEX_ZEROSIZE) || defined(DUK_USE_FLEX_ONESIZE))
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE  /* Not standard but common enough */
+#endif
+#endif
+
+#if !(defined(DUK_USE_PACK_GCC_ATTR) || defined(DUK_USE_PACK_CLANG_ATTR) || \
+      defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+
+#if 0  /* not defined by default */
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+/* Workaround for GH-323: avoid inlining control when compiling from
+ * multiple sources, as it causes compiler portability trouble.
+ */
+#if !defined(DUK_SINGLE_FILE)
+#undef DUK_NOINLINE
+#undef DUK_INLINE
+#undef DUK_ALWAYS_INLINE
+#define DUK_NOINLINE       /*nop*/
+#define DUK_INLINE         /*nop*/
+#define DUK_ALWAYS_INLINE  /*nop*/
+#endif
+
+/*
+ *  Check whether or not a packed duk_tval representation is possible.
+ *  What's basically required is that pointers are 32-bit values
+ *  (sizeof(void *) == 4).  Best effort check, not always accurate.
+ *  If guess goes wrong, crashes may result; self tests also verify
+ *  the guess.
+ */
+
+/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */
+#if !defined(DUK_F_PACKED_TVAL_PROVIDED)
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+
+/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)
+#if (DUK_SIZE_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+#undef DUK_USE_PACKED_TVAL
+#if defined(DUK_F_PACKED_TVAL_POSSIBLE)
+#define DUK_USE_PACKED_TVAL
+#endif
+
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+#endif  /* DUK_F_PACKED_TVAL_PROVIDED */
+
+/* Feature option forcing. */
+#if defined(DUK_OPT_NO_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#elif defined(DUK_OPT_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#define DUK_USE_PACKED_TVAL
+#endif
+/* Object property allocation layout has implications for memory and code
+ * footprint and generated code size/speed.  The best layout also depends
+ * on whether the platform has alignment requirements or benefits from
+ * having mostly aligned accesses.
+ */
+#undef DUK_USE_HOBJECT_LAYOUT_1
+#undef DUK_USE_HOBJECT_LAYOUT_2
+#undef DUK_USE_HOBJECT_LAYOUT_3
+#if (DUK_USE_ALIGN_BY == 1)
+/* On platforms without any alignment issues, layout 1 is preferable
+ * because it compiles to slightly less code and provides direct access
+ * to property keys.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_1
+#else
+/* On other platforms use layout 2, which requires some padding but
+ * is a bit more natural than layout 3 in ordering the entries.  Layout
+ * 3 is currently not used.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_2
+#endif
+
+/* GCC/clang inaccurate math would break compliance and probably duk_tval,
+ * so refuse to compile.  Relax this if -ffast-math is tested to work.
+ */
+#if defined(__FAST_MATH__)
+#error __FAST_MATH__ defined, refusing to compile
+#endif
+
+/*
+ *  Autogenerated defaults
+ */
+
+#undef DUK_USE_ASSERTIONS
+#define DUK_USE_AUGMENT_ERROR_CREATE
+#define DUK_USE_AUGMENT_ERROR_THROW
+#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
+#define DUK_USE_BASE64_FASTPATH
+#define DUK_USE_BROWSER_LIKE
+#define DUK_USE_BUFFEROBJECT_SUPPORT
+#undef DUK_USE_BUFLEN16
+#define DUK_USE_BUILTIN_INITJS
+#define DUK_USE_BYTECODE_DUMP_SUPPORT
+#define DUK_USE_COMMONJS_MODULES
+#define DUK_USE_COMPILER_RECLIMIT 2500
+#undef DUK_USE_CPP_EXCEPTIONS
+#undef DUK_USE_DATAPTR16
+#undef DUK_USE_DATAPTR_DEC16
+#undef DUK_USE_DATAPTR_ENC16
+#undef DUK_USE_DATE_FORMAT_STRING
+#undef DUK_USE_DATE_GET_LOCAL_TZOFFSET
+#undef DUK_USE_DATE_GET_NOW
+#undef DUK_USE_DATE_PARSE_STRING
+#undef DUK_USE_DATE_PRS_GETDATE
+#undef DUK_USE_DDDPRINT
+#undef DUK_USE_DDPRINT
+#undef DUK_USE_DEBUG
+#undef DUK_USE_DEBUGGER_DUMPHEAP
+#undef DUK_USE_DEBUGGER_FWD_LOGGING
+#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
+#undef DUK_USE_DEBUGGER_INSPECT
+#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#undef DUK_USE_DEBUGGER_SUPPORT
+#define DUK_USE_DEBUGGER_THROW_NOTIFY
+#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#define DUK_USE_DEBUG_BUFSIZE 65536L
+#define DUK_USE_DOUBLE_LINKED_HEAP
+#undef DUK_USE_DPRINT
+#undef DUK_USE_DPRINT_COLORS
+#undef DUK_USE_DPRINT_RDTSC
+#define DUK_USE_ERRCREATE
+#define DUK_USE_ERRTHROW
+#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#define DUK_USE_ES6_PROXY
+#define DUK_USE_ES6_REGEXP_BRACES
+#define DUK_USE_ESBC_LIMITS
+#define DUK_USE_ESBC_MAX_BYTES 2147418112L
+#define DUK_USE_ESBC_MAX_LINENUMBER 2147418112L
+#undef DUK_USE_EXEC_FUN_LOCAL
+#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK
+#undef DUK_USE_EXEC_TIMEOUT_CHECK
+#undef DUK_USE_EXPLICIT_NULL_INIT
+#undef DUK_USE_EXTSTR_FREE
+#undef DUK_USE_EXTSTR_INTERN_CHECK
+#undef DUK_USE_FASTINT
+#define DUK_USE_FAST_REFCOUNT_DEFAULT
+#define DUK_USE_FILE_IO
+#undef DUK_USE_FUNCPTR16
+#undef DUK_USE_FUNCPTR_DEC16
+#undef DUK_USE_FUNCPTR_ENC16
+#undef DUK_USE_GC_TORTURE
+#undef DUK_USE_HEAPPTR16
+#undef DUK_USE_HEAPPTR_DEC16
+#undef DUK_USE_HEAPPTR_ENC16
+#define DUK_USE_HEX_FASTPATH
+#define DUK_USE_HOBJECT_HASH_PART
+#define DUK_USE_HSTRING_CLEN
+#undef DUK_USE_HSTRING_EXTDATA
+#define DUK_USE_IDCHAR_FASTPATH
+#undef DUK_USE_INTERRUPT_COUNTER
+#undef DUK_USE_INTERRUPT_DEBUG_FIXUP
+#define DUK_USE_JC
+#define DUK_USE_JSON_DECNUMBER_FASTPATH
+#define DUK_USE_JSON_DECSTRING_FASTPATH
+#define DUK_USE_JSON_DEC_RECLIMIT 1000
+#define DUK_USE_JSON_EATWHITE_FASTPATH
+#define DUK_USE_JSON_ENC_RECLIMIT 1000
+#define DUK_USE_JSON_QUOTESTRING_FASTPATH
+#undef DUK_USE_JSON_STRINGIFY_FASTPATH
+#define DUK_USE_JX
+#define DUK_USE_LEXER_SLIDING_WINDOW
+#undef DUK_USE_LIGHTFUNC_BUILTINS
+#undef DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE
+#define DUK_USE_MARK_AND_SWEEP
+#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256
+#define DUK_USE_MATH_BUILTIN
+#define DUK_USE_MS_STRINGTABLE_RESIZE
+#define DUK_USE_NATIVE_CALL_RECLIMIT 1000
+#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
+#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#define DUK_USE_NONSTD_FUNC_STMT
+#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
+#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#undef DUK_USE_OBJSIZES16
+#define DUK_USE_OCTAL_SUPPORT
+#define DUK_USE_PANIC_ABORT
+#undef DUK_USE_PANIC_EXIT
+#undef DUK_USE_PANIC_HANDLER
+#undef DUK_USE_PANIC_SEGFAULT
+#undef DUK_USE_PARANOID_ERRORS
+#define DUK_USE_PC2LINE
+#undef DUK_USE_PREFER_SIZE
+#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
+#undef DUK_USE_REFCOUNT16
+#define DUK_USE_REFERENCE_COUNTING
+#undef DUK_USE_REFZERO_FINALIZER_TORTURE
+#undef DUK_USE_REGEXP_CANON_WORKAROUND
+#define DUK_USE_REGEXP_COMPILER_RECLIMIT 10000
+#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT 10000
+#define DUK_USE_REGEXP_SUPPORT
+#undef DUK_USE_ROM_GLOBAL_CLONE
+#undef DUK_USE_ROM_GLOBAL_INHERIT
+#undef DUK_USE_ROM_OBJECTS
+#define DUK_USE_ROM_PTRCOMP_FIRST 63488L
+#undef DUK_USE_ROM_STRINGS
+#define DUK_USE_SECTION_B
+#undef DUK_USE_SELF_TESTS
+#undef DUK_USE_SHUFFLE_TORTURE
+#define DUK_USE_SOURCE_NONBMP
+#undef DUK_USE_STRHASH16
+#undef DUK_USE_STRHASH_DENSE
+#define DUK_USE_STRHASH_SKIP_SHIFT 5
+#define DUK_USE_STRICT_DECL
+#undef DUK_USE_STRICT_UTF8_SOURCE
+#undef DUK_USE_STRLEN16
+#undef DUK_USE_STRTAB_CHAIN
+#undef DUK_USE_STRTAB_CHAIN_SIZE
+#define DUK_USE_STRTAB_PROBE
+#define DUK_USE_TAILCALL
+#define DUK_USE_TARGET_INFO "unknown"
+#define DUK_USE_TRACEBACKS
+#define DUK_USE_TRACEBACK_DEPTH 10
+#define DUK_USE_USER_DECLARE() /* no user declarations */
+#undef DUK_USE_USER_INITJS
+#undef DUK_USE_VALSTACK_UNSAFE
+#define DUK_USE_VERBOSE_ERRORS
+#define DUK_USE_VERBOSE_EXECUTOR_ERRORS
+#define DUK_USE_VOLUNTARY_GC
+#define DUK_USE_ZERO_BUFFER_DATA
+
+/*
+ *  Alternative customization header
+ *
+ *  If you want to modify the final DUK_USE_xxx flags directly (without
+ *  using the available DUK_OPT_xxx flags), define DUK_OPT_HAVE_CUSTOM_H
+ *  and tweak the final flags there.
+ */
+
+#if defined(DUK_OPT_HAVE_CUSTOM_H)
+#include "duk_custom.h"
+#endif
+
+/*
+ *  You may add overriding #define/#undef directives below for
+ *  customization.  You of course cannot un-#include or un-typedef
+ *  anything; these require direct changes above.
+ */
+
+/* __OVERRIDE_DEFINES__ */
+
+/*
+ *  Date provider selection
+ *
+ *  User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll
+ *  rely on an external provider.  If this is not done, revert to previous
+ *  behavior and use Unix/Windows built-in provider.
+ */
+
+#if defined(DUK_COMPILING_DUKTAPE)
+
+#if defined(DUK_USE_DATE_GET_NOW)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_gettimeofday((ctx))
+#elif defined(DUK_USE_DATE_NOW_TIME)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_time((ctx))
+#elif defined(DUK_USE_DATE_NOW_WINDOWS)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_windows((ctx))
+#else
+#error no provider for DUK_USE_DATE_GET_NOW()
+#endif
+
+#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
+#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_gmtime((d))
+#elif defined(DUK_USE_DATE_TZO_WINDOWS)
+#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_windows((d))
+#else
+#error no provider for DUK_USE_DATE_GET_LOCAL_TZOFFSET()
+#endif
+
+#if defined(DUK_USE_DATE_PARSE_STRING)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_PRS_STRPTIME)
+#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_strptime((ctx), (str))
+#elif defined(DUK_USE_DATE_PRS_GETDATE)
+#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_getdate((ctx), (str))
+#else
+/* No provider for DUK_USE_DATE_PARSE_STRING(), fall back to ISO 8601 only. */
+#endif
+
+#if defined(DUK_USE_DATE_FORMAT_STRING)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_FMT_STRFTIME)
+#define DUK_USE_DATE_FORMAT_STRING(ctx,parts,tzoffset,flags) \
+	duk_bi_date_format_parts_strftime((ctx), (parts), (tzoffset), (flags))
+#else
+/* No provider for DUK_USE_DATE_FORMAT_STRING(), fall back to ISO 8601 only. */
+#endif
+
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+/*
+ *  Checks for legacy feature options (DUK_OPT_xxx)
+ */
+
+#if defined(DUK_OPT_ASSERTIONS)
+#error unsupported legacy feature option DUK_OPT_ASSERTIONS used, consider options: DUK_USE_ASSERTIONS
+#endif
+#if defined(DUK_OPT_BUFFEROBJECT_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_BUFFEROBJECT_SUPPORT used
+#endif
+#if defined(DUK_OPT_BUFLEN16)
+#error unsupported legacy feature option DUK_OPT_BUFLEN16 used
+#endif
+#if defined(DUK_OPT_DATAPTR16)
+#error unsupported legacy feature option DUK_OPT_DATAPTR16 used
+#endif
+#if defined(DUK_OPT_DATAPTR_DEC16)
+#error unsupported legacy feature option DUK_OPT_DATAPTR_DEC16 used
+#endif
+#if defined(DUK_OPT_DATAPTR_ENC16)
+#error unsupported legacy feature option DUK_OPT_DATAPTR_ENC16 used
+#endif
+#if defined(DUK_OPT_DDDPRINT)
+#error unsupported legacy feature option DUK_OPT_DDDPRINT used
+#endif
+#if defined(DUK_OPT_DDPRINT)
+#error unsupported legacy feature option DUK_OPT_DDPRINT used
+#endif
+#if defined(DUK_OPT_DEBUG)
+#error unsupported legacy feature option DUK_OPT_DEBUG used
+#endif
+#if defined(DUK_OPT_DEBUGGER_DUMPHEAP)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_DUMPHEAP used
+#endif
+#if defined(DUK_OPT_DEBUGGER_FWD_LOGGING)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_LOGGING used
+#endif
+#if defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_PRINTALERT used
+#endif
+#if defined(DUK_OPT_DEBUGGER_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_SUPPORT used
+#endif
+#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_TRANSPORT_TORTURE used
+#endif
+#if defined(DUK_OPT_DEBUG_BUFSIZE)
+#error unsupported legacy feature option DUK_OPT_DEBUG_BUFSIZE used
+#endif
+#if defined(DUK_OPT_DECLARE)
+#error unsupported legacy feature option DUK_OPT_DECLARE used
+#endif
+#if defined(DUK_OPT_DEEP_C_STACK)
+#error unsupported legacy feature option DUK_OPT_DEEP_C_STACK used
+#endif
+#if defined(DUK_OPT_DLL_BUILD)
+#error unsupported legacy feature option DUK_OPT_DLL_BUILD used
+#endif
+#if defined(DUK_OPT_DPRINT)
+#error unsupported legacy feature option DUK_OPT_DPRINT used
+#endif
+#if defined(DUK_OPT_DPRINT_COLORS)
+#error unsupported legacy feature option DUK_OPT_DPRINT_COLORS used
+#endif
+#if defined(DUK_OPT_DPRINT_RDTSC)
+#error unsupported legacy feature option DUK_OPT_DPRINT_RDTSC used
+#endif
+#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK)
+#error unsupported legacy feature option DUK_OPT_EXEC_TIMEOUT_CHECK used
+#endif
+#if defined(DUK_OPT_EXTERNAL_STRINGS)
+#error unsupported legacy feature option DUK_OPT_EXTERNAL_STRINGS used, consider options: DUK_USE_HSTRING_EXTDATA
+#endif
+#if defined(DUK_OPT_EXTSTR_FREE)
+#error unsupported legacy feature option DUK_OPT_EXTSTR_FREE used
+#endif
+#if defined(DUK_OPT_EXTSTR_INTERN_CHECK)
+#error unsupported legacy feature option DUK_OPT_EXTSTR_INTERN_CHECK used
+#endif
+#if defined(DUK_OPT_FASTINT)
+#error unsupported legacy feature option DUK_OPT_FASTINT used, consider options: DUK_USE_FASTINT
+#endif
+#if defined(DUK_OPT_FORCE_ALIGN)
+#error unsupported legacy feature option DUK_OPT_FORCE_ALIGN used
+#endif
+#if defined(DUK_OPT_FORCE_BYTEORDER)
+#error unsupported legacy feature option DUK_OPT_FORCE_BYTEORDER used
+#endif
+#if defined(DUK_OPT_FUNCPTR16)
+#error unsupported legacy feature option DUK_OPT_FUNCPTR16 used
+#endif
+#if defined(DUK_OPT_FUNCPTR_DEC16)
+#error unsupported legacy feature option DUK_OPT_FUNCPTR_DEC16 used
+#endif
+#if defined(DUK_OPT_FUNCPTR_ENC16)
+#error unsupported legacy feature option DUK_OPT_FUNCPTR_ENC16 used
+#endif
+#if defined(DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY used
+#endif
+#if defined(DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY used
+#endif
+#if defined(DUK_OPT_GC_TORTURE)
+#error unsupported legacy feature option DUK_OPT_GC_TORTURE used
+#endif
+#if defined(DUK_OPT_HAVE_CUSTOM_H)
+#error unsupported legacy feature option DUK_OPT_HAVE_CUSTOM_H used
+#endif
+#if defined(DUK_OPT_HEAPPTR16)
+#error unsupported legacy feature option DUK_OPT_HEAPPTR16 used
+#endif
+#if defined(DUK_OPT_HEAPPTR_DEC16)
+#error unsupported legacy feature option DUK_OPT_HEAPPTR_DEC16 used
+#endif
+#if defined(DUK_OPT_HEAPPTR_ENC16)
+#error unsupported legacy feature option DUK_OPT_HEAPPTR_ENC16 used
+#endif
+#if defined(DUK_OPT_INTERRUPT_COUNTER)
+#error unsupported legacy feature option DUK_OPT_INTERRUPT_COUNTER used
+#endif
+#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH)
+#error unsupported legacy feature option DUK_OPT_JSON_STRINGIFY_FASTPATH used
+#endif
+#if defined(DUK_OPT_LIGHTFUNC_BUILTINS)
+#error unsupported legacy feature option DUK_OPT_LIGHTFUNC_BUILTINS used
+#endif
+#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY used
+#endif
+#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY used
+#endif
+#if defined(DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT)
+#error unsupported legacy feature option DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT used
+#endif
+#if defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#error unsupported legacy feature option DUK_OPT_NO_AUGMENT_ERRORS used
+#endif
+#if defined(DUK_OPT_NO_BROWSER_LIKE)
+#error unsupported legacy feature option DUK_OPT_NO_BROWSER_LIKE used
+#endif
+#if defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_BUFFEROBJECT_SUPPORT used
+#endif
+#if defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_BYTECODE_DUMP_SUPPORT used, consider options: DUK_USE_BYTECODE_DUMP_SUPPORT
+#endif
+#if defined(DUK_OPT_NO_COMMONJS_MODULES)
+#error unsupported legacy feature option DUK_OPT_NO_COMMONJS_MODULES used
+#endif
+#if defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY used
+#endif
+#if defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)
+#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF used
+#endif
+#if defined(DUK_OPT_NO_ES6_PROXY)
+#error unsupported legacy feature option DUK_OPT_NO_ES6_PROXY used
+#endif
+#if defined(DUK_OPT_NO_FILE_IO)
+#error unsupported legacy feature option DUK_OPT_NO_FILE_IO used, consider options: DUK_USE_FILE_IO
+#endif
+#if defined(DUK_OPT_NO_FUNC_STMT)
+#error unsupported legacy feature option DUK_OPT_NO_FUNC_STMT used
+#endif
+#if defined(DUK_OPT_NO_JC)
+#error unsupported legacy feature option DUK_OPT_NO_JC used
+#endif
+#if defined(DUK_OPT_NO_JSONC)
+#error unsupported legacy feature option DUK_OPT_NO_JSONC used
+#endif
+#if defined(DUK_OPT_NO_JSONX)
+#error unsupported legacy feature option DUK_OPT_NO_JSONX used
+#endif
+#if defined(DUK_OPT_NO_JX)
+#error unsupported legacy feature option DUK_OPT_NO_JX used
+#endif
+#if defined(DUK_OPT_NO_MARK_AND_SWEEP)
+#error unsupported legacy feature option DUK_OPT_NO_MARK_AND_SWEEP used
+#endif
+#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)
+#error unsupported legacy feature option DUK_OPT_NO_MS_STRINGTABLE_RESIZE used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_FUNC_STMT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_FUNC_STMT used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029 used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT used
+#endif
+#if defined(DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY used
+#endif
+#if defined(DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF)
+#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF used
+#endif
+#if defined(DUK_OPT_NO_OCTAL_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_OCTAL_SUPPORT used
+#endif
+#if defined(DUK_OPT_NO_PACKED_TVAL)
+#error unsupported legacy feature option DUK_OPT_NO_PACKED_TVAL used
+#endif
+#if defined(DUK_OPT_NO_PC2LINE)
+#error unsupported legacy feature option DUK_OPT_NO_PC2LINE used
+#endif
+#if defined(DUK_OPT_NO_REFERENCE_COUNTING)
+#error unsupported legacy feature option DUK_OPT_NO_REFERENCE_COUNTING used, consider options: DUK_USE_REFERENCE_COUNTING
+#endif
+#if defined(DUK_OPT_NO_REGEXP_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_REGEXP_SUPPORT used
+#endif
+#if defined(DUK_OPT_NO_SECTION_B)
+#error unsupported legacy feature option DUK_OPT_NO_SECTION_B used
+#endif
+#if defined(DUK_OPT_NO_SOURCE_NONBMP)
+#error unsupported legacy feature option DUK_OPT_NO_SOURCE_NONBMP used
+#endif
+#if defined(DUK_OPT_NO_STRICT_DECL)
+#error unsupported legacy feature option DUK_OPT_NO_STRICT_DECL used
+#endif
+#if defined(DUK_OPT_NO_TRACEBACKS)
+#error unsupported legacy feature option DUK_OPT_NO_TRACEBACKS used
+#endif
+#if defined(DUK_OPT_NO_VERBOSE_ERRORS)
+#error unsupported legacy feature option DUK_OPT_NO_VERBOSE_ERRORS used
+#endif
+#if defined(DUK_OPT_NO_VOLUNTARY_GC)
+#error unsupported legacy feature option DUK_OPT_NO_VOLUNTARY_GC used
+#endif
+#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA)
+#error unsupported legacy feature option DUK_OPT_NO_ZERO_BUFFER_DATA used
+#endif
+#if defined(DUK_OPT_OBJSIZES16)
+#error unsupported legacy feature option DUK_OPT_OBJSIZES16 used
+#endif
+#if defined(DUK_OPT_PANIC_HANDLER)
+#error unsupported legacy feature option DUK_OPT_PANIC_HANDLER used
+#endif
+#if defined(DUK_OPT_REFCOUNT16)
+#error unsupported legacy feature option DUK_OPT_REFCOUNT16 used
+#endif
+#if defined(DUK_OPT_SEGFAULT_ON_PANIC)
+#error unsupported legacy feature option DUK_OPT_SEGFAULT_ON_PANIC used
+#endif
+#if defined(DUK_OPT_SELF_TESTS)
+#error unsupported legacy feature option DUK_OPT_SELF_TESTS used
+#endif
+#if defined(DUK_OPT_SETJMP)
+#error unsupported legacy feature option DUK_OPT_SETJMP used
+#endif
+#if defined(DUK_OPT_SHUFFLE_TORTURE)
+#error unsupported legacy feature option DUK_OPT_SHUFFLE_TORTURE used
+#endif
+#if defined(DUK_OPT_SIGSETJMP)
+#error unsupported legacy feature option DUK_OPT_SIGSETJMP used
+#endif
+#if defined(DUK_OPT_STRHASH16)
+#error unsupported legacy feature option DUK_OPT_STRHASH16 used
+#endif
+#if defined(DUK_OPT_STRICT_UTF8_SOURCE)
+#error unsupported legacy feature option DUK_OPT_STRICT_UTF8_SOURCE used
+#endif
+#if defined(DUK_OPT_STRLEN16)
+#error unsupported legacy feature option DUK_OPT_STRLEN16 used
+#endif
+#if defined(DUK_OPT_STRTAB_CHAIN)
+#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN used
+#endif
+#if defined(DUK_OPT_STRTAB_CHAIN_SIZE)
+#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN_SIZE used
+#endif
+#if defined(DUK_OPT_TARGET_INFO)
+#error unsupported legacy feature option DUK_OPT_TARGET_INFO used
+#endif
+#if defined(DUK_OPT_TRACEBACK_DEPTH)
+#error unsupported legacy feature option DUK_OPT_TRACEBACK_DEPTH used
+#endif
+#if defined(DUK_OPT_UNDERSCORE_SETJMP)
+#error unsupported legacy feature option DUK_OPT_UNDERSCORE_SETJMP used
+#endif
+#if defined(DUK_OPT_USER_INITJS)
+#error unsupported legacy feature option DUK_OPT_USER_INITJS used
+#endif
+
+/*
+ *  Checks for config option consistency (DUK_USE_xxx)
+ */
+
+#if defined(DUK_USE_32BIT_PTRS)
+#error unsupported config option used (option has been removed): DUK_USE_32BIT_PTRS
+#endif
+#if defined(DUK_USE_ALIGN_4)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_4
+#endif
+#if defined(DUK_USE_ALIGN_8)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_8
+#endif
+#if defined(DUK_USE_BYTEORDER_FORCED)
+#error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED
+#endif
+#if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_DATAPTR_ENC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_ENC16 requires option DUK_USE_DATAPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_DEBUGGER_SUPPORT requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_DEEP_C_STACK)
+#error unsupported config option used (option has been removed): DUK_USE_DEEP_C_STACK
+#endif
+#if defined(DUK_USE_DOUBLE_BE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_BE
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_LE
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_ME
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG)
+#error config option DUK_USE_DPRINT requires option DUK_USE_DEBUG (which is missing)
+#endif
+#if defined(DUK_USE_ESBC_MAX_BYTES) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_BYTES requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_ESBC_MAX_LINENUMBER) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_LINENUMBER requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_EXEC_TIMEOUT_CHECK) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_EXEC_TIMEOUT_CHECK requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_FREE) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_FREE requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_INTERN_CHECK) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_INTERN_CHECK requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_FULL_TVAL)
+#error unsupported config option used (option has been removed): DUK_USE_FULL_TVAL
+#endif
+#if defined(DUK_USE_FUNCPTR_DEC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_DEC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_FUNCPTR_ENC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_ENC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
+#error unsupported config option used (option has been removed): DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
+#endif
+#if defined(DUK_USE_HEAPPTR16) && defined(DUK_USE_DEBUG)
+#error config option DUK_USE_HEAPPTR16 conflicts with option DUK_USE_DEBUG (which is also defined)
+#endif
+#if defined(DUK_USE_HEAPPTR_DEC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_DEC16 requires option DUK_USE_HEAPPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HEAPPTR_ENC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_ENC16 requires option DUK_USE_HEAPPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_INTEGER_BE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_BE
+#endif
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_LE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_LE
+#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_ME
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)
+#error unsupported config option used (option has been removed): DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
+#endif
+#if defined(DUK_USE_PACKED_TVAL_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_PACKED_TVAL_POSSIBLE
+#endif
+#if defined(DUK_USE_RDTSC)
+#error unsupported config option used (option has been removed): DUK_USE_RDTSC
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_STRINGS)
+#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_STRINGS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_OBJECTS)
+#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_OBJECTS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_CLONE) && defined(DUK_USE_ROM_GLOBAL_INHERIT)
+#error config option DUK_USE_ROM_GLOBAL_CLONE conflicts with option DUK_USE_ROM_GLOBAL_INHERIT (which is also defined)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_STRINGS)
+#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_STRINGS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_OBJECTS)
+#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_OBJECTS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && defined(DUK_USE_ROM_GLOBAL_CLONE)
+#error config option DUK_USE_ROM_GLOBAL_INHERIT conflicts with option DUK_USE_ROM_GLOBAL_CLONE (which is also defined)
+#endif
+#if defined(DUK_USE_ROM_OBJECTS) && !defined(DUK_USE_ROM_STRINGS)
+#error config option DUK_USE_ROM_OBJECTS requires option DUK_USE_ROM_STRINGS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_STRINGS) && !defined(DUK_USE_ROM_OBJECTS)
+#error config option DUK_USE_ROM_STRINGS requires option DUK_USE_ROM_OBJECTS (which is missing)
+#endif
+#if defined(DUK_USE_SETJMP)
+#error unsupported config option used (option has been removed): DUK_USE_SETJMP
+#endif
+#if defined(DUK_USE_SIGSETJMP)
+#error unsupported config option used (option has been removed): DUK_USE_SIGSETJMP
+#endif
+#if defined(DUK_USE_STRTAB_CHAIN_SIZE) && !defined(DUK_USE_STRTAB_CHAIN)
+#error config option DUK_USE_STRTAB_CHAIN_SIZE requires option DUK_USE_STRTAB_CHAIN (which is missing)
+#endif
+#if defined(DUK_USE_TAILCALL) && defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+#error config option DUK_USE_TAILCALL conflicts with option DUK_USE_NONSTD_FUNC_CALLER_PROPERTY (which is also defined)
+#endif
+#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
+#endif
+#if defined(DUK_USE_UNDERSCORE_SETJMP)
+#error unsupported config option used (option has been removed): DUK_USE_UNDERSCORE_SETJMP
+#endif
+
+#if defined(DUK_USE_CPP_EXCEPTIONS) && !defined(__cplusplus)
+#error DUK_USE_CPP_EXCEPTIONS enabled but not compiling with a C++ compiler
+#endif
+
+/*
+ *  Convert DUK_USE_BYTEORDER, from whatever source, into currently used
+ *  internal defines.  If detection failed, #error out.
+ */
+
+#if defined(DUK_USE_BYTEORDER)
+#if (DUK_USE_BYTEORDER == 1)
+#define DUK_USE_INTEGER_LE
+#define DUK_USE_DOUBLE_LE
+#elif (DUK_USE_BYTEORDER == 2)
+#define DUK_USE_INTEGER_LE  /* integer endianness is little on purpose */
+#define DUK_USE_DOUBLE_ME
+#elif (DUK_USE_BYTEORDER == 3)
+#define DUK_USE_INTEGER_BE
+#define DUK_USE_DOUBLE_BE
+#else
+#error unsupported: byte order invalid
+#endif  /* byte order */
+#else
+#error unsupported: byte order detection failed
+#endif  /* defined(DUK_USE_BYTEORDER) */
+
+#endif  /* DUK_CONFIG_H_INCLUDED */

+ 3415 - 0
src/third_party/duktape-1.5.2/config/duk_config.h-modular-static

@@ -0,0 +1,3415 @@
+/*
+ *  duk_config.h configuration header generated by genconfig.py.
+ *
+ *  Git commit: cad34ae155acb0846545ca6bf2d29f9463b22bbb
+ *  Git describe: v1.5.2
+ *  Git branch: HEAD
+ *
+ *  Supported platforms:
+ *      - Mac OSX, iPhone, Darwin
+ *      - OpenBSD
+ *      - Generic BSD
+ *      - Atari ST TOS
+ *      - AmigaOS
+ *      - Windows
+ *      - Flashplayer (Crossbridge)
+ *      - QNX
+ *      - TI-Nspire
+ *      - Emscripten
+ *      - Linux
+ *      - Solaris
+ *      - Generic POSIX
+ *      - Cygwin
+ *      - Generic UNIX
+ *      - Generic fallback
+ *
+ *  Supported architectures:
+ *      - x86
+ *      - x64
+ *      - x32
+ *      - ARM 32-bit
+ *      - ARM 64-bit
+ *      - MIPS 32-bit
+ *      - MIPS 64-bit
+ *      - PowerPC 32-bit
+ *      - PowerPC 64-bit
+ *      - SPARC 32-bit
+ *      - SPARC 64-bit
+ *      - SuperH
+ *      - Motorola 68k
+ *      - Emscripten
+ *      - Generic
+ *
+ *  Supported compilers:
+ *      - Clang
+ *      - GCC
+ *      - MSVC
+ *      - Emscripten
+ *      - TinyC
+ *      - VBCC
+ *      - Bruce's C compiler
+ *      - Generic
+ *
+ */
+
+#if !defined(DUK_CONFIG_H_INCLUDED)
+#define DUK_CONFIG_H_INCLUDED
+
+/*
+ *  Intermediate helper defines
+ */
+
+/* DLL build detection */
+#if defined(DUK_OPT_DLL_BUILD)
+#define DUK_F_DLL_BUILD
+#elif defined(DUK_OPT_NO_DLL_BUILD)
+#undef DUK_F_DLL_BUILD
+#else
+/* not configured for DLL build */
+#undef DUK_F_DLL_BUILD
+#endif
+
+/* Apple OSX, iOS */
+#if defined(__APPLE__)
+#define DUK_F_APPLE
+#endif
+
+/* OpenBSD */
+#if defined(__OpenBSD__) || defined(__OpenBSD)
+#define DUK_F_OPENBSD
+#endif
+
+/* NetBSD */
+#if defined(__NetBSD__) || defined(__NetBSD)
+#define DUK_F_NETBSD
+#endif
+
+/* FreeBSD */
+#if defined(__FreeBSD__) || defined(__FreeBSD)
+#define DUK_F_FREEBSD
+#endif
+
+/* BSD variant */
+#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \
+    defined(__bsdi__) || defined(__DragonFly__)
+#define DUK_F_BSD
+#endif
+
+/* Atari ST TOS.  __TOS__ defined by PureC.  No platform define in VBCC
+ * apparently, so to use with VBCC user must define __TOS__ manually.
+  */
+#if defined(__TOS__)
+#define DUK_F_TOS
+#endif
+
+/* Motorola 68K.  Not defined by VBCC, so user must define one of these
+ * manually when using VBCC.
+ */
+#if defined(__m68k__) || defined(M68000) || defined(__MC68K__)
+#define DUK_F_M68K
+#endif
+
+/* AmigaOS.  Neither AMIGA nor __amigaos__ is defined on VBCC, so user must
+ * define 'AMIGA' manually when using VBCC.
+ */
+#if defined(AMIGA) || defined(__amigaos__)
+#define DUK_F_AMIGAOS
+#endif
+
+/* PowerPC */
+#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__)
+#define DUK_F_PPC
+#if defined(__PPC64__) || defined(__LP64__) || defined(_LP64)
+#define DUK_F_PPC64
+#else
+#define DUK_F_PPC32
+#endif
+#endif
+
+/* Windows, both 32-bit and 64-bit */
+#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \
+    defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
+#define DUK_F_WINDOWS
+#if defined(_WIN64) || defined(WIN64)
+#define DUK_F_WIN64
+#else
+#define DUK_F_WIN32
+#endif
+#endif
+
+/* Flash player (e.g. Crossbridge) */
+#if defined(__FLASHPLAYER__)
+#define DUK_F_FLASHPLAYER
+#endif
+
+/* QNX */
+#if defined(__QNX__)
+#define DUK_F_QNX
+#endif
+
+/* TI-Nspire (using Ndless) */
+#if defined(_TINSPIRE)
+#define DUK_F_TINSPIRE
+#endif
+
+/* Emscripten (provided explicitly by user), improve if possible */
+#if defined(EMSCRIPTEN)
+#define DUK_F_EMSCRIPTEN
+#endif
+
+/* BCC (Bruce's C compiler): this is a "torture target" for compilation */
+#if defined(__BCC__) || defined(__BCC_VERSION__)
+#define DUK_F_BCC
+#endif
+
+/* Linux */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+#define DUK_F_LINUX
+#endif
+
+/* illumos / Solaris */
+#if defined(__sun) && defined(__SVR4)
+#define DUK_F_SUN
+#endif
+
+/* POSIX */
+#if defined(__posix)
+#define DUK_F_POSIX
+#endif
+
+/* Cygwin */
+#if defined(__CYGWIN__)
+#define DUK_F_CYGWIN
+#endif
+
+/* Generic Unix (includes Cygwin) */
+#if defined(__unix) || defined(__unix__) || defined(unix) || \
+    defined(DUK_F_LINUX) || defined(DUK_F_BSD)
+#define DUK_F_UNIX
+#endif
+
+/* stdint.h not available */
+#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
+#if (_MSC_VER < 1700)
+/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
+#define DUK_F_NO_STDINT_H
+#endif
+#endif
+#if !defined(DUK_F_NO_STDINT_H) && (defined(DUK_F_TOS) || defined(DUK_F_BCC))
+#define DUK_F_NO_STDINT_H
+#endif
+
+/* C++ */
+#undef DUK_F_CPP
+#if defined(__cplusplus)
+#define DUK_F_CPP
+#endif
+
+/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),
+ * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.
+ * https://sites.google.com/site/x32abi/
+ */
+#if defined(__amd64__) || defined(__amd64) || \
+    defined(__x86_64__) || defined(__x86_64) || \
+    defined(_M_X64) || defined(_M_AMD64)
+#if defined(__ILP32__) || defined(_ILP32)
+#define DUK_F_X32
+#else
+#define DUK_F_X64
+#endif
+#elif defined(i386) || defined(__i386) || defined(__i386__) || \
+      defined(__i486__) || defined(__i586__) || defined(__i686__) || \
+      defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \
+      defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)
+#if defined(__LP64__) || defined(_LP64)
+/* This should not really happen, but would indicate x64. */
+#define DUK_F_X64
+#else
+#define DUK_F_X86
+#endif
+#endif
+
+/* ARM */
+#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM)
+#define DUK_F_ARM
+#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__)
+#define DUK_F_ARM64
+#else
+#define DUK_F_ARM32
+#endif
+#endif
+
+/* MIPS.  Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */
+#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \
+    defined(_R3000) || defined(_R4000) || defined(_R5900) || \
+    defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \
+    defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \
+    defined(__mips) || defined(__MIPS__)
+#define DUK_F_MIPS
+#if defined(__LP64__) || defined(_LP64) || defined(__mips64) || \
+    defined(__mips64__) || defined(__mips_n64)
+#define DUK_F_MIPS64
+#else
+#define DUK_F_MIPS32
+#endif
+#endif
+
+/* SPARC */
+#if defined(sparc) || defined(__sparc) || defined(__sparc__)
+#define DUK_F_SPARC
+#if defined(__LP64__) || defined(_LP64)
+#define DUK_F_SPARC64
+#else
+#define DUK_F_SPARC32
+#endif
+#endif
+
+/* SuperH */
+#if defined(__sh__) || \
+    defined(__sh1__) || defined(__SH1__) || \
+    defined(__sh2__) || defined(__SH2__) || \
+    defined(__sh3__) || defined(__SH3__) || \
+    defined(__sh4__) || defined(__SH4__) || \
+    defined(__sh5__) || defined(__SH5__)
+#define DUK_F_SUPERH
+#endif
+
+/* Clang */
+#if defined(__clang__)
+#define DUK_F_CLANG
+#endif
+
+/* C99 or above */
+#undef DUK_F_C99
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define DUK_F_C99
+#endif
+
+/* C++11 or above */
+#undef DUK_F_CPP11
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+#define DUK_F_CPP11
+#endif
+
+/* GCC.  Clang also defines __GNUC__ so don't detect GCC if using Clang. */
+#if defined(__GNUC__) && !defined(__clang__) && !defined(DUK_F_CLANG)
+#define DUK_F_GCC
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */
+#define DUK_F_GCC_VERSION  (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
+#else
+#error cannot figure out gcc version
+#endif
+#endif
+
+/* MinGW.  Also GCC flags (DUK_F_GCC) are enabled now. */
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define DUK_F_MINGW
+#endif
+
+/* MSVC */
+#if defined(_MSC_VER)
+/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+ * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g.
+ * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp
+ */
+#define DUK_F_MSVC
+#if defined(_MSC_FULL_VER)
+#if (_MSC_FULL_VER > 100000000)
+#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER
+#else
+#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10)
+#endif
+#endif
+#endif  /* _MSC_VER */
+
+/* TinyC */
+#if defined(__TINYC__)
+/* http://bellard.org/tcc/tcc-doc.html#SEC9 */
+#define DUK_F_TINYC
+#endif
+
+/* VBCC */
+#if defined(__VBCC__)
+#define DUK_F_VBCC
+#endif
+
+/* Atari Mint */
+#if defined(__MINT__)
+#define DUK_F_MINT
+#endif
+
+/*
+ *  Platform autodetection
+ */
+
+/* Workaround for older C++ compilers before including <inttypes.h>,
+ * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366
+ */
+#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
+#define __STDC_LIMIT_MACROS
+#endif
+#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined(DUK_F_APPLE)
+/* --- Mac OSX, iPhone, Darwin --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <TargetConditionals.h>
+#include <architecture/byte_order.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */
+#if TARGET_IPHONE_SIMULATOR
+#define DUK_USE_OS_STRING "iphone-sim"
+#elif TARGET_OS_IPHONE
+#define DUK_USE_OS_STRING "iphone"
+#elif TARGET_OS_MAC
+#define DUK_USE_OS_STRING "osx"
+#else
+#define DUK_USE_OS_STRING "osx-unknown"
+#endif
+
+/* Use _setjmp() on Apple by default, see GH-55. */
+#define DUK_JMPBUF_TYPE       jmp_buf
+#define DUK_SETJMP(jb)        _setjmp((jb))
+#define DUK_LONGJMP(jb)       _longjmp((jb), 1)
+#elif defined(DUK_F_OPENBSD)
+/* --- OpenBSD --- */
+/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "openbsd"
+#elif defined(DUK_F_BSD)
+/* --- Generic BSD --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "bsd"
+#elif defined(DUK_F_TOS)
+/* --- Atari ST TOS --- */
+#define DUK_USE_DATE_NOW_TIME
+#define DUK_USE_DATE_TZO_GMTIME
+/* no parsing (not an error) */
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+
+#define DUK_USE_OS_STRING  "tos"
+
+/* TOS on M68K is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_M68K)
+#define DUK_USE_BYTEORDER 3
+#endif
+#elif defined(DUK_F_AMIGAOS)
+/* --- AmigaOS --- */
+#if defined(DUK_F_M68K)
+/* AmigaOS on M68k */
+#define DUK_USE_DATE_NOW_TIME
+#define DUK_USE_DATE_TZO_GMTIME
+/* no parsing (not an error) */
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#elif defined(DUK_F_PPC)
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#ifndef UINTPTR_MAX
+#define UINTPTR_MAX UINT_MAX
+#endif
+#else
+#error AmigaOS but not M68K/PPC, not supported now
+#endif
+
+#define DUK_USE_OS_STRING "amigaos"
+
+/* AmigaOS on M68K or PPC is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && (defined(DUK_F_M68K) || defined(DUK_F_PPC))
+#define DUK_USE_BYTEORDER 3
+#endif
+#elif defined(DUK_F_WINDOWS)
+/* --- Windows --- */
+/* Initial fix: disable secure CRT related warnings when compiling Duktape
+ * itself (must be defined before including Windows headers).  Don't define
+ * for user code including duktape.h.
+ */
+#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Windows 32-bit and 64-bit are currently the same. */
+/* MSVC does not have sys/param.h */
+#define DUK_USE_DATE_NOW_WINDOWS
+#define DUK_USE_DATE_TZO_WINDOWS
+/* Note: PRS and FMT are intentionally left undefined for now.  This means
+ * there is no platform specific date parsing/formatting but there is still
+ * the ISO 8601 standard format.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+/* Only include when compiling Duktape to avoid polluting application build
+ * with a lot of unnecessary defines.
+ */
+#include <windows.h>
+#endif
+
+#define DUK_USE_OS_STRING "windows"
+
+/* On Windows, assume we're little endian.  Even Itanium which has a
+ * configurable endianness runs little endian in Windows.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#elif defined(DUK_F_FLASHPLAYER)
+/* --- Flashplayer (Crossbridge) --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "flashplayer"
+
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_FLASHPLAYER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#elif defined(DUK_F_QNX)
+/* --- QNX --- */
+#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)
+/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */
+#define _XOPEN_SOURCE    600
+#define _POSIX_C_SOURCE  200112L
+#endif
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "qnx"
+#elif defined(DUK_F_TINSPIRE)
+/* --- TI-Nspire --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "tinspire"
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE  200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h */
+#else
+#include <endian.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdint.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "emscripten"
+#elif defined(DUK_F_LINUX)
+/* --- Linux --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE  200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h or stdint.h */
+#else
+#include <endian.h>
+#include <stdint.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "linux"
+#elif defined(DUK_F_SUN)
+/* --- Solaris --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#include <sys/types.h>
+#include <ast/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "solaris"
+#elif defined(DUK_F_POSIX)
+/* --- Generic POSIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "posix"
+#elif defined(DUK_F_CYGWIN)
+/* --- Cygwin --- */
+/* don't use strptime() for now */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/types.h>
+#include <endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_JMPBUF_TYPE       jmp_buf
+#define DUK_SETJMP(jb)        _setjmp((jb))
+#define DUK_LONGJMP(jb)       _longjmp((jb), 1)
+
+#define DUK_USE_OS_STRING "windows"
+#elif defined(DUK_F_UNIX)
+/* --- Generic UNIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#include <sys/time.h>
+#define DUK_USE_OS_STRING "unknown"
+#else
+/* --- Generic fallback --- */
+/* The most portable current time provider is time(), but it only has a
+ * one second resolution.
+ */
+#define DUK_USE_DATE_NOW_TIME
+
+/* The most portable way to figure out local time offset is gmtime(),
+ * but it's not thread safe so use with caution.
+ */
+#define DUK_USE_DATE_TZO_GMTIME
+
+/* Avoid custom date parsing and formatting for portability. */
+#undef DUK_USE_DATE_PRS_STRPTIME
+#undef DUK_USE_DATE_FMT_STRFTIME
+
+/* Rely on C89 headers only; time.h must be here. */
+#include <time.h>
+
+#define DUK_USE_OS_STRING "unknown"
+#endif  /* autodetect platform */
+
+/* Shared includes: C89 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>  /* varargs */
+#include <setjmp.h>
+#include <stddef.h>  /* e.g. ptrdiff_t */
+#include <math.h>
+#include <limits.h>
+
+/* date.h is omitted, and included per platform */
+
+/* Shared includes: stdint.h is C99 */
+#if defined(DUK_F_NO_STDINT_H)
+/* stdint.h not available */
+#else
+/* Technically C99 (C++11) but found in many systems.  On some systems
+ * __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS must be defined before
+ * including stdint.h (see above).
+ */
+#include <stdint.h>
+#endif
+
+#if defined(DUK_F_CPP)
+#include <exception>  /* std::exception */
+#endif
+
+/*
+ *  Architecture autodetection
+ */
+
+#if defined(DUK_F_X86)
+/* --- x86 --- */
+#define DUK_USE_ARCH_STRING "x86"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X64)
+/* --- x64 --- */
+#define DUK_USE_ARCH_STRING "x64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X32)
+/* --- x32 --- */
+#define DUK_USE_ARCH_STRING "x32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM32)
+/* --- ARM 32-bit --- */
+#define DUK_USE_ARCH_STRING "arm32"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM64)
+/* --- ARM 64-bit --- */
+#define DUK_USE_ARCH_STRING "arm64"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS32)
+/* --- MIPS 32-bit --- */
+#define DUK_USE_ARCH_STRING "mips32"
+/* MIPS byte order varies so rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux MIPS except for doubles, which need align by 4.  Alignment
+ * requirements vary based on target though.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS64)
+/* --- MIPS 64-bit --- */
+#define DUK_USE_ARCH_STRING "mips64"
+/* MIPS byte order varies so rely on autodetection. */
+/* Good default is a bit arbitrary because alignment requirements
+ * depend on target.  See https://github.com/svaarala/duktape/issues/102.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC32)
+/* --- PowerPC 32-bit --- */
+#define DUK_USE_ARCH_STRING "ppc32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC64)
+/* --- PowerPC 64-bit --- */
+#define DUK_USE_ARCH_STRING "ppc64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC32)
+/* --- SPARC 32-bit --- */
+#define DUK_USE_ARCH_STRING "sparc32"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC64)
+/* --- SPARC 64-bit --- */
+#define DUK_USE_ARCH_STRING "sparc64"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SUPERH)
+/* --- SuperH --- */
+#define DUK_USE_ARCH_STRING "sh"
+/* Byte order varies, rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux SH4, but align by 4 is probably a good basic default.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_M68K)
+/* --- Motorola 68k --- */
+#define DUK_USE_ARCH_STRING "m68k"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_USE_ARCH_STRING "emscripten"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#else
+/* --- Generic --- */
+/* These are necessary wild guesses. */
+#define DUK_USE_ARCH_STRING "generic"
+/* Rely on autodetection for byte order, alignment, and packed tval. */
+#endif  /* autodetect architecture */
+
+/*
+ *  Compiler autodetection
+ */
+
+#if defined(DUK_F_CLANG)
+/* --- Clang --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Clang: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#else
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and
+ * Clang.  Based on documentation it should suffice to have the attribute
+ * in the declaration only, but in practice some warnings are generated unless
+ * the attribute is also applied to the definition.
+ */
+#define DUK_INTERNAL_DECL  static __attribute__ ((unused))
+#define DUK_INTERNAL       static __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#endif
+#else
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden"))) __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "clang"
+#else
+#define DUK_USE_COMPILER_STRING "clang"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_UNION_INITIALIZERS
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#elif defined(DUK_F_GCC)
+/* --- GCC --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* GCC: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
+/* since gcc-2.5 */
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* since gcc-4.5 */
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* GCC: test not very accurate; enable only in relatively recent builds
+ * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
+ */
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+#endif
+
+#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \
+    defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 30101)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#elif defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40000)
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and
+ * Clang.  Based on documentation it should suffice to have the attribute
+ * in the declaration only, but in practice some warnings are generated unless
+ * the attribute is also applied to the definition.
+ */
+#define DUK_INTERNAL_DECL  static __attribute__ ((unused))
+#define DUK_INTERNAL       static __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#endif
+#else
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden"))) __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_MINGW)
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "mingw++"
+#else
+#define DUK_USE_COMPILER_STRING "mingw"
+#endif
+#else
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "g++"
+#else
+#define DUK_USE_COMPILER_STRING "gcc"
+#endif
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_UNION_INITIALIZERS
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)
+#define DUK_USE_GCC_PRAGMAS
+#else
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+#define DUK_USE_PACK_GCC_ATTR
+#elif defined(DUK_F_MSVC)
+/* --- MSVC --- */
+/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
+#define DUK_NORETURN(decl)  __declspec(noreturn) decl
+
+/* XXX: DUK_UNREACHABLE for msvc? */
+
+#undef DUK_USE_BRANCH_HINTS
+
+/* XXX: DUK_LIKELY, DUK_UNLIKELY for msvc? */
+/* XXX: DUK_NOINLINE, DUK_INLINE, DUK_ALWAYS_INLINE for msvc? */
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)
+#define DUK_EXTERNAL       __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)
+#define DUK_EXTERNAL       should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL_DECL  extern
+#define DUK_INTERNAL       /*empty*/
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "msvc++"
+#else
+#define DUK_USE_COMPILER_STRING "msvc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99)
+#define DUK_USE_VARIADIC_MACROS
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+/* VS2005+ should have variadic macros even when they're not C99. */
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_UNION_INITIALIZERS
+#if defined(_MSC_VER) && (_MSC_VER >= 1800)
+/* VS2013+ supports union initializers but there's a bug involving union-inside-struct:
+ * https://connect.microsoft.com/VisualStudio/feedback/details/805981
+ * The bug was fixed (at least) in VS2015 so check for VS2015 for now:
+ * https://blogs.msdn.microsoft.com/vcblog/2015/07/01/c-compiler-front-end-fixes-in-vs2015/
+ * Manually tested using VS2013, CL reports 18.00.31101, so enable for VS2013 too.
+ */
+#define DUK_USE_UNION_INITIALIZERS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+
+#define DUK_USE_PACK_MSVC_PRAGMA
+
+/* These have been tested from VS2008 onwards; may work in older VS versions
+ * too but not enabled by default.
+ */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+#define DUK_NOINLINE        __declspec(noinline)
+#define DUK_INLINE          __inline
+#define DUK_ALWAYS_INLINE   __forceinline
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define DUK_SNPRINTF     snprintf
+#define DUK_VSNPRINTF    vsnprintf
+#else
+/* (v)snprintf() is missing before MSVC 2015.  Note that _(v)snprintf() does
+ * NOT NUL terminate on truncation, but Duktape code never assumes that.
+ * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+ */
+#define DUK_SNPRINTF     _snprintf
+#define DUK_VSNPRINTF    _vsnprintf
+#endif
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_NORETURN(decl)  decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x)    __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE        __attribute__((noinline))
+#define DUK_INLINE          inline
+#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))
+#endif
+
+#define DUK_EXTERNAL_DECL  __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL       __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and
+ * Clang.  Based on documentation it should suffice to have the attribute
+ * in the declaration only, but in practice some warnings are generated unless
+ * the attribute is also applied to the definition.
+ */
+#define DUK_INTERNAL_DECL  static __attribute__ ((unused))
+#define DUK_INTERNAL       static __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  static
+#define DUK_INTERNAL       static
+#endif
+#else
+#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) __attribute__ ((unused)) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden"))) __attribute__ ((unused))
+#else
+#define DUK_INTERNAL_DECL  __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL       __attribute__ ((visibility("hidden")))
+#endif
+#endif
+#define DUK_LOCAL_DECL     static
+#define DUK_LOCAL          static
+
+#define DUK_USE_COMPILER_STRING "emscripten"
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_UNION_INITIALIZERS
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#elif defined(DUK_F_TINYC)
+/* --- TinyC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "tinyc++"
+#else
+#define DUK_USE_COMPILER_STRING "tinyc"
+#endif
+
+/* http://bellard.org/tcc/tcc-doc.html#SEC7 */
+#define DUK_USE_VARIADIC_MACROS
+
+#define DUK_USE_UNION_INITIALIZERS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#elif defined(DUK_F_VBCC)
+/* --- VBCC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "vbcc-c++"
+#else
+#define DUK_USE_COMPILER_STRING "vbcc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+/* VBCC supports C99 so check only for C99 for union initializer support.
+ * Designated union initializers would possibly work even without a C99 check.
+ */
+#undef DUK_USE_UNION_INITIALIZERS
+#if defined(DUK_F_C99)
+#define DUK_USE_UNION_INITIALIZERS
+#endif
+
+#define DUK_USE_FLEX_ZEROSIZE
+#define DUK_USE_PACK_DUMMY_MEMBER
+#elif defined(DUK_F_BCC)
+/* --- Bruce's C compiler --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "bcc++"
+#else
+#define DUK_USE_COMPILER_STRING "bcc"
+#endif
+
+/* Most portable */
+#undef DUK_USE_VARIADIC_MACROS
+
+/* Most portable, wastes space */
+#undef DUK_USE_UNION_INITIALIZERS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+
+/* BCC, assume we're on x86. */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#else
+/* --- Generic --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "generic-c++"
+#else
+#define DUK_USE_COMPILER_STRING "generic"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+/* C++ doesn't have standard designated union initializers ({ .foo = 1 }). */
+#undef DUK_USE_UNION_INITIALIZERS
+#if defined(DUK_F_C99)
+#define DUK_USE_UNION_INITIALIZERS
+#endif
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif  /* autodetect compiler */
+
+/* uclibc */
+#if defined(__UCLIBC__)
+#define DUK_F_UCLIBC
+#endif
+
+/*
+ *  Wrapper typedefs and constants for integer types, also sanity check types.
+ *
+ *  C99 typedefs are quite good but not always available, and we want to avoid
+ *  forcibly redefining the C99 typedefs.  So, there are Duktape wrappers for
+ *  all C99 typedefs and Duktape code should only use these typedefs.  Type
+ *  detection when C99 is not supported is best effort and may end up detecting
+ *  some types incorrectly.
+ *
+ *  Pointer sizes are a portability problem: pointers to different types may
+ *  have a different size and function pointers are very difficult to manage
+ *  portably.
+ *
+ *  http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types
+ *
+ *  Note: there's an interesting corner case when trying to define minimum
+ *  signed integer value constants which leads to the current workaround of
+ *  defining e.g. -0x80000000 as (-0x7fffffffL - 1L).  See doc/code-issues.txt
+ *  for a longer discussion.
+ *
+ *  Note: avoid typecasts and computations in macro integer constants as they
+ *  can then no longer be used in macro relational expressions (such as
+ *  #if DUK_SIZE_MAX < 0xffffffffUL).  There is internal code which relies on
+ *  being able to compare DUK_SIZE_MAX against a limit.
+ */
+
+/* XXX: add feature options to force basic types from outside? */
+
+#if !defined(INT_MAX)
+#error INT_MAX not defined
+#endif
+
+/* Check that architecture is two's complement, standard C allows e.g.
+ * INT_MIN to be -2**31+1 (instead of -2**31).
+ */
+#if defined(INT_MAX) && defined(INT_MIN)
+#if INT_MAX != -(INT_MIN + 1)
+#error platform does not seem complement of two
+#endif
+#else
+#error cannot check complement of two
+#endif
+
+/* Pointer size determination based on __WORDSIZE or architecture when
+ * that's not available.
+ */
+#if defined(DUK_F_X86) || defined(DUK_F_X32) || \
+    defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \
+    defined(DUK_F_BCC) || \
+    (defined(__WORDSIZE) && (__WORDSIZE == 32))
+#define DUK_F_32BIT_PTRS
+#elif defined(DUK_F_X64) || \
+      (defined(__WORDSIZE) && (__WORDSIZE == 64))
+#define DUK_F_64BIT_PTRS
+#else
+/* not sure, not needed with C99 anyway */
+#endif
+
+/* Intermediate define for 'have inttypes.h' */
+#undef DUK_F_HAVE_INTTYPES
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+    !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC))
+/* vbcc + AmigaOS has C99 but no inttypes.h */
+#define DUK_F_HAVE_INTTYPES
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+/* C++11 apparently ratified stdint.h */
+#define DUK_F_HAVE_INTTYPES
+#endif
+
+/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise
+ * through automatic detection.
+ */
+#if defined(DUK_F_HAVE_INTTYPES)
+/* C99 or compatible */
+
+#define DUK_F_HAVE_64BIT
+#include <inttypes.h>
+
+typedef uint8_t duk_uint8_t;
+typedef int8_t duk_int8_t;
+typedef uint16_t duk_uint16_t;
+typedef int16_t duk_int16_t;
+typedef uint32_t duk_uint32_t;
+typedef int32_t duk_int32_t;
+typedef uint64_t duk_uint64_t;
+typedef int64_t duk_int64_t;
+typedef uint_least8_t duk_uint_least8_t;
+typedef int_least8_t duk_int_least8_t;
+typedef uint_least16_t duk_uint_least16_t;
+typedef int_least16_t duk_int_least16_t;
+typedef uint_least32_t duk_uint_least32_t;
+typedef int_least32_t duk_int_least32_t;
+typedef uint_least64_t duk_uint_least64_t;
+typedef int_least64_t duk_int_least64_t;
+typedef uint_fast8_t duk_uint_fast8_t;
+typedef int_fast8_t duk_int_fast8_t;
+typedef uint_fast16_t duk_uint_fast16_t;
+typedef int_fast16_t duk_int_fast16_t;
+typedef uint_fast32_t duk_uint_fast32_t;
+typedef int_fast32_t duk_int_fast32_t;
+typedef uint_fast64_t duk_uint_fast64_t;
+typedef int_fast64_t duk_int_fast64_t;
+typedef uintptr_t duk_uintptr_t;
+typedef intptr_t duk_intptr_t;
+typedef uintmax_t duk_uintmax_t;
+typedef intmax_t duk_intmax_t;
+
+#define DUK_UINT8_MIN         0
+#define DUK_UINT8_MAX         UINT8_MAX
+#define DUK_INT8_MIN          INT8_MIN
+#define DUK_INT8_MAX          INT8_MAX
+#define DUK_UINT_LEAST8_MIN   0
+#define DUK_UINT_LEAST8_MAX   UINT_LEAST8_MAX
+#define DUK_INT_LEAST8_MIN    INT_LEAST8_MIN
+#define DUK_INT_LEAST8_MAX    INT_LEAST8_MAX
+#define DUK_UINT_FAST8_MIN    0
+#define DUK_UINT_FAST8_MAX    UINT_FAST8_MAX
+#define DUK_INT_FAST8_MIN     INT_FAST8_MIN
+#define DUK_INT_FAST8_MAX     INT_FAST8_MAX
+#define DUK_UINT16_MIN        0
+#define DUK_UINT16_MAX        UINT16_MAX
+#define DUK_INT16_MIN         INT16_MIN
+#define DUK_INT16_MAX         INT16_MAX
+#define DUK_UINT_LEAST16_MIN  0
+#define DUK_UINT_LEAST16_MAX  UINT_LEAST16_MAX
+#define DUK_INT_LEAST16_MIN   INT_LEAST16_MIN
+#define DUK_INT_LEAST16_MAX   INT_LEAST16_MAX
+#define DUK_UINT_FAST16_MIN   0
+#define DUK_UINT_FAST16_MAX   UINT_FAST16_MAX
+#define DUK_INT_FAST16_MIN    INT_FAST16_MIN
+#define DUK_INT_FAST16_MAX    INT_FAST16_MAX
+#define DUK_UINT32_MIN        0
+#define DUK_UINT32_MAX        UINT32_MAX
+#define DUK_INT32_MIN         INT32_MIN
+#define DUK_INT32_MAX         INT32_MAX
+#define DUK_UINT_LEAST32_MIN  0
+#define DUK_UINT_LEAST32_MAX  UINT_LEAST32_MAX
+#define DUK_INT_LEAST32_MIN   INT_LEAST32_MIN
+#define DUK_INT_LEAST32_MAX   INT_LEAST32_MAX
+#define DUK_UINT_FAST32_MIN   0
+#define DUK_UINT_FAST32_MAX   UINT_FAST32_MAX
+#define DUK_INT_FAST32_MIN    INT_FAST32_MIN
+#define DUK_INT_FAST32_MAX    INT_FAST32_MAX
+#define DUK_UINT64_MIN        0
+#define DUK_UINT64_MAX        UINT64_MAX
+#define DUK_INT64_MIN         INT64_MIN
+#define DUK_INT64_MAX         INT64_MAX
+#define DUK_UINT_LEAST64_MIN  0
+#define DUK_UINT_LEAST64_MAX  UINT_LEAST64_MAX
+#define DUK_INT_LEAST64_MIN   INT_LEAST64_MIN
+#define DUK_INT_LEAST64_MAX   INT_LEAST64_MAX
+#define DUK_UINT_FAST64_MIN   0
+#define DUK_UINT_FAST64_MAX   UINT_FAST64_MAX
+#define DUK_INT_FAST64_MIN    INT_FAST64_MIN
+#define DUK_INT_FAST64_MAX    INT_FAST64_MAX
+
+#define DUK_UINTPTR_MIN       0
+#define DUK_UINTPTR_MAX       UINTPTR_MAX
+#define DUK_INTPTR_MIN        INTPTR_MIN
+#define DUK_INTPTR_MAX        INTPTR_MAX
+
+#define DUK_UINTMAX_MIN       0
+#define DUK_UINTMAX_MAX       UINTMAX_MAX
+#define DUK_INTMAX_MIN        INTMAX_MIN
+#define DUK_INTMAX_MAX        INTMAX_MAX
+
+#define DUK_SIZE_MIN          0
+#define DUK_SIZE_MAX          SIZE_MAX
+#undef DUK_SIZE_MAX_COMPUTED
+
+#else  /* C99 types */
+
+/* When C99 types are not available, we use heuristic detection to get
+ * the basic 8, 16, 32, and (possibly) 64 bit types.  The fast/least
+ * types are then assumed to be exactly the same for now: these could
+ * be improved per platform but C99 types are very often now available.
+ * 64-bit types are not available on all platforms; this is OK at least
+ * on 32-bit platforms.
+ *
+ * This detection code is necessarily a bit hacky and can provide typedefs
+ * and defines that won't work correctly on some exotic platform.
+ */
+
+#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \
+    (defined(UCHAR_MAX) && (UCHAR_MAX == 255))
+typedef unsigned char duk_uint8_t;
+typedef signed char duk_int8_t;
+#else
+#error cannot detect 8-bit type
+#endif
+
+#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL)
+typedef unsigned short duk_uint16_t;
+typedef signed short duk_int16_t;
+#elif defined(UINT_MAX) && (UINT_MAX == 65535UL)
+/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
+typedef unsigned int duk_uint16_t;
+typedef signed int duk_int16_t;
+#else
+#error cannot detect 16-bit type
+#endif
+
+#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL)
+typedef unsigned int duk_uint32_t;
+typedef signed int duk_int32_t;
+#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL)
+/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */
+typedef unsigned long duk_uint32_t;
+typedef signed long duk_int32_t;
+#else
+#error cannot detect 32-bit type
+#endif
+
+/* 64-bit type detection is a bit tricky.
+ *
+ * ULLONG_MAX is a standard define.  __LONG_LONG_MAX__ and __ULONG_LONG_MAX__
+ * are used by at least GCC (even if system headers don't provide ULLONG_MAX).
+ * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__.
+ *
+ * ULL / LL constants are rejected / warned about by some compilers, even if
+ * the compiler has a 64-bit type and the compiler/system headers provide an
+ * unsupported constant (ULL/LL)!  Try to avoid using ULL / LL constants.
+ * As a side effect we can only check that e.g. ULONG_MAX is larger than 32
+ * bits but can't be sure it is exactly 64 bits.  Self tests will catch such
+ * cases.
+ */
+#undef DUK_F_HAVE_64BIT
+#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX)
+#if (ULONG_MAX > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long duk_uint64_t;
+typedef signed long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX)
+#if (ULLONG_MAX > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__)
+#if (__ULONG_LONG_MAX__ > 4294967295UL)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__)
+#if (__LONG_LONG_MAX__ > 2147483647L)
+#define DUK_F_HAVE_64BIT
+typedef unsigned long long duk_uint64_t;
+typedef signed long long duk_int64_t;
+#endif
+#endif
+#if !defined(DUK_F_HAVE_64BIT) && \
+    (defined(DUK_F_MINGW) || defined(DUK_F_MSVC))
+/* Both MinGW and MSVC have a 64-bit type. */
+#define DUK_F_HAVE_64BIT
+typedef unsigned long duk_uint64_t;
+typedef signed long duk_int64_t;
+#endif
+#if !defined(DUK_F_HAVE_64BIT)
+/* cannot detect 64-bit type, not always needed so don't error */
+#endif
+
+typedef duk_uint8_t duk_uint_least8_t;
+typedef duk_int8_t duk_int_least8_t;
+typedef duk_uint16_t duk_uint_least16_t;
+typedef duk_int16_t duk_int_least16_t;
+typedef duk_uint32_t duk_uint_least32_t;
+typedef duk_int32_t duk_int_least32_t;
+typedef duk_uint8_t duk_uint_fast8_t;
+typedef duk_int8_t duk_int_fast8_t;
+typedef duk_uint16_t duk_uint_fast16_t;
+typedef duk_int16_t duk_int_fast16_t;
+typedef duk_uint32_t duk_uint_fast32_t;
+typedef duk_int32_t duk_int_fast32_t;
+#if defined(DUK_F_HAVE_64BIT)
+typedef duk_uint64_t duk_uint_least64_t;
+typedef duk_int64_t duk_int_least64_t;
+typedef duk_uint64_t duk_uint_fast64_t;
+typedef duk_int64_t duk_int_fast64_t;
+#endif
+#if defined(DUK_F_HAVE_64BIT)
+typedef duk_uint64_t duk_uintmax_t;
+typedef duk_int64_t duk_intmax_t;
+#else
+typedef duk_uint32_t duk_uintmax_t;
+typedef duk_int32_t duk_intmax_t;
+#endif
+
+/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and
+ * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are
+ * -not- portable.  See code-issues.txt for a detailed discussion.
+ */
+#define DUK_UINT8_MIN         0UL
+#define DUK_UINT8_MAX         0xffUL
+#define DUK_INT8_MIN          (-0x80L)
+#define DUK_INT8_MAX          0x7fL
+#define DUK_UINT_LEAST8_MIN   0UL
+#define DUK_UINT_LEAST8_MAX   0xffUL
+#define DUK_INT_LEAST8_MIN    (-0x80L)
+#define DUK_INT_LEAST8_MAX    0x7fL
+#define DUK_UINT_FAST8_MIN    0UL
+#define DUK_UINT_FAST8_MAX    0xffUL
+#define DUK_INT_FAST8_MIN     (-0x80L)
+#define DUK_INT_FAST8_MAX     0x7fL
+#define DUK_UINT16_MIN        0UL
+#define DUK_UINT16_MAX        0xffffUL
+#define DUK_INT16_MIN         (-0x7fffL - 1L)
+#define DUK_INT16_MAX         0x7fffL
+#define DUK_UINT_LEAST16_MIN  0UL
+#define DUK_UINT_LEAST16_MAX  0xffffUL
+#define DUK_INT_LEAST16_MIN   (-0x7fffL - 1L)
+#define DUK_INT_LEAST16_MAX   0x7fffL
+#define DUK_UINT_FAST16_MIN   0UL
+#define DUK_UINT_FAST16_MAX   0xffffUL
+#define DUK_INT_FAST16_MIN    (-0x7fffL - 1L)
+#define DUK_INT_FAST16_MAX    0x7fffL
+#define DUK_UINT32_MIN        0UL
+#define DUK_UINT32_MAX        0xffffffffUL
+#define DUK_INT32_MIN         (-0x7fffffffL - 1L)
+#define DUK_INT32_MAX         0x7fffffffL
+#define DUK_UINT_LEAST32_MIN  0UL
+#define DUK_UINT_LEAST32_MAX  0xffffffffUL
+#define DUK_INT_LEAST32_MIN   (-0x7fffffffL - 1L)
+#define DUK_INT_LEAST32_MAX   0x7fffffffL
+#define DUK_UINT_FAST32_MIN   0UL
+#define DUK_UINT_FAST32_MAX   0xffffffffUL
+#define DUK_INT_FAST32_MIN    (-0x7fffffffL - 1L)
+#define DUK_INT_FAST32_MAX    0x7fffffffL
+
+/* 64-bit constants.  Since LL / ULL constants are not always available,
+ * use computed values.  These values can't be used in preprocessor
+ * comparisons; flag them as such.
+ */
+#if defined(DUK_F_HAVE_64BIT)
+#define DUK_UINT64_MIN        ((duk_uint64_t) 0)
+#define DUK_UINT64_MAX        ((duk_uint64_t) -1)
+#define DUK_INT64_MIN         ((duk_int64_t) (~(DUK_UINT64_MAX >> 1)))
+#define DUK_INT64_MAX         ((duk_int64_t) (DUK_UINT64_MAX >> 1))
+#define DUK_UINT_LEAST64_MIN  DUK_UINT64_MIN
+#define DUK_UINT_LEAST64_MAX  DUK_UINT64_MAX
+#define DUK_INT_LEAST64_MIN   DUK_INT64_MIN
+#define DUK_INT_LEAST64_MAX   DUK_INT64_MAX
+#define DUK_UINT_FAST64_MIN   DUK_UINT64_MIN
+#define DUK_UINT_FAST64_MAX   DUK_UINT64_MAX
+#define DUK_INT_FAST64_MIN    DUK_INT64_MIN
+#define DUK_INT_FAST64_MAX    DUK_INT64_MAX
+#define DUK_UINT64_MIN_COMPUTED
+#define DUK_UINT64_MAX_COMPUTED
+#define DUK_INT64_MIN_COMPUTED
+#define DUK_INT64_MAX_COMPUTED
+#define DUK_UINT_LEAST64_MIN_COMPUTED
+#define DUK_UINT_LEAST64_MAX_COMPUTED
+#define DUK_INT_LEAST64_MIN_COMPUTED
+#define DUK_INT_LEAST64_MAX_COMPUTED
+#define DUK_UINT_FAST64_MIN_COMPUTED
+#define DUK_UINT_FAST64_MAX_COMPUTED
+#define DUK_INT_FAST64_MIN_COMPUTED
+#define DUK_INT_FAST64_MAX_COMPUTED
+#endif
+
+#if defined(DUK_F_HAVE_64BIT)
+#define DUK_UINTMAX_MIN       DUK_UINT64_MIN
+#define DUK_UINTMAX_MAX       DUK_UINT64_MAX
+#define DUK_INTMAX_MIN        DUK_INT64_MIN
+#define DUK_INTMAX_MAX        DUK_INT64_MAX
+#define DUK_UINTMAX_MIN_COMPUTED
+#define DUK_UINTMAX_MAX_COMPUTED
+#define DUK_INTMAX_MIN_COMPUTED
+#define DUK_INTMAX_MAX_COMPUTED
+#else
+#define DUK_UINTMAX_MIN       0UL
+#define DUK_UINTMAX_MAX       0xffffffffUL
+#define DUK_INTMAX_MIN        (-0x7fffffffL - 1L)
+#define DUK_INTMAX_MAX        0x7fffffffL
+#endif
+
+/* This detection is not very reliable. */
+#if defined(DUK_F_32BIT_PTRS)
+typedef duk_int32_t duk_intptr_t;
+typedef duk_uint32_t duk_uintptr_t;
+#define DUK_UINTPTR_MIN       DUK_UINT32_MIN
+#define DUK_UINTPTR_MAX       DUK_UINT32_MAX
+#define DUK_INTPTR_MIN        DUK_INT32_MIN
+#define DUK_INTPTR_MAX        DUK_INT32_MAX
+#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT)
+typedef duk_int64_t duk_intptr_t;
+typedef duk_uint64_t duk_uintptr_t;
+#define DUK_UINTPTR_MIN       DUK_UINT64_MIN
+#define DUK_UINTPTR_MAX       DUK_UINT64_MAX
+#define DUK_INTPTR_MIN        DUK_INT64_MIN
+#define DUK_INTPTR_MAX        DUK_INT64_MAX
+#define DUK_UINTPTR_MIN_COMPUTED
+#define DUK_UINTPTR_MAX_COMPUTED
+#define DUK_INTPTR_MIN_COMPUTED
+#define DUK_INTPTR_MAX_COMPUTED
+#else
+#error cannot determine intptr type
+#endif
+
+/* SIZE_MAX may be missing so use an approximate value for it. */
+#undef DUK_SIZE_MAX_COMPUTED
+#if !defined(SIZE_MAX)
+#define DUK_SIZE_MAX_COMPUTED
+#define SIZE_MAX              ((size_t) (-1))
+#endif
+#define DUK_SIZE_MIN          0
+#define DUK_SIZE_MAX          SIZE_MAX
+
+#endif  /* C99 types */
+
+/* A few types are assumed to always exist. */
+typedef size_t duk_size_t;
+typedef ptrdiff_t duk_ptrdiff_t;
+
+/* The best type for an "all around int" in Duktape internals is "at least
+ * 32 bit signed integer" which is most convenient.  Same for unsigned type.
+ * Prefer 'int' when large enough, as it is almost always a convenient type.
+ */
+#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL)
+typedef int duk_int_t;
+typedef unsigned int duk_uint_t;
+#define DUK_INT_MIN           INT_MIN
+#define DUK_INT_MAX           INT_MAX
+#define DUK_UINT_MIN          0
+#define DUK_UINT_MAX          UINT_MAX
+#else
+typedef duk_int_fast32_t duk_int_t;
+typedef duk_uint_fast32_t duk_uint_t;
+#define DUK_INT_MIN           DUK_INT_FAST32_MIN
+#define DUK_INT_MAX           DUK_INT_FAST32_MAX
+#define DUK_UINT_MIN          DUK_UINT_FAST32_MIN
+#define DUK_UINT_MAX          DUK_UINT_FAST32_MAX
+#endif
+
+/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this
+ * distinction matters for the CPU.  These types are used mainly in the
+ * executor where it might really matter.
+ */
+typedef duk_int_fast32_t duk_int_fast_t;
+typedef duk_uint_fast32_t duk_uint_fast_t;
+#define DUK_INT_FAST_MIN      DUK_INT_FAST32_MIN
+#define DUK_INT_FAST_MAX      DUK_INT_FAST32_MAX
+#define DUK_UINT_FAST_MIN     DUK_UINT_FAST32_MIN
+#define DUK_UINT_FAST_MAX     DUK_UINT_FAST32_MAX
+
+/* Small integers (16 bits or more) can fall back to the 'int' type, but
+ * have a typedef so they are marked "small" explicitly.
+ */
+typedef int duk_small_int_t;
+typedef unsigned int duk_small_uint_t;
+#define DUK_SMALL_INT_MIN     INT_MIN
+#define DUK_SMALL_INT_MAX     INT_MAX
+#define DUK_SMALL_UINT_MIN    0
+#define DUK_SMALL_UINT_MAX    UINT_MAX
+
+/* Fast variants of small integers, again for really fast paths like the
+ * executor.
+ */
+typedef duk_int_fast16_t duk_small_int_fast_t;
+typedef duk_uint_fast16_t duk_small_uint_fast_t;
+#define DUK_SMALL_INT_FAST_MIN    DUK_INT_FAST16_MIN
+#define DUK_SMALL_INT_FAST_MAX    DUK_INT_FAST16_MAX
+#define DUK_SMALL_UINT_FAST_MIN   DUK_UINT_FAST16_MIN
+#define DUK_SMALL_UINT_FAST_MAX   DUK_UINT_FAST16_MAX
+
+/* Boolean values are represented with the platform 'int'. */
+typedef duk_small_int_t duk_bool_t;
+#define DUK_BOOL_MIN              DUK_SMALL_INT_MIN
+#define DUK_BOOL_MAX              DUK_SMALL_INT_MAX
+
+/* Index values must have at least 32-bit signed range. */
+typedef duk_int_t duk_idx_t;
+#define DUK_IDX_MIN               DUK_INT_MIN
+#define DUK_IDX_MAX               DUK_INT_MAX
+
+/* Unsigned index variant. */
+typedef duk_uint_t duk_uidx_t;
+#define DUK_UIDX_MIN              DUK_UINT_MIN
+#define DUK_UIDX_MAX              DUK_UINT_MAX
+
+/* Array index values, could be exact 32 bits.
+ * Currently no need for signed duk_arridx_t.
+ */
+typedef duk_uint_t duk_uarridx_t;
+#define DUK_UARRIDX_MIN           DUK_UINT_MIN
+#define DUK_UARRIDX_MAX           DUK_UINT_MAX
+
+/* Duktape/C function return value, platform int is enough for now to
+ * represent 0, 1, or negative error code.  Must be compatible with
+ * assigning truth values (e.g. duk_ret_t rc = (foo == bar);).
+ */
+typedef duk_small_int_t duk_ret_t;
+#define DUK_RET_MIN               DUK_SMALL_INT_MIN
+#define DUK_RET_MAX               DUK_SMALL_INT_MAX
+
+/* Error codes are represented with platform int.  High bits are used
+ * for flags and such, so 32 bits are needed.
+ */
+typedef duk_int_t duk_errcode_t;
+#define DUK_ERRCODE_MIN           DUK_INT_MIN
+#define DUK_ERRCODE_MAX           DUK_INT_MAX
+
+/* Codepoint type.  Must be 32 bits or more because it is used also for
+ * internal codepoints.  The type is signed because negative codepoints
+ * are used as internal markers (e.g. to mark EOF or missing argument).
+ * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to
+ * ensure duk_uint32_t casts back and forth nicely.  Almost everything
+ * else uses the signed one.
+ */
+typedef duk_int_t duk_codepoint_t;
+typedef duk_uint_t duk_ucodepoint_t;
+#define DUK_CODEPOINT_MIN         DUK_INT_MIN
+#define DUK_CODEPOINT_MAX         DUK_INT_MAX
+#define DUK_UCODEPOINT_MIN        DUK_UINT_MIN
+#define DUK_UCODEPOINT_MAX        DUK_UINT_MAX
+
+/* IEEE float/double typedef. */
+typedef float duk_float_t;
+typedef double duk_double_t;
+
+/* We're generally assuming that we're working on a platform with a 32-bit
+ * address space.  If DUK_SIZE_MAX is a typecast value (which is necessary
+ * if SIZE_MAX is missing), the check must be avoided because the
+ * preprocessor can't do a comparison.
+ */
+#if !defined(DUK_SIZE_MAX)
+#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX
+#elif !defined(DUK_SIZE_MAX_COMPUTED)
+#if DUK_SIZE_MAX < 0xffffffffUL
+/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value
+ * which seems incorrect if size_t is (at least) an unsigned 32-bit type.
+ * However, it doesn't seem useful to error out compilation if this is the
+ * case.
+ */
+#endif
+#endif
+
+/* Type for public API calls. */
+typedef struct duk_hthread duk_context;
+
+/* Check whether we should use 64-bit integers or not.
+ *
+ * Quite incomplete now.  Use 64-bit types if detected (C99 or other detection)
+ * unless they are known to be unreliable.  For instance, 64-bit types are
+ * available on VBCC but seem to misbehave.
+ */
+#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC)
+#define DUK_USE_64BIT_OPS
+#else
+#undef DUK_USE_64BIT_OPS
+#endif
+
+/*
+ *  Fill-ins for platform, architecture, and compiler
+ */
+
+#if !defined(DUK_SETJMP)
+#define DUK_JMPBUF_TYPE       jmp_buf
+#define DUK_SETJMP(jb)        setjmp((jb))
+#define DUK_LONGJMP(jb)       longjmp((jb), 1)
+#endif
+
+#if 0
+/* sigsetjmp() alternative */
+#define DUK_JMPBUF_TYPE       sigjmp_buf
+#define DUK_SETJMP(jb)        sigsetjmp((jb))
+#define DUK_LONGJMP(jb)       siglongjmp((jb), 1)
+#endif
+
+typedef FILE duk_file;
+#if !defined(DUK_STDIN)
+#define DUK_STDIN       stdin
+#endif
+#if !defined(DUK_STDOUT)
+#define DUK_STDOUT      stdout
+#endif
+#if !defined(DUK_STDERR)
+#define DUK_STDERR      stderr
+#endif
+
+/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h
+ * (which is unfortunately named).  May sometimes need replacement, e.g.
+ * some compilers don't handle zero length or NULL correctly in realloc().
+ */
+#if !defined(DUK_ANSI_MALLOC)
+#define DUK_ANSI_MALLOC      malloc
+#endif
+#if !defined(DUK_ANSI_REALLOC)
+#define DUK_ANSI_REALLOC     realloc
+#endif
+#if !defined(DUK_ANSI_CALLOC)
+#define DUK_ANSI_CALLOC      calloc
+#endif
+#if !defined(DUK_ANSI_FREE)
+#define DUK_ANSI_FREE        free
+#endif
+
+/* ANSI C (various versions) and some implementations require that the
+ * pointer arguments to memset(), memcpy(), and memmove() be valid values
+ * even when byte size is 0 (even a NULL pointer is considered invalid in
+ * this context).  Zero-size operations as such are allowed, as long as their
+ * pointer arguments point to a valid memory area.  The DUK_MEMSET(),
+ * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:
+ * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be
+ * allowed.  If these are not fulfilled, a macro wrapper is needed.
+ *
+ *   http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
+ *   http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html
+ *
+ * Not sure what's the required behavior when a pointer points just past the
+ * end of a buffer, which often happens in practice (e.g. zero size memmoves).
+ * For example, if allocation size is 3, the following pointer would not
+ * technically point to a valid memory byte:
+ *
+ *   <-- alloc -->
+ *   | 0 | 1 | 2 | .....
+ *                 ^-- p=3, points after last valid byte (2)
+ */
+#if !defined(DUK_MEMCPY)
+#if defined(DUK_F_UCLIBC)
+/* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide
+ * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html
+ */
+#define DUK_MEMCPY       memmove
+#else
+#define DUK_MEMCPY       memcpy
+#endif
+#endif
+#if !defined(DUK_MEMMOVE)
+#define DUK_MEMMOVE      memmove
+#endif
+#if !defined(DUK_MEMCMP)
+#define DUK_MEMCMP       memcmp
+#endif
+#if !defined(DUK_MEMSET)
+#define DUK_MEMSET       memset
+#endif
+#if !defined(DUK_STRLEN)
+#define DUK_STRLEN       strlen
+#endif
+#if !defined(DUK_STRCMP)
+#define DUK_STRCMP       strcmp
+#endif
+#if !defined(DUK_STRNCMP)
+#define DUK_STRNCMP      strncmp
+#endif
+#if !defined(DUK_PRINTF)
+#define DUK_PRINTF       printf
+#endif
+#if !defined(DUK_FPRINTF)
+#define DUK_FPRINTF      fprintf
+#endif
+#if !defined(DUK_SPRINTF)
+#define DUK_SPRINTF      sprintf
+#endif
+#if !defined(DUK_SNPRINTF)
+/* snprintf() is technically not part of C89 but usually available. */
+#define DUK_SNPRINTF     snprintf
+#endif
+#if !defined(DUK_VSPRINTF)
+#define DUK_VSPRINTF     vsprintf
+#endif
+#if !defined(DUK_VSNPRINTF)
+/* vsnprintf() is technically not part of C89 but usually available. */
+#define DUK_VSNPRINTF    vsnprintf
+#endif
+#if !defined(DUK_SSCANF)
+#define DUK_SSCANF       sscanf
+#endif
+#if !defined(DUK_VSSCANF)
+#define DUK_VSSCANF      vsscanf
+#endif
+#if !defined(DUK_FOPEN)
+#define DUK_FOPEN        fopen
+#endif
+#if !defined(DUK_FCLOSE)
+#define DUK_FCLOSE       fclose
+#endif
+#if !defined(DUK_FREAD)
+#define DUK_FREAD        fread
+#endif
+#if !defined(DUK_FWRITE)
+#define DUK_FWRITE       fwrite
+#endif
+#if !defined(DUK_FSEEK)
+#define DUK_FSEEK        fseek
+#endif
+#if !defined(DUK_FTELL)
+#define DUK_FTELL        ftell
+#endif
+#if !defined(DUK_FFLUSH)
+#define DUK_FFLUSH       fflush
+#endif
+#if !defined(DUK_FPUTC)
+#define DUK_FPUTC        fputc
+#endif
+#if !defined(DUK_MEMZERO)
+#define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n))
+#endif
+#if !defined(DUK_ABORT)
+#define DUK_ABORT        abort
+#endif
+#if !defined(DUK_EXIT)
+#define DUK_EXIT         exit
+#endif
+
+#if !defined(DUK_DOUBLE_2TO32)
+#define DUK_DOUBLE_2TO32     4294967296.0
+#endif
+#if !defined(DUK_DOUBLE_2TO31)
+#define DUK_DOUBLE_2TO31     2147483648.0
+#endif
+
+#if !defined(DUK_DOUBLE_INFINITY)
+#undef DUK_USE_COMPUTED_INFINITY
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600)
+/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */
+#define DUK_DOUBLE_INFINITY  (__builtin_inf())
+#elif defined(INFINITY)
+#define DUK_DOUBLE_INFINITY  ((double) INFINITY)
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#define DUK_DOUBLE_INFINITY  (1.0 / 0.0)
+#else
+/* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity.
+ * Use a computed infinity (initialized when a heap is created at the
+ * latest).
+ */
+#define DUK_USE_COMPUTED_INFINITY
+#define DUK_DOUBLE_INFINITY  duk_computed_infinity
+#endif
+#endif
+
+#if !defined(DUK_DOUBLE_NAN)
+#undef DUK_USE_COMPUTED_NAN
+#if defined(NAN)
+#define DUK_DOUBLE_NAN       NAN
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#define DUK_DOUBLE_NAN       (0.0 / 0.0)
+#else
+/* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN.
+ * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error.
+ * Use a computed NaN (initialized when a heap is created at the
+ * latest).
+ */
+#define DUK_USE_COMPUTED_NAN
+#define DUK_DOUBLE_NAN       duk_computed_nan
+#endif
+#endif
+
+/* Many platforms are missing fpclassify() and friends, so use replacements
+ * if necessary.  The replacement constants (FP_NAN etc) can be anything but
+ * match Linux constants now.
+ */
+#undef DUK_USE_REPL_FPCLASSIFY
+#undef DUK_USE_REPL_SIGNBIT
+#undef DUK_USE_REPL_ISFINITE
+#undef DUK_USE_REPL_ISNAN
+#undef DUK_USE_REPL_ISINF
+
+/* Complex condition broken into separate parts. */
+#undef DUK_F_USE_REPL_ALL
+#if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \
+      defined(FP_SUBNORMAL) && defined(FP_NORMAL))
+/* Missing some obvious constants. */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
+/* VBCC is missing the built-ins even in C99 mode (perhaps a header issue). */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_M68K)
+/* AmigaOS + M68K seems to have math issues even when using GCC cross
+ * compilation.  Use replacements for all AmigaOS versions on M68K
+ * regardless of compiler.
+ */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG)
+/* Placeholder fix for (detection is wider than necessary):
+ * http://llvm.org/bugs/show_bug.cgi?id=17788
+ */
+#define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_UCLIBC)
+/* At least some uclibc versions have broken floating point math.  For
+ * example, fpclassify() can incorrectly classify certain NaN formats.
+ * To be safe, use replacements.
+ */
+#define DUK_F_USE_REPL_ALL
+#endif
+
+#if defined(DUK_F_USE_REPL_ALL)
+#define DUK_USE_REPL_FPCLASSIFY
+#define DUK_USE_REPL_SIGNBIT
+#define DUK_USE_REPL_ISFINITE
+#define DUK_USE_REPL_ISNAN
+#define DUK_USE_REPL_ISINF
+#define DUK_FPCLASSIFY       duk_repl_fpclassify
+#define DUK_SIGNBIT          duk_repl_signbit
+#define DUK_ISFINITE         duk_repl_isfinite
+#define DUK_ISNAN            duk_repl_isnan
+#define DUK_ISINF            duk_repl_isinf
+#define DUK_FP_NAN           0
+#define DUK_FP_INFINITE      1
+#define DUK_FP_ZERO          2
+#define DUK_FP_SUBNORMAL     3
+#define DUK_FP_NORMAL        4
+#else
+#define DUK_FPCLASSIFY       fpclassify
+#define DUK_SIGNBIT          signbit
+#define DUK_ISFINITE         isfinite
+#define DUK_ISNAN            isnan
+#define DUK_ISINF            isinf
+#define DUK_FP_NAN           FP_NAN
+#define DUK_FP_INFINITE      FP_INFINITE
+#define DUK_FP_ZERO          FP_ZERO
+#define DUK_FP_SUBNORMAL     FP_SUBNORMAL
+#define DUK_FP_NORMAL        FP_NORMAL
+#endif
+
+#if defined(DUK_F_USE_REPL_ALL)
+#undef DUK_F_USE_REPL_ALL
+#endif
+
+/* Some math functions are C99 only.  This is also an issue with some
+ * embedded environments using uclibc where uclibc has been configured
+ * not to provide some functions.  For now, use replacements whenever
+ * using uclibc.
+ */
+#undef DUK_USE_MATH_FMIN
+#undef DUK_USE_MATH_FMAX
+#undef DUK_USE_MATH_ROUND
+#if defined(DUK_F_UCLIBC)
+/* uclibc may be missing these */
+#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)
+/* vbcc + AmigaOS may be missing these */
+#elif defined(DUK_F_MINT)
+/* mint clib is missing these */
+#elif !defined(DUK_F_C99) && !defined(DUK_F_CPP11)
+/* build is not C99 or C++11, play it safe */
+#else
+/* C99 or C++11, no known issues */
+#define DUK_USE_MATH_FMIN
+#define DUK_USE_MATH_FMAX
+#define DUK_USE_MATH_ROUND
+#endif
+
+/* These functions don't currently need replacement but are wrapped for
+ * completeness.  Because these are used as function pointers, they need
+ * to be defined as concrete C functions (not macros).
+ */
+#if !defined(DUK_FABS)
+#define DUK_FABS             fabs
+#endif
+#if !defined(DUK_FMIN)
+#define DUK_FMIN             fmin
+#endif
+#if !defined(DUK_FMAX)
+#define DUK_FMAX             fmax
+#endif
+#if !defined(DUK_FLOOR)
+#define DUK_FLOOR            floor
+#endif
+#if !defined(DUK_CEIL)
+#define DUK_CEIL             ceil
+#endif
+#if !defined(DUK_FMOD)
+#define DUK_FMOD             fmod
+#endif
+#if !defined(DUK_POW)
+#define DUK_POW              pow
+#endif
+#if !defined(DUK_ACOS)
+#define DUK_ACOS             acos
+#endif
+#if !defined(DUK_ASIN)
+#define DUK_ASIN             asin
+#endif
+#if !defined(DUK_ATAN)
+#define DUK_ATAN             atan
+#endif
+#if !defined(DUK_ATAN2)
+#define DUK_ATAN2            atan2
+#endif
+#if !defined(DUK_SIN)
+#define DUK_SIN              sin
+#endif
+#if !defined(DUK_COS)
+#define DUK_COS              cos
+#endif
+#if !defined(DUK_TAN)
+#define DUK_TAN              tan
+#endif
+#if !defined(DUK_EXP)
+#define DUK_EXP              exp
+#endif
+#if !defined(DUK_LOG)
+#define DUK_LOG              log
+#endif
+#if !defined(DUK_SQRT)
+#define DUK_SQRT             sqrt
+#endif
+
+/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,
+ * see test-bug-netbsd-math-pow.js.  Use NetBSD specific workaround.
+ * (This might be a wider problem; if so, generalize the define name.)
+ */
+#undef DUK_USE_POW_NETBSD_WORKAROUND
+#if defined(DUK_F_NETBSD)
+#define DUK_USE_POW_NETBSD_WORKAROUND
+#endif
+
+/* Rely as little as possible on compiler behavior for NaN comparison,
+ * signed zero handling, etc.  Currently never activated but may be needed
+ * for broken compilers.
+ */
+#undef DUK_USE_PARANOID_MATH
+
+/* There was a curious bug where test-bi-date-canceling.js would fail e.g.
+ * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99.  Some date computations
+ * using doubles would be optimized which then broke some corner case tests.
+ * The problem goes away by adding 'volatile' to the datetime computations.
+ * Not sure what the actual triggering conditions are, but using this on
+ * non-C99 systems solves the known issues and has relatively little cost
+ * on other platforms.
+ */
+#undef DUK_USE_PARANOID_DATE_COMPUTATION
+#if !defined(DUK_F_C99)
+#define DUK_USE_PARANOID_DATE_COMPUTATION
+#endif
+
+/*
+ *  Byte order and double memory layout detection
+ *
+ *  Endianness detection is a major portability hassle because the macros
+ *  and headers are not standardized.  There's even variance across UNIX
+ *  platforms.  Even with "standard" headers, details like underscore count
+ *  varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used
+ *  (Crossbridge has a single underscore, for instance).
+ *
+ *  The checks below are structured with this in mind: several approaches are
+ *  used, and at the end we check if any of them worked.  This allows generic
+ *  approaches to be tried first, and platform/compiler specific hacks tried
+ *  last.  As a last resort, the user can force a specific endianness, as it's
+ *  not likely that automatic detection will work on the most exotic platforms.
+ *
+ *  Duktape supports little and big endian machines.  There's also support
+ *  for a hybrid used by some ARM machines where integers are little endian
+ *  but IEEE double values use a mixed order (12345678 -> 43218765).  This
+ *  byte order for doubles is referred to as "mixed endian".
+ */
+
+/* For custom platforms allow user to define byteorder explicitly.
+ * Since endianness headers are not standardized, this is a useful
+ * workaround for custom platforms for which endianness detection
+ * is not directly supported.  Perhaps custom hardware is used and
+ * user cannot submit upstream patches.
+ */
+#if defined(DUK_OPT_FORCE_BYTEORDER)
+#undef DUK_USE_BYTEORDER
+#if (DUK_OPT_FORCE_BYTEORDER == 1)
+#define DUK_USE_BYTEORDER 1
+#elif (DUK_OPT_FORCE_BYTEORDER == 2)
+#define DUK_USE_BYTEORDER 2
+#elif (DUK_OPT_FORCE_BYTEORDER == 3)
+#define DUK_USE_BYTEORDER 3
+#else
+#error invalid DUK_OPT_FORCE_BYTEORDER value
+#endif
+#endif  /* DUK_OPT_FORCE_BYTEORDER */
+
+/* GCC and Clang provide endianness defines as built-in predefines, with
+ * leading and trailing double underscores (e.g. __BYTE_ORDER__).  See
+ * output of "make gccpredefs" and "make clangpredefs".  Clang doesn't
+ * seem to provide __FLOAT_WORD_ORDER__; assume not mixed endian for clang.
+ * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+ */
+#if !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__)
+#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#else
+/* Cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit
+ * integer ordering and is not relevant.
+ */
+#endif  /* integer byte order */
+#endif  /* !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) */
+
+/* More or less standard endianness predefines provided by header files.
+ * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER
+ * will be big endian, see: http://lists.mysql.com/internals/443.
+ * On some platforms some defines may be present with an empty value which
+ * causes comparisons to fail: https://github.com/svaarala/duktape/issues/453.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \
+    defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \
+    defined(__LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \
+    defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+      defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \
+      defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \
+      defined(__BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+    defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif  /* float word order */
+#else
+/* Cannot determine byte order. */
+#endif  /* integer byte order */
+#endif  /* !defined(DUK_USE_BYTEORDER) */
+
+/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  67:#define __LITTLEENDIAN__ 1
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  81:#define __BIGENDIAN__ 1
+ *  $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ *  70:#define __LITTLEENDIAN__ 1
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__LITTLEENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__BIGENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#endif
+#endif
+
+/*
+ *  Alignment requirement and support for unaligned accesses
+ *
+ *  Assume unaligned accesses are not supported unless specifically allowed
+ *  in the target platform.  Some platforms may support unaligned accesses
+ *  but alignment to 4 or 8 may still be desirable.
+ */
+
+/* If not provided, use safe default for alignment. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+
+/* User forced alignment to 4 or 8. */
+#if defined(DUK_OPT_FORCE_ALIGN)
+#undef DUK_USE_ALIGN_BY
+#if (DUK_OPT_FORCE_ALIGN == 4)
+#define DUK_USE_ALIGN_BY 4
+#elif (DUK_OPT_FORCE_ALIGN == 8)
+#define DUK_USE_ALIGN_BY 8
+#else
+#error invalid DUK_OPT_FORCE_ALIGN value
+#endif
+#endif
+
+/* Compiler specific hackery needed to force struct size to match aligment,
+ * see e.g. duk_hbuffer.h.
+ *
+ * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
+ * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
+ */
+#if !(defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_GCC_ATTR) || \
+      defined(DUK_USE_PACK_CLANG_ATTR) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+
+#if !defined(DUK_VA_COPY)
+/* We need va_copy() which is defined in C99 / C++11, so an awkward
+ * replacement is needed for pre-C99 / pre-C++11 environments.  This
+ * will quite likely need portability hacks for some non-C99
+ * environments.
+ */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required.
+ * Omit parenthesis on macro right side on purpose to minimize differences
+ * to direct use.
+ */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Pre-C99: va_list type is implementation dependent.  This replacement
+ * assumes it is a plain value so that a simple assignment will work.
+ * This is not the case on all platforms (it may be a single-array element,
+ * for instance).
+ */
+#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0)
+#endif
+#endif
+
+#if !defined(DUK_MACRO_STRINGIFY)
+/* Macro hackery to convert e.g. __LINE__ to a string without formatting,
+ * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
+ */
+#define DUK_MACRO_STRINGIFY_HELPER(x)  #x
+#define DUK_MACRO_STRINGIFY(x)  DUK_MACRO_STRINGIFY_HELPER(x)
+#endif
+
+#if !defined(DUK_CAUSE_SEGFAULT)
+/* This is optionally used by panic handling to cause the program to segfault
+ * (instead of e.g. abort()) on panic.  Valgrind will then indicate the C
+ * call stack leading to the panic.
+ */
+#define DUK_CAUSE_SEGFAULT()  do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0)
+#endif
+#if !defined(DUK_UNREF)
+/* Macro for suppressing warnings for potentially unreferenced variables.
+ * The variables can be actually unreferenced or unreferenced in some
+ * specific cases only; for instance, if a variable is only debug printed,
+ * it is unreferenced when debug printing is disabled.
+ */
+#define DUK_UNREF(x)  do { (void) (x); } while (0)
+#endif
+#if !defined(DUK_NORETURN)
+#define DUK_NORETURN(decl)  decl
+#endif
+#if !defined(DUK_UNREACHABLE)
+/* Don't know how to declare unreachable point, so don't do it; this
+ * may cause some spurious compilation warnings (e.g. "variable used
+ * uninitialized").
+ */
+#define DUK_UNREACHABLE()  do { } while (0)
+#endif
+#if !defined(DUK_LOSE_CONST)
+/* Convert any input pointer into a "void *", losing a const qualifier.
+ * This is not fully portable because casting through duk_uintptr_t may
+ * not work on all architectures (e.g. those with long, segmented pointers).
+ */
+#define DUK_LOSE_CONST(src) ((void *) (duk_uintptr_t) (src))
+#endif
+
+#if !defined(DUK_LIKELY)
+#define DUK_LIKELY(x)    (x)
+#endif
+#if !defined(DUK_UNLIKELY)
+#define DUK_UNLIKELY(x)  (x)
+#endif
+
+#if !defined(DUK_NOINLINE)
+#define DUK_NOINLINE       /*nop*/
+#endif
+#if !defined(DUK_INLINE)
+#define DUK_INLINE         /*nop*/
+#endif
+#if !defined(DUK_ALWAYS_INLINE)
+#define DUK_ALWAYS_INLINE  /*nop*/
+#endif
+
+#if !defined(DUK_EXTERNAL_DECL)
+#define DUK_EXTERNAL_DECL  extern
+#endif
+#if !defined(DUK_EXTERNAL)
+#define DUK_EXTERNAL       /*empty*/
+#endif
+#if !defined(DUK_INTERNAL_DECL)
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL  static
+#else
+#define DUK_INTERNAL_DECL  extern
+#endif
+#endif
+#if !defined(DUK_INTERNAL)
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL       static
+#else
+#define DUK_INTERNAL       /*empty*/
+#endif
+#endif
+#if !defined(DUK_LOCAL_DECL)
+#define DUK_LOCAL_DECL     static
+#endif
+#if !defined(DUK_LOCAL)
+#define DUK_LOCAL          static
+#endif
+
+#if !defined(DUK_FILE_MACRO)
+#define DUK_FILE_MACRO  __FILE__
+#endif
+#if !defined(DUK_LINE_MACRO)
+#define DUK_LINE_MACRO  __LINE__
+#endif
+#if !defined(DUK_FUNC_MACRO)
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_FUNC_MACRO  __func__
+#elif defined(__FUNCTION__)
+#define DUK_FUNC_MACRO  __FUNCTION__
+#else
+#define DUK_FUNC_MACRO  "unknown"
+#endif
+#endif
+
+#if !defined(DUK_BSWAP32)
+#define DUK_BSWAP32(x) \
+	((((duk_uint32_t) (x)) >> 24) | \
+	 ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
+	 ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
+	 (((duk_uint32_t) (x)) << 24))
+#endif
+#if !defined(DUK_BSWAP16)
+#define DUK_BSWAP16(x) \
+	((duk_uint16_t) (x) >> 8) | \
+	((duk_uint16_t) (x) << 8)
+#endif
+
+/* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */
+/* DUK_USE_UNION_INITIALIZERS: required from compilers, so no fill-in. */
+
+#if !(defined(DUK_USE_FLEX_C99) || defined(DUK_USE_FLEX_ZEROSIZE) || defined(DUK_USE_FLEX_ONESIZE))
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE  /* Not standard but common enough */
+#endif
+#endif
+
+#if !(defined(DUK_USE_PACK_GCC_ATTR) || defined(DUK_USE_PACK_CLANG_ATTR) || \
+      defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+
+#if 0  /* not defined by default */
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+/* Workaround for GH-323: avoid inlining control when compiling from
+ * multiple sources, as it causes compiler portability trouble.
+ */
+#if !defined(DUK_SINGLE_FILE)
+#undef DUK_NOINLINE
+#undef DUK_INLINE
+#undef DUK_ALWAYS_INLINE
+#define DUK_NOINLINE       /*nop*/
+#define DUK_INLINE         /*nop*/
+#define DUK_ALWAYS_INLINE  /*nop*/
+#endif
+
+/*
+ *  Check whether or not a packed duk_tval representation is possible.
+ *  What's basically required is that pointers are 32-bit values
+ *  (sizeof(void *) == 4).  Best effort check, not always accurate.
+ *  If guess goes wrong, crashes may result; self tests also verify
+ *  the guess.
+ */
+
+/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */
+#if !defined(DUK_F_PACKED_TVAL_PROVIDED)
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+
+/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)
+#if (DUK_SIZE_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
+
+#undef DUK_USE_PACKED_TVAL
+#if defined(DUK_F_PACKED_TVAL_POSSIBLE)
+#define DUK_USE_PACKED_TVAL
+#endif
+
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+#endif  /* DUK_F_PACKED_TVAL_PROVIDED */
+
+/* Feature option forcing. */
+#if defined(DUK_OPT_NO_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#elif defined(DUK_OPT_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#define DUK_USE_PACKED_TVAL
+#endif
+/* Object property allocation layout has implications for memory and code
+ * footprint and generated code size/speed.  The best layout also depends
+ * on whether the platform has alignment requirements or benefits from
+ * having mostly aligned accesses.
+ */
+#undef DUK_USE_HOBJECT_LAYOUT_1
+#undef DUK_USE_HOBJECT_LAYOUT_2
+#undef DUK_USE_HOBJECT_LAYOUT_3
+#if (DUK_USE_ALIGN_BY == 1)
+/* On platforms without any alignment issues, layout 1 is preferable
+ * because it compiles to slightly less code and provides direct access
+ * to property keys.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_1
+#else
+/* On other platforms use layout 2, which requires some padding but
+ * is a bit more natural than layout 3 in ordering the entries.  Layout
+ * 3 is currently not used.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_2
+#endif
+
+/* GCC/clang inaccurate math would break compliance and probably duk_tval,
+ * so refuse to compile.  Relax this if -ffast-math is tested to work.
+ */
+#if defined(__FAST_MATH__)
+#error __FAST_MATH__ defined, refusing to compile
+#endif
+
+/*
+ *  Autogenerated defaults
+ */
+
+#undef DUK_USE_ASSERTIONS
+#define DUK_USE_AUGMENT_ERROR_CREATE
+#define DUK_USE_AUGMENT_ERROR_THROW
+#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
+#define DUK_USE_BASE64_FASTPATH
+#define DUK_USE_BROWSER_LIKE
+#define DUK_USE_BUFFEROBJECT_SUPPORT
+#undef DUK_USE_BUFLEN16
+#define DUK_USE_BUILTIN_INITJS
+#define DUK_USE_BYTECODE_DUMP_SUPPORT
+#define DUK_USE_COMMONJS_MODULES
+#define DUK_USE_COMPILER_RECLIMIT 2500
+#undef DUK_USE_CPP_EXCEPTIONS
+#undef DUK_USE_DATAPTR16
+#undef DUK_USE_DATAPTR_DEC16
+#undef DUK_USE_DATAPTR_ENC16
+#undef DUK_USE_DATE_FORMAT_STRING
+#undef DUK_USE_DATE_GET_LOCAL_TZOFFSET
+#undef DUK_USE_DATE_GET_NOW
+#undef DUK_USE_DATE_PARSE_STRING
+#undef DUK_USE_DATE_PRS_GETDATE
+#undef DUK_USE_DDDPRINT
+#undef DUK_USE_DDPRINT
+#undef DUK_USE_DEBUG
+#undef DUK_USE_DEBUGGER_DUMPHEAP
+#undef DUK_USE_DEBUGGER_FWD_LOGGING
+#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
+#undef DUK_USE_DEBUGGER_INSPECT
+#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#undef DUK_USE_DEBUGGER_SUPPORT
+#define DUK_USE_DEBUGGER_THROW_NOTIFY
+#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#define DUK_USE_DEBUG_BUFSIZE 65536L
+#define DUK_USE_DOUBLE_LINKED_HEAP
+#undef DUK_USE_DPRINT
+#undef DUK_USE_DPRINT_COLORS
+#undef DUK_USE_DPRINT_RDTSC
+#define DUK_USE_ERRCREATE
+#define DUK_USE_ERRTHROW
+#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#define DUK_USE_ES6_PROXY
+#define DUK_USE_ES6_REGEXP_BRACES
+#define DUK_USE_ESBC_LIMITS
+#define DUK_USE_ESBC_MAX_BYTES 2147418112L
+#define DUK_USE_ESBC_MAX_LINENUMBER 2147418112L
+#undef DUK_USE_EXEC_FUN_LOCAL
+#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK
+#undef DUK_USE_EXEC_TIMEOUT_CHECK
+#undef DUK_USE_EXPLICIT_NULL_INIT
+#undef DUK_USE_EXTSTR_FREE
+#undef DUK_USE_EXTSTR_INTERN_CHECK
+#undef DUK_USE_FASTINT
+#define DUK_USE_FAST_REFCOUNT_DEFAULT
+#define DUK_USE_FILE_IO
+#undef DUK_USE_FUNCPTR16
+#undef DUK_USE_FUNCPTR_DEC16
+#undef DUK_USE_FUNCPTR_ENC16
+#undef DUK_USE_GC_TORTURE
+#undef DUK_USE_HEAPPTR16
+#undef DUK_USE_HEAPPTR_DEC16
+#undef DUK_USE_HEAPPTR_ENC16
+#define DUK_USE_HEX_FASTPATH
+#define DUK_USE_HOBJECT_HASH_PART
+#define DUK_USE_HSTRING_CLEN
+#undef DUK_USE_HSTRING_EXTDATA
+#define DUK_USE_IDCHAR_FASTPATH
+#undef DUK_USE_INTERRUPT_COUNTER
+#undef DUK_USE_INTERRUPT_DEBUG_FIXUP
+#define DUK_USE_JC
+#define DUK_USE_JSON_DECNUMBER_FASTPATH
+#define DUK_USE_JSON_DECSTRING_FASTPATH
+#define DUK_USE_JSON_DEC_RECLIMIT 1000
+#define DUK_USE_JSON_EATWHITE_FASTPATH
+#define DUK_USE_JSON_ENC_RECLIMIT 1000
+#define DUK_USE_JSON_QUOTESTRING_FASTPATH
+#undef DUK_USE_JSON_STRINGIFY_FASTPATH
+#define DUK_USE_JX
+#define DUK_USE_LEXER_SLIDING_WINDOW
+#undef DUK_USE_LIGHTFUNC_BUILTINS
+#undef DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE
+#define DUK_USE_MARK_AND_SWEEP
+#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256
+#define DUK_USE_MATH_BUILTIN
+#define DUK_USE_MS_STRINGTABLE_RESIZE
+#define DUK_USE_NATIVE_CALL_RECLIMIT 1000
+#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
+#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#define DUK_USE_NONSTD_FUNC_STMT
+#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
+#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#undef DUK_USE_OBJSIZES16
+#define DUK_USE_OCTAL_SUPPORT
+#define DUK_USE_PANIC_ABORT
+#undef DUK_USE_PANIC_EXIT
+#undef DUK_USE_PANIC_HANDLER
+#undef DUK_USE_PANIC_SEGFAULT
+#undef DUK_USE_PARANOID_ERRORS
+#define DUK_USE_PC2LINE
+#undef DUK_USE_PREFER_SIZE
+#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
+#undef DUK_USE_REFCOUNT16
+#define DUK_USE_REFERENCE_COUNTING
+#undef DUK_USE_REFZERO_FINALIZER_TORTURE
+#undef DUK_USE_REGEXP_CANON_WORKAROUND
+#define DUK_USE_REGEXP_COMPILER_RECLIMIT 10000
+#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT 10000
+#define DUK_USE_REGEXP_SUPPORT
+#undef DUK_USE_ROM_GLOBAL_CLONE
+#undef DUK_USE_ROM_GLOBAL_INHERIT
+#undef DUK_USE_ROM_OBJECTS
+#define DUK_USE_ROM_PTRCOMP_FIRST 63488L
+#undef DUK_USE_ROM_STRINGS
+#define DUK_USE_SECTION_B
+#undef DUK_USE_SELF_TESTS
+#undef DUK_USE_SHUFFLE_TORTURE
+#define DUK_USE_SOURCE_NONBMP
+#undef DUK_USE_STRHASH16
+#undef DUK_USE_STRHASH_DENSE
+#define DUK_USE_STRHASH_SKIP_SHIFT 5
+#define DUK_USE_STRICT_DECL
+#undef DUK_USE_STRICT_UTF8_SOURCE
+#undef DUK_USE_STRLEN16
+#undef DUK_USE_STRTAB_CHAIN
+#undef DUK_USE_STRTAB_CHAIN_SIZE
+#define DUK_USE_STRTAB_PROBE
+#define DUK_USE_TAILCALL
+#define DUK_USE_TARGET_INFO "unknown"
+#define DUK_USE_TRACEBACKS
+#define DUK_USE_TRACEBACK_DEPTH 10
+#define DUK_USE_USER_DECLARE() /* no user declarations */
+#undef DUK_USE_USER_INITJS
+#undef DUK_USE_VALSTACK_UNSAFE
+#define DUK_USE_VERBOSE_ERRORS
+#define DUK_USE_VERBOSE_EXECUTOR_ERRORS
+#define DUK_USE_VOLUNTARY_GC
+#define DUK_USE_ZERO_BUFFER_DATA
+
+/*
+ *  Alternative customization header
+ *
+ *  If you want to modify the final DUK_USE_xxx flags directly (without
+ *  using the available DUK_OPT_xxx flags), define DUK_OPT_HAVE_CUSTOM_H
+ *  and tweak the final flags there.
+ */
+
+#if defined(DUK_OPT_HAVE_CUSTOM_H)
+#include "duk_custom.h"
+#endif
+
+/*
+ *  You may add overriding #define/#undef directives below for
+ *  customization.  You of course cannot un-#include or un-typedef
+ *  anything; these require direct changes above.
+ */
+
+/* __OVERRIDE_DEFINES__ */
+
+/*
+ *  Date provider selection
+ *
+ *  User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll
+ *  rely on an external provider.  If this is not done, revert to previous
+ *  behavior and use Unix/Windows built-in provider.
+ */
+
+#if defined(DUK_COMPILING_DUKTAPE)
+
+#if defined(DUK_USE_DATE_GET_NOW)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_gettimeofday((ctx))
+#elif defined(DUK_USE_DATE_NOW_TIME)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_time((ctx))
+#elif defined(DUK_USE_DATE_NOW_WINDOWS)
+#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_windows((ctx))
+#else
+#error no provider for DUK_USE_DATE_GET_NOW()
+#endif
+
+#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
+#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_gmtime((d))
+#elif defined(DUK_USE_DATE_TZO_WINDOWS)
+#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_windows((d))
+#else
+#error no provider for DUK_USE_DATE_GET_LOCAL_TZOFFSET()
+#endif
+
+#if defined(DUK_USE_DATE_PARSE_STRING)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_PRS_STRPTIME)
+#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_strptime((ctx), (str))
+#elif defined(DUK_USE_DATE_PRS_GETDATE)
+#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_getdate((ctx), (str))
+#else
+/* No provider for DUK_USE_DATE_PARSE_STRING(), fall back to ISO 8601 only. */
+#endif
+
+#if defined(DUK_USE_DATE_FORMAT_STRING)
+/* External provider already defined. */
+#elif defined(DUK_USE_DATE_FMT_STRFTIME)
+#define DUK_USE_DATE_FORMAT_STRING(ctx,parts,tzoffset,flags) \
+	duk_bi_date_format_parts_strftime((ctx), (parts), (tzoffset), (flags))
+#else
+/* No provider for DUK_USE_DATE_FORMAT_STRING(), fall back to ISO 8601 only. */
+#endif
+
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+/*
+ *  Checks for legacy feature options (DUK_OPT_xxx)
+ */
+
+#if defined(DUK_OPT_ASSERTIONS)
+#error unsupported legacy feature option DUK_OPT_ASSERTIONS used, consider options: DUK_USE_ASSERTIONS
+#endif
+#if defined(DUK_OPT_BUFFEROBJECT_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_BUFFEROBJECT_SUPPORT used
+#endif
+#if defined(DUK_OPT_BUFLEN16)
+#error unsupported legacy feature option DUK_OPT_BUFLEN16 used
+#endif
+#if defined(DUK_OPT_DATAPTR16)
+#error unsupported legacy feature option DUK_OPT_DATAPTR16 used
+#endif
+#if defined(DUK_OPT_DATAPTR_DEC16)
+#error unsupported legacy feature option DUK_OPT_DATAPTR_DEC16 used
+#endif
+#if defined(DUK_OPT_DATAPTR_ENC16)
+#error unsupported legacy feature option DUK_OPT_DATAPTR_ENC16 used
+#endif
+#if defined(DUK_OPT_DDDPRINT)
+#error unsupported legacy feature option DUK_OPT_DDDPRINT used
+#endif
+#if defined(DUK_OPT_DDPRINT)
+#error unsupported legacy feature option DUK_OPT_DDPRINT used
+#endif
+#if defined(DUK_OPT_DEBUG)
+#error unsupported legacy feature option DUK_OPT_DEBUG used
+#endif
+#if defined(DUK_OPT_DEBUGGER_DUMPHEAP)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_DUMPHEAP used
+#endif
+#if defined(DUK_OPT_DEBUGGER_FWD_LOGGING)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_LOGGING used
+#endif
+#if defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_PRINTALERT used
+#endif
+#if defined(DUK_OPT_DEBUGGER_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_SUPPORT used
+#endif
+#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE)
+#error unsupported legacy feature option DUK_OPT_DEBUGGER_TRANSPORT_TORTURE used
+#endif
+#if defined(DUK_OPT_DEBUG_BUFSIZE)
+#error unsupported legacy feature option DUK_OPT_DEBUG_BUFSIZE used
+#endif
+#if defined(DUK_OPT_DECLARE)
+#error unsupported legacy feature option DUK_OPT_DECLARE used
+#endif
+#if defined(DUK_OPT_DEEP_C_STACK)
+#error unsupported legacy feature option DUK_OPT_DEEP_C_STACK used
+#endif
+#if defined(DUK_OPT_DLL_BUILD)
+#error unsupported legacy feature option DUK_OPT_DLL_BUILD used
+#endif
+#if defined(DUK_OPT_DPRINT)
+#error unsupported legacy feature option DUK_OPT_DPRINT used
+#endif
+#if defined(DUK_OPT_DPRINT_COLORS)
+#error unsupported legacy feature option DUK_OPT_DPRINT_COLORS used
+#endif
+#if defined(DUK_OPT_DPRINT_RDTSC)
+#error unsupported legacy feature option DUK_OPT_DPRINT_RDTSC used
+#endif
+#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK)
+#error unsupported legacy feature option DUK_OPT_EXEC_TIMEOUT_CHECK used
+#endif
+#if defined(DUK_OPT_EXTERNAL_STRINGS)
+#error unsupported legacy feature option DUK_OPT_EXTERNAL_STRINGS used, consider options: DUK_USE_HSTRING_EXTDATA
+#endif
+#if defined(DUK_OPT_EXTSTR_FREE)
+#error unsupported legacy feature option DUK_OPT_EXTSTR_FREE used
+#endif
+#if defined(DUK_OPT_EXTSTR_INTERN_CHECK)
+#error unsupported legacy feature option DUK_OPT_EXTSTR_INTERN_CHECK used
+#endif
+#if defined(DUK_OPT_FASTINT)
+#error unsupported legacy feature option DUK_OPT_FASTINT used, consider options: DUK_USE_FASTINT
+#endif
+#if defined(DUK_OPT_FORCE_ALIGN)
+#error unsupported legacy feature option DUK_OPT_FORCE_ALIGN used
+#endif
+#if defined(DUK_OPT_FORCE_BYTEORDER)
+#error unsupported legacy feature option DUK_OPT_FORCE_BYTEORDER used
+#endif
+#if defined(DUK_OPT_FUNCPTR16)
+#error unsupported legacy feature option DUK_OPT_FUNCPTR16 used
+#endif
+#if defined(DUK_OPT_FUNCPTR_DEC16)
+#error unsupported legacy feature option DUK_OPT_FUNCPTR_DEC16 used
+#endif
+#if defined(DUK_OPT_FUNCPTR_ENC16)
+#error unsupported legacy feature option DUK_OPT_FUNCPTR_ENC16 used
+#endif
+#if defined(DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY used
+#endif
+#if defined(DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY used
+#endif
+#if defined(DUK_OPT_GC_TORTURE)
+#error unsupported legacy feature option DUK_OPT_GC_TORTURE used
+#endif
+#if defined(DUK_OPT_HAVE_CUSTOM_H)
+#error unsupported legacy feature option DUK_OPT_HAVE_CUSTOM_H used
+#endif
+#if defined(DUK_OPT_HEAPPTR16)
+#error unsupported legacy feature option DUK_OPT_HEAPPTR16 used
+#endif
+#if defined(DUK_OPT_HEAPPTR_DEC16)
+#error unsupported legacy feature option DUK_OPT_HEAPPTR_DEC16 used
+#endif
+#if defined(DUK_OPT_HEAPPTR_ENC16)
+#error unsupported legacy feature option DUK_OPT_HEAPPTR_ENC16 used
+#endif
+#if defined(DUK_OPT_INTERRUPT_COUNTER)
+#error unsupported legacy feature option DUK_OPT_INTERRUPT_COUNTER used
+#endif
+#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH)
+#error unsupported legacy feature option DUK_OPT_JSON_STRINGIFY_FASTPATH used
+#endif
+#if defined(DUK_OPT_LIGHTFUNC_BUILTINS)
+#error unsupported legacy feature option DUK_OPT_LIGHTFUNC_BUILTINS used
+#endif
+#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY used
+#endif
+#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY used
+#endif
+#if defined(DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT)
+#error unsupported legacy feature option DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT used
+#endif
+#if defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#error unsupported legacy feature option DUK_OPT_NO_AUGMENT_ERRORS used
+#endif
+#if defined(DUK_OPT_NO_BROWSER_LIKE)
+#error unsupported legacy feature option DUK_OPT_NO_BROWSER_LIKE used
+#endif
+#if defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_BUFFEROBJECT_SUPPORT used
+#endif
+#if defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_BYTECODE_DUMP_SUPPORT used, consider options: DUK_USE_BYTECODE_DUMP_SUPPORT
+#endif
+#if defined(DUK_OPT_NO_COMMONJS_MODULES)
+#error unsupported legacy feature option DUK_OPT_NO_COMMONJS_MODULES used
+#endif
+#if defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY used
+#endif
+#if defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)
+#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF used
+#endif
+#if defined(DUK_OPT_NO_ES6_PROXY)
+#error unsupported legacy feature option DUK_OPT_NO_ES6_PROXY used
+#endif
+#if defined(DUK_OPT_NO_FILE_IO)
+#error unsupported legacy feature option DUK_OPT_NO_FILE_IO used, consider options: DUK_USE_FILE_IO
+#endif
+#if defined(DUK_OPT_NO_FUNC_STMT)
+#error unsupported legacy feature option DUK_OPT_NO_FUNC_STMT used
+#endif
+#if defined(DUK_OPT_NO_JC)
+#error unsupported legacy feature option DUK_OPT_NO_JC used
+#endif
+#if defined(DUK_OPT_NO_JSONC)
+#error unsupported legacy feature option DUK_OPT_NO_JSONC used
+#endif
+#if defined(DUK_OPT_NO_JSONX)
+#error unsupported legacy feature option DUK_OPT_NO_JSONX used
+#endif
+#if defined(DUK_OPT_NO_JX)
+#error unsupported legacy feature option DUK_OPT_NO_JX used
+#endif
+#if defined(DUK_OPT_NO_MARK_AND_SWEEP)
+#error unsupported legacy feature option DUK_OPT_NO_MARK_AND_SWEEP used
+#endif
+#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)
+#error unsupported legacy feature option DUK_OPT_NO_MS_STRINGTABLE_RESIZE used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_FUNC_STMT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_FUNC_STMT used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029 used
+#endif
+#if defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT)
+#error unsupported legacy feature option DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT used
+#endif
+#if defined(DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY)
+#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY used
+#endif
+#if defined(DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF)
+#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF used
+#endif
+#if defined(DUK_OPT_NO_OCTAL_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_OCTAL_SUPPORT used
+#endif
+#if defined(DUK_OPT_NO_PACKED_TVAL)
+#error unsupported legacy feature option DUK_OPT_NO_PACKED_TVAL used
+#endif
+#if defined(DUK_OPT_NO_PC2LINE)
+#error unsupported legacy feature option DUK_OPT_NO_PC2LINE used
+#endif
+#if defined(DUK_OPT_NO_REFERENCE_COUNTING)
+#error unsupported legacy feature option DUK_OPT_NO_REFERENCE_COUNTING used, consider options: DUK_USE_REFERENCE_COUNTING
+#endif
+#if defined(DUK_OPT_NO_REGEXP_SUPPORT)
+#error unsupported legacy feature option DUK_OPT_NO_REGEXP_SUPPORT used
+#endif
+#if defined(DUK_OPT_NO_SECTION_B)
+#error unsupported legacy feature option DUK_OPT_NO_SECTION_B used
+#endif
+#if defined(DUK_OPT_NO_SOURCE_NONBMP)
+#error unsupported legacy feature option DUK_OPT_NO_SOURCE_NONBMP used
+#endif
+#if defined(DUK_OPT_NO_STRICT_DECL)
+#error unsupported legacy feature option DUK_OPT_NO_STRICT_DECL used
+#endif
+#if defined(DUK_OPT_NO_TRACEBACKS)
+#error unsupported legacy feature option DUK_OPT_NO_TRACEBACKS used
+#endif
+#if defined(DUK_OPT_NO_VERBOSE_ERRORS)
+#error unsupported legacy feature option DUK_OPT_NO_VERBOSE_ERRORS used
+#endif
+#if defined(DUK_OPT_NO_VOLUNTARY_GC)
+#error unsupported legacy feature option DUK_OPT_NO_VOLUNTARY_GC used
+#endif
+#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA)
+#error unsupported legacy feature option DUK_OPT_NO_ZERO_BUFFER_DATA used
+#endif
+#if defined(DUK_OPT_OBJSIZES16)
+#error unsupported legacy feature option DUK_OPT_OBJSIZES16 used
+#endif
+#if defined(DUK_OPT_PANIC_HANDLER)
+#error unsupported legacy feature option DUK_OPT_PANIC_HANDLER used
+#endif
+#if defined(DUK_OPT_REFCOUNT16)
+#error unsupported legacy feature option DUK_OPT_REFCOUNT16 used
+#endif
+#if defined(DUK_OPT_SEGFAULT_ON_PANIC)
+#error unsupported legacy feature option DUK_OPT_SEGFAULT_ON_PANIC used
+#endif
+#if defined(DUK_OPT_SELF_TESTS)
+#error unsupported legacy feature option DUK_OPT_SELF_TESTS used
+#endif
+#if defined(DUK_OPT_SETJMP)
+#error unsupported legacy feature option DUK_OPT_SETJMP used
+#endif
+#if defined(DUK_OPT_SHUFFLE_TORTURE)
+#error unsupported legacy feature option DUK_OPT_SHUFFLE_TORTURE used
+#endif
+#if defined(DUK_OPT_SIGSETJMP)
+#error unsupported legacy feature option DUK_OPT_SIGSETJMP used
+#endif
+#if defined(DUK_OPT_STRHASH16)
+#error unsupported legacy feature option DUK_OPT_STRHASH16 used
+#endif
+#if defined(DUK_OPT_STRICT_UTF8_SOURCE)
+#error unsupported legacy feature option DUK_OPT_STRICT_UTF8_SOURCE used
+#endif
+#if defined(DUK_OPT_STRLEN16)
+#error unsupported legacy feature option DUK_OPT_STRLEN16 used
+#endif
+#if defined(DUK_OPT_STRTAB_CHAIN)
+#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN used
+#endif
+#if defined(DUK_OPT_STRTAB_CHAIN_SIZE)
+#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN_SIZE used
+#endif
+#if defined(DUK_OPT_TARGET_INFO)
+#error unsupported legacy feature option DUK_OPT_TARGET_INFO used
+#endif
+#if defined(DUK_OPT_TRACEBACK_DEPTH)
+#error unsupported legacy feature option DUK_OPT_TRACEBACK_DEPTH used
+#endif
+#if defined(DUK_OPT_UNDERSCORE_SETJMP)
+#error unsupported legacy feature option DUK_OPT_UNDERSCORE_SETJMP used
+#endif
+#if defined(DUK_OPT_USER_INITJS)
+#error unsupported legacy feature option DUK_OPT_USER_INITJS used
+#endif
+
+/*
+ *  Checks for config option consistency (DUK_USE_xxx)
+ */
+
+#if defined(DUK_USE_32BIT_PTRS)
+#error unsupported config option used (option has been removed): DUK_USE_32BIT_PTRS
+#endif
+#if defined(DUK_USE_ALIGN_4)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_4
+#endif
+#if defined(DUK_USE_ALIGN_8)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_8
+#endif
+#if defined(DUK_USE_BYTEORDER_FORCED)
+#error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED
+#endif
+#if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_DATAPTR_ENC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_ENC16 requires option DUK_USE_DATAPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_DEBUGGER_SUPPORT requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_DEEP_C_STACK)
+#error unsupported config option used (option has been removed): DUK_USE_DEEP_C_STACK
+#endif
+#if defined(DUK_USE_DOUBLE_BE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_BE
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_LE
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_ME
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG)
+#error config option DUK_USE_DPRINT requires option DUK_USE_DEBUG (which is missing)
+#endif
+#if defined(DUK_USE_ESBC_MAX_BYTES) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_BYTES requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_ESBC_MAX_LINENUMBER) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_LINENUMBER requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_EXEC_TIMEOUT_CHECK) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_EXEC_TIMEOUT_CHECK requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_FREE) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_FREE requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_INTERN_CHECK) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_INTERN_CHECK requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_FULL_TVAL)
+#error unsupported config option used (option has been removed): DUK_USE_FULL_TVAL
+#endif
+#if defined(DUK_USE_FUNCPTR_DEC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_DEC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_FUNCPTR_ENC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_ENC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
+#error unsupported config option used (option has been removed): DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
+#endif
+#if defined(DUK_USE_HEAPPTR16) && defined(DUK_USE_DEBUG)
+#error config option DUK_USE_HEAPPTR16 conflicts with option DUK_USE_DEBUG (which is also defined)
+#endif
+#if defined(DUK_USE_HEAPPTR_DEC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_DEC16 requires option DUK_USE_HEAPPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HEAPPTR_ENC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_ENC16 requires option DUK_USE_HEAPPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_INTEGER_BE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_BE
+#endif
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_LE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_LE
+#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_ME
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)
+#error unsupported config option used (option has been removed): DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
+#endif
+#if defined(DUK_USE_PACKED_TVAL_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_PACKED_TVAL_POSSIBLE
+#endif
+#if defined(DUK_USE_RDTSC)
+#error unsupported config option used (option has been removed): DUK_USE_RDTSC
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_STRINGS)
+#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_STRINGS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_OBJECTS)
+#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_OBJECTS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_CLONE) && defined(DUK_USE_ROM_GLOBAL_INHERIT)
+#error config option DUK_USE_ROM_GLOBAL_CLONE conflicts with option DUK_USE_ROM_GLOBAL_INHERIT (which is also defined)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_STRINGS)
+#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_STRINGS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_OBJECTS)
+#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_OBJECTS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && defined(DUK_USE_ROM_GLOBAL_CLONE)
+#error config option DUK_USE_ROM_GLOBAL_INHERIT conflicts with option DUK_USE_ROM_GLOBAL_CLONE (which is also defined)
+#endif
+#if defined(DUK_USE_ROM_OBJECTS) && !defined(DUK_USE_ROM_STRINGS)
+#error config option DUK_USE_ROM_OBJECTS requires option DUK_USE_ROM_STRINGS (which is missing)
+#endif
+#if defined(DUK_USE_ROM_STRINGS) && !defined(DUK_USE_ROM_OBJECTS)
+#error config option DUK_USE_ROM_STRINGS requires option DUK_USE_ROM_OBJECTS (which is missing)
+#endif
+#if defined(DUK_USE_SETJMP)
+#error unsupported config option used (option has been removed): DUK_USE_SETJMP
+#endif
+#if defined(DUK_USE_SIGSETJMP)
+#error unsupported config option used (option has been removed): DUK_USE_SIGSETJMP
+#endif
+#if defined(DUK_USE_STRTAB_CHAIN_SIZE) && !defined(DUK_USE_STRTAB_CHAIN)
+#error config option DUK_USE_STRTAB_CHAIN_SIZE requires option DUK_USE_STRTAB_CHAIN (which is missing)
+#endif
+#if defined(DUK_USE_TAILCALL) && defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+#error config option DUK_USE_TAILCALL conflicts with option DUK_USE_NONSTD_FUNC_CALLER_PROPERTY (which is also defined)
+#endif
+#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
+#endif
+#if defined(DUK_USE_UNDERSCORE_SETJMP)
+#error unsupported config option used (option has been removed): DUK_USE_UNDERSCORE_SETJMP
+#endif
+
+#if defined(DUK_USE_CPP_EXCEPTIONS) && !defined(__cplusplus)
+#error DUK_USE_CPP_EXCEPTIONS enabled but not compiling with a C++ compiler
+#endif
+
+/*
+ *  Convert DUK_USE_BYTEORDER, from whatever source, into currently used
+ *  internal defines.  If detection failed, #error out.
+ */
+
+#if defined(DUK_USE_BYTEORDER)
+#if (DUK_USE_BYTEORDER == 1)
+#define DUK_USE_INTEGER_LE
+#define DUK_USE_DOUBLE_LE
+#elif (DUK_USE_BYTEORDER == 2)
+#define DUK_USE_INTEGER_LE  /* integer endianness is little on purpose */
+#define DUK_USE_DOUBLE_ME
+#elif (DUK_USE_BYTEORDER == 3)
+#define DUK_USE_INTEGER_BE
+#define DUK_USE_DOUBLE_BE
+#else
+#error unsupported: byte order invalid
+#endif  /* byte order */
+#else
+#error unsupported: byte order detection failed
+#endif  /* defined(DUK_USE_BYTEORDER) */
+
+#endif  /* DUK_CONFIG_H_INCLUDED */

+ 1537 - 0
src/third_party/duktape-1.5.2/config/genconfig.py

@@ -0,0 +1,1537 @@
+#!/usr/bin/env python2
+#
+#  Process Duktape option metadata and produce various useful outputs:
+#
+#    - duk_config.h with specific or autodetected platform, compiler, and
+#      architecture; forced options; sanity checks; 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.
+#
+#  For Duktape 1.3 release the main goal was to autogenerate a Duktape 1.2
+#  compatible "autodetect" header from legacy snippets, with other outputs
+#  being experimental.  For Duktape 1.4 duk_config.h is always created from
+#  modular sources.
+#
+
+import os
+import sys
+import re
+import json
+import yaml
+import optparse
+import tarfile
+import tempfile
+import atexit
+import shutil
+try:
+	from StringIO import StringIO
+except ImportError:
+	from io 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',
+	'feature_no_default',
+	'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()).  Fill-ins provide missing optionals.
+platform_required_provides = [
+	'DUK_USE_OS_STRING'  # must be #define'd
+]
+
+# Architecture files must provide at least these (additional checks
+# in validate_architecture_file()).  Fill-ins provide missing optionals.
+architecture_required_provides = [
+	'DUK_USE_ARCH_STRING'
+]
+
+# Compiler files must provide at least these (additional checks
+# in validate_compiler_file()).  Fill-ins provide missing optionals.
+compiler_required_provides = [
+	# Compilers need a lot of defines; missing defines are automatically
+	# filled in with defaults (which are mostly compiler independent), so
+	# the requires define list is not very large.
+
+	'DUK_USE_COMPILER_STRING',    # must be #define'd
+	'DUK_USE_BRANCH_HINTS',       # may be #undef'd, as long as provided
+	'DUK_USE_VARIADIC_MACROS',    # may be #undef'd, as long as provided
+	'DUK_USE_UNION_INITIALIZERS'  # may be #undef'd, as long as provided
+]
+
+#
+#  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.
+	# (The 'redefine' hack is not actively needed now.)
+	#
+	# 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.  Such redefinitions
+			# are marked "/* redefine */" in the snippets.  They're best
+			# avoided (and not currently needed in Duktape 1.4.0).
+
+			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]
+				if line[:8] == '#snippet':
+					m = re.match(r'#snippet\s+"(.*?)"', line)
+					# XXX: better plumbing for lookup path
+					sub_fn = os.path.normpath(os.path.join(filename, '..', '..', 'header-snippets', m.group(1)))
+					#print('#snippet ' + sub_fn)
+					sn = Snippet.fromFile(sub_fn)
+					lines += sn.lines
+				else:
+					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)
+		return sn
+
+	def snippet_absolute(self, fn):
+		sn = Snippet.fromFile(fn)
+		self.vals.append(sn)
+		return 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_comment_line(self, msg):
+		self.vals.append(Snippet([ '/* %s */' % 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)
+	print('Resolved %d helper defines' % len(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_helper_snippets(dirname):  # DUK_F_xxx snippets
+	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 get_opt_defs(removed=True, deprecated=True, unused=True):
+	ret = []
+	for doc in opt_defs_list:
+		# XXX: aware of target version
+		if removed == False and doc.get('removed', None) is not None:
+			continue
+		if deprecated == False and doc.get('deprecated', None) is not None:
+			continue
+		if unused == False and doc.get('unused', False) == True:
+			continue
+		ret.append(doc)
+	return ret
+
+def get_use_defs(removed=True, deprecated=True, unused=True):
+	ret = []
+	for doc in use_defs_list:
+		# XXX: aware of target version
+		if removed == False and doc.get('removed', None) is not None:
+			continue
+		if deprecated == False and doc.get('deprecated', None) is not None:
+			continue
+		if unused == False and doc.get('unused', False) == True:
+			continue
+		ret.append(doc)
+	return ret
+
+def validate_platform_file(filename):
+	sn = Snippet.fromFile(filename)
+
+	for req in platform_required_provides:
+		if req not in sn.provides:
+			raise Exception('Platform %s is missing %s' % (filename, req))
+
+	# DUK_SETJMP, DUK_LONGJMP, DUK_JMPBUF_TYPE are optional, fill-in
+	# provides if none defined.
+
+def validate_architecture_file(filename):
+	sn = Snippet.fromFile(filename)
+
+	for req in architecture_required_provides:
+		if req not in sn.provides:
+			raise Exception('Architecture %s is missing %s' % (filename, req))
+
+	# Byte order and alignment defines are allowed to be missing,
+	# a fill-in will handle them.  This is necessary because for
+	# some architecture byte order and/or alignment may vary between
+	# targets and may be software configurable.
+
+	# XXX: require automatic detection to be signaled?
+	# e.g. define DUK_USE_ALIGN_BY -1
+	#      define DUK_USE_BYTE_ORDER -1
+
+def validate_compiler_file(filename):
+	sn = Snippet.fromFile(filename)
+
+	for req in compiler_required_provides:
+		if req not in sn.provides:
+			raise Exception('Compiler %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):
+	defs = get_opt_defs()
+	return generate_option_documentation(opts, opt_list=defs, rst_title='Duktape feature options', include_default=False)
+
+def generate_config_option_documentation(opts):
+	defs = get_use_defs()
+	return generate_option_documentation(opts, opt_list=defs, 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(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
+
+	if len(forced_opts.keys()) > 0:
+		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'])
+
+	# NOTE: careful with Python equality, e.g. "0 == False" is true.
+	if isinstance(defval, bool) and defval == True:
+		ret.line('#define ' + defname)
+	elif isinstance(defval, bool) and 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)')
+	ret.empty()
+
+	defs = []
+	for doc in get_opt_defs():
+		if doc['define'] not in defs:
+			defs.append(doc['define'])
+	for doc in get_opt_defs():
+		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 get_use_defs():
+			if optname in doc.get('related_feature_defines', []):
+				suggested.append(doc['define'])
+		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)')
+	ret.empty()
+
+	defs = []
+	for doc in get_use_defs():
+		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.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.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.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.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()
+	ret.snippet_relative('cpp_exception_sanity.h.in')
+	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, already_provided_keys):
+	ret.chdr_block_heading('Feature option handling')
+
+	for doc in get_use_defs(removed=False, deprecated=False, unused=False):
+		# 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
+
+			# For some options like DUK_OPT_PACKED_TVAL the default comes
+			# from platform definition.
+			if doc.get('feature_no_default', False):
+				print('Skip default for option %s' % config_define)
+				ret.line('/* Already provided above */')
+			elif already_provided_keys.has_key(config_define):
+				# This is a fallback in case config option metadata is wrong.
+				print('Skip default for option %s (already provided but not flagged in metadata!)' % config_define)
+				ret.line('/* Already provided above */')
+			else:
+				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 get_use_defs():
+		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 a duk_config.h where platform, architecture, and compiler are
+# all either autodetected or specified by user.
+#
+# Autodetection is based on a configured list of supported platforms,
+# architectures, and compilers.  For example, platforms.yaml defines the
+# supported platforms and provides a helper define (DUK_F_xxx) to use for
+# detecting that platform, and names the header snippet to provide the
+# platform-specific definitions.  Necessary dependencies (DUK_F_xxx) are
+# automatically pulled in.
+#
+# Automatic "fill ins" are used for mandatory platform, architecture, and
+# compiler defines which have a reasonable portable default.  This reduces
+# e.g. compiler-specific define count because there are a lot compiler
+# macros which have a good default.
+def generate_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)
+
+	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)
+
+	# XXX: indicate feature option support, sanity checks enabled, etc
+	# in general summary of options, perhaps genconfig command line?
+
+	ret.line('/*')
+	ret.line(' *  duk_config.h configuration 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(' *  Git branch: %s' % opts.git_branch 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('#if !defined(DUK_CONFIG_H_INCLUDED)')
+	ret.line('#define DUK_CONFIG_H_INCLUDED')
+	ret.empty()
+
+	ret.chdr_block_heading('Intermediate helper defines')
+
+	# DLL build affects visibility attributes on Windows but unfortunately
+	# cannot be detected automatically from preprocessor defines or such.
+	# DLL build status is hidden behind DUK_F_DLL_BUILD and there are two
+	# ways for that to be set:
+	#
+	#   - Duktape 1.3 backwards compatible DUK_OPT_DLL_BUILD
+	#   - Genconfig --dll option
+	ret.chdr_comment_line('DLL build detection')
+	ret.line('#if defined(DUK_OPT_DLL_BUILD)')
+	ret.line('#define DUK_F_DLL_BUILD')
+	ret.line('#elif defined(DUK_OPT_NO_DLL_BUILD)')
+	ret.line('#undef DUK_F_DLL_BUILD')
+	ret.line('#else')
+	if opts.dll:
+		ret.line('/* configured for DLL build */')
+		ret.line('#define DUK_F_DLL_BUILD')
+	else:
+		ret.line('/* not configured for DLL build */')
+		ret.line('#undef DUK_F_DLL_BUILD')
+	ret.line('#endif')
+	ret.empty()
+
+	idx_deps = len(ret.vals)  # position where to emit DUK_F_xxx 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
+		abs_fn = os.path.join(meta_dir, 'platforms', include)
+		validate_platform_file(abs_fn)
+		ret.snippet_absolute(abs_fn)
+	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']
+			abs_fn = os.path.join(meta_dir, 'platforms', include)
+
+			validate_platform_file(abs_fn)
+
+			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.line('/* --- %s --- */' % platf.get('name', '???'))
+			ret.snippet_absolute(abs_fn)
+		ret.line('#endif  /* autodetect platform */')
+
+	ret.empty()
+	ret.snippet_relative('platform_sharedincludes.h.in')
+	ret.empty()
+
+	byteorder_provided_by_all = True  # byteorder provided by all architecture files
+	alignment_provided_by_all = True  # alignment provided by all architecture files
+	packedtval_provided_by_all = True # packed tval provided by all architecture files
+
+	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
+		abs_fn = os.path.join(meta_dir, 'architectures', include)
+		validate_architecture_file(abs_fn)
+		sn = ret.snippet_absolute(abs_fn)
+		if not sn.provides.get('DUK_USE_BYTEORDER', False):
+			byteorder_provided_by_all = False
+		if not sn.provides.get('DUK_USE_ALIGN_BY', False):
+			alignment_provided_by_all = False
+		if sn.provides.get('DUK_USE_PACKED_TVAL', False):
+			ret.line('#define DUK_F_PACKED_TVAL_PROVIDED')  # signal to fillin
+		else:
+			packedtval_provided_by_all = False
+	else:
+		ret.chdr_block_heading('Architecture autodetection')
+
+		for idx, arch in enumerate(architectures['autodetect']):
+			check = arch.get('check', None)
+			include = arch['include']
+			abs_fn = os.path.join(meta_dir, 'architectures', include)
+
+			validate_architecture_file(abs_fn)
+
+			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.line('/* --- %s --- */' % arch.get('name', '???'))
+			sn = ret.snippet_absolute(abs_fn)
+			if not sn.provides.get('DUK_USE_BYTEORDER', False):
+				byteorder_provided_by_all = False
+			if not sn.provides.get('DUK_USE_ALIGN_BY', False):
+				alignment_provided_by_all = False
+			if sn.provides.get('DUK_USE_PACKED_TVAL', False):
+				ret.line('#define DUK_F_PACKED_TVAL_PROVIDED')  # signal to fillin
+			else:
+				packedtval_provided_by_all = False
+		ret.line('#endif  /* autodetect architecture */')
+
+	ret.empty()
+
+	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
+		abs_fn = os.path.join(meta_dir, 'compilers', include)
+		validate_compiler_file(abs_fn)
+		sn = ret.snippet_absolute(abs_fn)
+	else:
+		ret.chdr_block_heading('Compiler autodetection')
+
+		for idx, comp in enumerate(compilers['autodetect']):
+			check = comp.get('check', None)
+			include = comp['include']
+			abs_fn = os.path.join(meta_dir, 'compilers', include)
+
+			validate_compiler_file(abs_fn)
+
+			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.line('/* --- %s --- */' % comp.get('name', '???'))
+			sn = ret.snippet_absolute(abs_fn)
+		ret.line('#endif  /* autodetect compiler */')
+
+	ret.empty()
+
+	# DUK_F_UCLIBC is special because __UCLIBC__ is provided by an #include
+	# file, so the check must happen after platform includes.  It'd be nice
+	# for this to be automatic (e.g. DUK_F_UCLIBC.h.in could indicate the
+	# dependency somehow).
+
+	ret.snippet_absolute(os.path.join(meta_dir, 'helper-snippets', 'DUK_F_UCLIBC.h.in'))
+	ret.empty()
+
+	# XXX: platform/compiler could provide types; if so, need some signaling
+	# defines like DUK_F_TYPEDEFS_DEFINED
+
+	# Number types
+	if opts.c99_types_only:
+		ret.snippet_relative('types1.h.in')
+		ret.line('/* C99 types assumed */')
+		ret.snippet_relative('types_c99.h.in')
+		ret.empty()
+	else:
+		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()
+
+	# Platform, architecture, compiler fillins.  These are after all
+	# detection so that e.g. DUK_SPRINTF() can be provided by platform
+	# or compiler before trying a fill-in.
+
+	ret.chdr_block_heading('Fill-ins for platform, architecture, and compiler')
+
+	ret.snippet_relative('platform_fillins.h.in')
+	ret.empty()
+	ret.snippet_relative('architecture_fillins.h.in')
+	if not byteorder_provided_by_all:
+		ret.empty()
+		ret.snippet_relative('byteorder_fillin.h.in')
+	if not alignment_provided_by_all:
+		ret.empty()
+		ret.snippet_relative('alignment_fillin.h.in')
+	ret.empty()
+	ret.snippet_relative('compiler_fillins.h.in')
+	ret.empty()
+	ret.snippet_relative('inline_workaround.h.in')
+	ret.empty()
+	if not packedtval_provided_by_all:
+		ret.empty()
+		ret.snippet_relative('packed_tval_fillin.h.in')
+
+	# Object layout
+	ret.snippet_relative('object_layout.h.in')
+	ret.empty()
+
+	# Detect and reject 'fast math'
+	ret.snippet_relative('reject_fast_math.h.in')
+	ret.empty()
+
+	# Automatic DUK_OPT_xxx feature option handling
+	if opts.support_feature_options:
+		print('Autogenerating feature option (DUK_OPT_xxx) support')
+		tmp = Snippet(ret.join().split('\n'))
+		add_feature_option_handling(opts, ret, forced_opts, tmp.provides)
+
+	# 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 get_use_defs(removed=not opts.omit_removed_config_options,
+	                        deprecated=not opts.omit_deprecated_config_options,
+	                        unused=not opts.omit_unused_config_options):
+		defname = doc['define']
+
+		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 get_use_defs(removed=False):
+		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)
+
+	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)
+
+	# Derived defines (DUK_USE_INTEGER_LE, etc) from DUK_USE_BYTEORDER.
+	# Duktape internals currently rely on the derived defines.  This is
+	# after sanity checks because the derived defines are marked removed.
+	ret.snippet_relative('byteorder_derived.h.in')
+	ret.empty()
+
+	ret.line('#endif  /* DUK_CONFIG_H_INCLUDED */')
+	ret.empty()  # for trailing newline
+	return remove_duplicate_newlines(ret.join())
+
+#
+#  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 = [
+		'duk-config-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('--c99-types-only', dest='c99_types_only', action='store_true', default=False, help='assume C99 types, no legacy type detection')
+	parser.add_option('--dll', dest='dll', action='store_true', default=False, help='dll build of Duktape, affects symbol visibility macros especially on Windows')
+	parser.add_option('--support-feature-options', dest='support_feature_options', action='store_true', default=False, help='support DUK_OPT_xxx feature options in duk_config.h')
+	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')
+	parser.add_option('--git-branch', dest='git_branch', default=None, help='git branch 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
+		metadata_src_text = '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)
+		metadata_src_text = '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_helper_snippets(os.path.join(meta_dir, 'helper-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('%s, scanned %d DUK_OPT_xxx, %d DUK_USE_XXX, %d helper snippets' % \
+		(metadata_src_text, 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]
+
+	# Compatibility with Duktape 1.3
+	if cmd == 'autodetect-header':
+		cmd = 'duk-config-header'
+	if cmd == 'barebones-header':
+		cmd = 'duk-config-header'
+
+	if cmd == 'duk-config-header':
+		# Generate a duk_config.h header with platform, compiler, and
+		# architecture either autodetected (default) or specified by
+		# user.  Support for autogenerated DUK_OPT_xxx flags is also
+		# selected by user.
+		result = generate_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()

BIN
src/third_party/duktape-1.5.2/config/genconfig_metadata.tar.gz


+ 101 - 0
src/third_party/duktape-1.5.2/debugger/Makefile

@@ -0,0 +1,101 @@
+NODE:=$(shell which nodejs node | head -1)
+DUKLUV:=dukluv
+
+# 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)
+
+rundebug: 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) --verbose --log-messages /tmp/dukdebug-messages --dump-debug-pretty /tmp/dukdebug-pretty
+
+.PHONY: runproxynodejs
+runproxynodejs: 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
+	@echo "Running Node.js based debug proxy"
+	"$(NODE)" duk_debug.js --json-proxy
+
+.PHONY: runproxydukluv
+runproxydukluv: duk_debug_meta.json
+	@echo "Running Dukluv based debug proxy (you may need to edit DUKLUV in the Makefile)"
+	"$(DUKLUV)" duk_debug_proxy.js --log-level 2 --metadata duk_debug_meta.json --readable-numbers
+
+.PHONY: runproxy
+runproxy: runproxydukluv
+
+.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
+	@rm -f duk_debug_meta.json
+
+node_modules:
+	npm install
+
+duk_debug_meta.json:
+	python merge_debug_meta.py --output $@ \
+		--class-names duk_classnames.yaml \
+		--opcodes duk_opcodes.yaml \
+		--debug-commands duk_debugcommands.yaml \
+		--debug-errors duk_debugerrors.yaml
+
+static/socket.io-1.2.0.js:
+	wget -O $@ http://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/

+ 384 - 0
src/third_party/duktape-1.5.2/debugger/README.rst

@@ -0,0 +1,384 @@
+=========================================
+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``)
+on Unix and Windows.
+
+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 http://wiki.duktape.org/FeatureOptions.html):
+
+* ``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 <duktape dist directory>
+    $ 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 <duktape dist directory>
+    $ ./duk --debugger mandel.js
+
+    # Using Duktape Git repo
+    $ cd <duktape checkout>/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
+==========================
+
+There are two JSON debug proxy implementations: one implemented in DukLuv
+and another in Node.js.
+
+DukLuv JSON proxy
+-----------------
+
+DukLuv (https://github.com/creationix/dukluv) is a small and portable event
+loop based on LibUV and Duktape with MIT license (like Duktape).  As such it's
+easy to embed in a custom debug client: you just include the DukLuv executable
+and the JSON proxy source file in your debug client.
+
+Install DukLuv:
+
+* Ensure ``cmake`` is installed
+
+* ``git clone https://github.com/creationix/dukluv.git``
+
+* ``git submodule init; git submodule update``
+
+* ``make``
+
+* Binary should appear in:
+
+  - ``./build/dukluv`` on Linux
+
+  - ``.\build\Debug\dukluv.exe`` on Windows
+
+Run the proxy::
+
+    # Using Makefile; autogenerates duk_debug_meta.json
+    # (You may need to edit DUKLUV in Makefile to point to your DukLuv)
+    $ make runproxydukluv
+
+    # Manually: see "dukluv duk_debug_proxy.js --help" for help
+    $ .../path/to/dukluv duk_debug_proxy.js
+
+Start Duktape command line (or whatever your target is)::
+
+    $ cd <duktape checkout>/tests/ecmascript/
+    $ ../../duk --debugger test-dev-mandel2-func.js
+
+Now connect to the proxy using e.g. telnet::
+
+    $ telnet localhost 9093
+
+The proxy will then connect to the target and you can start issuing commands::
+
+    $ telnet localhost 9093
+    Trying 127.0.0.1...
+    Connected to localhost.
+    Escape character is '^]'.
+    {"notify":"_TargetConnecting","args":["127.0.0.1",9091]}
+    {"notify":"_TargetConnected","args":["1 10499 v1.4.0-140-gc9a6c7c 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":[10499,"v1.4.0-140-gc9a6c7c","duk command built from Duktape repo",1]}
+    {"request":"Eval","args":["print('Hello world!'); 123;"]}
+    {"notify":"Print","command":2,"args":["Hello world!\n"]}
+    {"reply":true,"args":[0,{"type":"number","data":"405ec00000000000"}]}
+    [...]
+
+The proxy log provides dumps both JSON and dvalue binary traffic which is
+quite useful in development::
+
+    $ make runproxydukluv
+    Running Dukluv based debug proxy
+    "dukluv" duk_debug_proxy.js --log-level 2 --metadata duk_debug_meta.json
+    2016-02-17T13:59:42.308Z INF Proxy: Read proxy metadata from duk_debug_meta.json
+    2016-02-17T13:59:42.325Z INF Proxy: Listening for incoming JSON debug connection on 0.0.0.0:9093, target is 127.0.0.1:9091
+    2016-02-17T13:59:47.994Z INF Proxy: JSON proxy client connected
+    2016-02-17T13:59:47.994Z INF Proxy: Connecting to debug target at 127.0.0.1:9091
+    2016-02-17T13:59:47.994Z INF Proxy: PROXY --> CLIENT: {"notify":"_TargetConnecting","args":["127.0.0.1",9091]}
+    2016-02-17T13:59:47.994Z INF Proxy: Connected to debug target at 127.0.0.1:9091
+    2016-02-17T13:59:48.003Z INF Proxy: PROXY --> CLIENT: {"notify":"_TargetConnected","args":["1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo"]}
+    2016-02-17T13:59:48.003Z INF Proxy: Target handshake: {"line":"1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo","protocolVersion":1,"text":"10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo","dukVersion":"1","dukGitDescribe":"10499","targetString":"v1.4.0-140-gc9a6c7c"}
+    2016-02-17T13:59:48.151Z INF Proxy: PROXY <-- TARGET: |04|
+    2016-02-17T13:59:48.152Z INF Proxy: PROXY <-- TARGET: |81|
+    2016-02-17T13:59:48.152Z INF Proxy: PROXY <-- TARGET: |81|
+    2016-02-17T13:59:48.160Z INF Proxy: PROXY <-- TARGET: |78746573742d6465762d6d616e64656c322d66756e632e6a73|
+    2016-02-17T13:59:48.161Z INF Proxy: PROXY <-- TARGET: |66676c6f62616c|
+    2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |ba|
+    2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |80|
+    2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |00|
+    2016-02-17T13:59:48.165Z INF Proxy: PROXY --> CLIENT: {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]}
+    2016-02-17T13:59:51.289Z INF Proxy: PROXY <-- CLIENT: {"request":"BasicInfo"}
+    2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |01|
+    2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |90|
+    2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |00|
+    2016-02-17T13:59:51.291Z INF Proxy: PROXY <-- TARGET: |02|
+    2016-02-17T13:59:51.291Z INF Proxy: PROXY <-- TARGET: |e903|
+    2016-02-17T13:59:51.292Z INF Proxy: PROXY <-- TARGET: |7376312e342e302d3134302d6763396136633763|
+    2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |12002364756b20636f6d6d616e64206275696c742066726f6d2044756b74617065207265706f|
+    2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |81|
+    2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |00|
+    2016-02-17T13:59:51.293Z INF Proxy: PROXY --> CLIENT: {"reply":true,"args":[10499,"v1.4.0-140-gc9a6c7c","duk command built from Duktape repo",1]}
+    2016-02-17T14:00:06.105Z INF Proxy: PROXY <-- CLIENT: {"request":"Eval","args":["print('Hello world!'); 123;"]}
+    2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |01|
+    2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |9e|
+    2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |7b7072696e74282748656c6c6f20776f726c642127293b203132333b|
+    2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |00|
+    2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |04|
+    2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |82|
+    2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |6d48656c6c6f20776f726c64210a|
+    2016-02-17T14:00:06.168Z INF Proxy: PROXY <-- TARGET: |00|
+    2016-02-17T14:00:06.168Z INF Proxy: PROXY --> CLIENT: {"notify":"Print","command":2,"args":["Hello world!\n"]}
+    2016-02-17T14:00:06.171Z INF Proxy: PROXY <-- TARGET: |02|
+    2016-02-17T14:00:06.171Z INF Proxy: PROXY <-- TARGET: |80|
+    2016-02-17T14:00:06.173Z INF Proxy: PROXY <-- TARGET: |1a405ec00000000000|
+    2016-02-17T14:00:06.173Z INF Proxy: PROXY <-- TARGET: |00|
+    2016-02-17T14:00:06.174Z INF Proxy: PROXY --> CLIENT: {"reply":true,"args":[0,{"type":"number","data":"405ec00000000000"}]}
+    [...]
+
+Node.js JSON proxy
+------------------
+
+A Node.js-based JSON debug proxy is also provided by ``duk_debug.js``::
+
+    # Same prerequisites as for running the debug client
+    $ make runproxynodejs
+
+Start Duktape command line (or whatever your target is)::
+
+    $ cd <duktape checkout>/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":"_TargetConnected","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.

+ 32 - 0
src/third_party/duktape-1.5.2/debugger/duk_classnames.yaml

@@ -0,0 +1,32 @@
+# Must match C header.
+class_names:
+  - 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

+ 2473 - 0
src/third_party/duktape-1.5.2/debugger/duk_debug.js

@@ -0,0 +1,2473 @@
+/*
+ *  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;
+var CMD_THROW = 0x05;
+var CMD_DETACHING = 0x06;
+
+// 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.  So merge the YAML metadata.
+var debugCommandMeta = yaml.load('duk_debugcommands.yaml');
+var debugCommandNames = [];  // list of command names, merged client/target
+debugCommandMeta.target_commands.forEach(function (k, i) {
+    debugCommandNames[i] = k;
+});
+debugCommandMeta.client_commands.forEach(function (k, i) {  // override
+    debugCommandNames[i] = k;
+});
+var debugCommandNumbers = {};  // map from (merged) command name to number
+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 dukClassNameMeta = yaml.load('duk_classnames.yaml');
+var dukClassNames = dukClassNameMeta.class_names;
+
+// 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;  // truncate higher bits
+    }
+}
+
+/* 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 '<pointer ' + x.pointer + '>';
+        } else if (x.type === 'lightfunc') {
+            return '<lightfunc 0x' + x.flags.toString(16) + ' ' + x.pointer + '>';
+        } 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, level) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_GETVAR, varname, (typeof level === 'number' ? level : -1), DVAL_EOM ]).then(function (msg) {
+        return { found: msg[1] === 1, value: msg[2] };
+    });
+};
+
+Debugger.prototype.sendPutVarRequest = function (varname, varvalue, level) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_PUTVAR, varname, varvalue, (typeof level === 'number' ? level : -1), 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 (level) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_GETLOCALS, (typeof level === 'number' ? level : -1), 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, level) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_EVAL, evalInput, (typeof level === 'number' ? level : -1), 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;
+        var idxPreformattedInstructions;
+
+        //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('');
+        idxPreformattedInstructions = preformatted.length;
+        bcode.forEach(function (v) {
+            preformatted.push(v.str);
+        });
+        preformatted = preformatted.join('\n') + '\n';
+
+        ret = {
+            constants: consts,
+            functions: funcs,
+            bytecode: bcode,
+            preformatted: preformatted,
+            idxPreformattedInstructions: idxPreformattedInstructions
+        };
+
+        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 if (msg[1] === CMD_THROW) {
+            this.uiMessage({ type: 'throw', fatal: msg[2], message: (msg[2] ? 'UNCAUGHT: ' : 'THROW: ') + prettyUiStringUnquoted(msg[3], UI_MESSAGE_CLIPLEN), fileName: msg[4], lineNumber: msg[5] });
+        } else if (msg[1] === CMD_DETACHING) {
+            this.uiMessage({ type: 'detaching', reason: msg[2], message: 'DETACH: ' + (msg.length >= 5 ? prettyUiStringUnquoted(msg[3]) : 'detaching') });
+        } else {
+            // Ignore unknown notify messages
+            console.log('Unknown notify, ignoring: ' + 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, msg.level).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.
+
+        // XXX: move this to the web UI so that the UI can control what
+        // locals are listed (or perhaps show locals for all levels with
+        // an expandable tree view).
+        _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, msg.level)
+        .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, msg.level)
+        .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 PutVar to
+        // complete here; the requests will pipeline automatically and be
+        // executed in order.
+
+        // XXX: make the client do this?
+        _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 (cmdName, cmdNumber) {
+    var ret;
+    if (typeof cmdName === 'string') {
+        ret = debugCommandNumbers[cmdName];
+    } else if (typeof cmdName === 'number') {
+        ret = cmdName;
+    }
+    ret = ret || cmdNumber;
+    if (typeof ret !== 'number') {
+        throw Error('cannot figure out command number for "' + cmdName + '" (' + 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: '_TargetConnected',
+            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[0].type === 'eom') {
+            throw new Error('unexpected initial dvalue: ' + msg[0]);
+        } else if (msg[0].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();

+ 1497 - 0
src/third_party/duktape-1.5.2/debugger/duk_debug_meta.json

@@ -0,0 +1,1497 @@
+{
+    "opcodes": [
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "LDREG"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "name": "STREG"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "LDCONST"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_LDINT"
+            ], 
+            "name": "LDINT"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_LDINTX"
+            ], 
+            "name": "LDINTX"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_I"
+            ], 
+            "name": "MPUTOBJ"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RI", 
+                "C_I"
+            ], 
+            "name": "MPUTOBJI"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_I"
+            ], 
+            "name": "MPUTARR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RI", 
+                "C_I"
+            ], 
+            "name": "MPUTARRI"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_I"
+            ], 
+            "name": "NEW"
+        }, 
+        {
+            "args": [
+                "B_RI", 
+                "C_I"
+            ], 
+            "name": "NEWI"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RC", 
+                "C_RC"
+            ], 
+            "name": "REGEXP"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R"
+            ], 
+            "name": "CSREG"
+        }, 
+        {
+            "args": [
+                "A_RI", 
+                "B_R"
+            ], 
+            "name": "CSREGI"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "GETVAR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_C"
+            ], 
+            "name": "PUTVAR"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_RC", 
+                "C_RC"
+            ], 
+            "flags": [
+                {
+                    "mask": 64, 
+                    "name": "writable"
+                }, 
+                {
+                    "mask": 128, 
+                    "name": "enumerable"
+                }, 
+                {
+                    "mask": 256, 
+                    "name": "configurable"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "accessor"
+                }, 
+                {
+                    "mask": 1024, 
+                    "name": "undef_value"
+                }, 
+                {
+                    "mask": 2048, 
+                    "name": "func_decl"
+                }
+            ], 
+            "name": "DECLVAR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RC"
+            ], 
+            "name": "DELVAR"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RC"
+            ], 
+            "name": "CSVAR"
+        }, 
+        {
+            "args": [
+                "A_RI", 
+                "B_RC"
+            ], 
+            "name": "CSVARI"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_I"
+            ], 
+            "name": "CLOSURE"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RC", 
+                "C_RC"
+            ], 
+            "name": "GETPROP"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RC", 
+                "C_RC"
+            ], 
+            "name": "PUTPROP"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_RC"
+            ], 
+            "name": "DELPROP"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_R", 
+                "C_RC"
+            ], 
+            "name": "CSPROP"
+        }, 
+        {
+            "args": [
+                "A_RI", 
+                "B_R", 
+                "C_RC"
+            ], 
+            "name": "CSPROPI"
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "B_RC", 
+                "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_B", 
+                "B_RC"
+            ], 
+            "name": "IF"
+        }, 
+        {
+            "args": [
+                "ABC_JUMP"
+            ], 
+            "name": "JUMP"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_RC"
+            ], 
+            "flags": [
+                {
+                    "mask": 64, 
+                    "name": "have_retval"
+                }
+            ], 
+            "name": "RETURN"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_R", 
+                "C_I"
+            ], 
+            "flags": [
+                {
+                    "mask": 64, 
+                    "name": "tailcall"
+                }, 
+                {
+                    "mask": 128, 
+                    "name": "evalcall"
+                }
+            ], 
+            "name": "CALL"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "B_RI", 
+                "C_I"
+            ], 
+            "name": "CALLI"
+        }, 
+        {
+            "args": [
+                "A_H", 
+                "BC_R"
+            ], 
+            "flags": [
+                {
+                    "mask": 64, 
+                    "name": "have_catch"
+                }, 
+                {
+                    "mask": 128, 
+                    "name": "have_finally"
+                }, 
+                {
+                    "mask": 256, 
+                    "name": "catch_binding"
+                }, 
+                {
+                    "mask": 512, 
+                    "name": "with_binding"
+                }
+            ], 
+            "name": "TRYCATCH"
+        }, 
+        {
+            "name": "EXTRA", 
+            "extra": true
+        }, 
+        {
+            "args": [
+                "A_R", 
+                "BC_R"
+            ], 
+            "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_C"
+            ], 
+            "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", 
+                "B_RC", 
+                "C_RC"
+            ], 
+            "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"
+        }
+    ], 
+    "client_commands": [
+        "Reserved_0", 
+        "Status", 
+        "Print", 
+        "Alert", 
+        "Log", 
+        "Throw", 
+        "Detaching", 
+        "AppNotify"
+    ], 
+    "extra": [
+        {
+            "name": "NOP"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "INVALID"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDTHIS"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDUNDEF"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDNULL"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDTRUE"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LDFALSE"
+        }, 
+        {
+            "args": [
+                "B_R"
+            ], 
+            "name": "NEWOBJ"
+        }, 
+        {
+            "args": [
+                "B_R"
+            ], 
+            "name": "NEWARR"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "SETALEN"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "TYPEOF"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_RC"
+            ], 
+            "name": "TYPEOFID"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "INITENUM"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "NEXTENUM"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_R"
+            ], 
+            "name": "INITSET"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_RI"
+            ], 
+            "name": "INITSETI"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_RI"
+            ], 
+            "name": "INITGET"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_RI"
+            ], 
+            "name": "INITGETI"
+        }, 
+        {
+            "name": "ENDTRY"
+        }, 
+        {
+            "name": "ENDCATCH"
+        }, 
+        {
+            "name": "ENDFIN"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "THROW"
+        }, 
+        {
+            "name": "INVLHS"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "UNM"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "UNP"
+        }, 
+        {
+            "name": "DEBUGGER"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "BREAK"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "CONTINUE"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "BNOT"
+        }, 
+        {
+            "args": [
+                "BC_R"
+            ], 
+            "name": "LNOT"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_RC"
+            ], 
+            "name": "INSTOF"
+        }, 
+        {
+            "args": [
+                "B_R", 
+                "C_RC"
+            ], 
+            "name": "IN"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "LABEL"
+        }, 
+        {
+            "args": [
+                "BC_I"
+            ], 
+            "name": "ENDLABEL"
+        }, 
+        {
+            "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"
+        }
+    ], 
+    "target_commands": [
+        "Reserved_0", 
+        "Reserved_1", 
+        "Reserved_2", 
+        "Reserved_3", 
+        "Reserved_4", 
+        "Reserved_5", 
+        "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", 
+        "AppRequest", 
+        "GetHeapObjInfo", 
+        "GetObjPropDesc", 
+        "GetObjPropDescRange"
+    ], 
+    "error_codes": [
+        "Unknown", 
+        "UnsupportedCommand", 
+        "TooMany", 
+        "NotFound", 
+        "ApplicationError"
+    ], 
+    "class_names": [
+        "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"
+    ]
+}

+ 1029 - 0
src/third_party/duktape-1.5.2/debugger/duk_debug_proxy.js

@@ -0,0 +1,1029 @@
+/*
+ *  JSON debug proxy written in DukLuv
+ *
+ *  This single file JSON debug proxy implementation is an alternative to the
+ *  Node.js-based proxy in duk_debug.js.  DukLuv is a much smaller dependency
+ *  than Node.js so embedding DukLuv in a debug client is easier.
+ */
+
+'use strict';
+
+// XXX: Code assumes uv.write() will write fully.  This is not necessarily
+// true; should add support for partial writes (or at least failing when
+// a partial write occurs).
+
+var log = new Duktape.Logger('Proxy');  // default logger
+//log.l = 0;  // enable debug and trace logging
+
+/*
+ *  Config
+ */
+
+var serverHost = '0.0.0.0';
+var serverPort = 9093;
+var targetHost = '127.0.0.1';
+var targetPort = 9091;
+var singleConnection = false;
+var readableNumberValue = false;
+var lenientJsonParse = false;
+var jxParse = false;
+var metadataFile = null;
+var metadata = {};
+var TORTURE = false;  // for manual testing of binary/json parsing robustness
+
+/*
+ *  Detect missing 'var' declarations
+ */
+
+// Prevent new bindings on global object.  This detects missing 'var'
+// declarations, e.g. "x = 123;" in a function without declaring it.
+var global = new Function('return this;')();
+log.debug('Preventing extensions on global object');
+log.debug('Global is extensible:', Object.isExtensible(global));
+Object.preventExtensions(global);
+log.debug('Global is extensible:', Object.isExtensible(global));
+
+/*
+ *  Misc helpers
+ */
+
+function plainBufferCopy(typedarray) {
+    // This is still pretty awkward in Duktape 1.4.x.
+    // Argument may be a "slice" and we want a copy of the slice
+    // (not the full underlying buffer).
+
+    var u8 = new Uint8Array(typedarray.length);
+    u8.set(typedarray);  // make a copy, ensuring there's no slice offset
+    return Duktape.Buffer(u8);  // get underlying plain buffer
+}
+
+function isObject(x) {
+    // Note that typeof null === 'object'.
+    return (typeof x === 'object' && x !== null);
+}
+
+function readFully(filename, cb) {
+    uv.fs_open(metadataFile, 'r', 0, function (handle, err) {
+        var fileOff = 0;
+        var data = new Uint8Array(256);
+        var dataOff = 0;
+
+        if (err) {
+            return cb(null, err);
+        }
+        function readCb(buf, err) {
+            var res;
+            var newData;
+
+            log.debug('Read callback:', buf.length, err);
+            if (err) {
+                uv.fs_close(handle);
+                return cb(null, err);
+            }
+            if (buf.length == 0) {
+                uv.fs_close(handle);
+                res = new Uint8Array(dataOff);
+                res.set(data.subarray(0, dataOff));
+                res = Duktape.Buffer(res);  // plain buffer
+                log.debug('Read', res.length, 'bytes from', filename);
+                return cb(res, null);
+            }
+            while (data.length - dataOff < buf.length) {
+                log.debug('Resize file read buffer:', data.length, '->', data.length * 2);
+                newData = new Uint8Array(data.length * 2);
+                newData.set(data);
+                data = newData;
+            }
+            data.set(new Uint8Array(buf), dataOff);
+            dataOff += buf.length;
+            fileOff += buf.length;
+            uv.fs_read(handle, 4096, fileOff, readCb);
+        }
+        uv.fs_read(handle, 4096, fileOff, readCb);
+    });
+}
+
+/*
+ *  JSON proxy server
+ *
+ *  Accepts an incoming JSON proxy client and connects to a debug target,
+ *  tying the two connections together.  Supports both a single connection
+ *  and a persistent mode.
+ */
+
+function JsonProxyServer(host, port) {
+    this.name = 'JsonProxyServer';
+    this.handle = uv.new_tcp();
+    uv.tcp_bind(this.handle, host, port);
+    uv.listen(this.handle, 128, this.onConnection.bind(this));
+}
+
+JsonProxyServer.prototype.onConnection = function onConnection(err) {
+    if (err) {
+        log.error('JSON proxy onConnection error:', err);
+        return;
+    }
+    log.info('JSON proxy client connected');  // XXX: it'd be nice to log remote peer host:port
+
+    var jsonSock = new JsonConnHandler(this);
+    var targSock = new TargetConnHandler(this);
+    jsonSock.targetHandler = targSock;
+    targSock.jsonHandler = jsonSock;
+    uv.accept(this.handle, jsonSock.handle);
+
+    log.info('Connecting to debug target at', targetHost + ':' + targetPort);
+    jsonSock.writeJson({ notify: '_TargetConnecting', args: [ targetHost, targetPort ] });
+    uv.tcp_connect(targSock.handle, targetHost, targetPort, targSock.onConnect.bind(targSock));
+
+    if (singleConnection) {
+        log.info('Single connection mode, stop listening for more connections');
+        uv.shutdown(this.handle);
+        uv.read_stop(this.handle);  // unnecessary but just in case
+        uv.close(this.handle);
+        this.handle = null;
+    }
+};
+
+JsonProxyServer.prototype.onProxyClientDisconnected = function onProxyClientDisconnected() {
+    // When this is invoked the proxy connection and the target connection
+    // have both been closed.
+    if (singleConnection) {
+        log.info('Proxy connection finished (single connection mode: we should be exiting now)');
+    } else {
+        log.info('Proxy connection finished (persistent mode: wait for more connections)');
+    }
+};
+
+/*
+ *  JSON connection handler
+ */
+
+function JsonConnHandler(server) {
+    var i, n;
+
+    this.name = 'JsonConnHandler';
+    this.server = server;
+    this.handle = uv.new_tcp();
+    this.incoming = new Uint8Array(4096);
+    this.incomingOffset = 0;
+    this.targetHandler = null;
+
+    this.commandNumberLookup = {};
+    if (metadata && metadata.target_commands) {
+        for (i = 0, n = metadata.target_commands.length; i < n; i++) {
+            this.commandNumberLookup[metadata.target_commands[i]] = i;
+        }
+    }
+}
+
+JsonConnHandler.prototype.finish = function finish(msg) {
+    var args;
+
+    if (!this.handle) {
+        log.info('JsonConnHandler already disconnected, ignore finish()');
+        return;
+    }
+    log.info('JsonConnHandler finished:', msg);
+    try {
+        args = msg ? [ msg ] : void 0;
+        this.writeJson({ notify: '_Disconnecting', args: args });
+    } catch (e) {
+        log.info('Failed to write _Disconnecting notify, ignoring:', e);
+    }
+    uv.shutdown(this.handle);
+    uv.read_stop(this.handle);
+    uv.close(this.handle);
+    this.handle = null;
+
+    this.targetHandler.finish(msg);  // disconnect target too (if not already disconnected)
+
+    this.server.onProxyClientDisconnected();
+};
+
+JsonConnHandler.prototype.onRead = function onRead(err, data) {
+    var newIncoming;
+    var msg;
+    var errmsg;
+    var tmpBuf;
+
+    log.trace('Received data from JSON socket, err:', err, 'data length:', data ? data.length : 'null');
+
+    if (err) {
+        errmsg = 'Error reading data from JSON debug client: ' + err;
+        this.finish(errmsg);
+        return;
+    }
+    if (data) {
+        // Feed the data one byte at a time when torture testing.
+        if (TORTURE && data.length > 1) {
+            for (var i = 0; i < data.length; i++) {
+                tmpBuf = Duktape.Buffer(1);
+                tmpBuf[0] = data[i];
+                this.onRead(null, tmpBuf);
+            }
+            return;
+        }
+
+        // Receive data into 'incoming', resizing as necessary.
+        while (data.length > this.incoming.length - this.incomingOffset) {
+            newIncoming = new Uint8Array(this.incoming.length * 1.3 + 16);
+            newIncoming.set(this.incoming);
+            this.incoming = newIncoming;
+            log.debug('Resize incoming JSON buffer to ' + this.incoming.length);
+        }
+        this.incoming.set(new Uint8Array(data), this.incomingOffset);
+        this.incomingOffset += data.length;
+
+        // Trial parse JSON message(s).
+        while (true) {
+            msg = this.trialParseJsonMessage();
+            if (!msg) {
+                break;
+            }
+            try {
+                this.dispatchJsonMessage(msg);
+            } catch (e) {
+                errmsg = 'JSON message dispatch failed: ' + e;
+                this.writeJson({ notify: '_Error', args: [ errmsg ] });
+                if (lenientJsonParse) {
+                    log.warn('JSON message dispatch failed (lenient mode, ignoring):', e);
+                } else {
+                    log.warn('JSON message dispatch failed (dropping connection):', e);
+                    this.finish(errmsg);
+                }
+            }
+        }
+    } else {
+        this.finish('JSON proxy client disconnected');
+    }
+};
+
+JsonConnHandler.prototype.writeJson = function writeJson(msg) {
+    log.info('PROXY --> CLIENT:', JSON.stringify(msg));
+    if (this.handle) {
+        uv.write(this.handle, JSON.stringify(msg) + '\n');
+    }
+};
+
+JsonConnHandler.prototype.handleDebugMessage = function handleDebugMessage(dvalues) {
+    var msg = {};
+    var idx = 0;
+    var cmd;
+
+    if (dvalues.length <= 0) {
+        throw new Error('invalid dvalues list: length <= 0');
+    }
+    var x = dvalues[idx++];
+    if (!isObject(x)) {
+        throw new Error('invalid initial dvalue: ' + Duktape.enc('jx', dvalues));
+    }
+    if (x.type === 'req') {
+        cmd = dvalues[idx++];
+        if (typeof cmd !== 'number') {
+            throw new Error('invalid command: ' + Duktape.enc('jx', cmd));
+        }
+        msg.request = this.determineCommandName(cmd) || true;
+        msg.command = cmd;
+    } else if (x.type === 'rep') {
+        msg.reply = true;
+    } else if (x.type === 'err') {
+        msg.error = true;
+    } else if (x.type === 'nfy') {
+        cmd = dvalues[idx++];
+        if (typeof cmd !== 'number') {
+            throw new Error('invalid command: ' + Duktape.enc('jx', cmd));
+        }
+        msg.notify = this.determineCommandName(cmd) || true;
+        msg.command = cmd;
+    } else {
+        throw new Error('invalid initial dvalue: ' + Duktape.enc('jx', dvalues));
+    }
+
+    for (; idx < dvalues.length - 1; idx++) {
+        if (!msg.args) {
+            msg.args = [];
+        }
+        msg.args.push(dvalues[idx]);
+    }
+
+    if (!isObject(dvalues[idx]) || dvalues[idx].type !== 'eom') {
+        throw new Error('invalid final dvalue: ' + Duktape.enc('jx', dvalues));
+    }
+
+    this.writeJson(msg);
+};
+
+JsonConnHandler.prototype.determineCommandName = function determineCommandName(cmd) {
+    if (!(metadata && metadata.client_commands)) {
+        return;
+    }
+    return metadata.client_commands[cmd];
+};
+
+JsonConnHandler.prototype.trialParseJsonMessage = function trialParseJsonMessage() {
+    var buf = this.incoming;
+    var avail = this.incomingOffset;
+    var i;
+    var msg, str, errmsg;
+
+    for (i = 0; i < avail; i++) {
+        if (buf[i] == 0x0a) {
+            str = String(plainBufferCopy(buf.subarray(0, i)));
+            try {
+                if (jxParse) {
+                    msg = Duktape.dec('jx', str);
+                } else {
+                    msg = JSON.parse(str);
+                }
+            } catch (e) {
+                // In lenient mode if JSON parse fails just send back an _Error
+                // and ignore the line (useful for initial development).
+                //
+                // In non-lenient mode drop the connection here; if the failed line
+                // was a request the client is expecting a reply/error message back
+                // (otherwise it may go out of sync) but we can't send a synthetic
+                // one (as we can't parse the request).
+                errmsg = 'JSON parse failed for: ' + JSON.stringify(str) + ': ' + e;
+                this.writeJson({ notify: '_Error', args: [ errmsg ] });
+                if (lenientJsonParse) {
+                    log.warn('JSON parse failed (lenient mode, ignoring):', e);
+                } else {
+                    log.warn('JSON parse failed (dropping connection):', e);
+                    this.finish(errmsg);
+                }
+            }
+
+            this.incoming.set(this.incoming.subarray(i + 1));
+            this.incomingOffset -= i + 1;
+            return msg;
+        }
+    }
+};
+
+JsonConnHandler.prototype.dispatchJsonMessage = function dispatchJsonMessage(msg) {
+    var cmd;
+    var dvalues = [];
+    var i, n;
+
+    log.info('PROXY <-- CLIENT:', JSON.stringify(msg));
+
+    // Parse message type, determine initial marker for binary message.
+    if (msg.request) {
+        cmd = this.determineCommandNumber(msg.request, msg.command);
+        dvalues.push(new Uint8Array([ 0x01 ]));
+        dvalues.push(this.encodeJsonDvalue(cmd));
+    } else if (msg.reply) {
+        dvalues.push(new Uint8Array([ 0x02 ]));
+    } else if (msg.notify) {
+        cmd = this.determineCommandNumber(msg.notify, msg.command);
+        dvalues.push(new Uint8Array([ 0x04 ]));
+        dvalues.push(this.encodeJsonDvalue(cmd));
+    } else if (msg.error) {
+        dvalues.push(new Uint8Array([ 0x03 ]));
+    } else {
+        throw new Error('invalid input JSON message: ' + JSON.stringify(msg));
+    }
+
+    // Encode arguments into dvalues.
+    for (i = 0, n = (msg.args ? msg.args.length : 0); i < n; i++) {
+        dvalues.push(this.encodeJsonDvalue(msg.args[i]));
+    }
+
+    // Add an EOM, and write out the dvalues to the debug target.
+    dvalues.push(new Uint8Array([ 0x00 ]));
+    for (i = 0, n = dvalues.length; i < n; i++) {
+        this.targetHandler.writeBinary(dvalues[i]);
+    }
+};
+
+JsonConnHandler.prototype.determineCommandNumber = function determineCommandNumber(name, val) {
+    var res;
+
+    if (typeof name === 'string') {
+        res = this.commandNumberLookup[name];
+        if (!res) {
+            log.info('Unknown command name: ' + name + ', command number: ' + val);
+        }
+    } else if (typeof name === 'number') {
+        res = name;
+    } else if (name !== true) {
+        throw new Error('invalid command name (must be string, number, or "true"): ' + name);
+    }
+    if (typeof res === 'undefined' && typeof val === 'undefined') {
+        throw new Error('cannot determine command number from name: ' + name);
+    }
+    if (typeof val !== 'number' && typeof val !== 'undefined') {
+        throw new Error('invalid command number: ' + val);
+    }
+    res = res || val;
+    return res;
+};
+
+JsonConnHandler.prototype.writeDebugStringToBuffer = function writeDebugStringToBuffer(v, buf, off) {
+    var i, n;
+
+    for (i = 0, n = v.length; i < n; i++) {
+        buf[off + i] = v.charCodeAt(i) & 0xff;  // truncate higher bits
+    }
+};
+
+JsonConnHandler.prototype.encodeJsonDvalue = function encodeJsonDvalue(v) {
+    var buf, dec, len, dv;
+
+    if (isObject(v)) {
+        if (v.type === 'eom') {
+            return new Uint8Array([ 0x00 ]);
+        } else if (v.type === 'req') {
+            return new Uint8Array([ 0x01 ]);
+        } else if (v.type === 'rep') {
+            return new Uint8Array([ 0x02 ]);
+        } else if (v.type === 'err') {
+            return new Uint8Array([ 0x03 ]);
+        } else if (v.type === 'nfy') {
+            return new Uint8Array([ 0x04 ]);
+        } else if (v.type === 'unused') {
+            return new Uint8Array([ 0x15 ]);
+        } else if (v.type === 'undefined') {
+            return new Uint8Array([ 0x16 ]);
+        } else if (v.type === 'number') {
+            dec = Duktape.dec('hex', v.data);
+            len = dec.length;
+            if (len !== 8) {
+                throw new TypeError('value cannot be converted to dvalue: ' + JSON.stringify(v));
+            }
+            buf = new Uint8Array(1 + len);
+            buf[0] = 0x1a;
+            buf.set(new Uint8Array(dec), 1);
+            return buf;
+        } else if (v.type === 'buffer') {
+            dec = Duktape.dec('hex', v.data);
+            len = dec.length;
+            if (len <= 0xffff) {
+                buf = new Uint8Array(3 + len);
+                buf[0] = 0x14;
+                buf[1] = (len >> 8) & 0xff;
+                buf[2] = (len >> 0) & 0xff;
+                buf.set(new Uint8Arrau(dec), 3);
+                return buf;
+            } else {
+                buf = new Uint8Array(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;
+                buf.set(new Uint8Array(dec), 5);
+                return buf;
+            }
+        } else if (v.type === 'object') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(3 + len);
+            buf[0] = 0x1b;
+            buf[1] = v.class;
+            buf[2] = len;
+            buf.set(new Uint8Array(dec), 3);
+            return buf;
+        } else if (v.type === 'pointer') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(2 + len);
+            buf[0] = 0x1c;
+            buf[1] = len;
+            buf.set(new Uint8Array(dec), 2);
+            return buf;
+        } else if (v.type === 'lightfunc') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(4 + len);
+            buf[0] = 0x1d;
+            buf[1] = (v.flags >> 8) & 0xff;
+            buf[2] = v.flags & 0xff;
+            buf[3] = len;
+            buf.set(new Uint8Array(dec), 4);
+            return buf;
+        } else if (v.type === 'heapptr') {
+            dec = Duktape.dec('hex', v.pointer);
+            len = dec.length;
+            buf = new Uint8Array(2 + len);
+            buf[0] = 0x1e;
+            buf[1] = len;
+            buf.set(new Uint8Array(dec), 2);
+            return buf;
+        }
+    } else if (v === null) {
+        return new Uint8Array([ 0x17 ]);
+    } else if (typeof v === 'boolean') {
+        return new Uint8Array([ 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 Uint8Array([ 0x80 + v ]);
+            } else if (v >= 0x0000 && v <= 0x3fff) {
+                return new Uint8Array([ 0xc0 + (v >> 8), v & 0xff ]);
+            } else if (v >= -0x80000000 && v <= 0x7fffffff) {
+                return new Uint8Array([ 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 Uint8Array(1 + 8);
+            buf[0] = 0x1a;
+            new DataView(buf).setFloat64(1, v, false);
+            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 Uint8Array(1 + v.length);
+            buf[0] = 0x60 + v.length;
+            this.writeDebugStringToBuffer(v, buf, 1);
+            return buf;
+        } else if (v.length <= 0xffff) {
+            buf = new Uint8Array(3 + v.length);
+            buf[0] = 0x12;
+            buf[1] = (v.length >> 8) & 0xff;
+            buf[2] = (v.length >> 0) & 0xff;
+            this.writeDebugStringToBuffer(v, buf, 3);
+            return buf;
+        } else {
+            buf = new Uint8Array(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;
+            this.writeDebugStringToBuffer(v, buf, 5);
+            return buf;
+        }
+    }
+
+    throw new TypeError('value cannot be converted to dvalue: ' + JSON.stringify(v));
+};
+
+/*
+ *  Target binary connection handler
+ */
+
+function TargetConnHandler(server) {
+    this.name = 'TargetConnHandler';
+    this.server = server;
+    this.handle = uv.new_tcp();
+    this.jsonHandler = null;
+    this.incoming = new Uint8Array(4096);
+    this.incomingOffset = 0;
+    this.dvalues = [];
+}
+
+TargetConnHandler.prototype.finish = function finish(msg) {
+    if (!this.handle) {
+        log.info('TargetConnHandler already disconnected, ignore finish()');
+        return;
+    }
+    log.info('TargetConnHandler finished:', msg);
+
+    this.jsonHandler.writeJson({ notify: '_TargetDisconnected' });
+
+    // XXX: write a notify to target?
+
+    uv.shutdown(this.handle);
+    uv.read_stop(this.handle);
+    uv.close(this.handle);
+    this.handle = null;
+
+    this.jsonHandler.finish(msg);  // disconnect JSON client too (if not already disconnected)
+};
+
+TargetConnHandler.prototype.onConnect = function onConnect(err) {
+    var errmsg;
+
+    if (err) {
+        errmsg = 'Failed to connect to target: ' + err;
+        log.warn(errmsg);
+        this.jsonHandler.writeJson({ notify: '_Error', args: [ String(err) ] });
+        this.finish(errmsg);
+        return;
+    }
+
+    // Once we're connected to the target, start read both binary and JSON
+    // input.  We don't want to read JSON input before this so that we can
+    // always translate incoming messages to dvalues and write them out
+    // without queueing.  Any pending JSON messages will be queued by the
+    // OS instead.
+
+    log.info('Connected to debug target at', targetHost + ':' + targetPort);
+    uv.read_start(this.jsonHandler.handle, this.jsonHandler.onRead.bind(this.jsonHandler));
+    uv.read_start(this.handle, this.onRead.bind(this));
+};
+
+TargetConnHandler.prototype.writeBinary = function writeBinary(buf) {
+    var plain = plainBufferCopy(buf);
+    log.info('PROXY --> TARGET:', Duktape.enc('jx', plain));
+    if (this.handle) {
+        uv.write(this.handle, plain);
+    }
+};
+
+TargetConnHandler.prototype.onRead = function onRead(err, data) {
+    var res;
+    var errmsg;
+    var tmpBuf;
+    var newIncoming;
+
+    log.trace('Received data from target socket, err:', err, 'data length:', data ? data.length : 'null');
+
+    if (err) {
+        errmsg = 'Error reading data from debug target: ' + err;
+        this.finish(errmsg);
+        return;
+    }
+
+    if (data) {
+        // Feed the data one byte at a time when torture testing.
+        if (TORTURE && data.length > 1) {
+            for (var i = 0; i < data.length; i++) {
+                tmpBuf = Duktape.Buffer(1);
+                tmpBuf[0] = data[i];
+                this.onRead(null, tmpBuf);
+            }
+            return;
+        }
+
+        // Receive data into 'incoming', resizing as necessary.
+        while (data.length > this.incoming.length - this.incomingOffset) {
+            newIncoming = new Uint8Array(this.incoming.length * 1.3 + 16);
+            newIncoming.set(this.incoming);
+            this.incoming = newIncoming;
+            log.debug('Resize incoming binary buffer to ' + this.incoming.length);
+        }
+        this.incoming.set(new Uint8Array(data), this.incomingOffset);
+        this.incomingOffset += data.length;
+
+        // Trial parse handshake unless done.
+        if (!this.handshake) {
+            this.trialParseHandshake();
+        }
+
+        // Trial parse dvalue(s) and debug messages.
+        if (this.handshake) {
+            for (;;) {
+                res = this.trialParseDvalue();
+                if (!res) {
+                    break;
+                }
+                log.trace('Got dvalue:', Duktape.enc('jx', res.dvalue));
+                this.dvalues.push(res.dvalue);
+                if (isObject(res.dvalue) && res.dvalue.type === 'eom') {
+                    try {
+                        this.jsonHandler.handleDebugMessage(this.dvalues);
+                        this.dvalues = [];
+                    } catch (e) {
+                        errmsg = 'JSON message handling failed: ' + e;
+                        this.jsonHandler.writeJson({ notify: '_Error', args: [ errmsg ] });
+                        if (lenientJsonParse) {
+                            log.warn('JSON message handling failed (lenient mode, ignoring):', e);
+                        } else {
+                            log.warn('JSON message handling failed (dropping connection):', e);
+                            this.finish(errmsg);
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        log.info('Target disconnected');
+        this.finish('Target disconnected');
+    }
+};
+
+TargetConnHandler.prototype.trialParseHandshake = function trialParseHandshake() {
+    var buf = this.incoming;
+    var avail = this.incomingOffset;
+    var i;
+    var msg;
+    var m;
+    var protocolVersion;
+
+    for (i = 0; i < avail; i++) {
+        if (buf[i] == 0x0a) {
+            msg = String(plainBufferCopy(buf.subarray(0, i)));
+            this.incoming.set(this.incoming.subarray(i + 1));
+            this.incomingOffset -= i + 1;
+
+            // Generic handshake format: only relies on initial version field.
+            m = /^(\d+) (.*)$/.exec(msg) || {};
+            protocolVersion = +m[1];
+            this.handshake = {
+                line: msg,
+                protocolVersion: protocolVersion,
+                text: m[2]
+            };
+
+            // More detailed v1 handshake line.
+            if (protocolVersion === 1) {
+                m = /^(\d+) (\d+) (.*?) (.*?) (.*)$/.exec(msg) || {};
+                this.handshake.dukVersion = m[1];
+                this.handshake.dukGitDescribe = m[2];
+                this.handshake.targetString = m[3];
+            }
+
+            this.jsonHandler.writeJson({ notify: '_TargetConnected', args: [ msg ] });
+
+            log.info('Target handshake: ' + JSON.stringify(this.handshake));
+            return;
+        }
+    }
+};
+
+TargetConnHandler.prototype.bufferToDebugString = function bufferToDebugString(buf) {
+    return String.fromCharCode.apply(null, buf);
+};
+
+TargetConnHandler.prototype.trialParseDvalue = function trialParseDvalue() {
+    var _this = this;
+    var buf = this.incoming;
+    var avail = this.incomingOffset;
+    var v;
+    var gotValue = false;  // explicit flag for e.g. v === undefined
+    var dv = new DataView(buf);
+    var tmp;
+    var x;
+    var len;
+
+    function consume(n) {
+        log.info('PROXY <-- TARGET:', Duktape.enc('jx', _this.incoming.subarray(0, n)));
+        _this.incoming.set(_this.incoming.subarray(n));
+        _this.incomingOffset -= n;
+    }
+
+    x = buf[0];
+    if (avail <= 0) {
+        ;
+    } else if (x >= 0xc0) {
+        // 0xc0...0xff: integers 0-16383
+        if (avail >= 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 (avail >= 1 + len) {
+            v = new Uint8Array(len);
+            v.set(buf.subarray(1, 1 + len));
+            v = this.bufferToDebugString(v);
+            consume(1 + len);
+        }
+    } else {
+        switch (x) {
+        case 0x00: consume(1); v = { type: 'eom' }; break;
+        case 0x01: consume(1); v = { type: 'req' }; break;
+        case 0x02: consume(1); v = { type: 'rep' }; break;
+        case 0x03: consume(1); v = { type: 'err' }; break;
+        case 0x04: consume(1); v = { type: 'nfy' }; break;
+        case 0x10:  // 4-byte signed integer
+            if (avail >= 5) {
+                v = dv.getInt32(1, false);
+                consume(5);
+            }
+            break;
+        case 0x11:  // 4-byte string
+            if (avail >= 5) {
+                len = dv.getUint32(1, false);
+                if (avail >= 5 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(5, 5 + len));
+                    v = this.bufferToDebugString(v);
+                    consume(5 + len);
+                }
+            }
+            break;
+        case 0x12:  // 2-byte string
+            if (avail >= 3) {
+                len = dv.getUint16(1, false);
+                if (avail >= 3 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(3, 3 + len));
+                    v = this.bufferToDebugString(v);
+                    consume(3 + len);
+                }
+            }
+            break;
+        case 0x13:  // 4-byte buffer
+            if (avail >= 5) {
+                len = dv.getUint32(1, false);
+                if (avail >= 5 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(5, 5 + len));
+                    v = { type: 'buffer', data: Duktape.enc('hex', Duktape.Buffer(v)) };
+                    consume(5 + len);
+                }
+            }
+            break;
+        case 0x14:  // 2-byte buffer
+            if (avail >= 3) {
+                len = dv.getUint16(1, false);
+                if (avail >= 3 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(3, 3 + len));
+                    v = { type: 'buffer', data: Duktape.enc('hex', Duktape.Buffer(v)) };
+                    consume(3 + len);
+                }
+            }
+            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 (avail >= 9) {
+                tmp = new Uint8Array(8);
+                tmp.set(buf.subarray(1, 9));
+                v = { type: 'number', data: Duktape.enc('hex', Duktape.Buffer(tmp)) };
+                if (readableNumberValue) {
+                    // The value key should not be used programmatically,
+                    // it is just there to make the dumps more readable.
+                    v.value = new DataView(tmp.buffer).getFloat64(0, false);
+                }
+                consume(9);
+            }
+            break;
+        case 0x1b:  // object
+            if (avail >= 3) {
+                len = buf[2];
+                if (avail >= 3 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(3, 3 + len));
+                    v = { type: 'object', 'class': buf[1], pointer: Duktape.enc('hex', Duktape.Buffer(v)) };
+                    consume(3 + len);
+                }
+            }
+            break;
+        case 0x1c:  // pointer
+            if (avail >= 2) {
+                len = buf[1];
+                if (avail >= 2 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(2, 2 + len));
+                    v = { type: 'pointer', pointer: Duktape.enc('hex', Duktape.Buffer(v)) };
+                    consume(2 + len);
+                }
+            }
+            break;
+        case 0x1d:  // lightfunc
+            if (avail >= 4) {
+                len = buf[3];
+                if (avail >= 4 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(4, 4 + len));
+                    v = { type: 'lightfunc', flags: dv.getUint16(1, false), pointer: Duktape.enc('hex', Duktape.Buffer(v)) };
+                    consume(4 + len);
+                }
+            }
+            break;
+        case 0x1e:  // heapptr
+            if (avail >= 2) {
+                len = buf[1];
+                if (avail >= 2 + len) {
+                    v = new Uint8Array(len);
+                    v.set(buf.subarray(2, 2 + len));
+                    v = { type: 'heapptr', pointer: Duktape.enc('hex', Duktape.Buffer(v)) };
+                    consume(2 + len);
+                }
+            }
+            break;
+        default:
+            throw new Error('failed parse initial byte: ' + buf[0]);
+        }
+    }
+
+    if (typeof v !== 'undefined' || gotValue) {
+        return { dvalue: v };
+    }
+};
+
+/*
+ *  Main
+ */
+
+function main() {
+    var argv = typeof uv.argv === 'function' ? uv.argv() : [];
+    var i;
+    for (i = 2; i < argv.length; i++) {  // skip dukluv and script name
+        if (argv[i] == '--help') {
+            print('Usage: dukluv ' + argv[1] + ' [option]+');
+            print('');
+            print('    --server-host HOST    JSON proxy server listen address');
+            print('    --server-port PORT    JSON proxy server listen port');
+            print('    --target-host HOST    Debug target address');
+            print('    --target-port PORT    Debug target port');
+            print('    --metadata FILE       Proxy metadata file (usually named duk_debug_meta.json)');
+            print('    --log-level LEVEL     Set log level, default is 2; 0=trace, 1=debug, 2=info, 3=warn, etc');
+            print('    --single              Run a single proxy connection and exit (default: persist for multiple connections)');
+            print('    --readable-numbers    Add a non-programmatic "value" key for IEEE doubles help readability');
+            print('    --lenient             Ignore (with warning) invalid JSON without dropping connection');
+            print('    --jx-parse            Parse JSON proxy input with JX, useful when testing manually');
+            print('');
+            return;  // don't register any sockets/timers etc to exit
+        } else if (argv[i] == '--single') {
+            singleConnection = true;
+            continue;
+        } else if (argv[i] == '--readable-numbers') {
+            readableNumberValue = true;
+            continue;
+        } else if (argv[i] == '--lenient') {
+            lenientJsonParse = true;
+            continue;
+        } else if (argv[i] == '--jx-parse') {
+            jxParse = true;
+            continue;
+        }
+        if (i >= argv.length - 1) {
+            throw new Error('missing option value for ' + argv[i]);
+        }
+        if (argv[i] == '--server-host') {
+            serverHost = argv[i + 1];
+            i++;
+        } else if (argv[i] == '--server-port') {
+            serverPort = Math.floor(+argv[i + 1]);
+            i++;
+        } else if (argv[i] == '--target-host') {
+            targetHost = argv[i + 1];
+            i++;
+        } else if (argv[i] == '--target-port') {
+            targetPort = Math.floor(+argv[i + 1]);
+            i++;
+        } else if (argv[i] == '--metadata') {
+            metadataFile = argv[i + 1];
+            i++;
+        } else if (argv[i] == '--log-level') {
+            log.l = Math.floor(+argv[i + 1]);
+            i++;
+        } else {
+            throw new Error('invalid option ' + argv[i]);
+        }
+    }
+
+    function runServer() {
+        var serverSocket = new JsonProxyServer(serverHost, serverPort);
+        var connMode = singleConnection ? 'single connection mode' : 'persistent connection mode';
+        log.info('Listening for incoming JSON debug connection on ' + serverHost + ':' + serverPort +
+                 ', target is ' + targetHost + ':' + targetPort + ', ' + connMode);
+    }
+
+    if (metadataFile) {
+        log.info('Read proxy metadata from', metadataFile);
+        readFully(metadataFile, function (data, err) {
+            if (err) {
+                log.error('Failed to load metadata:', err);
+                throw err;
+            }
+            try {
+                metadata = JSON.parse(String(data));
+            } catch (e) {
+                log.error('Failed to parse JSON metadata from ' + metadataFile + ': ' + e);
+                throw e;
+            }
+            runServer();
+        });
+    } else {
+        runServer();
+    }
+}
+
+main();

+ 52 - 0
src/third_party/duktape-1.5.2/debugger/duk_debugcommands.yaml

@@ -0,0 +1,52 @@
+# Debug request/notify command names provided by the debug client.
+# These are concretely notify names now.
+client_commands:
+  - Reserved_0
+  - Status
+  - Print
+  - Alert
+  - Log
+  - Throw
+  - Detaching
+  - AppNotify
+
+# Debug request/notify command names provided by the debug target (Duktape).
+target_commands:
+  - Reserved_0
+  - Reserved_1
+  - Reserved_2
+  - Reserved_3
+  - Reserved_4
+  - Reserved_5
+  - 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
+  - AppRequest
+  - GetHeapObjInfo
+  - GetObjPropDesc
+  - GetObjPropDescRange

+ 6 - 0
src/third_party/duktape-1.5.2/debugger/duk_debugerrors.yaml

@@ -0,0 +1,6 @@
+error_codes:
+  - Unknown
+  - UnsupportedCommand
+  - TooMany
+  - NotFound
+  - ApplicationError

+ 658 - 0
src/third_party/duktape-1.5.2/debugger/duk_opcodes.yaml

@@ -0,0 +1,658 @@
+# 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: 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

+ 32 - 0
src/third_party/duktape-1.5.2/debugger/merge_debug_meta.py

@@ -0,0 +1,32 @@
+#!/usr/bin/env python2
+#
+#  Merge debugger YAML metadata files and output a merged JSON metadata file.
+#
+
+import os, sys, json, yaml
+import optparse
+
+if __name__ == '__main__':
+	parser = optparse.OptionParser()
+	parser.add_option('--output', dest='output', default=None, help='output JSON filename')
+	parser.add_option('--class-names', dest='class_names', help='YAML metadata for class names')
+	parser.add_option('--debug-commands', dest='debug_commands', help='YAML metadata for debug commands')
+	parser.add_option('--debug-errors', dest='debug_errors', help='YAML metadata for debug protocol error codes')
+	parser.add_option('--opcodes', dest='opcodes', help='YAML metadata for opcodes')
+	(opts, args) = parser.parse_args()
+
+	res = {}
+	def merge(fn):
+		with open(fn, 'rb') as f:
+			doc = yaml.load(f)
+		for k in doc.keys():
+			res[k] = doc[k]
+
+	merge(opts.class_names)
+	merge(opts.debug_commands)
+	merge(opts.debug_errors)
+	merge(opts.opcodes)
+
+	with open(opts.output, 'wb') as f:
+		f.write(json.dumps(res, indent=4) + '\n')
+	print('Wrote merged debugger metadata to ' + str(opts.output))

+ 27 - 0
src/third_party/duktape-1.5.2/debugger/package.json

@@ -0,0 +1,27 @@
+{
+  "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"
+}

+ 96 - 0
src/third_party/duktape-1.5.2/debugger/static/index.html

@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<link rel="stylesheet" href="reset.css" type="text/css" />
+<link rel="stylesheet" href="jquery-ui.min.css" type="text/css" />
+<link rel="stylesheet" href="style.css" type="text/css" />
+<title>Duktape debugger</title>
+</head>
+<body>
+
+<div id="part-header">
+((o) Duktape debugger
+</div>  <!-- #part-header -->
+
+<div id="part-middle">
+
+<div id="left-area">
+<button id="stepinto-button">Step&#x00a0;into</button>
+<button id="stepover-button">Step&#x00a0;over</button>
+<button id="stepout-button">Step&#x00a0;out</button>
+<button id="resume-button">Resume</button>
+<button id="pause-button">Pause</button>
+<br />
+<br />
+<br />
+<br />
+<button id="attach-button">Attach</button>
+<button id="detach-button">Detach</button>
+<button id="about-button">About</button>
+<button id="heap-dump-download-button"><a id="heap-dump-download" href="/heapDump.json" target="_blank">Dump&#x00a0;heap</a></button>
+<button id="show-bytecode-button">Show bytecode</button>
+</div>  <!-- #left-area -->
+
+<div id="center-area">
+<pre id="source-pre" class="sourcecode"><code id="source-code" class="sourcecode">
+// No source loaded
+</code></pre>
+<div>
+<select id="source-select"></select><br />
+<!-- <span id="source-filename">?</span> -->
+</div>
+<div id="exec-status">
+<div id="exec-state"><span id="current-state">?</span></div>
+<div id="exec-other"><span id="current-fileline">?</span><br /><span id="current-funcpc">?</span></div>
+</div>  <!-- #exec-status -->
+<div id="output">
+<div style="color: #dddddd">(output from script, print() and alert() calls)</div>
+</div>
+</div>  <!-- #center-area -->
+
+<div id="right-area">
+<div id="callstack">
+<div style="color: #dddddd">(callstack)</div>
+</div>
+<div id="locals">
+<div style="color: #dddddd">(locals)</div>
+</div>
+<div id="breakpoints">
+<div style="color: #dddddd">(breakpoints)</div>
+</div>
+<div id="eval">
+<input id="eval-input" value="print('hello world'); 1+2" /><button id="eval-button">Eval</button><input id="eval-watch" type="checkbox" />&#xa0;watch (eval on pause)
+<div id="eval-output"></div>
+<button id="putvar-button">PutVar</button><button id="getvar-button">GetVar</button><input id="varname-input" value="varname" /><input id="varvalue-input" value="varvalue" />
+<div id="var-output"></div>
+</div>
+</div>  <!-- #right-area -->
+
+</div>  <!-- #part-middle -->
+
+<div id="part-footer">
+<div>DUK_VERSION: <span id="duk-version">?</span>, DUK_GIT_DESCRIBE: <span id="duk-git-describe">?</span>, Target info: <span id="target-info">?</span>, Endianness: <span id="endianness">?</span><br />
+Debug protocol stats:
+recv <span id="debug-rx-bytes">?</span> (<span id="debug-rx-kbrate">?</span> kB/s), <span id="debug-rx-dvalues">?</span> dvalues, <span id="debug-rx-messages">?</span> messages;
+send <span id="debug-tx-bytes">?</span> (<span id="debug-tx-kbrate">?</span> kB/s), <span id="debug-tx-dvalues">?</span> dvalues, <span id="debug-tx-messages">?</span> messages
+</div>
+</div>  <!-- #part-footer -->
+
+<div id="about-dialog" title="About Duktape debugger">
+<p>Duktape debugger is a web UI for debugging Ecmascript on a target device.</p>
+<p>This web UI talks to a NodeJS debug server using <a href="http://socket.io/" target="_blank">socket.io</a>.
+The debug server talks to the target device using the Duktape debug protocol
+(see <a href="https://github.com/svaarala/duktape/blob/master/doc/debugger.rst" target="_blank">debugger.rst</a>).</p>
+</div>  <!-- #about-dialog -->
+
+<div id="bytecode-dialog" title="Bytecode for current function">
+<pre id="bytecode-preformatted"></pre>
+</div>
+
+<script src="jquery-1.11.1.min.js" type="text/javascript"></script>
+<script src="jquery-ui.min.js" type="text/javascript"></script>
+<script src="socket.io-1.2.0.js" type="text/javascript"></script>
+<script src="webui.js" type="text/javascript"></script>
+</body>
+</html>

+ 516 - 0
src/third_party/duktape-1.5.2/debugger/static/style.css

@@ -0,0 +1,516 @@
+// 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: 10pt monospace;
+	color: #000000;
+}
+#bytecode-dialog div.highlight {
+	background: #888888;
+	color: #ffffff;
+}
+
+#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;
+}

+ 785 - 0
src/third_party/duktape-1.5.2/debugger/static/webui.js

@@ -0,0 +1,785 @@
+/*
+ *  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
+var bytecodeDialogOpen = false;     // bytecode dialog active
+var bytecodeIdxHighlight = null;    // index of currently highlighted line (or null)
+var bytecodeIdxInstr = 0;           // index to first line of bytecode instructions
+
+// 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');
+        }
+    }
+
+    // Bytecode dialog highlight
+    if (loadedFileExecuting && bytecodeDialogOpen && bytecodeIdxHighlight !== bytecodeIdxInstr + currPc) {
+        if (typeof bytecodeIdxHighlight === 'number') {
+            $('#bytecode-preformatted div')[bytecodeIdxHighlight].classList.remove('highlight');
+        }
+        bytecodeIdxHighlight = bytecodeIdxInstr + currPc;
+        $('#bytecode-preformatted div')[bytecodeIdxHighlight].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) {
+    // Not 100% reliable if callstack has several functions of the same name
+    if (bytecodeDialogOpen && (currFileName != msg.fileName || currFuncName != msg.funcName)) {
+        socket.emit('get-bytecode', {});
+    }
+
+    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($('<div></div>').text(ent.message));
+        } else if (ent.type === 'alert') {
+            elem.append($('<div class="alert"></div>').text(ent.message));
+        } else if (ent.type === 'log') {
+            elem.append($('<div class="log loglevel' + ent.level + '"></div>').text(ent.message));
+        } else if (ent.type === 'debugger-info') {
+            elem.append($('<div class="debugger-info"><div>').text(ent.message));
+        } else if (ent.type === 'debugger-debug') {
+            elem.append($('<div class="debugger-debug"><div>').text(ent.message));
+        } else {
+            elem.append($('<div></div>').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 = $('<a class="rest"></a>').text(e.fileName + ':' + e.lineNumber + ' (pc ' + e.pc + ')');  // float
+        s1.on('click', function () {
+            activeFileName = e.fileName;
+            activeLine = e.lineNumber || 1;
+            activeHighlight = activeLine;
+            requestSourceRefetch();
+        });
+        s2 = $('<span class="func"></span>').text(e.funcName + '()');
+        div = $('<div></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 = $('<span class="value"></span>').text(e.value);  // float
+        s2 = $('<span class="key"></span>').text(e.key);
+        div = $('<div></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 = $('<div></div>');
+    sub = $('<button id="delete-all-breakpoints-button"></button>').text('Delete all breakpoints');
+    sub.on('click', function () {
+        socket.emit('delete-all-breakpoints');
+    });
+    div.append(sub);
+    sub = $('<input id="add-breakpoint-file"></input>').val('file.js');
+    div.append(sub);
+    sub = $('<span></span>').text(':');
+    div.append(sub);
+    sub = $('<input id="add-breakpoint-line"></input>').val('123');
+    div.append(sub);
+    sub = $('<button id="add-breakpoint-button"></button>').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 = $('<span id="breakpoint-hint"></span>').text('or dblclick source');
+    div.append(sub);
+    elem.append(div);
+
+    // Active breakpoints follow
+    msg.breakpoints.forEach(function (bp) {
+        var div;
+        var sub;
+
+        div = $('<div class="breakpoint-line"></div>');
+        sub = $('<button class="delete-breakpoint-button"></button>').text('Delete');
+        sub.on('click', function () {
+            socket.emit('delete-breakpoint', {
+                fileName: bp.fileName,
+                lineNumber: bp.lineNumber
+            });
+        });
+        div.append(sub);
+        sub = $('<a></a>').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) {
+    var elem, div;
+    var div;
+
+    elem = $('#bytecode-preformatted');
+    elem.empty();
+
+    msg.preformatted.split('\n').forEach(function (line, idx) {
+        div = $('<div></div>');
+        div.text(line);
+        elem.append(div);
+    });
+
+    bytecodeIdxHighlight = null;
+    bytecodeIdxInstr = msg.idxPreformattedInstructions;
+});
+
+$('#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 () {
+    bytecodeDialogOpen = true;
+    $('#bytecode-dialog').dialog('open');
+
+    elem = $('#bytecode-preformatted');
+    elem.empty().text('Loading bytecode...');
+
+    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></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 = $('<option></option>').attr({ 'value': '__none__' }).text('No source file selected');
+            elem.append(opt);
+            data.forEach(function (ent) {
+                var opt = $('<option></option>').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: 700,
+        height: 600,
+        close: function () {
+            bytecodeDialogOpen = false;
+            bytecodeIdxHighlight = null;
+            bytecodeIdxInstr = 0;
+        }
+    });
+
+    // 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();
+});

+ 1349 - 0
src/third_party/duktape-1.5.2/duk_build_meta.json

@@ -0,0 +1,1349 @@
+{
+    "builtin_strings": [
+        "Undefined", 
+        "Null", 
+        "Arguments", 
+        "Object", 
+        "Function", 
+        "Array", 
+        "String", 
+        "Boolean", 
+        "Number", 
+        "Date", 
+        "RegExp", 
+        "Error", 
+        "Math", 
+        "JSON", 
+        "", 
+        "ArrayBuffer", 
+        "DataView", 
+        "Int8Array", 
+        "Uint8Array", 
+        "Uint8ClampedArray", 
+        "Int16Array", 
+        "Uint16Array", 
+        "Int32Array", 
+        "Uint32Array", 
+        "Float32Array", 
+        "Float64Array", 
+        "global", 
+        "ObjEnv", 
+        "DecEnv", 
+        "Buffer", 
+        "Pointer", 
+        "Thread", 
+        "eval", 
+        "defineProperty", 
+        "value", 
+        "writable", 
+        "configurable", 
+        "enumerable", 
+        "join", 
+        "toLocaleString", 
+        "valueOf", 
+        "toUTCString", 
+        "toISOString", 
+        "toGMTString", 
+        "source", 
+        "ignoreCase", 
+        "multiline", 
+        "lastIndex", 
+        "(?:)", 
+        "index", 
+        "prototype", 
+        "constructor", 
+        "message", 
+        "boolean", 
+        "number", 
+        "string", 
+        "object", 
+        "undefined", 
+        "NaN", 
+        "Infinity", 
+        "-Infinity", 
+        "-0", 
+        ",", 
+        " ", 
+        "\n    ", 
+        "[...]", 
+        "Invalid Date", 
+        "arguments", 
+        "callee", 
+        "caller", 
+        "has", 
+        "get", 
+        "deleteProperty", 
+        "enumerate", 
+        "ownKeys", 
+        "setPrototypeOf", 
+        "__proto__", 
+        "require", 
+        "id", 
+        "exports", 
+        "filename", 
+        "toString", 
+        "toJSON", 
+        "type", 
+        "data", 
+        "length", 
+        "byteLength", 
+        "byteOffset", 
+        "BYTES_PER_ELEMENT", 
+        "set", 
+        "stack", 
+        "pc", 
+        "lineNumber", 
+        "\u00ffTracedata", 
+        "name", 
+        "fileName", 
+        "buffer", 
+        "pointer", 
+        "\u00ffValue", 
+        "\u00ffNext", 
+        "\u00ffBytecode", 
+        "\u00ffFormals", 
+        "\u00ffVarmap", 
+        "\u00ffLexenv", 
+        "\u00ffVarenv", 
+        "\u00ffSource", 
+        "\u00ffPc2line", 
+        "\u00ffArgs", 
+        "\u00ffMap", 
+        "\u00ffFinalizer", 
+        "\u00ffHandler", 
+        "\u00ffCallee", 
+        "\u00ffThread", 
+        "\u00ffRegbase", 
+        "\u00ffTarget", 
+        "\u00ffThis", 
+        "compile", 
+        "input", 
+        "errCreate", 
+        "errThrow", 
+        "modSearch", 
+        "modLoaded", 
+        "env", 
+        "hex", 
+        "base64", 
+        "jx", 
+        "jc", 
+        "resume", 
+        "fmt", 
+        "raw", 
+        "trace", 
+        "debug", 
+        "info", 
+        "warn", 
+        "error", 
+        "fatal", 
+        "n", 
+        "l", 
+        "clog", 
+        "toLogString", 
+        "{\"_undef\":true}", 
+        "{\"_nan\":true}", 
+        "{\"_inf\":true}", 
+        "{\"_ninf\":true}", 
+        "{\"_func\":true}", 
+        "{_func:true}", 
+        "break", 
+        "case", 
+        "catch", 
+        "continue", 
+        "debugger", 
+        "default", 
+        "delete", 
+        "do", 
+        "else", 
+        "finally", 
+        "for", 
+        "function", 
+        "if", 
+        "in", 
+        "instanceof", 
+        "new", 
+        "return", 
+        "switch", 
+        "this", 
+        "throw", 
+        "try", 
+        "typeof", 
+        "var", 
+        "const", 
+        "void", 
+        "while", 
+        "with", 
+        "class", 
+        "enum", 
+        "export", 
+        "extends", 
+        "import", 
+        "super", 
+        "null", 
+        "true", 
+        "false", 
+        "implements", 
+        "interface", 
+        "let", 
+        "package", 
+        "private", 
+        "protected", 
+        "public", 
+        "static", 
+        "yield"
+    ], 
+    "builtin_strings_base64": [
+        "VW5kZWZpbmVk", 
+        "TnVsbA==", 
+        "QXJndW1lbnRz", 
+        "T2JqZWN0", 
+        "RnVuY3Rpb24=", 
+        "QXJyYXk=", 
+        "U3RyaW5n", 
+        "Qm9vbGVhbg==", 
+        "TnVtYmVy", 
+        "RGF0ZQ==", 
+        "UmVnRXhw", 
+        "RXJyb3I=", 
+        "TWF0aA==", 
+        "SlNPTg==", 
+        "", 
+        "QXJyYXlCdWZmZXI=", 
+        "RGF0YVZpZXc=", 
+        "SW50OEFycmF5", 
+        "VWludDhBcnJheQ==", 
+        "VWludDhDbGFtcGVkQXJyYXk=", 
+        "SW50MTZBcnJheQ==", 
+        "VWludDE2QXJyYXk=", 
+        "SW50MzJBcnJheQ==", 
+        "VWludDMyQXJyYXk=", 
+        "RmxvYXQzMkFycmF5", 
+        "RmxvYXQ2NEFycmF5", 
+        "Z2xvYmFs", 
+        "T2JqRW52", 
+        "RGVjRW52", 
+        "QnVmZmVy", 
+        "UG9pbnRlcg==", 
+        "VGhyZWFk", 
+        "ZXZhbA==", 
+        "ZGVmaW5lUHJvcGVydHk=", 
+        "dmFsdWU=", 
+        "d3JpdGFibGU=", 
+        "Y29uZmlndXJhYmxl", 
+        "ZW51bWVyYWJsZQ==", 
+        "am9pbg==", 
+        "dG9Mb2NhbGVTdHJpbmc=", 
+        "dmFsdWVPZg==", 
+        "dG9VVENTdHJpbmc=", 
+        "dG9JU09TdHJpbmc=", 
+        "dG9HTVRTdHJpbmc=", 
+        "c291cmNl", 
+        "aWdub3JlQ2FzZQ==", 
+        "bXVsdGlsaW5l", 
+        "bGFzdEluZGV4", 
+        "KD86KQ==", 
+        "aW5kZXg=", 
+        "cHJvdG90eXBl", 
+        "Y29uc3RydWN0b3I=", 
+        "bWVzc2FnZQ==", 
+        "Ym9vbGVhbg==", 
+        "bnVtYmVy", 
+        "c3RyaW5n", 
+        "b2JqZWN0", 
+        "dW5kZWZpbmVk", 
+        "TmFO", 
+        "SW5maW5pdHk=", 
+        "LUluZmluaXR5", 
+        "LTA=", 
+        "LA==", 
+        "IA==", 
+        "CiAgICA=", 
+        "Wy4uLl0=", 
+        "SW52YWxpZCBEYXRl", 
+        "YXJndW1lbnRz", 
+        "Y2FsbGVl", 
+        "Y2FsbGVy", 
+        "aGFz", 
+        "Z2V0", 
+        "ZGVsZXRlUHJvcGVydHk=", 
+        "ZW51bWVyYXRl", 
+        "b3duS2V5cw==", 
+        "c2V0UHJvdG90eXBlT2Y=", 
+        "X19wcm90b19f", 
+        "cmVxdWlyZQ==", 
+        "aWQ=", 
+        "ZXhwb3J0cw==", 
+        "ZmlsZW5hbWU=", 
+        "dG9TdHJpbmc=", 
+        "dG9KU09O", 
+        "dHlwZQ==", 
+        "ZGF0YQ==", 
+        "bGVuZ3Ro", 
+        "Ynl0ZUxlbmd0aA==", 
+        "Ynl0ZU9mZnNldA==", 
+        "QllURVNfUEVSX0VMRU1FTlQ=", 
+        "c2V0", 
+        "c3RhY2s=", 
+        "cGM=", 
+        "bGluZU51bWJlcg==", 
+        "/1RyYWNlZGF0YQ==", 
+        "bmFtZQ==", 
+        "ZmlsZU5hbWU=", 
+        "YnVmZmVy", 
+        "cG9pbnRlcg==", 
+        "/1ZhbHVl", 
+        "/05leHQ=", 
+        "/0J5dGVjb2Rl", 
+        "/0Zvcm1hbHM=", 
+        "/1Zhcm1hcA==", 
+        "/0xleGVudg==", 
+        "/1ZhcmVudg==", 
+        "/1NvdXJjZQ==", 
+        "/1BjMmxpbmU=", 
+        "/0FyZ3M=", 
+        "/01hcA==", 
+        "/0ZpbmFsaXplcg==", 
+        "/0hhbmRsZXI=", 
+        "/0NhbGxlZQ==", 
+        "/1RocmVhZA==", 
+        "/1JlZ2Jhc2U=", 
+        "/1RhcmdldA==", 
+        "/1RoaXM=", 
+        "Y29tcGlsZQ==", 
+        "aW5wdXQ=", 
+        "ZXJyQ3JlYXRl", 
+        "ZXJyVGhyb3c=", 
+        "bW9kU2VhcmNo", 
+        "bW9kTG9hZGVk", 
+        "ZW52", 
+        "aGV4", 
+        "YmFzZTY0", 
+        "ang=", 
+        "amM=", 
+        "cmVzdW1l", 
+        "Zm10", 
+        "cmF3", 
+        "dHJhY2U=", 
+        "ZGVidWc=", 
+        "aW5mbw==", 
+        "d2Fybg==", 
+        "ZXJyb3I=", 
+        "ZmF0YWw=", 
+        "bg==", 
+        "bA==", 
+        "Y2xvZw==", 
+        "dG9Mb2dTdHJpbmc=", 
+        "eyJfdW5kZWYiOnRydWV9", 
+        "eyJfbmFuIjp0cnVlfQ==", 
+        "eyJfaW5mIjp0cnVlfQ==", 
+        "eyJfbmluZiI6dHJ1ZX0=", 
+        "eyJfZnVuYyI6dHJ1ZX0=", 
+        "e19mdW5jOnRydWV9", 
+        "YnJlYWs=", 
+        "Y2FzZQ==", 
+        "Y2F0Y2g=", 
+        "Y29udGludWU=", 
+        "ZGVidWdnZXI=", 
+        "ZGVmYXVsdA==", 
+        "ZGVsZXRl", 
+        "ZG8=", 
+        "ZWxzZQ==", 
+        "ZmluYWxseQ==", 
+        "Zm9y", 
+        "ZnVuY3Rpb24=", 
+        "aWY=", 
+        "aW4=", 
+        "aW5zdGFuY2VvZg==", 
+        "bmV3", 
+        "cmV0dXJu", 
+        "c3dpdGNo", 
+        "dGhpcw==", 
+        "dGhyb3c=", 
+        "dHJ5", 
+        "dHlwZW9m", 
+        "dmFy", 
+        "Y29uc3Q=", 
+        "dm9pZA==", 
+        "d2hpbGU=", 
+        "d2l0aA==", 
+        "Y2xhc3M=", 
+        "ZW51bQ==", 
+        "ZXhwb3J0", 
+        "ZXh0ZW5kcw==", 
+        "aW1wb3J0", 
+        "c3VwZXI=", 
+        "bnVsbA==", 
+        "dHJ1ZQ==", 
+        "ZmFsc2U=", 
+        "aW1wbGVtZW50cw==", 
+        "aW50ZXJmYWNl", 
+        "bGV0", 
+        "cGFja2FnZQ==", 
+        "cHJpdmF0ZQ==", 
+        "cHJvdGVjdGVk", 
+        "cHVibGlj", 
+        "c3RhdGlj", 
+        "eWllbGQ="
+    ], 
+    "builtin_strings_info": [
+        {
+            "base64": "VW5kZWZpbmVk", 
+            "define": "DUK_STRIDX_UC_UNDEFINED", 
+            "plain": "Undefined"
+        }, 
+        {
+            "base64": "TnVsbA==", 
+            "define": "DUK_STRIDX_UC_NULL", 
+            "plain": "Null"
+        }, 
+        {
+            "base64": "QXJndW1lbnRz", 
+            "define": "DUK_STRIDX_UC_ARGUMENTS", 
+            "plain": "Arguments"
+        }, 
+        {
+            "base64": "T2JqZWN0", 
+            "define": "DUK_STRIDX_UC_OBJECT", 
+            "plain": "Object"
+        }, 
+        {
+            "base64": "RnVuY3Rpb24=", 
+            "define": "DUK_STRIDX_UC_FUNCTION", 
+            "plain": "Function"
+        }, 
+        {
+            "base64": "QXJyYXk=", 
+            "define": "DUK_STRIDX_ARRAY", 
+            "plain": "Array"
+        }, 
+        {
+            "base64": "U3RyaW5n", 
+            "define": "DUK_STRIDX_UC_STRING", 
+            "plain": "String"
+        }, 
+        {
+            "base64": "Qm9vbGVhbg==", 
+            "define": "DUK_STRIDX_UC_BOOLEAN", 
+            "plain": "Boolean"
+        }, 
+        {
+            "base64": "TnVtYmVy", 
+            "define": "DUK_STRIDX_UC_NUMBER", 
+            "plain": "Number"
+        }, 
+        {
+            "base64": "RGF0ZQ==", 
+            "define": "DUK_STRIDX_DATE", 
+            "plain": "Date"
+        }, 
+        {
+            "base64": "UmVnRXhw", 
+            "define": "DUK_STRIDX_REG_EXP", 
+            "plain": "RegExp"
+        }, 
+        {
+            "base64": "RXJyb3I=", 
+            "define": "DUK_STRIDX_UC_ERROR", 
+            "plain": "Error"
+        }, 
+        {
+            "base64": "TWF0aA==", 
+            "define": "DUK_STRIDX_MATH", 
+            "plain": "Math"
+        }, 
+        {
+            "base64": "SlNPTg==", 
+            "define": "DUK_STRIDX_JSON", 
+            "plain": "JSON"
+        }, 
+        {
+            "base64": "", 
+            "define": "DUK_STRIDX_EMPTY_STRING", 
+            "plain": ""
+        }, 
+        {
+            "base64": "QXJyYXlCdWZmZXI=", 
+            "define": "DUK_STRIDX_ARRAY_BUFFER", 
+            "plain": "ArrayBuffer"
+        }, 
+        {
+            "base64": "RGF0YVZpZXc=", 
+            "define": "DUK_STRIDX_DATA_VIEW", 
+            "plain": "DataView"
+        }, 
+        {
+            "base64": "SW50OEFycmF5", 
+            "define": "DUK_STRIDX_INT8_ARRAY", 
+            "plain": "Int8Array"
+        }, 
+        {
+            "base64": "VWludDhBcnJheQ==", 
+            "define": "DUK_STRIDX_UINT8_ARRAY", 
+            "plain": "Uint8Array"
+        }, 
+        {
+            "base64": "VWludDhDbGFtcGVkQXJyYXk=", 
+            "define": "DUK_STRIDX_UINT8_CLAMPED_ARRAY", 
+            "plain": "Uint8ClampedArray"
+        }, 
+        {
+            "base64": "SW50MTZBcnJheQ==", 
+            "define": "DUK_STRIDX_INT16_ARRAY", 
+            "plain": "Int16Array"
+        }, 
+        {
+            "base64": "VWludDE2QXJyYXk=", 
+            "define": "DUK_STRIDX_UINT16_ARRAY", 
+            "plain": "Uint16Array"
+        }, 
+        {
+            "base64": "SW50MzJBcnJheQ==", 
+            "define": "DUK_STRIDX_INT32_ARRAY", 
+            "plain": "Int32Array"
+        }, 
+        {
+            "base64": "VWludDMyQXJyYXk=", 
+            "define": "DUK_STRIDX_UINT32_ARRAY", 
+            "plain": "Uint32Array"
+        }, 
+        {
+            "base64": "RmxvYXQzMkFycmF5", 
+            "define": "DUK_STRIDX_FLOAT32_ARRAY", 
+            "plain": "Float32Array"
+        }, 
+        {
+            "base64": "RmxvYXQ2NEFycmF5", 
+            "define": "DUK_STRIDX_FLOAT64_ARRAY", 
+            "plain": "Float64Array"
+        }, 
+        {
+            "base64": "Z2xvYmFs", 
+            "define": "DUK_STRIDX_GLOBAL", 
+            "plain": "global"
+        }, 
+        {
+            "base64": "T2JqRW52", 
+            "define": "DUK_STRIDX_OBJ_ENV", 
+            "plain": "ObjEnv"
+        }, 
+        {
+            "base64": "RGVjRW52", 
+            "define": "DUK_STRIDX_DEC_ENV", 
+            "plain": "DecEnv"
+        }, 
+        {
+            "base64": "QnVmZmVy", 
+            "define": "DUK_STRIDX_UC_BUFFER", 
+            "plain": "Buffer"
+        }, 
+        {
+            "base64": "UG9pbnRlcg==", 
+            "define": "DUK_STRIDX_UC_POINTER", 
+            "plain": "Pointer"
+        }, 
+        {
+            "base64": "VGhyZWFk", 
+            "define": "DUK_STRIDX_UC_THREAD", 
+            "plain": "Thread"
+        }, 
+        {
+            "base64": "ZXZhbA==", 
+            "define": "DUK_STRIDX_EVAL", 
+            "plain": "eval"
+        }, 
+        {
+            "base64": "ZGVmaW5lUHJvcGVydHk=", 
+            "define": "DUK_STRIDX_DEFINE_PROPERTY", 
+            "plain": "defineProperty"
+        }, 
+        {
+            "base64": "dmFsdWU=", 
+            "define": "DUK_STRIDX_VALUE", 
+            "plain": "value"
+        }, 
+        {
+            "base64": "d3JpdGFibGU=", 
+            "define": "DUK_STRIDX_WRITABLE", 
+            "plain": "writable"
+        }, 
+        {
+            "base64": "Y29uZmlndXJhYmxl", 
+            "define": "DUK_STRIDX_CONFIGURABLE", 
+            "plain": "configurable"
+        }, 
+        {
+            "base64": "ZW51bWVyYWJsZQ==", 
+            "define": "DUK_STRIDX_ENUMERABLE", 
+            "plain": "enumerable"
+        }, 
+        {
+            "base64": "am9pbg==", 
+            "define": "DUK_STRIDX_JOIN", 
+            "plain": "join"
+        }, 
+        {
+            "base64": "dG9Mb2NhbGVTdHJpbmc=", 
+            "define": "DUK_STRIDX_TO_LOCALE_STRING", 
+            "plain": "toLocaleString"
+        }, 
+        {
+            "base64": "dmFsdWVPZg==", 
+            "define": "DUK_STRIDX_VALUE_OF", 
+            "plain": "valueOf"
+        }, 
+        {
+            "base64": "dG9VVENTdHJpbmc=", 
+            "define": "DUK_STRIDX_TO_UTC_STRING", 
+            "plain": "toUTCString"
+        }, 
+        {
+            "base64": "dG9JU09TdHJpbmc=", 
+            "define": "DUK_STRIDX_TO_ISO_STRING", 
+            "plain": "toISOString"
+        }, 
+        {
+            "base64": "dG9HTVRTdHJpbmc=", 
+            "define": "DUK_STRIDX_TO_GMT_STRING", 
+            "plain": "toGMTString"
+        }, 
+        {
+            "base64": "c291cmNl", 
+            "define": "DUK_STRIDX_SOURCE", 
+            "plain": "source"
+        }, 
+        {
+            "base64": "aWdub3JlQ2FzZQ==", 
+            "define": "DUK_STRIDX_IGNORE_CASE", 
+            "plain": "ignoreCase"
+        }, 
+        {
+            "base64": "bXVsdGlsaW5l", 
+            "define": "DUK_STRIDX_MULTILINE", 
+            "plain": "multiline"
+        }, 
+        {
+            "base64": "bGFzdEluZGV4", 
+            "define": "DUK_STRIDX_LAST_INDEX", 
+            "plain": "lastIndex"
+        }, 
+        {
+            "base64": "KD86KQ==", 
+            "define": "DUK_STRIDX_ESCAPED_EMPTY_REGEXP", 
+            "plain": "(?:)"
+        }, 
+        {
+            "base64": "aW5kZXg=", 
+            "define": "DUK_STRIDX_INDEX", 
+            "plain": "index"
+        }, 
+        {
+            "base64": "cHJvdG90eXBl", 
+            "define": "DUK_STRIDX_PROTOTYPE", 
+            "plain": "prototype"
+        }, 
+        {
+            "base64": "Y29uc3RydWN0b3I=", 
+            "define": "DUK_STRIDX_CONSTRUCTOR", 
+            "plain": "constructor"
+        }, 
+        {
+            "base64": "bWVzc2FnZQ==", 
+            "define": "DUK_STRIDX_MESSAGE", 
+            "plain": "message"
+        }, 
+        {
+            "base64": "Ym9vbGVhbg==", 
+            "define": "DUK_STRIDX_LC_BOOLEAN", 
+            "plain": "boolean"
+        }, 
+        {
+            "base64": "bnVtYmVy", 
+            "define": "DUK_STRIDX_LC_NUMBER", 
+            "plain": "number"
+        }, 
+        {
+            "base64": "c3RyaW5n", 
+            "define": "DUK_STRIDX_LC_STRING", 
+            "plain": "string"
+        }, 
+        {
+            "base64": "b2JqZWN0", 
+            "define": "DUK_STRIDX_LC_OBJECT", 
+            "plain": "object"
+        }, 
+        {
+            "base64": "dW5kZWZpbmVk", 
+            "define": "DUK_STRIDX_LC_UNDEFINED", 
+            "plain": "undefined"
+        }, 
+        {
+            "base64": "TmFO", 
+            "define": "DUK_STRIDX_NAN", 
+            "plain": "NaN"
+        }, 
+        {
+            "base64": "SW5maW5pdHk=", 
+            "define": "DUK_STRIDX_INFINITY", 
+            "plain": "Infinity"
+        }, 
+        {
+            "base64": "LUluZmluaXR5", 
+            "define": "DUK_STRIDX_MINUS_INFINITY", 
+            "plain": "-Infinity"
+        }, 
+        {
+            "base64": "LTA=", 
+            "define": "DUK_STRIDX_MINUS_ZERO", 
+            "plain": "-0"
+        }, 
+        {
+            "base64": "LA==", 
+            "define": "DUK_STRIDX_COMMA", 
+            "plain": ","
+        }, 
+        {
+            "base64": "IA==", 
+            "define": "DUK_STRIDX_SPACE", 
+            "plain": " "
+        }, 
+        {
+            "base64": "CiAgICA=", 
+            "define": "DUK_STRIDX_NEWLINE_4SPACE", 
+            "plain": "\n    "
+        }, 
+        {
+            "base64": "Wy4uLl0=", 
+            "define": "DUK_STRIDX_BRACKETED_ELLIPSIS", 
+            "plain": "[...]"
+        }, 
+        {
+            "base64": "SW52YWxpZCBEYXRl", 
+            "define": "DUK_STRIDX_INVALID_DATE", 
+            "plain": "Invalid Date"
+        }, 
+        {
+            "base64": "YXJndW1lbnRz", 
+            "define": "DUK_STRIDX_LC_ARGUMENTS", 
+            "plain": "arguments"
+        }, 
+        {
+            "base64": "Y2FsbGVl", 
+            "define": "DUK_STRIDX_CALLEE", 
+            "plain": "callee"
+        }, 
+        {
+            "base64": "Y2FsbGVy", 
+            "define": "DUK_STRIDX_CALLER", 
+            "plain": "caller"
+        }, 
+        {
+            "base64": "aGFz", 
+            "define": "DUK_STRIDX_HAS", 
+            "plain": "has"
+        }, 
+        {
+            "base64": "Z2V0", 
+            "define": "DUK_STRIDX_GET", 
+            "plain": "get"
+        }, 
+        {
+            "base64": "ZGVsZXRlUHJvcGVydHk=", 
+            "define": "DUK_STRIDX_DELETE_PROPERTY", 
+            "plain": "deleteProperty"
+        }, 
+        {
+            "base64": "ZW51bWVyYXRl", 
+            "define": "DUK_STRIDX_ENUMERATE", 
+            "plain": "enumerate"
+        }, 
+        {
+            "base64": "b3duS2V5cw==", 
+            "define": "DUK_STRIDX_OWN_KEYS", 
+            "plain": "ownKeys"
+        }, 
+        {
+            "base64": "c2V0UHJvdG90eXBlT2Y=", 
+            "define": "DUK_STRIDX_SET_PROTOTYPE_OF", 
+            "plain": "setPrototypeOf"
+        }, 
+        {
+            "base64": "X19wcm90b19f", 
+            "define": "DUK_STRIDX___PROTO__", 
+            "plain": "__proto__"
+        }, 
+        {
+            "base64": "cmVxdWlyZQ==", 
+            "define": "DUK_STRIDX_REQUIRE", 
+            "plain": "require"
+        }, 
+        {
+            "base64": "aWQ=", 
+            "define": "DUK_STRIDX_ID", 
+            "plain": "id"
+        }, 
+        {
+            "base64": "ZXhwb3J0cw==", 
+            "define": "DUK_STRIDX_EXPORTS", 
+            "plain": "exports"
+        }, 
+        {
+            "base64": "ZmlsZW5hbWU=", 
+            "define": "DUK_STRIDX_FILENAME", 
+            "plain": "filename"
+        }, 
+        {
+            "base64": "dG9TdHJpbmc=", 
+            "define": "DUK_STRIDX_TO_STRING", 
+            "plain": "toString"
+        }, 
+        {
+            "base64": "dG9KU09O", 
+            "define": "DUK_STRIDX_TO_JSON", 
+            "plain": "toJSON"
+        }, 
+        {
+            "base64": "dHlwZQ==", 
+            "define": "DUK_STRIDX_TYPE", 
+            "plain": "type"
+        }, 
+        {
+            "base64": "ZGF0YQ==", 
+            "define": "DUK_STRIDX_DATA", 
+            "plain": "data"
+        }, 
+        {
+            "base64": "bGVuZ3Ro", 
+            "define": "DUK_STRIDX_LENGTH", 
+            "plain": "length"
+        }, 
+        {
+            "base64": "Ynl0ZUxlbmd0aA==", 
+            "define": "DUK_STRIDX_BYTE_LENGTH", 
+            "plain": "byteLength"
+        }, 
+        {
+            "base64": "Ynl0ZU9mZnNldA==", 
+            "define": "DUK_STRIDX_BYTE_OFFSET", 
+            "plain": "byteOffset"
+        }, 
+        {
+            "base64": "QllURVNfUEVSX0VMRU1FTlQ=", 
+            "define": "DUK_STRIDX_BYTES_PER_ELEMENT", 
+            "plain": "BYTES_PER_ELEMENT"
+        }, 
+        {
+            "base64": "c2V0", 
+            "define": "DUK_STRIDX_SET", 
+            "plain": "set"
+        }, 
+        {
+            "base64": "c3RhY2s=", 
+            "define": "DUK_STRIDX_STACK", 
+            "plain": "stack"
+        }, 
+        {
+            "base64": "cGM=", 
+            "define": "DUK_STRIDX_PC", 
+            "plain": "pc"
+        }, 
+        {
+            "base64": "bGluZU51bWJlcg==", 
+            "define": "DUK_STRIDX_LINE_NUMBER", 
+            "plain": "lineNumber"
+        }, 
+        {
+            "base64": "/1RyYWNlZGF0YQ==", 
+            "define": "DUK_STRIDX_INT_TRACEDATA", 
+            "plain": "\u00ffTracedata"
+        }, 
+        {
+            "base64": "bmFtZQ==", 
+            "define": "DUK_STRIDX_NAME", 
+            "plain": "name"
+        }, 
+        {
+            "base64": "ZmlsZU5hbWU=", 
+            "define": "DUK_STRIDX_FILE_NAME", 
+            "plain": "fileName"
+        }, 
+        {
+            "base64": "YnVmZmVy", 
+            "define": "DUK_STRIDX_LC_BUFFER", 
+            "plain": "buffer"
+        }, 
+        {
+            "base64": "cG9pbnRlcg==", 
+            "define": "DUK_STRIDX_LC_POINTER", 
+            "plain": "pointer"
+        }, 
+        {
+            "base64": "/1ZhbHVl", 
+            "define": "DUK_STRIDX_INT_VALUE", 
+            "plain": "\u00ffValue"
+        }, 
+        {
+            "base64": "/05leHQ=", 
+            "define": "DUK_STRIDX_INT_NEXT", 
+            "plain": "\u00ffNext"
+        }, 
+        {
+            "base64": "/0J5dGVjb2Rl", 
+            "define": "DUK_STRIDX_INT_BYTECODE", 
+            "plain": "\u00ffBytecode"
+        }, 
+        {
+            "base64": "/0Zvcm1hbHM=", 
+            "define": "DUK_STRIDX_INT_FORMALS", 
+            "plain": "\u00ffFormals"
+        }, 
+        {
+            "base64": "/1Zhcm1hcA==", 
+            "define": "DUK_STRIDX_INT_VARMAP", 
+            "plain": "\u00ffVarmap"
+        }, 
+        {
+            "base64": "/0xleGVudg==", 
+            "define": "DUK_STRIDX_INT_LEXENV", 
+            "plain": "\u00ffLexenv"
+        }, 
+        {
+            "base64": "/1ZhcmVudg==", 
+            "define": "DUK_STRIDX_INT_VARENV", 
+            "plain": "\u00ffVarenv"
+        }, 
+        {
+            "base64": "/1NvdXJjZQ==", 
+            "define": "DUK_STRIDX_INT_SOURCE", 
+            "plain": "\u00ffSource"
+        }, 
+        {
+            "base64": "/1BjMmxpbmU=", 
+            "define": "DUK_STRIDX_INT_PC2LINE", 
+            "plain": "\u00ffPc2line"
+        }, 
+        {
+            "base64": "/0FyZ3M=", 
+            "define": "DUK_STRIDX_INT_ARGS", 
+            "plain": "\u00ffArgs"
+        }, 
+        {
+            "base64": "/01hcA==", 
+            "define": "DUK_STRIDX_INT_MAP", 
+            "plain": "\u00ffMap"
+        }, 
+        {
+            "base64": "/0ZpbmFsaXplcg==", 
+            "define": "DUK_STRIDX_INT_FINALIZER", 
+            "plain": "\u00ffFinalizer"
+        }, 
+        {
+            "base64": "/0hhbmRsZXI=", 
+            "define": "DUK_STRIDX_INT_HANDLER", 
+            "plain": "\u00ffHandler"
+        }, 
+        {
+            "base64": "/0NhbGxlZQ==", 
+            "define": "DUK_STRIDX_INT_CALLEE", 
+            "plain": "\u00ffCallee"
+        }, 
+        {
+            "base64": "/1RocmVhZA==", 
+            "define": "DUK_STRIDX_INT_THREAD", 
+            "plain": "\u00ffThread"
+        }, 
+        {
+            "base64": "/1JlZ2Jhc2U=", 
+            "define": "DUK_STRIDX_INT_REGBASE", 
+            "plain": "\u00ffRegbase"
+        }, 
+        {
+            "base64": "/1RhcmdldA==", 
+            "define": "DUK_STRIDX_INT_TARGET", 
+            "plain": "\u00ffTarget"
+        }, 
+        {
+            "base64": "/1RoaXM=", 
+            "define": "DUK_STRIDX_INT_THIS", 
+            "plain": "\u00ffThis"
+        }, 
+        {
+            "base64": "Y29tcGlsZQ==", 
+            "define": "DUK_STRIDX_COMPILE", 
+            "plain": "compile"
+        }, 
+        {
+            "base64": "aW5wdXQ=", 
+            "define": "DUK_STRIDX_INPUT", 
+            "plain": "input"
+        }, 
+        {
+            "base64": "ZXJyQ3JlYXRl", 
+            "define": "DUK_STRIDX_ERR_CREATE", 
+            "plain": "errCreate"
+        }, 
+        {
+            "base64": "ZXJyVGhyb3c=", 
+            "define": "DUK_STRIDX_ERR_THROW", 
+            "plain": "errThrow"
+        }, 
+        {
+            "base64": "bW9kU2VhcmNo", 
+            "define": "DUK_STRIDX_MOD_SEARCH", 
+            "plain": "modSearch"
+        }, 
+        {
+            "base64": "bW9kTG9hZGVk", 
+            "define": "DUK_STRIDX_MOD_LOADED", 
+            "plain": "modLoaded"
+        }, 
+        {
+            "base64": "ZW52", 
+            "define": "DUK_STRIDX_ENV", 
+            "plain": "env"
+        }, 
+        {
+            "base64": "aGV4", 
+            "define": "DUK_STRIDX_HEX", 
+            "plain": "hex"
+        }, 
+        {
+            "base64": "YmFzZTY0", 
+            "define": "DUK_STRIDX_BASE64", 
+            "plain": "base64"
+        }, 
+        {
+            "base64": "ang=", 
+            "define": "DUK_STRIDX_JX", 
+            "plain": "jx"
+        }, 
+        {
+            "base64": "amM=", 
+            "define": "DUK_STRIDX_JC", 
+            "plain": "jc"
+        }, 
+        {
+            "base64": "cmVzdW1l", 
+            "define": "DUK_STRIDX_RESUME", 
+            "plain": "resume"
+        }, 
+        {
+            "base64": "Zm10", 
+            "define": "DUK_STRIDX_FMT", 
+            "plain": "fmt"
+        }, 
+        {
+            "base64": "cmF3", 
+            "define": "DUK_STRIDX_RAW", 
+            "plain": "raw"
+        }, 
+        {
+            "base64": "dHJhY2U=", 
+            "define": "DUK_STRIDX_LC_TRACE", 
+            "plain": "trace"
+        }, 
+        {
+            "base64": "ZGVidWc=", 
+            "define": "DUK_STRIDX_LC_DEBUG", 
+            "plain": "debug"
+        }, 
+        {
+            "base64": "aW5mbw==", 
+            "define": "DUK_STRIDX_LC_INFO", 
+            "plain": "info"
+        }, 
+        {
+            "base64": "d2Fybg==", 
+            "define": "DUK_STRIDX_LC_WARN", 
+            "plain": "warn"
+        }, 
+        {
+            "base64": "ZXJyb3I=", 
+            "define": "DUK_STRIDX_LC_ERROR", 
+            "plain": "error"
+        }, 
+        {
+            "base64": "ZmF0YWw=", 
+            "define": "DUK_STRIDX_LC_FATAL", 
+            "plain": "fatal"
+        }, 
+        {
+            "base64": "bg==", 
+            "define": "DUK_STRIDX_LC_N", 
+            "plain": "n"
+        }, 
+        {
+            "base64": "bA==", 
+            "define": "DUK_STRIDX_LC_L", 
+            "plain": "l"
+        }, 
+        {
+            "base64": "Y2xvZw==", 
+            "define": "DUK_STRIDX_CLOG", 
+            "plain": "clog"
+        }, 
+        {
+            "base64": "dG9Mb2dTdHJpbmc=", 
+            "define": "DUK_STRIDX_TO_LOG_STRING", 
+            "plain": "toLogString"
+        }, 
+        {
+            "base64": "eyJfdW5kZWYiOnRydWV9", 
+            "define": "DUK_STRIDX_JSON_EXT_UNDEFINED", 
+            "plain": "{\"_undef\":true}"
+        }, 
+        {
+            "base64": "eyJfbmFuIjp0cnVlfQ==", 
+            "define": "DUK_STRIDX_JSON_EXT_NAN", 
+            "plain": "{\"_nan\":true}"
+        }, 
+        {
+            "base64": "eyJfaW5mIjp0cnVlfQ==", 
+            "define": "DUK_STRIDX_JSON_EXT_POSINF", 
+            "plain": "{\"_inf\":true}"
+        }, 
+        {
+            "base64": "eyJfbmluZiI6dHJ1ZX0=", 
+            "define": "DUK_STRIDX_JSON_EXT_NEGINF", 
+            "plain": "{\"_ninf\":true}"
+        }, 
+        {
+            "base64": "eyJfZnVuYyI6dHJ1ZX0=", 
+            "define": "DUK_STRIDX_JSON_EXT_FUNCTION1", 
+            "plain": "{\"_func\":true}"
+        }, 
+        {
+            "base64": "e19mdW5jOnRydWV9", 
+            "define": "DUK_STRIDX_JSON_EXT_FUNCTION2", 
+            "plain": "{_func:true}"
+        }, 
+        {
+            "base64": "YnJlYWs=", 
+            "define": "DUK_STRIDX_BREAK", 
+            "plain": "break"
+        }, 
+        {
+            "base64": "Y2FzZQ==", 
+            "define": "DUK_STRIDX_CASE", 
+            "plain": "case"
+        }, 
+        {
+            "base64": "Y2F0Y2g=", 
+            "define": "DUK_STRIDX_CATCH", 
+            "plain": "catch"
+        }, 
+        {
+            "base64": "Y29udGludWU=", 
+            "define": "DUK_STRIDX_CONTINUE", 
+            "plain": "continue"
+        }, 
+        {
+            "base64": "ZGVidWdnZXI=", 
+            "define": "DUK_STRIDX_DEBUGGER", 
+            "plain": "debugger"
+        }, 
+        {
+            "base64": "ZGVmYXVsdA==", 
+            "define": "DUK_STRIDX_DEFAULT", 
+            "plain": "default"
+        }, 
+        {
+            "base64": "ZGVsZXRl", 
+            "define": "DUK_STRIDX_DELETE", 
+            "plain": "delete"
+        }, 
+        {
+            "base64": "ZG8=", 
+            "define": "DUK_STRIDX_DO", 
+            "plain": "do"
+        }, 
+        {
+            "base64": "ZWxzZQ==", 
+            "define": "DUK_STRIDX_ELSE", 
+            "plain": "else"
+        }, 
+        {
+            "base64": "ZmluYWxseQ==", 
+            "define": "DUK_STRIDX_FINALLY", 
+            "plain": "finally"
+        }, 
+        {
+            "base64": "Zm9y", 
+            "define": "DUK_STRIDX_FOR", 
+            "plain": "for"
+        }, 
+        {
+            "base64": "ZnVuY3Rpb24=", 
+            "define": "DUK_STRIDX_LC_FUNCTION", 
+            "plain": "function"
+        }, 
+        {
+            "base64": "aWY=", 
+            "define": "DUK_STRIDX_IF", 
+            "plain": "if"
+        }, 
+        {
+            "base64": "aW4=", 
+            "define": "DUK_STRIDX_IN", 
+            "plain": "in"
+        }, 
+        {
+            "base64": "aW5zdGFuY2VvZg==", 
+            "define": "DUK_STRIDX_INSTANCEOF", 
+            "plain": "instanceof"
+        }, 
+        {
+            "base64": "bmV3", 
+            "define": "DUK_STRIDX_NEW", 
+            "plain": "new"
+        }, 
+        {
+            "base64": "cmV0dXJu", 
+            "define": "DUK_STRIDX_RETURN", 
+            "plain": "return"
+        }, 
+        {
+            "base64": "c3dpdGNo", 
+            "define": "DUK_STRIDX_SWITCH", 
+            "plain": "switch"
+        }, 
+        {
+            "base64": "dGhpcw==", 
+            "define": "DUK_STRIDX_THIS", 
+            "plain": "this"
+        }, 
+        {
+            "base64": "dGhyb3c=", 
+            "define": "DUK_STRIDX_THROW", 
+            "plain": "throw"
+        }, 
+        {
+            "base64": "dHJ5", 
+            "define": "DUK_STRIDX_TRY", 
+            "plain": "try"
+        }, 
+        {
+            "base64": "dHlwZW9m", 
+            "define": "DUK_STRIDX_TYPEOF", 
+            "plain": "typeof"
+        }, 
+        {
+            "base64": "dmFy", 
+            "define": "DUK_STRIDX_VAR", 
+            "plain": "var"
+        }, 
+        {
+            "base64": "Y29uc3Q=", 
+            "define": "DUK_STRIDX_CONST", 
+            "plain": "const"
+        }, 
+        {
+            "base64": "dm9pZA==", 
+            "define": "DUK_STRIDX_VOID", 
+            "plain": "void"
+        }, 
+        {
+            "base64": "d2hpbGU=", 
+            "define": "DUK_STRIDX_WHILE", 
+            "plain": "while"
+        }, 
+        {
+            "base64": "d2l0aA==", 
+            "define": "DUK_STRIDX_WITH", 
+            "plain": "with"
+        }, 
+        {
+            "base64": "Y2xhc3M=", 
+            "define": "DUK_STRIDX_CLASS", 
+            "plain": "class"
+        }, 
+        {
+            "base64": "ZW51bQ==", 
+            "define": "DUK_STRIDX_ENUM", 
+            "plain": "enum"
+        }, 
+        {
+            "base64": "ZXhwb3J0", 
+            "define": "DUK_STRIDX_EXPORT", 
+            "plain": "export"
+        }, 
+        {
+            "base64": "ZXh0ZW5kcw==", 
+            "define": "DUK_STRIDX_EXTENDS", 
+            "plain": "extends"
+        }, 
+        {
+            "base64": "aW1wb3J0", 
+            "define": "DUK_STRIDX_IMPORT", 
+            "plain": "import"
+        }, 
+        {
+            "base64": "c3VwZXI=", 
+            "define": "DUK_STRIDX_SUPER", 
+            "plain": "super"
+        }, 
+        {
+            "base64": "bnVsbA==", 
+            "define": "DUK_STRIDX_LC_NULL", 
+            "plain": "null"
+        }, 
+        {
+            "base64": "dHJ1ZQ==", 
+            "define": "DUK_STRIDX_TRUE", 
+            "plain": "true"
+        }, 
+        {
+            "base64": "ZmFsc2U=", 
+            "define": "DUK_STRIDX_FALSE", 
+            "plain": "false"
+        }, 
+        {
+            "base64": "aW1wbGVtZW50cw==", 
+            "define": "DUK_STRIDX_IMPLEMENTS", 
+            "plain": "implements"
+        }, 
+        {
+            "base64": "aW50ZXJmYWNl", 
+            "define": "DUK_STRIDX_INTERFACE", 
+            "plain": "interface"
+        }, 
+        {
+            "base64": "bGV0", 
+            "define": "DUK_STRIDX_LET", 
+            "plain": "let"
+        }, 
+        {
+            "base64": "cGFja2FnZQ==", 
+            "define": "DUK_STRIDX_PACKAGE", 
+            "plain": "package"
+        }, 
+        {
+            "base64": "cHJpdmF0ZQ==", 
+            "define": "DUK_STRIDX_PRIVATE", 
+            "plain": "private"
+        }, 
+        {
+            "base64": "cHJvdGVjdGVk", 
+            "define": "DUK_STRIDX_PROTECTED", 
+            "plain": "protected"
+        }, 
+        {
+            "base64": "cHVibGlj", 
+            "define": "DUK_STRIDX_PUBLIC", 
+            "plain": "public"
+        }, 
+        {
+            "base64": "c3RhdGlj", 
+            "define": "DUK_STRIDX_STATIC", 
+            "plain": "static"
+        }, 
+        {
+            "base64": "eWllbGQ=", 
+            "define": "DUK_STRIDX_YIELD", 
+            "plain": "yield"
+        }
+    ], 
+    "comment": "Metadata for Duktape build", 
+    "duk_version": 10502, 
+    "duk_version_string": "1.5.2", 
+    "git_describe": "v1.5.2"
+}

+ 10 - 0
src/third_party/duktape-1.5.2/examples/README.rst

@@ -0,0 +1,10 @@
+================
+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.

+ 10 - 0
src/third_party/duktape-1.5.2/examples/alloc-hybrid/README.rst

@@ -0,0 +1,10 @@
+=====================
+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.

+ 293 - 0
src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.c

@@ -0,0 +1,293 @@
+/*
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+/* 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
+}

+ 11 - 0
src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.h

@@ -0,0 +1,11 @@
+#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 */

+ 7 - 0
src/third_party/duktape-1.5.2/examples/alloc-logging/README.rst

@@ -0,0 +1,7 @@
+======================
+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.

+ 138 - 0
src/third_party/duktape-1.5.2/examples/alloc-logging/duk_alloc_logging.c

@@ -0,0 +1,138 @@
+/*
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#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) {
+			write_log("R %p %ld NULL 0\n", ptr, (long) old_size);
+			free((void *) hdr);
+			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);
+}

+ 10 - 0
src/third_party/duktape-1.5.2/examples/alloc-logging/duk_alloc_logging.h

@@ -0,0 +1,10 @@
+#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 */

+ 41 - 0
src/third_party/duktape-1.5.2/examples/alloc-logging/log2gnuplot.py

@@ -0,0 +1,41 @@
+#!/usr/bin/env python2
+#
+#  Analyze allocator logs and write total-bytes-in-use after every
+#  operation to stdout.  The output can be gnuplotted as:
+#
+#  $ python log2gnuplot.py </tmp/duk-alloc-log.txt >/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()

+ 10 - 0
src/third_party/duktape-1.5.2/examples/alloc-torture/README.rst

@@ -0,0 +1,10 @@
+==========================================
+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.

+ 182 - 0
src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.c

@@ -0,0 +1,182 @@
+/*
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#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);
+}

+ 10 - 0
src/third_party/duktape-1.5.2/examples/alloc-torture/duk_alloc_torture.h

@@ -0,0 +1,10 @@
+#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 */

+ 6 - 0
src/third_party/duktape-1.5.2/examples/cmdline/README.rst

@@ -0,0 +1,6 @@
+====================
+Duktape command line
+====================
+
+Ecmascript command line execution tool, useful for running Ecmascript code
+from a file, stdin, or interactively.  Also used by automatic testing.

+ 1463 - 0
src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline.c

@@ -0,0 +1,1463 @@
+/*
+ *  Command line execution tool.  Useful for test cases and manual testing.
+ *
+ *  To enable linenoise 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_*.
+ */
+
+/* Helper define to enable a feature set; can also use separate defines. */
+#if defined(DUK_CMDLINE_FANCY)
+#define DUK_CMDLINE_LINENOISE
+#define DUK_CMDLINE_LINENOISE_COMPLETION
+#define DUK_CMDLINE_RLIMIT
+#define DUK_CMDLINE_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
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+/* Workaround for snprintf() missing in older MSVC versions.
+ * Note that _snprintf() may not NUL terminate the string, but
+ * this difference does not matter here as a NUL terminator is
+ * always explicitly added.
+ */
+#define snprintf _snprintf
+#endif
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(DUK_CMDLINE_SIGNAL)
+#include <signal.h>
+#endif
+#if defined(DUK_CMDLINE_RLIMIT)
+#include <sys/resource.h>
+#endif
+#if defined(DUK_CMDLINE_LINENOISE)
+#include "linenoise.h"
+#endif
+#if defined(DUK_CMDLINE_FILEIO)
+#include <errno.h>
+#endif
+#if defined(EMSCRIPTEN)
+#include <emscripten.h>
+#endif
+#if defined(DUK_CMDLINE_ALLOC_LOGGING)
+#include "duk_alloc_logging.h"
+#endif
+#if defined(DUK_CMDLINE_ALLOC_TORTURE)
+#include "duk_alloc_torture.h"
+#endif
+#if defined(DUK_CMDLINE_ALLOC_HYBRID)
+#include "duk_alloc_hybrid.h"
+#endif
+#include "duktape.h"
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+/* Defined in duk_cmdline_ajduk.c or alljoyn.js headers. */
+void ajsheap_init(void);
+void ajsheap_free(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
+
+#if defined(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 main_argc = 0;
+static char **main_argv = NULL;
+static int interactive_mode = 0;
+#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
+static int debugger_reattach = 0;
+#endif
+
+/*
+ *  Misc helpers
+ */
+
+#if defined(DUK_CMDLINE_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  /* DUK_CMDLINE_RLIMIT */
+
+#if defined(DUK_CMDLINE_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);
+	(void) signal(SIGPIPE, SIG_IGN);  /* avoid SIGPIPE killing process */
+}
+#endif  /* DUK_CMDLINE_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;
+		char fnbuf[256];
+		const char *filename;
+
+		duk_dup_top(ctx);
+		duk_dump_function(ctx);
+		bc_ptr = duk_require_buffer(ctx, -1, &bc_len);
+		filename = duk_require_string(ctx, -5);
+#if defined(EMSCRIPTEN)
+		if (filename[0] == '/') {
+			snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
+		} else {
+			snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename);
+		}
+#else
+		snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
+#endif
+		fnbuf[sizeof(fnbuf) - 1] = (char) 0;
+
+		f = fopen(fnbuf, "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 */
+}
+
+/*
+ *  Minimal Linenoise completion support
+ */
+
+#if defined(DUK_CMDLINE_LINENOISE_COMPLETION)
+static duk_context *completion_ctx;
+
+static int completion_idpart(unsigned char c) {
+	/* Very simplified "is identifier part" check. */
+	if ((c >= (unsigned char) 'a' && c <= (unsigned char) 'z') ||
+	    (c >= (unsigned char) 'A' && c <= (unsigned char) 'Z') ||
+	    (c >= (unsigned char) '0' && c <= (unsigned char) '9') ||
+	    c == (unsigned char) '$' || c == (unsigned char) '_') {
+		return 1;
+	}
+	return 0;
+}
+
+static int completion_digit(unsigned char c) {
+	return (c >= (unsigned char) '0' && c <= (unsigned char) '9');
+}
+
+static duk_ret_t linenoise_completion_lookup(duk_context *ctx) {
+	duk_size_t len;
+	const char *orig;
+	const unsigned char *p;
+	const unsigned char *p_curr;
+	const unsigned char *p_end;
+	const char *key;
+	const char *prefix;
+	linenoiseCompletions *lc;
+	duk_idx_t idx_obj;
+
+	orig = duk_require_string(ctx, -3);
+	p_curr = (const unsigned char *) duk_require_lstring(ctx, -2, &len);
+	p_end = p_curr + len;
+	lc = duk_require_pointer(ctx, -1);
+
+	duk_push_global_object(ctx);
+	idx_obj = duk_require_top_index(ctx);
+
+	while (p_curr <= p_end) {
+		/* p_curr == p_end allowed on purpose, to handle 'Math.' for example. */
+		p = p_curr;
+		while (p < p_end && p[0] != (unsigned char) '.') {
+			p++;
+		}
+		/* 'p' points to a NUL (p == p_end) or a period. */
+		prefix = duk_push_lstring(ctx, (const char *) p_curr, (duk_size_t) (p - p_curr));
+
+#if 0
+		fprintf(stderr, "Completion check: '%s'\n", prefix);
+		fflush(stderr);
+#endif
+
+		if (p == p_end) {
+			/* 'idx_obj' points to the object matching the last
+			 * full component, use [p_curr,p[ as a filter for
+			 * that object.
+			 */
+
+			duk_enum(ctx, idx_obj, DUK_ENUM_INCLUDE_NONENUMERABLE);
+			while (duk_next(ctx, -1, 0 /*get_value*/)) {
+				key = duk_get_string(ctx, -1);
+#if 0
+				fprintf(stderr, "Key: %s\n", key ? key : "");
+				fflush(stderr);
+#endif
+				if (!key) {
+					/* Should never happen, just in case. */
+					goto next;
+				}
+
+				/* Ignore array index keys: usually not desirable, and would
+				 * also require ['0'] quoting.
+				 */
+				if (completion_digit(key[0])) {
+					goto next;
+				}
+
+				/* XXX: There's no key quoting now, it would require replacing the
+				 * last component with a ['foo\nbar'] style lookup when appropriate.
+				 */
+
+				if (strlen(prefix) == 0) {
+					/* Partial ends in a period, e.g. 'Math.' -> complete all Math properties. */
+					duk_push_string(ctx, orig);  /* original, e.g. 'Math.' */
+					duk_push_string(ctx, key);
+					duk_concat(ctx, 2);
+					linenoiseAddCompletion(lc, duk_require_string(ctx, -1));
+					duk_pop(ctx);
+				} else if (prefix && strcmp(key, prefix) == 0) {
+					/* Full completion, add a period, e.g. input 'Math' -> 'Math.'. */
+					duk_push_string(ctx, orig);  /* original, including partial last component */
+					duk_push_string(ctx, ".");
+					duk_concat(ctx, 2);
+					linenoiseAddCompletion(lc, duk_require_string(ctx, -1));
+					duk_pop(ctx);
+				} else if (prefix && strncmp(key, prefix, strlen(prefix)) == 0) {
+					/* Last component is partial, complete. */
+					duk_push_string(ctx, orig);  /* original, including partial last component */
+					duk_push_string(ctx, key + strlen(prefix));  /* completion to last component */
+					duk_concat(ctx, 2);
+					linenoiseAddCompletion(lc, duk_require_string(ctx, -1));
+					duk_pop(ctx);
+				}
+
+			 next:
+				duk_pop(ctx);
+			}
+			return 0;
+		} else {
+			if (duk_get_prop(ctx, idx_obj)) {
+				duk_to_object(ctx, -1);  /* for properties of plain strings etc */
+				duk_replace(ctx, idx_obj);
+				p_curr = p + 1;
+			} else {
+				/* Not found. */
+				return 0;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void linenoise_completion(const char *buf, linenoiseCompletions *lc) {
+	duk_context *ctx;
+	const unsigned char *p_start;
+	const unsigned char *p_end;
+	const unsigned char *p;
+	duk_int_t rc;
+
+	if (!buf) {
+		return;
+	}
+	ctx = completion_ctx;
+	if (!ctx) {
+		return;
+	}
+
+	p_start = (const unsigned char *) buf;
+	p_end = (const unsigned char *) (buf + strlen(buf));
+	p = p_end;
+
+	/* Scan backwards for a maximal string which looks like a property
+	 * chain (e.g. foo.bar.quux).
+	 */
+
+	while (--p >= p_start) {
+		if (p[0] == (unsigned char) '.') {
+			if (p <= p_start) {
+				break;
+			}
+			if (!completion_idpart(p[-1])) {
+				/* Catches e.g. 'foo..bar' -> we want 'bar' only. */
+				break;
+			}
+		} else if (!completion_idpart(p[0])) {
+			break;
+		}
+	}
+	/* 'p' will either be p_start - 1 (ran out of buffer) or point to
+	 * the first offending character.
+	 */
+	p++;
+	if (p < p_start || p >= p_end) {
+		return;  /* should never happen, but just in case */
+	}
+
+	/* 'p' now points to a string of the form 'foo.bar.quux'.  Look up
+	 * all the components except the last; treat the last component as
+	 * a partial name which is used as a filter for the previous full
+	 * component.  All lookups are from the global object now.
+	 */
+
+#if 0
+	fprintf(stderr, "Completion starting point: '%s'\n", p);
+	fflush(stderr);
+#endif
+
+	duk_push_string(ctx, (const char *) buf);
+	duk_push_lstring(ctx, (const char *) p, (duk_size_t) (p_end - p));
+	duk_push_pointer(ctx, (void *) lc);
+
+	rc = duk_safe_call(ctx, linenoise_completion_lookup, 3 /*nargs*/, 1 /*nrets*/);
+	if (rc != DUK_EXEC_SUCCESS) {
+		fprintf(stderr, "Completion handling failure: %s\n", duk_safe_to_string(ctx, -1));
+	}
+	duk_pop(ctx);
+}
+#endif  /* DUK_CMDLINE_LINENOISE_COMPLETION */
+
+/*
+ *  Execute from file handle etc
+ */
+
+static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename) {
+	char *buf = NULL;
+	size_t bufsz;
+	size_t bufoff;
+	size_t got;
+	int rc;
+	int retval = -1;
+
+	buf = (char *) malloc(1024);
+	if (!buf) {
+		goto error;
+	}
+	bufsz = 1024;
+	bufoff = 0;
+
+	/* Read until EOF, avoid fseek/stat because it won't work with stdin. */
+	for (;;) {
+		size_t avail;
+
+		avail = bufsz - bufoff;
+		if (avail < 1024) {
+			size_t newsz;
+			char *buf_new;
+#if 0
+			fprintf(stderr, "resizing read buffer: %ld -> %ld\n", (long) bufsz, (long) (bufsz * 2));
+#endif
+			newsz = bufsz + (bufsz >> 2) + 1024;  /* +25% and some extra */
+			buf_new = (char *) realloc(buf, newsz);
+			if (!buf_new) {
+				goto error;
+			}
+			buf = buf_new;
+			bufsz = newsz;
+		}
+
+		avail = bufsz - bufoff;
+#if 0
+		fprintf(stderr, "reading input: buf=%p bufsz=%ld bufoff=%ld avail=%ld\n",
+		        (void *) buf, (long) bufsz, (long) bufoff, (long) avail);
+#endif
+
+		got = fread((void *) (buf + bufoff), (size_t) 1, avail, f);
+#if 0
+		fprintf(stderr, "got=%ld\n", (long) got);
+#endif
+		if (got == 0) {
+			break;
+		}
+		bufoff += got;
+
+		/* Emscripten specific: stdin EOF doesn't work as expected.
+		 * Instead, when 'emduk' is executed using Node.js, a file
+		 * piped to stdin repeats (!).  Detect that repeat and cut off
+		 * the stdin read.  Ensure the loop repeats enough times to
+		 * avoid detecting spurious loops.
+		 *
+		 * This only seems to work for inputs up to 256 bytes long.
+		 */
+#if defined(EMSCRIPTEN)
+		if (bufoff >= 16384) {
+			size_t i, j, nloops;
+			int looped = 0;
+
+			for (i = 16; i < bufoff / 8; i++) {
+				int ok;
+
+				nloops = bufoff / i;
+				ok = 1;
+				for (j = 1; j < nloops; j++) {
+					if (memcmp((void *) buf, (void *) (buf + i * j), i) != 0) {
+						ok = 0;
+						break;
+					}
+				}
+				if (ok) {
+					fprintf(stderr, "emscripten workaround: detect looping at index %ld, verified with %ld loops\n", (long) i, (long) (nloops - 1));
+					bufoff = i;
+					looped = 1;
+					break;
+				}
+			}
+
+			if (looped) {
+				break;
+			}
+		}
+#endif
+	}
+
+	duk_push_string(ctx, bytecode_filename);
+	duk_push_pointer(ctx, (void *) buf);
+	duk_push_uint(ctx, (duk_uint_t) bufoff);
+	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);
+		buf = NULL;
+	}
+	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;
+	char fnbuf[256];
+
+	/* Example of sending an application specific debugger notification. */
+	duk_push_string(ctx, "DebuggerHandleFile");
+	duk_push_string(ctx, filename);
+	duk_debugger_notify(ctx, 2);
+
+#if defined(EMSCRIPTEN)
+	if (filename[0] == '/') {
+		snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
+	} else {
+		snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename);
+	}
+#else
+	snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
+#endif
+	fnbuf[sizeof(fnbuf) - 1] = (char) 0;
+
+	f = fopen(fnbuf, "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, 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;
+}
+
+#if defined(DUK_CMDLINE_LINENOISE)
+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(" [linenoise]"));
+	duk_pop(ctx);
+
+	linenoiseSetMultiLine(1);
+	linenoiseHistorySetMaxLen(64);
+#if defined(DUK_CMDLINE_LINENOISE_COMPLETION)
+	linenoiseSetCompletionCallback(linenoise_completion);
+#endif
+
+	for (;;) {
+		if (buffer) {
+			linenoiseFree(buffer);
+			buffer = NULL;
+		}
+
+#if defined(DUK_CMDLINE_LINENOISE_COMPLETION)
+		completion_ctx = ctx;
+#endif
+		buffer = linenoise(prompt);
+#if defined(DUK_CMDLINE_LINENOISE_COMPLETION)
+		completion_ctx = NULL;
+#endif
+
+		if (!buffer) {
+			break;
+		}
+
+		if (buffer && buffer[0] != (char) 0) {
+			linenoiseHistoryAdd(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) {
+			linenoiseFree(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) {
+		linenoiseFree(buffer);
+		buffer = NULL;
+	}
+
+	return retval;
+}
+#else  /* DUK_CMDLINE_LINENOISE */
+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(""));
+	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;
+}
+#endif  /* DUK_CMDLINE_LINENOISE */
+
+/*
+ *  Simple file read/write bindings
+ */
+
+#if defined(DUK_CMDLINE_FILEIO)
+static duk_ret_t fileio_read_file(duk_context *ctx) {
+	const char *fn;
+	char *buf;
+	size_t len;
+	size_t off;
+	int rc;
+	FILE *f;
+
+	fn = duk_require_string(ctx, 0);
+	f = fopen(fn, "rb");
+	if (!f) {
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "cannot open file %s for reading, errno %ld: %s",
+		          fn, (long) errno, strerror(errno));
+	}
+
+	rc = fseek(f, 0, SEEK_END);
+	if (rc < 0) {
+		(void) fclose(f);
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "fseek() failed for %s, errno %ld: %s",
+		          fn, (long) errno, strerror(errno));
+	}
+	len = (size_t) ftell(f);
+	rc = fseek(f, 0, SEEK_SET);
+	if (rc < 0) {
+		(void) fclose(f);
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "fseek() failed for %s, errno %ld: %s",
+		          fn, (long) errno, strerror(errno));
+	}
+
+	buf = (char *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
+	for (off = 0; off < len;) {
+		size_t got;
+		got = fread((void *) (buf + off), 1, len - off, f);
+		if (ferror(f)) {
+			(void) fclose(f);
+			duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while reading %s", fn);
+		}
+		if (got == 0) {
+			if (feof(f)) {
+				break;
+			} else {
+				(void) fclose(f);
+				duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while reading %s", fn);
+			}
+		}
+		off += got;
+	}
+
+	if (f) {
+		(void) fclose(f);
+	}
+
+	return 1;
+}
+
+static duk_ret_t fileio_write_file(duk_context *ctx) {
+	const char *fn;
+	const char *buf;
+	size_t len;
+	size_t off;
+	FILE *f;
+
+	fn = duk_require_string(ctx, 0);
+	f = fopen(fn, "wb");
+	if (!f) {
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "cannot open file %s for writing, errno %ld: %s",
+		          fn, (long) errno, strerror(errno));
+	}
+
+	len = 0;
+	buf = (char *) duk_to_buffer(ctx, 1, &len);
+	for (off = 0; off < len;) {
+		size_t got;
+		got = fwrite((const void *) (buf + off), 1, len - off, f);
+		if (ferror(f)) {
+			(void) fclose(f);
+			duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while writing %s", fn);
+		}
+		if (got == 0) {
+			(void) fclose(f);
+			duk_error(ctx, DUK_ERR_TYPE_ERROR, "error while writing %s", fn);
+		}
+		off += got;
+	}
+
+	if (f) {
+		(void) fclose(f);
+	}
+
+	return 0;
+}
+#endif  /* DUK_CMDLINE_FILEIO */
+
+/*
+ *  Duktape heap lifecycle
+ */
+
+#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
+static duk_idx_t debugger_request(duk_context *ctx, void *udata, duk_idx_t nvalues) {
+	const char *cmd;
+	int i;
+
+	(void) udata;
+
+	if (nvalues < 1) {
+		duk_push_string(ctx, "missing AppRequest argument(s)");
+		return -1;
+	}
+
+	cmd = duk_get_string(ctx, -nvalues + 0);
+
+	if (cmd && strcmp(cmd, "CommandLine") == 0) {
+		if (!duk_check_stack(ctx, main_argc)) {
+			/* Callback should avoid errors for now, so use
+			 * duk_check_stack() rather than duk_require_stack().
+			 */
+			duk_push_string(ctx, "failed to extend stack");
+			return -1;
+		}
+		for (i = 0; i < main_argc; i++) {
+			duk_push_string(ctx, main_argv[i]);
+		}
+		return main_argc;
+	}
+	duk_push_sprintf(ctx, "command not supported");
+	return -1;
+}
+
+static void debugger_detached(void *udata) {
+	duk_context *ctx = (duk_context *) udata;
+	(void) ctx;
+	fprintf(stderr, "Debugger detached, udata: %p\n", (void *) udata);
+	fflush(stderr);
+
+	/* Ensure socket is closed even when detach is initiated by Duktape
+	 * rather than debug client.
+	 */
+        duk_trans_socket_finish();
+
+	if (debugger_reattach) {
+		/* For automatic reattach testing. */
+		duk_trans_socket_init();
+		duk_trans_socket_waitconn();
+		fprintf(stderr, "Debugger reconnected, call duk_debugger_attach()\n");
+		fflush(stderr);
+#if 0
+		/* This is not necessary but should be harmless. */
+		duk_debugger_detach(ctx);
+#endif
+		duk_debugger_attach_custom(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_request,
+		                           debugger_detached,
+		                           (void *) ctx);
+	}
+}
+#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, int ajsheap_log) {
+	duk_context *ctx;
+
+	(void) ajsheap_log;  /* suppress warning */
+
+	ctx = NULL;
+	if (!ctx && alloc_provider == ALLOC_LOGGING) {
+#if defined(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) {
+#if defined(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) {
+#if defined(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) {
+#if defined(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);
+	}
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		fprintf(stdout, "Pool dump after heap creation\n");
+		ajsheap_dump();
+	}
+#endif
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		ajsheap_register(ctx);
+	}
+#endif
+
+#if defined(DUK_CMDLINE_FILEIO)
+	duk_push_c_function(ctx, fileio_read_file, 1 /*nargs*/);
+	duk_put_global_string(ctx, "readFile");
+	duk_push_c_function(ctx, fileio_write_file, 2 /*nargs*/);
+	duk_put_global_string(ctx, "writeFile");
+#endif
+
+	if (debugger) {
+#if defined(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_custom(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_request,
+		                           debugger_detached,
+		                           (void *) ctx);
+#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;
+
+#if defined(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);
+	}
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		fprintf(stdout, "Pool dump after duk_destroy_heap() (should have zero allocs)\n");
+		ajsheap_dump();
+	}
+	ajsheap_free();
+#endif
+}
+
+/*
+ *  Main
+ */
+
+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 no_heap_destroy = 0;
+	int verbose = 0;
+	int run_stdin = 0;
+	const char *compile_filename = NULL;
+	int i;
+
+	main_argc = argc;
+	main_argv = (char **) argv;
+
+#if defined(EMSCRIPTEN)
+	/* Try to use NODEFS to provide access to local files.  Mount the
+	 * CWD as /working, and then prepend "/working/" to relative native
+	 * paths in file calls to get something that works reasonably for
+	 * relative paths.  Emscripten doesn't support replacing virtual
+	 * "/" with host "/" (the default MEMFS at "/" can't be unmounted)
+	 * but we can mount "/tmp" as host "/tmp" to allow testcase runs.
+	 *
+	 * https://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.html#filesystem-api-nodefs
+	 * https://github.com/kripken/emscripten/blob/master/tests/fs/test_nodefs_rw.c
+	 */
+	EM_ASM(
+		/* At the moment it's not possible to replace the default MEMFS mounted at '/':
+		 * https://github.com/kripken/emscripten/issues/2040
+		 * https://github.com/kripken/emscripten/blob/incoming/src/library_fs.js#L1341-L1358
+		 */
+		/*
+		try {
+			FS.unmount("/");
+		} catch (e) {
+			console.log("Failed to unmount default '/' MEMFS mount: " + e);
+		}
+		*/
+		try {
+			FS.mkdir("/working");
+			FS.mount(NODEFS, { root: "." }, "/working");
+		} catch (e) {
+			console.log("Failed to mount NODEFS /working: " + e);
+		}
+		/* A virtual '/tmp' exists by default:
+		 * https://gist.github.com/evanw/e6be28094f34451bd5bd#file-temp-js-L3806-L3809
+		 */
+		/*
+		try {
+			FS.mkdir("/tmp");
+		} catch (e) {
+			console.log("Failed to create virtual /tmp: " + e);
+		}
+		*/
+		try {
+			FS.mount(NODEFS, { root: "/tmp" }, "/tmp");
+		} catch (e) {
+			console.log("Failed to mount NODEFS /tmp: " + e);
+		}
+	);
+#endif  /* EMSCRIPTEN */
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	alloc_provider = ALLOC_AJSHEAP;
+#endif
+	(void) ajsheap_log;
+
+	/*
+	 *  Signal handling setup
+	 */
+
+#if defined(DUK_CMDLINE_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;
+#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
+		} else if (strcmp(arg, "--reattach") == 0) {
+			debugger_reattach = 1;
+#endif
+		} else if (strcmp(arg, "--recreate-heap") == 0) {
+			recreate_heap = 1;
+		} else if (strcmp(arg, "--no-heap-destroy") == 0) {
+			no_heap_destroy = 1;
+		} else if (strcmp(arg, "--verbose") == 0) {
+			verbose = 1;
+		} else if (strcmp(arg, "--run-stdin") == 0) {
+			run_stdin = 1;
+		} else if (strlen(arg) >= 1 && arg[0] == '-') {
+			goto usage;
+		} else {
+			have_files = 1;
+		}
+	}
+	if (!have_files && !have_eval && !run_stdin) {
+		interactive = 1;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+#if defined(DUK_CMDLINE_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, ajsheap_log);
+
+	/*
+	 *  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, ajsheap_log);
+		}
+	}
+
+	if (run_stdin) {
+		/* Running stdin like a full file (reading all lines before
+		 * compiling) is useful with emduk:
+		 * cat test.js | ./emduk --run-stdin
+		 */
+		if (handle_fh(ctx, stdin, "stdin", 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, ajsheap_log);
+		}
+	}
+
+	/*
+	 *  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 && no_heap_destroy) {
+		duk_gc(ctx, 0);
+	}
+	if (ctx && !no_heap_destroy) {
+		destroy_duktape_heap(ctx, alloc_provider);
+	}
+	ctx = NULL;
+
+	return retval;
+
+	/*
+	 *  Usage
+	 */
+
+ usage:
+	fprintf(stderr, "Usage: duk [options] [<filenames>]\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"
+			"   --run-stdin        treat stdin like a file, i.e. compile full input (not line by line)\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"
+#if defined(DUK_CMDLINE_ALLOC_LOGGING)
+	                "   --alloc-logging    use logging allocator (writes to /tmp)\n"
+#endif
+#if defined(DUK_CMDLINE_ALLOC_TORTURE)
+	                "   --alloc-torture    use torture allocator\n"
+#endif
+#if defined(DUK_CMDLINE_ALLOC_HYBRID)
+	                "   --alloc-hybrid     use hybrid allocator\n"
+#endif
+#if defined(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
+#if defined(DUK_CMDLINE_DEBUGGER_SUPPORT)
+			"   --debugger         start example debugger\n"
+			"   --reattach         automatically reattach debugger on detach\n"
+#endif
+			"   --recreate-heap    recreate heap after every file\n"
+			"   --no-heap-destroy  force GC, but don't destroy heap at end (leak testing)\n"
+	                "\n"
+	                "If <filename> is omitted, interactive mode is started automatically.\n");
+	fflush(stderr);
+	exit(1);
+}

+ 1008 - 0
src/third_party/duktape-1.5.2/examples/cmdline/duk_cmdline_ajduk.c

@@ -0,0 +1,1008 @@
+/*
+ *  'ajduk' specific functionality, examples for low memory techniques
+ */
+
+#ifdef DUK_CMDLINE_AJSHEAP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "ajs.h"
+#include "ajs_heap.h"
+#include "duktape.h"
+
+extern uint8_t dbgHEAPDUMP;
+
+#if defined(DUK_USE_ROM_OBJECTS) && defined(DUK_USE_HEAPPTR16)
+/* Pointer compression with ROM strings/objects:
+ *
+ * For now, use DUK_USE_ROM_OBJECTS to signal the need for compressed ROM
+ * pointers.  DUK_USE_ROM_PTRCOMP_FIRST is provided for the ROM pointer
+ * compression range minimum to avoid duplication in user code.
+ */
+#if 0  /* This extern declaration is provided by duktape.h, array provided by duktape.c. */
+extern const void * const duk_rom_compressed_pointers[];
+#endif
+static const void *duk__romptr_low = NULL;
+static const void *duk__romptr_high = NULL;
+#define DUK__ROMPTR_COMPRESSION
+#define DUK__ROMPTR_FIRST DUK_USE_ROM_PTRCOMP_FIRST
+#endif
+
+/*
+ *  Helpers
+ */
+
+static void *ajduk__lose_const(const void *ptr) {
+	/* Somewhat portable way of losing a const without warnings.
+	 * Another approach is to cast through intptr_t, but that
+	 * type is not always available.
+	 */
+	union {
+		const void *p;
+		void *q;
+	} u;
+	u.p = ptr;
+	return u.q;
+}
+
+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,     600,  AJS_POOL_BORROW,  0 },
+	{ 16,     300,  AJS_POOL_BORROW,  0 },
+	{ 20,     300,  AJS_POOL_BORROW,  0 },
+	{ 24,     300,  AJS_POOL_BORROW,  0 },
+	{ 28,     150,  AJS_POOL_BORROW,  0 },
+	{ 32,     150,  AJS_POOL_BORROW,  0 },
+	{ 40,     150,  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 },
+	{ 320,    1,    AJS_POOL_BORROW,  0 },
+	{ 392,    1,    AJS_POOL_BORROW,  0 },  /* duk_hthread, with heap ptr compression, ROM strings+objects */
+	{ 512,    16,   AJS_POOL_BORROW,  0 },
+	{ 964,    1,    AJS_POOL_BORROW,  0 },  /* duk_heap, with heap ptr compression, ROM strings+objects */
+	{ 1024,   6,    AJS_POOL_BORROW,  0 },
+	{ 1344,   1,    AJS_POOL_BORROW,  0 },  /* duk_heap, with heap ptr compression, RAM strings+objects */
+	{ 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;
+
+#if defined(DUK__ROMPTR_COMPRESSION)
+	/* Scan ROM pointer range for faster detection of "is 'p' a ROM pointer"
+	 * later on.
+	 */
+	if (1) {
+		const void * const * ptrs = (const void * const *) duk_rom_compressed_pointers;
+		duk__romptr_low = duk__romptr_high = (const void *) *ptrs;
+		while (*ptrs) {
+			if (*ptrs > duk__romptr_high) {
+				duk__romptr_high = (const void *) *ptrs;
+			}
+			if (*ptrs < duk__romptr_low) {
+				duk__romptr_low = (const void *) *ptrs;
+			}
+			ptrs++;
+		}
+		fprintf(stderr, "romptrs: low=%p high=%p\n",
+		        (const void *) duk__romptr_low, (const void *) duk__romptr_high);
+		fflush(stderr);
+	}
+#endif
+}
+
+void ajsheap_free(void) {
+	if (ajsheap_ram != NULL) {
+		free(ajsheap_ram);
+		ajsheap_ram = NULL;
+	}
+}
+
+/* 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;
+
+#if defined(DUK__ROMPTR_COMPRESSION)
+	if (p >= duk__romptr_low && p <= duk__romptr_high) {
+		/* The if-condition should be the fastest possible check
+		 * for "is 'p' in ROM?".  If pointer is in ROM, we'd like
+		 * to compress it quickly.  Here we just scan a ~1K array
+		 * which is very bad for performance and for illustration
+		 * only.
+		 */
+		const void * const * ptrs = duk_rom_compressed_pointers;
+		while (*ptrs) {
+			if (*ptrs == p) {
+				ret = DUK__ROMPTR_FIRST + (ptrs - duk_rom_compressed_pointers);
+#if 0
+				fprintf(stderr, "ajsheap_enc16: rom pointer: %p -> 0x%04lx\n", (void *) p, (long) ret);
+				fflush(stderr);
+#endif
+				return (duk_uint16_t) ret;
+			}
+			ptrs++;
+		}
+
+		/* We should really never be here: Duktape should only be
+		 * compressing pointers which are in the ROM compressed
+		 * pointers list, which are known at 'make dist' time.
+		 * We go on, causing a pointer compression error.
+		 */
+		fprintf(stderr, "ajsheap_enc16: rom pointer: %p could not be compressed, should never happen\n", (void *) p);
+		fflush(stderr);
+	}
+#endif
+
+	/* 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: %p (ret was %ld)\n", (void *) p, (long) ret);
+		fflush(stderr);
+		abort();
+	}
+#if defined(DUK__ROMPTR_COMPRESSION)
+	if (ret >= DUK__ROMPTR_FIRST) {
+		fprintf(stderr, "Failed to compress pointer, in 16-bit range but matches romptr range: %p (ret was %ld)\n", (void *) p, (long) ret);
+		fflush(stderr);
+		abort();
+	}
+#endif
+	return (duk_uint16_t) ret;
+}
+
+void *ajsheap_dec16(void *ud, duk_uint16_t x) {
+	void *ret;
+	char *base = (char *) ajsheap_ram - 4;
+
+#if defined(DUK__ROMPTR_COMPRESSION)
+	if (x >= DUK__ROMPTR_FIRST) {
+		/* This is a blind lookup, could check index validity.
+		 * Duktape should never decompress a pointer which would
+		 * be out-of-bounds here.
+		 */
+		ret = (void *) ajduk__lose_const(duk_rom_compressed_pointers[x - DUK__ROMPTR_FIRST]);
+#if 0
+		fprintf(stderr, "ajsheap_dec16: rom pointer: 0x%04lx -> %p\n", (long) x, ret);
+		fflush(stderr);
+#endif
+		return ret;
+	}
+#endif
+
+	/* 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 *) ajduk__lose_const(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 *) ajduk__lose_const(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 */

+ 8 - 0
src/third_party/duktape-1.5.2/examples/codepage-conv/README.rst

@@ -0,0 +1,8 @@
+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.

+ 54 - 0
src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.c

@@ -0,0 +1,54 @@
+/*
+ *  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);
+}

+ 8 - 0
src/third_party/duktape-1.5.2/examples/codepage-conv/duk_codepage_conv.h

@@ -0,0 +1,8 @@
+#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 */

+ 286 - 0
src/third_party/duktape-1.5.2/examples/codepage-conv/test.c

@@ -0,0 +1,286 @@
+#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;
+}

+ 10 - 0
src/third_party/duktape-1.5.2/examples/coffee/README.rst

@@ -0,0 +1,10 @@
+=====================
+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

+ 7 - 0
src/third_party/duktape-1.5.2/examples/coffee/globals.coffee

@@ -0,0 +1,7 @@
+
+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
+

+ 2 - 0
src/third_party/duktape-1.5.2/examples/coffee/hello.coffee

@@ -0,0 +1,2 @@
+print 'Hello world!'
+print 'version: ' + Duktape.version

+ 28 - 0
src/third_party/duktape-1.5.2/examples/coffee/mandel.coffee

@@ -0,0 +1,28 @@
+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)
+

+ 29 - 0
src/third_party/duktape-1.5.2/examples/cpp-exceptions/README.rst

@@ -0,0 +1,29 @@
+=========================================
+C++ exceptions for long control transfers
+=========================================
+
+Normally Duktape uses ``setjmp()`` / ``longjmp()`` or their variants for
+internal long control transfers.  One downside of these functions is that
+C++ automatic destructors (scope-based resource management, SBRM, a special
+case of RAII) in Duktape/C functions won't be executed which is awkward for
+C++ programmers.
+
+When ``DUK_USE_CPP_EXCEPTIONS`` (``DUK_OPT_CPP_EXCEPTIONS``) is defined, and
+both Duktape and application code is compiled using a C++ compiler, Duktape
+uses C++ ``try-catch`` and ``throw`` for internal long control transfers.
+This allows automatic destructors to run as expected.  The config option is
+not enabled by default because C++ exceptions are sometimes disabled even
+when a C++ compiler is used (e.g. for performance reasons).
+
+The ``cpp_exceptions.cpp`` example illustrates how C++ exceptions can be
+used in Duktape/C functions at the moment:
+
+* Duktape uses C++ try/catch/throw internally; this is not visible to user
+  code directly.
+
+* Automatic destructors (scope-based resource management) work as expected.
+
+* C++ exceptions can be used in Duktape/C functions normally, but user
+  exceptions must be caught before they reach Duktape.  If this is not
+  done, such exceptions are caught by Duktape and converted to API errors
+  (in other words, they won't propagate "through" Duktape at the moment).

+ 274 - 0
src/third_party/duktape-1.5.2/examples/cpp-exceptions/cpp_exceptions.cpp

@@ -0,0 +1,274 @@
+/*
+ *  Example of how to use DUK_USE_CPP_EXCEPTIONS to support automatic
+ *  variables (e.g. destructor calls) in Duktape/C functions.
+ *
+ *  Compile with -DDUK_OPT_CPP_EXCEPTIONS:
+ *
+ *    $ g++ -otest -DDUK_OPT_CPP_EXCEPTIONS -I<duktape_dist>/src/ \
+ *      <duktape_dist>/src/duktape.c cpp_exceptions.cpp -lm
+ *
+ *  or ensure duk_config.h has DUK_USE_CPP_EXCEPTIONS enabled using
+ *  genconfig.  When executed you should see something like:
+ *
+ *    $ ./test
+ *    my_class instance created
+ *    my_class instance destroyed      <== destructor gets called
+ *    --> rc=1 (SyntaxError: parse error (line 1))
+ *    [...]
+ *
+ *  Duktape uses a custom exception class (duk_internal_exception) which
+ *  doesn't inherit from any base class, so that catching any base classes
+ *  in user code won't accidentally catch exceptions thrown by Duktape.
+ */
+
+#if !defined(__cplusplus)
+#error compile using a c++ compiler
+#endif
+
+#include <stdio.h>
+#include <exception>
+#include "duktape.h"
+
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT throw()
+#endif
+
+/*
+ *  Example class with a destructor
+ */
+
+class my_class {
+ public:
+	my_class();
+	~my_class();
+};
+
+my_class::my_class() {
+	printf("my_class instance created\n");
+}
+
+my_class::~my_class() {
+	printf("my_class instance destroyed\n");
+}
+
+/*
+ *  SyntaxError caused by eval exits Duktape/C function but destructors
+ *  are executed.
+ */
+
+duk_ret_t test1(duk_context *ctx) {
+	my_class myclass;
+
+	duk_eval_string(ctx, "aiee=");
+
+	return 0;
+}
+
+/*
+ *  You can use C++ exceptions inside Duktape/C functions for your own
+ *  purposes but you should catch them before they propagate to Duktape.
+ */
+
+duk_ret_t test2(duk_context *ctx) {
+	my_class myclass;
+
+	try {
+		throw 123;
+	} catch (int myvalue) {
+		printf("Caught: %d\n", myvalue);
+	}
+
+	return 0;
+}
+
+/*
+ *  If you let your own C++ exceptions propagate out of a Duktape/C function
+ *  it will be caught by Duktape and considered a programming error.  Duktape
+ *  will catch the exception and convert it to a Duktape error.
+ *
+ *  This may be allowed in a later version once all the implications have been
+ *  worked out.
+ */
+
+duk_ret_t test3(duk_context *ctx) {
+	my_class myclass;
+
+	throw 123;  /* ERROR: exception propagated to Duktape */
+
+	return 0;
+}
+
+/*
+ *  Same as above, but if the exception inherits from std::exception, it's
+ *  "what()" will be included in the error message.
+ */
+
+class my_exception : public std::exception {
+	virtual const char *what() const NOEXCEPT {
+		return "my_exception";
+	}
+};
+
+duk_ret_t test4(duk_context *ctx) {
+	my_class myclass;
+	my_exception myexc;
+
+	throw myexc;  /* ERROR: exception propagated to Duktape */
+
+	return 0;
+}
+
+/*
+ *  Same as above, but if the exception inherits from std::exception with
+ *  a NULL what().  Duktape will describe the error as 'unknown' if so.
+ */
+
+class my_exception2 : public std::exception {
+	virtual const char *what() const NOEXCEPT {
+		return NULL;
+	}
+};
+
+duk_ret_t test5(duk_context *ctx) {
+	my_class myclass;
+	my_exception2 myexc;
+
+	throw myexc;  /* ERROR: exception propagated to Duktape */
+
+	return 0;
+}
+
+int main(int argc, char *argv[]) {
+	duk_context *ctx = duk_create_heap_default();
+	duk_int_t rc;
+
+	(void) argc; (void) argv;  /* suppress warning */
+
+	printf("*** test1 - duk_pcall()\n");
+	duk_push_c_function(ctx, test1, 0);
+	rc = duk_pcall(ctx, 0);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test1 - duk_safe_call()\n");
+	rc = duk_safe_call(ctx, test1, 0, 1);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test1 - ecmascript try-catch\n");
+	duk_push_c_function(ctx, test1, 0);
+	duk_put_global_string(ctx, "test1");
+	duk_eval_string_noresult(ctx,
+		"try {\n"
+		"    test1();\n"
+		"} catch (e) {\n"
+		"    print(e.stack || e);\n"
+		"}\n");
+	printf("\n");
+
+	printf("*** test2 - duk_pcall()\n");
+	duk_push_c_function(ctx, test2, 0);
+	rc = duk_pcall(ctx, 0);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test2 - duk_safe_call()\n");
+	rc = duk_safe_call(ctx, test2, 0, 1);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test2 - ecmascript try-catch\n");
+	duk_push_c_function(ctx, test2, 0);
+	duk_put_global_string(ctx, "test2");
+	duk_eval_string_noresult(ctx,
+		"try {\n"
+		"    test2();\n"
+		"} catch (e) {\n"
+		"    print(e.stack || e);\n"
+		"}\n");
+	printf("\n");
+
+	printf("*** test3 - duk_pcall()\n");
+	duk_push_c_function(ctx, test3, 0);
+	rc = duk_pcall(ctx, 0);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test3 - duk_safe_call()\n");
+	rc = duk_safe_call(ctx, test3, 0, 1);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test3 - ecmascript try-catch\n");
+	duk_push_c_function(ctx, test3, 0);
+	duk_put_global_string(ctx, "test3");
+	duk_eval_string_noresult(ctx,
+		"try {\n"
+		"    test3();\n"
+		"} catch (e) {\n"
+		"    print(e.stack || e);\n"
+		"}\n");
+	printf("\n");
+
+	printf("*** test4 - duk_pcall()\n");
+	duk_push_c_function(ctx, test4, 0);
+	rc = duk_pcall(ctx, 0);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test4 - duk_safe_call()\n");
+	rc = duk_safe_call(ctx, test4, 0, 1);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test4 - ecmascript try-catch\n");
+	duk_push_c_function(ctx, test4, 0);
+	duk_put_global_string(ctx, "test4");
+	duk_eval_string_noresult(ctx,
+		"try {\n"
+		"    test4();\n"
+		"} catch (e) {\n"
+		"    print(e.stack || e);\n"
+		"}\n");
+	printf("\n");
+
+	printf("*** test5 - duk_pcall()\n");
+	duk_push_c_function(ctx, test5, 0);
+	rc = duk_pcall(ctx, 0);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test5 - duk_safe_call()\n");
+	rc = duk_safe_call(ctx, test5, 0, 1);
+	printf("--> rc=%ld (%s)\n", (long) rc, duk_safe_to_string(ctx, -1));
+	duk_pop(ctx);
+	printf("\n");
+
+	printf("*** test5 - ecmascript try-catch\n");
+	duk_push_c_function(ctx, test5, 0);
+	duk_put_global_string(ctx, "test5");
+	duk_eval_string_noresult(ctx,
+		"try {\n"
+		"    test5();\n"
+		"} catch (e) {\n"
+		"    print(e.stack || e);\n"
+		"}\n");
+	printf("\n");
+
+	printf("*** done\n");
+
+	duk_destroy_heap(ctx);
+
+	return 0;
+}

+ 17 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/Makefile

@@ -0,0 +1,17 @@
+# 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

+ 8 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/README.rst

@@ -0,0 +1,8 @@
+===========================================================
+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.

+ 1239 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.c

@@ -0,0 +1,1239 @@
+/*
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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);
+}

+ 113 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/duk_trans_dvalue.h

@@ -0,0 +1,113 @@
+#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 */

+ 236 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-dvalue/test.c

@@ -0,0 +1,236 @@
+/*
+ *  Example program using the dvalue debug transport.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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;
+}

+ 17 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-socket/README.rst

@@ -0,0 +1,17 @@
+================================================
+Debug transport using a simple socket connection
+================================================
+
+This example implements an example debug transport which uses a Linux or
+Windows TCP server socket on the debug target.
+
+Files:
+
+* ``duk_trans_socket.h``: header file for the transport, used for both Linux
+  and Windows socket variants.
+
+* ``duk_trans_socket_unix.c``: implementation for Linux/Unix.
+
+* ``duk_trans_socket_windows.c``: implementation for Windows.
+
+Compile either Unix or Windows source file only.

+ 15 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket.h

@@ -0,0 +1,15 @@
+#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_finish(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 */

+ 340 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_unix.c

@@ -0,0 +1,340 @@
+/*
+ *  Example debug transport using a Linux/Unix TCP socket
+ *
+ *  Provides a TCP server socket which a debug client can connect to.
+ *  After that data is just passed through.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <poll.h>
+#include <errno.h>
+#include "duktape.h"
+
+#if !defined(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 and finish
+ */
+
+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_finish(void) {
+	if (client_sock >= 0) {
+		(void) close(client_sock);
+		client_sock = -1;
+	}
+	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: (possibly 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, closing connection: %s\n",
+		        __FILE__, 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: (possibly 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, (const 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
+
+	if (client_sock < 0) {
+		return 0;
+	}
+
+	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) {
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	/* 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) {
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	/* 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;
+}

+ 414 - 0
src/third_party/duktape-1.5.2/examples/debug-trans-socket/duk_trans_socket_windows.c

@@ -0,0 +1,414 @@
+/*
+ *  Example debug transport using a Windows TCP socket
+ *
+ *  Provides a TCP server socket which a debug client can connect to.
+ *  After that data is just passed through.
+ *
+ *  https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx
+ *
+ *  Compiling 'duk' with debugger support using MSVC (Visual Studio):
+ *
+ *    > cl /W3 /O2 /Feduk.exe
+ *          /DDUK_OPT_DEBUGGER_SUPPORT /DDUK_OPT_INTERRUPT_COUNTER
+ *          /DDUK_CMDLINE_DEBUGGER_SUPPORT
+ *          /Iexamples\debug-trans-socket /Isrc
+ *          examples\cmdline\duk_cmdline.c
+ *          examples\debug-trans-socket\duk_trans_socket_windows.c
+ *          src\duktape.c
+ *
+ *  With MinGW:
+ *
+ *    $ gcc -oduk.exe -Wall -O2 \
+ *          -DDUK_OPT_DEBUGGER_SUPPORT -DDUK_OPT_INTERRUPT_COUNTER \
+ *          -DDUK_CMDLINE_DEBUGGER_SUPPORT \
+ *          -Iexamples/debug-trans-socket -Isrc \
+ *          examples/cmdline/duk_cmdline.c \
+ *          examples/debug-trans-socket/duk_trans_socket_windows.c \
+ *          src/duktape.c -lm -lws2_32
+ */
+
+#undef UNICODE
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+/* MinGW workaround for missing getaddrinfo() etc:
+ * http://programmingrants.blogspot.fi/2009/09/tips-on-undefined-reference-to.html
+ */
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0501
+#endif
+#endif
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stdio.h>
+#include <string.h>
+#include "duktape.h"
+
+#if defined(_MSC_VER)
+#pragma comment (lib, "Ws2_32.lib")
+#endif
+
+#if !defined(DUK_DEBUG_PORT)
+#define DUK_DEBUG_PORT 9091
+#endif
+#if !defined(DUK_DEBUG_ADDRESS)
+#define DUK_DEBUG_ADDRESS "0.0.0.0"
+#endif
+#define DUK__STRINGIFY_HELPER(x) #x
+#define DUK__STRINGIFY(x) DUK__STRINGIFY_HELPER(x)
+
+#if 0
+#define DEBUG_PRINTS
+#endif
+
+static SOCKET server_sock = INVALID_SOCKET;
+static SOCKET client_sock = INVALID_SOCKET;
+static int wsa_inited = 0;
+
+/*
+ *  Transport init and finish
+ */
+
+void duk_trans_socket_init(void) {
+	WSADATA wsa_data;
+	struct addrinfo hints;
+	struct addrinfo *result = NULL;
+	int rc;
+
+	memset((void *) &wsa_data, 0, sizeof(wsa_data));
+	memset((void *) &hints, 0, sizeof(hints));
+
+	rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
+	if (rc != 0) {
+		fprintf(stderr, "%s: WSAStartup() failed: %d\n", __FILE__, rc);
+		fflush(stderr);
+		goto fail;
+	}
+	wsa_inited = 1;
+
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
+	hints.ai_flags = AI_PASSIVE;
+
+	rc = getaddrinfo(DUK_DEBUG_ADDRESS, DUK__STRINGIFY(DUK_DEBUG_PORT), &hints, &result);
+	if (rc != 0) {
+		fprintf(stderr, "%s: getaddrinfo() failed: %d\n", __FILE__, rc);
+		fflush(stderr);
+		goto fail;
+	}
+
+	server_sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
+	if (server_sock == INVALID_SOCKET) {
+		fprintf(stderr, "%s: socket() failed with error: %ld\n",
+		        __FILE__, (long) WSAGetLastError());
+		fflush(stderr);
+		goto fail;
+	}
+
+	rc = bind(server_sock, result->ai_addr, (int) result->ai_addrlen);
+	if (rc == SOCKET_ERROR) {
+		fprintf(stderr, "%s: bind() failed with error: %ld\n",
+		        __FILE__, (long) WSAGetLastError());
+		fflush(stderr);
+		goto fail;
+	}
+
+	rc = listen(server_sock, SOMAXCONN);
+	if (rc == SOCKET_ERROR) {
+		fprintf(stderr, "%s: listen() failed with error: %ld\n",
+		        __FILE__, (long) WSAGetLastError());
+		fflush(stderr);
+		goto fail;
+	}
+
+	if (result != NULL) {
+		freeaddrinfo(result);
+		result = NULL;
+	}
+	return;
+
+ fail:
+	if (result != NULL) {
+		freeaddrinfo(result);
+		result = NULL;
+	}
+	if (server_sock != INVALID_SOCKET) {
+		(void) closesocket(server_sock);
+		server_sock = INVALID_SOCKET;
+	}
+	if (wsa_inited) {
+		WSACleanup();
+		wsa_inited = 0;
+	}
+}
+
+void duk_trans_socket_finish(void) {
+	if (client_sock != INVALID_SOCKET) {
+		(void) closesocket(client_sock);
+		client_sock = INVALID_SOCKET;
+	}
+	if (server_sock != INVALID_SOCKET) {
+		(void) closesocket(server_sock);
+		server_sock = INVALID_SOCKET;
+	}
+	if (wsa_inited) {
+		WSACleanup();
+		wsa_inited = 0;
+	}
+}
+
+void duk_trans_socket_waitconn(void) {
+	if (server_sock == INVALID_SOCKET) {
+		fprintf(stderr, "%s: no server socket, skip waiting for connection\n",
+		        __FILE__);
+		fflush(stderr);
+		return;
+	}
+	if (client_sock != INVALID_SOCKET) {
+		(void) closesocket(client_sock);
+		client_sock = INVALID_SOCKET;
+	}
+
+	fprintf(stderr, "Waiting for debug connection on port %d\n", (int) DUK_DEBUG_PORT);
+	fflush(stderr);
+
+	client_sock = accept(server_sock, NULL, NULL);
+	if (client_sock == INVALID_SOCKET) {
+		fprintf(stderr, "%s: accept() failed with error %ld, skip waiting for connection\n",
+		        __FILE__, (long) WSAGetLastError());
+		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 != INVALID_SOCKET) {
+		(void) closesocket(server_sock);
+		server_sock = INVALID_SOCKET;
+	}
+	return;
+
+ fail:
+	if (client_sock != INVALID_SOCKET) {
+		(void) closesocket(client_sock);
+		client_sock = INVALID_SOCKET;
+	}
+}
+
+/*
+ *  Duktape callbacks
+ */
+
+/* Duktape debug transport callback: (possibly partial) read. */
+duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length) {
+	int ret;
+
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n",
+	        __FUNCTION__, (void *) udata, (void *) buffer, (long) length);
+	fflush(stderr);
+#endif
+
+	if (client_sock == INVALID_SOCKET) {
+		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 = recv(client_sock, (void *) buffer, (int) length, 0);
+	if (ret < 0) {
+		fprintf(stderr, "%s: debug read failed, error %d, closing connection\n",
+		        __FILE__, ret);
+		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 > (int) 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 != INVALID_SOCKET) {
+		(void) closesocket(client_sock);
+		client_sock = INVALID_SOCKET;
+	}
+	return 0;
+}
+
+/* Duktape debug transport callback: (possibly partial) write. */
+duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length) {
+	int ret;
+
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n",
+	        __FUNCTION__, (void *) udata, (const void *) buffer, (long) length);
+	fflush(stderr);
+#endif
+
+	if (client_sock == INVALID_SOCKET) {
+		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 = send(client_sock, (const void *) buffer, (int) length, 0);
+	if (ret <= 0 || ret > (int) length) {
+		fprintf(stderr, "%s: debug write failed, ret %d, closing connection\n",
+		        __FILE__, ret);
+		fflush(stderr);
+		goto fail;
+	}
+
+	return (duk_size_t) ret;
+
+ fail:
+	if (client_sock != INVALID_SOCKET) {
+		(void) closesocket(INVALID_SOCKET);
+		client_sock = INVALID_SOCKET;
+	}
+	return 0;
+}
+
+duk_size_t duk_trans_socket_peek_cb(void *udata) {
+	u_long avail;
+	int rc;
+
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __FUNCTION__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	if (client_sock == INVALID_SOCKET) {
+		return 0;
+	}
+
+	avail = 0;
+	rc = ioctlsocket(client_sock, FIONREAD, &avail);
+	if (rc != 0) {
+		fprintf(stderr, "%s: ioctlsocket() returned %d, closing connection\n",
+		        __FILE__, rc);
+		fflush(stderr);
+		goto fail;  /* also returns 0, which is correct */
+	} else {
+		if (avail == 0) {
+			return 0;  /* nothing to read */
+		} else {
+			return 1;  /* something to read */
+		}
+	}
+	/* never here */
+
+ fail:
+	if (client_sock != INVALID_SOCKET) {
+		(void) closesocket(client_sock);
+		client_sock = INVALID_SOCKET;
+	}
+	return 0;
+}
+
+void duk_trans_socket_read_flush_cb(void *udata) {
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __FUNCTION__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	/* 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) {
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __FUNCTION__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	/* 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;
+}
+
+#undef DUK__STRINGIFY_HELPER
+#undef DUK__STRINGIFY

+ 5 - 0
src/third_party/duktape-1.5.2/examples/dummy-date-provider/README.rst

@@ -0,0 +1,5 @@
+====================================
+Dummy external Date provider example
+====================================
+
+This example implements a dummy, minimal external Date provider.

+ 27 - 0
src/third_party/duktape-1.5.2/examples/dummy-date-provider/dummy_date_provider.c

@@ -0,0 +1,27 @@
+/*
+ *  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;
+}

+ 5 - 0
src/third_party/duktape-1.5.2/examples/eval/README.rst

@@ -0,0 +1,5 @@
+============
+Eval example
+============
+
+Evaluate expressions from command line.

+ 48 - 0
src/third_party/duktape-1.5.2/examples/eval/eval.c

@@ -0,0 +1,48 @@
+/*
+ *  Very simple example program for evaluating expressions from
+ *  command line
+ */
+
+#include "duktape.h"
+#include <stdio.h>
+
+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 <expression> [<expression>] ...\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;
+}

+ 76 - 0
src/third_party/duktape-1.5.2/examples/eventloop/README.rst

@@ -0,0 +1,76 @@
+==================
+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.

+ 17 - 0
src/third_party/duktape-1.5.2/examples/eventloop/basic-test.js

@@ -0,0 +1,17 @@
+/*
+ *  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');
+

+ 618 - 0
src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.c

@@ -0,0 +1,618 @@
+/*
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <poll.h>
+
+#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 <stash>.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);
+}

+ 179 - 0
src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.js

@@ -0,0 +1,179 @@
+/*
+ *  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));
+}

+ 24 - 0
src/third_party/duktape-1.5.2/examples/eventloop/client-socket-test.js

@@ -0,0 +1,24 @@
+
+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");
+});
+

+ 79 - 0
src/third_party/duktape-1.5.2/examples/eventloop/curses-timers.js

@@ -0,0 +1,79 @@
+/*
+ *  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();

+ 466 - 0
src/third_party/duktape-1.5.2/examples/eventloop/ecma_eventloop.js

@@ -0,0 +1,466 @@
+/*
+ *  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();
+}

+ 69 - 0
src/third_party/duktape-1.5.2/examples/eventloop/fileio.c

@@ -0,0 +1,69 @@
+/*
+ *  File I/O binding example.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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);
+}

+ 256 - 0
src/third_party/duktape-1.5.2/examples/eventloop/main.c

@@ -0,0 +1,256 @@
+/*
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef NO_SIGNAL
+#include <signal.h>
+#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] <filename>\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 <filename> is '-', the entire STDIN executed.\n");
+	fflush(stderr);
+	exit(1);
+}

+ 105 - 0
src/third_party/duktape-1.5.2/examples/eventloop/ncurses.c

@@ -0,0 +1,105 @@
+/*
+ *  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 <curses.h>
+#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);
+}

+ 111 - 0
src/third_party/duktape-1.5.2/examples/eventloop/poll.c

@@ -0,0 +1,111 @@
+/*
+ *  C wrapper for poll().
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <poll.h>
+#include <time.h>
+
+#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);
+}

+ 34 - 0
src/third_party/duktape-1.5.2/examples/eventloop/server-socket-test.js

@@ -0,0 +1,34 @@
+
+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);
+    });
+});

+ 286 - 0
src/third_party/duktape-1.5.2/examples/eventloop/socket.c

@@ -0,0 +1,286 @@
+/*
+ *  TCP sockets binding example.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <time.h>
+
+#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);
+}

+ 5 - 0
src/third_party/duktape-1.5.2/examples/guide/README.rst

@@ -0,0 +1,5 @@
+===========================
+Duktape guide example files
+===========================
+
+Examples used in the Duktape guide.

+ 16 - 0
src/third_party/duktape-1.5.2/examples/guide/fib.js

@@ -0,0 +1,16 @@
+// 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();

+ 32 - 0
src/third_party/duktape-1.5.2/examples/guide/prime.js

@@ -0,0 +1,32 @@
+// 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(' '));
+}
+

+ 52 - 0
src/third_party/duktape-1.5.2/examples/guide/primecheck.c

@@ -0,0 +1,52 @@
+/* primecheck.c */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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);
+}

+ 12 - 0
src/third_party/duktape-1.5.2/examples/guide/process.js

@@ -0,0 +1,12 @@
+// 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 '<b>' + m + '</b>';
+         });
+}

+ 59 - 0
src/third_party/duktape-1.5.2/examples/guide/processlines.c

@@ -0,0 +1,59 @@
+/* processlines.c */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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);
+}

+ 42 - 0
src/third_party/duktape-1.5.2/examples/guide/uppercase.c

@@ -0,0 +1,42 @@
+/* uppercase.c */
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}

+ 5 - 0
src/third_party/duktape-1.5.2/examples/hello/README.rst

@@ -0,0 +1,5 @@
+===================
+Hello world example
+===================
+
+Very simple example, most useful for compilation tests.

+ 38 - 0
src/third_party/duktape-1.5.2/examples/hello/hello.c

@@ -0,0 +1,38 @@
+/*
+ *  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;
+}

+ 5 - 0
src/third_party/duktape-1.5.2/examples/jxpretty/README.rst

@@ -0,0 +1,5 @@
+================
+Jxpretty example
+================
+
+Simple command line utility to pretty print JSON in the JX format.

+ 63 - 0
src/third_party/duktape-1.5.2/examples/jxpretty/jxpretty.c

@@ -0,0 +1,63 @@
+/*
+ *  Pretty print JSON from stdin into indented JX.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}

+ 5 - 0
src/third_party/duktape-1.5.2/examples/sandbox/README.rst

@@ -0,0 +1,5 @@
+===============
+Sandbox example
+===============
+
+Very simple, minimal sandboxing example.

+ 252 - 0
src/third_party/duktape-1.5.2/examples/sandbox/sandbox.c

@@ -0,0 +1,252 @@
+/*
+ *  Sandboxing example
+ *
+ *  Uses custom memory allocation functions which keep track of total amount
+ *  of memory allocated, imposing a maximum total allocation size.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#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 <test.js>\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;
+}

+ 13 - 0
src/third_party/duktape-1.5.2/extras/README.rst

@@ -0,0 +1,13 @@
+==============
+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.

+ 3933 - 0
src/third_party/duktape-1.5.2/license.spdx

@@ -0,0 +1,3933 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rdf:RDF
+   xmlns:_3="http://spdx.org/rdf/terms#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+>
+  <rdf:Description rdf:nodeID="svBMzJkP376">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6f9134b7d1c939593043b9e0ecb308fbc745c9af</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP101">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP102"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/main.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP414">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>bd2f85dccd23b76b9cf9900b8b2b86f0bf97421b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP415">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP416"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_initjs_min.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP321">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP322"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_internal.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP292">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>b7ee0e88e6365390db594e5e1a90c383847cfd0f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP3">
+    <_3:created rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2016-12-08T20:32:53Z</_3:created>
+    <rdfs:comment></rdfs:comment>
+    <_3:licenseListVersion>1.20</_3:licenseListVersion>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#CreationInfo"/>
+    <_3:creator>Organization: duktape.org</_3:creator>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP79">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP80"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/coffee/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP275">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP276"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_stringtable.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP360">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d70b4083ccd3b5dac32ad07e58d3132dc3390b79</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP70">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f051b42ff42dc8655b9e17739f7cb7cb76bdf78d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP382">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>61db5ef1604240b33fa9e1e8825ad588076a5aef</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP365">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP366"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debug.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP208">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>52554f56c3e3420d3643aa22f563d32a2b18be1f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP323">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP324"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hbufferobject_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP441">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP442"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debug_fixedbuffer.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP32">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fb4f806e7282dd3cb2df04e228672d8b0b1b8eb4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP289">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP290"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP383">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP384"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_compile.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP468">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>422984e8fc919e9f8c64d5cc4b20d7f6d15e341b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP277">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP278"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_error_longjmp.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP258">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d0421b2e96d2365467764d4aecc442fe543d69ad</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP462">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>1db75c875cb94e1317f095e3d78f11275c17d154</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP137">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP138"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/cpp-exceptions/cpp_exceptions.cpp</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP180">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>23575db7cd88e42c0c3fc1630f44bf608fcec76d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP271">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP272"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_builtins.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP417">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP418"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_string.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP331">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP332"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_lexer.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP327">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP328"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_buffer.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP476">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>97bf0ab32255874def0bd3157bf4bb2fc731d37f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP147">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP148"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/process.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP388">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0811e545a133c3a62672e239624a0c1f11478b8d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP214">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>742d035afe3ae16b3498926494419b74c53dfaf4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP312">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>34b0dc439c1aeb920a1db0ac0ed20ee189069ea1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP439">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP440"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debug_heap.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP209">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP210"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_bufwriter.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP31">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP32"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.eval</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP408">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>221600498f2801d0bfc71e36009f084f363e159e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP443">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP444"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_alloc_default.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP374">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>bad7c737fdd2d5f21ac00c6936921184cd26908d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP246">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>21e33f2c348ab084c0869d3bba530b1885464f38</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP69">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP70"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/static/webui.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP349">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP350"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_object.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP279">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP280"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hstring.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP217">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP218"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_enum.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP436">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>525e80da2b6d3640fd42af0f662d7b68865d6529</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP370">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>84b33d737bba2dadfdd950adad7a96d3d88eb01d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP53">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP54"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/Makefile</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP105">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP106"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/ncurses.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP341">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP342"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_error_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP338">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>012bd42371c53e6c32e357201ee91c258640e546</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP253">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP254"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_bytecode.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP133">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP134"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eval/eval.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP305">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP306"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_tinyrandom.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP169">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP170"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-socket/duk_trans_socket_windows.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP263">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP264"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_forwdecl.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP351">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP352"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hbuffer.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP250">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a5985c22d5e36eaced8ebc72338a38ae0b73c9ad</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP103">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP104"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/c_eventloop.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP483">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP484"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./licenses/commonjs.txt</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP487">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP488"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src/duk_config.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP332">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4edee4bb513bcff807e343902af260ed8ff72850</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP423">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP424"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_tval.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP490">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5e427d4685c63b3e7c638c6eaac5e7df8216507f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP107">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP108"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/socket.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP165">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP166"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/cmdline/duk_cmdline.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP355">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP356"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_selftest.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP255">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP256"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP189">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP190"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/sandbox/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP373">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP374"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hbuffer_ops.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP466">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>11a7a5b6b1557adeca8a9def51cb44282f24c853</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP339">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP340"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_var.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP247">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP248"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_props.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP375">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP376"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_hashstring.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP38">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>2e1b55e44a5845fb785dde5b8c2e24bb7bd2e1bf</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP252">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a98ed9095834cad5b50d63cf8e659cca90e01062</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP227">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP228"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_date_unix.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP290">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>467388c812411a0d2b80760983171c346d35953d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP371">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP372"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_regexp_compiler.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP234">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4d3ab8c2d41261b0cae627db9d536d26f72b5f8e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP459">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP460"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/object-prototype-definesetter.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP56">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>79dac8ea1aa08daa3c8e9b6137b8a01c8d501893</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP142">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>8aa63b553757fe1229638e978b540d7116b70274</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP325">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP326"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_compiler.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP354">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>32ba21f45afd4b027113eda5aba53314c3f00da9</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP45">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP46"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_debug.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP342">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c00100a35037a372ebcde740082d5bb7c7735057</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP135">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP136"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/cpp-exceptions/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP485">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP486"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src/metadata.json</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP428">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5bd828887b0f46810358539868398e64b622d047</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP128">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>82314b509ee3b15b393fefe747c8e0169ab39aaa</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP407">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP408"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_numconv.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP269">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP270"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_date.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP440">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>23b6b54a8a35fbec735ffb332f4100a7f00557be</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP345">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP346"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hthread.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP57">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP58"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_debug_meta.json</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP50">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fe251e819feb6f84c1c8169eb6921174be2b1373</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP218">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6806426efc13e73e41899bef0aecca7eec097c18</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP433">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP434"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duktape.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP39">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP40"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-noline/duk_config.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP449">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP450"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debug_macros.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP174">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>012eed9a677efd2062f7ed6965d5a39e9e569c25</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP198">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>8015d14ffbc7a4a4b93d654f093aa48ec17fce4e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP117">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP118"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/curses-timers.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP8">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fa2824f02d8a2d21f729a4e9d44557f3b39a9355</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP403">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP404"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_strings.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP183">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP184"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-dvalue/duk_trans_dvalue.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP130">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a8c0b54002a3a7d8c69d385e7fbcf4b70d1efc70</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP62">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c81b68018e3d6f1b93683f7ead8761c01f2ca760</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP445">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP446"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_stringcache.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP20">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>df02f8688766b929639cca4881b73cb8f745c97c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP335">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP336"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_refcount.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP298">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>59df770184e4c26b190a76f4cd035c7e661d573f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP469">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP470"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./config/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP232">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fd24ca07cfd8fd37f3e70d10ad078ee5f149c9ce</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP29">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP30"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.dukdebug</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP435">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP436"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_replacements.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP188">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>22046b9dfc552ed692193d1bf5e3d0e182111ae5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP283">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP284"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_internal.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP399">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP400"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_executor.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP481">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP482"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./licenses/lua.txt</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP140">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>e023af5c2fb4b1efab74a230c552f1eb1b37fc10</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP127">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP128"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/dummy-date-provider/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP438">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>54a05944602f4a24864001a40d770591c6800daf</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP46">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4e41e7165a8d6e3bd370bc4536b16835a7204cf6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP308">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a23d89e3ff8fe247e09338af7b38bdab41da5c3e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP357">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP358"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_tval.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP336">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>821b268a1d4339ea2b309bdb6f527aa61bdb6b23</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP192">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>194e0bf80a1ddcc4d2d68ea6d2539656f3044f78</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP260">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>063133679b6d072efc1c27f3a510101744ffde0c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP353">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP354"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_bytecode.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP186">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5f3b6cd81be97aa687fe8b47751e68b5561d7c1b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP68">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ad583b87e72c08b4b44918dd1d7fce97e4950aa4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP96">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>7e2674dd72227576375a80f6ddbb11320f5b987a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP160">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>83b27494e6b257ab09828b0a4a1cf907686778a5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP367">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP368"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_boolean.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP42">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>829c4239ff43a1e15aa08bbbab41e7fba9207859</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP125">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP126"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/server-socket-test.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP392">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a913f60f44a9e19cd5c31e84242db88a0868eba8</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP143">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP144"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/uppercase.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP282">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>786369a33cccbadc3d2efba613a43fdd638971fc</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP219">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP220"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_debug.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP154">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>881f1b114c9fbba139044ddcbbc5398243185d10</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP63">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP64"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_opcodes.yaml</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP216">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>3fa5d72893eb3e1d42d07c8effc8bb1443f87dd6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP248">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>105dd2e79d90b96b6b1ae419bff31ed6a0273af6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP226">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>48eafa3f368fc879bfb79c2b2a30846a0b5d9b42</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP264">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>3f2b3b6b16cc969631b9980bc67aa6cc2c872048</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP313">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP314"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_error_augment.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP363">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP364"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_thrower.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP122">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6b98824e13a3d9536542b8da51d012a3d66ceec1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP66">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>23f0401f57af7b8e4df6636637caffce6956445b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP161">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP162"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/hello/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP410">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>457df68e290e23da40cac39a7cc35d6d6b4257c6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP61">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP62"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_classnames.yaml</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP164">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a4e2dfaee71b2316f2c3d149b4a507250b54dd96</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP213">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP214"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_jmpbuf.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP460">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>089c395fca3cedceec09fd38d32d0c77dc8658f4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP328">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>3f640daaa5e9d226a04fe419cb5eb1c07d06d346</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP47">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP48"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_debugerrors.yaml</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP369">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP370"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_error_macros.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP76">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4239a907720cf3620bd0b03eb43981e7182e305a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP293">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP294"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hthread_builtins.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP75">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP76"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/coffee/mandel.coffee</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP296">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6988aac432dcc185c2967732e21947ea0696377f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP300">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>7b167c1ea560de7ac67e217c1fdff8912f8b677d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP422">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>521f29841ddeb9be08ff9f7e2db06277da31bd47</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP155">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP156"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-torture/duk_alloc_torture.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP157">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP158"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-torture/duk_alloc_torture.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP71">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP72"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/static/index.html</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP356">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>93e24d8abbf79fb6a2fcd54679c476866ad6ab2a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP4">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:sourceInfo>Official duktape.org release built from GitHub repo https://github.com/svaarala/duktape.</_3:sourceInfo>
+    <_3:downloadLocation rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://duktape.org/duktape-1.5.2.tar.xz</_3:downloadLocation>
+    <_3:licenseDeclared rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:supplier>Organization: duktape.org</_3:supplier>
+    <_3:packageVerificationCode rdf:nodeID="svBMzJkP5"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Package"/>
+    <_3:description>Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint</_3:description>
+    <_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:licenseComments>
+    <_3:originator>Organization: duktape.org</_3:originator>
+    <_3:hasFile rdf:nodeID="svBMzJkP127"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP101"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP21"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP337"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP55"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP91"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP413"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP321"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP129"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP139"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP473"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP357"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP419"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP451"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP95"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP115"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP79"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP275"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP191"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP261"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP23"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP353"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP267"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP427"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP119"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP205"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP335"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP211"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP19"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP149"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP319"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP367"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP265"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP441"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP385"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP289"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP175"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP277"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP125"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP471"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP229"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP143"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP415"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP137"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP219"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP37"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP429"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP485"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP63"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP295"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP301"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP231"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP89"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP35"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP349"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP297"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP271"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP171"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP467"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP393"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP417"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP331"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP291"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP185"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP327"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP313"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP147"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP363"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP97"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP49"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP409"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP41"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP243"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP151"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP439"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP213"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP379"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP131"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP333"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP47"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP369"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP209"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP273"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP31"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP73"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP293"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP389"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP27"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP281"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP259"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP75"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP443"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP287"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP383"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP317"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP69"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP155"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP157"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP279"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP215"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP217"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP71"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP83"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP199"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP53"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP105"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP341"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP195"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP347"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP253"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP133"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP305"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP169"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP465"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP303"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP187"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP489"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP351"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP109"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP103"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP9"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP17"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP395"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP381"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP431"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP343"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP481"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP251"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP421"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP189"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP405"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP299"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP487"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP93"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP463"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP67"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP423"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP329"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP107"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP165"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP111"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP355"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP223"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP483"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP387"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP255"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP453"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP391"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP7"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP249"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP241"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP197"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP263"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP177"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP397"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP245"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP113"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP475"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP59"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP247"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP375"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP437"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP173"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP163"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP411"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP373"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP371"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP65"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP459"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP461"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP257"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP325"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP43"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP45"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP51"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP457"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP365"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP167"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP479"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP233"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP135"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP377"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP309"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP235"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP207"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP339"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP237"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP407"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP269"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP13"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP307"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP123"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP221"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP345"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP323"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP57"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP193"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP77"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP433"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP39"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP401"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP161"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP283"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP227"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP445"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP425"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP117"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP203"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP403"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP447"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP183"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP87"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP159"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP361"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP145"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP491"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP225"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP61"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP33"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP311"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP239"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP85"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP15"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP81"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP121"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP455"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP359"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP25"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP469"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP477"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP29"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP141"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP285"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP11"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP449"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP435"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP99"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP201"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP181"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP315"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP179"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP399"/>
+    <_3:hasFile rdf:nodeID="svBMzJkP153"/>
+    <_3:packageFileName>duktape-1.5.2.tar.xz</_3:packageFileName>
+    <_3:name>Duktape</_3:name>
+    <_3:homePage rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://duktape.org/</_3:homePage>
+    <_3:versionInfo>1.5.2</_3:versionInfo>
+    <_3:summary>Duktape Ecmascript interpreter</_3:summary>
+    <_3:licenseInfoFromFiles rdf:resource="http://spdx.org/licenses/MIT"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP80">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>af6b0cd61c02efa575b9106682606297d26f013b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP430">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ddcaaa8f260ff00f22e09d7fb4b4b7ca94858f30</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP176">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>bdb9243b436ef5c70967bddd16d0cc9e74971b1c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP12">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>cb09ad82ed76b6fcaf0ac32db698c1ce50e0a508</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP412">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>b3919a740c97b1d3ceb4e03c9ae53456916222a4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP368">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a20231719c1f9b97ea38fbc42dd8af1e21d74879</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP406">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>62b2d820f9a27df439cd24ac8766e680d27a95da</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP272">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>95a06fb24eca405019eb7b7d535179245eda6099</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP78">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ea413ed7d47cf27c6f3ffe25956b1370b653c200</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP54">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0bba41f542f2279b6bfa297ba4e7ee824e3ebd78</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP421">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP422"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_ops.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP7">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP8"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./LICENSE.txt</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP60">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>50a3349a079123b6bddf3db507df0dd9e877e246</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP299">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP300"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_logger.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP112">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>64566ae0bdc1c3e1017604b6b45d515c30d976eb</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP463">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP464"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/console-minimal.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP223">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP224"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_global.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP194">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>2c86a9ed51255ba3b0b225e48c093851a78cae71</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP196">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>742635fda10ef9775864077e647b59442768a69c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP249">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP250"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_call.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP397">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP398"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_regexp.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP163">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP164"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/cmdline/duk_cmdline_ajduk.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP411">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP412"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heaphdr.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP362">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5ab84f0ff2ed8c4b4a2daa5957d2a20447887103</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP444">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>8483a2211d6323480efa605ee646959695b742c6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP200">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fba891f21dc0b80d282f16d39c37007965adcd04</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP396">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>47e1001460004f53dfc350355e02bf56f18b0398</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP113">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP114"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/fileio.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP306">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d529a6faac560def1e5b2cdb991713a6d70b0e26</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP434">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>b7be4a3a943099fdf318480615d1c130be87a841</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP358">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a9493898a19810a5450d2442d1ff1dfb4ff76d1c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP220">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ee1f62688128fef0954cc9b93e41c199212e5a82</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP65">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP66"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/merge_debug_meta.py</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP44">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>bc9d119b5e66085e7e4219685fd351fb3f68d800</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP195">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP196"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-logging/duk_alloc_logging.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP452">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>aa1f72e7a2b4891ec1f445eb031dfba69bdc85de</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP270">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>1f430f45a3e52e4327eb17b2213a6f473dc1f6d2</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP206">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>9b7de9f9f25d095dfcffbf2d7629cd772fe632f0</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP401">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP402"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_date_windows.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP479">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP480"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./licenses/murmurhash2.txt</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP120">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>88ab1d060886393d94b6fb7c6054a0189117340b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP314">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d32ab97622eaf870648dfdf8e5b9cb034740affa</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP398">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>2e9dca0919a92c68ed30593292b3fe7140480062</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP378">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d5f1184bc60b9049b0dbf1e51ae6a5fe7e5e3192</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP18">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f3ed5c785b60b0f39a74cc3f5b73b0c6e24287c3</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP425">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP426"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_object.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP203">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP204"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_unicode_support.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP159">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP160"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/hello/hello.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP491">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP492"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src/duktape.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP391">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP392"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_duktape.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP33">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP34"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.eventloop</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP311">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP312"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_selftest.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP115">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP116"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/ecma_eventloop.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP92">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>01138dd2786346a159c06e43f094d07f002df881</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP405">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP406"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_buffer.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP141">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP142"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/processlines.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP236">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c763ffca7e15df01f44cf89518eb870380b03ee8</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP99">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP100"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/jxpretty/jxpretty.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP132">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>29b1960bc40607c2cf496465068611b2ffc4de87</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP482">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>55aa8c67f1fa418f8d625a32a9d6268e9d94429c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP333">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP334"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debug_vsnprintf.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP21">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP22"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.coffee</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP211">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP212"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_numconv.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP413">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP414"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_proxy.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP184">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0783cf4f48c9baf2b3820a36ab276b01e2102600</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP129">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP130"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/dummy-date-provider/dummy_date_provider.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP139">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP140"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP148">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>7edf7600e1a6f09d1e4a0e2f9be418b59fff7c52</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP95">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP96"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/codepage-conv/duk_codepage_conv.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP22">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>61043b4a6f3cf86375ea6e34ebf83b550a1935b2</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP418">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>13e6591c152934ace923d9e49cc52872c8a515b9</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP261">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP262"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_alloc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP48">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ca9e1a8f73c5dcbe2e8c45d25ce9865cd93866e6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP416">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>e17ef51b2a16cee731cf341ce08d04690da095ce</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP267">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP268"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_call.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP104">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>07a167411a356aebfbe987353846a9c711998f20</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP19">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP20"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.cmdline</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP319">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP320"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hnativefunction.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP472">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4fa87de84388dcd955ce27acbe2c2026babf32bc</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP156">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>9a31edd2028d39d24aa9bfdbd2b70ce2a64b8493</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP359">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP360"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hthread_alloc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP175">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP176"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-socket/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP229">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP230"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP23">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP24"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.codepage</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP486">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>9bcb9de5ed729ecc7093ab48e4f5c04e9704bb30</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP37">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP38"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-noline/metadata.json</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP302">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>494667f18c30e4fd36245e6c4e27f93fcf9df87d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP393">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP394"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_memory.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP295">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP296"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_class.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP36">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f88d68880f451267e7e2eca4b6c4191e8c3fe011</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP35">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP36"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.jxpretty</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP222">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>714e6fe76e2aed0bbb54f6c5e3674472813e4382</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP297">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP298"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_protos.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP171">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP172"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-socket/duk_trans_socket_unix.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP467">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP468"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./config/genconfig.py</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP350">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0ec3478b1e5713ffdbe7eb45cd5bb96c1a8a774b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP442">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>7c438de1ba7ca2ef226340d28ec0071ece1c9e43</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP116">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4db4ca2d7ce3f076fd195372d53e8bc5714d2597</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP84">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a8f8cf615ef79337a83eb791477dc9ed2c22822c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP124">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d869c0f8797a659124b3ba31c75f494b15bea5e6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP273">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP274"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_pc2line.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP389">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP390"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debugger.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP281">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP282"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_bitdecoder.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP380">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5bf6196d028d10a8f2f8e3da67b7d59bb8fd9eff</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP301">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP302"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_unicode_tables.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP324">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>29be453689679c9bab977c0b333a4a224d9f02e6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP110">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d535c4e27319a5db6026553a801e8a5ef0e6fe88</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP215">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP216"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP280">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fcdae530da6f6dfafd21219de294c547b91dd866</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP274">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>8521b45dcbc72d66c2b4e3f0db9e1dbfb75b45f5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP83">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP84"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-hybrid/duk_alloc_hybrid.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP26">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>3b8236810650f4e28bd84984b3c7e55029f241b0</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP453">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP454"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/duktape-error-setter-writable.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP278">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>cd7bd1908b56fe13dc63ac64b53ca793221f9359</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP337">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP338"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_markandsweep.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP465">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP466"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/performance-now.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP303">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP304"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_exception.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP187">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP188"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/sandbox/sandbox.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP109">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP110"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/c_eventloop.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP17">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP18"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./mandel.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP395">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP396"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hbufferobject.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP470">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6d5f56a1b76f9dcc9bb68d62ad0df958bd4d38ec</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP162">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>10c24a17c2f5f82d8c1a8fab8673c0c9075c1817</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP288">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>14ec83aeef66a38c6a4c48a175a544f66d319413</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP320">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>2c508fbc7eb127f6793cfe62bf947879668983a4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP172">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>01d4eb01e522172282a4a0ea3aa06f33ce7bec3c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP93">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP94"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/codepage-conv/test.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP144">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4baffeb2aa785bdc1065eb9ddb8c64c8a028655d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP150">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ed3bd07dbd103d285277ab38c4b4a7dd4a4b654b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP379">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP380"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_array.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP111">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP112"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP90">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>9bb6ca1fa3ad4c593b000b2de5aca013b95adda0</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP52">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>9406efff4ddfa3fe00ae52c28963df486fc48dfa</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP240">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ebbb5b2489ccab8f4a6ef741aac3eafac4c49ebd</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP134">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c2d899e7f2343579f29ad3079fde44eec5d6a544</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP197">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP198"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-logging/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP402">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0053a77d6c3562af6d2238f096f3a9bd4b5a834f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP348">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>82ae634976f8641d5582058879d42d843713927b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP178">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>11f16b15a8e52598a078b88a8d0440ff61dd5ba2</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP13">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP14"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP384">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d650b46e62e2579b3f4c16ee9b5a8abd1c8241b5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP344">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>11ecfff4142b35382d0aaf80ee6c04ae3dfd0b4c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP322">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0610275779180357a50777f77d1de0e0478f23a7</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP14">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0221b13981af62e7382a806c24f92450597b6106</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP152">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4e5a54de08355669dc98b5d4ad379384b33da4e5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP457">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP458"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/object-assign.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP6">
+    <rdfs:comment>SPDX license for Duktape 1.5.2</rdfs:comment>
+    <_3:referencesFile rdf:nodeID="svBMzJkP127"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP101"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP21"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP337"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP55"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP91"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP413"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP321"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP129"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP139"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP473"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP357"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP419"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP451"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP95"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP115"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP79"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP275"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP191"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP261"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP23"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP353"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP267"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP427"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP119"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP205"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP335"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP211"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP19"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP149"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP319"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP367"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP265"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP441"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP385"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP289"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP175"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP277"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP125"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP471"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP229"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP143"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP415"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP137"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP219"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP37"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP429"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP485"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP63"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP295"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP301"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP231"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP89"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP35"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP349"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP297"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP271"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP171"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP467"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP393"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP417"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP331"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP291"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP185"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP327"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP313"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP147"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP363"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP97"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP49"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP409"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP41"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP243"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP151"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP439"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP213"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP379"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP131"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP333"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP47"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP369"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP209"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP273"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP31"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP73"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP293"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP389"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP27"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP281"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP259"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP75"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP443"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP287"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP383"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP317"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP69"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP155"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP157"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP279"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP215"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP217"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP71"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP83"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP199"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP53"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP105"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP341"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP195"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP347"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP253"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP133"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP305"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP169"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP465"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP303"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP187"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP489"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP351"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP109"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP103"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP9"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP17"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP395"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP381"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP431"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP343"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP481"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP251"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP421"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP189"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP405"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP299"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP487"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP93"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP463"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP67"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP423"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP329"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP107"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP165"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP111"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP355"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP223"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP483"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP387"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP255"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP453"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP391"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP7"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP249"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP241"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP197"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP263"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP177"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP397"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP245"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP113"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP475"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP59"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP247"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP375"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP437"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP173"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP163"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP411"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP373"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP371"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP65"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP459"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP461"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP257"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP325"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP43"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP45"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP51"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP457"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP365"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP167"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP479"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP233"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP135"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP377"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP309"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP235"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP207"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP339"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP237"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP407"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP269"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP13"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP307"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP123"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP221"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP345"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP323"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP57"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP193"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP77"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP433"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP39"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP401"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP161"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP283"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP227"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP445"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP425"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP117"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP203"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP403"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP447"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP183"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP87"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP159"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP361"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP145"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP491"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP225"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP61"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP33"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP311"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP239"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP85"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP15"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP81"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP121"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP455"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP359"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP25"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP469"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP477"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP29"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP141"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP285"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP11"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP449"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP435"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP99"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP201"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP181"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP315"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP179"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP399"/>
+    <_3:referencesFile rdf:nodeID="svBMzJkP153"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#SpdxDocument"/>
+    <_3:dataLicense rdf:resource="http://spdx.org/licenses/CC0-1.0"/>
+    <_3:creationInfo rdf:nodeID="svBMzJkP3"/>
+    <_3:describesPackage rdf:nodeID="svBMzJkP4"/>
+    <_3:specVersion>SPDX-1.2</_3:specVersion>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP381">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP382"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_codec.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP233">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP234"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hthread_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP235">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP236"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP207">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP208"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_regexp_executor.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP478">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d49c1cdb51b3a4fdd823c13831617a1f0a93edd1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP334">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ef83823d07ee05f2373502187af9700d5c2aa952</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP237">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP238"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_js_compiler.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP364">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>982e40839854be361e3b57b5c07ef4f710ab749b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP307">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP308"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_replacements.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP123">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP124"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/client-socket-test.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP309">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP310"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_hashprime.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP347">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP348"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_json.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP149">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP150"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/primecheck.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP185">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP186"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-dvalue/test.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP242">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f788091973ac91ad9562aaadac9c2de87af2ba76</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP204">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>e70f9a590f4288c0feee56aa2c421cbc23036a1e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP82">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>75c61dd080cd643b7449f673105b7b7e4bdda0f5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP480">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>215f6fec820889330048f7f2c1b5a220eb963657</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP447">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP448"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_pointer.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP87">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP88"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-hybrid/duk_alloc_hybrid.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP448">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>2321e0a68bf940f8346d00adda9e4a58fa51f608</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP225">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP226"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_function.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP15">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP16"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.hello</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP81">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP82"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/coffee/globals.coffee</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP424">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>949e147e9b5e284590449d0e8f74427c8c12f00f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP455">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP456"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/object-prototype-definegetter.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP25">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP26"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.sandbox</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP477">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP478"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./extras/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP461">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP462"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/duktape-isfastint.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP285">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP286"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_logging.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP11">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP12"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./Makefile.sharedlibrary</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP316">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0f87aa4dae2a89f7ed3163197f96790ec6b28b19</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP310">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>e44b8b092afcfa97e693eb3e0be97d41f8aff301</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP315">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP316"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_heap.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP179">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP180"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-dvalue/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP98">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>8c5ee5b508a23ac5089a7e6c76593b6678965869</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP210">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>7f45dbd1e665b257c7186982b8b3362753856b18</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP55">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP56"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_debugcommands.yaml</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP91">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP92"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/codepage-conv/duk_codepage_conv.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP318">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>62ecbef7a21dd5c49b38fbe344e2511c07f36261</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP266">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>030ac3c728cca19fe93d652a4b6b8758d739d9b9</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP74">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>09ee87b3ae8afe8b7c2295127835b05b00603b25</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP473">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP474"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./config/duk_config.h-modular-static</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP254">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4fae13370046b51fe87c60fa86eb14f2948fd143</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP262">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c06e1c0dcc0c61e40f7337b40917df034f167e54</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP432">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>dfd71ae51277aae2fe511f4df732a20bc72ab75a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP419">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP420"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_thread.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP170">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>641b29e08addaa543f37561f5a35689f5fba876e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP286">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fb9c2ff459fd84b4587f846fbd36219cf8f06931</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP166">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>b1c899faac8f0a8b1f7844d8c773ce5e6d9262d1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP191">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP192"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-logging/duk_alloc_logging.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP158">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>d45e3fc443887261ce432a807aaebd2a1812264e</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP427">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP428"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_var.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP119">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP120"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/basic-test.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP205">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP206"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_builtins.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP94">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c8ae046bda2c920b5d807dfa68c8159b655b0873</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP30">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f20291ecae9e775ebac2a6ed24f5399c2b3a7883</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP385">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP386"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_heap_alloc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP366">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>239011a773fbafa409c2f02b5e889bd5d28d16e1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP118">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6a1500fea27ea278c4f0c64d908e16cc60df684b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP471">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP472"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./config/duk_config.h-modular-dll</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP58">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c33541d338ff3d8461dd1a8573a6372e19cb12e4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP231">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP232"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hstring_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP89">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP90"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/codepage-conv/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP24">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f396c6aec456b183ef77e33da1dfffc89c417056</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP326">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a9db75839022e7dcf7e691ada7480a9b7c2715d0</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP212">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a2c79a55a60f73e1a1567b96d584399571180ef5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP484">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>92ce3decf72b10b0023116ac727a752e8749aa90</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP390">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>339f26c72e051cf531426a63fe6c35c476bad645</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP114">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a9206a7b46f8d8319b798475650217f494fa76ab</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP34">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fa85ee3394206d18c611b837e700257ba8336250</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP291">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP292"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_json.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP86">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>149fd21526c90d52b22e77b297f76e6da3e656ff</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP72">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>03cad085177f1e776be90afceef1f2160e6c8bf4</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP49">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP50"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/duk_debug_proxy.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP409">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP410"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_debugger.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP41">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP42"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-noline/duktape.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP243">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP244"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_strings.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP151">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP152"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/prime.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP131">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP132"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eval/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP446">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>62a4483b185b620431e13ddb2b18555baa344937</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP294">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a476b63d336a8d171891330c965fbb8b72f5863a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP27">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP28"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./AUTHORS.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP259">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP260"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_regexp.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP287">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP288"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_math.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP284">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>a32730ebb239feb5599bcac3561b7a0acb3a1b94</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP317">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP318"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hthread_stacks.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP420">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>87018db6c5898305a7e5196d9590c5b42424a7ea</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP138">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>2df8e3d302a5c74ac385b0e1e110d0845a4aef35</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP40">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5ab84f0ff2ed8c4b4a2daa5957d2a20447887103</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP106">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>484fb41d516abcbe8c97af5aa80b76c67dbfb0cb</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP489">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP490"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src/duktape.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP199">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP200"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_error.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP59">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP60"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/package.json</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP9">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP10"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./duk_build_meta.json</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP431">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP432"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_hashbytes.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP146">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>206ffd13c06208e85baba2b257fe3ddebb56a6c2</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP228">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6b438afc07b9ac67fb6ea8bc9d4f01f3b362c9e1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP330">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>73ff75213f392b6125c68ab6b430176dfad71269</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP451">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP452"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./polyfills/duktape-error-setter-nonwritable.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP108">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>24a2346fa389c2294cc0e96427e0bd206dac10b9</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP394">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ff17cbc9cb84b86f83bb104a247e5c265a9fe5b5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP488">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5ab84f0ff2ed8c4b4a2daa5957d2a20447887103</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP5">
+    <_3:packageVerificationCodeExcludedFile>./license.spdx</_3:packageVerificationCodeExcludedFile>
+    <_3:packageVerificationCodeValue>a60d2f27825f0294858de60a5ef8f35433967a27</_3:packageVerificationCodeValue>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP67">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP68"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/static/style.css</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP329">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP330"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hcompiledfunction.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP241">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP242"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_misc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP450">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>036a814b2c1187af4c5c882095bd6b3d710cb79a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP386">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6fdfe8f7b5fc3226d83f0246079f76b33d4bcb9b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP202">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>b381ea15009eb8140c0789203345cdcc2c6c1cd6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP400">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6c4bfae55df6a1fef08fd758e32bf465316cab9a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP276">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>734560a1ac6155f124000b5a93569aae99149b6c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP265">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP266"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_string.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP426">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>64edd8d85b88c69b5c2c686b85f19b350bef7880</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP182">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>1c40a52fd54baf7ac334fce4829892d5d951401a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP251">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP252"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_lexer.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP429">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP430"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_stack.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP224">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>fbe432d33d4ef75f30fa2d87f4f1a83f78b4811b</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP177">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP178"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-dvalue/duk_trans_dvalue.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP492">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>bc9d119b5e66085e7e4219685fd351fb3f68d800</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP245">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP246"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_unicode.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP64">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>3da07a99a4ed68844140352133867b2857fab685</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP475">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP476"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./config/genconfig_metadata.tar.gz</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP343">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP344"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_api_memory.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP377">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP378"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP454">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4392fa63e6e9174ec09ef2e3a4e4e3bd03e94126</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP340">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>9b95f60e95f7da3773bdac1d2a436b3c5a662ab1</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP474">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>6985052d270ff2a00543b641115b946fc91ebf3a</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP126">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>f9072f5c361c86887b57ce662b3cd7211b4ce346</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP190">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5d593ae6316ed7a3ea6e7ed0a47267745d79d12d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP88">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ddbc206357dd4b97f3630b87bfdac148a5e8b190</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP257">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP258"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hbuffer_alloc.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP43">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP44"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-noline/duktape.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP51">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP52"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./debugger/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP73">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP74"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP404">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>89a7d62e8ae337fca35cacbb4b4cc6f294daedc9</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP102">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>5f89525f75f61dd8c89e010cb62bc071d6d13170</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP268">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>4396fb38f8a42bfc90ef1bc7c11c402074367343</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP238">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ab29fe562681a0e6785515ef284fc51a20f0f7b5</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP304">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>ebaa68746ec59e01ef742f68aab11e053f882f63</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP387">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP388"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_util_bitencoder.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP28">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>8ddbeb97a1a5acc3bed35f4df60e3aa1f4267380</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP97">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP98"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/jxpretty/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP167">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP168"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/cmdline/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP221">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP222"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_error.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP193">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP194"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-logging/log2gnuplot.py</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP77">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP78"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/coffee/hello.coffee</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP458">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>0125ebcabe62cef4923e75527d3128e8c48cdf1f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP437">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP438"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_bi_number.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP230">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>c1685717742f3e9af9c901796a8bb5a08950461f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP244">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>e172079513ed0c12550285bcbc4d6bfc83985676</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP173">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP174"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-socket/duk_trans_socket.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP352">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>52b4480b68f7f8bf93543d3bb795cdc5ade66fba</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP464">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>93573df8348a41adb790f59e39bf99d9a7bf3a3d</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP145">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP146"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/guide/fib.js</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP256">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>127e52c8b193d777811c25ceaab2c97c26a2bdab</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP136">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>601a6783177c1c6140c12b42c0bedb0ee0079d16</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP346">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>02741b89fd8d8df210223a3da3a200d0f609d803</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP239">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP240"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_hobject_finalizer.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP16">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>44c9219558aba26dc69982a9f432028290707c36</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP85">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP86"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-hybrid/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP372">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>1289ac12dfcacbe472caea1333de3fbe70a5662c</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP100">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>3d700df1f765c39fc63bfd4e31a9d7da8d15c543</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP121">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP122"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/eventloop/poll.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP456">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>e5a5f0db067ec56c6d2f7356f412222a8884dc92</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP10">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>46f70bf98738ea7c9e5b353490d3e8815c610aa6</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP201">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP202"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_error_throw.c</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP181">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP182"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/debug-trans-dvalue/Makefile</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP361">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP362"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./src-separate/duk_config.h</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP168">
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+    <_3:checksumValue>58c701ade28ee5a475dede84a6e771893e3fc40f</_3:checksumValue>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="svBMzJkP153">
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:copyrightText>Copyright 2013-2016 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:checksum rdf:nodeID="svBMzJkP154"/>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:fileName>./examples/alloc-torture/README.rst</_3:fileName>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+  </rdf:Description>
+</rdf:RDF>

+ 2 - 0
src/third_party/duktape-1.5.2/licenses/commonjs.txt

@@ -0,0 +1,2 @@
+CommonJS specification snapshots are included in the references/
+directory.  CommonJS is under the MIT license: http://www.commonjs.org/.

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است