瀏覽代碼

Experimental support for duktape (Step 1/?)

bel 9 年之前
父節點
當前提交
97c77c200e
共有 100 個文件被更改,包括 19935 次插入5 次删除
  1. 15 0
      VS2012/civetweb.sln
  2. 5 3
      VS2012/civetweb_lua/civetweb_lua.vcxproj
  3. 155 0
      VS2012/duktape_lib/duktape_lib.vcxproj
  4. 30 0
      VS2012/duktape_lib/duktape_lib.vcxproj.filters
  5. 78 2
      src/main.c
  6. 67 0
      src/third_party/duktape-1.3.0/AUTHORS.rst
  7. 25 0
      src/third_party/duktape-1.3.0/LICENSE.txt
  8. 30 0
      src/third_party/duktape-1.3.0/Makefile.cmdline
  9. 4 0
      src/third_party/duktape-1.3.0/Makefile.codepage
  10. 4 0
      src/third_party/duktape-1.3.0/Makefile.coffee
  11. 23 0
      src/third_party/duktape-1.3.0/Makefile.dukdebug
  12. 7 0
      src/third_party/duktape-1.3.0/Makefile.eval
  13. 22 0
      src/third_party/duktape-1.3.0/Makefile.eventloop
  14. 35 0
      src/third_party/duktape-1.3.0/Makefile.hello
  15. 8 0
      src/third_party/duktape-1.3.0/Makefile.jxpretty
  16. 7 0
      src/third_party/duktape-1.3.0/Makefile.sandbox
  17. 103 0
      src/third_party/duktape-1.3.0/README.rst
  18. 39 0
      src/third_party/duktape-1.3.0/config/README.rst
  19. 1872 0
      src/third_party/duktape-1.3.0/config/genconfig.py
  20. 二進制
      src/third_party/duktape-1.3.0/config/genconfig_metadata.tar.gz
  21. 80 0
      src/third_party/duktape-1.3.0/debugger/Makefile
  22. 268 0
      src/third_party/duktape-1.3.0/debugger/README.rst
  23. 31 0
      src/third_party/duktape-1.3.0/debugger/duk_classnames.yaml
  24. 2448 0
      src/third_party/duktape-1.3.0/debugger/duk_debug.js
  25. 36 0
      src/third_party/duktape-1.3.0/debugger/duk_debugcommands.yaml
  26. 660 0
      src/third_party/duktape-1.3.0/debugger/duk_opcodes.yaml
  27. 27 0
      src/third_party/duktape-1.3.0/debugger/package.json
  28. 96 0
      src/third_party/duktape-1.3.0/debugger/static/index.html
  29. 512 0
      src/third_party/duktape-1.3.0/debugger/static/style.css
  30. 745 0
      src/third_party/duktape-1.3.0/debugger/static/webui.js
  31. 838 0
      src/third_party/duktape-1.3.0/duk_build_meta.json
  32. 10 0
      src/third_party/duktape-1.3.0/examples/README.rst
  33. 10 0
      src/third_party/duktape-1.3.0/examples/alloc-hybrid/README.rst
  34. 293 0
      src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.c
  35. 11 0
      src/third_party/duktape-1.3.0/examples/alloc-hybrid/duk_alloc_hybrid.h
  36. 7 0
      src/third_party/duktape-1.3.0/examples/alloc-logging/README.rst
  37. 138 0
      src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.c
  38. 10 0
      src/third_party/duktape-1.3.0/examples/alloc-logging/duk_alloc_logging.h
  39. 41 0
      src/third_party/duktape-1.3.0/examples/alloc-logging/log2gnuplot.py
  40. 10 0
      src/third_party/duktape-1.3.0/examples/alloc-torture/README.rst
  41. 182 0
      src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.c
  42. 10 0
      src/third_party/duktape-1.3.0/examples/alloc-torture/duk_alloc_torture.h
  43. 6 0
      src/third_party/duktape-1.3.0/examples/cmdline/README.rst
  44. 873 0
      src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline.c
  45. 892 0
      src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline_ajduk.c
  46. 8 0
      src/third_party/duktape-1.3.0/examples/codepage-conv/README.rst
  47. 54 0
      src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.c
  48. 8 0
      src/third_party/duktape-1.3.0/examples/codepage-conv/duk_codepage_conv.h
  49. 286 0
      src/third_party/duktape-1.3.0/examples/codepage-conv/test.c
  50. 10 0
      src/third_party/duktape-1.3.0/examples/coffee/README.rst
  51. 7 0
      src/third_party/duktape-1.3.0/examples/coffee/globals.coffee
  52. 2 0
      src/third_party/duktape-1.3.0/examples/coffee/hello.coffee
  53. 28 0
      src/third_party/duktape-1.3.0/examples/coffee/mandel.coffee
  54. 17 0
      src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/Makefile
  55. 8 0
      src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/README.rst
  56. 1239 0
      src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.c
  57. 113 0
      src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/duk_trans_dvalue.h
  58. 236 0
      src/third_party/duktape-1.3.0/examples/debug-trans-dvalue/test.c
  59. 6 0
      src/third_party/duktape-1.3.0/examples/debug-trans-socket/README.rst
  60. 313 0
      src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.c
  61. 14 0
      src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.h
  62. 5 0
      src/third_party/duktape-1.3.0/examples/dummy-date-provider/README.rst
  63. 27 0
      src/third_party/duktape-1.3.0/examples/dummy-date-provider/dummy_date_provider.c
  64. 5 0
      src/third_party/duktape-1.3.0/examples/eval/README.rst
  65. 48 0
      src/third_party/duktape-1.3.0/examples/eval/eval.c
  66. 76 0
      src/third_party/duktape-1.3.0/examples/eventloop/README.rst
  67. 17 0
      src/third_party/duktape-1.3.0/examples/eventloop/basic-test.js
  68. 618 0
      src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.c
  69. 179 0
      src/third_party/duktape-1.3.0/examples/eventloop/c_eventloop.js
  70. 24 0
      src/third_party/duktape-1.3.0/examples/eventloop/client-socket-test.js
  71. 79 0
      src/third_party/duktape-1.3.0/examples/eventloop/curses-timers.js
  72. 466 0
      src/third_party/duktape-1.3.0/examples/eventloop/ecma_eventloop.js
  73. 69 0
      src/third_party/duktape-1.3.0/examples/eventloop/fileio.c
  74. 256 0
      src/third_party/duktape-1.3.0/examples/eventloop/main.c
  75. 105 0
      src/third_party/duktape-1.3.0/examples/eventloop/ncurses.c
  76. 111 0
      src/third_party/duktape-1.3.0/examples/eventloop/poll.c
  77. 34 0
      src/third_party/duktape-1.3.0/examples/eventloop/server-socket-test.js
  78. 286 0
      src/third_party/duktape-1.3.0/examples/eventloop/socket.c
  79. 5 0
      src/third_party/duktape-1.3.0/examples/guide/README.rst
  80. 16 0
      src/third_party/duktape-1.3.0/examples/guide/fib.js
  81. 32 0
      src/third_party/duktape-1.3.0/examples/guide/prime.js
  82. 52 0
      src/third_party/duktape-1.3.0/examples/guide/primecheck.c
  83. 12 0
      src/third_party/duktape-1.3.0/examples/guide/process.js
  84. 59 0
      src/third_party/duktape-1.3.0/examples/guide/processlines.c
  85. 42 0
      src/third_party/duktape-1.3.0/examples/guide/uppercase.c
  86. 5 0
      src/third_party/duktape-1.3.0/examples/hello/README.rst
  87. 38 0
      src/third_party/duktape-1.3.0/examples/hello/hello.c
  88. 5 0
      src/third_party/duktape-1.3.0/examples/jxpretty/README.rst
  89. 63 0
      src/third_party/duktape-1.3.0/examples/jxpretty/jxpretty.c
  90. 5 0
      src/third_party/duktape-1.3.0/examples/sandbox/README.rst
  91. 252 0
      src/third_party/duktape-1.3.0/examples/sandbox/sandbox.c
  92. 13 0
      src/third_party/duktape-1.3.0/extras/README.rst
  93. 3629 0
      src/third_party/duktape-1.3.0/license.spdx
  94. 2 0
      src/third_party/duktape-1.3.0/licenses/commonjs.txt
  95. 21 0
      src/third_party/duktape-1.3.0/licenses/murmurhash2.txt
  96. 53 0
      src/third_party/duktape-1.3.0/mandel.js
  97. 20 0
      src/third_party/duktape-1.3.0/polyfills/console-minimal.js
  98. 38 0
      src/third_party/duktape-1.3.0/polyfills/duktape-isfastint.js
  99. 45 0
      src/third_party/duktape-1.3.0/polyfills/object-assign.js
  100. 11 0
      src/third_party/duktape-1.3.0/polyfills/object-prototype-definegetter.js

+ 15 - 0
VS2012/civetweb.sln

@@ -2,6 +2,9 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual C++ Express 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "civetweb_lua", "civetweb_lua\civetweb_lua.vcxproj", "{9BE9C008-E851-42B1-A034-BD4630AE4CD6}"
+	ProjectSection(ProjectDependencies) = postProject
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD} = {0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}
+	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua_lib", "lua_lib\lua_lib.vcxproj", "{8F5E5D77-D269-4665-9E27-1045DA6CF0D8}"
 EndProject
@@ -19,6 +22,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Browser", "..\testutils\Bro
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testclient2", "..\testutils\testclient_chunked_linux\testclient2.vcxproj", "{150140C5-2989-4D0D-8714-5A47B78EAD4D}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "duktape_lib", "duktape_lib\duktape_lib.vcxproj", "{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Mixed Platforms = Debug|Mixed Platforms
@@ -125,6 +130,16 @@ Global
 		{150140C5-2989-4D0D-8714-5A47B78EAD4D}.Release|Win32.ActiveCfg = Release|Win32
 		{150140C5-2989-4D0D-8714-5A47B78EAD4D}.Release|Win32.Build.0 = Release|Win32
 		{150140C5-2989-4D0D-8714-5A47B78EAD4D}.Release|x64.ActiveCfg = Release|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Debug|Win32.Build.0 = Debug|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Debug|x64.ActiveCfg = Debug|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Release|Mixed Platforms.Build.0 = Release|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Release|Win32.ActiveCfg = Release|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Release|Win32.Build.0 = Release|Win32
+		{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}.Release|x64.ActiveCfg = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 5 - 3
VS2012/civetweb_lua/civetweb_lua.vcxproj

@@ -118,8 +118,8 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.3.0\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -227,7 +227,9 @@
     <ProjectReference Include="..\lua_lib\lua_lib.vcxproj">
       <Project>{8f5e5d77-d269-4665-9e27-1045da6cf0d8}</Project>
     </ProjectReference>
-  </ItemGroup>
+    <ProjectReference Include="..\duktape_lib\duktape_lib.vcxproj">
+      <Project>{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}</Project>
+    </ProjectReference>  </ItemGroup>
   <ItemGroup>
     <None Include="..\..\src\md5.inl" />
     <None Include="..\..\src\mod_lua.inl" />

+ 155 - 0
VS2012/duktape_lib/duktape_lib.vcxproj

@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0A11689C-DB6A-4BF6-97B2-AD32DB863FBD}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>duktape_lib</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(SolutionDir)\$(Configuration)\$(Platform)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(SolutionDir)\$(Configuration)\$(Platform)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(SolutionDir)\$(Configuration)\$(Platform)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(SolutionDir)\$(Configuration)\$(Platform)\</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>TurnOffAllWarnings</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>duktape_COMPAT_ALL;THREADSAFE=1;SQLITE_ENABLE_FTS3;SQLITE_ENABLE_FTS3_PARENTHESIS;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>duktape_COMPAT_ALL;THREADSAFE=1;SQLITE_ENABLE_FTS3;SQLITE_ENABLE_FTS3_PARENTHESIS;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>duktape_COMPAT_ALL;THREADSAFE=1;SQLITE_ENABLE_FTS3;SQLITE_ENABLE_FTS3_PARENTHESIS;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>duktape_COMPAT_ALL;THREADSAFE=1;SQLITE_ENABLE_FTS3;SQLITE_ENABLE_FTS3_PARENTHESIS;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\third_party\duktape-1.3.0\src\duktape.h" />
+    <ClInclude Include="..\..\src\third_party\duktape-1.3.0\src\duk_config.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\third_party\duktape-1.3.0\src\duktape.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 30 - 0
VS2012/duktape_lib/duktape_lib.vcxproj.filters

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\third_party\duktape-1.3.0\src\duk_config.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\third_party\duktape-1.3.0\src\duktape.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\third_party\duktape-1.3.0\src\duktape.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 78 - 2
src/main.c

@@ -733,6 +733,67 @@ static int run_lua(const char *file_name)
 #endif
 
 
+#ifdef USE_DUKTAPE
+
+#include "duktape.h"
+
+static int run_duktape(const char *file_name)
+{
+	duk_context *ctx = NULL;
+	char line[4096];
+	char idx;
+	int ch;
+
+	ctx = duk_create_heap_default();
+	if (!ctx) {
+		fprintf(stderr, "Failed to create a Duktape heap.\n");
+		exit(1);
+	}
+
+	if (duk_peval_file(ctx, file_name) != 0) {
+		fprintf(stderr, "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)) {
+			fprintf(stderr, "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) {
+				fprintf(stderr, "Error: %s\n", duk_safe_to_string(ctx, -1));
+			} else {
+				fprintf(stdout, "%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);
+
+	return 0;
+}
+#endif
+
+
 #if defined(__MINGW32__) || defined(__MINGW64__)
 /* For __MINGW32/64_MAJOR/MINOR_VERSION define */
 #include <_mingw.h>
@@ -901,8 +962,8 @@ static void start_civetweb(int argc, char *argv[])
 		         : EXIT_FAILURE);
 	}
 
-	/* Call Lua with additional Civetweb specific Lua functions, if -L option is
-	 * specified */
+	/* Call Lua with additional CivetWeb specific Lua functions, if -L option
+	 * is specified */
 	if (argc > 1 && !strcmp(argv[1], "-L")) {
 
 #ifdef USE_LUA
@@ -917,6 +978,21 @@ static void start_civetweb(int argc, char *argv[])
 #endif
 	}
 
+	/* Call Duktape, if -E option is specified */
+	if (argc > 1 && !strcmp(argv[1], "-E")) {
+
+#ifdef USE_DUKTAPE
+		if (argc != 3) {
+			show_usage_and_exit(argv[0]);
+		}
+		exit(run_duktape(argv[2]));
+#else
+		show_server_name();
+		fprintf(stderr, "\nError: Ecmascript support not enabled\n");
+		exit(EXIT_FAILURE);
+#endif
+	}
+
 	/* Show usage if -h or --help options are specified */
 	if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-H") ||
 	                  !strcmp(argv[1], "--help"))) {

+ 67 - 0
src/third_party/duktape-1.3.0/AUTHORS.rst

@@ -0,0 +1,67 @@
+===============
+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>
+
+Other contributions
+===================
+
+The following people have contributed something other than code (e.g. reported
+bugs, provided ideas, etc; roughly in order of appearance):
+
+* Greg Burns
+* Anthony Rabine
+* Carlos Costa
+* Aurélien Bouilland
+* Preet Desai (Pris Matic)
+* judofyr (http://www.reddit.com/user/judofyr)
+* Jason Woofenden
+* Michał Przybyś
+* Anthony Howe
+* Conrad Pankoff
+* Jim Schimpf
+* Rajaran Gaunker (https://github.com/zimbabao)
+* Andreas Öman
+* Doug Sanden
+* Josh Engebretson (https://github.com/JoshEngebretson)
+* Remo Eichenberger (https://github.com/remoe)
+* Mamod Mehyar (https://github.com/mamod)
+* David Demelier (https://github.com/markand)
+* Tim Caswell (https://github.com/creationix)
+* Mitchell Blank Jr (https://github.com/mitchblank)
+* https://github.com/yushli
+* Seo Sanghyeon (https://github.com/sanxiyn)
+* Han ChoongWoo (https://github.com/tunz)
+* Joshua Peek (https://github.com/josh)
+* Bruce E. Pascoe (https://github.com/fatcerberus)
+* https://github.com/Kelledin
+* https://github.com/sstruchtrup
+* Michael Drake (https://github.com/tlsa)
+* https://github.com/chris-y
+
+If you are accidentally missing from this list, send me an e-mail
+(``sami.vaarala@iki.fi``) and I'll fix the omission.

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

@@ -0,0 +1,25 @@
+===============
+Duktape license
+===============
+
+(http://opensource.org/licenses/MIT)
+
+Copyright (c) 2013-2015 by Duktape authors (see AUTHORS.rst)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 30 - 0
src/third_party/duktape-1.3.0/Makefile.cmdline

@@ -0,0 +1,30 @@
+#
+#  Example Makefile for building a program with embedded Duktape.
+#  The example program here is the Duktape command line tool.
+#
+
+DUKTAPE_SOURCES = src/duktape.c
+
+DUKTAPE_CMDLINE_SOURCES = \
+	examples/cmdline/duk_cmdline.c
+
+CC	= gcc
+CCOPTS	= -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer
+CCOPTS += -I./src   # duktape.h and duk_config.h must be in include path
+CCLIBS	= -lm
+
+# If you have readline, you may want to enable these.  On some platforms
+# -lreadline also requires -lncurses (e.g. RHEL), so it is added by default
+# (you may be able to remove it)
+#CCOPTS += -DDUK_CMDLINE_FANCY
+#CCLIBS += -lreadline
+#CCLIBS += -lncurses
+
+# Optional feature defines, see: http://duktape.org/guide.html#compiling
+CCOPTS += -DDUK_OPT_SELF_TESTS
+#CCOPTS += -DDUK_OPT_DEBUG
+#CCOPTS += -DDUK_OPT_DPRINT
+# ...
+
+duk:	$(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES)
+	$(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS)

+ 4 - 0
src/third_party/duktape-1.3.0/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.3.0/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

+ 23 - 0
src/third_party/duktape-1.3.0/Makefile.dukdebug

@@ -0,0 +1,23 @@
+#
+#  Duktape command line tool with debugger support.
+#
+
+DUKTAPE_SOURCES = src/duktape.c
+
+DUKTAPE_CMDLINE_SOURCES = \
+	examples/cmdline/duk_cmdline.c \
+	examples/debug-trans-socket/duk_trans_socket.c
+
+CC	= gcc
+CCOPTS	= -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer
+CCOPTS += -I./src -I./examples/debug-trans-socket
+CCOPTS += -DDUK_CMDLINE_DEBUGGER_SUPPORT     # enable --debugger in ./duk
+CCOPTS += -DDUK_OPT_DEBUGGER_SUPPORT         # enable debugger support in Duktape
+CCOPTS += -DDUK_OPT_INTERRUPT_COUNTER        # prerequisite for debugging
+CCOPTS += -DDUK_OPT_DEBUGGER_FWD_PRINTALERT  # optional debugger features
+CCOPTS += -DDUK_OPT_DEBUGGER_FWD_LOGGING
+CCOPTS += -DDUK_OPT_DEBUGGER_DUMPHEAP
+CCLIBS	= -lm
+
+duk:	$(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES)
+	$(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS)

+ 7 - 0
src/third_party/duktape-1.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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

+ 103 - 0
src/third_party/duktape-1.3.0/README.rst

@@ -0,0 +1,103 @@
+=======
+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-separate/``: main Duktape library in multiple files format.
+
+* ``config/``: genconfig utility for creating duk_config.h configuration
+  files, see: http://wiki.duktape.org/Configuring.html.
+
+* ``examples/``: further examples for using Duktape.  Although Duktape
+  itself is widely portable, some of the examples are Linux only.
+  For instance the ``eventloop`` example illustrates how ``setTimeout()``
+  and other standard timer functions could be implemented on Unix/Linux.
+
+* ``extras/``: utilities and modules which don't comfortably fit into the
+  main Duktape library because of footprint or portability concerns.
+  Extras are maintained and bug fixed code, but don't have the same version
+  guarantees as the main Duktape library.
+
+* ``polyfills/``: a few replacement suggestions for non-standard Javascript
+  functions provided by other implementations.
+
+* ``debugger/``: a debugger with a web UI, see ``debugger/README.rst`` and
+  https://github.com/svaarala/duktape/blob/master/doc/debugger.rst for
+  details on Duktape debugger support.
+
+* ``licenses/``: licensing information.
+
+You can find release notes at:
+
+* https://github.com/svaarala/duktape/blob/master/RELEASES.rst
+
+This distributable contains Duktape version 1.3.0, created from git
+commit 675165f35ea3a5bac34ff4d0a58b007cc2f442dc (v1.3.0).
+
+Duktape is copyrighted by its authors (see ``AUTHORS.rst``) and licensed
+under the MIT license (see ``LICENSE.txt``).  MurmurHash2 is used internally,
+it is also under the MIT license.  Duktape module loader is based on the
+CommonJS module loading specification (without sharing any code), CommonJS
+is under the MIT license.
+
+Have fun!
+
+Sami Vaarala (sami.vaarala@iki.fi)

+ 39 - 0
src/third_party/duktape-1.3.0/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.

+ 1872 - 0
src/third_party/duktape-1.3.0/config/genconfig.py

@@ -0,0 +1,1872 @@
+#!/usr/bin/python
+#
+#  Process Duktape option metadata and produce various useful outputs:
+#
+#    - duk_config.h matching Duktape 1.x feature option model (DUK_OPT_xxx)
+#    - duk_config.h for a selected platform, compiler, forced options, etc.
+#    - option documentation for Duktape 1.x feature options (DUK_OPT_xxx)
+#    - option documentation for Duktape 1.x/2.x config options (DUK_USE_xxx)
+#
+#  Genconfig tries to build all outputs based on modular metadata, so that
+#  managing a large number of config options (which is hard to avoid given
+#  the wide range of targets Duktape supports) remains maintainable.
+#
+#  Genconfig does *not* try to support all exotic platforms out there.
+#  Instead, the goal is to allow the metadata to be extended, or to provide
+#  a reasonable starting point for manual duk_config.h tweaking.
+#
+#  NOTE: For Duktape 1.3 release the main goal is to autogenerate a Duktape
+#  1.2 compatible "autodetect" header from snippets.  Other outputs are still
+#  experimental.
+#
+
+import os
+import sys
+import re
+import json
+import yaml
+import optparse
+import tarfile
+import tempfile
+import atexit
+import shutil
+import StringIO
+
+#
+#  Globals holding scanned metadata, helper snippets, etc
+#
+
+# Metadata to scan from config files.
+use_defs = None
+use_defs_list = None
+opt_defs = None
+opt_defs_list = None
+use_tags = None
+use_tags_list = None
+tags_meta = None
+required_use_meta_keys = [
+	'define',
+	'introduced',
+	'default',
+	'tags',
+	'description'
+]
+allowed_use_meta_keys = [
+	'define',
+	'feature_enables',
+	'feature_disables',
+	'feature_snippet',
+	'related_feature_defines',
+	'introduced',
+	'deprecated',
+	'removed',
+	'unused',
+	'requires',
+	'conflicts',
+	'related',
+	'default',
+	'tags',
+	'description',
+]
+required_opt_meta_keys = [
+	'define',
+	'introduced',
+	'tags',
+	'description'
+]
+allowed_opt_meta_keys = [
+	'define',
+	'introduced',
+	'deprecated',
+	'removed',
+	'unused',
+	'requires',
+	'conflicts',
+	'related',
+	'tags',
+	'description'
+]
+
+# Preferred tag order for option documentation.
+doc_tag_order = [
+	'portability',
+	'memory',
+	'lowmemory',
+	'ecmascript',
+	'execution',
+	'debugger',
+	'debug',
+	'development'
+]
+
+# Preferred tag order for generated C header files.
+header_tag_order = doc_tag_order
+
+# Helper headers snippets.
+helper_snippets = None
+
+# Assume these provides come from outside.
+assumed_provides = {
+	'DUK_SINGLE_FILE': True,         # compiling Duktape from a single source file (duktape.c) version
+	'DUK_COMPILING_DUKTAPE': True,   # compiling Duktape (not user application)
+	'DUK_CONFIG_H_INCLUDED': True,   # artifact, include guard
+}
+
+# Platform files must provide at least these (additional checks
+# in validate_platform_file()).
+platform_required_provides = [
+	'DUK_USE_OS_STRING',
+	'DUK_SETJMP', 'DUK_LONGJMP',
+]
+
+# Architecture files must provide at least these (additional checks
+# in validate_architecture_file()).
+architecture_required_provides = [
+	'DUK_USE_ARCH_STRING',
+	'DUK_USE_ALIGN_BY', 'DUK_USE_UNALIGNED_ACCESSES_POSSIBLE', 'DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS',
+	'DUK_USE_PACKED_TVAL', 'DUK_USE_PACKED_TVAL_POSSIBLE'
+]
+
+# Compiler files must provide at least these (additional checks
+# in validate_compiler_file()).
+compiler_required_provides = [
+	# XXX: incomplete, maybe a generic fill-in for missing stuff because
+	# there's quite a lot of required compiler defines.
+
+	'DUK_USE_COMPILER_STRING',
+
+	'DUK_EXTERNAL_DECL', 'DUK_EXTERNAL',
+	'DUK_INTERNAL_DECL', 'DUK_INTERNAL',
+	'DUK_LOCAL_DECL', 'DUK_LOCAL',
+
+	'DUK_FILE_MACRO', 'DUK_LINE_MACRO', 'DUK_FUNC_MACRO'
+]
+
+#
+#  Miscellaneous helpers
+#
+
+def get_auto_delete_tempdir():
+	tmpdir = tempfile.mkdtemp(suffix='-genconfig')
+	def _f(dirname):
+		print 'Deleting temporary directory: %r' % dirname
+		if os.path.isdir(dirname) and '-genconfig' in dirname:
+			shutil.rmtree(dirname)
+	atexit.register(_f, tmpdir)
+	return tmpdir
+
+def strip_comments_from_lines(lines):
+	# Not exact but close enough.  Doesn't handle string literals etc,
+	# but these are not a concrete issue for scanning preprocessor
+	# #define references.
+	#
+	# Comment contents are stripped of any DUK_ prefixed text to avoid
+	# incorrect requires/provides detection.  Other comment text is kept;
+	# in particular a "/* redefine */" comment must remain intact here.
+	#
+	# Avoid Python 2.6 vs. Python 2.7 argument differences.
+
+	def censor(x):
+		return re.sub(re.compile('DUK_\w+', re.MULTILINE), 'xxx', x.group(0))
+
+	tmp = '\n'.join(lines)
+	tmp = re.sub(re.compile('/\*.*?\*/', re.MULTILINE | re.DOTALL), censor, tmp)
+	tmp = re.sub(re.compile('//.*?$', re.MULTILINE), censor, tmp)
+	return tmp.split('\n')
+
+# Header snippet representation: lines, provides defines, requires defines.
+re_line_provides = re.compile(r'^#(?:define|undef)\s+(\w+).*$')
+re_line_requires = re.compile(r'(DUK_[A-Z0-9_]+)')  # uppercase only, don't match DUK_USE_xxx for example
+class Snippet:
+	lines = None     # lines of text and/or snippets
+	provides = None  # map from define to 'True' for now
+	requires = None  # map from define to 'True' for now
+
+	def __init__(self, lines, provides=None, requires=None, autoscan_requires=True, autoscan_provides=True):
+		self.lines = []
+		if not isinstance(lines, list):
+			raise Exception('Snippet constructor must be a list (not e.g. a string): %s' % repr(lines))
+		for line in lines:
+			if isinstance(line, str):
+				self.lines.append(line)
+			elif isinstance(line, unicode):
+				self.lines.append(line.encode('utf-8'))
+			else:
+				raise Exception('invalid line: %r' % line)
+		self.provides = {}
+		if provides is not None:
+			for k in provides.keys():
+				self.provides[k] = True
+		self.requires = {}
+		if requires is not None:
+			for k in requires.keys():
+				self.requires[k] = True
+
+		stripped_lines = strip_comments_from_lines(lines)
+		# for line in stripped_lines: print(line)
+
+		for line in stripped_lines:
+			# Careful with order, snippet may self-reference its own
+			# defines in which case there's no outward dependency.
+			# (This is not 100% because the order of require/provide
+			# matters and this is not handled now.)
+			#
+			# Also, some snippets may #undef/#define another define but
+			# they don't "provide" the define as such.  For example,
+			# DUK_F_CLANG.h.in undefines DUK_F_GCC defines if clang is
+			# detected: DUK_F_CLANG.h.in is considered to require
+			# DUK_F_GCC but doesn't provide it.  Such redefinitions are
+			# marked "/* redefine */" in the snippets.  They're best
+			# avoided, of course.
+
+			if autoscan_provides:
+				m = re_line_provides.match(line)
+				if m is not None and '/* redefine */' not in line and \
+					len(m.group(1)) > 0 and m.group(1)[-1] != '_':
+					# Don't allow e.g. DUK_USE_ which results from matching DUK_USE_xxx
+					#print('PROVIDES: %r' % m.group(1))
+					self.provides[m.group(1)] = True
+			if autoscan_requires:
+				matches = re.findall(re_line_requires, line)
+				for m in matches:
+					if len(m) > 0 and m[-1] == '_':
+						# Don't allow e.g. DUK_USE_ which results from matching DUK_USE_xxx
+						pass
+					elif m[:7] == 'DUK_OPT':
+						# DUK_OPT_xxx always come from outside
+						pass
+					elif m[:7] == 'DUK_USE':
+						# DUK_USE_xxx are internal and they should not be 'requirements'
+						pass
+					elif self.provides.has_key(m):
+						# Snippet provides it's own require; omit
+						pass
+					else:
+						#print('REQUIRES: %r' % m)
+						self.requires[m] = True
+
+	def fromFile(cls, filename):
+		lines = []
+		with open(filename, 'rb') as f:
+			for line in f:
+				if line[-1] == '\n':
+					line = line[:-1]
+				lines.append(line)
+		return Snippet(lines, autoscan_requires=True, autoscan_provides=True)
+	fromFile = classmethod(fromFile)
+
+	def merge(cls, snippets):
+		ret = Snippet([], [], [])
+		for s in snippets:
+			ret.lines += s.lines
+			for k in s.provides.keys():
+				ret.provides[k] = True
+			for k in s.requires.keys():
+				ret.requires[k] = True
+		return ret
+	merge = classmethod(merge)
+
+# Helper for building a text file from individual lines, injected files, etc.
+# Inserted values are converted to Snippets so that their provides/requires
+# information can be tracked.  When non-C outputs are created, these will be
+# bogus but ignored.
+class FileBuilder:
+	vals = None  # snippet list
+	base_dir = None
+	use_cpp_warning = False
+
+	def __init__(self, base_dir=None, use_cpp_warning=False):
+		self.vals = []
+		self.base_dir = base_dir
+		self.use_cpp_warning = use_cpp_warning
+
+	def line(self, line):
+		self.vals.append(Snippet([ line ]))
+
+	def lines(self, lines):
+		if len(lines) > 0 and lines[-1] == '\n':
+			lines = lines[:-1]  # strip last newline to avoid empty line
+		self.vals.append(Snippet(lines.split('\n')))
+
+	def empty(self):
+		self.vals.append(Snippet([ '' ]))
+
+	def rst_heading(self, title, char, doubled=False):
+		tmp = []
+		if doubled:
+			tmp.append(char * len(title))
+		tmp.append(title)
+		tmp.append(char * len(title))
+		self.vals.append(Snippet(tmp))
+
+	def snippet_relative(self, fn):
+		sn = Snippet.fromFile(os.path.join(self.base_dir, fn))
+		self.vals.append(sn)
+
+	def snippet_absolute(fn):
+		sn = Snippet.fromFile(fn)
+		self.vals.append(sn)
+
+	def cpp_error(self, msg):
+		# XXX: assume no newlines etc
+		self.vals.append(Snippet([ '#error %s' % msg ]))
+
+	def cpp_warning(self, msg):
+		# XXX: assume no newlines etc
+		# XXX: support compiler specific warning mechanisms
+		if self.use_cpp_warning:
+			# C preprocessor '#warning' is often supported
+			self.vals.append(Snippet([ '#warning %s' % msg ]))
+		else:
+			self.vals.append(Snippet([ '/* WARNING: %s */' % msg ]))
+
+	def cpp_warning_or_error(self, msg, is_error=True):
+		if is_error:
+			self.cpp_error(msg)
+		else:
+			self.cpp_warning(msg)
+
+	def chdr_block_heading(self, msg):
+		lines = []
+		lines.append('')
+		lines.append('/*')
+		lines.append(' *  ' + msg)
+		lines.append(' */')
+		lines.append('')
+		self.vals.append(Snippet(lines))
+
+	def join(self):
+		tmp = []
+		for line in self.vals:
+			if not isinstance(line, object):
+				raise Exception('self.vals must be all snippets')
+			for x in line.lines:  # x is a Snippet
+				tmp.append(x)
+		return '\n'.join(tmp)
+
+	def fill_dependencies_for_snippets(self, idx_deps):
+		fill_dependencies_for_snippets(self.vals, idx_deps)
+
+# Insert missing define dependencies into index 'idx_deps' repeatedly
+# until no unsatisfied dependencies exist.  This is used to pull in
+# the required DUK_F_xxx helper defines without pulling them all in.
+# The resolution mechanism also ensures dependencies are pulled in the
+# correct order, i.e. DUK_F_xxx helpers may depend on each other (as
+# long as there are no circular dependencies).
+#
+# XXX: this can be simplified a lot
+def fill_dependencies_for_snippets(snippets, idx_deps):
+	# graph[A] = [ B, ... ] <-> B, ... provide something A requires.
+	graph = {}
+	snlist = []
+	resolved = []   # for printing only
+
+	def add(sn):
+		if sn in snlist:
+			return  # already present
+		snlist.append(sn)
+
+		to_add = []
+
+		for k in sn.requires.keys():
+			if assumed_provides.has_key(k):
+				continue
+
+			found = False
+			for sn2 in snlist:
+				if sn2.provides.has_key(k):
+					if not graph.has_key(sn):
+						graph[sn] = []
+					graph[sn].append(sn2)
+					found = True  # at least one other node provides 'k'
+
+			if not found:
+				#print 'Resolving %r' % k
+				resolved.append(k)
+
+				# Find a header snippet which provides the missing define.
+				# Some DUK_F_xxx files provide multiple defines, so we don't
+				# necessarily know the snippet filename here.
+
+				sn_req = None
+				for sn2 in helper_snippets:
+					if sn2.provides.has_key(k):
+						sn_req = sn2
+						break
+				if sn_req is None:
+					print(repr(sn.lines))
+					raise Exception('cannot resolve missing require: %r' % k)
+
+				# Snippet may have further unresolved provides; add recursively
+				to_add.append(sn_req)
+
+				if not graph.has_key(sn):
+					graph[sn] = []
+				graph[sn].append(sn_req)
+
+		for sn in to_add:
+			add(sn)
+
+	# Add original snippets.  This fills in the required nodes
+	# recursively.
+	for sn in snippets:
+		add(sn)
+
+	# Figure out fill-ins by looking for snippets not in original
+	# list and without any unserialized dependent nodes.
+	handled = {}
+	for sn in snippets:
+		handled[sn] = True
+	keepgoing = True
+	while keepgoing:
+		keepgoing = False
+		for sn in snlist:
+			if handled.has_key(sn):
+				continue
+
+			success = True
+			for dep in graph.get(sn, []):
+				if not handled.has_key(dep):
+					success = False
+			if success:
+				snippets.insert(idx_deps, sn)
+				idx_deps += 1
+				snippets.insert(idx_deps, Snippet([ '' ]))
+				idx_deps += 1
+				handled[sn] = True
+				keepgoing = True
+				break
+
+	# XXX: detect and handle loops cleanly
+	for sn in snlist:
+		if handled.has_key(sn):
+			continue
+		print('UNHANDLED KEY')
+		print('PROVIDES: %r' % sn.provides)
+		print('REQUIRES: %r' % sn.requires)
+		print('\n'.join(sn.lines))
+
+#	print(repr(graph))
+#	print(repr(snlist))
+	print 'Resolved helper defines: %r' % resolved
+
+def serialize_snippet_list(snippets):
+	ret = []
+
+	emitted_provides = {}
+	for k in assumed_provides.keys():
+		emitted_provides[k] = True
+
+	for sn in snippets:
+		ret += sn.lines
+		for k in sn.provides.keys():
+			emitted_provides[k] = True
+		for k in sn.requires.keys():
+			if not emitted_provides.has_key(k):
+				# XXX: conditional warning, happens in some normal cases
+				#print('WARNING: define %r required, not provided so far' % k)
+				pass
+
+	return '\n'.join(ret)
+
+def remove_duplicate_newlines(x):
+	ret = []
+	empty = False
+	for line in x.split('\n'):
+		if line == '':
+			if empty:
+				pass
+			else:
+				ret.append(line)
+			empty = True
+		else:
+			empty = False
+			ret.append(line)
+	return '\n'.join(ret)
+
+def scan_use_defs(dirname):
+	global use_defs, use_defs_list
+	use_defs = {}
+	use_defs_list = []
+
+	for fn in os.listdir(dirname):
+		root, ext = os.path.splitext(fn)
+		if not root.startswith('DUK_USE_') or ext != '.yaml':
+			continue
+		with open(os.path.join(dirname, fn), 'rb') as f:
+			doc = yaml.load(f)
+			if doc.get('example', False):
+				continue
+			if doc.get('unimplemented', False):
+				print('WARNING: unimplemented: %s' % fn)
+				continue
+			dockeys = doc.keys()
+			for k in dockeys:
+				if not k in allowed_use_meta_keys:
+					print('WARNING: unknown key %s in metadata file %s' % (k, fn))
+			for k in required_use_meta_keys:
+				if not k in dockeys:
+					print('WARNING: missing key %s in metadata file %s' % (k, fn))
+
+			use_defs[doc['define']] = doc
+
+	keys = use_defs.keys()
+	keys.sort()
+	for k in keys:
+		use_defs_list.append(use_defs[k])
+
+def scan_opt_defs(dirname):
+	global opt_defs, opt_defs_list
+	opt_defs = {}
+	opt_defs_list = []
+
+	for fn in os.listdir(dirname):
+		root, ext = os.path.splitext(fn)
+		if not root.startswith('DUK_OPT_') or ext != '.yaml':
+			continue
+		with open(os.path.join(dirname, fn), 'rb') as f:
+			doc = yaml.load(f)
+			if doc.get('example', False):
+				continue
+			if doc.get('unimplemented', False):
+				print('WARNING: unimplemented: %s' % fn)
+				continue
+			dockeys = doc.keys()
+			for k in dockeys:
+				if not k in allowed_opt_meta_keys:
+					print('WARNING: unknown key %s in metadata file %s' % (k, fn))
+			for k in required_opt_meta_keys:
+				if not k in dockeys:
+					print('WARNING: missing key %s in metadata file %s' % (k, fn))
+
+			opt_defs[doc['define']] = doc
+
+	keys = opt_defs.keys()
+	keys.sort()
+	for k in keys:
+		opt_defs_list.append(opt_defs[k])
+
+def scan_use_tags():
+	global use_tags, use_tags_list
+	use_tags = {}
+
+	for doc in use_defs_list:
+		for tag in doc.get('tags', []):
+			use_tags[tag] = True
+
+	use_tags_list = use_tags.keys()
+	use_tags_list.sort()
+
+def scan_tags_meta(filename):
+	global tags_meta
+
+	with open(filename, 'rb') as f:
+		tags_meta = yaml.load(f)
+
+def scan_snippets(dirname):
+	global helper_snippets
+	helper_snippets = []
+
+	for fn in os.listdir(dirname):
+		if (fn[0:6] != 'DUK_F_'):
+			continue
+		#print('Autoscanning snippet: %s' % fn)
+		helper_snippets.append(Snippet.fromFile(os.path.join(dirname, fn)))
+
+def validate_platform_file(filename):
+	sn = Snippet.fromFile(filename)
+
+	# XXX: move required provides/defines into metadata only
+	for req in platform_required_provides:
+		if req not in sn.provides:
+			raise Exception('Platform %s is missing %s' % (filename, req))
+
+	if not ('DUK_USE_SETJMP' in sn.provides or 'DUK_USE_UNDERSCORE_SETJMP' in sn.provides or
+	        'DUK_USE_SIGSETJMP' in sn.provides):
+		raise Exception('Platform %s is missing a setjmp provider' % filename)
+
+def validate_architecture_file(filename):
+	sn = Snippet.fromFile(filename)
+
+	# XXX: move required provides/defines into metadata only
+	for req in architecture_required_provides:
+		if req not in sn.provides:
+			raise Exception('Architecture %s is missing %s' % (filename, req))
+
+def validate_compiler_file(filename):
+	sn = Snippet.fromFile(filename)
+
+	# XXX: move required provides/defines into metadata only
+	for req in compiler_required_provides:
+		if req not in sn.provides:
+			raise Exception('Architecture %s is missing %s' % (filename, req))
+
+def get_tag_title(tag):
+	meta = tags_meta.get(tag, None)
+	if meta is None:
+		return tag
+	else:
+		return meta.get('title', tag)
+
+def get_tag_description(tag):
+	meta = tags_meta.get(tag, None)
+	if meta is None:
+		return None
+	else:
+		return meta.get('description', None)
+
+def get_tag_list_with_preferred_order(preferred):
+	tags = []
+
+	# Preferred tags first
+	for tag in preferred:
+		if tag not in tags:
+			tags.append(tag)
+
+	# Remaining tags in alphabetic order
+	for tag in use_tags_list:
+		if tag not in tags:
+			tags.append(tag)
+
+	#print('Effective tag order: %r' % tags)
+	return tags
+
+def rst_format(text):
+	# XXX: placeholder, need to decide on markup conventions for YAML files
+	ret = []
+	for para in text.split('\n'):
+		if para == '':
+			continue
+		ret.append(para)
+	return '\n\n'.join(ret)
+
+def cint_encode(x):
+	if not isinstance(x, (int, long)):
+		raise Exception('invalid input: %r' % x)
+
+	# XXX: unsigned constants?
+	if x > 0x7fffffff or x < -0x80000000:
+		return '%dLL' % x
+	elif x > 0x7fff or x < -0x8000:
+		return '%dL' % x
+	else:
+		return '%d' % x
+
+def cstr_encode(x):
+	if isinstance(x, unicode):
+		x = x.encode('utf-8')
+	if not isinstance(x, str):
+		raise Exception('invalid input: %r' % x)
+
+	res = '"'
+	term = False
+	has_terms = False
+	for c in x:
+		if term:
+			# Avoid ambiguous hex escapes
+			res += '" "'
+			term = False
+			has_terms = True
+		o = ord(c)
+		if o < 0x20 or o > 0x7e or c in '"\\':
+			res += '\\x%02x' % o
+			term = True
+		else:
+			res += c
+	res += '"'
+
+	if has_terms:
+		res = '(' + res + ')'
+
+	return res
+
+#
+#  Autogeneration of option documentation
+#
+
+# Shared helper to generate DUK_OPT_xxx and DUK_USE_xxx documentation.
+# XXX: unfinished placeholder
+def generate_option_documentation(opts, opt_list=None, rst_title=None, include_default=False):
+	ret = FileBuilder(use_cpp_warning=opts.use_cpp_warning)
+
+	tags = get_tag_list_with_preferred_order(doc_tag_order)
+
+	title = rst_title
+	ret.rst_heading(title, '=', doubled=True)
+
+	handled = {}
+
+	for tag in tags:
+		first = True
+
+		for doc in opt_list:
+			if tag != doc['tags'][0]:  # sort under primary tag
+				continue
+			dname = doc['define']
+			desc = doc.get('description', None)
+
+			if handled.has_key(dname):
+				raise Exception('define handled twice, should not happen: %r' % dname)
+			handled[dname] = True
+
+			if first:  # emit tag heading only if there are subsections
+				ret.empty()
+				ret.rst_heading(get_tag_title(tag), '=')
+
+				tag_desc = get_tag_description(tag)
+				if tag_desc is not None:
+					ret.empty()
+					ret.line(rst_format(tag_desc))
+				first = False
+
+			ret.empty()
+			ret.rst_heading(dname, '-')
+
+			if desc is not None:
+				ret.empty()
+				ret.line(rst_format(desc))
+
+			if include_default:
+				ret.empty()
+				ret.line('Default: ``' + str(doc['default']) + '``')  # XXX: rst or other format
+
+	for doc in opt_list:
+		dname = doc['define']
+		if not handled.has_key(dname):
+			raise Exception('unhandled define (maybe missing from tags list?): %r' % dname)
+
+	ret.empty()
+	return ret.join()
+
+def generate_feature_option_documentation(opts):
+	return generate_option_documentation(opts, opt_list=opt_defs_list, rst_title='Duktape feature options', include_default=False)
+
+def generate_config_option_documentation(opts):
+	return generate_option_documentation(opts, opt_list=use_defs_list, rst_title='Duktape config options', include_default=True)
+
+#
+#  Helpers for duk_config.h generation
+#
+
+def get_forced_options(opts):
+	# Forced options, last occurrence wins (allows a base config file to be
+	# overridden by a more specific one).
+	forced_opts = {}
+	for val in opts.force_options_yaml:
+		doc = yaml.load(StringIO.StringIO(val))
+		for k in doc.keys():
+			if use_defs.has_key(k):
+				pass  # key is known
+			else:
+				print 'WARNING: option override key %s not defined in metadata, ignoring' % k
+			forced_opts[k] = doc[k]  # shallow copy
+
+	print 'Overrides: %s' % json.dumps(forced_opts)
+
+	return forced_opts
+
+# Emit a default #define / #undef for an option based on
+# a config option metadata node (parsed YAML doc).
+def emit_default_from_config_meta(ret, doc, forced_opts, undef_done):
+	defname = doc['define']
+	defval = forced_opts.get(defname, doc['default'])
+
+	if defval == True:
+		ret.line('#define ' + defname)
+	elif defval == False:
+		if not undef_done:
+			ret.line('#undef ' + defname)
+		else:
+			# Default value is false, and caller has emitted
+			# an unconditional #undef, so don't emit a duplicate
+			pass
+	elif isinstance(defval, (int, long)):
+		# integer value
+		ret.line('#define ' + defname + ' ' + cint_encode(defval))
+	elif isinstance(defval, (str, unicode)):
+		# verbatim value
+		ret.line('#define ' + defname + ' ' + defval)
+	elif isinstance(defval, dict):
+		if defval.has_key('verbatim'):
+			# verbatim text for the entire line
+			ret.line(defval['verbatim'])
+		elif defval.has_key('string'):
+			# C string value
+			ret.line('#define ' + defname + ' ' + cstr_encode(defval['string']))
+		else:
+			raise Exception('unsupported value for option %s: %r' % (defname, defval))
+	else:
+		raise Exception('unsupported value for option %s: %r' % (defname, defval))
+
+# Add a header snippet for detecting presence of DUK_OPT_xxx feature
+# options which will be removed in Duktape 2.x.
+def add_legacy_feature_option_checks(opts, ret):
+	ret.chdr_block_heading('Checks for legacy feature options (DUK_OPT_xxx)')
+
+	defs = []
+	for doc in opt_defs_list:
+		if doc['define'] not in defs:
+			defs.append(doc['define'])
+	for doc in use_defs_list:
+		for dname in doc.get('related_feature_defines', []):
+			if dname not in defs:
+				defs.append(dname)
+	defs.sort()
+
+	for optname in defs:
+		suggested = []
+		for doc in use_defs_list:
+			if optname in doc.get('related_feature_defines', []):
+				suggested.append(doc['define'])
+		ret.empty()
+		ret.line('#if defined(%s)' % optname)
+		if len(suggested) > 0:
+			ret.cpp_warning_or_error('unsupported legacy feature option %s used, consider options: %s' % (optname, ', '.join(suggested)), opts.sanity_strict)
+		else:
+			ret.cpp_warning_or_error('unsupported legacy feature option %s used' % optname, opts.sanity_strict)
+		ret.line('#endif')
+
+	ret.empty()
+
+# Add a header snippet for checking consistency of DUK_USE_xxx config
+# options, e.g. inconsistent options, invalid option values.
+def add_config_option_checks(opts, ret):
+	ret.chdr_block_heading('Checks for config option consistency (DUK_USE_xxx)')
+
+	defs = []
+	for doc in use_defs_list:
+		if doc['define'] not in defs:
+			defs.append(doc['define'])
+	defs.sort()
+
+	for optname in defs:
+		doc = use_defs[optname]
+		dname = doc['define']
+
+		# XXX: more checks
+
+		if doc.get('removed', None) is not None:
+			ret.empty()
+			ret.line('#if defined(%s)' % dname)
+			ret.cpp_warning_or_error('unsupported config option used (option has been removed): %s' % dname, opts.sanity_strict)
+			ret.line('#endif')
+		elif doc.get('deprecated', None) is not None:
+			ret.empty()
+			ret.line('#if defined(%s)' % dname)
+			ret.cpp_warning_or_error('unsupported config option used (option has been deprecated): %s' % dname, opts.sanity_strict)
+			ret.line('#endif')
+
+		for req in doc.get('requires', []):
+			ret.empty()
+			ret.line('#if defined(%s) && !defined(%s)' % (dname, req))
+			ret.cpp_warning_or_error('config option %s requires option %s (which is missing)' % (dname, req), opts.sanity_strict)
+			ret.line('#endif')
+
+		for req in doc.get('conflicts', []):
+			ret.empty()
+			ret.line('#if defined(%s) && defined(%s)' % (dname, req))
+			ret.cpp_warning_or_error('config option %s conflicts with option %s (which is also defined)' % (dname, req), opts.sanity_strict)
+			ret.line('#endif')
+
+	ret.empty()
+
+# Add a header snippet for providing a __OVERRIDE_DEFINES__ section.
+def add_override_defines_section(opts, ret):
+	ret.empty()
+	ret.line('/*')
+	ret.line(' *  You may add overriding #define/#undef directives below for')
+	ret.line(' *  customization.  You of course cannot un-#include or un-typedef')
+	ret.line(' *  anything; these require direct changes above.')
+	ret.line(' */')
+	ret.empty()
+	ret.line('/* __OVERRIDE_DEFINES__ */')
+	ret.empty()
+
+# Add automatic DUK_OPT_XXX and DUK_OPT_NO_XXX handling for backwards
+# compatibility with Duktape 1.2 and before.
+def add_feature_option_handling(opts, ret, forced_opts):
+	ret.chdr_block_heading('Feature option handling')
+
+	for doc in use_defs_list:
+		# If a related feature option exists, it can be used to force
+		# enable/disable the target feature.  If neither feature option
+		# (DUK_OPT_xxx or DUK_OPT_NO_xxx) is given, revert to default.
+
+		config_define = doc['define']
+
+		feature_define = None
+		feature_no_define = None
+		inverted = False
+		if doc.has_key('feature_enables'):
+			feature_define = doc['feature_enables']
+		elif doc.has_key('feature_disables'):
+			feature_define = doc['feature_disables']
+			inverted = True
+		else:
+			pass
+
+		if feature_define is not None:
+			feature_no_define = 'DUK_OPT_NO_' + feature_define[8:]
+			ret.line('#if defined(%s)' % feature_define)
+			if inverted:
+				ret.line('#undef %s' % config_define)
+			else:
+				ret.line('#define %s' % config_define)
+			ret.line('#elif defined(%s)' % feature_no_define)
+			if inverted:
+				ret.line('#define %s' % config_define)
+			else:
+				ret.line('#undef %s' % config_define)
+			ret.line('#else')
+			undef_done = False
+			emit_default_from_config_meta(ret, doc, forced_opts, undef_done)
+			ret.line('#endif')
+		elif doc.has_key('feature_snippet'):
+			ret.lines(doc['feature_snippet'])
+		else:
+			pass
+
+		ret.empty()
+
+	ret.empty()
+
+# Development time helper: add DUK_ACTIVE which provides a runtime C string
+# indicating what DUK_USE_xxx config options are active at run time.  This
+# is useful in genconfig development so that one can e.g. diff the active
+# run time options of two headers.  This is intended just for genconfig
+# development and is not available in normal headers.
+def add_duk_active_defines_macro(ret):
+	ret.chdr_block_heading('DUK_ACTIVE_DEFINES macro (development only)')
+
+	idx = 0
+	for doc in use_defs_list:
+		defname = doc['define']
+
+		ret.line('#if defined(%s)' % defname)
+		ret.line('#define DUK_ACTIVE_DEF%d " %s"' % (idx, defname))
+		ret.line('#else')
+		ret.line('#define DUK_ACTIVE_DEF%d ""' % idx)
+		ret.line('#endif')
+
+		idx += 1
+
+	tmp = []
+	for i in xrange(idx):
+		tmp.append('DUK_ACTIVE_DEF%d' % i)
+
+	ret.line('#define DUK_ACTIVE_DEFINES ("Active: ["' + ' '.join(tmp) + ' " ]")')
+
+#
+#  duk_config.h generation
+#
+
+# Generate the default duk_config.h which provides automatic detection of
+# platform, compiler, architecture, and features for major platforms.
+# Use manually written monolithic header snippets from Duktape 1.2 for
+# generating the header.  This header is Duktape 1.2 compatible and supports
+# DUK_OPT_xxx feature options.  Later on the DUK_OPT_xxx options will be
+# removed and users can override DUK_USE_xxx flags directly by modifying
+# duk_config.h or by generating a new header using genconfig.
+def generate_autodetect_duk_config_header(opts, meta_dir):
+	ret = FileBuilder(base_dir=os.path.join(meta_dir, 'header-snippets'), \
+	                  use_cpp_warning=opts.use_cpp_warning)
+
+	forced_opts = get_forced_options(opts)
+
+	ret.snippet_relative('comment_prologue.h.in')
+	ret.empty()
+
+	ret.line('#ifndef DUK_CONFIG_H_INCLUDED')
+	ret.line('#define DUK_CONFIG_H_INCLUDED')
+	ret.empty()
+
+	# Compiler features, processor/architecture, OS, compiler
+	ret.snippet_relative('compiler_features.h.in')
+	ret.empty()
+	ret.snippet_relative('rdtsc.h.in')  # XXX: move downwards
+	ret.empty()
+	ret.snippet_relative('platform1.h.in')
+	ret.empty()
+
+	# Feature selection, system include, Date provider
+	# Most #include statements are here
+	ret.snippet_relative('platform2.h.in')
+	ret.empty()
+	ret.snippet_relative('ullconsts.h.in')
+	ret.empty()
+	ret.snippet_relative('libc.h.in')
+	ret.empty()
+
+	# Number types
+	ret.snippet_relative('types1.h.in')
+	ret.line('#if defined(DUK_F_HAVE_INTTYPES)')
+	ret.line('/* C99 or compatible */')
+	ret.empty()
+	ret.snippet_relative('types_c99.h.in')
+	ret.empty()
+	ret.line('#else  /* C99 types */')
+	ret.empty()
+	ret.snippet_relative('types_legacy.h.in')
+	ret.empty()
+	ret.line('#endif  /* C99 types */')
+	ret.empty()
+	ret.snippet_relative('types2.h.in')
+	ret.empty()
+	ret.snippet_relative('64bitops.h.in')
+	ret.empty()
+
+	# Alignment
+	ret.snippet_relative('alignment.h.in')
+	ret.empty()
+
+	# Object layout
+	ret.snippet_relative('object_layout.h.in')
+	ret.empty()
+
+	# Byte order
+	ret.snippet_relative('byteorder.h.in')
+	ret.empty()
+
+	# Packed duk_tval
+	ret.snippet_relative('packed_tval.h.in')
+	ret.empty()
+
+	# Detect 'fast math'
+	ret.snippet_relative('reject_fast_math.h.in')
+	ret.empty()
+
+	# IEEE double constants
+	ret.snippet_relative('double_const.h.in')
+	ret.empty()
+
+	# Math and other ANSI replacements, NetBSD workaround, paranoid math, paranoid Date
+	ret.snippet_relative('repl_math.h.in')
+	ret.empty()
+	ret.snippet_relative('paranoid_date.h.in')
+	ret.empty()
+	ret.snippet_relative('repl_ansi.h.in')
+	ret.empty()
+
+	# Platform function pointers
+	ret.snippet_relative('platform_funcptr.h.in')
+	ret.empty()
+
+	# General compiler stuff
+	ret.snippet_relative('stringify.h.in')
+	ret.empty()
+	ret.snippet_relative('segfault.h.in')
+	ret.empty()
+	ret.snippet_relative('unreferenced.h.in')
+	ret.empty()
+	ret.snippet_relative('noreturn.h.in')
+	ret.empty()
+	ret.snippet_relative('unreachable.h.in')
+	ret.empty()
+	ret.snippet_relative('likely.h.in')
+	ret.empty()
+	ret.snippet_relative('inline.h.in')
+	ret.empty()
+	ret.snippet_relative('visibility.h.in')
+	ret.empty()
+	ret.snippet_relative('file_line_func.h.in')
+	ret.empty()
+	ret.snippet_relative('byteswap.h.in')
+	ret.empty()
+
+	# Arhitecture, OS, and compiler strings
+	ret.snippet_relative('arch_string.h.in')
+	ret.empty()
+	ret.snippet_relative('os_string.h.in')
+	ret.empty()
+	ret.snippet_relative('compiler_string.h.in')
+	ret.empty()
+
+	# Target info
+	ret.snippet_relative('target_info.h.in')
+	ret.empty()
+
+	# Longjmp handling
+	ret.snippet_relative('longjmp.h.in')
+	ret.empty()
+
+	# Unsorted flags, contains almost all actual Duktape-specific
+	# but platform independent features
+	ret.snippet_relative('unsorted_flags.h.in')
+	ret.empty()
+
+	# User declarations
+	ret.snippet_relative('user_declare.h.in')
+	ret.empty()
+
+	# Emit forced options.  If a corresponding option is already defined
+	# by a snippet above, #undef it first.
+
+	tmp = Snippet(ret.join().split('\n'))
+	first_forced = True
+	for doc in use_defs_list:
+		defname = doc['define']
+
+		if doc.get('removed', None) is not None and opts.omit_removed_config_options:
+			continue
+		if doc.get('deprecated', None) is not None and opts.omit_deprecated_config_options:
+			continue
+		if doc.get('unused', False) == True and opts.omit_unused_config_options:
+			continue
+		if not forced_opts.has_key(defname):
+			continue
+
+		if not doc.has_key('default'):
+			raise Exception('config option %s is missing default value' % defname)
+
+		if first_forced:
+			ret.chdr_block_heading('Forced options')
+			first_forced = False
+
+		undef_done = False
+		if tmp.provides.has_key(defname):
+			ret.line('#undef ' + defname)
+			undef_done = True
+
+		emit_default_from_config_meta(ret, doc, forced_opts, undef_done)
+
+	ret.empty()
+
+	# If manually-edited snippets don't #define or #undef a certain
+	# config option, emit a default value here.  This is useful to
+	# fill-in for new config options not covered by manual snippets
+	# (which is intentional).
+
+	tmp = Snippet(ret.join().split('\n'))
+	need = {}
+	for doc in use_defs_list:
+		if doc.get('removed', None) is not None:  # XXX: check version
+			continue
+		need[doc['define']] = True
+	for k in tmp.provides.keys():
+		if need.has_key(k):
+			del need[k]
+	need_keys = sorted(need.keys())
+
+	if len(need_keys) > 0:
+		ret.chdr_block_heading('Autogenerated defaults')
+
+		for k in need_keys:
+			#print('config option %s not covered by manual snippets, emitting default automatically' % k)
+			emit_default_from_config_meta(ret, use_defs[k], {}, False)
+
+		ret.empty()
+
+	ret.snippet_relative('custom_header.h.in')
+	ret.empty()
+
+	if len(opts.fixup_header_lines) > 0:
+		ret.chdr_block_heading('Fixups')
+		for line in opts.fixup_header_lines:
+			ret.line(line)
+		ret.empty()
+
+	add_override_defines_section(opts, ret)
+
+	# Date provider snippet is after custom header and overrides, so that
+	# the user may define e.g. DUK_USE_DATE_NOW_GETTIMEOFDAY in their
+	# custom header.
+	ret.snippet_relative('date_provider.h.in')
+	ret.empty()
+
+	# Sanity checks
+	# XXX: use autogenerated sanity checks instead
+	ret.snippet_relative('sanity.h.in')
+	ret.empty()
+
+	if opts.emit_legacy_feature_check:
+		# XXX: this doesn't really make sense for the autodetect
+		# header yet, because sanity.h.in already covers these.
+		add_legacy_feature_option_checks(opts, ret)
+	if opts.emit_config_sanity_check:
+		add_config_option_checks(opts, ret)
+	if opts.add_active_defines_macro:
+		add_duk_active_defines_macro(ret)
+
+	ret.line('#endif  /* DUK_CONFIG_H_INCLUDED */')
+	ret.empty()  # for trailing newline
+	return remove_duplicate_newlines(ret.join())
+
+# Generate a duk_config.h where platform, architecture, and compiler are
+# all either autodetected or specified by user.  When autodetection is
+# used, the generated header is based on modular snippets and metadata to
+# be more easily maintainable than manually edited monolithic snippets.
+#
+# This approach will replace the legacy autodetect header in Duktape 1.4,
+# and most likely the separate barebones header also.
+#
+# The generated header is Duktape 1.2 compatible for now, and supports
+# DUK_OPT_xxx feature options.  Later on the DUK_OPT_xxx options will be
+# removed and user code overrides DUK_USE_xxx flags directly by modifying
+# duk_config.h manually or by generating a new header using genconfig.
+def generate_autodetect_duk_config_header_modular(opts, meta_dir):
+	ret = FileBuilder(base_dir=os.path.join(meta_dir, 'header-snippets'), \
+	                  use_cpp_warning=opts.use_cpp_warning)
+
+	forced_opts = get_forced_options(opts)
+
+	platforms = None
+	with open(os.path.join(meta_dir, 'platforms.yaml'), 'rb') as f:
+		platforms = yaml.load(f)
+	architectures = None
+	with open(os.path.join(meta_dir, 'architectures.yaml'), 'rb') as f:
+		architectures = yaml.load(f)
+	compilers = None
+	with open(os.path.join(meta_dir, 'compilers.yaml'), 'rb') as f:
+		compilers = yaml.load(f)
+
+	ret.line('/*')
+	ret.line(' *  duk_config.h autodetect header generated by genconfig.py.')
+	ret.line(' *')
+	ret.line(' *  Git commit: %s' % opts.git_commit or 'n/a')
+	ret.line(' *  Git describe: %s' % opts.git_describe or 'n/a')
+	ret.line(' *')
+	if opts.platform is not None:
+		ret.line(' *  Platform: ' + opts.platform)
+	else:
+		ret.line(' *  Supported platforms:')
+		for platf in platforms['autodetect']:
+			ret.line(' *      - %s' % platf.get('name', platf.get('check')))
+	ret.line(' *')
+	if opts.architecture is not None:
+		ret.line(' *  Architecture: ' + opts.architecture)
+	else:
+		ret.line(' *  Supported architectures:')
+		for arch in architectures['autodetect']:
+			ret.line(' *      - %s' % arch.get('name', arch.get('check')))
+	ret.line(' *')
+	if opts.compiler is not None:
+		ret.line(' *  Compiler: ' + opts.compiler)
+	else:
+		ret.line(' *  Supported compilers:')
+		for comp in compilers['autodetect']:
+			ret.line(' *      - %s' % comp.get('name', comp.get('check')))
+	ret.line(' *')
+	ret.line(' */')
+	ret.empty()
+	ret.line('#ifndef DUK_CONFIG_H_INCLUDED')
+	ret.line('#define DUK_CONFIG_H_INCLUDED')
+	ret.empty()
+
+	ret.chdr_block_heading('Intermediate helper defines')
+
+	idx_deps = len(ret.vals)  # position where to emit dependencies
+
+	# Feature selection, system include, Date provider
+	# Most #include statements are here
+
+	if opts.platform is not None:
+		ret.chdr_block_heading('Platform: ' + opts.platform)
+
+		ret.snippet_relative('platform_cppextras.h.in')
+		ret.empty()
+
+		# XXX: better to lookup platforms metadata
+		include = 'platform_%s.h.in' % opts.platform
+		validate_platform_file(os.path.join(meta_dir, 'header-snippets', include))
+		ret.snippet_relative(include)
+	else:
+		ret.chdr_block_heading('Platform autodetection')
+
+		ret.snippet_relative('platform_cppextras.h.in')
+		ret.empty()
+
+		for idx, platf in enumerate(platforms['autodetect']):
+			check = platf.get('check', None)
+			include = platf['include']
+			validate_platform_file(os.path.join(meta_dir, 'header-snippets', include))
+
+			if idx == 0:
+				ret.line('#if defined(%s)' % check)
+			else:
+				if check is None:
+					ret.line('#else')
+				else:
+					ret.line('#elif defined(%s)' % check)
+			ret.snippet_relative(include)
+		ret.line('#endif  /* autodetect platform */')
+
+	ret.snippet_relative('platform_sharedincludes.h.in')
+	ret.empty()
+
+	if opts.architecture is not None:
+		ret.chdr_block_heading('Architecture: ' + opts.architecture)
+
+		# XXX: better to lookup architectures metadata
+		include = 'architecture_%s.h.in' % opts.architecture
+		validate_architecture_file(os.path.join(meta_dir, 'header-snippets', include))
+		ret.snippet_relative(include)
+	else:
+		ret.chdr_block_heading('Architecture autodetection')
+
+		for idx, arch in enumerate(architectures['autodetect']):
+			check = arch.get('check', None)
+			include = arch['include']
+			validate_architecture_file(os.path.join(meta_dir, 'header-snippets', include))
+
+			if idx == 0:
+				ret.line('#if defined(%s)' % check)
+			else:
+				if check is None:
+					ret.line('#else')
+				else:
+					ret.line('#elif defined(%s)' % check)
+			ret.snippet_relative(include)
+		ret.line('#endif  /* autodetect architecture */')
+
+	if opts.compiler is not None:
+		ret.chdr_block_heading('Compiler: ' + opts.compiler)
+
+		# XXX: better to lookup compilers metadata
+		include = 'compiler_%s.h.in' % opts.compiler
+		validate_compiler_file(os.path.join(meta_dir, 'header-snippets', include))
+		ret.snippet_relative(include)
+	else:
+		ret.chdr_block_heading('Compiler autodetection')
+
+		for idx, comp in enumerate(compilers['autodetect']):
+			check = comp.get('check', None)
+			include = comp['include']
+			validate_compiler_file(os.path.join(meta_dir, 'header-snippets', include))
+
+			if idx == 0:
+				ret.line('#if defined(%s)' % check)
+			else:
+				if check is None:
+					ret.line('#else')
+				else:
+					ret.line('#elif defined(%s)' % check)
+			ret.snippet_relative(include)
+		ret.line('#endif  /* autodetect compiler */')
+
+	# FIXME: The snippets below have some conflicts with the platform,
+	# architecture, and compiler snippets files included above.  These
+	# need to be resolved so that (a) each define is only provided from
+	# one place or (b) the latter definition is a "fill-in" which is
+	# only used when a certain define is missing from e.g. a compiler
+	# snippet (useful for e.g. compiler defines which have sane, standard
+	# defaults).
+
+	# FIXME: __uclibc__ needs stdlib.h, but it really is the only exception
+	ret.snippet_relative('libc.h.in')
+	ret.empty()
+
+	# Number types
+	ret.snippet_relative('types1.h.in')
+	ret.line('#if defined(DUK_F_HAVE_INTTYPES)')
+	ret.line('/* C99 or compatible */')
+	ret.empty()
+	ret.snippet_relative('types_c99.h.in')
+	ret.empty()
+	ret.line('#else  /* C99 types */')
+	ret.empty()
+	ret.snippet_relative('types_legacy.h.in')
+	ret.empty()
+	ret.line('#endif  /* C99 types */')
+	ret.empty()
+	ret.snippet_relative('types2.h.in')
+	ret.empty()
+	ret.snippet_relative('64bitops.h.in')
+	ret.empty()
+
+	# Alignment
+	ret.snippet_relative('alignment.h.in')
+	ret.empty()
+
+	# Object layout
+	ret.snippet_relative('object_layout.h.in')
+	ret.empty()
+
+	# Byte order
+	# FIXME: from the architecture snippet
+	ret.snippet_relative('byteorder.h.in')
+	ret.empty()
+
+	# Packed duk_tval
+	# FIXME: from the architecture snippet
+	ret.snippet_relative('packed_tval.h.in')
+	ret.empty()
+
+	# Detect 'fast math'
+	ret.snippet_relative('reject_fast_math.h.in')
+	ret.empty()
+
+	# IEEE double constants
+	# FIXME: these should maybe be 'fill-ins' if previous headers
+	# didn't provide something
+	ret.snippet_relative('double_const.h.in')
+	ret.empty()
+
+	# Math and other ANSI replacements, NetBSD workaround, paranoid math, paranoid Date
+	ret.snippet_relative('repl_math.h.in')
+	ret.empty()
+	ret.snippet_relative('paranoid_date.h.in')
+	ret.empty()
+	ret.snippet_relative('repl_ansi.h.in')
+	ret.empty()
+
+	# Platform function pointers
+	ret.snippet_relative('platform_funcptr.h.in')
+	ret.empty()
+
+	# General compiler stuff
+	ret.snippet_relative('stringify.h.in')
+	ret.empty()
+	ret.snippet_relative('segfault.h.in')
+	ret.empty()
+	ret.snippet_relative('unreferenced.h.in')
+	ret.empty()
+	ret.snippet_relative('noreturn.h.in')
+	ret.empty()
+	ret.snippet_relative('unreachable.h.in')
+	ret.empty()
+	ret.snippet_relative('likely.h.in')
+	ret.empty()
+	ret.snippet_relative('inline.h.in')
+	ret.empty()
+	ret.snippet_relative('visibility.h.in')
+	ret.empty()
+	ret.snippet_relative('file_line_func.h.in')
+	ret.empty()
+	ret.snippet_relative('byteswap.h.in')
+	ret.empty()
+
+	# These come directly from platform, architecture, and compiler
+	# snippets.
+	#ret.snippet_relative('arch_string.h.in')
+	#ret.empty()
+	#ret.snippet_relative('os_string.h.in')
+	#ret.empty()
+	#ret.snippet_relative('compiler_string.h.in')
+	#ret.empty()
+	#ret.snippet_relative('longjmp.h.in')
+	#ret.empty()
+
+	# Target info
+	ret.snippet_relative('target_info.h.in')
+	ret.empty()
+
+	# Automatic DUK_OPT_xxx feature option handling
+	# FIXME: platform setjmp/longjmp defines now conflict with this
+	if True:
+		# Unsorted flags, contains almost all actual Duktape-specific
+		# but platform independent features
+		#ret.snippet_relative('unsorted_flags.h.in')
+		#ret.empty()
+
+		add_feature_option_handling(opts, ret, forced_opts)
+
+	ret.snippet_relative('user_declare.h.in')
+	ret.empty()
+
+	# Emit forced options.  If a corresponding option is already defined
+	# by a snippet above, #undef it first.
+
+	tmp = Snippet(ret.join().split('\n'))
+	first_forced = True
+	for doc in use_defs_list:
+		defname = doc['define']
+
+		if doc.get('removed', None) is not None and opts.omit_removed_config_options:
+			continue
+		if doc.get('deprecated', None) is not None and opts.omit_deprecated_config_options:
+			continue
+		if doc.get('unused', False) == True and opts.omit_unused_config_options:
+			continue
+		if not forced_opts.has_key(defname):
+			continue
+
+		if not doc.has_key('default'):
+			raise Exception('config option %s is missing default value' % defname)
+
+		if first_forced:
+			ret.chdr_block_heading('Forced options')
+			first_forced = False
+
+		undef_done = False
+		if tmp.provides.has_key(defname):
+			ret.line('#undef ' + defname)
+			undef_done = True
+
+		emit_default_from_config_meta(ret, doc, forced_opts, undef_done)
+
+	ret.empty()
+
+	# If manually-edited snippets don't #define or #undef a certain
+	# config option, emit a default value here.  This is useful to
+	# fill-in for new config options not covered by manual snippets
+	# (which is intentional).
+
+	tmp = Snippet(ret.join().split('\n'))
+	need = {}
+	for doc in use_defs_list:
+		if doc.get('removed', None) is not None:  # XXX: check version
+			continue
+		need[doc['define']] = True
+	for k in tmp.provides.keys():
+		if need.has_key(k):
+			del need[k]
+	need_keys = sorted(need.keys())
+
+	if len(need_keys) > 0:
+		ret.chdr_block_heading('Autogenerated defaults')
+
+		for k in need_keys:
+			#print('config option %s not covered by manual snippets, emitting default automatically' % k)
+			emit_default_from_config_meta(ret, use_defs[k], {}, False)
+
+		ret.empty()
+
+	ret.snippet_relative('custom_header.h.in')
+	ret.empty()
+
+	if len(opts.fixup_header_lines) > 0:
+		ret.chdr_block_heading('Fixups')
+		for line in opts.fixup_header_lines:
+			ret.line(line)
+		ret.empty()
+
+	add_override_defines_section(opts, ret)
+
+	# Date provider snippet is after custom header and overrides, so that
+	# the user may define e.g. DUK_USE_DATE_NOW_GETTIMEOFDAY in their
+	# custom header.
+	ret.snippet_relative('date_provider.h.in')
+	ret.empty()
+
+	ret.fill_dependencies_for_snippets(idx_deps)
+
+	# FIXME: use autogenerated sanity instead of sanity.h.in
+
+	ret.snippet_relative('sanity.h.in')
+	ret.empty()
+
+	if opts.emit_legacy_feature_check:
+		# FIXME: this doesn't really make sense for the autodetect header yet
+		add_legacy_feature_option_checks(opts, ret)
+	if opts.emit_config_sanity_check:
+		add_config_option_checks(opts, ret)
+	if opts.add_active_defines_macro:
+		add_duk_active_defines_macro(ret)
+
+	ret.line('#endif  /* DUK_CONFIG_H_INCLUDED */')
+	ret.empty()  # for trailing newline
+	return remove_duplicate_newlines(ret.join())
+
+# Generate a barebones duk_config.h header for a specific platform, architecture,
+# and compiler.  The header won't do automatic feature detection and does not
+# support DUK_OPT_xxx feature options (which will be removed in Duktape 2.x).
+# Users can then modify this barebones header for very exotic platforms and manage
+# the needed changes either as a YAML file or by appending a fixup header snippet.
+#
+# XXX: to be replaced by generate_modular_duk_config_header().
+def generate_barebones_duk_config_header(opts, meta_dir):
+	ret = FileBuilder(base_dir=os.path.join(meta_dir, 'header-snippets'), \
+	                  use_cpp_warning=opts.use_cpp_warning)
+
+	# XXX: Provide more defines from YAML config files so that such
+	#      defines can be overridden more conveniently (e.g. DUK_COS).
+
+	forced_opts = get_forced_options(opts)
+
+	ret.line('/*')
+	ret.line(' *  duk_config.h generated by genconfig.py for:')
+	ret.line(' *      platform: %s' % opts.platform)
+	ret.line(' *      compiler: %s' % opts.compiler)
+	ret.line(' *      architecture: %s' % opts.architecture)
+	ret.line(' *')
+	ret.line(' *  Git commit: %s' % opts.git_commit or 'n/a')
+	ret.line(' *  Git describe: %s' % opts.git_describe or 'n/a')
+	ret.line(' */')
+	ret.empty()
+	ret.line('#ifndef DUK_CONFIG_H_INCLUDED')
+	ret.line('#define DUK_CONFIG_H_INCLUDED')
+
+	ret.chdr_block_heading('Intermediate helper defines')
+
+	idx_deps = len(ret.vals)  # position where to emit dependencies
+
+	ret.chdr_block_heading('Platform headers and typedefs')
+
+	if opts.platform is None:
+		raise Exception('no platform specified')
+
+	fn = 'platform_%s.h.in' % opts.platform
+	ret.snippet_relative(fn)
+	ret.empty()
+	ret.snippet_relative('types_c99.h.in')  # XXX: C99 typedefs forced for now
+	ret.snippet_relative('types2.h.in')     # XXX: boilerplate type stuff
+
+	ret.chdr_block_heading('Platform features')
+
+	# XXX: double constants
+	# XXX: replacement functions
+	# XXX: inherit definitions (like '#define DUK_FFLUSH fflush') from a
+	#      generic set of defaults, allow platform configs to override
+
+	ret.snippet_relative('platform_generic.h.in')
+
+	ret.chdr_block_heading('Compiler features')
+
+	if opts.compiler is None:
+		raise Exception('no compiler specified')
+
+	fn = 'compiler_%s.h.in' % opts.compiler
+	ret.snippet_relative(fn)
+
+	# noreturn, vacopy, etc
+	# visibility attributes
+
+	ret.chdr_block_heading('Architecture features')
+
+	if opts.architecture is None:
+		raise Exception('no architecture specified')
+
+	fn = 'architecture_%s.h.in' % opts.architecture
+	ret.snippet_relative(fn)
+
+	ret.chdr_block_heading('Config options')
+
+	tags = get_tag_list_with_preferred_order(header_tag_order)
+
+	handled = {}
+
+	# Mark all defines 'provided' by the snippets so far as handled.
+	# For example, if the system header provides a DUK_USE_OS_STRING,
+	# we won't emit it again below with its default value (but will
+	# emit an override value if specified).
+
+	for sn in ret.vals:
+		for k in sn.provides.keys():
+			handled[k] = True
+
+	for tag in tags:
+		ret.line('/* ' + get_tag_title(tag) + ' */')
+
+		for doc in use_defs_list:
+			defname = doc['define']
+
+			if doc.get('removed', None) is not None and opts.omit_removed_config_options:
+				continue
+			if doc.get('deprecated', None) is not None and opts.omit_deprecated_config_options:
+				continue
+			if doc.get('unused', False) == True and opts.omit_unused_config_options:
+				continue
+
+			if tag != doc['tags'][0]:  # sort under primary tag
+				continue
+
+			if not doc.has_key('default'):
+				raise Exception('config option %s is missing default value' % defname)
+
+			undef_done = False
+
+			if handled.has_key(defname):
+				defval = forced_opts.get(defname, None)
+				if defval is None:
+					ret.line('/* %s already emitted above */' % defname)
+					continue
+
+				# Define already emitted by snippets above but
+				# an explicit override wants to redefine it.
+				# Undef first and then use shared handler to
+				# setup the forced value.
+				ret.line('#undef ' + defname)
+				undef_done = True
+
+			# FIXME: macro args; DUK_USE_USER_DECLARE vs. DUK_USE_USER_DECLARE()
+			#        vs. DUK_USE_USER_DECLARE(x,y)
+
+			handled[defname] = True
+			emit_default_from_config_meta(ret, doc, forced_opts, undef_done)
+
+		ret.empty()
+
+	if len(opts.fixup_header_lines) > 0:
+		ret.chdr_block_heading('Fixups')
+		for line in opts.fixup_header_lines:
+			ret.line(line)
+
+	add_override_defines_section(opts, ret)
+
+	# Date provider snippet is after custom header and overrides, so that
+	# the user may define e.g. DUK_USE_DATE_NOW_GETTIMEOFDAY in their
+	# custom header.
+	ret.empty()
+	ret.snippet_relative('date_provider.h.in')
+	ret.empty()
+
+	ret.fill_dependencies_for_snippets(idx_deps)
+
+	# XXX: ensure no define is unhandled at the end
+
+	# Check for presence of legacy feature options (DUK_OPT_xxx),
+	# and consistency of final DUK_USE_xxx options.
+	#
+	# These could also be emitted into Duktape source code, but it's
+	# probably better that the checks can be easily disabled from
+	# duk_config.h.
+
+	if opts.emit_legacy_feature_check:
+		add_legacy_feature_option_checks(opts, ret)
+	if opts.emit_config_sanity_check:
+		add_config_option_checks(opts, ret)
+	if opts.add_active_defines_macro:
+		add_duk_active_defines_macro(ret)
+
+	ret.line('#endif  /* DUK_CONFIG_H_INCLUDED */')
+	ret.empty()  # for trailing newline
+
+	return remove_duplicate_newlines(serialize_snippet_list(ret.vals))  # XXX: refactor into FileBuilder
+
+#
+#  Main
+#
+
+def main():
+	# Forced options from multiple sources are gathered into a shared list
+	# so that the override order remains the same as on the command line.
+	force_options_yaml = []
+	def add_force_option_yaml(option, opt, value, parser):
+		# XXX: check that YAML parses
+		force_options_yaml.append(value)
+	def add_force_option_file(option, opt, value, parser):
+		# XXX: check that YAML parses
+		with open(value, 'rb') as f:
+			force_options_yaml.append(f.read())
+	def add_force_option_define(option, opt, value, parser):
+		tmp = value.split('=')
+		if len(tmp) == 1:
+			doc = { tmp[0]: True }
+		elif len(tmp) == 2:
+			doc = { tmp[0]: tmp[1] }
+		else:
+			raise Exception('invalid option value: %r' % value)
+		force_options_yaml.append(yaml.safe_dump(doc))
+	def add_force_option_undefine(option, opt, value, parser):
+		tmp = value.split('=')
+		if len(tmp) == 1:
+			doc = { tmp[0]: False }
+		else:
+			raise Exception('invalid option value: %r' % value)
+		force_options_yaml.append(yaml.safe_dump(doc))
+
+	fixup_header_lines = []
+	def add_fixup_header_line(option, opt, value, parser):
+		fixup_header_lines.append(value)
+	def add_fixup_header_file(option, opt, value, parser):
+		with open(value, 'rb') as f:
+			for line in f:
+				if line[-1] == '\n':
+					line = line[:-1]
+				fixup_header_lines.append(line)
+
+	commands = [
+		'autodetect-header',
+		'barebones-header',
+		'feature-documentation',
+		'config-documentation'
+	]
+	parser = optparse.OptionParser(
+		usage='Usage: %prog [options] COMMAND',
+		description='Generate a duk_config.h or config option documentation based on config metadata.',
+		epilog='COMMAND can be one of: ' + ', '.join(commands) + '.'
+	)
+	parser.add_option('--metadata', dest='metadata', default=None, help='metadata directory or metadata tar.gz file')
+	parser.add_option('--output', dest='output', default=None, help='output filename for C header or RST documentation file')
+	parser.add_option('--platform', dest='platform', default=None, help='platform (for "barebones-header" command)')
+	parser.add_option('--compiler', dest='compiler', default=None, help='compiler (for "barebones-header" command)')
+	parser.add_option('--architecture', dest='architecture', default=None, help='architecture (for "barebones-header" command)')
+	parser.add_option('--dll', dest='dll', action='store_true', default=False, help='dll build of Duktape, affects symbol visibility macros especially on Windows')  # FIXME: unimplemented
+	parser.add_option('--emit-legacy-feature-check', dest='emit_legacy_feature_check', action='store_true', default=False, help='emit preprocessor checks to reject legacy feature options (DUK_OPT_xxx)')
+	parser.add_option('--emit-config-sanity-check', dest='emit_config_sanity_check', action='store_true', default=False, help='emit preprocessor checks for config option consistency (DUK_OPT_xxx)')
+	parser.add_option('--omit-removed-config-options', dest='omit_removed_config_options', action='store_true', default=False, help='omit removed config options from generated headers')
+	parser.add_option('--omit-deprecated-config-options', dest='omit_deprecated_config_options', action='store_true', default=False, help='omit deprecated config options from generated headers')
+	parser.add_option('--omit-unused-config-options', dest='omit_unused_config_options', action='store_true', default=False, help='omit unused config options from generated headers')
+	parser.add_option('--add-active-defines-macro', dest='add_active_defines_macro', action='store_true', default=False, help='add DUK_ACTIVE_DEFINES macro, for development only')
+	parser.add_option('--define', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_define, default=force_options_yaml, help='force #define option using a C compiler like syntax, e.g. "--define DUK_USE_DEEP_C_STACK" or "--define DUK_USE_TRACEBACK_DEPTH=10"')
+	parser.add_option('-D', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_define, default=force_options_yaml, help='synonym for --define, e.g. "-DDUK_USE_DEEP_C_STACK" or "-DDUK_USE_TRACEBACK_DEPTH=10"')
+	parser.add_option('--undefine', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_undefine, default=force_options_yaml, help='force #undef option using a C compiler like syntax, e.g. "--undefine DUK_USE_DEEP_C_STACK"')
+	parser.add_option('-U', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_undefine, default=force_options_yaml, help='synonym for --undefine, e.g. "-UDUK_USE_DEEP_C_STACK"')
+	parser.add_option('--option-yaml', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_yaml, default=force_options_yaml, help='force option(s) using inline YAML (e.g. --option-yaml "DUK_USE_DEEP_C_STACK: true")')
+	parser.add_option('--option-file', type='string', dest='force_options_yaml', action='callback', callback=add_force_option_file, default=force_options_yaml, help='YAML file(s) providing config option overrides')
+	parser.add_option('--fixup-file', type='string', dest='fixup_header_lines', action='callback', callback=add_fixup_header_file, default=fixup_header_lines, help='C header snippet file(s) to be appended to generated header, useful for manual option fixups')
+	parser.add_option('--fixup-line', type='string', dest='fixup_header_lines', action='callback', callback=add_fixup_header_line, default=fixup_header_lines, help='C header fixup line to be appended to generated header (e.g. --fixup-line "#define DUK_USE_FASTINT")')
+	parser.add_option('--sanity-warning', dest='sanity_strict', action='store_false', default=True, help='emit a warning instead of #error for option sanity check issues')
+	parser.add_option('--use-cpp-warning', dest='use_cpp_warning', action='store_true', default=False, help='emit a (non-portable) #warning when appropriate')
+	parser.add_option('--git-commit', dest='git_commit', default=None, help='git commit hash to be included in header comments')
+	parser.add_option('--git-describe', dest='git_describe', default=None, help='git describe string to be included in header comments')
+	(opts, args) = parser.parse_args()
+
+	meta_dir = opts.metadata
+	if opts.metadata is None:
+		if os.path.isfile(os.path.join('.', 'genconfig_metadata.tar.gz')):
+			opts.metadata = 'genconfig_metadata.tar.gz'
+		elif os.path.isdir(os.path.join('.', 'config-options')):
+			opts.metadata = '.'
+
+	if opts.metadata is not None and os.path.isdir(opts.metadata):
+		meta_dir = opts.metadata
+		print 'Using metadata directory: %r' % meta_dir
+	elif opts.metadata is not None and os.path.isfile(opts.metadata) and tarfile.is_tarfile(opts.metadata):
+		meta_dir = get_auto_delete_tempdir()
+		tar = tarfile.open(name=opts.metadata, mode='r:*')
+		tar.extractall(path=meta_dir)
+		print 'Using metadata tar file %r, unpacked to directory: %r' % (opts.metadata, meta_dir)
+	else:
+		raise Exception('metadata source must be a directory or a tar.gz file')
+
+	scan_snippets(os.path.join(meta_dir, 'header-snippets'))
+	scan_use_defs(os.path.join(meta_dir, 'config-options'))
+	scan_opt_defs(os.path.join(meta_dir, 'feature-options'))
+	scan_use_tags()
+	scan_tags_meta(os.path.join(meta_dir, 'tags.yaml'))
+	print('Scanned %d DUK_OPT_xxx, %d DUK_USE_XXX, %d helper snippets' % \
+		(len(opt_defs.keys()), len(use_defs.keys()), len(helper_snippets)))
+	#print('Tags: %r' % use_tags_list)
+
+	if len(args) == 0:
+		raise Exception('missing command')
+	cmd = args[0]
+
+	if cmd == 'autodetect-header':
+		cmd = 'autodetect-header-legacy'
+
+	if cmd == 'autodetect-header-legacy':
+		# Generate a duk_config.h similar to Duktape 1.2 feature detection,
+		# based on manually written monolithic snippets.
+		# To be replaced by modular header.
+		result = generate_autodetect_duk_config_header(opts, meta_dir)
+		with open(opts.output, 'wb') as f:
+			f.write(result)
+	elif cmd == 'autodetect-header-modular':
+		# Generate a duk_config.h similar to Duktape 1.2 feature detection.
+		# Platform, architecture, and compiler can each be either autodetected
+		# or specified by user.  Generated header is based on modular snippets
+		# rather than a monolithic platform detection header.
+		result = generate_autodetect_duk_config_header_modular(opts, meta_dir)
+		with open(opts.output, 'wb') as f:
+			f.write(result)
+	elif cmd == 'barebones-header':
+		# Generate a duk_config.h with default options for a specific platform,
+		# compiler, and architecture.
+		result = generate_barebones_duk_config_header(opts, meta_dir)
+		with open(opts.output, 'wb') as f:
+			f.write(result)
+	elif cmd == 'feature-documentation':
+		result = generate_feature_option_documentation(opts)
+		with open(opts.output, 'wb') as f:
+			f.write(result)
+	elif cmd == 'config-documentation':
+		result = generate_config_option_documentation(opts)
+		with open(opts.output, 'wb') as f:
+			f.write(result)
+	else:
+		raise Exception('invalid command: %r' % cmd)
+
+if __name__ == '__main__':
+	main()

二進制
src/third_party/duktape-1.3.0/config/genconfig_metadata.tar.gz


+ 80 - 0
src/third_party/duktape-1.3.0/debugger/Makefile

@@ -0,0 +1,80 @@
+NODE:=$(shell which nodejs node | head -1)
+
+# Try to get a useful default --source-dirs which works both in the Duktape
+# repo and in the distributable.  We don't want to add '..' because it would
+# scan a lot of undesired files in the Duktape repo (e.g. test262 testcases).
+ifeq ($(wildcard ../tests/ecmascript/*.js),)
+SOURCEDIRS:=../
+else
+SOURCEDIRS:=../tests/ecmascript
+endif
+
+.PHONY: all
+all: run
+
+.PHONY: run
+run: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images
+	$(NODE) duk_debug.js --source-dirs=$(SOURCEDIRS)
+
+.PHONY: runproxy
+runproxy: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images
+	$(NODE) duk_debug.js --json-proxy
+
+.PHONY: clean
+clean:
+	@rm -f static/socket.io-1.2.0.js
+	@rm -f static/jquery-1.11.1.min.js
+	@rm -f static/jquery.syntaxhighlighter.min.js
+	@rm -f static/jquery.snippet.min.js
+	@rm -f static/jquery.snippet.min.css
+	@rm -f static/prefixfree.min.js
+	@rm -f static/reset.css
+	@rm -f static/jquery-ui.min.js
+	@rm -f static/jquery-ui.min.css
+	@rm -rf static/images
+	@rm -f jquery-ui-1.11.2.zip
+	@rm -rf jquery-ui-1.11.2
+	@rm -rf node_modules
+
+node_modules:
+	npm install
+
+static/socket.io-1.2.0.js:
+	wget -O $@ https://cdn.socket.io/socket.io-1.2.0.js
+
+static/jquery-1.11.1.min.js:
+	wget -O $@ http://code.jquery.com/jquery-1.11.1.min.js
+
+# http://balupton.github.io/jquery-syntaxhighlighter/demo/
+static/jquery.syntaxhighlighter.min.js:
+	wget -O $@ http://balupton.github.com/jquery-syntaxhighlighter/scripts/jquery.syntaxhighlighter.min.js
+
+# http://steamdev.com/snippet/
+static/jquery.snippet.min.js:
+	wget -O $@ http://steamdev.com/snippet/js/jquery.snippet.min.js
+static/jquery.snippet.min.css:
+	wget -O $@ http://steamdev.com/snippet/css/jquery.snippet.min.css
+
+# http://prismjs.com/
+# http://prismjs.com/plugins/line-highlight/
+#
+# XXX: prism download manually?
+
+# https://raw.github.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js
+static/prefixfree.min.js:
+	wget -O $@ https://raw.github.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js
+
+# http://meyerweb.com/eric/tools/css/reset/
+static/reset.css:
+	wget -O $@ http://meyerweb.com/eric/tools/css/reset/reset.css
+
+jquery-ui-1.11.2.zip:
+	wget -O $@ http://jqueryui.com/resources/download/jquery-ui-1.11.2.zip
+jquery-ui-1.11.2: jquery-ui-1.11.2.zip
+	unzip $<
+static/jquery-ui.min.js: jquery-ui-1.11.2
+	cp jquery-ui-1.11.2/jquery-ui.min.js $@
+static/jquery-ui.min.css: jquery-ui-1.11.2
+	cp jquery-ui-1.11.2/jquery-ui.min.css $@
+static/images: jquery-ui-1.11.2
+	cp -r jquery-ui-1.11.2/images static/

+ 268 - 0
src/third_party/duktape-1.3.0/debugger/README.rst

@@ -0,0 +1,268 @@
+=========================================
+Duktape debug client and JSON debug proxy
+=========================================
+
+Overview
+========
+
+Debugger web UI which connects to the Duktape command line tool or any other
+target supporting the example TCP transport (``examples/debug-trans-socket``).
+
+Also provides a JSON debug proxy with a JSON mapping for the Duktape debug
+protocol.
+
+For detailed documentation of the debugger internals, see `debugger.rst`__.
+
+__ https://github.com/svaarala/duktape/blob/master/doc/debugger.rst
+
+Using the debugger web UI
+=========================
+
+Some prerequisites:
+
+* You'll need Node.js v0.10.x or newer.  Older Node.js versions don't support
+  the required packages.
+
+Compile Duktape command line tool with debugger support (for further options
+see ``doc/feature-options.rst``):
+
+* ``DUK_OPT_DEBUGGER_SUPPORT``
+
+* ``DUK_OPT_INTERRUPT_COUNTER``
+
+* ``DUK_CMDLINE_DEBUGGER_SUPPORT``
+
+The source distributable contains a Makefile to build a "duk" command with
+debugger support::
+
+    $ cd <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
+==========================
+
+A JSON debug proxy is also provided by ``duk_debug.js``::
+
+    # Same prerequisites as above
+    $ make runproxy
+
+Start Duktape command line (or whatever your target is)::
+
+    $ cd <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":"_Connected","args":["1 10199 v1.1.0-275-gbd4d610-dirty duk command built from Duktape repo"]}
+    <-- {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]}
+    --> {"request":"BasicInfo"}
+    <-- {"reply":true,"args":[10199,"v1.1.0-275-gbd4d610-dirty","duk command built from Duktape repo",1]}
+    --> {"request":"Eval", "args":[ "print(Math.PI)" ]}
+    <-- {"notify":"Print","command":2,"args":["3.141592653589793\n"]}
+    <-- {"reply":true,"args":[0,{"type":"undefined"}]}
+    --> {"request":"Resume"}
+    <-- {"reply":true,"args":[]}
+    <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]}
+    <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]}
+    <-- {"notify":"Print","command":2,"args":["................................................................................\n"]}
+    <-- {"notify":"Print","command":2,"args":["................................................................................\n"]}
+    <-- {"notify":"Print","command":2,"args":["................................................................................\n"]}
+    [...]
+    <-- {"notify":"_Disconnecting"}
+
+A telnet connection allows you to experiment with debug commands by simply
+copy-pasting debug commands to the telnet session.  This is useful even if
+you decide to implement the binary protocol directly.
+
+The debug target used by the proxy can be configured with ``duk_debug.js``
+command line options.
+
+Source search path
+==================
+
+The NodeJS debug client needs to be able to find source code files matching
+code running on the target ("duk" command line).  **The filenames used on the
+target and on the debug client must match exactly**, because e.g. breakpoints
+are targeted based on the 'fileName' property of Function objects.
+
+The search path can be set using the ``--source-dirs`` option given to
+``duk_debug.js``, with the default search paths including only
+``../tests/ecmascript/``.
+
+The default search path means that if a function on the target has fileName
+``foo/bar.js`` it would be loaded from (relative to the duk_debug.js working
+directory, ``debugger/``)::
+
+    ../tests/ecmascript/foo/bar.js
+
+Similarly, if the filesystem contained::
+
+    ../tests/ecmascript/baz/quux.js
+
+the web UI dropdown would show ``baz/quux.js``.  If you selected that file
+and added a breakpoint, the breakpoint fileName sent to the debug target
+would be ``baz/quux.js``.
+
+.. note:: There's much to improve in the search path.  For instance, it'd
+          be nice to add a certain path to search but exclude files based
+          on paths and patterns, etc.
+
+Architecture
+============
+
+::
+
+    +-------------------+
+    | Web browser       |  [debug UI]
+    +-------------------+
+          |
+          | http (port 9092)
+          | socket.io
+          v
+    +-------------------+
+    | duk_debug.js      |  [debug client]
+    +-------------------+
+          |          /\
+          |          ||
+          +----------||---- [example tcp transport] (port 9091)
+          |          ||     (application provides concrete transport)
+          |          ||
+          |          ||---- [debug protocol stream]
+          |          ||     (between debug client and Duktape)
+          |          ||
+    + - - | - - - - -|| - - +
+    :     v          ||     :
+    :  +-------------||-+   :  [target]
+    :  | application || |   :
+    :  +-------------||-+   :
+    :     ^          ||     :
+    :     |          ||     :   [debug API]
+    :     +----------||-------- debug transport callbacks
+    :     |          ||     :   (read, write, peek, read/write flush)
+    :     |          ||     :   implemented by application
+    :     |          \/     :
+    :  +----------------+   :
+    :  | Duktape        |   :
+    :  +----------------+   :
+    + - - - - - - - - - - - +
+
+The debug transport is application specific:
+
+* Duktape command line ("duk") and this debug client use an **example** TCP
+  transport as a concrete example.
+
+* It is entirely up to the application to come up with the most suitable
+  transport for its environment.  Different mechanisms will be needed for
+  Wi-Fi, serial, etc.
+
+The debug protocol running inside the transport is transport independent:
+
+* The debug protocol is documented in ``doc/debugger.rst``.
+
+* This debug client provides further concrete examples and clarifications
+  on how the protocol can be used.
+
+Using a custom transport
+========================
+
+Quite possibly your target device cannot use the example TCP transport and
+you need to implement your own transport.  You'll need to implement your
+custom transport both for the target device and for the debug client.
+
+Target device
+-------------
+
+Implement the debug transport callbacks needed by ``duk_debugger_attach()``.
+
+See ``doc/debugger.rst`` for details and ``examples/debug-trans-socket``
+for example running code for a TCP transport.
+
+Debug client alternative 1: duk_debug.js + custom TCP proxy
+-----------------------------------------------------------
+
+If you don't want to change ``duk_debug.js`` you can implement a TCP proxy
+which accepts a TCP connection from ``duk_debug.js`` and then uses your
+custom transport to talk to the target::
+
+   +--------------+   TCP   +-------+   custom   +--------+
+   | duk_debug.js | ------> | proxy | ---------> | target |
+   +--------------+         +-------+            +--------+
+
+This is a straightforward option and a proxy can be used with other debug
+clients too (perhaps custom scripts talking to the target etc).
+
+You could also use netcat and implement your proxy so that it talks to
+``duk_debug.js`` using stdin/stdout.
+
+Debug client alternative 2: duk_debug.js + custom NodeJS stream
+---------------------------------------------------------------
+
+To make ``duk_debug.js`` use a custom transport you need to:
+
+* Implement your own transport as NodeJS stream.  You can add it directly to
+  ``duk_debug.js`` but it's probably easiest to use a separate module so that
+  the diff to ``duk_debug.js`` stays minimal.
+
+* Change ``duk_debug.js`` to use the custom transport instead of a TCP
+  stream.  Search for "CUSTOMTRANSPORT" in ``duk_debug.js``.
+
+See:
+
+* http://nodejs.org/api/stream.html
+
+* https://github.com/substack/stream-handbook
+
+Debug client alternative 3: custom debug client
+-----------------------------------------------
+
+You can also implement your own debug client and debug UI with support for
+your custom transport.
+
+You'll also need to implement the client part of the Duktape debugger
+protocol.  See ``doc/debugger.rst`` for the specification and ``duk_debug.js``
+for example running code which should illustrate the protocol in more detail.
+
+The JSON debug proxy allows you to implement a debug client without needing
+to implement the Duktape binary debug protocol.  The JSON protocol provides
+a roughly 1:1 mapping to the binary protocol but with an easier syntax.

+ 31 - 0
src/third_party/duktape-1.3.0/debugger/duk_classnames.yaml

@@ -0,0 +1,31 @@
+# Must match C header
+- unused
+- Arguments
+- Array
+- Boolean
+- Date
+- Error
+- Function
+- JSON
+- Math
+- Number
+- Object
+- RegExp
+- String
+- global
+- ObjEnv
+- DecEnv
+- Buffer
+- Pointer
+- Thread
+- ArrayBuffer
+- DataView
+- Int8Array
+- Uint8Array
+- Uint8ClampedArray
+- Int16Array
+- Uint16Array
+- Int32Array
+- Uint32Array
+- Float32Array
+- Float64Array

+ 2448 - 0
src/third_party/duktape-1.3.0/debugger/duk_debug.js

@@ -0,0 +1,2448 @@
+/*
+ *  Minimal debug web console for Duktape command line tool
+ *
+ *  See debugger/README.rst.
+ *
+ *  The web UI socket.io communication can easily become a bottleneck and
+ *  it's important to ensure that the web UI remains responsive.  Basic rate
+ *  limiting mechanisms (token buckets, suppressing identical messages, etc)
+ *  are used here now.  Ideally the web UI would pull data on its own terms
+ *  which would provide natural rate limiting.
+ *
+ *  Promises are used to structure callback chains.
+ *
+ *  https://github.com/petkaantonov/bluebird
+ *  https://github.com/petkaantonov/bluebird/blob/master/API.md
+ *  https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns
+ */
+
+var Promise = require('bluebird');
+var events = require('events');
+var stream = require('stream');
+var path = require('path');
+var fs = require('fs');
+var net = require('net');
+var byline = require('byline');
+var util = require('util');
+var readline = require('readline');
+var sprintf = require('sprintf').sprintf;
+var utf8 = require('utf8');
+var wrench = require('wrench');  // https://github.com/ryanmcgrath/wrench-js
+var yaml = require('yamljs');
+
+// Command line options (defaults here, overwritten if necessary)
+var optTargetHost = '127.0.0.1';
+var optTargetPort = 9091;
+var optHttpPort = 9092;
+var optJsonProxyPort = 9093;
+var optJsonProxy = false;
+var optSourceSearchDirs = [ '../tests/ecmascript' ];
+var optDumpDebugRead = null;
+var optDumpDebugWrite = null;
+var optDumpDebugPretty = null;
+var optLogMessages = false;
+
+// Constants
+var UI_MESSAGE_CLIPLEN = 128;
+var LOCALS_CLIPLEN = 64;
+var EVAL_CLIPLEN = 4096;
+var GETVAR_CLIPLEN = 4096;
+
+// Commands initiated by Duktape
+var CMD_STATUS = 0x01;
+var CMD_PRINT = 0x02;
+var CMD_ALERT = 0x03;
+var CMD_LOG = 0x04;
+
+// Commands initiated by the debug client (= us)
+var CMD_BASICINFO = 0x10;
+var CMD_TRIGGERSTATUS = 0x11;
+var CMD_PAUSE = 0x12;
+var CMD_RESUME = 0x13;
+var CMD_STEPINTO = 0x14;
+var CMD_STEPOVER = 0x15;
+var CMD_STEPOUT = 0x16;
+var CMD_LISTBREAK = 0x17;
+var CMD_ADDBREAK = 0x18;
+var CMD_DELBREAK = 0x19;
+var CMD_GETVAR = 0x1a;
+var CMD_PUTVAR = 0x1b;
+var CMD_GETCALLSTACK = 0x1c;
+var CMD_GETLOCALS = 0x1d;
+var CMD_EVAL = 0x1e;
+var CMD_DETACH = 0x1f;
+var CMD_DUMPHEAP = 0x20;
+var CMD_GETBYTECODE = 0x21;
+
+// Errors
+var ERR_UNKNOWN = 0x00;
+var ERR_UNSUPPORTED = 0x01;
+var ERR_TOOMANY = 0x02;
+var ERR_NOTFOUND = 0x03;
+
+// Marker objects for special protocol values
+var DVAL_EOM = { type: 'eom' };
+var DVAL_REQ = { type: 'req' };
+var DVAL_REP = { type: 'rep' };
+var DVAL_ERR = { type: 'err' };
+var DVAL_NFY = { type: 'nfy' };
+
+// String map for commands (debug dumping).  A single map works (instead of
+// separate maps for each direction) because command numbers don't currently
+// overlap.
+var debugCommandNames = yaml.load('duk_debugcommands.yaml');
+
+// Map debug command names to numbers.
+var debugCommandNumbers = {};
+debugCommandNames.forEach(function (k, i) {
+    debugCommandNumbers[k] = i;
+});
+
+// Duktape heaphdr type constants, must match C headers
+var DUK_HTYPE_STRING = 1;
+var DUK_HTYPE_OBJECT = 2;
+var DUK_HTYPE_BUFFER = 3;
+
+// Duktape internal class numbers, must match C headers
+var dukClassNames = yaml.load('duk_classnames.yaml');
+
+// Bytecode opcode/extraop metadata
+var dukOpcodes = yaml.load('duk_opcodes.yaml')
+if (dukOpcodes.opcodes.length != 64) {
+    throw new Error('opcode metadata length incorrect');
+}
+if (dukOpcodes.extra.length != 256) {
+    throw new Error('extraop metadata length incorrect');
+}
+
+/*
+ *  Miscellaneous helpers
+ */
+
+var nybbles = '0123456789abcdef';
+
+/* Convert a buffer into a string using Unicode codepoints U+0000...U+00FF.
+ * This is the NodeJS 'binary' encoding, but since it's being deprecated,
+ * reimplement it here.  We need to avoid parsing strings as e.g. UTF-8:
+ * although Duktape strings are usually UTF-8/CESU-8 that's not always the
+ * case, e.g. for internal strings.  Buffer values are also represented as
+ * strings in the debug protocol, so we must deal accurately with arbitrary
+ * byte arrays.
+ */
+function bufferToDebugString(buf) {
+    var cp = [];
+    var i, n;
+
+/*
+    // This fails with "RangeError: Maximum call stack size exceeded" for some
+    // reason, so use a much slower variant.
+
+    for (i = 0, n = buf.length; i < n; i++) {
+        cp[i] = buf[i];
+    }
+
+    return String.fromCharCode.apply(String, cp);
+*/
+
+    for (i = 0, n = buf.length; i < n; i++) {
+        cp[i] = String.fromCharCode(buf[i]);
+    }
+
+    return cp.join('');
+}
+
+/* Write a string into a buffer interpreting codepoints U+0000...U+00FF
+ * as bytes.  Drop higher bits.
+ */
+function writeDebugStringToBuffer(str, buf, off) {
+    var i, n;
+
+    for (i = 0, n = str.length; i < n; i++) {
+        buf[off + i] = str.charCodeAt(i) & 0xff;
+    }
+}
+
+/* Encode an ordinary Unicode string into a dvalue compatible format, i.e.
+ * into a byte array represented as codepoints U+0000...U+00FF.  Concretely,
+ * encode with UTF-8 and then represent the bytes with U+0000...U+00FF.
+ */
+function stringToDebugString(str) {
+    return utf8.encode(str);
+}
+
+/* Pretty print a dvalue.  Useful for dumping etc. */
+function prettyDebugValue(x) {
+    if (typeof x === 'object' && x !== null) {
+        if (x.type === 'eom') {
+            return 'EOM';
+        } else if (x.type === 'req') {
+            return 'REQ';
+        } else if (x.type === 'rep') {
+            return 'REP';
+        } else if (x.type === 'err') {
+            return 'ERR';
+        } else if (x.type === 'nfy') {
+            return 'NFY';
+        }
+    }
+    return JSON.stringify(x);
+}
+
+/* Pretty print a number for UI usage.  Types and values should be easy to
+ * read and typing should be obvious.  For numbers, support Infinity, NaN,
+ * and signed zeroes properly.
+ */
+function prettyUiNumber(x) {
+    if (x === 1/0) { return 'Infinity'; }
+    if (x === -1/0) { return '-Infinity'; }
+    if (Number.isNaN(x)) { return 'NaN'; }
+    if (x === 0 && 1/x > 0) { return '0'; }
+    if (x === 0 && 1/x < 0) { return '-0'; }
+    return x.toString();
+}
+
+/* Pretty print a dvalue string (bytes represented as U+0000...U+00FF)
+ * for UI usage.  Try UTF-8 decoding to get a nice Unicode string (JSON
+ * encoded) but if that fails, ensure that bytes are encoded transparently.
+ * The result is a quoted string with a special quote marker for a "raw"
+ * string when UTF-8 decoding fails.  Very long strings are optionally
+ * clipped.
+ */
+function prettyUiString(x, cliplen) {
+    var ret;
+
+    if (typeof x !== 'string') {
+        throw new Error('invalid input to prettyUiString: ' + typeof x);
+    }
+    try {
+        // Here utf8.decode() is better than decoding using NodeJS buffer
+        // operations because we want strict UTF-8 interpretation.
+        ret = JSON.stringify(utf8.decode(x));
+    } catch (e) {
+        // When we fall back to representing bytes, indicate that the string
+        // is "raw" with a 'r"' prefix (a somewhat arbitrary convention).
+        // U+0022 = ", U+0027 = '
+        ret = 'r"' + x.replace(/[\u0022\u0027\u0000-\u001f\u0080-\uffff]/g, function (match) {
+            var cp = match.charCodeAt(0);
+            return '\\x' + nybbles[(cp >> 4) & 0x0f] + nybbles[cp & 0x0f];
+        }) + '"';
+    }
+
+    if (cliplen && ret.length > cliplen) {
+        ret = ret.substring(0, cliplen) + '...';  // trailing '"' intentionally missing
+    }
+    return ret;
+}
+
+/* Pretty print a dvalue string (bytes represented as U+0000...U+00FF)
+ * for UI usage without quotes.
+ */
+function prettyUiStringUnquoted(x, cliplen) {
+    var ret;
+
+    if (typeof x !== 'string') {
+        throw new Error('invalid input to prettyUiStringUnquoted: ' + typeof x);
+    }
+
+    try {
+        // Here utf8.decode() is better than decoding using NodeJS buffer
+        // operations because we want strict UTF-8 interpretation.
+
+        // XXX: unprintable characters etc?  In some UI cases we'd want to
+        // e.g. escape newlines and in others not.
+        ret = utf8.decode(x);
+    } catch (e) {
+        // For the unquoted version we don't need to escape single or double
+        // quotes.
+        ret = x.replace(/[\u0000-\u001f\u0080-\uffff]/g, function (match) {
+            var cp = match.charCodeAt(0);
+            return '\\x' + nybbles[(cp >> 4) & 0x0f] + nybbles[cp & 0x0f];
+        });
+    }
+
+    if (cliplen && ret.length > cliplen) {
+        ret = ret.substring(0, cliplen) + '...';
+    }
+    return ret;
+}
+
+/* Pretty print a dvalue for UI usage.  Everything comes out as a ready-to-use
+ * string.
+ *
+ * XXX: Currently the debug client formats all values for UI use.  A better
+ * solution would be to pass values in typed form and let the UI format them,
+ * so that styling etc. could take typing into account.
+ */
+function prettyUiDebugValue(x, cliplen) {
+    if (typeof x === 'object' && x !== null) {
+        // Note: typeof null === 'object', so null special case explicitly
+        if (x.type === 'eom') {
+            return 'EOM';
+        } else if (x.type === 'req') {
+            return 'REQ';
+        } else if (x.type === 'rep') {
+            return 'REP';
+        } else if (x.type === 'err') {
+            return 'ERR';
+        } else if (x.type === 'nfy') {
+            return 'NFY';
+        } else if (x.type === 'unused') {
+            return 'unused';
+        } else if (x.type === 'undefined') {
+            return 'undefined';
+        } else if (x.type === 'buffer') {
+            return '|' + x.data + '|';
+        } else if (x.type === 'object') {
+            return '[object ' + (dukClassNames[x.class] || ('class ' + x.class)) + ' ' + x.pointer + ']';
+        } else if (x.type === 'pointer') {
+            return '<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) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_GETVAR, varname, DVAL_EOM ]).then(function (msg) {
+        return { found: msg[1] === 1, value: msg[2] };
+    });
+};
+
+Debugger.prototype.sendPutVarRequest = function (varname, varvalue) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_PUTVAR, varname, varvalue, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendInvalidCommandTestRequest = function () {
+    // Intentional invalid command
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, 0xdeadbeef, DVAL_EOM ]);
+}
+
+Debugger.prototype.sendStatusRequest = function () {
+    // Send a status request to trigger a status notify, result is ignored:
+    // target sends a status notify instead of a meaningful reply
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_TRIGGERSTATUS, DVAL_EOM ]);
+}
+
+Debugger.prototype.sendBreakpointListRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_LISTBREAK, DVAL_EOM ]).then(function (msg) {
+        var i, n;
+        var breakpts = [];
+
+        for (i = 1, n = msg.length - 1; i < n; i += 2) {
+            breakpts.push({ fileName: msg[i], lineNumber: msg[i + 1] });
+        }
+
+        _this.breakpoints = breakpts;
+        _this.emit('breakpoints-update');
+        return msg;
+    });
+};
+
+Debugger.prototype.sendGetLocalsRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_GETLOCALS, DVAL_EOM ]).then(function (msg) {
+        var i;
+        var locals = [];
+
+        for (i = 1; i <= msg.length - 2; i += 2) {
+            // XXX: do pretty printing in debug client for now
+            locals.push({ key: msg[i], value: prettyUiDebugValue(msg[i + 1], LOCALS_CLIPLEN) });
+        }
+
+        _this.locals = locals;
+        _this.emit('locals-update');
+        return msg;
+    });
+};
+
+Debugger.prototype.sendGetCallStackRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_GETCALLSTACK, DVAL_EOM ]).then(function (msg) {
+        var i;
+        var stack = [];
+
+        for (i = 1; i + 3 <= msg.length - 1; i += 4) {
+            stack.push({
+                fileName: msg[i],
+                funcName: msg[i + 1],
+                lineNumber: msg[i + 2],
+                pc: msg[i + 3]
+            });
+        }
+
+        _this.callstack = stack;
+        _this.emit('callstack-update');
+        return msg;
+    });
+};
+
+Debugger.prototype.sendStepIntoRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_STEPINTO, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendStepOverRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_STEPOVER, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendStepOutRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_STEPOUT, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendPauseRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_PAUSE, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendResumeRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_RESUME, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendEvalRequest = function (evalInput) {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_EVAL, evalInput, DVAL_EOM ]).then(function (msg) {
+        return { error: msg[1] === 1 /*error*/, value: msg[2] };
+    });
+};
+
+Debugger.prototype.sendDetachRequest = function () {
+    var _this = this;
+    return this.sendRequest([ DVAL_REQ, CMD_DETACH, DVAL_EOM ]);
+};
+
+Debugger.prototype.sendDumpHeapRequest = function () {
+    var _this = this;
+
+    return this.sendRequest([ DVAL_REQ, CMD_DUMPHEAP, DVAL_EOM ]).then(function (msg) {
+        var res = {};
+        var objs = [];
+        var i, j, n, m, o, prop;
+
+        res.type = 'heapDump';
+        res.heapObjects = objs;
+
+        for (i = 1, n = msg.length - 1; i < n; /*nop*/) {
+            o = {};
+            o.ptr = msg[i++];
+            o.type = msg[i++];
+            o.flags = msg[i++] >>> 0;  /* unsigned */
+            o.refc = msg[i++];
+
+            if (o.type === DUK_HTYPE_STRING) {
+                o.blen = msg[i++];
+                o.clen = msg[i++];
+                o.hash = msg[i++] >>> 0;  /* unsigned */
+                o.data = msg[i++];
+            } else if (o.type === DUK_HTYPE_BUFFER) {
+                o.len = msg[i++];
+                o.data = msg[i++];
+            } else if (o.type === DUK_HTYPE_OBJECT) {
+                o['class'] = msg[i++];
+                o.proto = msg[i++];
+                o.esize = msg[i++];
+                o.enext = msg[i++];
+                o.asize = msg[i++];
+                o.hsize = msg[i++];
+                o.props = [];
+                for (j = 0, m = o.enext; j < m; j++) {
+                    prop = {};
+                    prop.flags = msg[i++];
+                    prop.key = msg[i++];
+                    prop.accessor = (msg[i++] == 1);
+                    if (prop.accessor) {
+                        prop.getter = msg[i++];
+                        prop.setter = msg[i++];
+                    } else {
+                        prop.value = msg[i++];
+                    }
+                    o.props.push(prop);
+                }
+                o.array = [];
+                for (j = 0, m = o.asize; j < m; j++) {
+                    prop = {};
+                    prop.value = msg[i++];
+                    o.array.push(prop);
+                }
+            } else {
+                console.log('invalid htype: ' + o.type + ', disconnect');
+                _this.disconnectDebugger();
+                throw new Error('invalid htype');
+                return;
+            }
+
+            objs.push(o);
+        }
+
+        return res;
+    });
+};
+
+Debugger.prototype.sendGetBytecodeRequest = function () {
+    var _this = this;
+
+    return this.sendRequest([ DVAL_REQ, CMD_GETBYTECODE, DVAL_EOM ]).then(function (msg) {
+        var idx = 1;
+        var nconst;
+        var nfunc;
+        var val;
+        var buf;
+        var i, n;
+        var consts = [];
+        var funcs = [];
+        var bcode;
+        var preformatted;
+        var ret;
+
+        //console.log(JSON.stringify(msg));
+
+        nconst = msg[idx++];
+        for (i = 0; i < nconst; i++) {
+            val = msg[idx++];
+            consts.push(val);
+        }
+
+        nfunc = msg[idx++];
+        for (i = 0; i < nfunc; i++) {
+            val = msg[idx++];
+            funcs.push(val);
+        }
+        val = msg[idx++];
+
+        // Right now bytecode is a string containing a direct dump of the
+        // bytecode in target endianness.  Decode here so that the web UI
+        // doesn't need to.
+
+        buf = new Buffer(val.length);
+        writeDebugStringToBuffer(val, buf, 0);
+        bcode = _this.decodeBytecodeFromBuffer(buf, consts, funcs);
+
+        preformatted = [];
+        consts.forEach(function (v, i) {
+            preformatted.push('; c' + i + ' ' + JSON.stringify(v));
+        });
+        preformatted.push('');
+        bcode.forEach(function (v) {
+            preformatted.push(v.str);
+        });
+        preformatted = preformatted.join('\n') + '\n';
+
+        ret = {
+            constants: consts,
+            functions: funcs,
+            bytecode: bcode,
+            preformatted: preformatted
+        };
+
+        return ret;
+    });
+};
+
+Debugger.prototype.changeBreakpoint = function (fileName, lineNumber, mode) {
+    var _this = this;
+
+    return this.sendRequest([ DVAL_REQ, CMD_LISTBREAK, DVAL_EOM ]).then(function (msg) {
+        var i, n;
+        var breakpts = [];
+        var deleted = false;
+
+        // Up-to-date list of breakpoints on target
+        for (i = 1, n = msg.length - 1; i < n; i += 2) {
+            breakpts.push({ fileName: msg[i], lineNumber: msg[i + 1] });
+        }
+
+        // Delete matching breakpoints in reverse order so that indices
+        // remain valid.  We do this for all operations so that duplicates
+        // are eliminated if present.
+        for (i = breakpts.length - 1; i >= 0; i--) {
+            var bp = breakpts[i];
+            if (mode === 'deleteall' || (bp.fileName === fileName && bp.lineNumber === lineNumber)) {
+                deleted = true;
+                _this.sendRequest([ DVAL_REQ, CMD_DELBREAK, i, DVAL_EOM ], function (msg) {
+                    // nop
+                }, function (err) {
+                    // nop
+                });
+            }
+        }
+
+        // Technically we should wait for each delbreak reply but because
+        // target processes the requests in order, it doesn't matter.
+        if ((mode === 'add') || (mode === 'toggle' && !deleted)) {
+            _this.sendRequest([ DVAL_REQ, CMD_ADDBREAK, fileName, lineNumber, DVAL_EOM ], function (msg) {
+                // nop
+            }, function (err) {
+                _this.uiMessage('debugger-info', 'Failed to add breakpoint: ' + err);
+            });
+        }
+
+        // Read final, effective breakpoints from the target
+        _this.sendBreakpointListRequest();
+    });
+};
+
+Debugger.prototype.disconnectDebugger = function () {
+    if (this.targetStream) {
+        // We require a destroy() method from the actual target stream
+        this.targetStream.destroy();
+        this.targetStream = null;
+    }
+    if (this.inputParser) {
+        this.inputParser.close();
+        this.inputParser = null;
+    }
+    if (this.outputPassThroughStream) {
+        // There is no close() or destroy() for a passthrough stream, so just
+        // close the outputParser which will cancel timers etc.
+    }
+    if (this.outputParser) {
+        this.outputParser.close();
+        this.outputParser = null;
+    }
+
+    this.attached = false;
+    this.handshook = false;
+    this.reqQueue = null;
+    this.execStatus = {
+        attached: false,
+        state: 'detached',
+        fileName: '',
+        funcName: '',
+        line: 0,
+        pc: 0
+    };
+};
+
+Debugger.prototype.connectDebugger = function () {
+    var _this = this;
+
+    this.disconnectDebugger();  // close previous target connection
+
+    // CUSTOMTRANSPORT: to use a custom transport, change this.targetStream to
+    // use your custom transport.
+
+    console.log('Connecting to ' + optTargetHost + ':' + optTargetPort + '...');
+    this.targetStream = new net.Socket();
+    this.targetStream.connect(optTargetPort, optTargetHost, function () {
+        console.log('Debug transport connected');
+        _this.attached = true;
+        _this.reqQueue = [];
+        _this.uiMessage('debugger-info', 'Debug transport connected');
+    });
+
+    this.inputParser = new DebugProtocolParser(
+        this.targetStream,
+        null,
+        optDumpDebugRead,
+        optDumpDebugPretty,
+        optDumpDebugPretty ? 'Recv: ' : null,
+        null,
+        null   // console logging is done at a higher level to match request/response
+    );
+
+    // Use a PassThrough stream to debug dump and get stats for output messages.
+    // Simply write outgoing data to both the targetStream and this passthrough
+    // separately.
+    this.outputPassThroughStream = stream.PassThrough();
+    this.outputParser = new DebugProtocolParser(
+        this.outputPassThroughStream,
+        1,
+        optDumpDebugWrite,
+        optDumpDebugPretty,
+        optDumpDebugPretty ? 'Send: ' : null,
+        null,
+        null   // console logging is done at a higher level to match request/response
+    );
+
+    this.inputParser.on('transport-close', function () {
+        _this.uiMessage('debugger-info', 'Debug transport closed');
+        _this.disconnectDebugger();
+        _this.emit('exec-status-update');
+        _this.emit('detached');
+    });
+
+    this.inputParser.on('transport-error', function (err) {
+        _this.uiMessage('debugger-info', 'Debug transport error: ' + err);
+        _this.disconnectDebugger();
+    });
+
+    this.inputParser.on('protocol-version', function (msg) {
+        var ver = msg.protocolVersion;
+        console.log('Debug version identification:', msg.versionIdentification);
+        _this.protocolVersion = ver;
+        _this.uiMessage('debugger-info', 'Debug version identification: ' + msg.versionIdentification);
+        if (ver !== 1) {
+            _this.uiMessage('debugger-info', 'Protocol version ' + ver + ' unsupported, dropping connection');
+            _this.targetStream.destroy();
+        } else {
+            _this.uiMessage('debugger-info', 'Debug protocol version: ' + ver);
+            _this.handshook = true;
+            _this.execStatus = {
+                attached: true,
+                state: 'attached',
+                fileName: '',
+                funcName: '',
+                line: 0,
+                pc: 0
+            };
+            _this.emit('exec-status-update');
+            _this.emit('attached');  // inform web UI
+
+            // Fetch basic info right away
+            _this.sendBasicInfoRequest();
+        }
+    });
+
+    this.inputParser.on('debug-message', function (msg) {
+        _this.processDebugMessage(msg);
+    });
+
+    this.inputParser.on('stats-update', function () {
+        _this.stats.rxBytes = this.bytes;
+        _this.stats.rxDvalues = this.dvalues;
+        _this.stats.rxMessages = this.messages;
+        _this.stats.rxBytesPerSec = this.bytesPerSec;
+        _this.emit('debug-stats-update');
+    });
+
+    this.outputParser.on('stats-update', function () {
+        _this.stats.txBytes = this.bytes;
+        _this.stats.txDvalues = this.dvalues;
+        _this.stats.txMessages = this.messages;
+        _this.stats.txBytesPerSec = this.bytesPerSec;
+        _this.emit('debug-stats-update');
+    });
+};
+
+Debugger.prototype.processDebugMessage = function (msg) {
+    var req;
+    var prevState, newState;
+    var err;
+
+    if (msg[0] === DVAL_REQ) {
+        // No actual requests sent by the target right now (just notifys).
+        console.log('Unsolicited reply message, dropping connection: ' + prettyDebugMessage(msg));
+    } else if (msg[0] === DVAL_REP) {
+        if (this.reqQueue.length <= 0) {
+            console.log('Unsolicited reply message, dropping connection: ' + prettyDebugMessage(msg));
+            this.targetStream.destroy();
+        }
+        req = this.reqQueue.shift();
+
+        if (optLogMessages) {
+            console.log('Reply for ' + prettyDebugCommand(req.reqCmd) + ': ' + prettyDebugMessage(msg));
+        }
+
+        if (req.resolveCb) {
+            req.resolveCb(msg);
+        } else {
+            // nop: no callback
+        }
+    } else if (msg[0] === DVAL_ERR) {
+        if (this.reqQueue.length <= 0) {
+            console.log('Unsolicited error message, dropping connection: ' + prettyDebugMessage(msg));
+            this.targetStream.destroy();
+        }
+        err = new Error(String(msg[2]) + ' (code ' + String(msg[1]) + ')');
+        err.errorCode = msg[1] || 0;
+        req = this.reqQueue.shift();
+
+        if (optLogMessages) {
+            console.log('Error for ' + prettyDebugCommand(req.reqCmd) + ': ' + prettyDebugMessage(msg));
+        }
+
+        if (req.rejectCb) {
+            req.rejectCb(err);
+        } else {
+            // nop: no callback
+        }
+    } else if (msg[0] === DVAL_NFY) {
+        if (optLogMessages) {
+            console.log('Notify ' + prettyDebugCommand(msg[1]) + ': ' + prettyDebugMessage(msg));
+        }
+
+        if (msg[1] === CMD_STATUS) {
+            prevState = this.execStatus.state;
+            newState = msg[2] === 0 ? 'running' : 'paused';
+            this.execStatus = {
+                attached: true,
+                state: newState,
+                fileName: msg[3],
+                funcName: msg[4],
+                line: msg[5],
+                pc: msg[6]
+            };
+
+            if (prevState !== newState && newState === 'paused') {
+                // update run state now that we're paused
+                this.sendBreakpointListRequest();
+                this.sendGetLocalsRequest();
+                this.sendGetCallStackRequest();
+            }
+
+            this.emit('exec-status-update');
+        } else if (msg[1] === CMD_PRINT) {
+            this.uiMessage('print', prettyUiStringUnquoted(msg[2], UI_MESSAGE_CLIPLEN));
+        } else if (msg[1] === CMD_ALERT) {
+            this.uiMessage('alert', prettyUiStringUnquoted(msg[2], UI_MESSAGE_CLIPLEN));
+        } else if (msg[1] === CMD_LOG) {
+            this.uiMessage({ type: 'log', level: msg[2], message: prettyUiStringUnquoted(msg[3], UI_MESSAGE_CLIPLEN) });
+        } else {
+            console.log('Unknown notify, dropping connection: ' + prettyDebugMessage(msg));
+            this.targetStream.destroy();
+        }
+    } else {
+        console.log('Invalid initial dvalue, dropping connection: ' + prettyDebugMessage(msg));
+        this.targetStream.destroy();
+    }
+};
+
+Debugger.prototype.run = function () {
+    var _this = this;
+
+    // Initial debugger connection
+
+    this.connectDebugger();
+
+    // Poll various state items when running
+
+    var sendRound = 0;
+    var statusPending = false;
+    var bplistPending = false;
+    var localsPending = false;
+    var callStackPending = false;
+
+    setInterval(function () {
+        if (_this.execStatus.state !== 'running') {
+            return;
+        }
+
+        // Could also check for an empty request queue, but that's probably
+        // too strict?
+
+        // Pending flags are used to avoid requesting the same thing twice
+        // while a previous request is pending.  The flag-based approach is
+        // quite awkward.  Rework to use promises.
+
+        switch(sendRound) {
+        case 0:
+            if (!statusPending) {
+                statusPending = true;
+                _this.sendStatusRequest().finally(function () { statusPending = false; });
+            }
+            break;
+        case 1:
+            if (!bplistPending) {
+                bplistPending = true;
+                _this.sendBreakpointListRequest().finally(function () { bplistPending = false; });
+            }
+            break;
+        case 2:
+            if (!localsPending) {
+                localsPending = true;
+                _this.sendGetLocalsRequest().finally(function () { localsPending = false; });
+            }
+            break;
+        case 3:
+            if (!callStackPending) {
+                callStackPending = true;
+                _this.sendGetCallStackRequest().finally(function () { callStackPending = false; });
+            }
+            break;
+        }
+        sendRound = (sendRound + 1) % 4;
+    }, 500);
+};
+
+/*
+ *  Express setup and socket.io
+ */
+
+function DebugWebServer() {
+    this.dbg = null;       // debugger singleton
+    this.socket = null;    // current socket (or null)
+    this.keepaliveTimer = null;
+    this.uiMessageLimiter = null;
+    this.cachedJson = {};  // cache to avoid resending identical data
+    this.sourceFileManager = new SourceFileManager(optSourceSearchDirs);
+    this.sourceFileManager.scan();
+}
+
+DebugWebServer.prototype.handleSourcePost = function (req, res) {
+    var fileName = req.body && req.body.fileName;
+    var fileData;
+
+    console.log('Source request: ' + fileName);
+
+    if (typeof fileName !== 'string') {
+        res.status(500).send('invalid request');
+        return;
+    }
+    fileData = this.sourceFileManager.search(fileName, optSourceSearchDirs);
+    if (typeof fileData !== 'string') {
+        res.status(404).send('not found');
+        return;
+    }
+    res.status(200).send(fileData);  // UTF-8
+};
+
+DebugWebServer.prototype.handleSourceListPost = function (req, res) {
+    console.log('Source list request');
+
+    var files = this.sourceFileManager.getFiles();
+    res.header('Content-Type', 'application/json');
+    res.status(200).json(files);
+};
+
+DebugWebServer.prototype.handleHeapDumpGet = function (req, res) {
+    console.log('Heap dump get');
+
+    this.dbg.sendDumpHeapRequest().then(function (val) {
+        res.header('Content-Type', 'application/json');
+        //res.status(200).json(val);
+        res.status(200).send(JSON.stringify(val, null, 4));
+    }).catch(function (err) {
+        res.status(500).send('Failed to get heap dump: ' + (err.stack || err));
+    });
+};
+
+DebugWebServer.prototype.run = function () {
+    var _this = this;
+
+    var express = require('express');
+    var bodyParser = require('body-parser');
+    var app = express();
+    var http = require('http').Server(app);
+    var io = require('socket.io')(http);
+
+    app.use(bodyParser.json());
+    app.post('/source', this.handleSourcePost.bind(this));
+    app.post('/sourceList', this.handleSourceListPost.bind(this));
+    app.get('/heapDump.json', this.handleHeapDumpGet.bind(this));
+    app.use('/', express.static(__dirname + '/static'));
+
+    http.listen(optHttpPort, function () {
+        console.log('Listening on *:' + optHttpPort);
+    });
+
+    io.on('connection', this.handleNewSocketIoConnection.bind(this));
+
+    this.dbg.on('attached', function () {
+        console.log('Debugger attached');
+    });
+
+    this.dbg.on('detached', function () {
+        console.log('Debugger detached');
+    });
+
+    this.dbg.on('debug-stats-update', function () {
+        _this.debugStatsLimiter.trigger();
+    });
+
+    this.dbg.on('ui-message-update', function () {
+        // Explicit rate limiter because this is a source of a lot of traffic.
+        _this.uiMessageLimiter.trigger();
+    });
+
+    this.dbg.on('basic-info-update', function () {
+        _this.emitBasicInfo();
+    });
+
+    this.dbg.on('breakpoints-update', function () {
+        _this.emitBreakpoints();
+    });
+
+    this.dbg.on('exec-status-update', function () {
+        // Explicit rate limiter because this is a source of a lot of traffic.
+        _this.execStatusLimiter.trigger();
+    });
+
+    this.dbg.on('locals-update', function () {
+        _this.emitLocals();
+    });
+
+    this.dbg.on('callstack-update', function () {
+        _this.emitCallStack();
+    });
+
+    this.uiMessageLimiter = new RateLimited(10, 1000, this.uiMessageLimiterCallback.bind(this));
+    this.execStatusLimiter = new RateLimited(50, 500, this.execStatusLimiterCallback.bind(this));
+    this.debugStatsLimiter = new RateLimited(1, 2000, this.debugStatsLimiterCallback.bind(this));
+
+    this.keepaliveTimer = setInterval(this.emitKeepalive.bind(this), 30000);
+};
+
+DebugWebServer.prototype.handleNewSocketIoConnection = function (socket) {
+    var _this = this;
+
+    console.log('Socket.io connected');
+    if (this.socket) {
+        console.log('Closing previous socket.io socket');
+        this.socket.emit('replaced');
+    }
+    this.socket = socket;
+
+    this.emitKeepalive();
+
+    socket.on('disconnect', function () {
+        console.log('Socket.io disconnected');
+        if (_this.socket === socket) {
+             _this.socket = null;
+        }
+    });
+
+    socket.on('keepalive', function (msg) {
+        // nop
+    });
+
+    socket.on('attach', function (msg) {
+        if (_this.dbg.targetStream) {
+            console.log('Attach request when debugger already has a connection, ignoring');
+        } else {
+            _this.dbg.connectDebugger();
+        }
+    });
+
+    socket.on('detach', function (msg) {
+        // Try to detach cleanly, timeout if no response
+        Promise.any([
+            _this.dbg.sendDetachRequest(),
+            Promise.delay(3000)
+        ]).finally(function () {
+            _this.dbg.disconnectDebugger();
+        });
+    });
+
+    socket.on('stepinto', function (msg) {
+        _this.dbg.sendStepIntoRequest();
+    });
+
+    socket.on('stepover', function (msg) {
+        _this.dbg.sendStepOverRequest();
+    });
+
+    socket.on('stepout', function (msg) {
+        _this.dbg.sendStepOutRequest();
+    });
+
+    socket.on('pause', function (msg) {
+        _this.dbg.sendPauseRequest();
+    });
+
+    socket.on('resume', function (msg) {
+        _this.dbg.sendResumeRequest();
+    });
+
+    socket.on('eval', function (msg) {
+        // msg.input is a proper Unicode strings here, and needs to be
+        // converted into a protocol string (U+0000...U+00FF).
+        var input = stringToDebugString(msg.input);
+        _this.dbg.sendEvalRequest(input).then(function (v) {
+            socket.emit('eval-result', { error: v.error, result: prettyUiDebugValue(v.value, EVAL_CLIPLEN) });
+        });
+
+        // An eval call quite possibly changes the local variables so always
+        // re-read locals afterwards.  We don't need to wait for eval() to
+        // complete here; the requests will pipeline automatically and be
+        // executed in order.
+        _this.dbg.sendGetLocalsRequest();
+    });
+
+    socket.on('getvar', function (msg) {
+        // msg.varname is a proper Unicode strings here, and needs to be
+        // converted into a protocol string (U+0000...U+00FF).
+        var varname = stringToDebugString(msg.varname);
+        _this.dbg.sendGetVarRequest(varname)
+        .then(function (v) {
+            socket.emit('getvar-result', { found: v.found, result: prettyUiDebugValue(v.value, GETVAR_CLIPLEN) });
+        });
+    });
+
+    socket.on('putvar', function (msg) {
+        // msg.varname and msg.varvalue are proper Unicode strings here, they
+        // need to be converted into protocol strings (U+0000...U+00FF).
+        var varname = stringToDebugString(msg.varname);
+        var varvalue = msg.varvalue;
+
+        // varvalue is JSON parsed by the web UI for now, need special string
+        // encoding here.
+        if (typeof varvalue === 'string') {
+            varvalue = stringToDebugString(msg.varvalue);
+        }
+
+        _this.dbg.sendPutVarRequest(varname, varvalue)
+        .then(function (v) {
+            console.log('putvar done');  // XXX: signal success to UI?
+        });
+
+        // A PutVar call quite possibly changes the local variables so always
+        // re-read locals afterwards.  We don't need to wait for eval() to
+        // complete here; the requests will pipeline automatically and be
+        // executed in order.
+        _this.dbg.sendGetLocalsRequest();
+    });
+
+    socket.on('add-breakpoint', function (msg) {
+        _this.dbg.changeBreakpoint(msg.fileName, msg.lineNumber, 'add');
+    });
+
+    socket.on('delete-breakpoint', function (msg) {
+        _this.dbg.changeBreakpoint(msg.fileName, msg.lineNumber, 'delete');
+    });
+
+    socket.on('toggle-breakpoint', function (msg) {
+        _this.dbg.changeBreakpoint(msg.fileName, msg.lineNumber, 'toggle');
+    });
+
+    socket.on('delete-all-breakpoints', function (msg) {
+        _this.dbg.changeBreakpoint(null, null, 'deleteall');
+    });
+
+    socket.on('get-bytecode', function (msg) {
+        _this.dbg.sendGetBytecodeRequest().then(function (res) {
+            socket.emit('bytecode', res);
+        });
+    });
+
+    // Resend all debugger state for new client
+    this.cachedJson = {};  // clear client state cache
+    this.emitBasicInfo();
+    this.emitStats();
+    this.emitExecStatus();
+    this.emitUiMessages();
+    this.emitBreakpoints();
+    this.emitCallStack();
+    this.emitLocals();
+};
+
+// Check if 'msg' would encode to the same JSON which was previously sent
+// to the web client.  The caller then avoid resending unnecessary stuff.
+DebugWebServer.prototype.cachedJsonCheck = function (cacheKey, msg) {
+    var newJson = JSON.stringify(msg);
+    if (this.cachedJson[cacheKey] === newJson) {
+        return true;  // cached
+    }
+    this.cachedJson[cacheKey] = newJson;
+    return false;  // not cached, send (cache already updated)
+};
+
+DebugWebServer.prototype.uiMessageLimiterCallback = function () {
+    this.emitUiMessages();
+};
+
+DebugWebServer.prototype.execStatusLimiterCallback = function () {
+    this.emitExecStatus();
+};
+
+DebugWebServer.prototype.debugStatsLimiterCallback = function () {
+    this.emitStats();
+};
+
+DebugWebServer.prototype.emitKeepalive = function () {
+    if (!this.socket) { return; }
+
+    this.socket.emit('keepalive', { nodeVersion: process.version });
+};
+
+DebugWebServer.prototype.emitBasicInfo = function () {
+    if (!this.socket) { return; }
+
+    var newMsg = {
+        duk_version: this.dbg.dukVersion,
+        duk_git_describe: this.dbg.dukGitDescribe,
+        target_info: this.dbg.targetInfo,
+        endianness: this.dbg.endianness
+    };
+    if (this.cachedJsonCheck('basic-info', newMsg)) {
+        return;
+    }
+    this.socket.emit('basic-info', newMsg);
+};
+
+DebugWebServer.prototype.emitStats = function () {
+    if (!this.socket) { return; }
+
+    this.socket.emit('debug-stats', this.dbg.stats);
+};
+
+DebugWebServer.prototype.emitExecStatus = function () {
+    if (!this.socket) { return; }
+
+    var newMsg = this.dbg.execStatus;
+    if (this.cachedJsonCheck('exec-status', newMsg)) {
+        return;
+    }
+    this.socket.emit('exec-status', newMsg);
+};
+
+DebugWebServer.prototype.emitUiMessages = function () {
+    if (!this.socket) { return; }
+
+    var newMsg = this.dbg.messageLines;
+    if (this.cachedJsonCheck('output-lines', newMsg)) {
+        return;
+    }
+    this.socket.emit('output-lines', newMsg);
+};
+
+DebugWebServer.prototype.emitBreakpoints = function () {
+    if (!this.socket) { return; }
+
+    var newMsg = { breakpoints: this.dbg.breakpoints };
+    if (this.cachedJsonCheck('breakpoints', newMsg)) {
+        return;
+    }
+    this.socket.emit('breakpoints', newMsg);
+};
+
+DebugWebServer.prototype.emitCallStack = function () {
+    if (!this.socket) { return; }
+
+    var newMsg = { callstack: this.dbg.callstack };
+    if (this.cachedJsonCheck('callstack', newMsg)) {
+        return;
+    }
+    this.socket.emit('callstack', newMsg);
+};
+
+DebugWebServer.prototype.emitLocals = function () {
+    if (!this.socket) { return; }
+
+    var newMsg = { locals: this.dbg.locals };
+    if (this.cachedJsonCheck('locals', newMsg)) {
+        return;
+    }
+    this.socket.emit('locals', newMsg);
+};
+
+/*
+ *  JSON debug proxy
+ */
+
+function DebugProxy(serverPort) {
+    this.serverPort = serverPort;
+    this.server = null;
+    this.socket = null;
+    this.targetStream = null;
+    this.inputParser = null;
+
+    // preformatted dvalues
+    this.dval_eom = formatDebugValue(DVAL_EOM);
+    this.dval_req = formatDebugValue(DVAL_REQ);
+    this.dval_rep = formatDebugValue(DVAL_REP);
+    this.dval_nfy = formatDebugValue(DVAL_NFY);
+    this.dval_err = formatDebugValue(DVAL_ERR);
+}
+
+DebugProxy.prototype.determineCommandNumber = function (cmdString, cmdNumber) {
+    var ret;
+    if (typeof cmdString === 'string') {
+        ret = debugCommandNumbers[cmdString];
+    }
+    ret = ret || cmdNumber;
+    if (typeof ret !== 'number') {
+        throw Error('cannot figure out command number for "' + cmdString + '" (' + cmdNumber + ')');
+    }
+    return ret;
+};
+
+DebugProxy.prototype.commandNumberToString = function (id) {
+    return debugCommandNames[id] || String(id);
+};
+
+DebugProxy.prototype.formatDvalues = function (args) {
+    if (!args) {
+        return [];
+    }
+    return args.map(function (v) {
+        return formatDebugValue(v);
+    });
+};
+
+DebugProxy.prototype.writeJson = function (val) {
+    this.socket.write(JSON.stringify(val) + '\n');
+};
+
+DebugProxy.prototype.writeJsonSafe = function (val) {
+    try {
+        this.writeJson(val);
+    } catch (e) {
+        console.log('Failed to write JSON in writeJsonSafe, ignoring: ' + e);
+    }
+};
+
+DebugProxy.prototype.disconnectJsonClient = function () {
+    if (this.socket) {
+        this.socket.destroy();
+        this.socket = null;
+    }
+};
+
+DebugProxy.prototype.disconnectTarget = function () {
+    if (this.inputParser) {
+        this.inputParser.close();
+        this.inputParser = null;
+    }
+    if (this.targetStream) {
+        this.targetStream.destroy();
+        this.targetStream = null;
+    }
+};
+
+DebugProxy.prototype.run = function () {
+    var _this = this;
+
+    console.log('Waiting for client connections on port ' + this.serverPort);
+    this.server = net.createServer(function (socket) {
+        console.log('JSON proxy client connected');
+
+        _this.disconnectJsonClient();
+        _this.disconnectTarget();
+
+        // A byline-parser is simple and good enough for now (assume
+        // compact JSON with no newlines).
+        var socketByline = byline(socket);
+        _this.socket = socket;
+
+        socketByline.on('data', function (line) {
+            try {
+                // console.log('Received json proxy input line: ' + line.toString('utf8'));
+                var msg = JSON.parse(line.toString('utf8'));
+                var first_dval;
+                var args_dvalues = _this.formatDvalues(msg.args);
+                var last_dval = _this.dval_eom;
+                var cmd;
+
+                if (msg.request) {
+                    // "request" can be a string or "true"
+                    first_dval = _this.dval_req;
+                    cmd = _this.determineCommandNumber(msg.request, msg.command);
+                } else if (msg.reply) {
+                    first_dval = _this.dval_rep;
+                } else if (msg.notify) {
+                    // "notify" can be a string or "true"
+                    first_dval = _this.dval_nfy;
+                    cmd = _this.determineCommandNumber(msg.notify, msg.command);
+                } else if (msg.error) {
+                    first_dval = _this.dval_err;
+                } else {
+                    throw new Error('Invalid input JSON message: ' + JSON.stringify(msg));
+                }
+
+                _this.targetStream.write(first_dval);
+                if (cmd) {
+                    _this.targetStream.write(formatDebugValue(cmd));
+                }
+                args_dvalues.forEach(function (v) {
+                    _this.targetStream.write(v);
+                });
+                _this.targetStream.write(last_dval);
+            } catch (e) {
+                console.log(e);
+
+                _this.writeJsonSafe({
+                    notify: '_Error',
+                    args: [ 'Failed to handle input json message: ' + e ]
+                });
+
+                _this.disconnectJsonClient();
+                _this.disconnectTarget();
+            }
+        });
+
+        _this.connectToTarget();
+    }).listen(this.serverPort);
+};
+
+DebugProxy.prototype.connectToTarget = function () {
+    var _this = this;
+
+    console.log('Connecting to ' + optTargetHost + ':' + optTargetPort + '...');
+    this.targetStream = new net.Socket();
+    this.targetStream.connect(optTargetPort, optTargetHost, function () {
+        console.log('Debug transport connected');
+    });
+
+    this.inputParser = new DebugProtocolParser(
+        this.targetStream,
+        null,
+        optDumpDebugRead,
+        optDumpDebugPretty,
+        optDumpDebugPretty ? 'Recv: ' : null,
+        null,
+        null   // console logging is done at a higher level to match request/response
+    );
+
+    // Don't add a '_value' key to numbers.
+    this.inputParser.readableNumberValue = false;
+
+    this.inputParser.on('transport-close', function () {
+        console.log('Debug transport closed');
+
+        _this.writeJsonSafe({
+            notify: '_Disconnecting'
+        });
+
+        _this.disconnectJsonClient();
+        _this.disconnectTarget();
+    });
+
+    this.inputParser.on('transport-error', function (err) {
+        console.log('Debug transport error', err);
+
+        _this.writeJsonSafe({
+            notify: '_Error',
+            args: [ String(err) ]
+        });
+    });
+
+    this.inputParser.on('protocol-version', function (msg) {
+        var ver = msg.protocolVersion;
+        console.log('Debug version identification:', msg.versionIdentification);
+
+        _this.writeJson({
+            notify: '_Connected',
+            args: [ msg.versionIdentification ]  // raw identification string
+        });
+
+        if (ver !== 1) {
+            console.log('Protocol version ' + ver + ' unsupported, dropping connection');
+        }
+    });
+
+    this.inputParser.on('debug-message', function (msg) {
+        var t;
+
+        //console.log(msg);
+
+        if (typeof msg[0] !== 'object' || msg[0] === null) {
+            throw new Error('unexpected initial dvalue: ' + msg[0]);
+        } else if (msg.type === 'eom') {
+            throw new Error('unexpected initial dvalue: ' + msg[0]);
+        } else if (msg.type === 'req') {
+            if (typeof msg[1] !== 'number') {
+                throw new Error('unexpected request command number: ' + msg[1]);
+            }
+            t = {
+                request: _this.commandNumberToString(msg[1]),
+                command: msg[1],
+                args: msg.slice(2, msg.length - 1)
+            }
+            _this.writeJson(t);
+        } else if (msg[0].type === 'rep') {
+            t = {
+                reply: true,
+                args: msg.slice(1, msg.length - 1)
+            }
+            _this.writeJson(t);
+        } else if (msg[0].type === 'err') {
+            t = {
+                error: true,
+                args: msg.slice(1, msg.length - 1)
+            }
+            _this.writeJson(t);
+        } else if (msg[0].type === 'nfy') {
+            if (typeof msg[1] !== 'number') {
+                throw new Error('unexpected notify command number: ' + msg[1]);
+            }
+            t = {
+                notify: _this.commandNumberToString(msg[1]),
+                command: msg[1],
+                args: msg.slice(2, msg.length - 1)
+            }
+            _this.writeJson(t);
+        } else {
+            throw new Error('unexpected initial dvalue: ' + msg[0]);
+        }
+    });
+
+    this.inputParser.on('stats-update', function () {
+    });
+};
+
+/*
+ *  Command line parsing and initialization
+ */
+
+function main() {
+    console.log('((o) Duktape debugger');
+
+    // Parse arguments.
+
+    var argv = require('minimist')(process.argv.slice(2));
+    //console.dir(argv);
+    if (argv['target-host']) {
+        optTargetHost = argv['target-host'];
+    }
+    if (argv['target-port']) {
+        optTargetPort = argv['target-port'];
+    }
+    if (argv['http-port']) {
+        optHttpPort = argv['http-port'];
+    }
+    if (argv['json-proxy-port']) {
+        optJsonProxyPort = argv['json-proxy-port'];
+    }
+    if (argv['json-proxy']) {
+        optJsonProxy = argv['json-proxy'];
+    }
+    if (argv['source-dirs']) {
+        optSourceSearchDirs = argv['source-dirs'].split(path.delimiter);
+    }
+    if (argv['dump-debug-read']) {
+        optDumpDebugRead = argv['dump-debug-read'];
+    }
+    if (argv['dump-debug-write']) {
+        optDumpDebugWrite = argv['dump-debug-write'];
+    }
+    if (argv['dump-debug-pretty']) {
+        optDumpDebugPretty = argv['dump-debug-pretty'];
+    }
+    if (argv['log-messages']) {
+        optLogMessages = true;
+    }
+
+    // Dump effective options.  Also provides a list of option names.
+
+    console.log('');
+    console.log('Effective options:');
+    console.log('  --target-host:       ' + optTargetHost);
+    console.log('  --target-port:       ' + optTargetPort);
+    console.log('  --http-port:         ' + optHttpPort);
+    console.log('  --json-proxy-port:   ' + optJsonProxyPort);
+    console.log('  --json-proxy:        ' + optJsonProxy);
+    console.log('  --source-dirs:       ' + optSourceSearchDirs.join(' '));
+    console.log('  --dump-debug-read:   ' + optDumpDebugRead);
+    console.log('  --dump-debug-write:  ' + optDumpDebugWrite);
+    console.log('  --dump-debug-pretty: ' + optDumpDebugPretty);
+    console.log('  --log-messages:      ' + optLogMessages);
+    console.log('');
+
+    // Create debugger and web UI singletons, tie them together and
+    // start them.
+
+    if (optJsonProxy) {
+        console.log('Starting in JSON proxy mode, JSON port: ' + optJsonProxyPort);
+
+        var prx = new DebugProxy(optJsonProxyPort);
+        prx.run();
+    } else {
+        var dbg = new Debugger();
+        var web = new DebugWebServer();
+        dbg.web = web;
+        web.dbg = dbg;
+        dbg.run();
+        web.run();
+    }
+}
+
+main();

+ 36 - 0
src/third_party/duktape-1.3.0/debugger/duk_debugcommands.yaml

@@ -0,0 +1,36 @@
+# Debug command names.  A single map works for now because command names
+# provided by client/target don't overlap.
+- Reserved_0
+- Status
+- Print
+- Alert
+- Log
+- Gc
+- Reserved_6
+- Reserved_7
+- Reserved_8
+- Reserved_9
+- Reserved_10
+- Reserved_11
+- Reserved_12
+- Reserved_13
+- Reserved_14
+- Reserved_15
+- BasicInfo
+- TriggerStatus
+- Pause
+- Resume
+- StepInto
+- StepOver
+- StepOut
+- ListBreak
+- AddBreak
+- DelBreak
+- GetVar
+- PutVar
+- GetCallStack
+- GetLocals
+- Eval
+- Detach
+- DumpHeap
+- GetBytecode

+ 660 - 0
src/third_party/duktape-1.3.0/debugger/duk_opcodes.yaml

@@ -0,0 +1,660 @@
+# Duktape opcode metadata for debugger.
+# - See duk_debug.js for the argument formats (A_R etc).
+# - Flag bits are for the whole instruction as a 32-bit integer,
+#   they are not field shifted
+#
+# NOTE: Use YAML comments only on comment-only lines (not trailing content):
+# Node.js 'yamljs' seems to refuse parsing trailing comments in some cases.
+
+opcodes:
+  - name: LDREG
+    args:
+      - A_R
+      - BC_R
+  - name: STREG
+    args:
+      - A_R
+      - BC_R
+  - name: LDCONST
+    args:
+      - A_R
+      - BC_C
+  - name: LDINT
+    args:
+      - A_R
+      - BC_LDINT
+  - name: LDINTX
+    args:
+      - A_R
+      - BC_LDINTX
+  - name: MPUTOBJ
+    args:
+      - A_R
+      - B_R
+      - C_I
+  - name: MPUTOBJI
+    args:
+      - A_R
+      - B_RI
+      - C_I
+  - name: MPUTARR
+    args:
+      - A_R
+      - B_R
+      - C_I
+  - name: MPUTARRI
+    args:
+      - A_R
+      - B_RI
+      - C_I
+  - name: NEW
+    args:
+      - B_R
+      - C_I
+  - name: NEWI
+    args:
+      - B_RI
+      - C_I
+  - name: REGEXP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: CSREG
+    args:
+      - A_R
+      - B_R
+  - name: CSREGI
+    args:
+      - A_RI
+      - B_R
+  - name: GETVAR
+    args:
+      - A_R
+      - BC_C
+  - name: PUTVAR
+    args:
+      - A_R
+      - BC_C
+  - name: DECLVAR
+    args:
+      - A_H
+      - B_RC
+      - C_RC
+    flags:
+      - mask: 0x40
+        name: writable
+      - mask: 0x80
+        name: enumerable
+      - mask: 0x100
+        name: configurable
+      - mask: 0x200
+        name: accessor
+      - mask: 0x400
+        name: undef_value
+      - mask: 0x800
+        name: func_decl
+  - name: DELVAR
+    args:
+      - A_R
+      - B_RC
+  - name: CSVAR
+    args:
+      - A_R
+      - B_RC
+  - name: CSVARI
+    args:
+      - A_RI
+      - B_RC
+  - name: CLOSURE
+    args:
+      - A_R
+      - BC_I
+  - name: GETPROP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: PUTPROP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: DELPROP
+    args:
+      - A_R
+      - B_R
+      - C_RC
+  - name: CSPROP
+    args:
+      - A_R
+      - B_R
+      - C_RC
+  - name: CSPROPI
+    args:
+      - A_RI
+      - B_R
+      - C_RC
+  - name: ADD
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: SUB
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: MUL
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: DIV
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: MOD
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: BAND
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: BOR
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: BXOR
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: BASL
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: BLSR
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: BASR
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: EQ
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: NEQ
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: SEQ
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: SNEQ
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: GT
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: GE
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: LT
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: LE
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: IF
+    args:
+      - A_B
+      - B_RC
+  - name: JUMP
+    args:
+      - ABC_JUMP
+  - name: RETURN
+    args:
+      - A_H
+      - B_RC
+    flags:
+      - mask: 0x40
+        name: fast_return
+      - mask: 0x80
+        name: have_retval
+  - name: CALL
+    args:
+      - A_H
+      - B_R
+      - C_I
+    flags:
+      - mask: 0x40
+        name: tailcall
+      - mask: 0x80
+        name: evalcall
+  - name: CALLI
+    args:
+      - A_H
+      - B_RI
+      - C_I
+  - name: TRYCATCH
+    args:
+      - A_H
+      # base register for two consecutive regs (base_reg + 0, base_reg + 1) used for two things:
+      # - input: either 'with' target register or catch varname constant (base_reg + 0), depending on flags
+      # - output: when caught, catch value (base_reg + 0) and type (base_reg + 1)
+      - BC_R
+    flags:
+      - mask: 0x40
+        name: have_catch
+      - mask: 0x80
+        name: have_finally
+      - mask: 0x100
+        name: catch_binding
+      - mask: 0x200
+        name: with_binding
+  - name: EXTRA
+    extra: true
+  - name: PREINCR
+    args:
+      - A_R
+      - BC_R
+  - name: PREDECR
+    args:
+      - A_R
+      - BC_R
+  - name: POSTINCR
+    args:
+      - A_R
+      - BC_R
+  - name: POSTDECR
+    args:
+      - A_R
+      - BC_R
+  - name: PREINCV
+    args:
+      - A_R
+      - BC_C
+  - name: PREDECV
+    args:
+      - A_R
+      - BC_C
+  - name: POSTINCV
+    args:
+      - A_R
+      - BC_C
+  - name: POSTDECV
+    args:
+      - A_R
+      - BC_C
+  - name: PREINCP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: PREDECP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: POSTINCP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+  - name: POSTDECP
+    args:
+      - A_R
+      - B_RC
+      - C_RC
+
+extra:
+  - name: NOP
+  - name: INVALID
+    args:
+      - BC_I
+  - name: LDTHIS
+    args:
+      - BC_R
+  - name: LDUNDEF
+    args:
+      - BC_R
+  - name: LDNULL
+    args:
+      - BC_R
+  - name: LDTRUE
+    args:
+      - BC_R
+  - name: LDFALSE
+    args:
+      - BC_R
+  - name: NEWOBJ
+    args:
+      # XXX: extend to BC?
+      - B_R
+  - name: NEWARR
+    args:
+      # XXX: extend to BC?
+      - B_R
+  - name: SETALEN
+    args:
+      - B_R
+      - C_R
+  - name: TYPEOF
+    args:
+      - BC_R
+  - name: TYPEOFID
+    args:
+      - B_R
+      # maybe changed to C_C later
+      - C_RC
+  - name: INITENUM
+    args:
+      - B_R
+      - C_R
+  - name: NEXTENUM
+    args:
+      - B_R
+      - C_R
+  - name: INITSET
+    args:
+      - B_R
+      - C_R
+  - name: INITSETI
+    args:
+      - B_R
+      - C_RI
+  - name: INITGET
+    args:
+      - B_R
+      - C_RI
+  - name: INITGETI
+    args:
+      - B_R
+      - C_RI
+  - name: ENDTRY
+  - name: ENDCATCH
+  - name: ENDFIN
+  - name: THROW
+    args:
+      - BC_R
+  - name: INVLHS
+  - name: UNM
+    args:
+      - BC_R
+  - name: UNP
+    args:
+      - BC_R
+  - name: DEBUGGER
+  - name: BREAK
+    args:
+      - BC_I
+  - name: CONTINUE
+    args:
+      - BC_I
+  - name: BNOT
+    args:
+      - BC_R
+  - name: LNOT
+    args:
+      - BC_R
+  - name: INSTOF
+    args:
+      - B_R
+      - C_RC
+  - name: IN
+    args:
+      - B_R
+      - C_RC
+  - name: LABEL
+    args:
+      - BC_I
+  - name: ENDLABEL
+    args:
+      - BC_I
+  - name: EXTRA34
+  - name: EXTRA35
+  - name: EXTRA36
+  - name: EXTRA37
+  - name: EXTRA38
+  - name: EXTRA39
+  - name: EXTRA40
+  - name: EXTRA41
+  - name: EXTRA42
+  - name: EXTRA43
+  - name: EXTRA44
+  - name: EXTRA45
+  - name: EXTRA46
+  - name: EXTRA47
+  - name: EXTRA48
+  - name: EXTRA49
+  - name: EXTRA50
+  - name: EXTRA51
+  - name: EXTRA52
+  - name: EXTRA53
+  - name: EXTRA54
+  - name: EXTRA55
+  - name: EXTRA56
+  - name: EXTRA57
+  - name: EXTRA58
+  - name: EXTRA59
+  - name: EXTRA60
+  - name: EXTRA61
+  - name: EXTRA62
+  - name: EXTRA63
+  - name: EXTRA64
+  - name: EXTRA65
+  - name: EXTRA66
+  - name: EXTRA67
+  - name: EXTRA68
+  - name: EXTRA69
+  - name: EXTRA70
+  - name: EXTRA71
+  - name: EXTRA72
+  - name: EXTRA73
+  - name: EXTRA74
+  - name: EXTRA75
+  - name: EXTRA76
+  - name: EXTRA77
+  - name: EXTRA78
+  - name: EXTRA79
+  - name: EXTRA80
+  - name: EXTRA81
+  - name: EXTRA82
+  - name: EXTRA83
+  - name: EXTRA84
+  - name: EXTRA85
+  - name: EXTRA86
+  - name: EXTRA87
+  - name: EXTRA88
+  - name: EXTRA89
+  - name: EXTRA90
+  - name: EXTRA91
+  - name: EXTRA92
+  - name: EXTRA93
+  - name: EXTRA94
+  - name: EXTRA95
+  - name: EXTRA96
+  - name: EXTRA97
+  - name: EXTRA98
+  - name: EXTRA99
+  - name: EXTRA100
+  - name: EXTRA101
+  - name: EXTRA102
+  - name: EXTRA103
+  - name: EXTRA104
+  - name: EXTRA105
+  - name: EXTRA106
+  - name: EXTRA107
+  - name: EXTRA108
+  - name: EXTRA109
+  - name: EXTRA110
+  - name: EXTRA111
+  - name: EXTRA112
+  - name: EXTRA113
+  - name: EXTRA114
+  - name: EXTRA115
+  - name: EXTRA116
+  - name: EXTRA117
+  - name: EXTRA118
+  - name: EXTRA119
+  - name: EXTRA120
+  - name: EXTRA121
+  - name: EXTRA122
+  - name: EXTRA123
+  - name: EXTRA124
+  - name: EXTRA125
+  - name: EXTRA126
+  - name: EXTRA127
+  - name: EXTRA128
+  - name: EXTRA129
+  - name: EXTRA130
+  - name: EXTRA131
+  - name: EXTRA132
+  - name: EXTRA133
+  - name: EXTRA134
+  - name: EXTRA135
+  - name: EXTRA136
+  - name: EXTRA137
+  - name: EXTRA138
+  - name: EXTRA139
+  - name: EXTRA140
+  - name: EXTRA141
+  - name: EXTRA142
+  - name: EXTRA143
+  - name: EXTRA144
+  - name: EXTRA145
+  - name: EXTRA146
+  - name: EXTRA147
+  - name: EXTRA148
+  - name: EXTRA149
+  - name: EXTRA150
+  - name: EXTRA151
+  - name: EXTRA152
+  - name: EXTRA153
+  - name: EXTRA154
+  - name: EXTRA155
+  - name: EXTRA156
+  - name: EXTRA157
+  - name: EXTRA158
+  - name: EXTRA159
+  - name: EXTRA160
+  - name: EXTRA161
+  - name: EXTRA162
+  - name: EXTRA163
+  - name: EXTRA164
+  - name: EXTRA165
+  - name: EXTRA166
+  - name: EXTRA167
+  - name: EXTRA168
+  - name: EXTRA169
+  - name: EXTRA170
+  - name: EXTRA171
+  - name: EXTRA172
+  - name: EXTRA173
+  - name: EXTRA174
+  - name: EXTRA175
+  - name: EXTRA176
+  - name: EXTRA177
+  - name: EXTRA178
+  - name: EXTRA179
+  - name: EXTRA180
+  - name: EXTRA181
+  - name: EXTRA182
+  - name: EXTRA183
+  - name: EXTRA184
+  - name: EXTRA185
+  - name: EXTRA186
+  - name: EXTRA187
+  - name: EXTRA188
+  - name: EXTRA189
+  - name: EXTRA190
+  - name: EXTRA191
+  - name: EXTRA192
+  - name: EXTRA193
+  - name: EXTRA194
+  - name: EXTRA195
+  - name: EXTRA196
+  - name: EXTRA197
+  - name: EXTRA198
+  - name: EXTRA199
+  - name: EXTRA200
+  - name: EXTRA201
+  - name: EXTRA202
+  - name: EXTRA203
+  - name: EXTRA204
+  - name: EXTRA205
+  - name: EXTRA206
+  - name: EXTRA207
+  - name: EXTRA208
+  - name: EXTRA209
+  - name: EXTRA210
+  - name: EXTRA211
+  - name: EXTRA212
+  - name: EXTRA213
+  - name: EXTRA214
+  - name: EXTRA215
+  - name: EXTRA216
+  - name: EXTRA217
+  - name: EXTRA218
+  - name: EXTRA219
+  - name: EXTRA220
+  - name: EXTRA221
+  - name: EXTRA222
+  - name: EXTRA223
+  - name: EXTRA224
+  - name: EXTRA225
+  - name: EXTRA226
+  - name: EXTRA227
+  - name: EXTRA228
+  - name: EXTRA229
+  - name: EXTRA230
+  - name: EXTRA231
+  - name: EXTRA232
+  - name: EXTRA233
+  - name: EXTRA234
+  - name: EXTRA235
+  - name: EXTRA236
+  - name: EXTRA237
+  - name: EXTRA238
+  - name: EXTRA239
+  - name: EXTRA240
+  - name: EXTRA241
+  - name: EXTRA242
+  - name: EXTRA243
+  - name: EXTRA244
+  - name: EXTRA245
+  - name: EXTRA246
+  - name: EXTRA247
+  - name: EXTRA248
+  - name: EXTRA249
+  - name: EXTRA250
+  - name: EXTRA251
+  - name: EXTRA252
+  - name: EXTRA253
+  - name: EXTRA254
+  - name: EXTRA255

+ 27 - 0
src/third_party/duktape-1.3.0/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.3.0/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>

+ 512 - 0
src/third_party/duktape-1.3.0/debugger/static/style.css

@@ -0,0 +1,512 @@
+// http://stackoverflow.com/questions/71074/how-to-remove-firefoxs-dotted-outline-on-buttons-as-well-as-links/3844452#3844452
+:focus {
+	outline: none;
+}
+::-moz-focus-inner {
+	border: 0;
+}
+
+@keyframes pulsate {
+	from { opacity: 1; }
+	to { opacity: 0.25; }
+}
+
+#part-header {
+	background: #444444;
+	color: #ffffff;
+	font: 24pt monospace;
+	border-bottom: 2px solid #cccccc;
+	padding: 20px 0px 20px 10px;
+}
+
+/* http://css-tricks.com/snippets/css/a-guide-to-flexbox/ */
+#part-middle {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: nowrap;
+	justify-content: space-between;
+	align-items: stretch;
+	align-content: stretch;
+
+	min-height: 800px;
+
+	border-top: 1px solid #ffffff;
+	padding: 8px;
+	margin-top: 2px;
+}
+#left-area {
+	flex: 0 0 11em;
+	margin-right: 20px;
+	margin-bottom: 10px;
+}
+#center-area {
+	flex: 1 1 0;
+	margin-bottom: 10px;
+}
+#right-area {
+	flex: 0 0 40em;
+	margin-left: 20px;
+	margin-bottom: 10px;
+}
+
+#part-footer {
+	clear: both;
+	border-top: 2px solid #bbbbbb;
+	background: #eeeeee;
+	color: #555555;
+	text-align: center;
+	padding-top: 12px;
+	padding-bottom: 12px;
+	line-height: 1.5;
+}
+
+#exec-status {
+	margin-top: 25px;
+	margin-bottom: 25px;
+}
+#exec-state {
+	display: inline-block;
+	vertical-align: middle;
+}
+#exec-other {
+	display: inline-block;
+	vertical-align: middle;
+	font-size: 125%;
+}
+#current-state {
+	background: #228822;
+	color: #ffffff;
+	font: 16pt;
+	padding: 6pt;
+	border: 5px solid #228822;
+	border-radius: 10px;
+	font-size: 200%;
+	font-weight: bold;
+	margin-right: 10px;
+}
+#current-state.notrunning {
+	background: #882222;
+	border: 5px solid #882222;
+	border-radius: 10px;
+	animation: pulsate 0.7s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate;
+}
+#exec-other:hover {
+	text-decoration: underline;
+	color: #9999ff;
+}
+
+#left-area button {
+	display: inline-block;
+	width: 100%;
+	min-width: 8em;
+	background: #226622;
+	color: #ffffff;
+	font: 16pt sans-serif;
+	font-weight: bold;
+	text-decoration: none;
+	margin: 10px 0 0 0;
+	padding: 0.4em;
+	border: 2px solid #000000;
+	border-radius: 4px;
+}
+#left-area button a {
+	color: #ffffff;
+	text-decoration: none;
+}
+#left-area button:hover {
+	background: #55aa55;
+}
+#left-area button:disabled {
+	background: #555555;
+	color: #888888;
+}
+#left-area button:disabled a {
+	background: #555555;
+	color: #888888;
+}
+
+#pause-button.pending {
+	background: #5555ff;
+	animation: pulsate 0.2s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate;
+}
+
+#attach-button {
+}
+#attach-button.enabled {
+	animation: pulsate 0.7s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate;
+}
+
+.duktape-exec-line {
+	outline: 2px solid red;
+	background: #550000;
+}
+.duktape-break-line {
+	outline: 2px solid white;
+}
+
+#output {
+	font: 9pt monospace;
+	color: #000000;
+	border: 2px solid #cccccc;
+	border-radius: 5px;
+	padding: 3px;
+	height: 30ex;
+	overflow: scroll;
+	overflow-x: auto;
+	overflow-y: scroll;
+	white-space: pre;
+}
+#output .alert {
+	color: #ff0000;
+}
+/* Default color (should be overridden by level) */
+#output .log {
+	color: #00ff00;
+}
+/* Trace */
+#output .loglevel0 {
+	color: #cccccc;
+}
+/* Debug */
+#output .loglevel1 {
+	color: #cccccc;
+}
+/* Info */
+#output .loglevel2 {
+	color: #888888;
+	font-weight: bold;
+}
+/* Warn */
+#output .loglevel3 {
+	color: #ff4444;
+	font-weight: bold;
+}
+/* Error */
+#output .loglevel4 {
+	color: #ff0000;
+	font-weight: bold;
+}
+/* Fatal */
+#output .loglevel5 {
+	background: #000000;
+	color: #ff0000;
+	font-weight: bold;
+}
+#output .debugger-info {
+	color: #880000;
+	font-weight: bold;
+	font-style: italic;
+}
+#output .debugger-debug {
+	color: #888888;
+	font-weight: bold;
+	font-style: italic;
+}
+
+#callstack {
+	font: 9pt monospace;
+	color: #000000;
+	margin-top: 10px;
+	border: 2px solid #cccccc;
+	border-radius: 5px;
+	padding: 3px;
+	height: 14ex;
+	overflow: scroll;
+	overflow-x: auto;
+	overflow-y: scroll;
+	white-space: pre;
+}
+#callstack div:nth-child(2n) {
+	background: #eeeeee;
+}
+#callstack .func {
+}
+#callstack .rest {
+	float: right;
+	color: #6666ff;
+}
+#callstack .rest:hover {
+	text-decoration: underline;
+	color: #9999ff;
+}
+
+#locals {
+	font: 9pt monospace;
+	color: #000000;
+	margin-top: 10px;
+	border: 2px solid #cccccc;
+	border-radius: 5px;
+	padding: 10px;
+	height: 30ex;
+	overflow: scroll;
+	overflow-x: auto;
+	overflow-y: scroll;
+	white-space: pre;
+}
+#locals div:nth-child(2n) {
+	background: #eeeeee;
+}
+#locals .key {
+}
+#locals .value {
+	float: right;
+	color: #888888;
+}
+
+#breakpoints {
+	color: #000000;
+	margin-top: 10px;
+	border: 2px solid #cccccc;
+	border-radius: 5px;
+	padding: 3px;
+	height: 15ex;
+	overflow: scroll;
+	overflow-x: auto;
+	overflow-y: scroll;
+	white-space: pre;
+}
+#breakpoints div {
+	margin: 2px 0 2px 0;
+}
+#breakpoints div:nth-child(2n) {
+	background: #eeeeee;
+}
+#breakpoints a {
+	font: 9pt monospace;
+	color: #6666ff;
+}
+#breakpoints a:hover {
+	text-decoration: underline;
+	color: #9999ff;
+}
+.breakpoint-line {
+	clear: both;
+	padding-top: 2px;
+	padding-bottom: 2px;
+}
+#add-breakpoint-file {
+	font: 10pt monospace;
+	width: 10em;
+	padding: 5px;
+}
+#add-breakpoint-line {
+	font: 10pt monospace;
+	width: 3em;
+	margin-left: 3px;
+	padding: 5px;
+}
+#delete-all-breakpoints-button {
+	float: right;
+	font: 10pt sans-serif;
+	padding: 5px;
+	border: 1px solid #888888;
+	background: #ddffdd;
+	color: #000000;
+}
+#delete-all-breakpoints-button:hover {
+	background: #f8fff8;
+}
+#delete-all-breakpoints-button:disabled {
+	background: #dddddd;
+	color: #444444;
+}
+#add-breakpoint-button {
+	font: 10pt sans-serif;
+	margin-left: 10px;
+	padding: 5px;
+	border: 1px solid #888888;
+	background: #ddffdd;
+	color: #000000;
+}
+#add-breakpoint-button:hover {
+	background: #f8fff8;
+}
+#add-breakpoint-button:disabled {
+	background: #dddddd;
+	color: #444444;
+}
+#breakpoint-hint {
+	color: #aaaaaa;
+	font-style: italic;
+	margin-left: 10px;
+}
+.delete-breakpoint-button {
+	float: right;
+	display: inline;
+	font: 9pt sans-serif;
+	padding: 3px;
+	border: none;
+	background: none;
+	color: #6666ff;
+}
+.delete-breakpoint-button {
+	font: 9pt sans-serif;
+}
+.delete-breakpoint-button:hover {
+	text-decoration: underline;
+	color: #9999ff;
+}
+.delete-breakpoint-button:disabled {
+	color: #888888;
+}
+
+#about-dialog p {
+	margin: 10px 0 10px 0;
+}
+
+#bytecode-dialog p {
+	margin: 10px 0 10px 0;
+}
+#bytecode-dialog pre {
+	font: 14pt monospace;
+	color: #000000;
+}
+
+#eval {
+	color: #000000;
+	margin-top: 10px;
+	border: 2px solid #cccccc;
+	border-radius: 5px;
+	padding: 3px;
+	height: 30ex;
+	overflow: scroll;
+	overflow-x: auto;
+	overflow-y: scroll;
+	white-space: pre;
+}
+#eval-input {
+	display: inline;
+	font: 10pt monospace;
+	width: 20em;
+	padding: 5px;
+}
+#eval-button {
+	display: inline;
+	margin-left: 10px;
+	padding: 5px;
+	border: 1px solid #888888;
+	font: 10pt sans-serif;
+	background: #ddffdd;
+	color: #000000;
+}
+#eval-button {
+}
+#eval-button:hover {
+	background: #f8fff8;
+}
+#eval-button:disabled {
+	background: #dddddd;
+	color: #444444;
+}
+#eval-button.pending {
+	background: #5555ff;
+	animation: pulsate 0.2s cubic-bezier(0.75, 0, 0.75, 1) infinite alternate;
+}
+#eval-watch {
+	margin-left: 20px;
+	vertical-align: middle;
+}
+#eval-output {
+	font: 10pt monospace;
+	white-space: pre;
+	padding: 5px;
+	border: 1px solid #888888;
+	min-height: 4ex;
+	margin-top: 5px;
+}
+
+#varname-input {
+	font: 10pt monospace;
+	width: 10em;
+	padding: 5px;
+}
+#varvalue-input {
+	margin-left: 10px;
+	font: 10pt monospace;
+	width: 20em;
+	padding: 5px;
+}
+#getvar-button,
+#putvar-button {
+	display: inline;
+	float: right;
+	margin-left: 10px;
+	padding: 5px;
+	border: 1px solid #888888;
+	font: 10pt sans-serif;
+	background: #ddffdd;
+	color: #000000;
+}
+#getvar-button:hover,
+#putvar-button:hover {
+	background: #f8fff8;
+}
+#getvar-button:disabled,
+#putvar-button:disabled {
+	background: #dddddd;
+	color: #444444;
+}
+#var-output {
+	font: 10pt monospace;
+	white-space: pre;
+	padding: 5px;
+	border: 1px solid #888888;
+	min-height: 4ex;
+	margin-top: 5px;
+}
+
+#source-pre {
+	margin-top: 10px;
+	border: 2px solid #cccccc;
+	border-radius: 5px;
+	height: 400px;
+	overflow: scroll;
+	overflow-x: auto;
+	overflow-y: scroll;
+}
+#source-pre.running {
+	background: #eeeeee;
+	color: #888888;
+}
+#source-pre.running #source-code {
+	background: #eeeeee;
+	color: #888888;
+}
+#source-filename {
+	font-size: 125%;
+	color: #888888;
+}
+code.sourcecode {
+	counter-reset: source-line;
+}
+code.sourcecode div {
+	font: 10pt monospace;
+	padding: 2px 5px 2px 5px;
+	white-space: pre;
+	border-bottom: 1px solid #eeeeee;
+}
+code.sourcecode div:before {
+	display: inline-block;
+	content: counter(source-line);
+	counter-increment: source-line;
+	width: 4em;
+	color: #888888;
+	text-align: right;
+	margin-right: 20px;
+}
+code.sourcecode div.breakpoint:before {
+	margin-right: 0px;
+	border-right: 20px solid #ff0000;
+}
+code.sourcecode div.highlight {
+	background: #aaaaaa;
+	color: #000000;
+}
+code.sourcecode div.execution {
+	background: #000000;
+	color: #ffffff;
+}
+
+#source-select {
+	margin-top: 5px;
+}

+ 745 - 0
src/third_party/duktape-1.3.0/debugger/static/webui.js

@@ -0,0 +1,745 @@
+/*
+ *  Duktape debugger web client
+ *
+ *  Talks to the NodeJS server using socket.io.
+ *
+ *  http://unixpapa.com/js/key.html
+ */
+
+// Update interval for custom source highlighting.
+var SOURCE_UPDATE_INTERVAL = 350;
+
+// Source view
+var activeFileName = null;          // file that we want to be loaded in source view
+var activeLine = null;              // scroll to line once file has been loaded
+var activeHighlight = null;         // line that we want to highlight (if any)
+var loadedFileName = null;          // currently loaded (shown) file
+var loadedLineCount = 0;            // currently loaded file line count
+var loadedFileExecuting = false;    // true if currFileName (loosely) matches loadedFileName
+var loadedLinePending = null;       // if set, scroll loaded file to requested line
+var highlightLine = null;           // highlight line
+var sourceEditedLines = [];         // line numbers which have been modified
+                                    // (added classes etc, tracked for removing)
+var sourceUpdateInterval = null;    // timer for updating source view
+var sourceFetchXhr = null;          // current AJAX request for fetching a source file (if any)
+var forceButtonUpdate = false;      // hack to reset button states
+
+// Execution state
+var prevState = null;             // previous execution state ('paused', 'running', etc)
+var prevAttached = null;          // previous debugger attached state (true, false, null)
+var currFileName = null;          // current filename being executed
+var currFuncName = null;          // current function name being executed
+var currLine = 0;                 // current line being executed
+var currPc = 0;                   // current bytecode PC being executed
+var currState = 0;                // current execution state ('paused', 'running', 'detached', etc)
+var currAttached = false;         // current debugger attached state (true or false)
+var currLocals = [];              // current local variables
+var currCallstack = [];           // current callstack (from top to bottom)
+var currBreakpoints = [];         // current breakpoints
+var startedRunning = 0;           // timestamp when last started running (if running)
+                                  // (used to grey out the source file if running for long enough)
+
+/*
+ *  Helpers
+ */
+
+function formatBytes(x) {
+    if (x < 1024) {
+        return String(x) + ' bytes';
+    } else if (x < 1024 * 1024) {
+        return (x / 1024).toPrecision(3) + ' kB';
+    } else {
+        return (x / (1024 * 1024)).toPrecision(3) + ' MB';
+    }
+}
+
+/*
+ *  Source view periodic update handling
+ */
+
+function doSourceUpdate() {
+    var elem;
+
+    // Remove previously added custom classes
+    sourceEditedLines.forEach(function (linenum) {
+        elem = $('#source-code div')[linenum - 1];
+        if (elem) {
+            elem.classList.remove('breakpoint');
+            elem.classList.remove('execution');
+            elem.classList.remove('highlight');
+        }
+    });
+    sourceEditedLines.length = 0;
+
+    // If we're executing the file shown, highlight current line
+    if (loadedFileExecuting) {
+        elem = $('#source-code div')[currLine - 1];
+        if (elem) {
+            sourceEditedLines.push(currLine);
+            elem.classList.add('execution');
+        }
+    }
+
+    // Add breakpoints
+    currBreakpoints.forEach(function (bp) {
+        if (bp.fileName === loadedFileName) {
+            elem = $('#source-code div')[bp.lineNumber - 1];
+            if (elem) {
+                sourceEditedLines.push(bp.lineNumber);
+                elem.classList.add('breakpoint');
+            }
+        }
+    });
+
+    if (highlightLine !== null) {
+        elem = $('#source-code div')[highlightLine - 1];
+        if (elem) {
+            sourceEditedLines.push(highlightLine);
+            elem.classList.add('highlight');
+        }
+    }
+
+    // If no-one requested us to scroll to a specific line, finish.
+    if (loadedLinePending == null) {
+        return;
+    }
+
+    var reqLine = loadedLinePending;
+    loadedLinePending = null;
+
+    // Scroll to requested line.  This is not very clean, so a better solution
+    // should be found:
+    // https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView
+    // http://erraticdev.blogspot.fi/2011/02/jquery-scroll-into-view-plugin-with.html
+    // http://flesler.blogspot.fi/2007/10/jqueryscrollto.html
+    var tmpLine = Math.max(reqLine - 5, 0);
+    elem = $('#source-code div')[tmpLine];
+    if (elem) {
+        elem.scrollIntoView();
+    }
+}
+
+// Source is updated periodically.  Other code can also call doSourceUpdate()
+// directly if an immediate update is needed.
+sourceUpdateInterval = setInterval(doSourceUpdate, SOURCE_UPDATE_INTERVAL);
+
+/*
+ *  UI update handling when exec-status update arrives
+ */
+
+function doUiUpdate() {
+    var now = Date.now();
+
+    // Note: loadedFileName can be either from target or from server, but they
+    // must match exactly.  We could do a loose match here, but exact matches
+    // are needed for proper breakpoint handling anyway.
+    loadedFileExecuting = (loadedFileName === currFileName);
+
+    // If we just started running, store a timestamp so we can grey out the
+    // source view only if we execute long enough (i.e. we're not just
+    // stepping).
+    if (currState !== prevState && currState === 'running') {
+        startedRunning = now;
+    }
+
+    // If we just became paused, check for eval watch
+    if (currState !== prevState && currState === 'paused') {
+        if ($('#eval-watch').is(':checked')) {
+            submitEval();  // don't clear eval input
+        }
+    }
+
+    // Update current execution state
+    if (currFileName === '' && currLine === 0) {
+        $('#current-fileline').text('');
+    } else {
+        $('#current-fileline').text(String(currFileName) + ':' + String(currLine));
+    }
+    if (currFuncName === '' && currPc === 0) {
+        $('#current-funcpc').text('');
+    } else {
+        $('#current-funcpc').text(String(currFuncName) + '() pc ' + String(currPc));
+    }
+    $('#current-state').text(String(currState));
+
+    // Update buttons
+    if (currState !== prevState || currAttached !== prevAttached || forceButtonUpdate) {
+        $('#stepinto-button').prop('disabled', !currAttached || currState !== 'paused');
+        $('#stepover-button').prop('disabled', !currAttached || currState !== 'paused');
+        $('#stepout-button').prop('disabled', !currAttached || currState !== 'paused');
+        $('#resume-button').prop('disabled', !currAttached || currState !== 'paused');
+        $('#pause-button').prop('disabled', !currAttached || currState !== 'running');
+        $('#attach-button').prop('disabled', currAttached);
+        if (currAttached) {
+            $('#attach-button').removeClass('enabled');
+        } else {
+            $('#attach-button').addClass('enabled');
+        }
+        $('#detach-button').prop('disabled', !currAttached);
+        $('#eval-button').prop('disabled', !currAttached);
+        $('#add-breakpoint-button').prop('disabled', !currAttached);
+        $('#delete-all-breakpoints-button').prop('disabled', !currAttached);
+        $('.delete-breakpoint-button').prop('disabled', !currAttached);
+        $('#putvar-button').prop('disabled', !currAttached);
+        $('#getvar-button').prop('disabled', !currAttached);
+        $('#heap-dump-download-button').prop('disabled', !currAttached);
+    }
+    if (currState !== 'running' || forceButtonUpdate) {
+        // Remove pending highlight once we're no longer running.
+        $('#pause-button').removeClass('pending');
+        $('#eval-button').removeClass('pending');
+    }
+    forceButtonUpdate = false;
+
+    // Make source window grey when running for a longer time, use a small
+    // delay to avoid flashing grey when stepping.
+    if (currState === 'running' && now - startedRunning >= 500) {
+        $('#source-pre').removeClass('notrunning');
+        $('#current-state').removeClass('notrunning');
+    } else {
+        $('#source-pre').addClass('notrunning');
+        $('#current-state').addClass('notrunning');
+    }
+
+    // Force source view to match currFileName only when running or when
+    // just became paused (from running or detached).
+    var fetchSource = false;
+    if (typeof currFileName === 'string') {
+        if (currState === 'running' ||
+            (prevState !== 'paused' && currState === 'paused') ||
+            (currAttached !== prevAttached)) {
+            if (activeFileName !== currFileName) {
+                fetchSource = true;
+                activeFileName = currFileName;
+                activeLine = currLine;
+                activeHighlight = null;
+                requestSourceRefetch();
+            }
+        }
+    }
+
+    // Force line update (scrollTop) only when running or just became paused.
+    // Otherwise let user browse and scroll source files freely.
+    if (!fetchSource) {
+        if ((prevState !== 'paused' && currState === 'paused') ||
+            currState === 'running') {
+            loadedLinePending = currLine || 0;
+        }
+    }
+}
+
+/*
+ *  Init socket.io and add handlers
+ */
+
+var socket = io();  // returns a Manager
+
+setInterval(function () {
+    socket.emit('keepalive', {
+        userAgent: (navigator || {}).userAgent
+    });
+}, 30000);
+
+socket.on('connect', function () {
+    $('#socketio-info').text('connected');
+    currState = 'connected';
+
+    fetchSourceList();
+});
+socket.on('disconnect', function () {
+    $('#socketio-info').text('not connected');
+    currState = 'disconnected';
+});
+socket.on('reconnecting', function () {
+    $('#socketio-info').text('reconnecting');
+    currState = 'reconnecting';
+});
+socket.on('error', function (err) {
+    $('#socketio-info').text(err);
+});
+
+socket.on('replaced', function () {
+    // XXX: how to minimize the chance we'll further communciate with the
+    // server or reconnect to it?  socket.reconnection()?
+
+    // We'd like to window.close() here but can't (not allowed from scripts).
+    // Alert is the next best thing.
+    alert('Debugger connection replaced by a new one, do you have multiple tabs open? If so, please close this tab.');
+});
+
+socket.on('keepalive', function (msg) {
+    // Not really interesting in the UI
+    // $('#server-info').text(new Date() + ': ' + JSON.stringify(msg));
+});
+
+socket.on('basic-info', function (msg) {
+    $('#duk-version').text(String(msg.duk_version));
+    $('#duk-git-describe').text(String(msg.duk_git_describe));
+    $('#target-info').text(String(msg.target_info));
+    $('#endianness').text(String(msg.endianness));
+});
+
+socket.on('exec-status', function (msg) {
+    currFileName = msg.fileName;
+    currFuncName = msg.funcName;
+    currLine = msg.line;
+    currPc = msg.pc;
+    currState = msg.state;
+    currAttached = msg.attached;
+
+    // Duktape now restricts execution status updates quite effectively so
+    // there's no need to rate limit UI updates now.
+
+    doUiUpdate();
+
+    prevState = currState;
+    prevAttached = currAttached;
+});
+
+// Update the "console" output based on lines sent by the server.  The server
+// rate limits these updates to keep the browser load under control.  Even
+// better would be for the client to pull this (and other stuff) on its own.
+socket.on('output-lines', function (msg) {
+    var elem = $('#output');
+    var i, n, ent;
+
+    elem.empty();
+    for (i = 0, n = msg.length; i < n; i++) {
+        ent = msg[i];
+        if (ent.type === 'print') {
+            elem.append($('<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) {
+    $('#bytecode-preformatted').text(msg.preformatted);
+    $('#bytecode-dialog').dialog('open');
+});
+
+$('#stepinto-button').click(function () {
+    socket.emit('stepinto', {});
+});
+
+$('#stepover-button').click(function () {
+    socket.emit('stepover', {});
+});
+
+$('#stepout-button').click(function () {
+    socket.emit('stepout', {});
+});
+
+$('#pause-button').click(function () {
+    socket.emit('pause', {});
+
+    // Pause may take seconds to complete so indicate it is pending.
+    $('#pause-button').addClass('pending');
+});
+
+$('#resume-button').click(function () {
+    socket.emit('resume', {});
+});
+
+$('#attach-button').click(function () {
+    socket.emit('attach', {});
+});
+
+$('#detach-button').click(function () {
+    socket.emit('detach', {});
+});
+
+$('#about-button').click(function () {
+    $('#about-dialog').dialog('open');
+});
+
+$('#show-bytecode-button').click(function () {
+    socket.emit('get-bytecode', {});
+});
+
+function submitEval() {
+    socket.emit('eval', { input: $('#eval-input').val() });
+
+    // Eval may take seconds to complete so indicate it is pending.
+    $('#eval-button').addClass('pending');
+}
+
+$('#eval-button').click(function () {
+    submitEval();
+    $('#eval-input').val('');
+});
+
+$('#getvar-button').click(function () {
+    socket.emit('getvar', { varname: $('#varname-input').val() });
+});
+
+$('#putvar-button').click(function () {
+    // The variable value is parsed as JSON right now, but it'd be better to
+    // also be able to parse buffer values etc.
+    var val = JSON.parse($('#varvalue-input').val());
+    socket.emit('putvar', { varname: $('#varname-input').val(), varvalue: val });
+});
+
+$('#source-code').dblclick(function (event) {
+    var target = event.target;
+    var elems = $('#source-code div');
+    var i, n;
+    var line = 0;
+
+    // XXX: any faster way; elems doesn't have e.g. indexOf()
+    for (i = 0, n = elems.length; i < n; i++) {
+        if (target === elems[i]) {
+            line = i + 1;
+        }
+    }
+
+    socket.emit('toggle-breakpoint', {
+        fileName: loadedFileName,
+        lineNumber: line
+    });
+});
+
+function setSourceText(data) {
+    var elem, div;
+
+    elem = $('#source-code');
+    elem.empty();
+    data.split('\n').forEach(function (line) {
+        div = $('<div></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: 1000,
+        height: 800
+    });
+
+    // http://diveintohtml5.info/storage.html
+    if (typeof localStorage !== 'undefined') {
+        if (localStorage.getItem('about-shown')) {
+            showAbout = false;
+        } else {
+            localStorage.setItem('about-shown', 'yes');
+        }
+    }
+    if (showAbout) {
+        $('#about-dialog').dialog('open');
+    }
+
+    // onclick handler for exec status text
+    function loadCurrFunc() {
+        activeFileName = currFileName;
+        activeLine = currLine;
+        requestSourceRefetch();
+    }
+    $('#exec-other').on('click', loadCurrFunc);
+
+    // Enter handling for eval input
+    // https://forum.jquery.com/topic/bind-html-input-to-enter-key-keypress
+    $('#eval-input').keypress(function (event) {
+        if (event.keyCode == 13) {
+            submitEval();
+            $('#eval-input').val('');
+        }
+    });
+
+    // Eval watch handling
+    $('#eval-watch').change(function () {
+        // nop
+    });
+
+    forceButtonUpdate = true;
+    doUiUpdate();
+});

+ 838 - 0
src/third_party/duktape-1.3.0/duk_build_meta.json

@@ -0,0 +1,838 @@
+{
+    "builtin_strings": [
+        "Logger", 
+        "Thread", 
+        "Pointer", 
+        "DecEnv", 
+        "ObjEnv", 
+        "Float64Array", 
+        "Float32Array", 
+        "Uint32Array", 
+        "Int32Array", 
+        "Uint16Array", 
+        "Int16Array", 
+        "Uint8ClampedArray", 
+        "Uint8Array", 
+        "Int8Array", 
+        "DataView", 
+        "ArrayBuffer", 
+        "Buffer", 
+        "", 
+        "global", 
+        "Arguments", 
+        "JSON", 
+        "Math", 
+        "Error", 
+        "RegExp", 
+        "Date", 
+        "Number", 
+        "Boolean", 
+        "String", 
+        "Array", 
+        "Function", 
+        "Object", 
+        "Null", 
+        "Undefined", 
+        "{_func:true}", 
+        "{\"_func\":true}", 
+        "{\"_ninf\":true}", 
+        "{\"_inf\":true}", 
+        "{\"_nan\":true}", 
+        "{\"_undef\":true}", 
+        "toLogString", 
+        "clog", 
+        "l", 
+        "n", 
+        "fatal", 
+        "error", 
+        "warn", 
+        "debug", 
+        "trace", 
+        "raw", 
+        "fmt", 
+        "current", 
+        "resume", 
+        "compact", 
+        "jc", 
+        "jx", 
+        "base64", 
+        "hex", 
+        "dec", 
+        "enc", 
+        "fin", 
+        "gc", 
+        "act", 
+        "info", 
+        "version", 
+        "env", 
+        "modLoaded", 
+        "modSearch", 
+        "errThrow", 
+        "errCreate", 
+        "compile", 
+        "\u0000Regbase", 
+        "\u0000Thread", 
+        "\u0000Handler", 
+        "\u0000Finalizer", 
+        "\u0000Callee", 
+        "\u0000Map", 
+        "\u0000Args", 
+        "\u0000This", 
+        "\u0000Pc2line", 
+        "\u0000Source", 
+        "\u0000Varenv", 
+        "\u0000Lexenv", 
+        "\u0000Varmap", 
+        "\u0000Formals", 
+        "\u0000Bytecode", 
+        "\u0000Next", 
+        "\u0000Target", 
+        "\u0000Value", 
+        "pointer", 
+        "\u0000Tracedata", 
+        "lineNumber", 
+        "fileName", 
+        "pc", 
+        "stack", 
+        "ThrowTypeError", 
+        "Duktape", 
+        "setFloat64", 
+        "setFloat32", 
+        "setUint32", 
+        "setInt32", 
+        "setUint16", 
+        "setInt16", 
+        "setUint8", 
+        "setInt8", 
+        "getFloat64", 
+        "getFloat32", 
+        "getUint32", 
+        "getInt32", 
+        "getUint16", 
+        "getInt16", 
+        "getUint8", 
+        "getInt8", 
+        "subarray", 
+        "BYTES_PER_ELEMENT", 
+        "byteOffset", 
+        "buffer", 
+        "isView", 
+        "data", 
+        "type", 
+        "writeIntBE", 
+        "writeIntLE", 
+        "writeUIntBE", 
+        "writeUIntLE", 
+        "writeDoubleBE", 
+        "writeDoubleLE", 
+        "writeFloatBE", 
+        "writeFloatLE", 
+        "writeInt32BE", 
+        "writeInt32LE", 
+        "writeUInt32BE", 
+        "writeUInt32LE", 
+        "writeInt16BE", 
+        "writeInt16LE", 
+        "writeUInt16BE", 
+        "writeUInt16LE", 
+        "writeInt8", 
+        "writeUInt8", 
+        "readIntBE", 
+        "readIntLE", 
+        "readUIntBE", 
+        "readUIntLE", 
+        "readDoubleBE", 
+        "readDoubleLE", 
+        "readFloatBE", 
+        "readFloatLE", 
+        "readInt32BE", 
+        "readInt32LE", 
+        "readUInt32BE", 
+        "readUInt32LE", 
+        "readInt16BE", 
+        "readInt16LE", 
+        "readUInt16BE", 
+        "readUInt16LE", 
+        "readInt8", 
+        "readUInt8", 
+        "copy", 
+        "equals", 
+        "fill", 
+        "write", 
+        "compare", 
+        "byteLength", 
+        "isBuffer", 
+        "isEncoding", 
+        "exports", 
+        "id", 
+        "require", 
+        "__proto__", 
+        "setPrototypeOf", 
+        "ownKeys", 
+        "enumerate", 
+        "deleteProperty", 
+        "has", 
+        "Proxy", 
+        "callee", 
+        "Invalid Date", 
+        "[...]", 
+        "\n\t", 
+        " ", 
+        ",", 
+        "-0", 
+        "+0", 
+        "0", 
+        "-Infinity", 
+        "+Infinity", 
+        "Infinity", 
+        "object", 
+        "string", 
+        "number", 
+        "boolean", 
+        "undefined", 
+        "stringify", 
+        "tan", 
+        "sqrt", 
+        "sin", 
+        "round", 
+        "random", 
+        "pow", 
+        "min", 
+        "max", 
+        "log", 
+        "floor", 
+        "exp", 
+        "cos", 
+        "ceil", 
+        "atan2", 
+        "atan", 
+        "asin", 
+        "acos", 
+        "abs", 
+        "SQRT2", 
+        "SQRT1_2", 
+        "PI", 
+        "LOG10E", 
+        "LOG2E", 
+        "LN2", 
+        "LN10", 
+        "E", 
+        "message", 
+        "name", 
+        "input", 
+        "index", 
+        "(?:)", 
+        "lastIndex", 
+        "multiline", 
+        "ignoreCase", 
+        "source", 
+        "test", 
+        "exec", 
+        "toGMTString", 
+        "setYear", 
+        "getYear", 
+        "toJSON", 
+        "toISOString", 
+        "toUTCString", 
+        "setUTCFullYear", 
+        "setFullYear", 
+        "setUTCMonth", 
+        "setMonth", 
+        "setUTCDate", 
+        "setDate", 
+        "setUTCHours", 
+        "setHours", 
+        "setUTCMinutes", 
+        "setMinutes", 
+        "setUTCSeconds", 
+        "setSeconds", 
+        "setUTCMilliseconds", 
+        "setMilliseconds", 
+        "setTime", 
+        "getTimezoneOffset", 
+        "getUTCMilliseconds", 
+        "getMilliseconds", 
+        "getUTCSeconds", 
+        "getSeconds", 
+        "getUTCMinutes", 
+        "getMinutes", 
+        "getUTCHours", 
+        "getHours", 
+        "getUTCDay", 
+        "getDay", 
+        "getUTCDate", 
+        "getDate", 
+        "getUTCMonth", 
+        "getMonth", 
+        "getUTCFullYear", 
+        "getFullYear", 
+        "getTime", 
+        "toLocaleTimeString", 
+        "toLocaleDateString", 
+        "toTimeString", 
+        "toDateString", 
+        "now", 
+        "UTC", 
+        "parse", 
+        "toPrecision", 
+        "toExponential", 
+        "toFixed", 
+        "POSITIVE_INFINITY", 
+        "NEGATIVE_INFINITY", 
+        "NaN", 
+        "MIN_VALUE", 
+        "MAX_VALUE", 
+        "substr", 
+        "trim", 
+        "toLocaleUpperCase", 
+        "toUpperCase", 
+        "toLocaleLowerCase", 
+        "toLowerCase", 
+        "substring", 
+        "split", 
+        "search", 
+        "replace", 
+        "match", 
+        "localeCompare", 
+        "charCodeAt", 
+        "charAt", 
+        "fromCharCode", 
+        "reduceRight", 
+        "reduce", 
+        "filter", 
+        "map", 
+        "forEach", 
+        "some", 
+        "every", 
+        "lastIndexOf", 
+        "indexOf", 
+        "unshift", 
+        "splice", 
+        "sort", 
+        "slice", 
+        "shift", 
+        "reverse", 
+        "push", 
+        "pop", 
+        "join", 
+        "concat", 
+        "isArray", 
+        "arguments", 
+        "caller", 
+        "bind", 
+        "call", 
+        "apply", 
+        "propertyIsEnumerable", 
+        "isPrototypeOf", 
+        "hasOwnProperty", 
+        "valueOf", 
+        "toLocaleString", 
+        "toString", 
+        "constructor", 
+        "set", 
+        "get", 
+        "enumerable", 
+        "configurable", 
+        "writable", 
+        "value", 
+        "keys", 
+        "isExtensible", 
+        "isFrozen", 
+        "isSealed", 
+        "preventExtensions", 
+        "freeze", 
+        "seal", 
+        "defineProperties", 
+        "defineProperty", 
+        "create", 
+        "getOwnPropertyNames", 
+        "getOwnPropertyDescriptor", 
+        "getPrototypeOf", 
+        "prototype", 
+        "length", 
+        "alert", 
+        "print", 
+        "unescape", 
+        "escape", 
+        "encodeURIComponent", 
+        "encodeURI", 
+        "decodeURIComponent", 
+        "decodeURI", 
+        "isFinite", 
+        "isNaN", 
+        "parseFloat", 
+        "parseInt", 
+        "eval", 
+        "URIError", 
+        "TypeError", 
+        "SyntaxError", 
+        "ReferenceError", 
+        "RangeError", 
+        "EvalError", 
+        "break", 
+        "case", 
+        "catch", 
+        "continue", 
+        "debugger", 
+        "default", 
+        "delete", 
+        "do", 
+        "else", 
+        "finally", 
+        "for", 
+        "function", 
+        "if", 
+        "in", 
+        "instanceof", 
+        "new", 
+        "return", 
+        "switch", 
+        "this", 
+        "throw", 
+        "try", 
+        "typeof", 
+        "var", 
+        "void", 
+        "while", 
+        "with", 
+        "class", 
+        "const", 
+        "enum", 
+        "export", 
+        "extends", 
+        "import", 
+        "super", 
+        "null", 
+        "true", 
+        "false", 
+        "implements", 
+        "interface", 
+        "let", 
+        "package", 
+        "private", 
+        "protected", 
+        "public", 
+        "static", 
+        "yield"
+    ], 
+    "builtin_strings_base64": [
+        "TG9nZ2Vy", 
+        "VGhyZWFk", 
+        "UG9pbnRlcg==", 
+        "RGVjRW52", 
+        "T2JqRW52", 
+        "RmxvYXQ2NEFycmF5", 
+        "RmxvYXQzMkFycmF5", 
+        "VWludDMyQXJyYXk=", 
+        "SW50MzJBcnJheQ==", 
+        "VWludDE2QXJyYXk=", 
+        "SW50MTZBcnJheQ==", 
+        "VWludDhDbGFtcGVkQXJyYXk=", 
+        "VWludDhBcnJheQ==", 
+        "SW50OEFycmF5", 
+        "RGF0YVZpZXc=", 
+        "QXJyYXlCdWZmZXI=", 
+        "QnVmZmVy", 
+        "", 
+        "Z2xvYmFs", 
+        "QXJndW1lbnRz", 
+        "SlNPTg==", 
+        "TWF0aA==", 
+        "RXJyb3I=", 
+        "UmVnRXhw", 
+        "RGF0ZQ==", 
+        "TnVtYmVy", 
+        "Qm9vbGVhbg==", 
+        "U3RyaW5n", 
+        "QXJyYXk=", 
+        "RnVuY3Rpb24=", 
+        "T2JqZWN0", 
+        "TnVsbA==", 
+        "VW5kZWZpbmVk", 
+        "e19mdW5jOnRydWV9", 
+        "eyJfZnVuYyI6dHJ1ZX0=", 
+        "eyJfbmluZiI6dHJ1ZX0=", 
+        "eyJfaW5mIjp0cnVlfQ==", 
+        "eyJfbmFuIjp0cnVlfQ==", 
+        "eyJfdW5kZWYiOnRydWV9", 
+        "dG9Mb2dTdHJpbmc=", 
+        "Y2xvZw==", 
+        "bA==", 
+        "bg==", 
+        "ZmF0YWw=", 
+        "ZXJyb3I=", 
+        "d2Fybg==", 
+        "ZGVidWc=", 
+        "dHJhY2U=", 
+        "cmF3", 
+        "Zm10", 
+        "Y3VycmVudA==", 
+        "cmVzdW1l", 
+        "Y29tcGFjdA==", 
+        "amM=", 
+        "ang=", 
+        "YmFzZTY0", 
+        "aGV4", 
+        "ZGVj", 
+        "ZW5j", 
+        "Zmlu", 
+        "Z2M=", 
+        "YWN0", 
+        "aW5mbw==", 
+        "dmVyc2lvbg==", 
+        "ZW52", 
+        "bW9kTG9hZGVk", 
+        "bW9kU2VhcmNo", 
+        "ZXJyVGhyb3c=", 
+        "ZXJyQ3JlYXRl", 
+        "Y29tcGlsZQ==", 
+        "/1JlZ2Jhc2U=", 
+        "/1RocmVhZA==", 
+        "/0hhbmRsZXI=", 
+        "/0ZpbmFsaXplcg==", 
+        "/0NhbGxlZQ==", 
+        "/01hcA==", 
+        "/0FyZ3M=", 
+        "/1RoaXM=", 
+        "/1BjMmxpbmU=", 
+        "/1NvdXJjZQ==", 
+        "/1ZhcmVudg==", 
+        "/0xleGVudg==", 
+        "/1Zhcm1hcA==", 
+        "/0Zvcm1hbHM=", 
+        "/0J5dGVjb2Rl", 
+        "/05leHQ=", 
+        "/1RhcmdldA==", 
+        "/1ZhbHVl", 
+        "cG9pbnRlcg==", 
+        "/1RyYWNlZGF0YQ==", 
+        "bGluZU51bWJlcg==", 
+        "ZmlsZU5hbWU=", 
+        "cGM=", 
+        "c3RhY2s=", 
+        "VGhyb3dUeXBlRXJyb3I=", 
+        "RHVrdGFwZQ==", 
+        "c2V0RmxvYXQ2NA==", 
+        "c2V0RmxvYXQzMg==", 
+        "c2V0VWludDMy", 
+        "c2V0SW50MzI=", 
+        "c2V0VWludDE2", 
+        "c2V0SW50MTY=", 
+        "c2V0VWludDg=", 
+        "c2V0SW50OA==", 
+        "Z2V0RmxvYXQ2NA==", 
+        "Z2V0RmxvYXQzMg==", 
+        "Z2V0VWludDMy", 
+        "Z2V0SW50MzI=", 
+        "Z2V0VWludDE2", 
+        "Z2V0SW50MTY=", 
+        "Z2V0VWludDg=", 
+        "Z2V0SW50OA==", 
+        "c3ViYXJyYXk=", 
+        "QllURVNfUEVSX0VMRU1FTlQ=", 
+        "Ynl0ZU9mZnNldA==", 
+        "YnVmZmVy", 
+        "aXNWaWV3", 
+        "ZGF0YQ==", 
+        "dHlwZQ==", 
+        "d3JpdGVJbnRCRQ==", 
+        "d3JpdGVJbnRMRQ==", 
+        "d3JpdGVVSW50QkU=", 
+        "d3JpdGVVSW50TEU=", 
+        "d3JpdGVEb3VibGVCRQ==", 
+        "d3JpdGVEb3VibGVMRQ==", 
+        "d3JpdGVGbG9hdEJF", 
+        "d3JpdGVGbG9hdExF", 
+        "d3JpdGVJbnQzMkJF", 
+        "d3JpdGVJbnQzMkxF", 
+        "d3JpdGVVSW50MzJCRQ==", 
+        "d3JpdGVVSW50MzJMRQ==", 
+        "d3JpdGVJbnQxNkJF", 
+        "d3JpdGVJbnQxNkxF", 
+        "d3JpdGVVSW50MTZCRQ==", 
+        "d3JpdGVVSW50MTZMRQ==", 
+        "d3JpdGVJbnQ4", 
+        "d3JpdGVVSW50OA==", 
+        "cmVhZEludEJF", 
+        "cmVhZEludExF", 
+        "cmVhZFVJbnRCRQ==", 
+        "cmVhZFVJbnRMRQ==", 
+        "cmVhZERvdWJsZUJF", 
+        "cmVhZERvdWJsZUxF", 
+        "cmVhZEZsb2F0QkU=", 
+        "cmVhZEZsb2F0TEU=", 
+        "cmVhZEludDMyQkU=", 
+        "cmVhZEludDMyTEU=", 
+        "cmVhZFVJbnQzMkJF", 
+        "cmVhZFVJbnQzMkxF", 
+        "cmVhZEludDE2QkU=", 
+        "cmVhZEludDE2TEU=", 
+        "cmVhZFVJbnQxNkJF", 
+        "cmVhZFVJbnQxNkxF", 
+        "cmVhZEludDg=", 
+        "cmVhZFVJbnQ4", 
+        "Y29weQ==", 
+        "ZXF1YWxz", 
+        "ZmlsbA==", 
+        "d3JpdGU=", 
+        "Y29tcGFyZQ==", 
+        "Ynl0ZUxlbmd0aA==", 
+        "aXNCdWZmZXI=", 
+        "aXNFbmNvZGluZw==", 
+        "ZXhwb3J0cw==", 
+        "aWQ=", 
+        "cmVxdWlyZQ==", 
+        "X19wcm90b19f", 
+        "c2V0UHJvdG90eXBlT2Y=", 
+        "b3duS2V5cw==", 
+        "ZW51bWVyYXRl", 
+        "ZGVsZXRlUHJvcGVydHk=", 
+        "aGFz", 
+        "UHJveHk=", 
+        "Y2FsbGVl", 
+        "SW52YWxpZCBEYXRl", 
+        "Wy4uLl0=", 
+        "Cgk=", 
+        "IA==", 
+        "LA==", 
+        "LTA=", 
+        "KzA=", 
+        "MA==", 
+        "LUluZmluaXR5", 
+        "K0luZmluaXR5", 
+        "SW5maW5pdHk=", 
+        "b2JqZWN0", 
+        "c3RyaW5n", 
+        "bnVtYmVy", 
+        "Ym9vbGVhbg==", 
+        "dW5kZWZpbmVk", 
+        "c3RyaW5naWZ5", 
+        "dGFu", 
+        "c3FydA==", 
+        "c2lu", 
+        "cm91bmQ=", 
+        "cmFuZG9t", 
+        "cG93", 
+        "bWlu", 
+        "bWF4", 
+        "bG9n", 
+        "Zmxvb3I=", 
+        "ZXhw", 
+        "Y29z", 
+        "Y2VpbA==", 
+        "YXRhbjI=", 
+        "YXRhbg==", 
+        "YXNpbg==", 
+        "YWNvcw==", 
+        "YWJz", 
+        "U1FSVDI=", 
+        "U1FSVDFfMg==", 
+        "UEk=", 
+        "TE9HMTBF", 
+        "TE9HMkU=", 
+        "TE4y", 
+        "TE4xMA==", 
+        "RQ==", 
+        "bWVzc2FnZQ==", 
+        "bmFtZQ==", 
+        "aW5wdXQ=", 
+        "aW5kZXg=", 
+        "KD86KQ==", 
+        "bGFzdEluZGV4", 
+        "bXVsdGlsaW5l", 
+        "aWdub3JlQ2FzZQ==", 
+        "c291cmNl", 
+        "dGVzdA==", 
+        "ZXhlYw==", 
+        "dG9HTVRTdHJpbmc=", 
+        "c2V0WWVhcg==", 
+        "Z2V0WWVhcg==", 
+        "dG9KU09O", 
+        "dG9JU09TdHJpbmc=", 
+        "dG9VVENTdHJpbmc=", 
+        "c2V0VVRDRnVsbFllYXI=", 
+        "c2V0RnVsbFllYXI=", 
+        "c2V0VVRDTW9udGg=", 
+        "c2V0TW9udGg=", 
+        "c2V0VVRDRGF0ZQ==", 
+        "c2V0RGF0ZQ==", 
+        "c2V0VVRDSG91cnM=", 
+        "c2V0SG91cnM=", 
+        "c2V0VVRDTWludXRlcw==", 
+        "c2V0TWludXRlcw==", 
+        "c2V0VVRDU2Vjb25kcw==", 
+        "c2V0U2Vjb25kcw==", 
+        "c2V0VVRDTWlsbGlzZWNvbmRz", 
+        "c2V0TWlsbGlzZWNvbmRz", 
+        "c2V0VGltZQ==", 
+        "Z2V0VGltZXpvbmVPZmZzZXQ=", 
+        "Z2V0VVRDTWlsbGlzZWNvbmRz", 
+        "Z2V0TWlsbGlzZWNvbmRz", 
+        "Z2V0VVRDU2Vjb25kcw==", 
+        "Z2V0U2Vjb25kcw==", 
+        "Z2V0VVRDTWludXRlcw==", 
+        "Z2V0TWludXRlcw==", 
+        "Z2V0VVRDSG91cnM=", 
+        "Z2V0SG91cnM=", 
+        "Z2V0VVRDRGF5", 
+        "Z2V0RGF5", 
+        "Z2V0VVRDRGF0ZQ==", 
+        "Z2V0RGF0ZQ==", 
+        "Z2V0VVRDTW9udGg=", 
+        "Z2V0TW9udGg=", 
+        "Z2V0VVRDRnVsbFllYXI=", 
+        "Z2V0RnVsbFllYXI=", 
+        "Z2V0VGltZQ==", 
+        "dG9Mb2NhbGVUaW1lU3RyaW5n", 
+        "dG9Mb2NhbGVEYXRlU3RyaW5n", 
+        "dG9UaW1lU3RyaW5n", 
+        "dG9EYXRlU3RyaW5n", 
+        "bm93", 
+        "VVRD", 
+        "cGFyc2U=", 
+        "dG9QcmVjaXNpb24=", 
+        "dG9FeHBvbmVudGlhbA==", 
+        "dG9GaXhlZA==", 
+        "UE9TSVRJVkVfSU5GSU5JVFk=", 
+        "TkVHQVRJVkVfSU5GSU5JVFk=", 
+        "TmFO", 
+        "TUlOX1ZBTFVF", 
+        "TUFYX1ZBTFVF", 
+        "c3Vic3Ry", 
+        "dHJpbQ==", 
+        "dG9Mb2NhbGVVcHBlckNhc2U=", 
+        "dG9VcHBlckNhc2U=", 
+        "dG9Mb2NhbGVMb3dlckNhc2U=", 
+        "dG9Mb3dlckNhc2U=", 
+        "c3Vic3RyaW5n", 
+        "c3BsaXQ=", 
+        "c2VhcmNo", 
+        "cmVwbGFjZQ==", 
+        "bWF0Y2g=", 
+        "bG9jYWxlQ29tcGFyZQ==", 
+        "Y2hhckNvZGVBdA==", 
+        "Y2hhckF0", 
+        "ZnJvbUNoYXJDb2Rl", 
+        "cmVkdWNlUmlnaHQ=", 
+        "cmVkdWNl", 
+        "ZmlsdGVy", 
+        "bWFw", 
+        "Zm9yRWFjaA==", 
+        "c29tZQ==", 
+        "ZXZlcnk=", 
+        "bGFzdEluZGV4T2Y=", 
+        "aW5kZXhPZg==", 
+        "dW5zaGlmdA==", 
+        "c3BsaWNl", 
+        "c29ydA==", 
+        "c2xpY2U=", 
+        "c2hpZnQ=", 
+        "cmV2ZXJzZQ==", 
+        "cHVzaA==", 
+        "cG9w", 
+        "am9pbg==", 
+        "Y29uY2F0", 
+        "aXNBcnJheQ==", 
+        "YXJndW1lbnRz", 
+        "Y2FsbGVy", 
+        "YmluZA==", 
+        "Y2FsbA==", 
+        "YXBwbHk=", 
+        "cHJvcGVydHlJc0VudW1lcmFibGU=", 
+        "aXNQcm90b3R5cGVPZg==", 
+        "aGFzT3duUHJvcGVydHk=", 
+        "dmFsdWVPZg==", 
+        "dG9Mb2NhbGVTdHJpbmc=", 
+        "dG9TdHJpbmc=", 
+        "Y29uc3RydWN0b3I=", 
+        "c2V0", 
+        "Z2V0", 
+        "ZW51bWVyYWJsZQ==", 
+        "Y29uZmlndXJhYmxl", 
+        "d3JpdGFibGU=", 
+        "dmFsdWU=", 
+        "a2V5cw==", 
+        "aXNFeHRlbnNpYmxl", 
+        "aXNGcm96ZW4=", 
+        "aXNTZWFsZWQ=", 
+        "cHJldmVudEV4dGVuc2lvbnM=", 
+        "ZnJlZXpl", 
+        "c2VhbA==", 
+        "ZGVmaW5lUHJvcGVydGllcw==", 
+        "ZGVmaW5lUHJvcGVydHk=", 
+        "Y3JlYXRl", 
+        "Z2V0T3duUHJvcGVydHlOYW1lcw==", 
+        "Z2V0T3duUHJvcGVydHlEZXNjcmlwdG9y", 
+        "Z2V0UHJvdG90eXBlT2Y=", 
+        "cHJvdG90eXBl", 
+        "bGVuZ3Ro", 
+        "YWxlcnQ=", 
+        "cHJpbnQ=", 
+        "dW5lc2NhcGU=", 
+        "ZXNjYXBl", 
+        "ZW5jb2RlVVJJQ29tcG9uZW50", 
+        "ZW5jb2RlVVJJ", 
+        "ZGVjb2RlVVJJQ29tcG9uZW50", 
+        "ZGVjb2RlVVJJ", 
+        "aXNGaW5pdGU=", 
+        "aXNOYU4=", 
+        "cGFyc2VGbG9hdA==", 
+        "cGFyc2VJbnQ=", 
+        "ZXZhbA==", 
+        "VVJJRXJyb3I=", 
+        "VHlwZUVycm9y", 
+        "U3ludGF4RXJyb3I=", 
+        "UmVmZXJlbmNlRXJyb3I=", 
+        "UmFuZ2VFcnJvcg==", 
+        "RXZhbEVycm9y", 
+        "YnJlYWs=", 
+        "Y2FzZQ==", 
+        "Y2F0Y2g=", 
+        "Y29udGludWU=", 
+        "ZGVidWdnZXI=", 
+        "ZGVmYXVsdA==", 
+        "ZGVsZXRl", 
+        "ZG8=", 
+        "ZWxzZQ==", 
+        "ZmluYWxseQ==", 
+        "Zm9y", 
+        "ZnVuY3Rpb24=", 
+        "aWY=", 
+        "aW4=", 
+        "aW5zdGFuY2VvZg==", 
+        "bmV3", 
+        "cmV0dXJu", 
+        "c3dpdGNo", 
+        "dGhpcw==", 
+        "dGhyb3c=", 
+        "dHJ5", 
+        "dHlwZW9m", 
+        "dmFy", 
+        "dm9pZA==", 
+        "d2hpbGU=", 
+        "d2l0aA==", 
+        "Y2xhc3M=", 
+        "Y29uc3Q=", 
+        "ZW51bQ==", 
+        "ZXhwb3J0", 
+        "ZXh0ZW5kcw==", 
+        "aW1wb3J0", 
+        "c3VwZXI=", 
+        "bnVsbA==", 
+        "dHJ1ZQ==", 
+        "ZmFsc2U=", 
+        "aW1wbGVtZW50cw==", 
+        "aW50ZXJmYWNl", 
+        "bGV0", 
+        "cGFja2FnZQ==", 
+        "cHJpdmF0ZQ==", 
+        "cHJvdGVjdGVk", 
+        "cHVibGlj", 
+        "c3RhdGlj", 
+        "eWllbGQ="
+    ], 
+    "comment": "Metadata for Duktape build", 
+    "duk_version": 10300, 
+    "duk_version_string": "1.3.0", 
+    "git_describe": "v1.3.0"
+}

+ 10 - 0
src/third_party/duktape-1.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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) {
+			free((void *) hdr);
+			write_log("R %p %ld NULL 0\n", ptr, (long) old_size);
+			return NULL;
+		} else {
+			t = realloc((void *) hdr, size + sizeof(alloc_hdr));
+			if (!t) {
+				write_log("R %p %ld FAIL %ld\n", ptr, (long) old_size, (long) size);
+				return NULL;
+			}
+			hdr = (alloc_hdr *) t;
+			hdr->u.sz = size;
+			ret = (void *) (hdr + 1);
+			write_log("R %p %ld %p %ld\n", ptr, (long) old_size, ret, (long) size);
+			return ret;
+		}
+	} else {
+		if (size == 0) {
+			write_log("R NULL 0 NULL 0\n");
+			return NULL;
+		} else {
+			hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr));
+			if (!hdr) {
+				write_log("R NULL 0 FAIL %ld\n", (long) size);
+				return NULL;
+			}
+			hdr->u.sz = size;
+			ret = (void *) (hdr + 1);
+			write_log("R NULL 0 %p %ld\n", ret, (long) size);
+			return ret;
+		}
+	}
+}
+
+void duk_free_logging(void *udata, void *ptr) {
+	alloc_hdr *hdr;
+
+	(void) udata;  /* Suppress warning. */
+
+	if (!ptr) {
+		write_log("F NULL 0\n");
+		return;
+	}
+	hdr = (alloc_hdr *) (void *) ((unsigned char *) ptr - sizeof(alloc_hdr));
+	write_log("F %p %ld\n", ptr, (long) hdr->u.sz);
+	free((void *) hdr);
+}

+ 10 - 0
src/third_party/duktape-1.3.0/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.3.0/examples/alloc-logging/log2gnuplot.py

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

+ 873 - 0
src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline.c

@@ -0,0 +1,873 @@
+/*
+ *  Command line execution tool.  Useful for test cases and manual testing.
+ *
+ *  To enable readline and other fancy stuff, compile with -DDUK_CMDLINE_FANCY.
+ *  It is not the default to maximize portability.  You can also compile in
+ *  support for example allocators, grep for DUK_CMDLINE_*.
+ */
+
+#ifndef DUK_CMDLINE_FANCY
+#define NO_READLINE
+#define NO_RLIMIT
+#define NO_SIGNAL
+#endif
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \
+    defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
+/* Suppress warnings about plain fopen() etc. */
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#define  GREET_CODE(variant)  \
+	"print('((o) Duktape" variant " ' + " \
+	"Math.floor(Duktape.version / 10000) + '.' + " \
+	"Math.floor(Duktape.version / 100) % 100 + '.' + " \
+	"Duktape.version % 100" \
+	", '(" DUK_GIT_DESCRIBE ")');"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef NO_SIGNAL
+#include <signal.h>
+#endif
+#ifndef NO_RLIMIT
+#include <sys/resource.h>
+#endif
+#ifndef NO_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+#ifdef DUK_CMDLINE_ALLOC_LOGGING
+#include "duk_alloc_logging.h"
+#endif
+#ifdef DUK_CMDLINE_ALLOC_TORTURE
+#include "duk_alloc_torture.h"
+#endif
+#ifdef DUK_CMDLINE_ALLOC_HYBRID
+#include "duk_alloc_hybrid.h"
+#endif
+#include "duktape.h"
+
+#ifdef DUK_CMDLINE_AJSHEAP
+/* Defined in duk_cmdline_ajduk.c or alljoyn.js headers. */
+void ajsheap_init(void);
+void ajsheap_dump(void);
+void ajsheap_register(duk_context *ctx);
+void ajsheap_start_exec_timeout(void);
+void ajsheap_clear_exec_timeout(void);
+void *ajsheap_alloc_wrapped(void *udata, duk_size_t size);
+void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size);
+void ajsheap_free_wrapped(void *udata, void *ptr);
+void *AJS_Alloc(void *udata, duk_size_t size);
+void *AJS_Realloc(void *udata, void *ptr, duk_size_t size);
+void AJS_Free(void *udata, void *ptr);
+#endif
+
+#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT
+#include "duk_trans_socket.h"
+#endif
+
+#define  MEM_LIMIT_NORMAL   (128*1024*1024)   /* 128 MB */
+#define  MEM_LIMIT_HIGH     (2047*1024*1024)  /* ~2 GB */
+#define  LINEBUF_SIZE       65536
+
+static int interactive_mode = 0;
+
+#ifndef NO_RLIMIT
+static void set_resource_limits(rlim_t mem_limit_value) {
+	int rc;
+	struct rlimit lim;
+
+	rc = getrlimit(RLIMIT_AS, &lim);
+	if (rc != 0) {
+		fprintf(stderr, "Warning: cannot read RLIMIT_AS\n");
+		return;
+	}
+
+	if (lim.rlim_max < mem_limit_value) {
+		fprintf(stderr, "Warning: rlim_max < mem_limit_value (%d < %d)\n", (int) lim.rlim_max, (int) mem_limit_value);
+		return;
+	}
+
+	lim.rlim_cur = mem_limit_value;
+	lim.rlim_max = mem_limit_value;
+
+	rc = setrlimit(RLIMIT_AS, &lim);
+	if (rc != 0) {
+		fprintf(stderr, "Warning: setrlimit failed\n");
+		return;
+	}
+
+#if 0
+	fprintf(stderr, "Set RLIMIT_AS to %d\n", (int) mem_limit_value);
+#endif
+}
+#endif  /* NO_RLIMIT */
+
+#ifndef NO_SIGNAL
+static void my_sighandler(int x) {
+	fprintf(stderr, "Got signal %d\n", x);
+	fflush(stderr);
+}
+static void set_sigint_handler(void) {
+	(void) signal(SIGINT, my_sighandler);
+}
+#endif  /* NO_SIGNAL */
+
+static int get_stack_raw(duk_context *ctx) {
+	if (!duk_is_object(ctx, -1)) {
+		return 1;
+	}
+	if (!duk_has_prop_string(ctx, -1, "stack")) {
+		return 1;
+	}
+	if (!duk_is_error(ctx, -1)) {
+		/* Not an Error instance, don't read "stack". */
+		return 1;
+	}
+
+	duk_get_prop_string(ctx, -1, "stack");  /* caller coerces */
+	duk_remove(ctx, -2);
+	return 1;
+}
+
+/* Print error to stderr and pop error. */
+static void print_pop_error(duk_context *ctx, FILE *f) {
+	/* Print error objects with a stack trace specially.
+	 * Note that getting the stack trace may throw an error
+	 * so this also needs to be safe call wrapped.
+	 */
+	(void) duk_safe_call(ctx, get_stack_raw, 1 /*nargs*/, 1 /*nrets*/);
+	fprintf(f, "%s\n", duk_safe_to_string(ctx, -1));
+	fflush(f);
+	duk_pop(ctx);
+}
+
+static int wrapped_compile_execute(duk_context *ctx) {
+	const char *src_data;
+	duk_size_t src_len;
+	int comp_flags;
+
+	/* XXX: Here it'd be nice to get some stats for the compilation result
+	 * when a suitable command line is given (e.g. code size, constant
+	 * count, function count.  These are available internally but not through
+	 * the public API.
+	 */
+
+	/* Use duk_compile_lstring_filename() variant which avoids interning
+	 * the source code.  This only really matters for low memory environments.
+	 */
+
+	/* [ ... bytecode_filename src_data src_len filename ] */
+
+	src_data = (const char *) duk_require_pointer(ctx, -3);
+	src_len = (duk_size_t) duk_require_uint(ctx, -2);
+
+	if (src_data != NULL && src_len >= 2 && src_data[0] == (char) 0xff) {
+		/* Bytecode. */
+		duk_push_lstring(ctx, src_data, src_len);
+		duk_to_buffer(ctx, -1, NULL);
+		duk_load_function(ctx);
+	} else {
+		/* Source code. */
+		comp_flags = 0;
+		duk_compile_lstring_filename(ctx, comp_flags, src_data, src_len);
+	}
+
+	/* [ ... bytecode_filename src_data src_len function ] */
+
+	/* Optional bytecode dump. */
+	if (duk_is_string(ctx, -4)) {
+		FILE *f;
+		void *bc_ptr;
+		duk_size_t bc_len;
+		size_t wrote;
+
+		duk_dup_top(ctx);
+		duk_dump_function(ctx);
+		bc_ptr = duk_require_buffer(ctx, -1, &bc_len);
+		f = fopen(duk_require_string(ctx, -5), "wb");
+		if (!f) {
+			duk_error(ctx, DUK_ERR_ERROR, "failed to open bytecode output file");
+		}
+		wrote = fwrite(bc_ptr, 1, (size_t) bc_len, f);  /* XXX: handle partial writes */
+		(void) fclose(f);
+		if (wrote != bc_len) {
+			duk_error(ctx, DUK_ERR_ERROR, "failed to write all bytecode");
+		}
+
+		return 0;  /* duk_safe_call() cleans up */
+	}
+
+#if 0
+	/* Manual test for bytecode dump/load cycle: dump and load before
+	 * execution.  Enable manually, then run "make qecmatest" for a
+	 * reasonably good coverage of different functions and programs.
+	 */
+	duk_dump_function(ctx);
+	duk_load_function(ctx);
+#endif
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	ajsheap_start_exec_timeout();
+#endif
+
+	duk_push_global_object(ctx);  /* 'this' binding */
+	duk_call_method(ctx, 0);
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	ajsheap_clear_exec_timeout();
+#endif
+
+	if (interactive_mode) {
+		/*
+		 *  In interactive mode, write to stdout so output won't
+		 *  interleave as easily.
+		 *
+		 *  NOTE: the ToString() coercion may fail in some cases;
+		 *  for instance, if you evaluate:
+		 *
+		 *    ( {valueOf: function() {return {}},
+		 *       toString: function() {return {}}});
+		 *
+		 *  The error is:
+		 *
+		 *    TypeError: failed to coerce with [[DefaultValue]]
+		 *            duk_api.c:1420
+		 *
+		 *  These are handled now by the caller which also has stack
+		 *  trace printing support.  User code can print out errors
+		 *  safely using duk_safe_to_string().
+		 */
+
+		fprintf(stdout, "= %s\n", duk_to_string(ctx, -1));
+		fflush(stdout);
+	} else {
+		/* In non-interactive mode, success results are not written at all.
+		 * It is important that the result value is not string coerced,
+		 * as the string coercion may cause an error in some cases.
+		 */
+	}
+
+	return 0;  /* duk_safe_call() cleans up */
+}
+
+static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char *bytecode_filename) {
+	char *buf = NULL;
+	int len;
+	size_t got;
+	int rc;
+	int retval = -1;
+
+	if (fseek(f, 0, SEEK_END) < 0) {
+		goto error;
+	}
+	len = (int) ftell(f);
+	if (fseek(f, 0, SEEK_SET) < 0) {
+		goto error;
+	}
+	buf = (char *) malloc(len);
+	if (!buf) {
+		goto error;
+	}
+
+	got = fread((void *) buf, (size_t) 1, (size_t) len, f);
+
+	duk_push_string(ctx, bytecode_filename);
+	duk_push_pointer(ctx, (void *) buf);
+	duk_push_uint(ctx, (duk_uint_t) got);
+	duk_push_string(ctx, filename);
+
+	interactive_mode = 0;  /* global */
+
+	rc = duk_safe_call(ctx, wrapped_compile_execute, 4 /*nargs*/, 1 /*nret*/);
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	ajsheap_clear_exec_timeout();
+#endif
+
+	free(buf);
+	buf = NULL;
+
+	if (rc != DUK_EXEC_SUCCESS) {
+		print_pop_error(ctx, stderr);
+		goto error;
+	} else {
+		duk_pop(ctx);
+		retval = 0;
+	}
+	/* fall thru */
+
+ cleanup:
+	if (buf) {
+		free(buf);
+	}
+	return retval;
+
+ error:
+	fprintf(stderr, "error in executing file %s\n", filename);
+	fflush(stderr);
+	goto cleanup;
+}
+
+static int handle_file(duk_context *ctx, const char *filename, const char *bytecode_filename) {
+	FILE *f = NULL;
+	int retval;
+
+	f = fopen(filename, "rb");
+	if (!f) {
+		fprintf(stderr, "failed to open source file: %s\n", filename);
+		fflush(stderr);
+		goto error;
+	}
+
+	retval = handle_fh(ctx, f, filename, bytecode_filename);
+
+	fclose(f);
+	return retval;
+
+ error:
+	return -1;
+}
+
+static int handle_eval(duk_context *ctx, const char *code) {
+	int rc;
+	int retval = -1;
+
+	duk_push_pointer(ctx, (void *) code);
+	duk_push_uint(ctx, (duk_uint_t) strlen(code));
+	duk_push_string(ctx, "eval");
+
+	interactive_mode = 0;  /* global */
+
+	rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/);
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+	ajsheap_clear_exec_timeout();
+#endif
+
+	if (rc != DUK_EXEC_SUCCESS) {
+		print_pop_error(ctx, stderr);
+	} else {
+		duk_pop(ctx);
+		retval = 0;
+	}
+
+	return retval;
+}
+
+#ifdef NO_READLINE
+static int handle_interactive(duk_context *ctx) {
+	const char *prompt = "duk> ";
+	char *buffer = NULL;
+	int retval = 0;
+	int rc;
+	int got_eof = 0;
+
+	duk_eval_string(ctx, GREET_CODE(" [no readline]"));
+	duk_pop(ctx);
+
+	buffer = (char *) malloc(LINEBUF_SIZE);
+	if (!buffer) {
+		fprintf(stderr, "failed to allocated a line buffer\n");
+		fflush(stderr);
+		retval = -1;
+		goto done;
+	}
+
+	while (!got_eof) {
+		size_t idx = 0;
+
+		fwrite(prompt, 1, strlen(prompt), stdout);
+		fflush(stdout);
+
+		for (;;) {
+			int c = fgetc(stdin);
+			if (c == EOF) {
+				got_eof = 1;
+				break;
+			} else if (c == '\n') {
+				break;
+			} else if (idx >= LINEBUF_SIZE) {
+				fprintf(stderr, "line too long\n");
+				fflush(stderr);
+				retval = -1;
+				goto done;
+			} else {
+				buffer[idx++] = (char) c;
+			}
+		}
+
+		duk_push_pointer(ctx, (void *) buffer);
+		duk_push_uint(ctx, (duk_uint_t) idx);
+		duk_push_string(ctx, "input");
+
+		interactive_mode = 1;  /* global */
+
+		rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/);
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+		ajsheap_clear_exec_timeout();
+#endif
+
+		if (rc != DUK_EXEC_SUCCESS) {
+			/* in interactive mode, write to stdout */
+			print_pop_error(ctx, stdout);
+			retval = -1;  /* an error 'taints' the execution */
+		} else {
+			duk_pop(ctx);
+		}
+	}
+
+ done:
+	if (buffer) {
+		free(buffer);
+		buffer = NULL;
+	}
+
+	return retval;
+}
+#else  /* NO_READLINE */
+static int handle_interactive(duk_context *ctx) {
+	const char *prompt = "duk> ";
+	char *buffer = NULL;
+	int retval = 0;
+	int rc;
+
+	duk_eval_string(ctx, GREET_CODE(""));
+	duk_pop(ctx);
+
+	/*
+	 *  Note: using readline leads to valgrind-reported leaks inside
+	 *  readline itself.  Execute code from an input file (and not
+	 *  through stdin) for clean valgrind runs.
+	 */
+
+	rl_initialize();
+
+	for (;;) {
+		if (buffer) {
+			free(buffer);
+			buffer = NULL;
+		}
+
+		buffer = readline(prompt);
+		if (!buffer) {
+			break;
+		}
+
+		if (buffer && buffer[0] != (char) 0) {
+			add_history(buffer);
+		}
+
+		duk_push_pointer(ctx, (void *) buffer);
+		duk_push_uint(ctx, (duk_uint_t) strlen(buffer));
+		duk_push_string(ctx, "input");
+
+		interactive_mode = 1;  /* global */
+
+		rc = duk_safe_call(ctx, wrapped_compile_execute, 3 /*nargs*/, 1 /*nret*/);
+
+#if defined(DUK_CMDLINE_AJSHEAP)
+		ajsheap_clear_exec_timeout();
+#endif
+
+		if (buffer) {
+			free(buffer);
+			buffer = NULL;
+		}
+
+		if (rc != DUK_EXEC_SUCCESS) {
+			/* in interactive mode, write to stdout */
+			print_pop_error(ctx, stdout);
+			retval = -1;  /* an error 'taints' the execution */
+		} else {
+			duk_pop(ctx);
+		}
+	}
+
+	if (buffer) {
+		free(buffer);
+		buffer = NULL;
+	}
+
+	return retval;
+}
+#endif  /* NO_READLINE */
+
+#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT
+static void debugger_detached(void *udata) {
+	fprintf(stderr, "Debugger detached, udata: %p\n", (void *) udata);
+	fflush(stderr);
+}
+#endif
+
+#define  ALLOC_DEFAULT  0
+#define  ALLOC_LOGGING  1
+#define  ALLOC_TORTURE  2
+#define  ALLOC_HYBRID   3
+#define  ALLOC_AJSHEAP  4
+
+static duk_context *create_duktape_heap(int alloc_provider, int debugger) {
+	duk_context *ctx;
+
+	ctx = NULL;
+	if (!ctx && alloc_provider == ALLOC_LOGGING) {
+#ifdef DUK_CMDLINE_ALLOC_LOGGING
+		ctx = duk_create_heap(duk_alloc_logging,
+		                      duk_realloc_logging,
+		                      duk_free_logging,
+		                      (void *) 0xdeadbeef,
+		                      NULL);
+#else
+		fprintf(stderr, "Warning: option --alloc-logging ignored, no logging allocator support\n");
+		fflush(stderr);
+#endif
+	}
+	if (!ctx && alloc_provider == ALLOC_TORTURE) {
+#ifdef DUK_CMDLINE_ALLOC_TORTURE
+		ctx = duk_create_heap(duk_alloc_torture,
+		                      duk_realloc_torture,
+		                      duk_free_torture,
+		                      (void *) 0xdeadbeef,
+		                      NULL);
+#else
+		fprintf(stderr, "Warning: option --alloc-torture ignored, no torture allocator support\n");
+		fflush(stderr);
+#endif
+	}
+	if (!ctx && alloc_provider == ALLOC_HYBRID) {
+#ifdef DUK_CMDLINE_ALLOC_HYBRID
+		void *udata = duk_alloc_hybrid_init();
+		if (!udata) {
+			fprintf(stderr, "Failed to init hybrid allocator\n");
+			fflush(stderr);
+		} else {
+			ctx = duk_create_heap(duk_alloc_hybrid,
+			                      duk_realloc_hybrid,
+			                      duk_free_hybrid,
+			                      udata,
+			                      NULL);
+		}
+#else
+		fprintf(stderr, "Warning: option --alloc-hybrid ignored, no hybrid allocator support\n");
+		fflush(stderr);
+#endif
+	}
+	if (!ctx && alloc_provider == ALLOC_AJSHEAP) {
+#ifdef DUK_CMDLINE_AJSHEAP
+		ajsheap_init();
+
+		ctx = duk_create_heap(
+			ajsheap_log ? ajsheap_alloc_wrapped : AJS_Alloc,
+			ajsheap_log ? ajsheap_realloc_wrapped : AJS_Realloc,
+			ajsheap_log ? ajsheap_free_wrapped : AJS_Free,
+			(void *) 0xdeadbeef,  /* heap_udata: ignored by AjsHeap, use as marker */
+			NULL
+		);                /* fatal_handler */
+#else
+		fprintf(stderr, "Warning: option --alloc-ajsheap ignored, no ajsheap allocator support\n");
+		fflush(stderr);
+#endif
+	}
+	if (!ctx && alloc_provider == ALLOC_DEFAULT) {
+		ctx = duk_create_heap_default();
+	}
+
+	if (!ctx) {
+		fprintf(stderr, "Failed to create Duktape heap\n");
+		fflush(stderr);
+		exit(-1);
+	}
+
+#ifdef DUK_CMDLINE_AJSHEAP
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		fprintf(stdout, "Pool dump after heap creation\n");
+		ajsheap_dump();
+	}
+#endif
+
+#ifdef DUK_CMDLINE_AJSHEAP
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		ajsheap_register(ctx);
+	}
+#endif
+
+	if (debugger) {
+#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT
+		fprintf(stderr, "Debugger enabled, create socket and wait for connection\n");
+		fflush(stderr);
+		duk_trans_socket_init();
+		duk_trans_socket_waitconn();
+		fprintf(stderr, "Debugger connected, call duk_debugger_attach() and then execute requested file(s)/eval\n");
+		fflush(stderr);
+		duk_debugger_attach(ctx,
+		                    duk_trans_socket_read_cb,
+		                    duk_trans_socket_write_cb,
+		                    duk_trans_socket_peek_cb,
+		                    duk_trans_socket_read_flush_cb,
+		                    duk_trans_socket_write_flush_cb,
+		                    debugger_detached,
+		                    (void *) 0xbeef1234);
+#else
+		fprintf(stderr, "Warning: option --debugger ignored, no debugger support\n");
+		fflush(stderr);
+#endif
+	}
+
+#if 0
+	/* Manual test for duk_debugger_cooperate() */
+	{
+		for (i = 0; i < 60; i++) {
+			printf("cooperate: %d\n", i);
+			usleep(1000000);
+			duk_debugger_cooperate(ctx);
+		}
+	}
+#endif
+
+	return ctx;
+}
+
+static void destroy_duktape_heap(duk_context *ctx, int alloc_provider) {
+	(void) alloc_provider;
+
+#ifdef DUK_CMDLINE_AJSHEAP
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		fprintf(stdout, "Pool dump before duk_destroy_heap(), before forced gc\n");
+		ajsheap_dump();
+
+		duk_gc(ctx, 0);
+
+		fprintf(stdout, "Pool dump before duk_destroy_heap(), after forced gc\n");
+		ajsheap_dump();
+	}
+#endif
+
+	if (ctx) {
+		duk_destroy_heap(ctx);
+	}
+
+#ifdef DUK_CMDLINE_AJSHEAP
+	if (alloc_provider == ALLOC_AJSHEAP) {
+		fprintf(stdout, "Pool dump after duk_destroy_heap() (should have zero allocs)\n");
+		ajsheap_dump();
+	}
+#endif
+}
+
+int main(int argc, char *argv[]) {
+	duk_context *ctx = NULL;
+	int retval = 0;
+	int have_files = 0;
+	int have_eval = 0;
+	int interactive = 0;
+	int memlimit_high = 1;
+	int alloc_provider = ALLOC_DEFAULT;
+	int ajsheap_log = 0;
+	int debugger = 0;
+	int recreate_heap = 0;
+	int verbose = 0;
+	const char *compile_filename = NULL;
+	int i;
+
+#ifdef DUK_CMDLINE_AJSHEAP
+	alloc_provider = ALLOC_AJSHEAP;
+#endif
+	(void) ajsheap_log;
+
+	/*
+	 *  Signal handling setup
+	 */
+
+#ifndef NO_SIGNAL
+	set_sigint_handler();
+
+	/* This is useful at the global level; libraries should avoid SIGPIPE though */
+	/*signal(SIGPIPE, SIG_IGN);*/
+#endif
+
+	/*
+	 *  Parse options
+	 */
+
+	for (i = 1; i < argc; i++) {
+		char *arg = argv[i];
+		if (!arg) {
+			goto usage;
+		}
+		if (strcmp(arg, "--restrict-memory") == 0) {
+			memlimit_high = 0;
+		} else if (strcmp(arg, "-i") == 0) {
+			interactive = 1;
+		} else if (strcmp(arg, "-c") == 0) {
+			if (i == argc - 1) {
+				goto usage;
+			}
+			i++;
+			compile_filename = argv[i];
+		} else if (strcmp(arg, "-e") == 0) {
+			have_eval = 1;
+			if (i == argc - 1) {
+				goto usage;
+			}
+			i++;  /* skip code */
+		} else if (strcmp(arg, "--alloc-default") == 0) {
+			alloc_provider = ALLOC_DEFAULT;
+		} else if (strcmp(arg, "--alloc-logging") == 0) {
+			alloc_provider = ALLOC_LOGGING;
+		} else if (strcmp(arg, "--alloc-torture") == 0) {
+			alloc_provider = ALLOC_TORTURE;
+		} else if (strcmp(arg, "--alloc-hybrid") == 0) {
+			alloc_provider = ALLOC_HYBRID;
+		} else if (strcmp(arg, "--alloc-ajsheap") == 0) {
+			alloc_provider = ALLOC_AJSHEAP;
+		} else if (strcmp(arg, "--ajsheap-log") == 0) {
+			ajsheap_log = 1;
+		} else if (strcmp(arg, "--debugger") == 0) {
+			debugger = 1;
+		} else if (strcmp(arg, "--recreate-heap") == 0) {
+			recreate_heap = 1;
+		} else if (strcmp(arg, "--verbose") == 0) {
+			verbose = 1;
+		} else if (strlen(arg) >= 1 && arg[0] == '-') {
+			goto usage;
+		} else {
+			have_files = 1;
+		}
+	}
+	if (!have_files && !have_eval) {
+		interactive = 1;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+#ifndef NO_RLIMIT
+	set_resource_limits(memlimit_high ? MEM_LIMIT_HIGH : MEM_LIMIT_NORMAL);
+#else
+	if (memlimit_high == 0) {
+		fprintf(stderr, "Warning: option --restrict-memory ignored, no rlimit support\n");
+		fflush(stderr);
+	}
+#endif
+
+	/*
+	 *  Create heap
+	 */
+
+	ctx = create_duktape_heap(alloc_provider, debugger);
+
+	/*
+	 *  Execute any argument file(s)
+	 */
+
+	for (i = 1; i < argc; i++) {
+		char *arg = argv[i];
+		if (!arg) {
+			continue;
+		} else if (strlen(arg) == 2 && strcmp(arg, "-e") == 0) {
+			/* Here we know the eval arg exists but check anyway */
+			if (i == argc - 1) {
+				retval = 1;
+				goto cleanup;
+			}
+			if (handle_eval(ctx, argv[i + 1]) != 0) {
+				retval = 1;
+				goto cleanup;
+			}
+			i++;  /* skip code */
+			continue;
+		} else if (strlen(arg) == 2 && strcmp(arg, "-c") == 0) {
+			i++;  /* skip filename */
+			continue;
+		} else if (strlen(arg) >= 1 && arg[0] == '-') {
+			continue;
+		}
+
+		if (verbose) {
+			fprintf(stderr, "*** Executing file: %s\n", arg);
+			fflush(stderr);
+		}
+
+		if (handle_file(ctx, arg, compile_filename) != 0) {
+			retval = 1;
+			goto cleanup;
+		}
+
+		if (recreate_heap) {
+			if (verbose) {
+				fprintf(stderr, "*** Recreating heap...\n");
+				fflush(stderr);
+			}
+
+			destroy_duktape_heap(ctx, alloc_provider);
+			ctx = create_duktape_heap(alloc_provider, debugger);
+		}
+	}
+
+	/*
+	 *  Enter interactive mode if options indicate it
+	 */
+
+	if (interactive) {
+		if (handle_interactive(ctx) != 0) {
+			retval = 1;
+			goto cleanup;
+		}
+	}
+
+	/*
+	 *  Cleanup and exit
+	 */
+
+ cleanup:
+	if (interactive) {
+		fprintf(stderr, "Cleaning up...\n");
+		fflush(stderr);
+	}
+
+	if (ctx) {
+		destroy_duktape_heap(ctx, alloc_provider);
+	}
+	ctx = NULL;
+
+	return retval;
+
+	/*
+	 *  Usage
+	 */
+
+ usage:
+	fprintf(stderr, "Usage: duk [options] [<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"
+			"   --verbose          verbose messages to stderr\n"
+	                "   --restrict-memory  use lower memory limit (used by test runner)\n"
+	                "   --alloc-default    use Duktape default allocator\n"
+#ifdef DUK_CMDLINE_ALLOC_LOGGING
+	                "   --alloc-logging    use logging allocator (writes to /tmp)\n"
+#endif
+#ifdef DUK_CMDLINE_ALLOC_TORTURE
+	                "   --alloc-torture    use torture allocator\n"
+#endif
+#ifdef DUK_CMDLINE_ALLOC_HYBRID
+	                "   --alloc-hybrid     use hybrid allocator\n"
+#endif
+#ifdef DUK_CMDLINE_AJSHEAP
+	                "   --alloc-ajsheap    use ajsheap allocator (enabled by default with 'ajduk')\n"
+	                "   --ajsheap-log      write alloc log to /tmp/ajduk-alloc-log.txt\n"
+#endif
+#ifdef DUK_CMDLINE_DEBUGGER_SUPPORT
+			"   --debugger         start example debugger\n"
+#endif
+			"   --recreate-heap    recreate heap after every file\n"
+	                "\n"
+	                "If <filename> is omitted, interactive mode is started automatically.\n");
+	fflush(stderr);
+	exit(1);
+}

+ 892 - 0
src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline_ajduk.c

@@ -0,0 +1,892 @@
+/*
+ *  '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"
+
+extern uint8_t dbgHEAPDUMP;
+
+/*
+ *  Helpers
+ */
+
+static void safe_print_chars(const char *p, duk_size_t len, int until_nul) {
+	duk_size_t i;
+
+	printf("\"");
+	for (i = 0; i < len; i++) {
+		unsigned char x = (unsigned char) p[i];
+		if (until_nul && x == 0U) {
+			break;
+		}
+		if (x < 0x20 || x >= 0x7e || x == '"' || x == '\'' || x == '\\') {
+			printf("\\x%02x", (int) x);
+		} else {
+			printf("%c", (char) x);
+		}
+	}
+	printf("\"");
+}
+
+/*
+ *  Heap initialization when using AllJoyn.js pool allocator (without any
+ *  other AllJoyn.js integration).  This serves as an example of how to
+ *  integrate Duktape with a pool allocator and is useful for low memory
+ *  testing.
+ *
+ *  The pool sizes are not optimized here.  The sizes are chosen so that
+ *  you can look at the high water mark (hwm) and use counts (use) and see
+ *  how much allocations are needed for each pool size.  To optimize pool
+ *  sizes more accurately, you can use --alloc-logging and inspect the memory
+ *  allocation log which provides exact byte counts etc.
+ *
+ *  https://git.allseenalliance.org/cgit/core/alljoyn-js.git
+ *  https://git.allseenalliance.org/cgit/core/alljoyn-js.git/tree/ajs.c
+ */
+
+static const AJS_HeapConfig ajsheap_config[] = {
+	{ 8,      10,   AJS_POOL_BORROW,  0 },
+	{ 12,     10,   AJS_POOL_BORROW,  0 },
+	{ 16,     200,  AJS_POOL_BORROW,  0 },
+	{ 20,     400,  AJS_POOL_BORROW,  0 },
+	{ 24,     400,  AJS_POOL_BORROW,  0 },
+	{ 28,     200,  AJS_POOL_BORROW,  0 },
+	{ 32,     200,  AJS_POOL_BORROW,  0 },
+	{ 40,     200,  AJS_POOL_BORROW,  0 },
+	{ 48,     50,   AJS_POOL_BORROW,  0 },
+	{ 52,     50,   AJS_POOL_BORROW,  0 },
+	{ 56,     50,   AJS_POOL_BORROW,  0 },
+	{ 60,     50,   AJS_POOL_BORROW,  0 },
+	{ 64,     50,   AJS_POOL_BORROW,  0 },
+	{ 128,    80,   AJS_POOL_BORROW,  0 },
+	{ 256,    16,   AJS_POOL_BORROW,  0 },
+	{ 512,    16,   AJS_POOL_BORROW,  0 },
+	{ 1024,   6,    AJS_POOL_BORROW,  0 },
+	{ 1360,   1,    AJS_POOL_BORROW,  0 },  /* duk_heap, with heap ptr compression */
+	{ 2048,   5,    AJS_POOL_BORROW,  0 },
+	{ 4096,   3,    0,                0 },
+	{ 8192,   3,    0,                0 },
+	{ 16384,  1,    0,                0 },
+	{ 32768,  1,    0,                0 }
+};
+
+uint8_t *ajsheap_ram = NULL;
+
+void ajsheap_init(void) {
+	size_t heap_sz[1];
+	uint8_t *heap_array[1];
+	uint8_t num_pools, i;
+	AJ_Status ret;
+
+	num_pools = (uint8_t) (sizeof(ajsheap_config) / sizeof(AJS_HeapConfig));
+	heap_sz[0] = AJS_HeapRequired(ajsheap_config,  /* heapConfig */
+	                              num_pools,       /* numPools */
+	                              0);              /* heapNum */
+	ajsheap_ram = (uint8_t *) malloc(heap_sz[0]);
+	if (ajsheap_ram == NULL) {
+		fprintf(stderr, "Failed to allocate AJS heap\n");
+		fflush(stderr);
+		exit(1);
+	}
+	heap_array[0] = ajsheap_ram;
+
+	fprintf(stderr, "Allocated AJS heap of %ld bytes, pools:", (long) heap_sz[0]);
+	for (i = 0; i < num_pools; i++) {
+		fprintf(stderr, " (sz:%ld,num:%ld,brw:%ld,idx:%ld)",
+		        (long) ajsheap_config[i].size, (long) ajsheap_config[i].entries,
+		        (long) ajsheap_config[i].borrow, (long) ajsheap_config[i].heapIndex);
+	}
+	fprintf(stderr, "\n");
+	fflush(stderr);
+
+	ret = AJS_HeapInit((void **) heap_array,   /* heap */
+	                   (size_t *) heap_sz,     /* heapSz */
+	                   ajsheap_config,         /* heapConfig */
+	                   num_pools,              /* numPools */
+	                   1);                     /* numHeaps */
+	fprintf(stderr, "AJS_HeapInit() -> %ld\n", (long) ret);
+	fflush(stderr);
+
+	/* Enable heap dumps */
+	dbgHEAPDUMP = 1;
+}
+
+/* AjsHeap.dump(), allows Ecmascript code to dump heap status at suitable
+ * points.
+ */
+duk_ret_t ajsheap_dump_binding(duk_context *ctx) {
+	AJS_HeapDump();
+	fflush(stdout);
+	return 0;
+}
+
+void ajsheap_dump(void) {
+	AJS_HeapDump();
+	fflush(stdout);
+}
+
+void ajsheap_register(duk_context *ctx) {
+	duk_push_object(ctx);
+	duk_push_c_function(ctx, ajsheap_dump_binding, 0);
+	duk_put_prop_string(ctx, -2, "dump");
+	duk_put_global_string(ctx, "AjsHeap");
+}
+
+/*
+ *  Wrapped ajs_heap.c alloc functions
+ *
+ *  Used to write an alloc log.
+ */
+
+static FILE *ajsheap_alloc_log = NULL;
+
+static void ajsheap_write_alloc_log(const char *fmt, ...) {
+	va_list ap;
+	char buf[256];
+
+	va_start(ap, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	buf[sizeof(buf) - 1] = (char) 0;
+	va_end(ap);
+
+	if (ajsheap_alloc_log == NULL) {
+		ajsheap_alloc_log = fopen("/tmp/ajduk-alloc-log.txt", "wb");
+		if (ajsheap_alloc_log == NULL) {
+			fprintf(stderr, "WARNING: failed to write alloc log, ignoring\n");
+			fflush(stderr);
+			return;
+		}
+	}
+
+	(void) fwrite((const void *) buf, 1, strlen(buf), ajsheap_alloc_log);
+	(void) fflush(ajsheap_alloc_log);
+}
+
+void *ajsheap_alloc_wrapped(void *udata, duk_size_t size) {
+	void *ret = AJS_Alloc(udata, size);
+	if (size > 0 && ret == NULL) {
+		ajsheap_write_alloc_log("A FAIL %ld\n", (long) size);
+	} else if (ret == NULL) {
+		ajsheap_write_alloc_log("A NULL %ld\n", (long) size);
+	} else {
+		ajsheap_write_alloc_log("A %p %ld\n", ret, (long) size);
+	}
+	return ret;
+}
+
+void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size) {
+	void *ret = AJS_Realloc(udata, ptr, size);
+	if (size > 0 && ret == NULL) {
+		if (ptr == NULL) {
+			ajsheap_write_alloc_log("R NULL -1 FAIL %ld\n", (long) size);
+		} else {
+			ajsheap_write_alloc_log("R %p -1 FAIL %ld\n", ptr, (long) size);
+		}
+	} else if (ret == NULL) {
+		if (ptr == NULL) {
+			ajsheap_write_alloc_log("R NULL -1 NULL %ld\n", (long) size);
+		} else {
+			ajsheap_write_alloc_log("R %p -1 NULL %ld\n", ptr, (long) size);
+		}
+	} else {
+		if (ptr == NULL) {
+			ajsheap_write_alloc_log("R NULL -1 %p %ld\n", ret, (long) size);
+		} else {
+			ajsheap_write_alloc_log("R %p -1 %p %ld\n", ptr, ret, (long) size);
+		}
+	}
+	return ret;
+}
+
+void ajsheap_free_wrapped(void *udata, void *ptr) {
+	AJS_Free(udata, ptr);
+	if (ptr == NULL) {
+	} else {
+		ajsheap_write_alloc_log("F %p -1\n", ptr);
+	}
+}
+
+/*
+ *  Example pointer compression functions.
+ *
+ *  'base' is chosen so that no non-NULL pointer results in a zero result
+ *  which is reserved for NULL pointers.
+ */
+
+duk_uint16_t ajsheap_enc16(void *ud, void *p) {
+	duk_uint32_t ret;
+	char *base = (char *) ajsheap_ram - 4;
+
+	/* Userdata is not needed in this case but would be useful if heap
+	 * pointer compression were used for multiple heaps.  The userdata
+	 * allows the callback to distinguish between heaps and their base
+	 * pointers.
+	 *
+	 * If not needed, the userdata can be left out during compilation
+	 * by simply ignoring the userdata argument of the pointer encode
+	 * and decode macros.  It is kept here so that any bugs in actually
+	 * providing the value inside Duktape are revealed during compilation.
+	 */
+	(void) ud;
+#if 1
+	/* Ensure that we always get the heap_udata given in heap creation.
+	 * (Useful for Duktape development, not needed for user programs.)
+	 */
+	if (ud != (void *) 0xdeadbeef) {
+		fprintf(stderr, "invalid udata for ajsheap_enc16: %p\n", ud);
+		fflush(stderr);
+	}
+#endif
+
+	if (p == NULL) {
+		ret = 0;
+	} else {
+		ret = (duk_uint32_t) (((char *) p - base) >> 2);
+	}
+#if 0
+	printf("ajsheap_enc16: %p -> %u\n", p, (unsigned int) ret);
+#endif
+	if (ret > 0xffffUL) {
+		fprintf(stderr, "Failed to compress pointer\n");
+		fflush(stderr);
+		abort();
+	}
+	return (duk_uint16_t) ret;
+}
+void *ajsheap_dec16(void *ud, duk_uint16_t x) {
+	void *ret;
+	char *base = (char *) ajsheap_ram - 4;
+
+	/* See userdata discussion in ajsheap_enc16(). */
+	(void) ud;
+#if 1
+	/* Ensure that we always get the heap_udata given in heap creation. */
+	if (ud != (void *) 0xdeadbeef) {
+		fprintf(stderr, "invalid udata for ajsheap_dec16: %p\n", ud);
+		fflush(stderr);
+	}
+#endif
+
+	if (x == 0) {
+		ret = NULL;
+	} else {
+		ret = (void *) (base + (((duk_uint32_t) x) << 2));
+	}
+#if 0
+	printf("ajsheap_dec16: %u -> %p\n", (unsigned int) x, ret);
+#endif
+	return ret;
+}
+
+/*
+ *  Simplified example of an external strings strategy where incoming strings
+ *  are written sequentially into a fixed, memory mapped flash area.
+ *
+ *  The example first scans if the string is already in the flash (which may
+ *  happen if the same string is interned multiple times), then adds it to
+ *  flash if there is space.
+ *
+ *  This example is too slow to be used in a real world application: there
+ *  should be e.g. a hash table to quickly check for strings that are already
+ *  present in the string data (similarly to how string interning works in
+ *  Duktape itself).
+ */
+
+static uint8_t ajsheap_strdata[65536];
+static size_t ajsheap_strdata_used = 0;
+
+const void *ajsheap_extstr_check_1(const void *ptr, duk_size_t len) {
+	uint8_t *p, *p_end;
+	uint8_t initial;
+	uint8_t *ret;
+	size_t left;
+
+	(void) safe_print_chars;  /* potentially unused */
+
+	if (len <= 3) {
+		/* It's not worth it to make very small strings external, as
+		 * they would take the same space anyway.  Also avoids zero
+		 * length degenerate case.
+		 */
+		return NULL;
+	}
+
+	/*
+	 *  Check if we already have the string.  Be careful to compare for
+	 *  NUL terminator too, it is NOT present in 'ptr'.  This algorithm
+	 *  is too simplistic and way too slow for actual use.
+	 */
+
+	initial = ((const uint8_t *) ptr)[0];
+	for (p = ajsheap_strdata, p_end = p + ajsheap_strdata_used; p != p_end; p++) {
+		if (*p != initial) {
+			continue;
+		}
+		left = (size_t) (p_end - p);
+		if (left >= len + 1 &&
+		    memcmp(p, ptr, len) == 0 &&
+		    p[len] == 0) {
+			ret = p;
+#if 0
+			printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ",
+			       (void *) ptr, (long) len);
+			safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+			printf(" -> existing %p (used=%ld)\n",
+			       (void *) ret, (long) ajsheap_strdata_used);
+#endif
+			return ret;
+		}
+	}
+
+	/*
+	 *  Not present yet, check if we have space.  Again, be careful to
+	 *  ensure there is space for a NUL following the input data.
+	 */
+
+	if (ajsheap_strdata_used + len + 1 > sizeof(ajsheap_strdata)) {
+#if 0
+		printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", (void *) ptr, (long) len);
+		safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+		printf(" -> no space (used=%ld)\n", (long) ajsheap_strdata_used);
+#endif
+		return NULL;
+	}
+
+	/*
+	 *  There is space, add the string to our collection, being careful
+	 *  to append the NUL.
+	 */
+
+	ret = ajsheap_strdata + ajsheap_strdata_used;
+	memcpy(ret, ptr, len);
+	ret[len] = (uint8_t) 0;
+	ajsheap_strdata_used += len + 1;
+
+#if 0
+	printf("ajsheap_extstr_check_1: ptr=%p, len=%ld -> ", (void *) ptr, (long) len);
+	safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+	printf(" -> %p (used=%ld)\n", (void *) ret, (long) ajsheap_strdata_used);
+#endif
+	return (const void *) ret;
+}
+
+void ajsheap_extstr_free_1(const void *ptr) {
+	(void) ptr;
+#if 0
+	printf("ajsheap_extstr_free_1: freeing extstr %p -> ", ptr);
+	safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/);
+	printf("\n");
+#endif
+}
+
+/*
+ *  Simplified example of an external strings strategy where a set of strings
+ *  is gathered during application compile time and baked into the application
+ *  binary.
+ *
+ *  Duktape built-in strings are available from duk_build_meta.json, see
+ *  util/duk_meta_to_strarray.py.  There may also be a lot of application
+ *  specific strings, e.g. those used by application specific APIs.  These
+ *  must be gathered through some other means, see e.g. util/scan_strings.py.
+ */
+
+static const char *strdata_duk_builtin_strings[] = {
+	/*
+	 *  These strings are from util/duk_meta_to_strarray.py
+	 */
+
+	"Logger",
+	"Thread",
+	"Pointer",
+	"Buffer",
+	"DecEnv",
+	"ObjEnv",
+	"",
+	"global",
+	"Arguments",
+	"JSON",
+	"Math",
+	"Error",
+	"RegExp",
+	"Date",
+	"Number",
+	"Boolean",
+	"String",
+	"Array",
+	"Function",
+	"Object",
+	"Null",
+	"Undefined",
+	"{_func:true}",
+	"{\x22" "_func\x22" ":true}",
+	"{\x22" "_ninf\x22" ":true}",
+	"{\x22" "_inf\x22" ":true}",
+	"{\x22" "_nan\x22" ":true}",
+	"{\x22" "_undef\x22" ":true}",
+	"toLogString",
+	"clog",
+	"l",
+	"n",
+	"fatal",
+	"error",
+	"warn",
+	"debug",
+	"trace",
+	"raw",
+	"fmt",
+	"current",
+	"resume",
+	"compact",
+	"jc",
+	"jx",
+	"base64",
+	"hex",
+	"dec",
+	"enc",
+	"fin",
+	"gc",
+	"act",
+	"info",
+	"version",
+	"env",
+	"modLoaded",
+	"modSearch",
+	"errThrow",
+	"errCreate",
+	"compile",
+	"\xff" "Regbase",
+	"\xff" "Thread",
+	"\xff" "Handler",
+	"\xff" "Finalizer",
+	"\xff" "Callee",
+	"\xff" "Map",
+	"\xff" "Args",
+	"\xff" "This",
+	"\xff" "Pc2line",
+	"\xff" "Source",
+	"\xff" "Varenv",
+	"\xff" "Lexenv",
+	"\xff" "Varmap",
+	"\xff" "Formals",
+	"\xff" "Bytecode",
+	"\xff" "Next",
+	"\xff" "Target",
+	"\xff" "Value",
+	"pointer",
+	"buffer",
+	"\xff" "Tracedata",
+	"lineNumber",
+	"fileName",
+	"pc",
+	"stack",
+	"ThrowTypeError",
+	"Duktape",
+	"id",
+	"require",
+	"__proto__",
+	"setPrototypeOf",
+	"ownKeys",
+	"enumerate",
+	"deleteProperty",
+	"has",
+	"Proxy",
+	"callee",
+	"Invalid Date",
+	"[...]",
+	"\x0a" "\x09",
+	" ",
+	",",
+	"-0",
+	"+0",
+	"0",
+	"-Infinity",
+	"+Infinity",
+	"Infinity",
+	"object",
+	"string",
+	"number",
+	"boolean",
+	"undefined",
+	"stringify",
+	"tan",
+	"sqrt",
+	"sin",
+	"round",
+	"random",
+	"pow",
+	"min",
+	"max",
+	"log",
+	"floor",
+	"exp",
+	"cos",
+	"ceil",
+	"atan2",
+	"atan",
+	"asin",
+	"acos",
+	"abs",
+	"SQRT2",
+	"SQRT1_2",
+	"PI",
+	"LOG10E",
+	"LOG2E",
+	"LN2",
+	"LN10",
+	"E",
+	"message",
+	"name",
+	"input",
+	"index",
+	"(?:)",
+	"lastIndex",
+	"multiline",
+	"ignoreCase",
+	"source",
+	"test",
+	"exec",
+	"toGMTString",
+	"setYear",
+	"getYear",
+	"toJSON",
+	"toISOString",
+	"toUTCString",
+	"setUTCFullYear",
+	"setFullYear",
+	"setUTCMonth",
+	"setMonth",
+	"setUTCDate",
+	"setDate",
+	"setUTCHours",
+	"setHours",
+	"setUTCMinutes",
+	"setMinutes",
+	"setUTCSeconds",
+	"setSeconds",
+	"setUTCMilliseconds",
+	"setMilliseconds",
+	"setTime",
+	"getTimezoneOffset",
+	"getUTCMilliseconds",
+	"getMilliseconds",
+	"getUTCSeconds",
+	"getSeconds",
+	"getUTCMinutes",
+	"getMinutes",
+	"getUTCHours",
+	"getHours",
+	"getUTCDay",
+	"getDay",
+	"getUTCDate",
+	"getDate",
+	"getUTCMonth",
+	"getMonth",
+	"getUTCFullYear",
+	"getFullYear",
+	"getTime",
+	"toLocaleTimeString",
+	"toLocaleDateString",
+	"toTimeString",
+	"toDateString",
+	"now",
+	"UTC",
+	"parse",
+	"toPrecision",
+	"toExponential",
+	"toFixed",
+	"POSITIVE_INFINITY",
+	"NEGATIVE_INFINITY",
+	"NaN",
+	"MIN_VALUE",
+	"MAX_VALUE",
+	"substr",
+	"trim",
+	"toLocaleUpperCase",
+	"toUpperCase",
+	"toLocaleLowerCase",
+	"toLowerCase",
+	"substring",
+	"split",
+	"search",
+	"replace",
+	"match",
+	"localeCompare",
+	"charCodeAt",
+	"charAt",
+	"fromCharCode",
+	"reduceRight",
+	"reduce",
+	"filter",
+	"map",
+	"forEach",
+	"some",
+	"every",
+	"lastIndexOf",
+	"indexOf",
+	"unshift",
+	"splice",
+	"sort",
+	"slice",
+	"shift",
+	"reverse",
+	"push",
+	"pop",
+	"join",
+	"concat",
+	"isArray",
+	"arguments",
+	"caller",
+	"bind",
+	"call",
+	"apply",
+	"propertyIsEnumerable",
+	"isPrototypeOf",
+	"hasOwnProperty",
+	"valueOf",
+	"toLocaleString",
+	"toString",
+	"constructor",
+	"set",
+	"get",
+	"enumerable",
+	"configurable",
+	"writable",
+	"value",
+	"keys",
+	"isExtensible",
+	"isFrozen",
+	"isSealed",
+	"preventExtensions",
+	"freeze",
+	"seal",
+	"defineProperties",
+	"defineProperty",
+	"create",
+	"getOwnPropertyNames",
+	"getOwnPropertyDescriptor",
+	"getPrototypeOf",
+	"prototype",
+	"length",
+	"alert",
+	"print",
+	"unescape",
+	"escape",
+	"encodeURIComponent",
+	"encodeURI",
+	"decodeURIComponent",
+	"decodeURI",
+	"isFinite",
+	"isNaN",
+	"parseFloat",
+	"parseInt",
+	"eval",
+	"URIError",
+	"TypeError",
+	"SyntaxError",
+	"ReferenceError",
+	"RangeError",
+	"EvalError",
+	"break",
+	"case",
+	"catch",
+	"continue",
+	"debugger",
+	"default",
+	"delete",
+	"do",
+	"else",
+	"finally",
+	"for",
+	"function",
+	"if",
+	"in",
+	"instanceof",
+	"new",
+	"return",
+	"switch",
+	"this",
+	"throw",
+	"try",
+	"typeof",
+	"var",
+	"void",
+	"while",
+	"with",
+	"class",
+	"const",
+	"enum",
+	"export",
+	"extends",
+	"import",
+	"super",
+	"null",
+	"true",
+	"false",
+	"implements",
+	"interface",
+	"let",
+	"package",
+	"private",
+	"protected",
+	"public",
+	"static",
+	"yield",
+
+	/*
+	 *  These strings are manually added, and would be gathered in some
+	 *  application specific manner.
+	 */
+
+	"foo",
+	"bar",
+	"quux",
+	"enableFrob",
+	"disableFrob"
+	/* ... */
+};
+
+const void *ajsheap_extstr_check_2(const void *ptr, duk_size_t len) {
+	int i, n;
+
+	(void) safe_print_chars;  /* potentially unused */
+
+	/* Linear scan.  An actual implementation would need some acceleration
+	 * structure, e.g. select a sublist based on first character.
+	 *
+	 * NOTE: input string (behind 'ptr' with 'len' bytes) DOES NOT have a
+	 * trailing NUL character.  Any strings returned from this function
+	 * MUST have a trailing NUL character.
+	 */
+
+	n = (int) (sizeof(strdata_duk_builtin_strings) / sizeof(const char *));
+	for (i = 0; i < n; i++) {
+		const char *str;
+
+		str = strdata_duk_builtin_strings[i];
+		if (strlen(str) == len && memcmp(ptr, (const void *) str, len) == 0) {
+#if 0
+			printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ",
+			       (void *) ptr, (long) len);
+			safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+			printf(" -> constant string index %ld\n", (long) i);
+#endif
+			return (void *) strdata_duk_builtin_strings[i];
+		}
+	}
+
+#if 0
+	printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ",
+	       (void *) ptr, (long) len);
+	safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+	printf(" -> not found\n");
+#endif
+	return NULL;
+}
+
+void ajsheap_extstr_free_2(const void *ptr) {
+	(void) ptr;
+#if 0
+	printf("ajsheap_extstr_free_2: freeing extstr %p -> ", ptr);
+	safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/);
+	printf("\n");
+#endif
+}
+
+/*
+ *  External strings strategy intended for valgrind testing: external strings
+ *  are allocated using malloc()/free() so that valgrind can be used to ensure
+ *  that strings are e.g. freed exactly once.
+ */
+
+const void *ajsheap_extstr_check_3(const void *ptr, duk_size_t len) {
+	duk_uint8_t *ret;
+
+	(void) safe_print_chars;  /* potentially unused */
+
+	ret = malloc((size_t) len + 1);
+	if (ret == NULL) {
+#if 0
+		printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ",
+		       (void *) ptr, (long) len);
+		safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+		printf(" -> malloc failed, return NULL\n");
+#endif
+		return (const void *) NULL;
+	}
+
+	if (len > 0) {
+		memcpy((void *) ret, ptr, (size_t) len);
+	}
+	ret[len] = (duk_uint8_t) 0;
+
+#if 0
+	printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ",
+	       (void *) ptr, (long) len);
+	safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
+	printf(" -> %p\n", (void *) ret);
+#endif
+	return (const void *) ret;
+}
+
+void ajsheap_extstr_free_3(const void *ptr) {
+	(void) ptr;
+#if 0
+	printf("ajsheap_extstr_free_3: freeing extstr %p -> ", ptr);
+	safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/);
+	printf("\n");
+#endif
+	free((void *) ptr);
+}
+
+/*
+ *  Execution timeout example
+ */
+
+#define  AJSHEAP_EXEC_TIMEOUT  5  /* seconds */
+
+static time_t curr_pcall_start = 0;
+static long exec_timeout_check_counter = 0;
+
+void ajsheap_start_exec_timeout(void) {
+	curr_pcall_start = time(NULL);
+}
+
+void ajsheap_clear_exec_timeout(void) {
+	curr_pcall_start = 0;
+}
+
+duk_bool_t ajsheap_exec_timeout_check(void *udata) {
+	time_t now = time(NULL);
+	time_t diff = now - curr_pcall_start;
+
+	(void) udata;  /* not needed */
+
+	exec_timeout_check_counter++;
+#if 0
+	printf("exec timeout check %ld: now=%ld, start=%ld, diff=%ld\n",
+	       (long) exec_timeout_check_counter, (long) now, (long) curr_pcall_start, (long) diff);
+	fflush(stdout);
+#endif
+
+	if (curr_pcall_start == 0) {
+		/* protected call not yet running */
+		return 0;
+	}
+	if (diff > AJSHEAP_EXEC_TIMEOUT) {
+		return 1;
+	}
+	return 0;
+}
+
+#else  /* DUK_CMDLINE_AJSHEAP */
+
+int ajs_dummy = 0;  /* to avoid empty source file */
+
+#endif  /* DUK_CMDLINE_AJSHEAP */

+ 8 - 0
src/third_party/duktape-1.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/examples/coffee/hello.coffee

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

+ 28 - 0
src/third_party/duktape-1.3.0/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)
+

+ 17 - 0
src/third_party/duktape-1.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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;
+}

+ 6 - 0
src/third_party/duktape-1.3.0/examples/debug-trans-socket/README.rst

@@ -0,0 +1,6 @@
+================================================
+Debug transport using a simple socket connection
+================================================
+
+This example implements an example debug transport which uses a Linux server
+socket on the debug target.

+ 313 - 0
src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.c

@@ -0,0 +1,313 @@
+/*
+ *  Example debug transport using a TCP socket
+ *
+ *  The application has a server socket which can be connected to.
+ *  After that data is just passed through.
+ *
+ *  NOTE: This is Linux specific on purpose, as it's just an example how
+ *  a debug transport can be concretely implemented.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <poll.h>
+#include <errno.h>
+#include "duktape.h"
+
+#ifndef DUK_DEBUG_PORT
+#define DUK_DEBUG_PORT 9091
+#endif
+
+#if 0
+#define DEBUG_PRINTS
+#endif
+
+static int server_sock = -1;
+static int client_sock = -1;
+
+/*
+ *  Transport init
+ */
+
+void duk_trans_socket_init(void) {
+	struct sockaddr_in addr;
+	int on;
+
+	server_sock = socket(AF_INET, SOCK_STREAM, 0);
+	if (server_sock < 0) {
+		fprintf(stderr, "%s: failed to create server socket: %s\n", __FILE__, strerror(errno));
+		fflush(stderr);
+		goto fail;
+	}
+
+	on = 1;
+	if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) {
+		fprintf(stderr, "%s: failed to set SO_REUSEADDR for server socket: %s\n", __FILE__, strerror(errno));
+		fflush(stderr);
+		goto fail;
+	}
+
+	memset((void *) &addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = INADDR_ANY;
+	addr.sin_port = htons(DUK_DEBUG_PORT);
+
+	if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		fprintf(stderr, "%s: failed to bind server socket: %s\n", __FILE__, strerror(errno));
+		fflush(stderr);
+		goto fail;
+	}
+
+	listen(server_sock, 1 /*backlog*/);
+	return;
+
+ fail:
+	if (server_sock >= 0) {
+		(void) close(server_sock);
+		server_sock = -1;
+	}
+}
+
+void duk_trans_socket_waitconn(void) {
+	struct sockaddr_in addr;
+	socklen_t sz;
+
+	if (server_sock < 0) {
+		fprintf(stderr, "%s: no server socket, skip waiting for connection\n", __FILE__);
+		fflush(stderr);
+		return;
+	}
+	if (client_sock >= 0) {
+		(void) close(client_sock);
+		client_sock = -1;
+	}
+
+	fprintf(stderr, "Waiting for debug connection on port %d\n", (int) DUK_DEBUG_PORT);
+	fflush(stderr);
+
+	sz = (socklen_t) sizeof(addr);
+	client_sock = accept(server_sock, (struct sockaddr *) &addr, &sz);
+	if (client_sock < 0) {
+		fprintf(stderr, "%s: accept() failed, skip waiting for connection: %s\n", __FILE__, strerror(errno));
+		fflush(stderr);
+		goto fail;
+	}
+
+	fprintf(stderr, "Debug connection established\n");
+	fflush(stderr);
+
+	/* XXX: For now, close the listen socket because we won't accept new
+	 * connections anyway.  A better implementation would allow multiple
+	 * debug attaches.
+	 */
+
+	if (server_sock >= 0) {
+		(void) close(server_sock);
+		server_sock = -1;
+	}
+	return;
+
+ fail:
+	if (client_sock >= 0) {
+		(void) close(client_sock);
+		client_sock = -1;
+	}
+}
+
+/*
+ *  Duktape callbacks
+ */
+
+/* Duktape debug transport callback: partial read */
+duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length) {
+	ssize_t ret;
+
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n",
+	        __func__, (void *) udata, (void *) buffer, (long) length);
+	fflush(stderr);
+#endif
+
+	if (client_sock < 0) {
+		return 0;
+	}
+
+	if (length == 0) {
+		/* This shouldn't happen. */
+		fprintf(stderr, "%s: read request length == 0, closing connection\n", __FILE__);
+		fflush(stderr);
+		goto fail;
+	}
+
+	if (buffer == NULL) {
+		/* This shouldn't happen. */
+		fprintf(stderr, "%s: read request buffer == NULL, closing connection\n", __FILE__);
+		fflush(stderr);
+		goto fail;
+	}
+
+	/* In a production quality implementation there would be a sanity
+	 * timeout here to recover from "black hole" disconnects.
+	 */
+
+	ret = read(client_sock, (void *) buffer, (size_t) length);
+	if (ret < 0) {
+		fprintf(stderr, "%s: debug read failed, errno %d, closing connection: %s\n", __FILE__, errno, strerror(errno));
+		fflush(stderr);
+		goto fail;
+	} else if (ret == 0) {
+		fprintf(stderr, "%s: debug read failed, ret == 0 (EOF), closing connection\n", __FILE__);
+		fflush(stderr);
+		goto fail;
+	} else if (ret > (ssize_t) length) {
+		fprintf(stderr, "%s: debug read failed, ret too large (%ld > %ld), closing connection\n", __FILE__, (long) ret, (long) length);
+		fflush(stderr);
+		goto fail;
+	}
+
+	return (duk_size_t) ret;
+
+ fail:
+	if (client_sock >= 0) {
+		(void) close(client_sock);
+		client_sock = -1;
+	}
+	return 0;
+}
+
+/* Duktape debug transport callback: partial write */
+duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length) {
+	ssize_t ret;
+
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p, buffer=%p, length=%ld\n",
+	        __func__, (void *) udata, (void *) buffer, (long) length);
+	fflush(stderr);
+#endif
+
+	if (client_sock < 0) {
+		return 0;
+	}
+
+	if (length == 0) {
+		/* This shouldn't happen. */
+		fprintf(stderr, "%s: write request length == 0, closing connection\n", __FILE__);
+		fflush(stderr);
+		goto fail;
+	}
+
+	if (buffer == NULL) {
+		/* This shouldn't happen. */
+		fprintf(stderr, "%s: write request buffer == NULL, closing connection\n", __FILE__);
+		fflush(stderr);
+		goto fail;
+	}
+
+	/* In a production quality implementation there would be a sanity
+	 * timeout here to recover from "black hole" disconnects.
+	 */
+
+	ret = write(client_sock, (const void *) buffer, (size_t) length);
+	if (ret <= 0 || ret > (ssize_t) length) {
+		fprintf(stderr, "%s: debug write failed, closing connection: %s\n", __FILE__, strerror(errno));
+		fflush(stderr);
+		goto fail;
+	}
+
+	return (duk_size_t) ret;
+
+ fail:
+	if (client_sock >= 0) {
+		(void) close(client_sock);
+		client_sock = -1;
+	}
+	return 0;
+}
+
+duk_size_t duk_trans_socket_peek_cb(void *udata) {
+	struct pollfd fds[1];
+	int poll_rc;
+
+	(void) udata;  /* not needed by the example */
+
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	fds[0].fd = client_sock;
+	fds[0].events = POLLIN;
+	fds[0].revents = 0;
+
+	poll_rc = poll(fds, 1, 0);
+	if (poll_rc < 0) {
+		fprintf(stderr, "%s: poll returned < 0, closing connection: %s\n", __FILE__, strerror(errno));
+		fflush(stderr);
+		goto fail;  /* also returns 0, which is correct */
+	} else if (poll_rc > 1) {
+		fprintf(stderr, "%s: poll returned > 1, treating like 1\n", __FILE__);
+		fflush(stderr);
+		return 1;  /* should never happen */
+	} else if (poll_rc == 0) {
+		return 0;  /* nothing to read */
+	} else {
+		return 1;  /* something to read */
+	}
+
+ fail:
+	if (client_sock >= 0) {
+		(void) close(client_sock);
+		client_sock = -1;
+	}
+	return 0;
+}
+
+void duk_trans_socket_read_flush_cb(void *udata) {
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	(void) udata;  /* not needed by the example */
+
+	/* Read flush: Duktape may not be making any more read calls at this
+	 * time.  If the transport maintains a receive window, it can use a
+	 * read flush as a signal to update the window status to the remote
+	 * peer.  A read flush is guaranteed to occur before Duktape stops
+	 * reading for a while; it may occur in other situations as well so
+	 * it's not a 100% reliable indication.
+	 */
+
+	/* This TCP transport requires no read flush handling so ignore.
+	 * You can also pass a NULL to duk_debugger_attach() and not
+	 * implement this callback at all.
+	 */
+}
+
+void duk_trans_socket_write_flush_cb(void *udata) {
+#if defined(DEBUG_PRINTS)
+	fprintf(stderr, "%s: udata=%p\n", __func__, (void *) udata);
+	fflush(stderr);
+#endif
+
+	(void) udata;  /* not needed by the example */
+
+	/* Write flush.  If the transport combines multiple writes
+	 * before actually sending, a write flush is an indication
+	 * to write out any pending bytes: Duktape may not be doing
+	 * any more writes on this occasion.
+	 */
+
+	/* This TCP transport requires no write flush handling so ignore.
+	 * You can also pass a NULL to duk_debugger_attach() and not
+	 * implement this callback at all.
+	 */
+	return;
+}

+ 14 - 0
src/third_party/duktape-1.3.0/examples/debug-trans-socket/duk_trans_socket.h

@@ -0,0 +1,14 @@
+#ifndef DUK_TRANS_SOCKET_H_INCLUDED
+#define DUK_TRANS_SOCKET_H_INCLUDED
+
+#include "duktape.h"
+
+void duk_trans_socket_init(void);
+void duk_trans_socket_waitconn(void);
+duk_size_t duk_trans_socket_read_cb(void *udata, char *buffer, duk_size_t length);
+duk_size_t duk_trans_socket_write_cb(void *udata, const char *buffer, duk_size_t length);
+duk_size_t duk_trans_socket_peek_cb(void *udata);
+void duk_trans_socket_read_flush_cb(void *udata);
+void duk_trans_socket_write_flush_cb(void *udata);
+
+#endif  /* DUK_TRANS_SOCKET_H_INCLUDED */

+ 5 - 0
src/third_party/duktape-1.3.0/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.3.0/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.3.0/examples/eval/README.rst

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

+ 48 - 0
src/third_party/duktape-1.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/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.3.0/examples/sandbox/README.rst

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

+ 252 - 0
src/third_party/duktape-1.3.0/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.3.0/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.

+ 3629 - 0
src/third_party/duktape-1.3.0/license.spdx

@@ -0,0 +1,3629 @@
+<?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="NukVOfZA85">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/c_eventloop.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA86"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA159">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/debug-trans-dvalue/duk_trans_dvalue.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA160"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA446">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>215f6fec820889330048f7f2c1b5a220eb963657</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA191">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA192"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA44">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>50a3349a079123b6bddf3db507df0dd9e877e246</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA51">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./debugger/static/webui.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA52"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA276">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5ebff36a2dd7cb495eed358c59670541c6c8be19</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA3">
+    <_3:created rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2015-09-12T02:15:22Z</_3:created>
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#CreationInfo"/>
+    <_3:licenseListVersion>1.20</_3:licenseListVersion>
+    <_3:creator>Organization: duktape.org</_3:creator>
+    <rdfs:comment></rdfs:comment>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA387">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_proxy.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA388"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA431">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./polyfills/duktape-isfastint.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA432"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA409">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_replacements.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA410"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA285">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_selftest.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA286"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA448">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>92ce3decf72b10b0023116ac727a752e8749aa90</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA112">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a8c0b54002a3a7d8c69d385e7fbcf4b70d1efc70</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA24">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3b8236810650f4e28bd84984b3c7e55029f241b0</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA121">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/guide/uppercase.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA122"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA5">
+    <_3:packageVerificationCodeValue>39d0d436fe36ae0901ab8ed9cbdaf379037760fb</_3:packageVerificationCodeValue>
+    <_3:packageVerificationCodeExcludedFile>./license.spdx</_3:packageVerificationCodeExcludedFile>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA430">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>089c395fca3cedceec09fd38d32d0c77dc8658f4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA217">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA218"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA93">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/eventloop/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA94"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA104">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6b98824e13a3d9536542b8da51d012a3d66ceec1</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA440">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6d5f56a1b76f9dcc9bb68d62ad0df958bd4d38ec</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA70">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ddbc206357dd4b97f3630b87bfdac148a5e8b190</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA54">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>03cad085177f1e776be90afceef1f2160e6c8bf4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA116">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c2d899e7f2343579f29ad3079fde44eec5d6a544</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA233">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hbuffer_alloc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA234"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA35">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./debugger/duk_debug.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA36"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA77">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/codepage-conv/duk_codepage_conv.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA78"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA123">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/guide/fib.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA124"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA373">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_executor.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA374"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA352">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>78e85afbf3394e8f79b30bdcbd479faf8781e25d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA316">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>afd3e5c9becf5feecaf57e4c5586b83da1ca61c3</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA249">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_pc2line.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA250"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA201">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_function.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA202"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA309">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_refcount.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA310"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA270">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>7b1e7e495bd7199d2e50c20e672c7fc01fcd3a42</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA365">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_duktape.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA366"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA213">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_compiler.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA214"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA198">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3d8403c0150e1633ddb87362bc3d85518e26cd6a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA308">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6da918cc81769eeeb7c2fe20b549aebf744f175a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA205">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA206"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA94">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>64566ae0bdc1c3e1017604b6b45d515c30d976eb</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA132">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>881f1b114c9fbba139044ddcbbc5398243185d10</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA6">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#SpdxDocument"/>
+    <_3:describesPackage rdf:nodeID="NukVOfZA4"/>
+    <_3:specVersion>SPDX-1.2</_3:specVersion>
+    <_3:dataLicense rdf:resource="http://spdx.org/licenses/CC0-1.0"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA85"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA159"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA189"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA269"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA447"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA403"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA191"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA255"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA61"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA267"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA23"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA179"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA271"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA197"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA367"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA365"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA425"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA351"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA317"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA211"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA207"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA431"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA331"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA33"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA285"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA371"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA423"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA199"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA163"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA81"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA291"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA25"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA97"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA341"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA339"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA217"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA93"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA175"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA193"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA117"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA377"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA69"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA75"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA21"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA111"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA63"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA287"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA239"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA147"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA233"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA89"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA181"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA77"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA79"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA123"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA373"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA319"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA131"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA137"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA249"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA201"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA437"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA417"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA309"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA393"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA157"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA241"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA213"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA419"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA101"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA235"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA205"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA143"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA363"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA221"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA289"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA135"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA109"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA35"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA439"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA399"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA411"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA307"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA169"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA203"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA39"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA187"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA103"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA409"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA343"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA231"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA389"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA379"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA253"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA321"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA243"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA167"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA311"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA275"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA127"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA29"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA429"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA257"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA325"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA435"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA337"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA259"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA381"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA407"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA177"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA449"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA53"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA395"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA209"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA27"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA397"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA237"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA335"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA139"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA41"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA171"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA7"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA387"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA83"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA421"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA327"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA347"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA277"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA279"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA59"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA185"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA329"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA427"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA273"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA361"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA345"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA223"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA375"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA445"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA15"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA359"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA45"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA215"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA183"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA369"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA265"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA305"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA51"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA113"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA13"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA43"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA133"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA383"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA251"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA55"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA295"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA401"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA433"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA161"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA299"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA95"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA107"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA227"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA323"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA333"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA105"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA443"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA153"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA141"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA353"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA9"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA281"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA11"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA385"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA229"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA297"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA405"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA151"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA165"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA67"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA115"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA65"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA49"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA263"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA125"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA91"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA19"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA283"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA349"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA173"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA355"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA303"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA441"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA357"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA195"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA225"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA57"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA121"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA453"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA415"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA261"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA301"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA391"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA17"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA245"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA71"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA129"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA293"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA31"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA119"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA219"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA451"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA145"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA73"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA37"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA87"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA247"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA99"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA47"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA413"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA155"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA313"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA315"/>
+    <_3:referencesFile rdf:nodeID="NukVOfZA149"/>
+    <rdfs:comment>SPDX license for Duktape 1.3.0</rdfs:comment>
+    <_3:creationInfo rdf:nodeID="NukVOfZA3"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA386">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c14747594add785dd952855071e51077f5152bad</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA48">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>cd025a84635e6a1353f756cf9c74c27bfd36862d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA411">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_number.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA412"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA187">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_numconv.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA188"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA34">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f88d68880f451267e7e2eca4b6c4191e8c3fe011</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA434">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>93573df8348a41adb790f59e39bf99d9a7bf3a3d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA64">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>75c61dd080cd643b7449f673105b7b7e4bdda0f5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA321">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_json.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA322"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA243">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_call.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA244"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA328">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>de9650befceae510999c0e852a79f994d74fc531</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA311">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_markandsweep.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA312"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA257">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_bitdecoder.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA258"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA325">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hbuffer.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA326"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA168">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ce19fb1254e02c8ff3ed8e0737522d6af7b977c5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA110">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>82314b509ee3b15b393fefe747c8e0169ab39aaa</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA395">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_ops.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA396"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA182">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a3d2ce3d28d6bb5afd29e35ade770a8ae5f45c3f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA66">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a8f8cf615ef79337a83eb791477dc9ed2c22822c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA78">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>7e2674dd72227576375a80f6ddbb11320f5b987a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA274">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>37a995b627b3a85cecc2a5851537589d4da3bf63</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA14">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>44c9219558aba26dc69982a9f432028290707c36</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA389">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_initjs_min.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA390"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA329">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_selftest.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA330"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA364">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>59d3c2d44ed8707fa6c907a7387ffce611d89e44</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA345">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_regexp_compiler.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA346"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA324">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>79f806448cbd4724bf60e0723414b391686be098</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA391">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_string.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA392"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA265">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA266"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA305">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_lexer.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA306"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA113">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/eval/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA114"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA318">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>11ecfff4142b35382d0aaf80ee6c04ae3dfd0b4c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA43">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/package.json</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA44"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA295">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_internal.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA296"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA370">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>47e1001460004f53dfc350355e02bf56f18b0398</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA107">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/server-socket-test.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA108"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA406">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>43a0dfbf1cb06dbfe3a37959ad1b93bc036f78cb</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA105">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/client-socket-test.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA106"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA190">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b5f54e8a18d5dc9a791cb36976a7d2345d26b549</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA9">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./duk_build_meta.json</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA10"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA11">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA12"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA400">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a9c998dbedde09cc435eec0ac1a3a428090b37a9</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA297">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hbufferobject_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA298"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA195">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_debug.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA196"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA67">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/alloc-hybrid/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA68"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA334">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>8d307ae071694f3d2242578c7d88bcae5c2ef7de</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA349">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_hashstring.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA350"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA173">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/alloc-logging/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA174"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA426">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>e5a5f0db067ec56c6d2f7356f412222a8884dc92</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA441">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./config/genconfig_metadata.tar.gz</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA442"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA312">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d68dbb37b698f98f51a9136d4026b2ac0a2911c4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA100">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6a1500fea27ea278c4f0c64d908e16cc60df684b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA4">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Package"/>
+    <_3:name>Duktape</_3:name>
+    <_3:originator>Organization: duktape.org</_3:originator>
+    <_3:versionInfo>1.3.0</_3:versionInfo>
+    <_3:packageVerificationCode rdf:nodeID="NukVOfZA5"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:summary>Duktape Ecmascript interpreter</_3:summary>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:downloadLocation rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://duktape.org/duktape-1.3.0.tar.xz</_3:downloadLocation>
+    <_3:homePage rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://duktape.org/</_3:homePage>
+    <_3:licenseDeclared rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseComments>Duktape is copyrighted by its authors and licensed under the MIT license.  MurmurHash2 is used internally, it is also under the MIT license. Duktape module loader is based on the CommonJS module loading specification (without sharing any code), CommonJS is under the MIT license.</_3:licenseComments>
+    <_3:supplier>Organization: duktape.org</_3:supplier>
+    <_3:sourceInfo>Official duktape.org release built from GitHub repo https://github.com/svaarala/duktape.</_3:sourceInfo>
+    <_3:licenseInfoFromFiles rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:packageFileName>duktape-1.3.0.tar.xz</_3:packageFileName>
+    <_3:hasFile rdf:nodeID="NukVOfZA85"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA159"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA189"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA269"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA447"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA403"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA191"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA255"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA61"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA267"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA23"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA179"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA271"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA197"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA367"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA365"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA425"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA351"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA317"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA211"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA207"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA431"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA331"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA33"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA285"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA371"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA423"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA199"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA163"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA81"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA291"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA25"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA97"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA341"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA339"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA217"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA93"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA175"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA193"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA117"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA377"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA69"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA75"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA21"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA111"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA63"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA287"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA239"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA147"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA233"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA89"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA181"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA77"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA79"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA123"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA373"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA319"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA131"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA137"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA249"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA201"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA437"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA417"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA309"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA393"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA157"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA241"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA213"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA419"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA101"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA235"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA205"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA143"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA363"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA221"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA289"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA135"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA109"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA35"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA439"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA399"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA411"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA307"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA169"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA203"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA39"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA187"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA103"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA409"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA343"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA231"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA389"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA379"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA253"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA321"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA243"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA167"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA311"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA275"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA127"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA29"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA429"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA257"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA325"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA435"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA337"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA259"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA381"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA407"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA177"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA449"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA53"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA395"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA209"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA27"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA397"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA237"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA335"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA139"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA41"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA171"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA7"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA387"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA83"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA421"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA327"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA347"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA277"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA279"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA59"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA185"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA329"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA427"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA273"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA361"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA345"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA223"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA375"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA445"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA15"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA359"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA45"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA215"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA183"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA369"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA265"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA305"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA51"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA113"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA13"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA43"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA133"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA383"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA251"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA55"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA295"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA401"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA433"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA161"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA299"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA95"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA107"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA227"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA323"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA333"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA105"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA443"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA153"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA141"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA353"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA9"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA281"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA11"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA385"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA229"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA297"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA405"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA151"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA165"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA67"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA115"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA65"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA49"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA263"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA125"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA91"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA19"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA283"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA349"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA173"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA355"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA303"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA441"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA357"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA195"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA225"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA57"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA121"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA453"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA415"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA261"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA301"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA391"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA17"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA245"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA71"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA129"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA293"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA31"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA119"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA219"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA451"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA145"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA73"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA37"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA87"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA247"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA99"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA47"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA413"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA155"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA313"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA315"/>
+    <_3:hasFile rdf:nodeID="NukVOfZA149"/>
+    <_3:description>Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint</_3:description>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA232">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2cdc31948853f9f0bf0d5f726b6034c508ee9d67</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA239">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_forwdecl.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA240"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA152">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>e2a167fd8048cbd7c85fd62da70749b2a0109b2a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA453">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src/duktape.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA454"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA115">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eval/eval.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA116"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA330">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a8e7b9b9bed773ecc7e08f4b73716dad741fd50b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA314">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4ee4843558692861cb91a6c6906539795b639091</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA83">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/main.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA84"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA31">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.eventloop</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA32"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA40">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d84a903a426cf3a158072565161c35240a1c68e5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA124">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>206ffd13c06208e85baba2b257fe3ddebb56a6c2</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA382">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6b150b9183cc8453536713de0d1e79adc21a3fee</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA99">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/curses-timers.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA100"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA47">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/duk_opcodes.yaml</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA48"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA388">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>bd2f85dccd23b76b9cf9900b8b2b86f0bf97421b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA8">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>e4d3286030d5ef1e74dd07a5b2efa37cd907697e</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA142">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d48fe743ca18b8b3205d6443a08463d6b0334153</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA20">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>61043b4a6f3cf86375ea6e34ebf83b550a1935b2</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA425">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./polyfills/object-prototype-definegetter.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA426"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA236">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>063133679b6d072efc1c27f3a510101744ffde0c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA380">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ca663612967cb12b33d666180d7bb3008314ca7a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA23">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.sandbox</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA24"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA397">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_tval.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA398"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA351">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA352"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA258">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>786369a33cccbadc3d2efba613a43fdd638971fc</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA228">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f5251445a782e4bfac8af043f24ecbac740f67eb</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA420">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>1bce4dadb408a2a6a77b366f0ecfc18398cbb722</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA374">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f65888efe272f584113d4df273cc6e7a5c5a43dd</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA204">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>df7b9fe732c2bc300d096c06d90bbdc71fada213</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA199">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_global.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA200"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA25">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./AUTHORS.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA26"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA97">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/ecma_eventloop.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA98"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA378">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b54cd58e7947b2899eb8662d2cdaf022dd680ea6</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA26">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ea1ee74bace7e1958d0049c1035b3832ef951e82</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA238">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6d0092ec677f2d4aa5c91cf9f71d8aca5171c8e2</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA69">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/alloc-hybrid/duk_alloc_hybrid.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA70"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA354">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>41f24f22ab9039c1f9a548fb75c9639453380065</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA60">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ea413ed7d47cf27c6f3ffe25956b1370b653c200</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA106">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d869c0f8797a659124b3ba31c75f494b15bea5e6</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA225">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_call.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA226"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA147">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/debug-trans-socket/duk_trans_socket.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA148"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA181">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_builtins.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA182"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA242">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2c811905f5b8781c8b70d099687773a8d20ce082</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA335">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_config.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA336"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA72">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>9bb6ca1fa3ad4c593b000b2de5aca013b95adda0</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA184">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b298f68a888cec4efea00f221053645a59748c18</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA130">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4e5a54de08355669dc98b5d4ad379384b33da4e5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA442">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2878666c896a9a9a4dddefd943c0ddf3a09310a4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA86">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>07a167411a356aebfbe987353846a9c711998f20</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA393">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_thread.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA394"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA157">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/debug-trans-dvalue/Makefile</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA158"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA356">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>27813a75f3f27a0dcdf51e269582a97679585827</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA134">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>9a31edd2028d39d24aa9bfdbd2b70ce2a64b8493</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA403">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_stack.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA404"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA189">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_jmpbuf.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA190"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA148">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5a72a639353c2f9e3bfb1c369246775ecd6f005e</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA221">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_unicode.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA222"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA188">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a2c79a55a60f73e1a1567b96d584399571180ef5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA56">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>09ee87b3ae8afe8b7c2295127835b05b00603b25</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA135">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/alloc-torture/duk_alloc_torture.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA136"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA296">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6b097ba4583a27d31c21b60cb15770804dd1ba9d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA298">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>29be453689679c9bab977c0b333a4a224d9f02e6</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA439">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./config/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA440"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA307">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debug_vsnprintf.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA308"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA169">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/alloc-logging/log2gnuplot.py</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA170"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA384">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5d56f0bab3e87abdca8da4d6e8580cb9132fd697</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA162">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5f3b6cd81be97aa687fe8b47751e68b5561d7c1b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA366">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b6cf7cd6cdf526aa3cf60144c6a9569e6d112f36</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA167">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/alloc-logging/duk_alloc_logging.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA168"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA126">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>7edf7600e1a6f09d1e4a0e2f9be418b59fff7c52</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA220">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>16a4c10bea273a74018fa0a7a8889b7b43a3119b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA376">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>0053a77d6c3562af6d2238f096f3a9bd4b5a834f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA59">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/coffee/hello.coffee</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA60"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA29">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.eval</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA30"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA310">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b2872f0cbb3cbe10184bbc3a95b1d7c365b8ed32</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA340">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a5afcd26ab65a29d95a6e33bf0f33645ee4fd91b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA435">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./polyfills/performance-now.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA436"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA396">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>32a98d7fe78d83f08173234229f862698fce2090</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA407">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duktape.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA408"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA38">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>02b01faf5220448b3d678abba34a0a9be96d71ca</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA368">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ff17cbc9cb84b86f83bb104a247e5c265a9fe5b5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA27">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.dukdebug</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA28"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA129">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/guide/prime.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA130"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA264">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>14ec83aeef66a38c6a4c48a175a544f66d319413</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA421">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_pointer.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA422"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA277">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_unicode_tables.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA278"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA114">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>29b1960bc40607c2cf496465068611b2ffc4de87</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA418">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b398df12e0b18a0e3edca6c4d55f7575cea9a76a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA192">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f437b6a49e9ad85f1bed504b9d7724358eb37ad8</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA401">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_var.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA402"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA375">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_date_windows.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA376"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA15">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./mandel.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA16"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA359">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_alloc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA360"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA183">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_regexp_executor.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA184"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA383">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debugger.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA384"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA251">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_stringtable.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA252"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA154">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>11f16b15a8e52598a078b88a8d0440ff61dd5ba2</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA290">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>1eb3bb219637be52abe8a154551ec76bfc5ecf31</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA333">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hthread_alloc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA334"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA443">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./extras/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA444"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA146">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>58c701ade28ee5a475dede84a6e771893e3fc40f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA353">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_array.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA354"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA360">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6961515d6681b7dfb59d2d080b87cdeb2a673025</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA281">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_replacements.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA282"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA256">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>89ce4d46fcef5a35b3b6652d79ebe556b121d2a8</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA229">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_bytecode.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA230"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA405">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_hashbytes.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA406"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA49">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/static/style.css</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA50"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA19">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.coffee</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA20"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA449">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src/duk_config.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA450"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA248">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3948c3f17d6863157361cb817b6bc7bf7799122f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA357">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_compile.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA358"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA57">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/coffee/mandel.coffee</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA58"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA415">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debug_fixedbuffer.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA416"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA245">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_date.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA246"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA210">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4d3ab8c2d41261b0cae627db9d536d26f72b5f8e</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA185">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_bufwriter.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA186"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA222">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4588ca1842f93e72254f9b428d6d07ad22b57163</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA145">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/cmdline/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA146"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA87">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/ncurses.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA88"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA404">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d90697f65158589fb137e9a48cbf288bde2ef230</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA155">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/debug-trans-dvalue/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA156"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA303">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hcompiledfunction.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA304"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA300">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a9db75839022e7dcf7e691ada7480a9b7c2715d0</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA82">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3d700df1f765c39fc63bfd4e31a9d7da8d15c543</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA269">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hthread_builtins.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA270"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA61">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/coffee/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA62"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA84">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5f89525f75f61dd8c89e010cb62bc071d6d13170</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA278">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>7b236da6f48b6f6aef43e6c959b43edaa8120ff4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA408">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ad475950dc26e62ba57f5bfa266687681b09e10f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA32">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>fa85ee3394206d18c611b837e700257ba8336250</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA423">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debug_macros.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA424"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA250">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>8521b45dcbc72d66c2b4e3f0db9e1dbfb75b45f5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA317">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_memory.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA318"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA207">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hstring_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA208"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA224">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2c2b647e4cf2c94e91f5193987a01a029bf01690</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA33">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.jxpretty</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA34"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA371">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_regexp.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA372"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA88">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>484fb41d516abcbe8c97af5aa80b76c67dbfb0cb</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA390">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>7108fbe42728e2fe1c2448b119a6a1f52568ce53</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA81">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/jxpretty/jxpretty.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA82"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA230">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3c10dd228daad9be3ea381c2f8b1e07e524fae6f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA341">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_boolean.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA342"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA30">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>fb4f806e7282dd3cb2df04e228672d8b0b1b8eb4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA315">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_error_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA316"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA175">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_error.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA176"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA193">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_enum.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA194"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA117">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/guide/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA118"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA372">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2e9dca0919a92c68ed30593292b3fe7140480062</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA377">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_strings.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA378"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA75">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/codepage-conv/test.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA76"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA21">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.codepage</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA22"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA111">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/dummy-date-provider/dummy_date_provider.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA112"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA437">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./config/genconfig.py</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA438"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA344">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>dfaa38c7372de482fd12634e4a3507f46e467e0f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA338">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>982e40839854be361e3b57b5c07ef4f710ab749b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA362">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>0811e545a133c3a62672e239624a0c1f11478b8d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA202">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>0fd79121cfa729c2dd3e47632ec46204609013ef</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA79">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/jxpretty/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA80"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA108">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f9072f5c361c86887b57ce662b3cd7211b4ce346</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA131">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/alloc-torture/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA132"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA444">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d49c1cdb51b3a4fdd823c13831617a1f0a93edd1</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA419">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_stringcache.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA420"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA417">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_alloc_default.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA418"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA143">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/cmdline/duk_cmdline.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA144"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA144">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>506914e460ff9d7536f10efef54b24b83c390410</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA363">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debugger.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA364"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA289">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_heap.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA290"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA50">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>1c45360bd50cff6c2c25087d52136b390179e8fc</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA302">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>bf522799f089bf27e5ef2196b73c7e3d294ee5ba</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA399">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_object.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA400"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA103">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/poll.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA104"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA379">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_buffer.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA380"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA436">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>11a7a5b6b1557adeca8a9def51cb44282f24c853</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA253">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_error_longjmp.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA254"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA120">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>8aa63b553757fe1229638e978b540d7116b70274</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA414">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>23b6b54a8a35fbec735ffb332f4100a7f00557be</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA227">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_lexer.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA228"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA416">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>61c7f89aa56094410418e766c89c1975db021daa</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA268">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>bf5a69136d03c3a573822dc1fe6e595a92c5d9b5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA424">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4d3413b7b28775afc4a5be95e91208fab25b02f3</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA337">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_thrower.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA338"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA259">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_internal.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA260"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA381">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_numconv.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA382"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA454">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>76fafefbb89d1d3561a44bf6c253415ab86633f7</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA177">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_error_throw.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA178"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA53">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/static/index.html</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA54"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA46">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d8fe87c8e0d17bd6977bbc34d562e4b79c06f1a3</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA240">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3a4934f863facf317ffcc1a6ce1d8f17ac658f38</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA7">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./LICENSE.txt</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA8"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA90">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>24a2346fa389c2294cc0e96427e0bd206dac10b9</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA279">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_tinyrandom.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA280"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA58">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4239a907720cf3620bd0b03eb43981e7182e305a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA292">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>578b63fa72c87e894a47a9f82102ecee895f932f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA350">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>628eded8d5c2a48cb32a615bb7f11f164c949540</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA385">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heaphdr.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA386"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA327">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_bytecode.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA328"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA172">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>742635fda10ef9775864077e647b59442768a69c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA451">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src/duktape.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA452"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA266">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>533dd2148cf54628be701ce5bbbda88c443244fd</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA133">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/alloc-torture/duk_alloc_torture.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA134"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA170">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>439430cb950965d418b5bcb4ca36047f77a26a7c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA358">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>925915ad11fea8da4582dbd9bc9e8b5ffbb8994d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA299">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_compiler.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA300"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA95">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/fileio.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA96"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA18">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c2a8bb08084e49f0e12d31562a90f72046761028</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA234">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>bce447cad4609861c4db6edbfe38bf2fa150e651</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA422">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2321e0a68bf940f8346d00adda9e4a58fa51f608</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA320">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>839ade6f7b93fd0fc604e3e0934568331eedd648</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA96">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a9206a7b46f8d8319b798475650217f494fa76ab</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA65">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/alloc-hybrid/duk_alloc_hybrid.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA66"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA219">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_strings.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA220"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA263">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_math.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA264"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA428">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>0125ebcabe62cef4923e75527d3128e8c48cdf1f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA176">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>bfbf3b8ea996451740a7ad2d8d1376feca4ca382</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA355">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_codec.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA356"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA429">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./polyfills/object-prototype-definesetter.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA430"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA163">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/sandbox/sandbox.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA164"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA89">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/socket.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA90"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA301">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_buffer.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA302"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA291">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hthread_stacks.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA292"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA17">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.cmdline</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA18"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA98">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4db4ca2d7ce3f076fd195372d53e8bc5714d2597</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA196">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>813eed354904f72d97568c814fbcf5fffbb62d12</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA171">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/alloc-logging/duk_alloc_logging.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA172"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA293">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hnativefunction.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA294"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA119">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/guide/processlines.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA120"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA194">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c000aebe8b6794338529fdf6e02c0cfdcf4d2dfc</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA294">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2c508fbc7eb127f6793cfe62bf947879668983a4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA37">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA38"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA452">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b4c9666ce152c9a98bf965aae4ef4fe0b36b2130</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA180">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b4d00dadc78f1ac25d87d8d7a48fd67161235d4f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA413">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debug_heap.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA414"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA313">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js_var.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA314"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA149">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/debug-trans-socket/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA150"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA339">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_debug.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA340"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA272">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6988aac432dcc185c2967732e21947ea0696377f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA447">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./licenses/commonjs.txt</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA448"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA52">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>878e91bed3a8756c70aaa43bb1566040fe6e42f0</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA255">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hstring.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA256"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA267">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_json.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA268"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA118">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>e023af5c2fb4b1efab74a230c552f1eb1b37fc10</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA284">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>e44b8b092afcfa97e693eb3e0be97d41f8aff301</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA432">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2eadae5af69aec5e3336b6a869fe64771d4db080</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA212">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>935644ce5c2bcd1f9b725c742a91dd34ec7c7fc3</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA392">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>13d0e469fd05cef5066b33ad1310658e4cf5c7c8</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA150">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f1dee4b05f535519fbf3662469c2ce810b6e2545</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA331">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_tval.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA332"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA260">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>635d4642c9ecd5fd9a5346bf9f0e38db102b09b6</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA208">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>7502f77b459c82f4e9a45ecdde05125d79153bdf</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA10">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>042bfc66d9b0f01ce8075818959c9a72c35b4bb4</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA427">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./polyfills/object-assign.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA428"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA348">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5e8812e8226d2ec0387af6e2ce9565755e274164</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA216">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>56a4e5fbd50d1b9917625a0dfcf6e2619b034786</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA174">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>8015d14ffbc7a4a4b93d654f093aa48ec17fce4e</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA304">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>73ff75213f392b6125c68ab6b430176dfad71269</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA342">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a20231719c1f9b97ea38fbc42dd8af1e21d74879</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA367">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap_memory.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA368"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA398">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>949e147e9b5e284590449d0e8f74427c8c12f00f</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA209">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hthread_misc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA210"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA28">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c1036bb5992816ffb09e8b2ee24f082a881326e9</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA211">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_js.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA212"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA63">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/coffee/globals.coffee</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA64"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA287">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_error_augment.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA288"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA319">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hthread.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA320"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA137">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/hello/hello.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA138"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA62">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>af6b0cd61c02efa575b9106682606297d26f013b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA450">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>57f519aabc8730f19d197bd00fe7e4f592063ddf</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA433">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./polyfills/console-minimal.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA434"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA332">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>1e6c5c99fdcef26a561724faa703bf9c53c73bca</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA241">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_string.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA242"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA261">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_logging.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA262"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA101">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/basic-test.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA102"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA235">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_regexp.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA236"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA402">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>12da70c807ea25465e5e0191784203ff6a1c7d0c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA140">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>10c24a17c2f5f82d8c1a8fab8673c0c9075c1817</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA109">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/dummy-date-provider/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA110"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA394">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b2f66f393c178e011c068b230f17ef8a48b4ee29</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA231">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_heap.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA232"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA306">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>0aee8a99ab7468ae7254d0b19f898a7c67f24c4d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA164">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>22046b9dfc552ed692193d1bf5e3d0e182111ae5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA203">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_date_unix.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA204"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA68">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>149fd21526c90d52b22e77b297f76e6da3e656ff</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA39">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/Makefile</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA40"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA343">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_error_macros.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA344"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA76">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c8ae046bda2c920b5d807dfa68c8159b655b0873</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA214">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3e4c09bd49dbe5d8509da6f2387eadfca945126c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA178">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b381ea15009eb8140c0789203345cdcc2c6c1cd6</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA127">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/guide/primecheck.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA128"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA412">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f79f6933571dcdd7108447f6e8e86f4735b30caf</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA346">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5583c0190c2038be60ba2de07d155d5077defb03</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA71">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/codepage-conv/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA72"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA288">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a1b146201fb105044a9922781e22d14bcbd5584c</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA166">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>5d593ae6316ed7a3ea6e7ed0a47267745d79d12d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA226">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>136f423bdc27f3effc1e45c44327c1d3ef82f0d9</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA218">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>bf80565339b6d9eb92f7e8b35420317cf00392f1</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA237">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_alloc.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA238"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA36">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>36b07bc32cf613c091d5e4261cbe44b0556704fd</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA74">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>01138dd2786346a159c06e43f094d07f002df881</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA139">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/hello/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA140"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA252">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>edc510f4b2921d24eb9bc37ee0dd4a3d42743083</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA41">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/duk_debugcommands.yaml</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA42"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA102">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>88ab1d060886393d94b6fb7c6054a0189117340b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA347">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hbuffer_ops.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA348"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA273">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_protos.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA274"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA361">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_bitencoder.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA362"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA223">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_props.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA224"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA445">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./licenses/murmurhash2.txt</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA446"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA45">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./debugger/duk_classnames.yaml</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA46"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA22">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f396c6aec456b183ef77e33da1dfffc89c417056</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA156">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>23575db7cd88e42c0c3fc1630f44bf608fcec76d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA246">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>b0916311103fdea3fd5bbf76a99748a3d21a5486</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA158">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>1c40a52fd54baf7ac334fce4829892d5d951401a</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA138">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>83b27494e6b257ab09828b0a4a1cf907686778a5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA13">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./Makefile.hello</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA14"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA12">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>71d2f9df7bf793f80f3cd6080c986a437f9b2991</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA55">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA56"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA42">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>c8d7674f8215d515779d2cfaf61105c4d2fd5eb5</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA80">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>8c5ee5b508a23ac5089a7e6c76593b6678965869</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA161">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/debug-trans-dvalue/test.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA162"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA136">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d45e3fc443887261ce432a807aaebd2a1812264e</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA336">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>57f519aabc8730f19d197bd00fe7e4f592063ddf</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA275">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_bi_logger.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA276"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA153">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/debug-trans-dvalue/duk_trans_dvalue.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA154"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA141">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/cmdline/duk_cmdline_ajduk.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA142"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA244">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ba20a4d987de1eef311c99f21db6621cb4b1a5d1</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA369">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hbufferobject.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA370"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA323">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_api_object.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA324"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA151">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/debug-trans-socket/duk_trans_socket.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA152"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA165">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_other"/>
+    <_3:fileName>./examples/sandbox/README.rst</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA166"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA215">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_finalizer.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA216"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA125">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/guide/process.js</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA126"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA91">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/eventloop/c_eventloop.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA92"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA179">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_unicode_support.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA180"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA283">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_util_hashprime.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA284"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA322">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>37e22b43351b7f0518b7fbb9e5c109d7a53a31e7</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA262">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>fb9c2ff459fd84b4587f846fbd36219cf8f06931</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA280">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d529a6faac560def1e5b2cdb991713a6d70b0e26</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA16">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>f3ed5c785b60b0f39a74cc3f5b73b0c6e24287c3</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA286">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>34b0dc439c1aeb920a1db0ac0ed20ee189069ea1</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA326">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>111a7b97b46f038bd7f0f260ef5c9ff66c057217</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA271">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_hobject_class.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA272"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA128">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>ed3bd07dbd103d285277ab38c4b4a7dd4a4b654b</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA247">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_builtins.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA248"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA410">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6fec920096ab278342b4832aac85e480f47c3b69</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA206">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>767b33200578243befc9b2b6b4a579dc3784f748</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA282">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>84b3f74e55ed4d76634e144d668601480573b369</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA73">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./examples/codepage-conv/duk_codepage_conv.c</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA74"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA254">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>6f12665affb325d53ab11c0e40418b2326c1ac17</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA186">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>2b7443b734ad4f6e53e2f35e5aff74464410a680</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA197">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#File"/>
+    <_3:licenseInfoInFile rdf:resource="http://spdx.org/rdf/terms#none"/>
+    <_3:licenseConcluded rdf:resource="http://spdx.org/licenses/MIT"/>
+    <_3:copyrightText>Copyright 2013-2014 Duktape authors (see AUTHORS.rst in the Duktape distributable)</_3:copyrightText>
+    <_3:fileType rdf:resource="http://spdx.org/rdf/terms#fileType_source"/>
+    <_3:fileName>./src-separate/duk_error.h</_3:fileName>
+    <_3:checksum rdf:nodeID="NukVOfZA198"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA438">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>a2896c39c83a21a2f79d0c4babd5012d85873116</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA200">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>3c8a488f2b4195d33379874172ae6d8b74beaa58</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA92">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>d535c4e27319a5db6026553a801e8a5ef0e6fe88</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA122">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>4baffeb2aa785bdc1065eb9ddb8c64c8a028655d</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+  <rdf:Description rdf:nodeID="NukVOfZA160">
+    <rdf:type rdf:resource="http://spdx.org/rdf/terms#Checksum"/>
+    <_3:checksumValue>0783cf4f48c9baf2b3820a36ab276b01e2102600</_3:checksumValue>
+    <_3:algorithm rdf:resource="http://spdx.org/rdf/terms#checksumAlgorithm_sha1"/>
+  </rdf:Description>
+</rdf:RDF>

+ 2 - 0
src/third_party/duktape-1.3.0/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/.

+ 21 - 0
src/third_party/duktape-1.3.0/licenses/murmurhash2.txt

@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) <year> <copyright holders>
+
+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.

+ 53 - 0
src/third_party/duktape-1.3.0/mandel.js

@@ -0,0 +1,53 @@
+/*
+ *  Mandelbrot example:
+ *
+ *    $ ./duk mandel.js
+ *    [...]
+ */
+
+function mandel() {
+    var w = 76, h = 28, iter = 100;
+    var i, j, k, c;
+    var x0, y0, xx, yy, xx2, yy2;
+    var line;
+
+    for (i = 0; i < h; i++) {
+        y0 = (i / h) * 2.5 - 1.25;
+
+        for (j = 0, line = []; j < w; j++) {
+            x0 = (j / w) * 3.0 - 2.0;
+
+            for (k = 0, xx = 0, yy = 0, c = '#'; k < iter; k++) {
+                /* z -> z^2 + c
+                 *   -> (xx+i*yy)^2 + (x0+i*y0)
+                 *   -> xx*xx+i*2*xx*yy-yy*yy + x0 + i*y0
+                 *   -> (xx*xx - yy*yy + x0) + i*(2*xx*yy + y0)
+                 */
+
+                xx2 = xx*xx; yy2 = yy*yy;
+
+                if (xx2 + yy2 < 4.0) {
+                    yy = 2*xx*yy + y0;
+                    xx = xx2 - yy2 + x0;
+                } else {
+                    /* xx^2 + yy^2 >= 4.0 */
+                    if (k < 3) { c = '.'; }
+                    else if (k < 5) { c = ','; }
+                    else if (k < 10) { c = '-'; }
+                    else { c = '='; }
+                    break;
+                }
+            }
+
+            line.push(c);
+        }
+
+        print(line.join(''));
+    }
+}
+
+try {
+    mandel();
+} catch (e) {
+    print(e.stack || e);
+}

+ 20 - 0
src/third_party/duktape-1.3.0/polyfills/console-minimal.js

@@ -0,0 +1,20 @@
+/*
+ *  Minimal console.log() polyfill
+ */
+
+if (typeof console === 'undefined') {
+    Object.defineProperty(this, 'console', {
+        value: {}, writable: true, enumerable: false, configurable: true
+    });
+}
+if (typeof console.log === 'undefined') {
+    (function () {
+        var origPrint = print;  // capture in closure in case changed later
+        Object.defineProperty(this.console, 'log', {
+            value: function () {
+                var strArgs = Array.prototype.map.call(arguments, function (v) { return String(v); });
+                origPrint(Array.prototype.join.call(strArgs, ' '));
+            }, writable: true, enumerable: false, configurable: true
+        });
+    })();
+}

+ 38 - 0
src/third_party/duktape-1.3.0/polyfills/duktape-isfastint.js

@@ -0,0 +1,38 @@
+/*
+ *  Helper to check if a number is internally represented as a fastint:
+ *
+ *    if (Duktape.isFastint(x)) {
+ *        print('fastint');
+ *    } else {
+ *        print('not a fastint (or not a number)');
+ *    }
+ *
+ *  NOTE: This helper depends on the internal tag numbering (defined in
+ *  duk_tval.h) which is both version specific and depends on whether
+ *  duk_tval is packed or not.
+ */
+
+if (typeof Duktape === 'object') {
+    if (typeof Duktape.fastintTag === 'undefined') {
+        Object.defineProperty(Duktape, 'fastintTag', {
+            /* Tag number depends on duk_tval packing. */
+            value: (Duktape.info(true)[1] === 0xfff4) ?
+                    0xfff1 /* tag for packed duk_tval */ :
+                    1 /* tag for unpacked duk_tval */,
+            writable: false,
+            enumerable: false,
+            configurable: true
+        });
+    }
+    if (typeof Duktape.isFastint === 'undefined') {
+        Object.defineProperty(Duktape, 'isFastint', {
+            value: function (v) {
+                return Duktape.info(v)[0] === 4 &&                 /* public type is DUK_TYPE_NUMBER */
+                       Duktape.info(v)[1] === Duktape.fastintTag;  /* internal tag is fastint */
+            },
+            writable: false,
+            enumerable: false,
+            configurable: true
+        });
+    }
+}

+ 45 - 0
src/third_party/duktape-1.3.0/polyfills/object-assign.js

@@ -0,0 +1,45 @@
+/*
+ *  Object.assign(), described in E6 Section 19.1.2.1
+ *
+ *  http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.assign
+ */
+
+if (typeof Object.assign === 'undefined') {
+   Object.defineProperty(Object, 'assign', {
+       value: function (target) {
+           var i, n, j, m, k;
+           var source, keys;
+           var gotError;
+           var pendingError;
+
+           if (target == null) {
+               throw new Exception('target null or undefined');
+           }
+
+           for (i = 1, n = arguments.length; i < n; i++) {
+               source = arguments[i];
+               if (source == null) {
+                   continue;  // null or undefined
+               }
+               source = Object(source);
+               keys = Object.keys(source);  // enumerable own keys
+
+               for (j = 0, m = keys.length; j < m; j++) {
+                   k = keys[j];
+                   try {
+                       target[k] = source[k];
+                   } catch (e) {
+                       if (!gotError) {
+                           gotError = true;
+                           pendingError = e;
+                       }
+                   }
+               }
+           }
+
+           if (gotError) {
+               throw pendingError;
+           }
+       }, writable: true, enumerable: false, configurable: true
+   });
+}

+ 11 - 0
src/third_party/duktape-1.3.0/polyfills/object-prototype-definegetter.js

@@ -0,0 +1,11 @@
+/*
+ *  Object.prototype.__defineGetter__ polyfill
+ */
+
+if (typeof Object.prototype.__defineGetter__ === 'undefined') {
+    Object.defineProperty(Object.prototype, '__defineGetter__', {
+        value: function (n, f) {
+            Object.defineProperty(this, n, { enumerable: true, configurable: true, get: f });
+        }, writable: true, enumerable: false, configurable: true
+    });
+}

部分文件因文件數量過多而無法顯示