duktape: upgrade to 2.6.0, closes #2504

Mon, 19 Oct 2020 10:43:25 +0200

author
David Demelier <markand@malikania.fr>
date
Mon, 19 Oct 2020 10:43:25 +0200
changeset 88
b561f5e85bdd
parent 87
00ef6d3553bd
child 89
cdd2ea1a6dd9

duktape: upgrade to 2.6.0, closes #2504

VERSION.libduktape.txt file | annotate | diff | comparison | revisions
libduktape/duk_config.h file | annotate | diff | comparison | revisions
libduktape/duktape.cpp file | annotate | diff | comparison | revisions
libduktape/duktape.h file | annotate | diff | comparison | revisions
--- a/VERSION.libduktape.txt	Thu Mar 26 10:06:12 2020 +0100
+++ b/VERSION.libduktape.txt	Mon Oct 19 10:43:25 2020 +0200
@@ -1,1 +1,1 @@
-2.3.0
+2.6.0
--- a/libduktape/duk_config.h	Thu Mar 26 10:06:12 2020 +0100
+++ b/libduktape/duk_config.h	Mon Oct 19 10:43:25 2020 +0200
@@ -1,9 +1,9 @@
 /*
  *  duk_config.h configuration header generated by genconfig.py.
  *
- *  Git commit: d7fdb67f18561a50e06bafd196c6b423af9ad6fe
- *  Git describe: v2.3.0
- *  Git branch: master
+ *  Git commit: fffa346eff06a8764b02c31d4336f63a773a95c3
+ *  Git describe: v2.6.0
+ *  Git branch: v2-maintenance
  *
  *  Supported platforms:
  *      - Mac OSX, iPhone, Darwin
@@ -18,6 +18,7 @@
  *      - QNX
  *      - TI-Nspire
  *      - Emscripten
+ *      - Android
  *      - Linux
  *      - Solaris
  *      - AIX
@@ -39,6 +40,8 @@
  *      - PowerPC 64-bit
  *      - SPARC 32-bit
  *      - SPARC 64-bit
+ *      - RISC-V 32-bit
+ *      - RISC-V 64-bit
  *      - SuperH
  *      - Motorola 68k
  *      - Emscripten
@@ -63,6 +66,10 @@
  *  Intermediate helper defines
  */
 
+/* DLL build detection */
+/* not configured for DLL build */
+#undef DUK_F_DLL_BUILD
+
 /* Apple OSX, iOS */
 #if defined(__APPLE__)
 #define DUK_F_APPLE
@@ -166,6 +173,10 @@
 #define DUK_F_BCC
 #endif
 
+#if defined(ANDROID) || defined(__ANDROID__)
+#define DUK_F_ANDROID
+#endif
+
 /* Linux */
 #if defined(__linux) || defined(__linux__) || defined(linux)
 #define DUK_F_LINUX
@@ -242,9 +253,9 @@
 #endif
 
 /* ARM */
-#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(__aarch64__)
+#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__)
 #define DUK_F_ARM
-#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__)
+#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__) || defined(_M_ARM64) || defined(__aarch64__)
 #define DUK_F_ARM64
 #else
 #define DUK_F_ARM32
@@ -276,6 +287,22 @@
 #endif
 #endif
 
+/* RISC-V, https://github.com/riscv/riscv-toolchain-conventions#cc-preprocessor-definitions */
+#if defined(__riscv)
+#define DUK_F_RISCV
+#if defined(__riscv_xlen)
+#if (__riscv_xlen == 32)
+#define DUK_F_RISCV32
+#elif (__riscv_xlen == 64)
+#define DUK_F_RISCV64
+#else
+#error __riscv_xlen has unsupported value (not 32 or 64)
+#endif
+#else
+#error __riscv defined without __riscv_xlen
+#endif
+#endif  /* __riscv */
+
 /* SuperH */
 #if defined(__sh__) || \
     defined(__sh1__) || defined(__SH1__) || \
@@ -352,10 +379,6 @@
 #define DUK_F_VBCC
 #endif
 
-#if defined(ANDROID) || defined(__ANDROID__)
-#define DUK_F_ANDROID
-#endif
-
 /* Atari Mint */
 #if defined(__MINT__)
 #define DUK_F_MINT
@@ -661,6 +684,41 @@
 #define DUK_USE_DATE_FMT_STRFTIME
 
 #define DUK_USE_OS_STRING "emscripten"
+#elif defined(DUK_F_ANDROID)
+/* --- Android --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE  200809L
+#endif
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE      /* e.g. getdate_r */
+#endif
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE    /* e.g. strptime */
+#endif
+#endif  /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h or stdint.h */
+#else
+#include <endian.h>
+#include <stdint.h>
+#endif  /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
+#if 0  /* XXX: safe condition? */
+#define DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME
+#endif
+
+#define DUK_USE_OS_STRING "android"
 #elif defined(DUK_F_LINUX)
 /* --- Linux --- */
 #if defined(DUK_COMPILING_DUKTAPE)
@@ -711,7 +769,7 @@
 #define DUK_USE_BYTEORDER 3
 #endif
 #else  /* DUK_F_OLD_SOLARIS */
-#include <ast/endian.h>
+#include <sys/param.h>
 #endif  /* DUK_F_OLD_SOLARIS */
 
 #include <sys/param.h>
@@ -906,9 +964,7 @@
 #elif defined(DUK_F_PPC64)
 /* --- PowerPC 64-bit --- */
 #define DUK_USE_ARCH_STRING "ppc64"
-#if !defined(DUK_USE_BYTEORDER)
-#define DUK_USE_BYTEORDER 3
-#endif
+/* No forced byteorder (both little and big endian are possible). */
 #undef DUK_USE_PACKED_TVAL
 #define DUK_F_PACKED_TVAL_PROVIDED
 #elif defined(DUK_F_SPARC32)
@@ -923,6 +979,18 @@
 /* SPARC byte order varies so rely on autodetection. */
 #undef DUK_USE_PACKED_TVAL
 #define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_RISCV32)
+/* --- RISC-V 32-bit --- */
+#define DUK_USE_ARCH_STRING "riscv32"
+#define DUK_USE_BYTEORDER 1
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_RISCV64)
+/* --- RISC-V 64-bit --- */
+#define DUK_USE_ARCH_STRING "riscv64"
+#define DUK_USE_BYTEORDER 1
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
 #elif defined(DUK_F_SUPERH)
 /* --- SuperH --- */
 #define DUK_USE_ARCH_STRING "sh"
@@ -1063,8 +1131,20 @@
 #define DUK_USE_FLEX_ZEROSIZE
 #endif
 
-#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_CLANG_PRAGMAS
 #define DUK_USE_PACK_CLANG_ATTR
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_bswap64)
+#define DUK_BSWAP64(x) ((duk_uint64_t) __builtin_bswap64((duk_uint64_t) (x)))
+#endif
+#if __has_builtin(__builtin_bswap32)
+#define DUK_BSWAP32(x) ((duk_uint32_t) __builtin_bswap32((duk_uint32_t) (x)))
+#endif
+#if __has_builtin(__builtin_bswap16)
+#define DUK_BSWAP16(x) ((duk_uint16_t) __builtin_bswap16((duk_uint16_t) (x)))
+#endif
+#endif
 #elif defined(DUK_F_GCC)
 /* --- GCC --- */
 #if defined(DUK_F_C99) || defined(DUK_F_CPP11)
@@ -1075,13 +1155,17 @@
 #define DUK_VA_COPY(dest,src) __va_copy(dest,src)
 #endif
 
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
-/* since gcc-2.5 */
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L) && (DUK_F_GCC_VERSION < 50000L)
+/* Since gcc-2.5.
+ *
+ * Disabled temporarily in GCC 5+ because of an unresolved noreturn-related
+ * issue: https://github.com/svaarala/duktape/issues/2155.
+ */
 #define DUK_NORETURN(decl)  decl __attribute__((noreturn))
 #endif
 
 #if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
-/* since gcc-4.5 */
+/* Since gcc-4.5. */
 #define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)
 #endif
 
@@ -1187,6 +1271,7 @@
 #define DUK_USE_FLEX_ZEROSIZE
 #endif
 
+/* Since 4.6 one can '#pragma GCC diagnostic push/pop'. */
 #if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)
 #define DUK_USE_GCC_PRAGMAS
 #else
@@ -1194,6 +1279,16 @@
 #endif
 
 #define DUK_USE_PACK_GCC_ATTR
+
+/* Availability varies based on platform (between GCC 4.4 and 4.8), and there
+ * are apparently some bugs in GCC 4.x.  Check for GCC 5.0 before enabling
+ * these to be safe.
+ */
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 50000L)
+#define DUK_BSWAP64(x) ((duk_uint64_t) __builtin_bswap64((duk_uint64_t) (x)))
+#define DUK_BSWAP32(x) ((duk_uint32_t) __builtin_bswap32((duk_uint32_t) (x)))
+#define DUK_BSWAP16(x) ((duk_uint16_t) __builtin_bswap16((duk_uint16_t) (x)))
+#endif
 #elif defined(DUK_F_MSVC)
 /* --- MSVC --- */
 /* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
@@ -2500,7 +2595,7 @@
 #define DUK_USE_ALIGN_BY 8
 #endif
 
-/* Compiler specific hackery needed to force struct size to match aligment,
+/* Compiler specific hackery needed to force struct size to match alignment,
  * see e.g. duk_hbuffer.h.
  *
  * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
@@ -2511,6 +2606,13 @@
 #define DUK_USE_PACK_DUMMY_MEMBER
 #endif
 
+#if !defined(DUK_U64_CONSTANT)
+#define DUK_U64_CONSTANT(x) x##ULL
+#endif
+#if !defined(DUK_I64_CONSTANT)
+#define DUK_I64_CONSTANT(x) x##LL
+#endif
+
 #if !defined(DUK_VA_COPY)
 /* We need va_copy() which is defined in C99 / C++11, so an awkward
  * replacement is needed for pre-C99 / pre-C++11 environments.  This
@@ -2575,12 +2677,15 @@
 #define DUK_WO_NORETURN(stmt) do { stmt } while (0)
 #endif
 
-#if !defined(DUK_UNREACHABLE)
+#if defined(DUK_UNREACHABLE)
+#define DUK_WO_UNREACHABLE(stmt) do { } while (0)
+#else
 /* Don't know how to declare unreachable point, so don't do it; this
  * may cause some spurious compilation warnings (e.g. "variable used
  * uninitialized").
  */
 #define DUK_UNREACHABLE()  do { } while (0)
+#define DUK_WO_UNREACHABLE(stmt) do { stmt } while (0)
 #endif
 
 #if !defined(DUK_LOSE_CONST)
@@ -2661,17 +2766,30 @@
 #endif
 #endif
 
+#if defined(DUK_F_HAVE_64BIT)
+#if !defined(DUK_BSWAP64)
+#define DUK_BSWAP64(x) \
+	((((duk_uint64_t) (x)) >> 56U) | \
+	 ((((duk_uint64_t) (x)) >> 40U) & DUK_U64_CONSTANT(0xff00)) | \
+	 ((((duk_uint64_t) (x)) >> 24U) & DUK_U64_CONSTANT(0xff0000)) | \
+	 ((((duk_uint64_t) (x)) >> 8U) & DUK_U64_CONSTANT(0xff000000)) | \
+	 ((((duk_uint64_t) (x)) << 8U) & DUK_U64_CONSTANT(0xff00000000)) | \
+	 ((((duk_uint64_t) (x)) << 24U) & DUK_U64_CONSTANT(0xff0000000000)) | \
+	 ((((duk_uint64_t) (x)) << 40U) & DUK_U64_CONSTANT(0xff000000000000)) | \
+	 (((duk_uint64_t) (x)) << 56U))
+#endif
+#endif
 #if !defined(DUK_BSWAP32)
 #define DUK_BSWAP32(x) \
-	((((duk_uint32_t) (x)) >> 24) | \
-	 ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
-	 ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
-	 (((duk_uint32_t) (x)) << 24))
+	((((duk_uint32_t) (x)) >> 24U) | \
+	 ((((duk_uint32_t) (x)) >> 8U) & 0xff00UL) | \
+	 ((((duk_uint32_t) (x)) << 8U) & 0xff0000UL) | \
+	 (((duk_uint32_t) (x)) << 24U))
 #endif
 #if !defined(DUK_BSWAP16)
 #define DUK_BSWAP16(x) \
-	((duk_uint16_t) (x) >> 8) | \
-	((duk_uint16_t) (x) << 8)
+	((duk_uint16_t) (x) >> 8U) | \
+	((duk_uint16_t) (x) << 8U)
 #endif
 
 /* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */
@@ -2694,13 +2812,6 @@
 #undef DUK_USE_GCC_PRAGMAS
 #endif
 
-#if !defined(DUK_U64_CONSTANT)
-#define DUK_U64_CONSTANT(x) x##ULL
-#endif
-#if !defined(DUK_I64_CONSTANT)
-#define DUK_I64_CONSTANT(x) x##LL
-#endif
-
 /* Workaround for GH-323: avoid inlining control when compiling from
  * multiple sources, as it causes compiler portability trouble.
  */
@@ -2803,7 +2914,10 @@
 #define DUK_USE_CACHE_ACTIVATION
 #define DUK_USE_CACHE_CATCHER
 #define DUK_USE_CALLSTACK_LIMIT 10000
-#define DUK_USE_COMMONJS_MODULES
+#define DUK_USE_CBOR_BUILTIN
+#define DUK_USE_CBOR_DEC_RECLIMIT 1000
+#define DUK_USE_CBOR_ENC_RECLIMIT 1000
+#define DUK_USE_CBOR_SUPPORT
 #define DUK_USE_COMPILER_RECLIMIT 2500
 #define DUK_USE_COROUTINE_SUPPORT
 #undef DUK_USE_CPP_EXCEPTIONS
@@ -2867,7 +2981,7 @@
 #undef DUK_USE_GC_TORTURE
 #undef DUK_USE_GET_MONOTONIC_TIME
 #undef DUK_USE_GET_RANDOM_DOUBLE
-#undef DUK_USE_GLOBAL_BINDING
+#define DUK_USE_GLOBAL_BINDING
 #define DUK_USE_GLOBAL_BUILTIN
 #undef DUK_USE_HEAPPTR16
 #undef DUK_USE_HEAPPTR_DEC16
@@ -2875,6 +2989,7 @@
 #define DUK_USE_HEX_FASTPATH
 #define DUK_USE_HEX_SUPPORT
 #define DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT 2
+#define DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE 257
 #define DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT 9
 #define DUK_USE_HOBJECT_ARRAY_MINGROW_ADD 16
 #define DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR 8
@@ -2908,6 +3023,7 @@
 #define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256
 #define DUK_USE_MATH_BUILTIN
 #define DUK_USE_NATIVE_CALL_RECLIMIT 1000
+#undef DUK_USE_NATIVE_STACK_CHECK
 #define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
 #undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
 #undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
@@ -2958,12 +3074,11 @@
 #define DUK_USE_STRTAB_RESIZE_CHECK_MASK 255
 #define DUK_USE_STRTAB_SHRINK_LIMIT 6
 #undef DUK_USE_STRTAB_TORTURE
-#undef DUK_USE_SYMBOL_BUILTIN
+#define DUK_USE_SYMBOL_BUILTIN
 #define DUK_USE_TAILCALL
 #define DUK_USE_TARGET_INFO "unknown"
 #define DUK_USE_TRACEBACKS
 #define DUK_USE_TRACEBACK_DEPTH 10
-#define DUK_USE_USER_DECLARE() /* no user declarations */
 #define DUK_USE_VALSTACK_GROW_SHIFT 2
 #define DUK_USE_VALSTACK_LIMIT 1000000L
 #define DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT 2
@@ -3379,6 +3494,9 @@
 #if defined(DUK_USE_BYTEORDER_FORCED)
 #error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED
 #endif
+#if defined(DUK_USE_COMMONJS_MODULES)
+#error unsupported config option used (option has been removed): DUK_USE_COMMONJS_MODULES
+#endif
 #if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16)
 #error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing)
 #endif
@@ -3625,6 +3743,9 @@
 #if defined(DUK_USE_UNDERSCORE_SETJMP)
 #error unsupported config option used (option has been removed): DUK_USE_UNDERSCORE_SETJMP
 #endif
+#if defined(DUK_USE_USER_DECLARE)
+#error unsupported config option used (option has been removed): DUK_USE_USER_DECLARE
+#endif
 #if defined(DUK_USE_USER_INITJS)
 #error unsupported config option used (option has been removed): DUK_USE_USER_INITJS
 #endif
--- a/libduktape/duktape.cpp	Thu Mar 26 10:06:12 2020 +0100
+++ b/libduktape/duktape.cpp	Mon Oct 19 10:43:25 2020 +0200
@@ -1,8 +1,8 @@
 /*
- *  Single source autogenerated distributable for Duktape 2.3.0.
- *
- *  Git commit d7fdb67f18561a50e06bafd196c6b423af9ad6fe (v2.3.0).
- *  Git branch master.
+ *  Single source autogenerated distributable for Duktape 2.6.0.
+ *
+ *  Git commit fffa346eff06a8764b02c31d4336f63a773a95c3 (v2.6.0).
+ *  Git branch v2-maintenance.
  *
  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
@@ -16,7 +16,7 @@
 *
 *  (http://opensource.org/licenses/MIT)
 *
-*  Copyright (c) 2013-2018 by Duktape authors (see AUTHORS.rst)
+*  Copyright (c) 2013-2019 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
@@ -95,6 +95,16 @@
 *  * Michal Kasperek (https://github.com/michalkas)
 *  * Andrew Janke (https://github.com/apjanke)
 *  * Steve Fan (https://github.com/stevefan1999)
+*  * Edward Betts (https://github.com/edwardbetts)
+*  * Ozhan Duz (https://github.com/webfolderio)
+*  * Akos Kiss (https://github.com/akosthekiss)
+*  * TheBrokenRail (https://github.com/TheBrokenRail)
+*  * Jesse Doyle (https://github.com/jessedoyle)
+*  * Gero Kuehn (https://github.com/dc6jgk)
+*  * James Swift (https://github.com/phraemer)
+*  * Luis de Bethencourt (https://github.com/luisbg)
+*  * Ian Whyman (https://github.com/v00d00)
+*  * Rick Sayre (https://github.com/whorfin)
 *
 *  Other contributions
 *  ===================
@@ -135,6 +145,8 @@
 *  * Neil Kolban (https://github.com/nkolban)
 *  * Wilhelm Wanecek (https://github.com/wanecek)
 *  * Andrew Janke (https://github.com/apjanke)
+*  * Unamer (https://github.com/unamer)
+*  * Karl Dahlke (eklhad@gmail.com)
 *
 *  If you are accidentally missing from this list, send me an e-mail
 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
@@ -179,13 +191,6 @@
 #include "duktape.h"
 
 /*
- *  User declarations, e.g. prototypes for user functions used by Duktape
- *  macros.
- */
-
-DUK_USE_USER_DECLARE()
-
-/*
  *  Duktape includes (other than duk_features.h)
  *
  *  The header files expect to be included in an order which satisfies header
@@ -224,13 +229,14 @@
  *
  *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE
  *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE
- *    D C B A H G F E    Mixed/cross endian (e.g. ARM)   DUK_USE_DOUBLE_ME
- *
- *  ARM is a special case: ARM double values are in mixed/cross endian
- *  format while ARM duk_uint64_t values are in standard little endian
+ *    D C B A H G F E    Mixed endian (e.g. ARM FPA)     DUK_USE_DOUBLE_ME
+ *
+ *  Legacy ARM (FPA) is a special case: ARM double values are in mixed
+ *  endian format while ARM duk_uint64_t values are in standard little endian
  *  format (H G F E D C B A).  When a double is read as a duk_uint64_t
  *  from memory, the register will contain the (logical) value
  *  E F G H A B C D.  This requires some special handling below.
+ *  See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Bcfhgcgd.html.
  *
  *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
  *  the logical (big endian) order:
@@ -519,7 +525,8 @@
 	} while (0)
 
 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \
-		if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \
+		/* Check must be full. */ \
+		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
 			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
 		} \
 	} while (0)
@@ -531,12 +538,11 @@
  */
 
 #if defined(DUK_USE_PACKED_TVAL)
-#if defined(DUK_USE_FULL_TVAL)
 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))
 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))
-#else
+#if 0
 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))
 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
@@ -619,6 +625,47 @@
 #endif
 
 #endif  /* DUK_DBLUNION_H_INCLUDED */
+/* #include duk_fltunion.h */
+#line 1 "duk_fltunion.h"
+/*
+ *  Union to access IEEE float memory representation.
+ */
+
+#if !defined(DUK_FLTUNION_H_INCLUDED)
+#define DUK_FLTUNION_H_INCLUDED
+
+/* #include duk_internal.h -> already included */
+
+union duk_float_union {
+	float f;
+	duk_uint32_t ui[1];
+	duk_uint16_t us[2];
+	duk_uint8_t uc[4];
+};
+
+typedef union duk_float_union duk_float_union;
+
+#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
+#define DUK_FLT_IDX_UI0    0
+#define DUK_FLT_IDX_US0    1
+#define DUK_FLT_IDX_US1    0
+#define DUK_FLT_IDX_UC0    3
+#define DUK_FLT_IDX_UC1    2
+#define DUK_FLT_IDX_UC2    1
+#define DUK_FLT_IDX_UC3    0
+#elif defined(DUK_USE_DOUBLE_BE)
+#define DUK_FLT_IDX_UI0    0
+#define DUK_FLT_IDX_US0    0
+#define DUK_FLT_IDX_US1    1
+#define DUK_FLT_IDX_UC0    0
+#define DUK_FLT_IDX_UC1    1
+#define DUK_FLT_IDX_UC2    2
+#define DUK_FLT_IDX_UC3    3
+#else
+#error internal error
+#endif
+
+#endif  /* DUK_FLTUNION_H_INCLUDED */
 /* #include duk_replacements.h */
 #line 1 "duk_replacements.h"
 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
@@ -1477,6 +1524,13 @@
 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
 #endif
 
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
+#define DUK_TVAL_ASSERT_VALID(tv)  do { duk_tval_assert_valid((tv)); } while (0)
+#else
+#define DUK_TVAL_ASSERT_VALID(tv)  do {} while (0)
+#endif
+
 #endif  /* DUK_TVAL_H_INCLUDED */
 /* #include duk_builtins.h */
 #line 1 "duk_builtins.h"
@@ -1508,9 +1562,9 @@
 #define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
-#define DUK_STRIDX_ARRAY                                              6                              /* 'Array' */
-#define DUK_HEAP_STRING_ARRAY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
-#define DUK_HTHREAD_STRING_ARRAY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
+#define DUK_STRIDX_UC_ARRAY                                           6                              /* 'Array' */
+#define DUK_HEAP_STRING_UC_ARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARRAY)
+#define DUK_HTHREAD_STRING_UC_ARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARRAY)
 #define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
@@ -1520,9 +1574,9 @@
 #define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
-#define DUK_STRIDX_DATE                                               10                             /* 'Date' */
-#define DUK_HEAP_STRING_DATE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
-#define DUK_HTHREAD_STRING_DATE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
+#define DUK_STRIDX_UC_DATE                                            10                             /* 'Date' */
+#define DUK_HEAP_STRING_UC_DATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_DATE)
+#define DUK_HTHREAD_STRING_UC_DATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_DATE)
 #define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
@@ -1748,260 +1802,263 @@
 #define DUK_STRIDX_DATA                                               85                             /* 'data' */
 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
-#define DUK_STRIDX_LENGTH                                             86                             /* 'length' */
+#define DUK_STRIDX_LC_BUFFER                                          86                             /* 'buffer' */
+#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
+#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
+#define DUK_STRIDX_LENGTH                                             87                             /* 'length' */
 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
-#define DUK_STRIDX_SET                                                87                             /* 'set' */
+#define DUK_STRIDX_SET                                                88                             /* 'set' */
 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
-#define DUK_STRIDX_STACK                                              88                             /* 'stack' */
+#define DUK_STRIDX_STACK                                              89                             /* 'stack' */
 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
-#define DUK_STRIDX_PC                                                 89                             /* 'pc' */
+#define DUK_STRIDX_PC                                                 90                             /* 'pc' */
 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
-#define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
+#define DUK_STRIDX_LINE_NUMBER                                        91                             /* 'lineNumber' */
 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
-#define DUK_STRIDX_INT_TRACEDATA                                      91                             /* '\x82Tracedata' */
+#define DUK_STRIDX_INT_TRACEDATA                                      92                             /* '\x82Tracedata' */
 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
-#define DUK_STRIDX_NAME                                               92                             /* 'name' */
+#define DUK_STRIDX_NAME                                               93                             /* 'name' */
 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
-#define DUK_STRIDX_FILE_NAME                                          93                             /* 'fileName' */
+#define DUK_STRIDX_FILE_NAME                                          94                             /* 'fileName' */
 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
-#define DUK_STRIDX_LC_POINTER                                         94                             /* 'pointer' */
+#define DUK_STRIDX_LC_POINTER                                         95                             /* 'pointer' */
 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
-#define DUK_STRIDX_INT_TARGET                                         95                             /* '\x82Target' */
+#define DUK_STRIDX_INT_TARGET                                         96                             /* '\x82Target' */
 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
-#define DUK_STRIDX_INT_NEXT                                           96                             /* '\x82Next' */
+#define DUK_STRIDX_INT_NEXT                                           97                             /* '\x82Next' */
 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
-#define DUK_STRIDX_INT_BYTECODE                                       97                             /* '\x82Bytecode' */
+#define DUK_STRIDX_INT_BYTECODE                                       98                             /* '\x82Bytecode' */
 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
-#define DUK_STRIDX_INT_FORMALS                                        98                             /* '\x82Formals' */
+#define DUK_STRIDX_INT_FORMALS                                        99                             /* '\x82Formals' */
 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
-#define DUK_STRIDX_INT_VARMAP                                         99                             /* '\x82Varmap' */
+#define DUK_STRIDX_INT_VARMAP                                         100                            /* '\x82Varmap' */
 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
-#define DUK_STRIDX_INT_SOURCE                                         100                            /* '\x82Source' */
+#define DUK_STRIDX_INT_SOURCE                                         101                            /* '\x82Source' */
 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
-#define DUK_STRIDX_INT_PC2LINE                                        101                            /* '\x82Pc2line' */
+#define DUK_STRIDX_INT_PC2LINE                                        102                            /* '\x82Pc2line' */
 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
-#define DUK_STRIDX_INT_MAP                                            102                            /* '\x82Map' */
+#define DUK_STRIDX_INT_MAP                                            103                            /* '\x82Map' */
 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
-#define DUK_STRIDX_INT_VARENV                                         103                            /* '\x82Varenv' */
+#define DUK_STRIDX_INT_VARENV                                         104                            /* '\x82Varenv' */
 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
-#define DUK_STRIDX_INT_FINALIZER                                      104                            /* '\x82Finalizer' */
+#define DUK_STRIDX_INT_FINALIZER                                      105                            /* '\x82Finalizer' */
 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
-#define DUK_STRIDX_INT_VALUE                                          105                            /* '\x82Value' */
+#define DUK_STRIDX_INT_VALUE                                          106                            /* '\x82Value' */
 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
-#define DUK_STRIDX_COMPILE                                            106                            /* 'compile' */
+#define DUK_STRIDX_COMPILE                                            107                            /* 'compile' */
 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
-#define DUK_STRIDX_INPUT                                              107                            /* 'input' */
+#define DUK_STRIDX_INPUT                                              108                            /* 'input' */
 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
-#define DUK_STRIDX_ERR_CREATE                                         108                            /* 'errCreate' */
+#define DUK_STRIDX_ERR_CREATE                                         109                            /* 'errCreate' */
 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
-#define DUK_STRIDX_ERR_THROW                                          109                            /* 'errThrow' */
+#define DUK_STRIDX_ERR_THROW                                          110                            /* 'errThrow' */
 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
-#define DUK_STRIDX_ENV                                                110                            /* 'env' */
+#define DUK_STRIDX_ENV                                                111                            /* 'env' */
 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
-#define DUK_STRIDX_HEX                                                111                            /* 'hex' */
+#define DUK_STRIDX_HEX                                                112                            /* 'hex' */
 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
-#define DUK_STRIDX_BASE64                                             112                            /* 'base64' */
+#define DUK_STRIDX_BASE64                                             113                            /* 'base64' */
 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
-#define DUK_STRIDX_JX                                                 113                            /* 'jx' */
+#define DUK_STRIDX_JX                                                 114                            /* 'jx' */
 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
-#define DUK_STRIDX_JC                                                 114                            /* 'jc' */
+#define DUK_STRIDX_JC                                                 115                            /* 'jc' */
 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
-#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 115                            /* '{"_undef":true}' */
+#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 116                            /* '{"_undef":true}' */
 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
-#define DUK_STRIDX_JSON_EXT_NAN                                       116                            /* '{"_nan":true}' */
+#define DUK_STRIDX_JSON_EXT_NAN                                       117                            /* '{"_nan":true}' */
 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
-#define DUK_STRIDX_JSON_EXT_POSINF                                    117                            /* '{"_inf":true}' */
+#define DUK_STRIDX_JSON_EXT_POSINF                                    118                            /* '{"_inf":true}' */
 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
-#define DUK_STRIDX_JSON_EXT_NEGINF                                    118                            /* '{"_ninf":true}' */
+#define DUK_STRIDX_JSON_EXT_NEGINF                                    119                            /* '{"_ninf":true}' */
 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
-#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 119                            /* '{"_func":true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 120                            /* '{"_func":true}' */
 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
-#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 120                            /* '{_func:true}' */
+#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 121                            /* '{_func:true}' */
 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
-#define DUK_STRIDX_BREAK                                              121                            /* 'break' */
+#define DUK_STRIDX_BREAK                                              122                            /* 'break' */
 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
-#define DUK_STRIDX_CASE                                               122                            /* 'case' */
+#define DUK_STRIDX_CASE                                               123                            /* 'case' */
 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
-#define DUK_STRIDX_CATCH                                              123                            /* 'catch' */
+#define DUK_STRIDX_CATCH                                              124                            /* 'catch' */
 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
-#define DUK_STRIDX_CONTINUE                                           124                            /* 'continue' */
+#define DUK_STRIDX_CONTINUE                                           125                            /* 'continue' */
 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
-#define DUK_STRIDX_DEBUGGER                                           125                            /* 'debugger' */
+#define DUK_STRIDX_DEBUGGER                                           126                            /* 'debugger' */
 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
-#define DUK_STRIDX_DEFAULT                                            126                            /* 'default' */
+#define DUK_STRIDX_DEFAULT                                            127                            /* 'default' */
 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
-#define DUK_STRIDX_DELETE                                             127                            /* 'delete' */
+#define DUK_STRIDX_DELETE                                             128                            /* 'delete' */
 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
-#define DUK_STRIDX_DO                                                 128                            /* 'do' */
+#define DUK_STRIDX_DO                                                 129                            /* 'do' */
 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
-#define DUK_STRIDX_ELSE                                               129                            /* 'else' */
+#define DUK_STRIDX_ELSE                                               130                            /* 'else' */
 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
-#define DUK_STRIDX_FINALLY                                            130                            /* 'finally' */
+#define DUK_STRIDX_FINALLY                                            131                            /* 'finally' */
 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
-#define DUK_STRIDX_FOR                                                131                            /* 'for' */
+#define DUK_STRIDX_FOR                                                132                            /* 'for' */
 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
-#define DUK_STRIDX_LC_FUNCTION                                        132                            /* 'function' */
+#define DUK_STRIDX_LC_FUNCTION                                        133                            /* 'function' */
 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
-#define DUK_STRIDX_IF                                                 133                            /* 'if' */
+#define DUK_STRIDX_IF                                                 134                            /* 'if' */
 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
-#define DUK_STRIDX_IN                                                 134                            /* 'in' */
+#define DUK_STRIDX_IN                                                 135                            /* 'in' */
 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
-#define DUK_STRIDX_INSTANCEOF                                         135                            /* 'instanceof' */
+#define DUK_STRIDX_INSTANCEOF                                         136                            /* 'instanceof' */
 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
-#define DUK_STRIDX_NEW                                                136                            /* 'new' */
+#define DUK_STRIDX_NEW                                                137                            /* 'new' */
 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
-#define DUK_STRIDX_RETURN                                             137                            /* 'return' */
+#define DUK_STRIDX_RETURN                                             138                            /* 'return' */
 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
-#define DUK_STRIDX_SWITCH                                             138                            /* 'switch' */
+#define DUK_STRIDX_SWITCH                                             139                            /* 'switch' */
 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
-#define DUK_STRIDX_THIS                                               139                            /* 'this' */
+#define DUK_STRIDX_THIS                                               140                            /* 'this' */
 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
-#define DUK_STRIDX_THROW                                              140                            /* 'throw' */
+#define DUK_STRIDX_THROW                                              141                            /* 'throw' */
 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
-#define DUK_STRIDX_TRY                                                141                            /* 'try' */
+#define DUK_STRIDX_TRY                                                142                            /* 'try' */
 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
-#define DUK_STRIDX_TYPEOF                                             142                            /* 'typeof' */
+#define DUK_STRIDX_TYPEOF                                             143                            /* 'typeof' */
 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
-#define DUK_STRIDX_VAR                                                143                            /* 'var' */
+#define DUK_STRIDX_VAR                                                144                            /* 'var' */
 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
-#define DUK_STRIDX_CONST                                              144                            /* 'const' */
+#define DUK_STRIDX_CONST                                              145                            /* 'const' */
 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
-#define DUK_STRIDX_VOID                                               145                            /* 'void' */
+#define DUK_STRIDX_VOID                                               146                            /* 'void' */
 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
-#define DUK_STRIDX_WHILE                                              146                            /* 'while' */
+#define DUK_STRIDX_WHILE                                              147                            /* 'while' */
 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
-#define DUK_STRIDX_WITH                                               147                            /* 'with' */
+#define DUK_STRIDX_WITH                                               148                            /* 'with' */
 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
-#define DUK_STRIDX_CLASS                                              148                            /* 'class' */
+#define DUK_STRIDX_CLASS                                              149                            /* 'class' */
 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
-#define DUK_STRIDX_ENUM                                               149                            /* 'enum' */
+#define DUK_STRIDX_ENUM                                               150                            /* 'enum' */
 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
-#define DUK_STRIDX_EXPORT                                             150                            /* 'export' */
+#define DUK_STRIDX_EXPORT                                             151                            /* 'export' */
 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
-#define DUK_STRIDX_EXTENDS                                            151                            /* 'extends' */
+#define DUK_STRIDX_EXTENDS                                            152                            /* 'extends' */
 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
-#define DUK_STRIDX_IMPORT                                             152                            /* 'import' */
+#define DUK_STRIDX_IMPORT                                             153                            /* 'import' */
 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
-#define DUK_STRIDX_SUPER                                              153                            /* 'super' */
+#define DUK_STRIDX_SUPER                                              154                            /* 'super' */
 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
-#define DUK_STRIDX_LC_NULL                                            154                            /* 'null' */
+#define DUK_STRIDX_LC_NULL                                            155                            /* 'null' */
 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
-#define DUK_STRIDX_TRUE                                               155                            /* 'true' */
+#define DUK_STRIDX_TRUE                                               156                            /* 'true' */
 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
-#define DUK_STRIDX_FALSE                                              156                            /* 'false' */
+#define DUK_STRIDX_FALSE                                              157                            /* 'false' */
 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
-#define DUK_STRIDX_IMPLEMENTS                                         157                            /* 'implements' */
+#define DUK_STRIDX_IMPLEMENTS                                         158                            /* 'implements' */
 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
-#define DUK_STRIDX_INTERFACE                                          158                            /* 'interface' */
+#define DUK_STRIDX_INTERFACE                                          159                            /* 'interface' */
 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
-#define DUK_STRIDX_LET                                                159                            /* 'let' */
+#define DUK_STRIDX_LET                                                160                            /* 'let' */
 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
-#define DUK_STRIDX_PACKAGE                                            160                            /* 'package' */
+#define DUK_STRIDX_PACKAGE                                            161                            /* 'package' */
 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
-#define DUK_STRIDX_PRIVATE                                            161                            /* 'private' */
+#define DUK_STRIDX_PRIVATE                                            162                            /* 'private' */
 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
-#define DUK_STRIDX_PROTECTED                                          162                            /* 'protected' */
+#define DUK_STRIDX_PROTECTED                                          163                            /* 'protected' */
 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
-#define DUK_STRIDX_PUBLIC                                             163                            /* 'public' */
+#define DUK_STRIDX_PUBLIC                                             164                            /* 'public' */
 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
-#define DUK_STRIDX_STATIC                                             164                            /* 'static' */
+#define DUK_STRIDX_STATIC                                             165                            /* 'static' */
 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
-#define DUK_STRIDX_YIELD                                              165                            /* 'yield' */
+#define DUK_STRIDX_YIELD                                              166                            /* 'yield' */
 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
 
-#define DUK_HEAP_NUM_STRINGS                                          166
-#define DUK_STRIDX_START_RESERVED                                     121
-#define DUK_STRIDX_START_STRICT_RESERVED                              157
-#define DUK_STRIDX_END_RESERVED                                       166                            /* exclusive endpoint */
+#define DUK_HEAP_NUM_STRINGS                                          167
+#define DUK_STRIDX_START_RESERVED                                     122
+#define DUK_STRIDX_START_STRICT_RESERVED                              158
+#define DUK_STRIDX_END_RESERVED                                       167                            /* exclusive endpoint */
 
 /* To convert a heap stridx to a token number, subtract
  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
  */
 #if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[967];
+DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[972];
 #endif  /* !DUK_SINGLE_FILE */
 #define DUK_STRDATA_MAX_STRLEN                                        27
-#define DUK_STRDATA_DATA_LENGTH                                       967
+#define DUK_STRDATA_DATA_LENGTH                                       972
 #endif  /* DUK_USE_ROM_STRINGS */
 
 #if defined(DUK_USE_ROM_OBJECTS)
@@ -2023,6 +2080,7 @@
 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
@@ -2063,6 +2121,7 @@
 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
@@ -2118,6 +2177,7 @@
 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
@@ -2158,6 +2218,9 @@
 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
@@ -2178,13 +2241,15 @@
 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_encode(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_decode(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
 DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
 #if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[177];
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[185];
 #endif  /* !DUK_SINGLE_FILE */
 #define DUK_BIDX_GLOBAL                                               0
 #define DUK_BIDX_GLOBAL_ENV                                           1
@@ -2239,28 +2304,28 @@
 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
 #define DUK_NUM_BUILTINS                                              51
 #define DUK_NUM_BIDX_BUILTINS                                         51
-#define DUK_NUM_ALL_BUILTINS                                          78
+#define DUK_NUM_ALL_BUILTINS                                          80
 #if defined(DUK_USE_DOUBLE_LE)
 #if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
 #endif  /* !DUK_SINGLE_FILE */
-#define DUK_BUILTINS_DATA_LENGTH                                      4116
+#define DUK_BUILTINS_DATA_LENGTH                                      4281
 #elif defined(DUK_USE_DOUBLE_BE)
 #if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
 #endif  /* !DUK_SINGLE_FILE */
-#define DUK_BUILTINS_DATA_LENGTH                                      4116
+#define DUK_BUILTINS_DATA_LENGTH                                      4281
 #elif defined(DUK_USE_DOUBLE_ME)
 #if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
+DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
 #endif  /* !DUK_SINGLE_FILE */
-#define DUK_BUILTINS_DATA_LENGTH                                      4116
+#define DUK_BUILTINS_DATA_LENGTH                                      4281
 #else
 #error invalid endianness defines
 #endif
 #endif  /* DUK_USE_ROM_OBJECTS */
 #endif  /* DUK_BUILTINS_H_INCLUDED */
-#line 51 "duk_internal.h"
+#line 45 "duk_internal.h"
 
 /* #include duk_util.h */
 #line 1 "duk_util.h"
@@ -2333,40 +2398,49 @@
 
 /*
  *  Raw write/read macros for big endian, unaligned basic values.
- *  Caller ensures there's enough space.  The macros update the pointer
- *  argument automatically on resizes.  The idiom seems a bit odd, but
- *  leads to compact code.
+ *  Caller ensures there's enough space.  The INC macro variants
+ *  update the pointer argument automatically.
  */
 
 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
+		*(ptr) = (duk_uint8_t) (val); \
+	} while (0)
+#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
+#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
+#define DUK_RAW_WRITE_FLOAT_BE(ptr,val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
+#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
+#define DUK_RAW_WRITE_XUTF8(ptr,val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))
+
+#define DUK_RAW_WRITEINC_U8(ptr,val)  do { \
 		*(ptr)++ = (duk_uint8_t) (val); \
 	} while (0)
-#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
-#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
-#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
-#define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \
-		/* 'ptr' is evaluated both as LHS and RHS. */ \
-		duk_uint8_t *duk__ptr; \
-		duk_small_int_t duk__len; \
-		duk__ptr = (duk_uint8_t *) (ptr); \
-		duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
-		duk__ptr += duk__len; \
-		(ptr) = duk__ptr; \
-	} while (0)
-#define DUK_RAW_WRITE_CESU8(ptr,val)  do { \
-		/* 'ptr' is evaluated both as LHS and RHS. */ \
-		duk_uint8_t *duk__ptr; \
-		duk_small_int_t duk__len; \
-		duk__ptr = (duk_uint8_t *) (ptr); \
-		duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
-		duk__ptr += duk__len; \
-		(ptr) = duk__ptr; \
-	} while (0)
-
-#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
-#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
-#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
-#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
+#define DUK_RAW_WRITEINC_U16_BE(ptr,val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
+#define DUK_RAW_WRITEINC_U32_BE(ptr,val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
+#define DUK_RAW_WRITEINC_FLOAT_BE(ptr,val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
+#define DUK_RAW_WRITEINC_DOUBLE_BE(ptr,val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
+#define DUK_RAW_WRITEINC_XUTF8(ptr,val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
+#define DUK_RAW_WRITEINC_CESU8(ptr,val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))
+
+#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
+#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
+#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
+#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));
+
+#define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
+#define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
+#define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
+#define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));
+
+/*
+ *  Double and float byte order operations.
+ */
+
+DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u);
+DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u);
+DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u);
 
 /*
  *  Buffer writer (dynamic buffer only)
@@ -2425,24 +2499,20 @@
 		                 (const char *) (bw_ctx)->p_base, \
 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
 	} while (0)
+
 /* Pointers may be NULL for a while when 'buf' size is zero and before any
  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
  * are required to be non-NULL so that it's always valid to use memcpy() and
  * memmove(), even for zero size.
  */
-#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
-	DUK_ASSERT_EXPR((bw_ctx) != NULL && \
-	                (bw_ctx)->buf != NULL && \
-			((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
-				((bw_ctx)->p != NULL && \
-		                 (bw_ctx)->p_base != NULL && \
-		                 (bw_ctx)->p_limit != NULL && \
-		                 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
-		                 (bw_ctx)->p >= (bw_ctx)->p_base && \
-		                 (bw_ctx)->p <= (bw_ctx)->p_limit)))
-#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
-		DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
+#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  (duk_bw_assert_valid((thr), (bw_ctx)))
+#define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do { duk_bw_assert_valid((thr), (bw_ctx)); } while (0)
+#else
+#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  DUK_ASSERT_EXPR(1)
+#define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do {} while (0)
+#endif
 
 /* Working with the pointer and current size. */
 
@@ -2799,12 +2869,26 @@
 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
 
-DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
-DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
-DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
-DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
-DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
-DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
+DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p);
+DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p);
+DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
+DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
+DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
+DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val);
+DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val);
+DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val);
+DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val);
 
 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
@@ -2955,6 +3039,8 @@
 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
+DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y);
+DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y);
 
 /*
  *  Miscellaneous
@@ -3055,10 +3141,12 @@
 /* JSON */
 #define DUK_STR_FMT_PTR                          "%p"
 #define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
-#define DUK_STR_JSONDEC_RECLIMIT                 "json decode recursion limit"
-#define DUK_STR_JSONENC_RECLIMIT                 "json encode recursion limit"
 #define DUK_STR_CYCLIC_INPUT                     "cyclic input"
 
+/* Generic codec */
+#define DUK_STR_DEC_RECLIMIT                     "decode recursion limit"
+#define DUK_STR_ENC_RECLIMIT                     "encode recursion limit"
+
 /* Object property access */
 #define DUK_STR_INVALID_BASE                     "invalid base value"
 #define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
@@ -3131,7 +3219,7 @@
 #define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
 #define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
-#define DUK_STR_C_CALLSTACK_LIMIT                "C call stack depth limit"
+#define DUK_STR_NATIVE_STACK_LIMIT               "C stack depth limit"
 #define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
 #define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
 #define DUK_STR_REG_LIMIT                        "register limit"
@@ -4669,24 +4757,16 @@
 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
  * h->prev->next should point back to h.
  */
-#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
-#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
-		if ((h) != NULL) { \
-			duk_heaphdr *h__prev, *h__next; \
-			h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
-			h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
-			DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
-			DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
-		} \
-	} while (0)
-#else
-#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
-#endif
-
-#define DUK_ASSERT_HEAPHDR_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((h))); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
+DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
+#define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do { duk_heaphdr_assert_links((heap), (h)); } while (0)
+#define DUK_HEAPHDR_ASSERT_VALID(h)  do { duk_heaphdr_assert_valid((h)); } while (0)
+#else
+#define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do {} while (0)
+#define DUK_HEAPHDR_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 #endif  /* DUK_HEAPHDR_H_INCLUDED */
 /* #include duk_refcount.h */
@@ -5426,7 +5506,27 @@
 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
 #define DUK_API_INTERNAL_H_INCLUDED
 
-#define DUK_INTERNAL_SYMBOL(x)     ("\x82" x)
+/* Inline macro helpers. */
+#if defined(DUK_USE_PREFER_SIZE)
+#define DUK_INLINE_PERF
+#define DUK_ALWAYS_INLINE_PERF
+#define DUK_NOINLINE_PERF
+#else
+#define DUK_INLINE_PERF DUK_INLINE
+#define DUK_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
+#define DUK_NOINLINE_PERF DUK_NOINLINE
+#endif
+
+/* Inline macro helpers, for bytecode executor. */
+#if defined(DUK_USE_EXEC_PREFER_SIZE)
+#define DUK_EXEC_INLINE_PERF
+#define DUK_EXEC_ALWAYS_INLINE_PERF
+#define DUK_EXEC_NOINLINE_PERF
+#else
+#define DUK_EXEC_INLINE_PERF DUK_INLINE
+#define DUK_EXEC_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
+#define DUK_EXEC_NOINLINE_PERF DUK_NOINLINE
+#endif
 
 /* duk_push_sprintf constants */
 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
@@ -5520,6 +5620,8 @@
 
 DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
 
+DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx);
+
 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
@@ -5646,6 +5748,14 @@
 	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */
 
+DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx);
+DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);
+DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
+#define duk_xget_owndataprop_stridx_short(thr,obj_idx,stridx) \
+	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
+	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
+	 duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
+
 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
 #define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
@@ -5713,8 +5823,6 @@
 DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
 #endif
 
-DUK_INTERNAL_DECL void duk_require_constructor_call(duk_hthread *thr);
-DUK_INTERNAL_DECL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx);
 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
 
 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
@@ -5747,6 +5855,8 @@
 DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
 #endif
 
+DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx);
+
 /* Raw internal valstack access macros: access is unsafe so call site
  * must have a guarantee that the index is valid.  When that is the case,
  * using these macro results in faster and smaller code than duk_get_tval().
@@ -5946,6 +6056,14 @@
 #define DUK_SYMBOL_TYPE_LOCAL 2
 #define DUK_SYMBOL_TYPE_WELLKNOWN 3
 
+/* Assertion for duk_hstring validity. */
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
+#define DUK_HSTRING_ASSERT_VALID(h)  do { duk_hstring_assert_valid((h)); } while (0)
+#else
+#define DUK_HSTRING_ASSERT_VALID(h)  do {} while (0)
+#endif
+
 /*
  *  Misc
  */
@@ -6358,26 +6476,12 @@
  *  Assert for currently guaranteed relations between flags, for instance.
  */
 
-#define DUK_ASSERT_HOBJECT_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
-		           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
-		DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \
-		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
-		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
-		/* Object is an Array <=> object has exotic array behavior */ \
-		DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \
-		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
+#define DUK_HOBJECT_ASSERT_VALID(h)  do { duk_hobject_assert_valid((h)); } while (0)
+#else
+#define DUK_HOBJECT_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 /*
  *  Macros to access the 'props' allocation.
@@ -6928,18 +7032,13 @@
 #endif
 
 /* low-level property functions */
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
-DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
-DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
-DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
+DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
 
-/* XXX: when optimizing for guaranteed property slots, use a guaranteed
- * slot for internal value; this call can then access it directly.
- */
-#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
-	duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
-
 /* core property functions */
 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
 DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
@@ -6983,8 +7082,10 @@
 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
 
 /* internal properties */
-DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
+DUK_INTERNAL_DECL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj);
 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
+DUK_INTERNAL_DECL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj);
+DUK_INTERNAL_DECL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj);
 
 /* hobject management functions */
 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
@@ -7156,9 +7257,12 @@
  *  Validity assert
  */
 
-#define DUK_ASSERT_HCOMPFUNC_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
+#define DUK_HCOMPFUNC_ASSERT_VALID(h)  do { duk_hcompfunc_assert_valid((h)); } while (0)
+#else
+#define DUK_HCOMPFUNC_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 /*
  *  Main struct
@@ -7302,6 +7406,13 @@
 #if !defined(DUK_HNATFUNC_H_INCLUDED)
 #define DUK_HNATFUNC_H_INCLUDED
 
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
+#define DUK_HNATFUNC_ASSERT_VALID(h)  do { duk_hnatfunc_assert_valid((h)); } while (0)
+#else
+#define DUK_HNATFUNC_ASSERT_VALID(h)  do {} while (0)
+#endif
+
 #define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
 #define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)
 
@@ -7341,15 +7452,12 @@
  */
 #define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
 
-#define DUK_ASSERT_HBOUNDFUNC_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) (h))); \
-		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&(h)->target) || \
-		           (DUK_TVAL_IS_OBJECT(&(h)->target) && \
-		            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&(h)->target)))); \
-		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&(h)->this_binding)); \
-		DUK_ASSERT((h)->nargs == 0 || (h)->args != NULL); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
+#define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do { duk_hboundfunc_assert_valid((h)); } while (0)
+#else
+#define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 struct duk_hboundfunc {
 	/* Shared object part. */
@@ -7392,32 +7500,12 @@
 #define DUK_HBUFOBJ_ELEM_FLOAT64         8
 #define DUK_HBUFOBJ_ELEM_MAX             8
 
-#define DUK_ASSERT_HBUFOBJ_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT((h)->shift <= 3); \
-		DUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \
-		DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \
-		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \
-		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \
-		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \
-		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \
-		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \
-		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \
-		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \
-		           ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \
-		DUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \
-		DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \
-		if ((h)->buf == NULL) { \
-			DUK_ASSERT((h)->offset == 0); \
-			DUK_ASSERT((h)->length == 0); \
-		} else { \
-			/* No assertions for offset or length; in particular, \
-			 * it's OK for length to be longer than underlying \
-			 * buffer.  Just ensure they don't wrap when added. \
-			 */ \
-			DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
-		} \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
+#define DUK_HBUFOBJ_ASSERT_VALID(h)  do { duk_hbufobj_assert_valid((h)); } while (0)
+#else
+#define DUK_HBUFOBJ_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 /* Get the current data pointer (caller must ensure buf != NULL) as a
  * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
@@ -7512,6 +7600,10 @@
 DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
 
+#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
+
+/* nothing */
+
 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 #endif  /* DUK_HBUFOBJ_H_INCLUDED */
 /* #include duk_hthread.h */
@@ -7662,37 +7754,24 @@
  *  diagnose behavior so it's worth checking even when the check is not 100%.
  */
 
+#if defined(DUK_USE_ASSERTIONS)
 /* Assertions for internals. */
-#define DUK_ASSERT_HTHREAD_VALID(thr) do { \
-		DUK_ASSERT((thr) != NULL); \
-		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (thr)) == DUK_HTYPE_OBJECT); \
-		DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (thr))); \
-		DUK_ASSERT((thr)->unused1 == 0); \
-		DUK_ASSERT((thr)->unused2 == 0); \
-	} while (0)
+DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
+#define DUK_HTHREAD_ASSERT_VALID(thr)  do { duk_hthread_assert_valid((thr)); } while (0)
 
 /* Assertions for public API calls; a bit stronger. */
-#define DUK_ASSERT_CTX_VALID(thr) do { \
-		DUK_ASSERT((thr) != NULL); \
-		DUK_ASSERT_HTHREAD_VALID((thr)); \
-		DUK_ASSERT((thr)->valstack != NULL); \
-		DUK_ASSERT((thr)->valstack_bottom != NULL); \
-		DUK_ASSERT((thr)->valstack_top != NULL); \
-		DUK_ASSERT((thr)->valstack_end != NULL); \
-		DUK_ASSERT((thr)->valstack_alloc_end != NULL); \
-		DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack); \
-		DUK_ASSERT((thr)->valstack_end >= (thr)->valstack); \
-		DUK_ASSERT((thr)->valstack_top >= (thr)->valstack); \
-		DUK_ASSERT((thr)->valstack_top >= (thr)->valstack_bottom); \
-		DUK_ASSERT((thr)->valstack_end >= (thr)->valstack_top); \
-		DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack_end); \
-	} while (0)
+DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
+#define DUK_CTX_ASSERT_VALID(thr)  do { duk_ctx_assert_valid((thr)); } while (0)
+#else
+#define DUK_HTHREAD_ASSERT_VALID(thr)  do {} while (0)
+#define DUK_CTX_ASSERT_VALID(thr)  do {} while (0)
+#endif
 
 /* Assertions for API call entry specifically.  Checks 'ctx' but also may
  * check internal state (e.g. not in a debugger transport callback).
  */
 #define DUK_ASSERT_API_ENTRY(thr) do { \
-		DUK_ASSERT_CTX_VALID((thr)); \
+		DUK_CTX_ASSERT_VALID((thr)); \
 		DUK_ASSERT((thr)->heap != NULL); \
 		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
 	} while (0)
@@ -7950,11 +8029,12 @@
 #if !defined(DUK_HARRAY_H_INCLUDED)
 #define DUK_HARRAY_H_INCLUDED
 
-#define DUK_ASSERT_HARRAY_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \
-		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
+#define DUK_HARRAY_ASSERT_VALID(h)  do { duk_harray_assert_valid((h)); } while (0)
+#else
+#define DUK_HARRAY_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 #define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
 #define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
@@ -7995,18 +8075,15 @@
 #if !defined(DUK_HENV_H_INCLUDED)
 #define DUK_HENV_H_INCLUDED
 
-#define DUK_ASSERT_HDECENV_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) (h))); \
-		DUK_ASSERT((h)->thread == NULL || (h)->varmap != NULL); \
-	} while (0)
-
-#define DUK_ASSERT_HOBJENV_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) (h))); \
-		DUK_ASSERT((h)->target != NULL); \
-		DUK_ASSERT((h)->has_this == 0 || (h)->has_this == 1); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
+DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
+#define DUK_HDECENV_ASSERT_VALID(h)  do { duk_hdecenv_assert_valid((h)); } while (0)
+#define DUK_HOBJENV_ASSERT_VALID(h)  do { duk_hobjenv_assert_valid((h)); } while (0)
+#else
+#define DUK_HDECENV_ASSERT_VALID(h)  do {} while (0)
+#define DUK_HOBJENV_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 struct duk_hdecenv {
 	/* Shared object part. */
@@ -8202,6 +8279,14 @@
 	)
 #endif
 
+/* Validity assert. */
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
+#define DUK_HBUFFER_ASSERT_VALID(h)  do { duk_hbuffer_assert_valid((h)); } while (0)
+#else
+#define DUK_HBUFFER_ASSERT_VALID(h)  do {} while (0)
+#endif
+
 /*
  *  Structs
  */
@@ -8375,12 +8460,12 @@
 #if !defined(DUK_HPROXY_H_INCLUDED)
 #define DUK_HPROXY_H_INCLUDED
 
-#define DUK_ASSERT_HPROXY_VALID(h) do { \
-		DUK_ASSERT((h) != NULL); \
-		DUK_ASSERT((h)->target != NULL); \
-		DUK_ASSERT((h)->handler != NULL); \
-		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) (h))); \
-	} while (0)
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
+#define DUK_HPROXY_ASSERT_VALID(h)  do { duk_hproxy_assert_valid((h)); } while (0)
+#else
+#define DUK_HPROXY_ASSERT_VALID(h)  do {} while (0)
+#endif
 
 struct duk_hproxy {
 	/* Shared object part. */
@@ -8466,20 +8551,17 @@
  */
 #define DUK_MS_FLAG_EMERGENCY                (1U << 0)
 
-/* Voluntary mark-and-sweep: triggered periodically. */
-#define DUK_MS_FLAG_VOLUNTARY                (1U << 1)
-
 /* Postpone rescue decisions for reachable objects with FINALIZED set.
  * Used during finalize_list processing to avoid incorrect rescue
  * decisions due to finalize_list being a reachability root.
  */
-#define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 2)
+#define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 1)
 
 /* Don't compact objects; needed during object property table resize
  * to prevent a recursive resize.  It would suffice to protect only the
  * current object being resized, but this is not yet implemented.
  */
-#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 3)
+#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 2)
 
 /*
  *  Thread switching
@@ -8736,6 +8818,13 @@
  *  Main heap structure
  */
 
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
+#define DUK_HEAP_ASSERT_VALID(heap)  do { duk_heap_assert_valid((heap)); } while (0)
+#else
+#define DUK_HEAP_ASSERT_VALID(heap)  do {} while (0)
+#endif
+
 struct duk_heap {
 	duk_small_uint_t flags;
 
@@ -8807,6 +8896,11 @@
 
 	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
 	 * refzero events to be ignored (= objects won't be queued to refzero_list).
+	 *
+	 * 0: mark-and-sweep not running
+	 * 1: mark-and-sweep is running
+	 * 2: heap destruction active or debugger active, prevent mark-and-sweep
+	 *    and refzero processing (but mark-and-sweep not itself running)
 	 */
 	duk_uint_t ms_running;
 
@@ -9025,6 +9119,11 @@
 	duk_int_t stats_putprop_proxy;
 	duk_int_t stats_getvar_all;
 	duk_int_t stats_putvar_all;
+	duk_int_t stats_envrec_delayedcreate;
+	duk_int_t stats_envrec_create;
+	duk_int_t stats_envrec_newenv;
+	duk_int_t stats_envrec_oldenv;
+	duk_int_t stats_envrec_pushclosure;
 #endif
 };
 
@@ -9629,6 +9728,10 @@
 #define DUK_ERROR_UNSUPPORTED(thr) do { \
 		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
 	} while (0)
+#define DUK_DCERROR_UNSUPPORTED(thr) do { \
+		DUK_ERROR_UNSUPPORTED((thr)); \
+		return 0; \
+	} while (0)
 #define DUK_ERROR_ERROR(thr,msg) do { \
 		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
 	} while (0)
@@ -9717,6 +9820,10 @@
 #define DUK_ERROR_UNSUPPORTED(thr) do { \
 		duk_err_error((thr)); \
 	} while (0)
+#define DUK_DCERROR_UNSUPPORTED(thr) do { \
+		DUK_UNREF((thr)); \
+		return DUK_RET_ERROR; \
+	} while (0)
 #define DUK_ERROR_ERROR(thr,msg) do { \
 		duk_err_error((thr)); \
 	} while (0)
@@ -10150,13 +10257,13 @@
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-extern const duk_uint8_t duk_unicode_ids_noa[1063];
+extern const duk_uint8_t duk_unicode_ids_noa[1116];
 #else
 /*
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-extern const duk_uint8_t duk_unicode_ids_noabmp[626];
+extern const duk_uint8_t duk_unicode_ids_noabmp[625];
 #endif
 
 #if defined(DUK_USE_SOURCE_NONBMP)
@@ -10178,7 +10285,7 @@
  *  Automatically generated by extract_chars.py, do not edit!
  */
 
-extern const duk_uint8_t duk_unicode_idp_m_ids_noa[549];
+extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
 #else
 /*
  *  Automatically generated by extract_chars.py, do not edit!
@@ -10191,8 +10298,8 @@
  *  Automatically generated by extract_caseconv.py, do not edit!
  */
 
-extern const duk_uint8_t duk_unicode_caseconv_uc[1386];
-extern const duk_uint8_t duk_unicode_caseconv_lc[680];
+extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
+extern const duk_uint8_t duk_unicode_caseconv_lc[706];
 
 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
 /*
@@ -10242,6 +10349,7 @@
 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp);
 DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end);
 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
+DUK_INTERNAL_DECL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len);
 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
@@ -10376,6 +10484,8 @@
 #endif
 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
+DUK_INTERNAL_DECL duk_bool_t duk_js_isarray_hobject(duk_hobject *h);
+DUK_INTERNAL_DECL duk_bool_t duk_js_isarray(duk_tval *tv);
 
 /* arithmetic */
 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
@@ -10427,12 +10537,13 @@
                                            duk_bool_t add_auto_proto);
 
 /* call handling */
+DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr);
 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
 DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
 DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
 #if defined(DUK_USE_VERBOSE_ERRORS)
-DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key);
+DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key);
 #endif
 
 /* bytecode execution */
@@ -10645,7 +10756,7 @@
 #endif
 
 #endif  /* DUK_SELFTEST_H_INCLUDED */
-#line 82 "duk_internal.h"
+#line 76 "duk_internal.h"
 
 #endif  /* DUK_INTERNAL_H_INCLUDED */
 #line 10 "duk_replacements.c"
@@ -10830,7 +10941,7 @@
 #if defined(DUK_USE_ROM_STRINGS)
 #error ROM support not enabled, rerun configure.py with --rom-support
 #else  /* DUK_USE_ROM_STRINGS */
-DUK_INTERNAL const duk_uint8_t duk_strings_data[967] = {
+DUK_INTERNAL const duk_uint8_t duk_strings_data[972] = {
 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
@@ -10858,34 +10969,34 @@
 113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
 201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
 214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
-242,16,96,152,12,178,52,211,56,228,73,150,83,0,148,39,137,75,67,73,198,209,
-129,36,85,185,201,196,2,32,193,48,17,160,97,16,84,44,156,104,24,67,189,200,
-108,201,19,238,114,96,137,137,50,238,113,164,188,211,185,192,226,100,19,
-134,68,110,112,174,139,0,185,31,115,149,4,88,7,159,115,146,117,34,34,35,
-115,143,22,146,208,210,19,115,140,3,207,185,202,130,36,109,85,185,194,161,
-160,90,50,72,155,115,149,2,232,67,137,204,122,22,66,161,175,164,210,72,199,
-130,137,1,50,32,145,143,38,120,186,195,35,106,51,146,230,8,36,77,109,65,38,
-226,72,159,191,189,181,70,140,133,222,249,212,227,66,125,245,187,251,219,
-77,3,119,190,117,56,208,159,125,110,254,246,210,26,93,239,157,78,52,39,223,
-93,191,189,180,212,52,187,223,58,156,104,79,190,187,127,123,104,180,104,
-183,190,117,56,208,159,125,102,254,209,104,209,124,234,113,161,62,250,80,
-196,128,81,4,9,16,162,4,196,116,9,205,154,27,66,32,100,13,12,98,68,227,33,
-65,69,204,195,34,201,50,8,110,33,23,34,28,168,104,22,188,12,174,138,11,70,
-138,104,115,68,130,137,13,82,27,41,129,162,35,138,54,146,198,137,39,72,180,
-210,178,38,35,146,103,68,139,51,197,214,28,227,131,79,15,35,138,58,130,37,
-19,155,41,146,174,64,203,99,161,100,37,145,51,148,75,4,164,66,54,140,49,46,
-247,70,103,37,230,70,142,70,67,30,232,204,178,163,201,18,54,139,89,39,26,
-16,165,2,228,69,33,143,89,24,70,206,73,67,102,72,148,2,32,214,73,157,224,
-18,128,98,29,241,69,65,50,37,241,116,200,41,144,102,125,2,180,8,210,152,38,
-129,23,8,34,198,
+242,16,96,152,12,26,20,164,137,150,70,154,103,28,137,50,202,96,18,132,241,
+41,104,105,56,218,48,36,138,183,57,56,128,68,24,38,2,52,12,34,10,133,147,
+141,3,8,119,185,13,153,34,125,206,76,17,49,38,93,206,52,151,154,119,56,28,
+76,130,112,200,141,206,21,209,96,23,35,238,114,160,139,0,243,238,114,78,
+164,68,68,110,113,226,210,90,26,66,110,113,128,121,247,57,80,68,141,170,
+183,56,84,52,11,70,73,19,110,114,160,93,8,113,57,143,66,200,84,53,244,154,
+73,24,240,81,32,38,68,18,49,228,207,23,88,100,109,70,114,92,193,4,137,173,
+168,36,220,73,19,247,247,182,168,209,144,187,223,58,156,104,79,190,183,127,
+123,105,160,110,247,206,167,26,19,239,173,223,222,218,67,75,189,243,169,
+198,132,251,235,183,247,182,154,134,151,123,231,83,141,9,247,215,111,239,
+109,22,141,22,247,206,167,26,19,239,172,223,218,45,26,47,157,78,52,39,223,
+74,24,144,10,32,129,34,20,64,152,142,129,57,179,67,104,68,12,129,161,140,
+72,156,100,40,40,185,152,100,89,38,65,13,196,34,228,67,149,13,2,215,129,
+149,209,65,104,209,77,14,104,144,81,33,170,67,101,48,52,68,113,70,210,88,
+209,36,233,22,154,86,68,196,114,76,232,145,102,120,186,195,156,112,105,225,
+228,113,71,80,68,162,115,101,50,85,200,25,108,116,44,132,178,38,114,137,96,
+148,136,70,209,134,37,222,232,204,228,188,200,209,200,200,99,221,25,150,84,
+121,34,70,209,107,36,227,66,20,160,92,136,164,49,235,35,8,217,201,40,108,
+201,18,128,68,26,201,51,188,2,80,12,67,190,40,168,38,68,190,46,153,5,50,12,
+207,160,86,129,26,83,4,208,34,225,4,88,192,
 };
 #endif  /* DUK_USE_ROM_STRINGS */
 
 #if defined(DUK_USE_ROM_OBJECTS)
 #error ROM support not enabled, rerun configure.py with --rom-support
 #else  /* DUK_USE_ROM_OBJECTS */
-/* native functions: 177 */
-DUK_INTERNAL const duk_c_function duk_bi_native_functions[177] = {
+/* native functions: 185 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[185] = {
 	NULL,
 	duk_bi_array_constructor,
 	duk_bi_array_constructor_is_array,
@@ -10911,6 +11022,8 @@
 	duk_bi_buffer_readfield,
 	duk_bi_buffer_slice_shared,
 	duk_bi_buffer_writefield,
+	duk_bi_cbor_decode,
+	duk_bi_cbor_encode,
 	duk_bi_dataview_constructor,
 	duk_bi_date_constructor,
 	duk_bi_date_constructor_now,
@@ -10921,6 +11034,7 @@
 	duk_bi_date_prototype_set_shared,
 	duk_bi_date_prototype_set_time,
 	duk_bi_date_prototype_to_json,
+	duk_bi_date_prototype_toprimitive,
 	duk_bi_date_prototype_tostring_shared,
 	duk_bi_date_prototype_value_of,
 	duk_bi_duktape_object_act,
@@ -10943,6 +11057,7 @@
 	duk_bi_function_prototype_apply,
 	duk_bi_function_prototype_bind,
 	duk_bi_function_prototype_call,
+	duk_bi_function_prototype_hasinstance,
 	duk_bi_function_prototype_to_string,
 	duk_bi_global_object_decode_uri,
 	duk_bi_global_object_decode_uri_component,
@@ -11045,6 +11160,10 @@
 	duk_bi_string_prototype_substring,
 	duk_bi_string_prototype_to_string,
 	duk_bi_string_prototype_trim,
+	duk_bi_symbol_constructor_shared,
+	duk_bi_symbol_key_for,
+	duk_bi_symbol_toprimitive,
+	duk_bi_symbol_tostring_shared,
 	duk_bi_textdecoder_constructor,
 	duk_bi_textdecoder_prototype_decode,
 	duk_bi_textdecoder_prototype_shared_getter,
@@ -11065,577 +11184,604 @@
 	duk_bi_uint8array_plainof,
 };
 #if defined(DUK_USE_DOUBLE_LE)
-DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
-144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
-124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
-167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
-64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
-142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
-242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
-1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
-33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
-174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
-248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
-128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
-154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
-249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
-136,67,134,19,49,0,0,0,0,0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1,
-172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
-149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
-141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
-132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
-96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
-243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
-79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
-147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
-121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
-151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
-180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
-78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
-146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
-70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
-55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
-96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
-103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
-1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
-46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
-217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
-241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
-96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
-46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
-194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
-109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
-240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
-174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
-104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
-194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
-16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
-129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
-224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
-248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
-124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
-131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
-192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
-255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
-245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
-163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
-5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
-34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
-211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
-22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
-197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
-127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
-132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
-190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,255,255,255,
-255,222,254,39,172,67,118,170,5,208,144,0,64,0,0,0,0,0,0,51,16,0,0,0,0,0,0,
-62,31,200,245,238,146,38,138,147,105,13,42,26,137,226,0,0,0,0,0,0,7,131,
-249,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,0,0,0,0,240,255,15,210,
-62,72,91,155,0,0,0,0,0,0,2,192,240,135,88,11,237,72,5,38,210,27,50,24,145,
-129,255,255,255,255,255,254,126,134,67,172,67,118,164,2,147,105,13,153,12,
-72,192,255,255,255,255,255,255,63,195,16,240,70,68,226,27,51,199,138,120,
-35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,
-144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,
-142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,
-224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,
-92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,
-210,98,177,252,3,107,173,88,3,146,211,141,32,0,0,0,0,0,3,225,255,19,175,
-188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,
-161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,
-18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,
-8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,
-32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,
-57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
-153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
-144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
-22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
-166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
-39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
-32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
-68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
-16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
-11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
-36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
-191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
-43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
-201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
-123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
-215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
-131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
-176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
-127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
-57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
-191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
-80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
-220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
-27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
-186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
-28,24,61,73,25,33,205,128,0,0,0,0,1,167,166,129,108,242,151,15,39,8,34,26,
-87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
-130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
-80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
-139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
-0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
-0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
-130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
-62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
-159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
-133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
-62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
-217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
-244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
-158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
-196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,168,71,
-161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,200,
-71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,
-232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,
-8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,40,
-71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,72,
-71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,
-104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,
-52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135,
-52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
-50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
-214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
-136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
-161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
-171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
-4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
-89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
-29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
-207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
-235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
-108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
-155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
-122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
-218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
-75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
-137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
-131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
-73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
-117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
-226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
-114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
-162,137,147,111,2,8,4,16,7,8,96,120,72,13,42,226,145,97,87,224,168,1,58,
-182,232,232,64,22,85,181,187,177,107,2,64,7,213,183,74,7,121,207,215,242,
-17,119,49,248,94,173,198,210,36,15,232,34,182,84,113,95,115,240,221,91,141,
-163,160,72,1,220,164,194,175,121,123,103,224,186,244,64,24,45,68,84,251,33,
-9,64,15,217,66,51,209,218,210,129,154,118,254,205,61,65,204,126,23,178,132,
-103,165,3,52,237,253,154,122,131,216,254,168,48,6,90,130,1,0,39,75,80,72,8,
-9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,
-65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,
-8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,
-168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,
-216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,
-234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,
-115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,
-76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,
-192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,
-182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,
-49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,
-39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,
-100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,
-217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,
-225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,
-156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,
-114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,
-69,145,132,108,224,0,0,0,0,0,0,120,31,153,172,56,132,122,28,76,146,218,121,
-35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,30,176,33,
-184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,
-242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,88,145,8,244,56,153,37,
-180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,161,8,244,56,153,37,
-180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,177,8,244,56,153,37,
-180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,193,8,244,56,153,
-37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,209,8,244,56,
-153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,225,8,244,
-56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,64,32,227,194,0,
-97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,
-29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,
-112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,
-240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,
-148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,
-214,3,192,
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
+144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
+124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
+167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
+64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
+142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
+242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
+1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
+33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
+198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
+10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
+53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
+84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
+109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
+11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
+145,153,136,0,0,0,0,0,0,31,15,249,152,0,0,0,0,0,0,30,15,249,120,144,13,96,
+155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
+194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
+137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
+36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
+209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
+144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
+122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
+136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
+195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
+17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
+2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
+35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
+174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
+0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
+73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
+89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
+144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
+78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
+196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
+132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
+162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
+160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
+151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
+113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
+129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
+168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
+153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
+36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
+203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
+136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
+207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
+37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
+44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
+231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
+30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
+196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
+35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
+34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
+120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
+68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
+228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
+18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
+249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
+102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
+9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
+255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
+57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
+130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
+11,161,32,127,255,255,255,255,255,247,191,137,235,16,221,170,129,116,36,0,
+16,0,0,0,0,0,0,12,196,0,0,0,0,0,0,15,135,242,61,123,164,137,162,164,218,67,
+74,134,162,120,128,0,0,0,0,0,1,224,254,71,173,33,129,52,84,155,72,105,80,
+212,79,16,0,0,0,0,0,0,60,63,195,244,143,146,22,230,192,0,0,0,0,0,0,176,60,
+33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,255,255,255,255,159,161,
+144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,255,255,255,255,207,
+240,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
+92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
+194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
+0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
+18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
+5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,0,
+0,0,0,248,127,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
+185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
+130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
+197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
+12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
+218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
+98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
+250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
+40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
+49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
+56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
+173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
+168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
+18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
+210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
+72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
+72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
+186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
+50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
+74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
+186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
+162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
+55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
+48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
+82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
+144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
+221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
+105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
+137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
+23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
+19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
+72,115,96,0,0,0,0,0,15,106,32,91,60,165,195,201,194,8,134,149,216,162,0,
+192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
+195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
+1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
+36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
+0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
+102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
+20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
+216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
+81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
+166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
+20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
+68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
+159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
+67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
+173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
+140,35,103,0,0,0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,
+162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,
+201,29,162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,
+211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,
+150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,
+100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,
+226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,
+208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,
+35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,
+154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
+25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
+235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
+196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
+200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
+213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
+183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
+221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
+31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
+18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
+59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
+39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
+73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
+61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
+67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
+167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
+68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
+193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
+178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
+157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
+81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
+133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
+22,209,68,201,187,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,
+157,91,116,116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,
+249,8,187,152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,
+198,209,208,36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,
+144,132,160,7,236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,
+217,66,51,210,129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,194,
+1,0,39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,
+65,6,51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,
+80,0,201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,
+69,234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,
+165,1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,
+107,64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,
+132,103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,
+145,52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,
+104,146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,
+56,18,52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,
+47,129,6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,
+15,155,163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,
+36,3,17,46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,
+248,75,204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,
+206,9,113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,
+178,66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,
+38,232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,
+38,3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,
+202,160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,
+0,0,179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,
+181,192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,
+121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,
+146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,
+30,176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,
+153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,
+56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,
+244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,
+8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,
+193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,
+120,209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,
+51,120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,
+64,32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,
+137,112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,
+34,74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,
+8,35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,
+117,96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,
+32,148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,
+238,2,3,107,173,218,3,192,
 };
 #elif defined(DUK_USE_DOUBLE_BE)
-DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
-144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
-124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
-167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
-64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
-142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
-242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
-1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
-33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
-174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
-248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
-128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
-154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
-249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
-136,67,134,19,49,1,255,224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1,
-172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
-149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
-141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
-132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
-96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
-243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
-79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
-147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
-121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
-151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
-180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
-78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
-146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
-70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
-55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
-96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
-103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
-1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
-46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
-217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
-241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
-96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
-46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
-194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
-109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
-240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
-174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
-104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
-194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
-16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
-129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
-224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
-248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
-124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
-131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
-192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
-255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
-245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
-163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
-5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
-34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
-211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
-22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
-197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
-127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
-132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
-190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,128,255,223,255,255,255,
-255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,0,0,0,115,16,31,254,0,0,
-0,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,3,255,128,0,0,0,0,0,
-1,30,180,134,4,209,82,109,33,165,67,81,60,64,255,240,0,0,0,0,0,0,15,210,62,
-72,91,155,0,242,192,0,0,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,128,
-134,127,255,255,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,72,
-192,195,63,255,255,255,255,255,255,16,240,70,68,226,27,51,199,138,120,35,
-34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,144,
-196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,142,
-224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,224,
-3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,92,
-221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,210,
-98,177,252,3,107,173,88,3,146,211,141,33,255,224,0,0,0,0,0,3,19,175,188,0,
-100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,161,166,
-188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,18,155,
-184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,8,77,
-133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,32,
-35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,57,
-179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
-153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
-144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
-22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
-166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
-39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
-32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
-68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
-16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
-11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
-36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
-191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
-43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
-201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
-123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
-215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
-131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
-176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
-127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
-57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
-191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
-80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
-220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
-27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
-186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
-28,24,61,73,25,33,205,128,129,167,166,0,0,0,0,1,108,242,151,15,39,8,34,26,
-87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
-130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
-80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
-139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
-0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
-0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
-130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
-62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
-159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
-133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
-62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
-217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
-244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
-158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
-196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,168,71,
-161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,200,
-71,161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,
-232,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,
-8,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,40,
-71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,72,
-71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,
-104,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,
-52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,2,1,0,0,0,0,0,0,1,135,
-52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
-50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
-214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
-136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
-161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
-171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
-4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
-89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
-29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
-207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
-235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
-108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
-155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
-122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
-218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
-75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
-137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
-131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
-73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
-117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
-226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
-114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
-162,137,147,111,2,8,4,16,7,8,96,120,72,8,0,183,225,81,98,138,237,33,58,182,
-232,232,64,64,2,107,177,187,181,85,22,7,213,183,74,1,255,49,114,23,247,209,
-207,120,94,173,198,210,36,3,255,113,84,118,82,184,47,224,221,91,141,163,
-160,72,7,251,121,111,98,164,220,161,192,186,244,64,64,9,33,251,84,68,45,24,
-15,217,66,51,209,218,210,128,127,205,65,60,204,254,119,154,23,178,132,103,
-165,0,255,218,130,121,153,252,239,54,168,48,6,90,130,1,0,39,75,80,72,8,9,
-33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,65,
-17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,8,
-41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,168,
-40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,216,
-134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,234,
-10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,115,3,
-117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,76,
-130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,192,
-56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,182,
-140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,49,
-39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,39,
-199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,100,
-128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,217,
-114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,225,
-64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,156,
-113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,114,1,
-18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,69,145,
-132,108,224,31,248,0,0,0,0,0,0,25,172,56,132,122,28,76,146,218,121,35,180,
-69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,176,33,184,0,0,
-175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,242,71,
-104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,88,145,8,244,56,153,37,180,242,
-71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,161,8,244,56,153,37,180,242,
-71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,177,8,244,56,153,37,180,242,
-71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,193,8,244,56,153,37,180,
-242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,209,8,244,56,153,37,
-180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,225,8,244,56,153,
-37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,32,227,194,0,97,57,
-162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,29,153,
-1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,112,28,
-211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,240,117,
-32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,148,25,
-174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,214,3,
-192,
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
+144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
+124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
+167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
+64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
+142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
+242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
+1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
+33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
+198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
+10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
+53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
+84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
+109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
+11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
+145,153,136,15,255,0,0,0,0,0,0,25,152,15,254,0,0,0,0,0,0,25,120,144,13,96,
+155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
+194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
+137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
+36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
+209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
+144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
+122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
+136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
+195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
+17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
+2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
+35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
+174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
+0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
+73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
+89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
+144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
+78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
+196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
+132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
+162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
+160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
+151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
+113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
+129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
+168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
+153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
+36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
+203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
+136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
+207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
+37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
+44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
+231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
+30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
+196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
+35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
+34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
+120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
+68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
+228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
+18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
+249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
+102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
+9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
+255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
+57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
+130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
+11,161,32,63,247,255,255,255,255,255,255,137,235,16,221,170,129,116,36,0,0,
+0,0,0,0,0,0,28,196,7,255,128,0,0,0,0,0,2,61,123,164,137,162,164,218,67,74,
+134,162,120,128,255,224,0,0,0,0,0,0,71,173,33,129,52,84,155,72,105,80,212,
+79,16,63,252,0,0,0,0,0,0,3,244,143,146,22,230,192,60,176,0,0,0,0,0,0,33,
+214,2,251,82,1,73,180,134,204,134,36,96,33,159,255,255,255,255,255,255,144,
+235,16,221,169,0,164,218,67,102,67,18,48,48,207,255,255,255,255,255,255,
+196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,92,
+42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
+194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
+0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
+18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
+5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,127,
+248,0,0,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
+185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
+130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
+197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
+12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
+218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
+98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
+250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
+40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
+49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
+56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
+173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
+168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
+18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
+210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
+72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
+72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
+186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
+50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
+74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
+186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
+162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
+55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
+48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
+82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
+144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
+221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
+105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
+137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
+23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
+19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
+72,115,96,32,106,15,0,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
+192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
+195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
+1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
+36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
+0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
+102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
+20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
+216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
+81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
+166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
+20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
+68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
+159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
+67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
+173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
+140,35,103,0,255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
+162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,
+201,29,162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,
+211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,
+150,211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,
+100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,
+226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,
+208,226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,
+35,208,226,100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,
+154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
+25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
+235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
+196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
+200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
+213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
+183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
+221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
+31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
+18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
+59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
+39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
+73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
+61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
+67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
+167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
+68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
+193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
+178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
+157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
+81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
+133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
+22,209,68,201,187,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,
+157,91,116,116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,
+11,251,232,231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,
+198,209,208,36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,
+34,22,140,7,236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,
+66,51,210,128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,194,1,0,
+39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
+51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
+201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
+234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
+1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
+64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
+103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
+52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
+146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
+52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
+6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
+163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
+46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
+204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
+113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
+66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
+232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
+3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
+160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
+179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
+192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
+35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,
+218,121,35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,
+176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
+37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,
+153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,
+56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,
+244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,
+8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,
+209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,
+120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,
+32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
+112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
+74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
+35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
+96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
+148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
+3,107,173,218,3,192,
 };
 #elif defined(DUK_USE_DOUBLE_ME)
-DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
-144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
-124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
-167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
-64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
-142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
-242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
-1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
-33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
-174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
-248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
-128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
-154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
-249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
-136,67,134,19,49,0,0,3,225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1,
-172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
-149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
-141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
-132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
-96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
-243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
-79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
-147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
-121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
-151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
-180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
-78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
-146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
-70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
-55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
-96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
-103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
-1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
-46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
-217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
-241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
-96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
-46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
-194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
-109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
-240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
-174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
-104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
-194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
-16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
-129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
-224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
-248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
-124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
-131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
-192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
-255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
-245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
-163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
-5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
-34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
-211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
-22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
-197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
-127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
-132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
-190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,222,255,255,
-255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,64,0,0,51,16,0,0,62,31,
-192,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,0,0,7,131,248,0,0,
-0,1,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,240,255,0,0,0,0,15,210,
-62,72,91,155,0,0,2,192,240,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,
-129,255,254,126,135,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,
-72,192,255,255,63,195,255,255,255,255,16,240,70,68,226,27,51,199,138,120,
-35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,
-144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,
-142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,
-224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,
-92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,
-210,98,177,252,3,107,173,88,3,146,211,141,32,0,3,225,252,0,0,0,3,19,175,
-188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,
-161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,
-18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,
-8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,
-32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,
-57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
-153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
-144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
-22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
-166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
-39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
-32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
-68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
-16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
-11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
-36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
-191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
-43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
-201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
-123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
-215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
-131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
-176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
-127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
-57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
-191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
-80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
-220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
-27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
-186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
-28,24,61,73,25,33,205,128,1,167,166,128,0,0,0,1,108,242,151,15,39,8,34,26,
-87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
-130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
-80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
-139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
-0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
-0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
-130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
-62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
-159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
-133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
-62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
-217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
-244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
-158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
-196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,168,71,
-161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,200,
-71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,
-232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,
-8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,40,
-71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,72,
-71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,
-104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,
-52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135,
-52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
-50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
-214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
-136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
-161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
-171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
-4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
-89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
-29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
-207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
-235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
-108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
-155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
-122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
-218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
-75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
-137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
-131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
-73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
-117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
-226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
-114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
-162,137,147,111,2,8,4,16,7,8,96,120,72,1,87,224,168,13,42,226,145,97,58,
-182,232,232,64,177,107,2,64,22,85,181,187,7,213,183,74,2,17,119,49,255,121,
-207,215,240,94,173,198,210,36,4,113,95,115,255,232,34,182,80,221,91,141,
-163,160,72,15,121,123,103,225,220,164,194,160,186,244,64,251,33,9,64,24,45,
-68,84,15,217,66,51,209,218,210,129,61,65,204,127,154,118,254,204,23,178,
-132,103,165,2,122,131,216,255,52,237,253,154,168,48,6,90,130,1,0,39,75,80,
-72,8,9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,
-128,65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,
-234,10,8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,
-141,168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,
-47,0,216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,
-209,234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,
-192,115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,
-113,67,76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,
-1,78,192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,
-147,182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,
-188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,
-14,49,39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,
-35,100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,
-28,217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,
-32,225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,
-76,156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,
-114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,
-69,145,132,108,224,0,0,120,31,128,0,0,0,25,172,56,132,122,28,76,146,218,
-121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,176,
-33,184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,
-180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,88,145,8,244,56,153,
-37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,161,8,244,56,153,
-37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,177,8,244,56,153,
-37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,193,8,244,56,
-153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,209,8,244,
-56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,225,8,
-244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,32,227,194,
-0,97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,
-29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,
-112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,
-240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,
-148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,
-214,3,192,
+DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
+144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
+124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
+167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
+64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
+142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
+242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
+1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
+33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
+198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
+10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
+53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
+84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
+109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
+11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
+145,153,136,0,0,31,15,224,0,0,0,25,152,0,0,30,15,224,0,0,0,25,120,144,13,
+96,155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,
+23,194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
+137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
+36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
+209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
+144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
+122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
+136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
+195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
+17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
+2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
+35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
+174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
+0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
+73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
+89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
+144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
+78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
+196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
+132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
+162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
+160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
+151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
+113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
+129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
+168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
+153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
+36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
+203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
+136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
+207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
+37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
+44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
+231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
+30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
+196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
+35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
+34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
+120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
+68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
+228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
+18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
+249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
+102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
+9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
+255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
+57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
+130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
+11,161,32,127,255,247,191,255,255,255,255,137,235,16,221,170,129,116,36,0,
+0,0,0,0,16,0,0,12,196,0,0,15,135,240,0,0,0,2,61,123,164,137,162,164,218,67,
+74,134,162,120,128,0,1,224,254,0,0,0,0,71,173,33,129,52,84,155,72,105,80,
+212,79,16,0,0,60,63,192,0,0,0,3,244,143,146,22,230,192,0,0,176,60,0,0,0,0,
+33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,159,161,255,255,255,255,
+144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,207,240,255,255,255,
+255,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
+92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
+194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
+0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
+18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
+5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,
+248,127,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
+185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
+130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
+197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
+12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
+218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
+98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
+250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
+40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
+49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
+56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
+173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
+168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
+18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
+210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
+72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
+72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
+186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
+50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
+74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
+186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
+162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
+55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
+48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
+82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
+144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
+221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
+105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
+137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
+23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
+19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
+72,115,96,0,15,106,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
+192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
+195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
+1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
+36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
+0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
+102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
+20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
+216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
+81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
+166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
+20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
+68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
+159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
+67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
+173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
+140,35,103,0,0,3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
+162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,
+201,29,162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,
+211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,
+150,211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,
+100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,
+226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,
+208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,
+35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,
+154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
+25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
+235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
+196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
+200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
+213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
+183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
+221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
+31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
+18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
+59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
+39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
+73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
+61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
+67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
+167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
+68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
+193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
+178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
+157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
+81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
+133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
+22,209,68,201,187,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,
+157,91,116,116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,
+255,188,231,235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,
+198,209,208,36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,
+22,162,42,7,236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,
+66,51,210,129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,194,1,0,
+39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
+51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
+201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
+234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
+1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
+64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
+103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
+52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
+146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
+52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
+6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
+163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
+46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
+204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
+113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
+66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
+232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
+3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
+160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
+179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
+192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
+35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,
+218,121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,
+176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
+37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,
+153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,
+56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,
+244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,
+8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,
+209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,
+120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,
+32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
+112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
+74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
+35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
+96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
+148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
+3,107,173,218,3,192,
 };
 #else
 #error invalid endianness defines
@@ -12200,6 +12346,90 @@
 }
 #endif  /* DUK_USE_PREFER_SIZE */
 
+/* Check whether a string is UTF-8 compatible or not. */
+DUK_INTERNAL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len) {
+	duk_size_t i = 0;
+#if !defined(DUK_USE_PREFER_SIZE)
+	duk_size_t len_safe;
+#endif
+
+	/* Many practical strings are ASCII only, so use a fast path check
+	 * to check chunks of bytes at once with minimal branch cost.
+	 */
+#if !defined(DUK_USE_PREFER_SIZE)
+	len_safe = len & ~0x03UL;
+	for (; i < len_safe; i += 4) {
+		duk_uint8_t t = buf[i] | buf[i + 1] | buf[i + 2] | buf[i + 3];
+		if (DUK_UNLIKELY((t & 0x80U) != 0U)) {
+			/* At least one byte was outside 0x00-0x7f, break
+			 * out to slow path (and remain there).
+			 *
+			 * XXX: We could also deal with the problem character
+			 * and resume fast path later.
+			 */
+			break;
+		}
+	}
+#endif
+
+	for (; i < len;) {
+		duk_uint8_t t;
+		duk_size_t left;
+		duk_size_t ncont;
+		duk_uint32_t cp;
+		duk_uint32_t mincp;
+
+		t = buf[i++];
+		if (DUK_LIKELY((t & 0x80U) == 0U)) {
+			/* Fast path, ASCII. */
+			continue;
+		}
+
+		/* Non-ASCII start byte, slow path.
+		 *
+		 * 10xx xxxx          -> continuation byte
+		 * 110x xxxx + 1*CONT -> [0x80, 0x7ff]
+		 * 1110 xxxx + 2*CONT -> [0x800, 0xffff], must reject [0xd800,0xdfff]
+		 * 1111 0xxx + 3*CONT -> [0x10000, 0x10ffff]
+		 */
+		left = len - i;
+		if (t <= 0xdfU) {  /* 1101 1111 = 0xdf */
+			if (t <= 0xbfU) {  /* 1011 1111 = 0xbf */
+				return 0;
+			}
+			ncont = 1;
+			mincp = 0x80UL;
+			cp = t & 0x1fU;
+		} else if (t <= 0xefU) {  /* 1110 1111 = 0xef */
+			ncont = 2;
+			mincp = 0x800UL;
+			cp = t & 0x0fU;
+		} else if (t <= 0xf7U) {  /* 1111 0111 = 0xf7 */
+			ncont = 3;
+			mincp = 0x10000UL;
+			cp = t & 0x07U;
+		} else {
+			return 0;
+		}
+		if (left < ncont) {
+			return 0;
+		}
+		while (ncont > 0U) {
+			t = buf[i++];
+			if ((t & 0xc0U) != 0x80U) {  /* 10xx xxxx */
+				return 0;
+			}
+			cp = (cp << 6) + (t & 0x3fU);
+			ncont--;
+		}
+		if (cp < mincp || cp > 0x10ffffUL || (cp >= 0xd800UL && cp <= 0xdfffUL)) {
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
 /*
  *  Unicode range matcher
  *
@@ -12982,6 +13212,155 @@
 };
 
 #endif  /* DUK_USE_REGEXP_SUPPORT */
+#line 1 "duk_util_memrw.c"
+/*
+ *  Macro support functions for reading/writing raw data.
+ *
+ *  These are done using memcpy to ensure they're valid even for unaligned
+ *  reads/writes on platforms where alignment counts.  On x86 at least gcc
+ *  is able to compile these into a bswap+mov.  "Always inline" is used to
+ *  ensure these macros compile to minimal code.
+ */
+
+/* #include duk_internal.h -> already included */
+
+union duk__u16_union {
+	duk_uint8_t b[2];
+	duk_uint16_t x;
+};
+typedef union duk__u16_union duk__u16_union;
+
+union duk__u32_union {
+	duk_uint8_t b[4];
+	duk_uint32_t x;
+};
+typedef union duk__u32_union duk__u32_union;
+
+#if defined(DUK_USE_64BIT_OPS)
+union duk__u64_union {
+	duk_uint8_t b[8];
+	duk_uint64_t x;
+};
+typedef union duk__u64_union duk__u64_union;
+#endif
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
+	duk__u16_union u;
+	duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
+	u.x = DUK_NTOH16(u.x);
+	return u.x;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
+	duk__u32_union u;
+	duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
+	u.x = DUK_NTOH32(u.x);
+	return u.x;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_read_float_be(const duk_uint8_t *p) {
+	duk_float_union fu;
+	duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
+	duk_fltunion_big_to_host(&fu);
+	return fu.f;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(const duk_uint8_t *p) {
+	duk_double_union du;
+	duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
+	duk_dblunion_big_to_host(&du);
+	return du.d;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
+	duk_uint16_t res = duk_raw_read_u16_be(*p);
+	*p += 2;
+	return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
+	duk_uint32_t res = duk_raw_read_u32_be(*p);
+	*p += 4;
+	return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p) {
+	duk_float_t res = duk_raw_read_float_be(*p);
+	*p += 4;
+	return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p) {
+	duk_double_t res = duk_raw_read_double_be(*p);
+	*p += 8;
+	return res;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
+	duk__u16_union u;
+	u.x = DUK_HTON16(val);
+	duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
+	duk__u32_union u;
+	u.x = DUK_HTON32(val);
+	duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val) {
+	duk_float_union fu;
+	fu.f = val;
+	duk_fltunion_host_to_big(&fu);
+	duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val) {
+	duk_double_union du;
+	du.d = val;
+	duk_dblunion_host_to_big(&du);
+	duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
+}
+
+DUK_INTERNAL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val) {
+	duk_small_int_t len = duk_unicode_encode_xutf8(val, p);
+	return len;
+}
+
+DUK_INTERNAL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val) {
+	duk_small_int_t len = duk_unicode_encode_cesu8(val, p);
+	return len;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
+	duk_raw_write_u16_be(*p, val);
+	*p += 2;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
+	duk_raw_write_u32_be(*p, val);
+	*p += 4;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val) {
+	duk_raw_write_float_be(*p, val);
+	*p += 4;
+}
+
+DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val) {
+	duk_raw_write_double_be(*p, val);
+	*p += 8;
+}
+
+DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
+	duk_small_int_t len = duk_unicode_encode_xutf8(val, *p);
+	*p += len;
+}
+
+DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
+	duk_small_int_t len = duk_unicode_encode_cesu8(val, *p);
+	*p += len;
+}
 #line 1 "duk_util_misc.c"
 /*
  *  Misc util stuff.
@@ -13176,13 +13555,13 @@
 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
 #error constant too large
 #endif
-#if (DUK_STRIDX_ARRAY > 255)
+#if (DUK_STRIDX_UC_ARRAY > 255)
 #error constant too large
 #endif
 #if (DUK_STRIDX_UC_BOOLEAN > 255)
 #error constant too large
 #endif
-#if (DUK_STRIDX_DATE > 255)
+#if (DUK_STRIDX_UC_DATE > 255)
 #error constant too large
 #endif
 #if (DUK_STRIDX_UC_ERROR > 255)
@@ -13265,11 +13644,11 @@
 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
 	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
 	DUK_STRIDX_UC_OBJECT,
-	DUK_STRIDX_ARRAY,
+	DUK_STRIDX_UC_ARRAY,
 	DUK_STRIDX_UC_FUNCTION,
 	DUK_STRIDX_UC_ARGUMENTS,
 	DUK_STRIDX_UC_BOOLEAN,
-	DUK_STRIDX_DATE,
+	DUK_STRIDX_UC_DATE,
 	DUK_STRIDX_UC_ERROR,
 	DUK_STRIDX_JSON,
 	DUK_STRIDX_MATH,
@@ -13432,20 +13811,20 @@
  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
  */
 
-DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_hthread *thr, duk_uint8_t *p) {
+DUK_LOCAL const duk_uint8_t *duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p) {
 	duk_uint32_t len;
 
-	len = DUK_RAW_READ_U32_BE(p);
+	len = DUK_RAW_READINC_U32_BE(p);
 	duk_push_lstring(thr, (const char *) p, len);
 	p += len;
 	return p;
 }
 
-DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) {
+DUK_LOCAL const duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p) {
 	duk_uint32_t len;
 	duk_uint8_t *buf;
 
-	len = DUK_RAW_READ_U32_BE(p);
+	len = DUK_RAW_READINC_U32_BE(p);
 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
 	DUK_ASSERT(buf != NULL);
 	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
@@ -13462,7 +13841,7 @@
 	len = DUK_HSTRING_GET_BYTELEN(h);
 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
 	tmp32 = (duk_uint32_t) len;
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 	duk_memcpy((void *) p,
 	           (const void *) DUK_HSTRING_GET_DATA(h),
 	           len);
@@ -13481,7 +13860,7 @@
 	len = DUK_HBUFFER_GET_SIZE(h);
 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
 	tmp32 = (duk_uint32_t) len;
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 	/* When len == 0, buffer data pointer may be NULL. */
 	duk_memcpy_unsafe((void *) p,
 	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
@@ -13494,7 +13873,7 @@
 	duk_hstring *h_str;
 	duk_tval *tv;
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
 		h_str = DUK_TVAL_GET_STRING(tv);
 		DUK_ASSERT(h_str != NULL);
@@ -13511,7 +13890,7 @@
 DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {
 	duk_tval *tv;
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
 		duk_hbuffer *h_buf;
 		h_buf = DUK_TVAL_GET_BUFFER(tv);
@@ -13521,7 +13900,7 @@
 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
 	} else {
 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
-		DUK_RAW_WRITE_U32_BE(p, 0);
+		DUK_RAW_WRITEINC_U32_BE(p, 0);
 	}
 	return p;
 }
@@ -13530,28 +13909,24 @@
 	duk_tval *tv;
 	duk_uint32_t val;
 
-	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
+	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
 	} else {
 		val = def_value;
 	}
 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
-	DUK_RAW_WRITE_U32_BE(p, val);
+	DUK_RAW_WRITEINC_U32_BE(p, val);
 	return p;
 }
 
 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
-	duk_tval *tv;
-
-	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
-	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
-		duk_hobject *h;
+	duk_hobject *h;
+
+	h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
+	if (h != NULL) {
 		duk_uint_fast32_t i;
 
-		h = DUK_TVAL_GET_OBJECT(tv);
-		DUK_ASSERT(h != NULL);
-
 		/* We know _Varmap only has own properties so walk property
 		 * table directly.  We also know _Varmap is dense and all
 		 * values are numbers; assert for these.  GC and finalizers
@@ -13579,20 +13954,19 @@
 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
 			p = duk__dump_hstring_raw(p, key);
-			DUK_RAW_WRITE_U32_BE(p, val);
+			DUK_RAW_WRITEINC_U32_BE(p, val);
 		}
 	}
 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
-	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
+	DUK_RAW_WRITEINC_U32_BE(p, 0);  /* end of _Varmap */
 	return p;
 }
 
 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
-	duk_tval *tv;
-
-	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
-	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
-		duk_harray *h;
+	duk_harray *h;
+
+	h = duk_hobject_get_formals(thr, (duk_hobject *) func);
+	if (h != NULL) {
 		duk_uint32_t i;
 
 		/* Here we rely on _Formals being a dense array containing
@@ -13600,14 +13974,10 @@
 		 * tweaked by the application (which we don't support right
 		 * now).
 		 */
-		h = (duk_harray *) DUK_TVAL_GET_OBJECT(tv);
-		DUK_ASSERT(h != NULL);
-		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
-		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
 
 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
 		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
-		DUK_RAW_WRITE_U32_BE(p, h->length);
+		DUK_RAW_WRITEINC_U32_BE(p, h->length);
 
 		for (i = 0; i < h->length; i++) {
 			duk_tval *tv_val;
@@ -13628,7 +13998,7 @@
 	} else {
 		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
-		DUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
+		DUK_RAW_WRITEINC_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
 	}
 	return p;
 }
@@ -13668,27 +14038,27 @@
 
 	/* Fixed header info. */
 	tmp32 = count_instr;
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 	tmp16 = func->nregs;
-	DUK_RAW_WRITE_U16_BE(p, tmp16);
+	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
 	tmp16 = func->nargs;
-	DUK_RAW_WRITE_U16_BE(p, tmp16);
+	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
 #if defined(DUK_USE_DEBUGGER_SUPPORT)
 	tmp32 = func->start_line;
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 	tmp32 = func->end_line;
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
-#else
-	DUK_RAW_WRITE_U32_BE(p, 0);
-	DUK_RAW_WRITE_U32_BE(p, 0);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
+#else
+	DUK_RAW_WRITEINC_U32_BE(p, 0);
+	DUK_RAW_WRITEINC_U32_BE(p, 0);
 #endif
 	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
 	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
-	DUK_RAW_WRITE_U32_BE(p, tmp32);
+	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 
 	/* Bytecode instructions: endian conversion needed unless
 	 * platform is big endian.
@@ -13702,7 +14072,7 @@
 #else
 	while (ins != ins_end) {
 		tmp32 = (duk_uint32_t) (*ins);
-		DUK_RAW_WRITE_U32_BE(p, tmp32);
+		DUK_RAW_WRITEINC_U32_BE(p, tmp32);
 		ins++;
 	}
 #endif
@@ -13727,7 +14097,7 @@
 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
 			*p++ = DUK__SER_NUMBER;
 			d = DUK_TVAL_GET_NUMBER(tv);
-			DUK_RAW_WRITE_DOUBLE_BE(p, d);
+			DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
 		}
 		tv++;
 	}
@@ -13788,7 +14158,7 @@
 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
 	} while (0)
 
-static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t *p_end) {
+static const duk_uint8_t *duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end) {
 	duk_hcompfunc *h_fun;
 	duk_hbuffer *h_data;
 	duk_size_t data_size;
@@ -13812,12 +14182,12 @@
 
 	DUK_ASSERT(thr != NULL);
 
-	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
+	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (const void *) p, (const void *) p_end));
 
 	DUK__ASSERT_LEFT(3 * 4);
-	count_instr = DUK_RAW_READ_U32_BE(p);
-	count_const = DUK_RAW_READ_U32_BE(p);
-	count_funcs = DUK_RAW_READ_U32_BE(p);
+	count_instr = DUK_RAW_READINC_U32_BE(p);
+	count_const = DUK_RAW_READINC_U32_BE(p);
+	count_funcs = DUK_RAW_READINC_U32_BE(p);
 
 	data_size = sizeof(duk_tval) * count_const +
 	            sizeof(duk_hobject *) * count_funcs +
@@ -13845,17 +14215,17 @@
 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
 
-	h_fun->nregs = DUK_RAW_READ_U16_BE(p);
-	h_fun->nargs = DUK_RAW_READ_U16_BE(p);
+	h_fun->nregs = DUK_RAW_READINC_U16_BE(p);
+	h_fun->nargs = DUK_RAW_READINC_U16_BE(p);
 #if defined(DUK_USE_DEBUGGER_SUPPORT)
-	h_fun->start_line = DUK_RAW_READ_U32_BE(p);
-	h_fun->end_line = DUK_RAW_READ_U32_BE(p);
+	h_fun->start_line = DUK_RAW_READINC_U32_BE(p);
+	h_fun->end_line = DUK_RAW_READINC_U32_BE(p);
 #else
 	p += 8;  /* skip line info */
 #endif
 
 	/* duk_hcompfunc flags; quite version specific */
-	tmp32 = DUK_RAW_READ_U32_BE(p);
+	tmp32 = DUK_RAW_READINC_U32_BE(p);
 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */
 
 	/* standard prototype (no need to set here, already set) */
@@ -13870,6 +14240,7 @@
 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
+	DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(&h_fun->obj));
 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
@@ -13890,7 +14261,7 @@
 #else
 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
 	for (n = count_instr; n > 0; n--) {
-		*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
+		*((duk_instr_t *) (void *) q) = DUK_RAW_READINC_U32_BE(p);
 		q += sizeof(duk_instr_t);
 	}
 #endif
@@ -13898,7 +14269,7 @@
 	/* Load constants onto value stack but don't yet copy to buffer. */
 	for (n = count_const; n > 0; n--) {
 		DUK__ASSERT_LEFT(1);
-		const_type = DUK_RAW_READ_U8(p);
+		const_type = DUK_RAW_READINC_U8(p);
 		switch (const_type) {
 		case DUK__SER_STRING: {
 			p = duk__load_string_raw(thr, p);
@@ -13911,7 +14282,7 @@
 			duk_tval tv_tmp;
 			duk_double_t val;
 			DUK__ASSERT_LEFT(8);
-			val = DUK_RAW_READ_DOUBLE_BE(p);
+			val = DUK_RAW_READINC_DOUBLE_BE(p);
 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
 			duk_push_tval(thr, &tv_tmp);
 			break;
@@ -13978,7 +14349,7 @@
 	duk_set_top(thr, idx_base + 1);
 
 	/* Setup function properties. */
-	tmp32 = DUK_RAW_READ_U32_BE(p);
+	tmp32 = DUK_RAW_READINC_U32_BE(p);
 	duk_push_u32(thr, tmp32);
 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
 
@@ -14001,7 +14372,7 @@
 		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
 		DUK_ASSERT(new_env->varmap == NULL);
 		DUK_ASSERT(new_env->regbase_byteoff == 0);
-		DUK_ASSERT_HDECENV_VALID(new_env);
+		DUK_HDECENV_ASSERT_VALID(new_env);
 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
 		DUK_HOBJECT_INCREF(thr, func_env);
@@ -14034,9 +14405,11 @@
 
 	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
 		/* Restore empty external .prototype only for constructable
-		 * functions.
+		 * functions.  The prototype object should inherit from
+		 * Object.prototype.
 		 */
 		duk_push_object(thr);
+		DUK_ASSERT(!duk_is_bare_object(thr, -1));
 		duk_dup_m2(thr);
 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
 		duk_compact_m1(thr);
@@ -14048,7 +14421,7 @@
 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
 #endif  /* DUK_USE_PC2LINE */
 
-	duk_push_object(thr);  /* _Varmap */
+	duk_push_bare_object(thr);  /* _Varmap */
 	for (;;) {
 		/* XXX: awkward */
 		p = duk__load_string_raw(thr, p);
@@ -14056,7 +14429,7 @@
 			duk_pop(thr);
 			break;
 		}
-		tmp32 = DUK_RAW_READ_U32_BE(p);
+		tmp32 = DUK_RAW_READINC_U32_BE(p);
 		duk_push_u32(thr, tmp32);
 		duk_put_prop(thr, -3);
 	}
@@ -14066,9 +14439,9 @@
 	/* _Formals may have been missing in the original function, which is
 	 * handled using a marker length.
 	 */
-	arr_limit = DUK_RAW_READ_U32_BE(p);
+	arr_limit = DUK_RAW_READINC_U32_BE(p);
 	if (arr_limit != DUK__NO_FORMALS) {
-		duk_push_array(thr);  /* _Formals */
+		duk_push_bare_array(thr);  /* _Formals */
 		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
 			p = duk__load_string_raw(thr, p);
 			duk_put_prop_index(thr, -2, arr_idx);
@@ -14120,7 +14493,7 @@
 }
 
 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
-	duk_uint8_t *p_buf, *p, *p_end;
+	const duk_uint8_t *p_buf, *p, *p_end;
 	duk_size_t sz;
 
 	DUK_ASSERT_API_ENTRY(thr);
@@ -14264,7 +14637,7 @@
  * May currently throw an error e.g. when getting the property.
  */
 DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(nargs >= 0);
 
 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
@@ -14280,18 +14653,16 @@
 
 #if defined(DUK_USE_VERBOSE_ERRORS)
 	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
-		duk_tval *tv_targ;
 		duk_tval *tv_base;
 		duk_tval *tv_key;
 
-		tv_targ = DUK_GET_TVAL_NEGIDX(thr, -1);
+		/* tv_targ is passed on stack top (at index -1). */
 		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
 		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
-		DUK_ASSERT(tv_targ >= thr->valstack_bottom && tv_targ < thr->valstack_top);
 		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
 		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
 
-		duk_call_setup_propcall_error(thr, tv_targ, tv_base, tv_key);
+		duk_call_setup_propcall_error(thr, tv_base, tv_key);
 	}
 #endif
 
@@ -14361,7 +14732,7 @@
 	duk_idx_t idx_func;
 	duk_int_t ret;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(udata != NULL);
 
 	args = (duk__pcall_args *) udata;
@@ -14397,7 +14768,7 @@
 	duk_idx_t idx_func;
 	duk_int_t ret;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(udata != NULL);
 
 	args = (duk__pcall_method_args *) udata;
@@ -14438,7 +14809,7 @@
 	duk_idx_t obj_idx;
 	duk_int_t ret;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(udata != NULL);
 
 	args = (duk__pcall_prop_args *) udata;
@@ -14564,10 +14935,7 @@
 	return 0;
 }
 
-/* XXX: Make this obsolete by adding a function flag for rejecting a
- * non-constructor call automatically?
- */
-DUK_INTERNAL void duk_require_constructor_call(duk_hthread *thr) {
+DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr) {
 	DUK_ASSERT_API_ENTRY(thr);
 
 	if (!duk_is_constructor_call(thr)) {
@@ -14673,7 +15041,7 @@
 DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
 	duk_tval *tv;
 
-	DUK_ASSERT_HTHREAD_VALID(thr);
+	DUK_HTHREAD_ASSERT_VALID(thr);
 
 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
 	if (DUK_TVAL_IS_OBJECT(tv)) {
@@ -14719,23 +15087,34 @@
 
 /* Shared handling for encode/decode argument.  Fast path handling for
  * buffer and string values because they're the most common.  In particular,
- * avoid creating a temporary string or buffer when possible.
+ * avoid creating a temporary string or buffer when possible.  Return value
+ * is guaranteed to be non-NULL, even for zero length input.
  */
 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
-	void *ptr;
+	const void *def_ptr = (const void *) out_len;  /* Any non-NULL pointer will do. */
+	const void *ptr;
 	duk_bool_t isbuffer;
 
+	DUK_ASSERT(out_len != NULL);
+	DUK_ASSERT(def_ptr != NULL);
 	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */
 
-	/* XXX: with def_ptr set to a stack related pointer, isbuffer could
-	 * be removed from the helper?
-	 */
-	ptr = duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
+	ptr = (const void *) duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
 	if (isbuffer) {
-		DUK_ASSERT(*out_len == 0 || ptr != NULL);
-		return (const duk_uint8_t *) ptr;
-	}
-	return (const duk_uint8_t *) duk_to_lstring(thr, idx, out_len);
+		DUK_ASSERT(ptr != NULL || *out_len == 0U);
+		if (DUK_UNLIKELY(ptr == NULL)) {
+			ptr = def_ptr;
+		}
+		DUK_ASSERT(ptr != NULL);
+	} else {
+		/* For strings a non-NULL pointer is always guaranteed because
+		 * at least a NUL will be present.
+		 */
+		ptr = (const void *) duk_to_lstring(thr, idx, out_len);
+		DUK_ASSERT(ptr != NULL);
+	}
+	DUK_ASSERT(ptr != NULL);
+	return (const duk_uint8_t *) ptr;
 }
 
 /*
@@ -14979,6 +15358,8 @@
 	const duk_uint8_t *p_end_safe;
 	duk_uint8_t *q;
 
+	DUK_ASSERT(src != NULL);  /* Required by pointer arithmetic below, which fails for NULL. */
+
 	p = src;
 	p_end = src + srclen;
 	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
@@ -15314,7 +15695,7 @@
 
 	idx = duk_require_normalize_index(thr, idx);
 	src = duk__prep_codec_arg(thr, idx, &srclen);
-	/* Note: for srclen=0, src may be NULL */
+	DUK_ASSERT(src != NULL);
 
 	/* Compute exact output length.  Computation must not wrap; this
 	 * limit works for 32-bit size_t:
@@ -15350,6 +15731,7 @@
 
 	idx = duk_require_normalize_index(thr, idx);
 	src = duk__prep_codec_arg(thr, idx, &srclen);
+	DUK_ASSERT(src != NULL);
 
 	/* Round up and add safety margin.  Avoid addition before division to
 	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
@@ -15379,7 +15761,7 @@
 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
 	DUK_UNREF(idx);
 	DUK_ERROR_UNSUPPORTED(thr);
-	DUK_WO_NORETURN(return;);
+	DUK_WO_NORETURN(return NULL;);
 }
 
 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
@@ -15409,7 +15791,7 @@
 
 	idx = duk_require_normalize_index(thr, idx);
 	inp = duk__prep_codec_arg(thr, idx, &len);
-	DUK_ASSERT(inp != NULL || len == 0);
+	DUK_ASSERT(inp != NULL);
 
 	/* Fixed buffer, no zeroing because we'll fill all the data. */
 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
@@ -15466,7 +15848,7 @@
 
 	idx = duk_require_normalize_index(thr, idx);
 	inp = duk__prep_codec_arg(thr, idx, &len);
-	DUK_ASSERT(inp != NULL || len == 0);
+	DUK_ASSERT(inp != NULL);
 
 	if (len & 0x01) {
 		goto type_error;
@@ -15541,7 +15923,7 @@
 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
 	DUK_UNREF(idx);
 	DUK_ERROR_UNSUPPORTED(thr);
-	DUK_WO_NORETURN(return;);
+	DUK_WO_NORETURN(return NULL;);
 }
 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
 	DUK_UNREF(idx);
@@ -15678,7 +16060,7 @@
 	duk_uint_t flags;
 	duk_hcompfunc *h_templ;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(udata != NULL);
 
 	/* Note: strictness is not inherited from the current Duktape/C
@@ -15807,7 +16189,7 @@
 	 */
 
 	top = duk_get_top(thr);
-	duk_push_array(thr);
+	duk_push_bare_array(thr);
 	for (idx = 0; idx < top; idx++) {
 		duk_dup(thr, idx);
 		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
@@ -16063,6 +16445,7 @@
 	duk_ljstate lj;
 	duk_bool_t creating_error;
 	duk_hthread *curr_thread;
+	duk_uint8_t thread_state;
 	duk_int_t call_recursion_depth;
 };
 
@@ -16161,6 +16544,7 @@
 	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
 	snapshot->creating_error = heap->creating_error;
 	snapshot->curr_thread = heap->curr_thread;
+	snapshot->thread_state = thr->state;
 	snapshot->call_recursion_depth = heap->call_recursion_depth;
 
 	lj->jmpbuf_ptr = NULL;
@@ -16170,6 +16554,8 @@
 	heap->creating_error = 0;
 	heap->curr_thread = NULL;
 	heap->call_recursion_depth = 0;
+
+	thr->state = DUK_HTHREAD_STATE_INACTIVE;
 }
 
 DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
@@ -16186,6 +16572,8 @@
 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
 	DUK_ASSERT(thr->heap->creating_error == 0);
 
+	thr->state = snapshot->thread_state;
+
 	heap = thr->heap;
 
 	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
@@ -16694,6 +17082,57 @@
 	return duk_to_boolean_top_pop(thr);
 }
 
+/* This get variant is for internal use, it differs from standard
+ * duk_get_prop() in that:
+ *   - Object argument must be an object (primitive values not supported).
+ *   - Key argument must be a string (no coercion).
+ *   - Only own properties are checked (no inheritance).  Only "entry part"
+ *     properties are checked (not array index properties).
+ *   - Property must be a plain data property, not a getter.
+ *   - Proxy traps are not triggered.
+ */
+DUK_INTERNAL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx) {
+	duk_hobject *h_obj;
+	duk_hstring *h_key;
+	duk_tval *tv_val;
+
+	DUK_ASSERT_API_ENTRY(thr);
+
+	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
+	 * resize is not necessary for a property get right now.
+	 */
+
+	h_obj = duk_get_hobject(thr, obj_idx);
+	if (h_obj == NULL) {
+		return 0;
+	}
+	h_key = duk_require_hstring(thr, -1);
+
+	tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
+	if (tv_val == NULL) {
+		return 0;
+	}
+
+	duk_push_tval(thr, tv_val);
+	duk_remove_m2(thr);  /* remove key */
+
+	return 1;
+}
+
+DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
+	DUK_ASSERT_API_ENTRY(thr);
+	DUK_ASSERT_STRIDX_VALID(stridx);
+
+	obj_idx = duk_require_normalize_index(thr, obj_idx);
+	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
+	return duk_xget_owndataprop(thr, obj_idx);
+}
+
+DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
+	return duk_xget_owndataprop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
+	                                   (duk_small_uint_t) (packed_args & 0xffffUL));
+}
+
 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
 	duk_tval *tv_obj;
 	duk_tval *tv_key;
@@ -17151,9 +17590,6 @@
 
 /*
  *  Object related
- *
- *  Note: seal() and freeze() are accessible through ECMAScript bindings,
- *  and are not exposed through the API.
  */
 
 DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
@@ -17487,6 +17923,37 @@
 	duk_pop(thr);
 }
 
+DUK_INTERNAL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx) {
+	duk_hobject *obj;
+
+	DUK_ASSERT_API_ENTRY(thr);
+
+	obj = duk_require_hobject(thr, idx);
+	DUK_ASSERT(obj != NULL);
+
+#if defined(DUK_USE_ROM_OBJECTS)
+	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
+		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
+		DUK_WO_NORETURN(return;);
+	}
+#endif
+
+	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
+}
+
+DUK_INTERNAL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx) {
+	duk_hobject *obj;
+	duk_hobject *proto;
+
+	DUK_ASSERT_API_ENTRY(thr);
+
+	obj = duk_require_hobject(thr, idx);
+	DUK_ASSERT(obj != NULL);
+
+	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
+	return (proto == NULL);
+}
+
 /*
  *  Object finalizer
  */
@@ -17500,6 +17967,10 @@
 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
 	DUK_ASSERT_API_ENTRY(thr);
 
+	/* This get intentionally walks the inheritance chain at present,
+	 * which matches how the effective finalizer property is also
+	 * looked up in GC.
+	 */
 	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
 }
 
@@ -17511,6 +17982,12 @@
 
 	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
 	callable = duk_is_callable(thr, -1);
+
+	/* At present finalizer is stored as a hidden Symbol, with normal
+	 * inheritance and access control.  As a result, finalizer cannot
+	 * currently be set on a non-extensible (sealed or frozen) object.
+	 * It might be useful to allow it.
+	 */
 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
 
 	/* In addition to setting the finalizer property, keep a "have
@@ -18244,7 +18721,7 @@
 	duk_tval *tv_prev_alloc_end;
 	duk_tval *p;
 
-	DUK_ASSERT_HTHREAD_VALID(thr);
+	DUK_HTHREAD_ASSERT_VALID(thr);
 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
@@ -18730,7 +19207,7 @@
 	 * => [ ... | q | p | x | x ]
 	 */
 
-	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
+	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
 
 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
 	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
@@ -18766,6 +19243,40 @@
 	}
 }
 
+DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
+	duk_tval *p;
+	duk_tval *q;
+	duk_tval tv_tmp;
+	duk_size_t nbytes;
+
+	DUK_ASSERT_API_ENTRY(thr);
+
+	/*                         nbytes
+	 *                       <--------->
+	 *    [ ... | x | x | p | y | y | q ]
+	 * => [ ... | x | x | y | y | q | p ]
+	 */
+
+	p = duk_require_tval(thr, from_idx);
+	DUK_ASSERT(p != NULL);
+	q = duk_require_tval(thr, -1);
+	DUK_ASSERT(q != NULL);
+
+	DUK_ASSERT(q >= p);
+
+	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
+
+	DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
+	                     (long) from_idx, (void *) p, (void *) q, (unsigned long) nbytes));
+
+	/* No net refcount changes.  No need to special case nbytes == 0
+	 * (p == q).
+	 */
+	DUK_TVAL_SET_TVAL(&tv_tmp, p);
+	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
+	DUK_TVAL_SET_TVAL(q, &tv_tmp);
+}
+
 DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
 	duk_tval *tv1;
 	duk_tval *tv2;
@@ -18918,8 +19429,8 @@
 	/* XXX: several pointer comparison issues here */
 
 	DUK_ASSERT_API_ENTRY(to_thr);
-	DUK_ASSERT_CTX_VALID(to_thr);
-	DUK_ASSERT_CTX_VALID(from_thr);
+	DUK_CTX_ASSERT_VALID(to_thr);
+	DUK_CTX_ASSERT_VALID(from_thr);
 	DUK_ASSERT(to_thr->heap == from_thr->heap);
 
 	if (DUK_UNLIKELY(to_thr == from_thr)) {
@@ -19045,7 +19556,7 @@
 	duk_bool_t ret;
 	duk_tval *tv;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	tv = duk_get_tval_or_unused(thr, idx);
 	DUK_ASSERT(tv != NULL);
@@ -19103,7 +19614,7 @@
 	duk_double_union ret;
 	duk_tval *tv;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	tv = duk_get_tval_or_unused(thr, idx);
 	DUK_ASSERT(tv != NULL);
@@ -19388,7 +19899,7 @@
 	duk_tval *tv;
 	void *p;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	tv = duk_get_tval_or_unused(thr, idx);
 	DUK_ASSERT(tv != NULL);
@@ -19463,7 +19974,7 @@
 	duk_size_t len;
 	duk_tval *tv;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	if (out_size != NULL) {
 		*out_size = 0;
@@ -19562,7 +20073,7 @@
 			 * duk_hbufobj, get a validated buffer pointer/length.
 			 */
 			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
-			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 			if (h_bufobj->buf != NULL &&
 			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
@@ -19625,7 +20136,7 @@
 	duk_tval *tv;
 	duk_heaphdr *ret;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	tv = duk_get_tval_or_unused(thr, idx);
 	DUK_ASSERT(tv != NULL);
@@ -19860,7 +20371,7 @@
 	}
 }
 
-DUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
+DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
 	duk_hobject *h;
 
 	DUK_ASSERT_API_ENTRY(thr);
@@ -19969,7 +20480,7 @@
 	duk_uint_t val_mask;
 	duk_hobject *res;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
 	if (DUK_LIKELY(res != NULL)) {
@@ -20145,7 +20656,7 @@
 	duk_tval *tv;
 	duk_heaphdr *h;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	if (idx < 0) {
 		tv = thr->valstack_top + idx;
 	} else {
@@ -20447,7 +20958,7 @@
 	duk_tval *tv;
 	duk_double_t d;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	tv = duk_require_tval(thr, idx);
 	DUK_ASSERT(tv != NULL);
@@ -20562,7 +21073,7 @@
 	}
 
 	t = d - DUK_FLOOR(d);
-	if (t == 0.5) {
+	if (duk_double_equals(t, 0.5)) {
 		/* Exact halfway, round to even. */
 		ret = (duk_uint8_t) d;
 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
@@ -20585,10 +21096,10 @@
 }
 
 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_UNREF(udata);
 
-	duk_to_string(thr, -1);
+	(void) duk_to_string(thr, -1);
 	return 1;
 }
 
@@ -20625,6 +21136,60 @@
 	return duk_get_lstring(thr, idx, out_len);
 }
 
+DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
+	DUK_ASSERT_API_ENTRY(thr);
+	idx = duk_require_normalize_index(thr, idx);
+
+	/* The expected argument to the call is an Error object.  The stack
+	 * trace is extracted without an inheritance-based instanceof check
+	 * so that one can also extract the stack trace of a foreign error
+	 * created in another Realm.  Accept only a string .stack property.
+	 */
+	if (duk_is_object(thr, idx)) {
+		(void) duk_get_prop_string(thr, idx, "stack");
+		if (duk_is_string(thr, -1)) {
+			duk_replace(thr, idx);
+		} else {
+			duk_pop(thr);
+		}
+	}
+
+	return duk_to_string(thr, idx);
+}
+
+DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata) {
+	DUK_CTX_ASSERT_VALID(thr);
+	DUK_UNREF(udata);
+
+	(void) duk_to_stacktrace(thr, -1);
+
+	return 1;
+}
+
+DUK_EXTERNAL const char *duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
+	duk_int_t rc;
+
+	DUK_ASSERT_API_ENTRY(thr);
+	idx = duk_require_normalize_index(thr, idx);
+
+	duk_dup(thr, idx);
+	rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
+	if (rc != 0) {
+		/* Coercion failed.  Try to coerce the coercion itself error
+		 * to a stack trace once.  If that also fails, return a fixed,
+		 * preallocated 'Error' string to avoid potential infinite loop.
+		 */
+		rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
+		if (rc != 0) {
+			duk_pop_unsafe(thr);
+			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
+		}
+	}
+	duk_replace(thr, idx);
+
+	return duk_get_string(thr, idx);
+}
+
 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
 	duk_hstring *h;
 
@@ -20656,134 +21221,6 @@
 #endif
 
 /* Push Object.prototype.toString() output for 'tv'. */
-#if 0  /* See XXX note why this variant doesn't work. */
-DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
-	duk_uint_t stridx_bidx = 0;  /* (prototype_bidx << 16) + default_tag_stridx */
-
-	DUK_ASSERT_API_ENTRY(thr);
-
-	/* Conceptually for any non-undefined/null value we should do a
-	 * ToObject() coercion and look up @@toStringTag (from the object
-	 * prototype) to see if a custom tag should be used.  Avoid the
-	 * actual conversion by doing a prototype lookup without the object
-	 * coercion.  However, see problem below.
-	 */
-
-	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
-
-	switch (DUK_TVAL_GET_TAG(tv)) {
-	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
-	case DUK_TAG_UNDEFINED: {
-		stridx_bidx = DUK_STRIDX_UC_UNDEFINED;
-		goto use_stridx;
-	}
-	case DUK_TAG_NULL: {
-		stridx_bidx = DUK_STRIDX_UC_NULL;
-		goto use_stridx;
-	}
-	case DUK_TAG_BOOLEAN: {
-		stridx_bidx = (DUK_BIDX_BOOLEAN_PROTOTYPE << 16) + DUK_STRIDX_UC_BOOLEAN;
-		goto use_proto_bidx;
-	}
-	case DUK_TAG_POINTER: {
-		stridx_bidx = (DUK_BIDX_POINTER_PROTOTYPE << 16) + DUK_STRIDX_UC_POINTER;
-		goto use_proto_bidx;
-	}
-	case DUK_TAG_LIGHTFUNC: {
-		stridx_bidx = (DUK_BIDX_FUNCTION_PROTOTYPE << 16) + DUK_STRIDX_UC_FUNCTION;
-		goto use_proto_bidx;
-	}
-	case DUK_TAG_STRING: {
-		duk_hstring *h;
-		h = DUK_TVAL_GET_STRING(tv);
-		DUK_ASSERT(h != NULL);
-		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
-			/* Even without DUK_USE_SYMBOL_BUILTIN the Symbol
-			 * prototype exists so we can lookup @@toStringTag
-			 * and provide [object Symbol] for symbol values
-			 * created from C code.
-			 */
-			stridx_bidx = (DUK_BIDX_SYMBOL_PROTOTYPE << 16) + DUK_STRIDX_UC_SYMBOL;
-		} else {
-			stridx_bidx = (DUK_BIDX_STRING_PROTOTYPE << 16) + DUK_STRIDX_UC_STRING;
-		}
-		goto use_proto_bidx;
-	}
-	case DUK_TAG_OBJECT: {
-		duk_push_tval(thr, tv);
-		stridx_bidx = 0xffffffffUL;  /* Marker value. */
-		goto use_pushed_object;
-	}
-	case DUK_TAG_BUFFER: {
-		stridx_bidx = (DUK_BIDX_UINT8ARRAY_PROTOTYPE << 16) + DUK_STRIDX_UINT8_ARRAY;
-		goto use_proto_bidx;
-	}
-#if defined(DUK_USE_FASTINT)
-	case DUK_TAG_FASTINT:
-		/* Fall through to generic number case. */
-#endif
-	default: {
-		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* number (maybe fastint) */
-		stridx_bidx = (DUK_BIDX_NUMBER_PROTOTYPE << 16) + DUK_STRIDX_UC_NUMBER;
-		goto use_proto_bidx;
-	}
-	}
-	DUK_ASSERT(0);  /* Never here. */
-
- use_proto_bidx:
-	DUK_ASSERT_BIDX_VALID((stridx_bidx >> 16) & 0xffffUL);
-	duk_push_hobject(thr, thr->builtins[(stridx_bidx >> 16) & 0xffffUL]);
-	/* Fall through. */
-
- use_pushed_object:
-	/* [ ... "[object" obj ] */
-
-#if defined(DUK_USE_SYMBOL_BUILTIN)
-	/* XXX: better handling with avoid_side_effects == 1; lookup tval
-	 * without Proxy or getter side effects, and use it in sanitized
-	 * form if it's a string.
-	 */
-	if (!avoid_side_effects) {
-		/* XXX: The problem with using the prototype object as the
-		 * lookup base is that if @@toStringTag is a getter, its
-		 * 'this' binding must be the ToObject() coerced input value,
-		 * not the prototype object of the type.
-		 */
-		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
-		if (duk_is_string_notsymbol(thr, -1)) {
-			duk_remove_m2(thr);
-			goto finish;
-		}
-		duk_pop_unsafe(thr);
-	}
-#endif
-
-	if (stridx_bidx == 0xffffffffUL) {
-		duk_hobject *h_obj;
-		duk_small_uint_t classnum;
-
-		h_obj = duk_known_hobject(thr, -1);
-		DUK_ASSERT(h_obj != NULL);
-		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
-		stridx_bidx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
-	} else {
-		/* stridx_bidx already has the desired fallback stridx. */
-		;
-	}
-	duk_pop_unsafe(thr);
-	/* Fall through. */
-
- use_stridx:
-	/* [ ... "[object" ] */
-	duk_push_hstring_stridx(thr, stridx_bidx & 0xffffUL);
-
- finish:
-	/* [ ... "[object" tag ] */
-	duk_push_literal(thr, "]");
-	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
-}
-#endif  /* 0 */
-
 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
 	duk_hobject *h_obj;
 	duk_small_uint_t classnum;
@@ -20799,11 +21236,13 @@
 
 	/* Conceptually for any non-undefined/null value we should do a
 	 * ToObject() coercion and look up @@toStringTag (from the object
-	 * prototype) to see if a custom result should be used.  We'd like to
-	 * avoid the actual conversion, but even for primitive types the
-	 * prototype may have @@toStringTag.  What's worse, the @@toStringTag
-	 * property may be a getter that must get the object coerced value
-	 * (not the prototype) as its 'this' binding.
+	 * prototype) to see if a custom result should be used, with the
+	 * exception of Arrays which are handled specially first.
+	 *
+	 * We'd like to avoid the actual conversion, but even for primitive
+	 * types the prototype may have @@toStringTag.  What's worse, the
+	 * @@toStringTag property may be a getter that must get the object
+	 * coerced value (not the prototype) as its 'this' binding.
 	 *
 	 * For now, do an actual object coercion.  This could be avoided by
 	 * doing a side effect free lookup to see if a getter would be invoked.
@@ -20828,31 +21267,33 @@
 
 	duk_push_tval(thr, tv);
 	tv = NULL;  /* Invalidated by ToObject(). */
-	duk_to_object(thr, -1);
-
-	/* [ ... "[object" obj ] */
+	h_obj = duk_to_hobject(thr, -1);
+	DUK_ASSERT(h_obj != NULL);
+	if (duk_js_isarray_hobject(h_obj)) {
+		stridx = DUK_STRIDX_UC_ARRAY;
+	} else {
+		/* [ ... "[object" obj ] */
 
 #if defined(DUK_USE_SYMBOL_BUILTIN)
-	/* XXX: better handling with avoid_side_effects == 1; lookup tval
-	 * without Proxy or getter side effects, and use it in sanitized
-	 * form if it's a string.
-	 */
-	if (!avoid_side_effects) {
-		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
-		if (duk_is_string_notsymbol(thr, -1)) {
-			duk_remove_m2(thr);
-			goto finish;
-		}
-		duk_pop_unsafe(thr);
-	}
-#else
-	DUK_UNREF(avoid_side_effects);
-#endif
-
-	h_obj = duk_known_hobject(thr, -1);
-	DUK_ASSERT(h_obj != NULL);
-	classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
-	stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
+		/* XXX: better handling with avoid_side_effects == 1; lookup tval
+		 * without Proxy or getter side effects, and use it in sanitized
+		 * form if it's a string.
+		 */
+		if (!avoid_side_effects) {
+			(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
+			if (duk_is_string_notsymbol(thr, -1)) {
+				duk_remove_m2(thr);
+				goto finish;
+			}
+			duk_pop_unsafe(thr);
+		}
+#else
+		DUK_UNREF(avoid_side_effects);
+#endif
+
+		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
+		stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
+	}
 	duk_pop_unsafe(thr);
 	duk_push_hstring_stridx(thr, stridx);
 
@@ -21691,14 +22132,15 @@
 	return 0;
 }
 
+/* IsArray(), returns true for Array instance or Proxy of Array instance. */
 DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
-	duk_hobject *obj;
-
-	DUK_ASSERT_API_ENTRY(thr);
-
-	obj = duk_get_hobject(thr, idx);
-	if (obj) {
-		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
+	duk_tval *tv;
+
+	DUK_ASSERT_API_ENTRY(thr);
+
+	tv = duk_get_tval(thr, idx);
+	if (tv) {
+		return duk_js_isarray(tv);
 	}
 	return 0;
 }
@@ -22277,7 +22719,7 @@
 
 /* XXX: size optimize */
 DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
-	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
+	if (!duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
 		duk_pop_unsafe(thr);
 		duk_push_bare_object(thr);
@@ -22316,7 +22758,7 @@
 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
 	duk_int_t len;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_UNREF(thr);
 
 	/* NUL terminator handling doesn't matter here */
@@ -22493,6 +22935,33 @@
 	return ret;
 }
 
+DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr) {
+	duk_uint_t flags;
+	duk_harray *obj;
+	duk_idx_t ret;
+	duk_tval *tv_slot;
+
+	DUK_ASSERT_API_ENTRY(thr);
+
+	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
+	        DUK_HOBJECT_FLAG_FASTREFS |
+	        DUK_HOBJECT_FLAG_ARRAY_PART |
+	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
+	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
+
+	obj = duk_harray_alloc(thr, flags);
+	DUK_ASSERT(obj != NULL);
+
+	tv_slot = thr->valstack_top;
+	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
+	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
+	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
+	thr->valstack_top++;
+
+	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
+	return ret;
+}
+
 DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
 	/* XXX: API call could do this directly, cast to void in API macro. */
 	duk_harray *a;
@@ -22666,7 +23135,7 @@
 	duk_tval *tv_slot;
 	duk_int16_t func_nargs;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	DUK__CHECK_SPACE();
 
@@ -22811,7 +23280,7 @@
 	DUK_ASSERT(obj != NULL);
 
 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
-	DUK_ASSERT_HBUFOBJ_VALID(obj);
+	DUK_HBUFOBJ_ASSERT_VALID(obj);
 
 	tv_slot = thr->valstack_top;
 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
@@ -22885,7 +23354,7 @@
 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
 		duk_uint_t tmp_offset;
 
-		DUK_ASSERT_HBUFOBJ_VALID((duk_hbufobj *) h_arraybuf);
+		DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
 		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
 		if (DUK_UNLIKELY(h_val == NULL)) {
 			goto arg_error;
@@ -22934,7 +23403,7 @@
 	h_bufobj->shift = (tmp >> 4) & 0x0f;
 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
 	h_bufobj->is_typedarray = tmp & 0x0f;
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 	/* TypedArray views need an automatic ArrayBuffer which must be
 	 * provided as .buffer property of the view.  The ArrayBuffer is
@@ -23172,7 +23641,7 @@
 	h_proxy->target = h_target;
 	DUK_ASSERT(h_handler != NULL);
 	h_proxy->handler = h_handler;
-	DUK_ASSERT_HPROXY_VALID(h_proxy);
+	DUK_HPROXY_ASSERT_VALID(h_proxy);
 
 	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
 	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
@@ -23326,7 +23795,7 @@
 		return ret;
 	}
 
-	DUK_ASSERT_HEAPHDR_VALID((duk_heaphdr *) ptr);
+	DUK_HEAPHDR_ASSERT_VALID((duk_heaphdr *) ptr);
 
 	/* If the argument is on finalize_list it has technically been
 	 * unreachable before duk_push_heapptr() but it's still safe to
@@ -23461,7 +23930,7 @@
 	duk_tval *tv_end;
 #endif
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(count >= 0);
 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
 
@@ -23562,7 +24031,7 @@
 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
 	duk_tval *tv;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
@@ -23644,7 +24113,7 @@
 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
 	duk_tval *tv;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
@@ -23715,6 +24184,7 @@
  */
 
 /* XXX: pack index range? array index offset? */
+/* XXX: need ability to pack into a bare array? */
 DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
 	duk_tval *tv_src;
 	duk_tval *tv_dst;
@@ -23743,6 +24213,7 @@
 
 	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
 	DUK_ASSERT(count == 0 || tv_dst != NULL);
+	DUK_ASSERT(!duk_is_bare_object(thr, -1));
 
 	/* Copy value stack values directly to the array part without
 	 * any refcount updates: net refcount changes are zero.
@@ -23877,6 +24348,13 @@
  *  Error throwing
  */
 
+#if defined(DUK_USE_GCC_PRAGMAS)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
+#elif defined(DUK_USE_CLANG_PRAGMAS)
+#pragma clang diagnostic push
+#endif
+
 DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
 	duk_tval *tv_val;
 
@@ -23966,6 +24444,12 @@
 	DUK_WO_NORETURN(return;);
 }
 
+#if defined(DUK_USE_GCC_PRAGMAS)
+#pragma GCC diagnostic pop
+#elif defined(DUK_USE_CLANG_PRAGMAS)
+#pragma clang diagnostic pop
+#endif
+
 #if !defined(DUK_USE_VARIADIC_MACROS)
 DUK_NORETURN(DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));
 
@@ -23973,7 +24457,7 @@
 	const char *filename;
 	duk_int_t line;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	filename = duk_api_global_filename;
 	line = duk_api_global_line;
@@ -24211,7 +24695,7 @@
 	duk_ucodepoint_t cp;
 	duk_small_uint_t nchars;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(h_input != NULL);
 	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
 
@@ -24255,7 +24739,7 @@
 }
 
 DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	/* 'tv' may be NULL */
 
 	if (tv == NULL) {
@@ -24293,7 +24777,7 @@
 				 * but traverse inheritance chain.
 				 */
 				duk_tval *tv_msg;
-				tv_msg = duk_hobject_find_existing_entry_tval_ptr(thr->heap, h, DUK_HTHREAD_STRING_MESSAGE(thr));
+				tv_msg = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, h, DUK_STRIDX_MESSAGE);
 				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
 					/* It's critical to avoid recursion so
 					 * only summarize a string .message.
@@ -24442,7 +24926,7 @@
 	duk_hstring *h;
 	duk_uint8_t *buf;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	if (DUK_UNLIKELY(count_in <= 0)) {
 		if (count_in < 0) {
@@ -24981,7 +25465,7 @@
 
 	/* XXX: push more directly? */
 	(void) duk_push_this_coercible_to_object(thr);
-	DUK_ASSERT_HOBJECT_VALID(duk_get_hobject(thr, -1));
+	DUK_HOBJECT_ASSERT_VALID(duk_get_hobject(thr, -1));
 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
 	len = duk_to_uint32(thr, -1);
 
@@ -25075,7 +25559,7 @@
 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
 		d = duk_get_number(thr, 0);
 		len = duk_to_uint32(thr, 0);
-		if (((duk_double_t) len) != d) {
+		if (!duk_double_equals((duk_double_t) len, d)) {
 			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
 		}
 
@@ -25085,6 +25569,7 @@
 		len_prealloc = len < 64 ? len : 64;
 		a = duk_push_harray_with_size(thr, len_prealloc);
 		DUK_ASSERT(a != NULL);
+		DUK_ASSERT(!duk_is_bare_object(thr, -1));
 		a->length = len;
 		return 1;
 	}
@@ -25098,10 +25583,8 @@
  */
 
 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
-	duk_hobject *h;
-
-	h = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_ARRAY);
-	duk_push_boolean(thr, (h != NULL));
+	DUK_ASSERT_TOP(thr, 1);
+	duk_push_boolean(thr, duk_js_isarray(DUK_GET_TVAL_POSIDX(thr, 0)));
 	return 1;
 }
 
@@ -25194,13 +25677,13 @@
 #if defined(DUK_USE_SYMBOL_BUILTIN)
 			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
 			if (duk_is_undefined(thr, -1)) {
-				spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
+				spreadable = duk_js_isarray_hobject(h);
 			} else {
 				spreadable = duk_to_boolean(thr, -1);
 			}
 			duk_pop_nodecref_unsafe(thr);
 #else
-			spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
+			spreadable = duk_js_isarray_hobject(h);
 #endif
 		}
 
@@ -26607,7 +27090,7 @@
 		DUK_ASSERT(h != NULL);
 
 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
-			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
 			DUK_ASSERT(duk_is_boolean(thr, -1));
 			goto type_ok;
 		}
@@ -26768,7 +27251,7 @@
 	duk_push_this(thr);
 	DUK_ASSERT(duk_is_buffer(thr, -1));
 	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
-	DUK_ASSERT_HBUFOBJ_VALID(res);
+	DUK_HBUFOBJ_ASSERT_VALID(res);
 	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
 
 	tv_dst = duk_get_borrowed_this_tval(thr);
@@ -26798,7 +27281,7 @@
 		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(h_this != NULL);
 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
-			DUK_ASSERT_HBUFOBJ_VALID(h_this);
+			DUK_HBUFOBJ_ASSERT_VALID(h_this);
 			return (duk_heaphdr *) h_this;
 		}
 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
@@ -26812,7 +27295,7 @@
 			/* XXX: make this conditional to a flag if call sites need it? */
 			h_this = duk__hbufobj_promote_this(thr);
 			DUK_ASSERT(h_this != NULL);
-			DUK_ASSERT_HBUFOBJ_VALID(h_this);
+			DUK_HBUFOBJ_ASSERT_VALID(h_this);
 			return (duk_heaphdr *) h_this;
 		} else {
 			/* XXX: ugly, share return pointer for duk_hbuffer. */
@@ -26853,13 +27336,13 @@
 		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(h_obj != NULL);
 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
-			DUK_ASSERT_HBUFOBJ_VALID(h_obj);
+			DUK_HBUFOBJ_ASSERT_VALID(h_obj);
 			return h_obj;
 		}
 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
 		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
 		DUK_ASSERT(h_obj != NULL);
-		DUK_ASSERT_HBUFOBJ_VALID(h_obj);
+		DUK_HBUFOBJ_ASSERT_VALID(h_obj);
 		return h_obj;
 	}
 
@@ -26872,7 +27355,7 @@
 	DUK_ASSERT(h_bufobj != NULL);
 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
 	DUK_ASSERT(h_val != NULL);
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 	DUK_UNREF(thr);
 
 	h_bufobj->buf = h_val;
@@ -26882,7 +27365,7 @@
 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
 
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 }
 
 /* Shared offset/length coercion helper. */
@@ -27066,7 +27549,7 @@
 	DUK_ASSERT(h_bufobj != NULL);
 	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
 	h_bufobj->is_typedarray = 1;
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 	h_arrbuf = duk_push_bufobj_raw(thr,
 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
@@ -27076,7 +27559,7 @@
 	DUK_ASSERT(h_arrbuf != NULL);
 	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
 	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
-	DUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);
+	DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);
 
 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
 	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
@@ -27295,7 +27778,7 @@
 	duk_hbuffer *h_val;
 	duk_int_t len;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 
 	duk_require_constructor_call(thr);
 
@@ -27314,7 +27797,7 @@
 	DUK_ASSERT(h_bufobj != NULL);
 
 	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 	return 1;
 
@@ -27465,7 +27948,7 @@
 			h_bufobj->shift = (duk_uint8_t) shift;
 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
 			h_bufobj->is_typedarray = 1;
-			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 			/* Set .buffer to the argument ArrayBuffer. */
 			DUK_ASSERT(h_bufobj->buf_prop == NULL);
@@ -27480,7 +27963,7 @@
 			 */
 
 			h_bufarg = (duk_hbufobj *) h_obj;
-			DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
+			DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
 			if (h_bufarg->buf == NULL) {
 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
@@ -27569,7 +28052,7 @@
 	h_bufobj->shift = (duk_uint8_t) shift;
 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
 	h_bufobj->is_typedarray = 1;
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 	/* Copy values, the copy method depends on the arguments.
 	 *
@@ -27753,7 +28236,7 @@
 	DUK_ASSERT(h_bufarg != NULL);
 	DUK_HBUFOBJ_INCREF(thr, h_bufarg);
 
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 	return 1;
 }
 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
@@ -27841,7 +28324,7 @@
 		duk_push_literal(thr, "[object Object]");
 		return 1;
 	}
-	DUK_ASSERT_HBUFOBJ_VALID(h_this);
+	DUK_HBUFOBJ_ASSERT_VALID(h_this);
 
 	/* Ignore encoding for now. */
 
@@ -27912,6 +28395,7 @@
 	/* XXX: uninitialized would be OK */
 	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
+	DUK_ASSERT(!duk_is_bare_object(thr, -1));
 
 	DUK_ASSERT(h_this->buf != NULL);
 	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
@@ -28249,7 +28733,7 @@
 
 	h_this = duk__require_bufobj_this(thr);
 	DUK_ASSERT(h_this != NULL);
-	DUK_ASSERT_HBUFOBJ_VALID(h_this);
+	DUK_HBUFOBJ_ASSERT_VALID(h_this);
 
 	if (h_this->buf == NULL) {
 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
@@ -28304,7 +28788,7 @@
 		duk_small_uint_t dst_elem_size;
 
 		h_bufarg = (duk_hbufobj *) h_obj;
-		DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
+		DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
 
 		if (h_bufarg->buf == NULL) {
 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
@@ -28693,7 +29177,7 @@
 	}
 	/* unbalanced stack on purpose */
 
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 	return 1;
 }
 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
@@ -28875,7 +29359,7 @@
 
 	duk__set_bufobj_buffer(thr, h_bufres, h_val);
 	h_bufres->is_typedarray = 1;
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufres);
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufres);
 
 	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */
 
@@ -28909,12 +29393,12 @@
 
 /* XXX: split into separate functions for each field type? */
 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
-	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
-	duk_small_int_t magic_ftype;
-	duk_small_int_t magic_bigendian;
-	duk_small_int_t magic_signed;
-	duk_small_int_t magic_typedarray;
-	duk_small_int_t endswap;
+	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
+	duk_small_uint_t magic_ftype;
+	duk_small_uint_t magic_bigendian;
+	duk_small_uint_t magic_signed;
+	duk_small_uint_t magic_typedarray;
+	duk_small_uint_t endswap;
 	duk_hbufobj *h_this;
 	duk_bool_t no_assert;
 	duk_int_t offset_signed;
@@ -28924,10 +29408,10 @@
 	duk_uint8_t *buf;
 	duk_double_union du;
 
-	magic_ftype = magic & 0x0007;
-	magic_bigendian = magic & 0x0008;
-	magic_signed = magic & 0x0010;
-	magic_typedarray = magic & 0x0020;
+	magic_ftype = magic & 0x0007U;
+	magic_bigendian = magic & 0x0008U;
+	magic_signed = magic & 0x0010U;
+	magic_typedarray = magic & 0x0020U;
 
 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
 	DUK_ASSERT(h_this != NULL);
@@ -28966,7 +29450,7 @@
 
 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
-	                     "endswap=%d",
+	                     "endswap=%u",
 	                     (long) buffer_length, (long) offset, (int) no_assert,
 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
 	                     (int) (magic_signed >> 4), (int) endswap));
@@ -29168,12 +29652,12 @@
 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
 /* XXX: split into separate functions for each field type? */
 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
-	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
-	duk_small_int_t magic_ftype;
-	duk_small_int_t magic_bigendian;
-	duk_small_int_t magic_signed;
-	duk_small_int_t magic_typedarray;
-	duk_small_int_t endswap;
+	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
+	duk_small_uint_t magic_ftype;
+	duk_small_uint_t magic_bigendian;
+	duk_small_uint_t magic_signed;
+	duk_small_uint_t magic_typedarray;
+	duk_small_uint_t endswap;
 	duk_hbufobj *h_this;
 	duk_bool_t no_assert;
 	duk_int_t offset_signed;
@@ -29184,10 +29668,10 @@
 	duk_double_union du;
 	duk_int_t nbytes = 0;
 
-	magic_ftype = magic & 0x0007;
-	magic_bigendian = magic & 0x0008;
-	magic_signed = magic & 0x0010;
-	magic_typedarray = magic & 0x0020;
+	magic_ftype = magic & 0x0007U;
+	magic_bigendian = magic & 0x0008U;
+	magic_signed = magic & 0x0010U;
+	magic_typedarray = magic & 0x0020U;
 	DUK_UNREF(magic_signed);
 
 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
@@ -29227,7 +29711,7 @@
 	 * (offset + nbytes) even when write fails due to invalid offset.
 	 */
 	if (magic_ftype != DUK__FLD_VARINT) {
-		DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
+		DUK_ASSERT(magic_ftype < (duk_small_uint_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
 	} else {
 		nbytes = duk_get_int(thr, 2);
@@ -29244,7 +29728,7 @@
 
 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
-	                     "endswap=%d",
+	                     "endswap=%u",
 	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
 	                     (int) (magic_signed >> 4), (int) endswap));
@@ -29456,7 +29940,7 @@
 	DUK_UNREF(h_res);
 
 	duk__set_bufobj_buffer(thr, h_res, h_buf);
-	DUK_ASSERT_HBUFOBJ_VALID(h_res);
+	DUK_HBUFOBJ_ASSERT_VALID(h_res);
 	DUK_ASSERT(h_res->buf_prop == NULL);
 	return h_res;
 }
@@ -29580,6 +30064,1747 @@
 #undef DUK__FLD_SIGNED
 #undef DUK__FLD_TYPEDARRAY
 #undef DUK__FLD_VARINT
+#line 1 "duk_bi_cbor.c"
+/*
+ *  CBOR bindings.
+ *
+ *  http://cbor.io/
+ *  https://tools.ietf.org/html/rfc7049
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_CBOR_SUPPORT)
+
+/* #define DUK_CBOR_STRESS */
+
+/* Default behavior for encoding strings: use CBOR text string if string
+ * is UTF-8 compatible, otherwise use CBOR byte string.  These defines
+ * can be used to force either type for all strings.  Using text strings
+ * for non-UTF-8 data is technically invalid CBOR.
+ */
+/* #define DUK_CBOR_TEXT_STRINGS */
+/* #define DUK_CBOR_BYTE_STRINGS */
+
+/* Misc. defines. */
+/* #define DUK_CBOR_PREFER_SIZE */
+/* #define DUK_CBOR_DOUBLE_AS_IS */
+/* #define DUK_CBOR_DECODE_FASTPATH */
+
+typedef struct {
+	duk_hthread *thr;
+	duk_uint8_t *ptr;
+	duk_uint8_t *buf;
+	duk_uint8_t *buf_end;
+	duk_size_t len;
+	duk_idx_t idx_buf;
+	duk_uint_t recursion_depth;
+	duk_uint_t recursion_limit;
+} duk_cbor_encode_context;
+
+typedef struct {
+	duk_hthread *thr;
+	const duk_uint8_t *buf;
+	duk_size_t off;
+	duk_size_t len;
+	duk_uint_t recursion_depth;
+	duk_uint_t recursion_limit;
+} duk_cbor_decode_context;
+
+DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx);
+DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx);
+
+/*
+ *  Misc
+ */
+
+DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d) {
+	/* Out of range casts are undefined behavior, so caller must avoid. */
+	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);
+	return (duk_uint32_t) d;
+}
+
+/*
+ *  Encoding
+ */
+
+DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx) {
+	(void) duk_type_error(enc_ctx->thr, "cbor encode error");
+}
+
+DUK_LOCAL void duk__cbor_encode_req_stack(duk_cbor_encode_context *enc_ctx) {
+	duk_require_stack(enc_ctx->thr, 4);
+}
+
+DUK_LOCAL void duk__cbor_encode_objarr_entry(duk_cbor_encode_context *enc_ctx) {
+	duk_hthread *thr = enc_ctx->thr;
+
+	/* Native stack check in object/array recursion. */
+	duk_native_stack_check(thr);
+
+	/* When working with deeply recursive structures, this is important
+	 * to ensure there's no effective depth limit.
+	 */
+	duk__cbor_encode_req_stack(enc_ctx);
+
+	DUK_ASSERT(enc_ctx->recursion_depth <= enc_ctx->recursion_limit);
+	if (enc_ctx->recursion_depth >= enc_ctx->recursion_limit) {
+		DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
+		DUK_WO_NORETURN(return;);
+	}
+	enc_ctx->recursion_depth++;
+}
+
+DUK_LOCAL void duk__cbor_encode_objarr_exit(duk_cbor_encode_context *enc_ctx) {
+	DUK_ASSERT(enc_ctx->recursion_depth > 0);
+	enc_ctx->recursion_depth--;
+}
+
+/* Check that a size_t is in uint32 range to avoid out-of-range casts. */
+DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
+	if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) {
+		duk__cbor_encode_error(enc_ctx);
+	}
+}
+
+DUK_LOCAL DUK_NOINLINE void duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
+	duk_size_t oldlen;
+	duk_size_t minlen;
+	duk_size_t newlen;
+	duk_uint8_t *p_new;
+	duk_size_t old_data_len;
+
+	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
+	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->ptr);
+	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->buf);
+
+	/* Overflow check.
+	 *
+	 * Limit example: 0xffffffffUL / 2U = 0x7fffffffUL, we reject >= 0x80000000UL.
+	 */
+	oldlen = enc_ctx->len;
+	minlen = oldlen + len;
+	if (DUK_UNLIKELY(oldlen > DUK_SIZE_MAX / 2U || minlen < oldlen)) {
+		duk__cbor_encode_error(enc_ctx);
+	}
+
+#if defined(DUK_CBOR_STRESS)
+	newlen = oldlen + 1U;
+#else
+	newlen = oldlen * 2U;
+#endif
+	DUK_ASSERT(newlen >= oldlen);
+
+	if (minlen > newlen) {
+		newlen = minlen;
+	}
+	DUK_ASSERT(newlen >= oldlen);
+	DUK_ASSERT(newlen >= minlen);
+	DUK_ASSERT(newlen > 0U);
+
+	DUK_DD(DUK_DDPRINT("cbor encode buffer resized to %ld", (long) newlen));
+
+	p_new = (duk_uint8_t *) duk_resize_buffer(enc_ctx->thr, enc_ctx->idx_buf, newlen);
+	DUK_ASSERT(p_new != NULL);
+	old_data_len = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);
+	enc_ctx->buf = p_new;
+	enc_ctx->buf_end = p_new + newlen;
+	enc_ctx->ptr = p_new + old_data_len;
+	enc_ctx->len = newlen;
+}
+
+DUK_LOCAL DUK_INLINE void duk__cbor_encode_ensure(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
+	if (DUK_LIKELY((duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr) >= len)) {
+		return;
+	}
+	duk__cbor_encode_ensure_slowpath(enc_ctx, len);
+}
+
+DUK_LOCAL duk_size_t duk__cbor_get_reserve(duk_cbor_encode_context *enc_ctx) {
+	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
+	DUK_ASSERT(enc_ctx->ptr <= enc_ctx->buf_end);
+	return (duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr);
+}
+
+DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base) {
+	duk_uint8_t *p;
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 4);
+
+	p = enc_ctx->ptr;
+	if (DUK_LIKELY(u <= 23U)) {
+		*p++ = (duk_uint8_t) (base + (duk_uint8_t) u);
+	} else if (u <= 0xffUL) {
+		*p++ = base + 0x18U;
+		*p++ = (duk_uint8_t) u;
+	} else if (u <= 0xffffUL) {
+		*p++ = base + 0x19U;
+		DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) u);
+	} else {
+		*p++ = base + 0x1aU;
+		DUK_RAW_WRITEINC_U32_BE(p, u);
+	}
+	enc_ctx->ptr = p;
+}
+
+#if defined(DUK_CBOR_DOUBLE_AS_IS)
+DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
+	duk_uint8_t *p;
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	p = enc_ctx->ptr;
+	*p++ = 0xfbU;
+	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
+	p += 8;
+	enc_ctx->ptr = p;
+}
+#else  /* DUK_CBOR_DOUBLE_AS_IS */
+DUK_LOCAL void duk__cbor_encode_double_fp(duk_cbor_encode_context *enc_ctx, double d) {
+	duk_double_union u;
+	duk_uint16_t u16;
+	duk_int16_t expt;
+	duk_uint8_t *p;
+
+	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	/* Organize into little endian (no-op if platform is little endian). */
+	u.d = d;
+	duk_dblunion_host_to_little(&u);
+
+	/* Check if 'd' can represented as a normal half-float.
+	 * Denormal half-floats could also be used, but that check
+	 * isn't done now (denormal half-floats are decoded of course).
+	 * So just check exponent range and that at most 10 significant
+	 * bits (excluding implicit leading 1) are used in 'd'.
+	 */
+	u16 = (((duk_uint16_t) u.uc[7]) << 8) | ((duk_uint16_t) u.uc[6]);
+	expt = (duk_int16_t) ((u16 & 0x7ff0U) >> 4) - 1023;
+
+	if (expt >= -14 && expt <= 15) {
+		/* Half-float normal exponents (excl. denormals).
+		 *
+		 *          7        6        5        4        3        2        1        0  (LE index)
+		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+		 * half:         seeeee mmmm mmmmmm00 00000000 00000000 00000000 00000000 00000000
+		 */
+		duk_bool_t use_half_float;
+
+		use_half_float =
+		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && u.uc[3] == 0 &&
+		     u.uc[4] == 0 && (u.uc[5] & 0x03U) == 0);
+
+		if (use_half_float) {
+			duk_uint32_t t;
+
+			expt += 15;
+			t = (duk_uint32_t) (u.uc[7] & 0x80U) << 8;
+			t += (duk_uint32_t) expt << 10;
+			t += ((duk_uint32_t) u.uc[6] & 0x0fU) << 6;
+			t += ((duk_uint32_t) u.uc[5]) >> 2;
+
+			/* seeeeemm mmmmmmmm */
+			p = enc_ctx->ptr;
+			*p++ = 0xf9U;
+			DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) t);
+			enc_ctx->ptr = p;
+			return;
+		}
+	}
+
+	/* Same check for plain float.  Also no denormal support here. */
+	if (expt >= -126 && expt <= 127) {
+		/* Float normal exponents (excl. denormals).
+		 *
+		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+		 * float:     seeee eeeemmmm mmmmmmmm mmmmmmmm mmm00000 00000000 00000000 00000000
+		 */
+		duk_bool_t use_float;
+		duk_float_t d_float;
+
+		/* We could do this explicit mantissa check, but doing
+		 * a double-float-double cast is fine because we've
+		 * already verified that the exponent is in range so
+		 * that the narrower cast is not undefined behavior.
+		 */
+#if 0
+		use_float =
+		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && (u.uc[3] & 0xe0U) == 0);
+#endif
+		d_float = (duk_float_t) d;
+		use_float = duk_double_equals((duk_double_t) d_float, d);
+		if (use_float) {
+			p = enc_ctx->ptr;
+			*p++ = 0xfaU;
+			DUK_RAW_WRITEINC_FLOAT_BE(p, d_float);
+			enc_ctx->ptr = p;
+			return;
+		}
+	}
+
+	/* Special handling for NaN and Inf which we want to encode as
+	 * half-floats.  They share the same (maximum) exponent.
+	 */
+	if (expt == 1024) {
+		DUK_ASSERT(DUK_ISNAN(d) || DUK_ISINF(d));
+		p = enc_ctx->ptr;
+		*p++ = 0xf9U;
+		if (DUK_ISNAN(d)) {
+			/* Shortest NaN encoding is using a half-float.  Lose the
+			 * exact NaN bits in the process.  IEEE double would be
+			 * 7ff8 0000 0000 0000, i.e. a quiet NaN in most architectures
+			 * (https://en.wikipedia.org/wiki/NaN#Encoding).  The
+			 * equivalent half float is 7e00.
+			 */
+			*p++ = 0x7eU;
+		} else {
+			/* Shortest +/- Infinity encoding is using a half-float. */
+			if (DUK_SIGNBIT(d)) {
+				*p++ = 0xfcU;
+			} else {
+				*p++ = 0x7cU;
+			}
+		}
+		*p++ = 0x00U;
+		enc_ctx->ptr = p;
+		return;
+	}
+
+	/* Cannot use half-float or float, encode as full IEEE double. */
+	p = enc_ctx->ptr;
+	*p++ = 0xfbU;
+	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
+	enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
+	duk_uint8_t *p;
+	double d_floor;
+
+	/* Integers and floating point values of all types are conceptually
+	 * equivalent in CBOR.  Try to always choose the shortest encoding
+	 * which is not always immediately obvious.  For example, NaN and Inf
+	 * can be most compactly represented as a half-float (assuming NaN
+	 * bits are not preserved), and 0x1'0000'0000 as a single precision
+	 * float.  Shortest forms in preference order (prefer integer over
+	 * float when equal length):
+	 *
+	 *   uint        1 byte    [0,23] (not -0)
+	 *   sint        1 byte    [-24,-1]
+	 *   uint+1      2 bytes   [24,255]
+	 *   sint+1      2 bytes   [-256,-25]
+	 *   uint+2      3 bytes   [256,65535]
+	 *   sint+2      3 bytes   [-65536,-257]
+	 *   half-float  3 bytes   -0, NaN, +/- Infinity, range [-65504,65504]
+	 *   uint+4      5 bytes   [65536,4294967295]
+	 *   sint+4      5 bytes   [-4294967296,-258]
+	 *   float       5 bytes   range [-(1 - 2^(-24)) * 2^128, (1 - 2^(-24)) * 2^128]
+	 *   uint+8      9 bytes   [4294967296,18446744073709551615]
+	 *   sint+8      9 bytes   [-18446744073709551616,-4294967297]
+	 *   double      9 bytes
+	 *
+	 * For whole numbers (compatible with integers):
+	 *   - 1-byte or 2-byte uint/sint representation is preferred for
+	 *     [-256,255].
+	 *   - 3-byte uint/sint is preferred for [-65536,65535].  Half floats
+	 *     are never preferred because they have the same length.
+	 *   - 5-byte uint/sint is preferred for [-4294967296,4294967295].
+	 *     Single precision floats are never preferred, and half-floats
+	 *     don't reach above the 3-byte uint/sint range so they're never
+	 *     preferred.
+	 *   - So, for all integers up to signed/unsigned 32-bit range the
+	 *     preferred encoding is always an integer uint/sint.
+	 *   - For integers above 32 bits the situation is more complicated.
+	 *     Half-floats are never useful for them because of their limited
+	 *     range, but IEEE single precision floats (5 bytes encoded) can
+	 *     represent some integers between the 32-bit and 64-bit ranges
+	 *     which require 9 bytes as a uint/sint.
+	 *
+	 * For floating point values not compatible with integers, the
+	 * preferred encoding is quite clear:
+	 *   - For +Inf/-Inf use half-float.
+	 *   - For NaN use a half-float, assuming NaN bits ("payload") is
+	 *     not worth preserving.  Duktape doesn't in general guarantee
+	 *     preservation of the NaN payload so using a half-float seems
+	 *     consistent with that.
+	 *   - For remaining values, prefer the shortest form which doesn't
+	 *     lose any precision.  For normal half-floats and single precision
+	 *     floats this is simple: just check exponent and mantissa bits
+	 *     using a fixed mask.  For denormal half-floats and single
+	 *     precision floats the check is a bit more complicated: a normal
+	 *     IEEE double can sometimes be represented as a denormal
+	 *     half-float or single precision float.
+	 *
+	 * https://en.wikipedia.org/wiki/Half-precision_floating-point_format#IEEE_754_half-precision_binary_floating-point_format:_binary16
+	 */
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	/* Most important path is integers.  The floor() test will be true
+	 * for Inf too (but not NaN).
+	 */
+	d_floor = DUK_FLOOR(d);  /* identity if d is +/- 0.0, NaN, or +/- Infinity */
+	if (DUK_LIKELY(duk_double_equals(d_floor, d) != 0)) {
+		DUK_ASSERT(!DUK_ISNAN(d));  /* NaN == NaN compares false. */
+		if (DUK_SIGNBIT(d)) {
+			if (d >= -4294967296.0) {
+				d = -1.0 - d;
+				if (d >= 0.0) {
+					DUK_ASSERT(d >= 0.0);
+					duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x20U);
+					return;
+				}
+
+				/* Input was negative zero, d == -1.0 < 0.0.
+				 * Shortest -0 is using half-float.
+				 */
+				p = enc_ctx->ptr;
+				*p++ = 0xf9U;
+				*p++ = 0x80U;
+				*p++ = 0x00U;
+				enc_ctx->ptr = p;
+				return;
+			}
+		} else {
+			if (d <= 4294967295.0) {
+				/* Positive zero needs no special handling. */
+				DUK_ASSERT(d >= 0.0);
+				duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x00U);
+				return;
+			}
+		}
+	}
+
+	/* 64-bit integers are not supported at present.  So
+	 * we also don't need to deal with choosing between a
+	 * 64-bit uint/sint representation vs. IEEE double or
+	 * float.
+	 */
+
+	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
+	duk__cbor_encode_double_fp(enc_ctx, d);
+}
+#endif  /* DUK_CBOR_DOUBLE_AS_IS */
+
+DUK_LOCAL void duk__cbor_encode_string_top(duk_cbor_encode_context *enc_ctx) {
+	const duk_uint8_t *str;
+	duk_size_t len;
+	duk_uint8_t *p;
+
+	/* CBOR differentiates between UTF-8 text strings and byte strings.
+	 * Text strings MUST be valid UTF-8, so not all Duktape strings can
+	 * be encoded as valid CBOR text strings.  Possible behaviors:
+	 *
+	 *   1. Use text string when input is valid UTF-8, otherwise use
+	 *      byte string (maybe tagged to indicate it was an extended
+	 *      UTF-8 string).
+	 *   2. Always use text strings, but sanitize input string so that
+	 *      invalid UTF-8 is replaced with U+FFFD for example.  Combine
+	 *      surrogates whenever possible.
+	 *   3. Always use byte strings.  This is simple and produces valid
+	 *      CBOR, but isn't ideal for interoperability.
+	 *   4. Always use text strings, even for invalid UTF-8 such as
+	 *      codepoints in the surrogate pair range.  This is simple but
+	 *      produces technically invalid CBOR for non-UTF-8 strings which
+	 *      may affect interoperability.
+	 *
+	 * Current default is 1; can be changed with defines.
+	 */
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	str = (const duk_uint8_t *) duk_require_lstring(enc_ctx->thr, -1, &len);
+	if (duk_is_symbol(enc_ctx->thr, -1)) {
+		/* Symbols, encode as an empty table for now.  This matches
+		 * the behavior of cbor-js.
+		 *
+		 * XXX: Maybe encode String() coercion with a tag?
+		 * XXX: Option to keep enough information to recover
+		 * Symbols when decoding (this is not always desirable).
+		 */
+		p = enc_ctx->ptr;
+		*p++ = 0xa0U;
+		enc_ctx->ptr = p;
+		return;
+	}
+
+	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+#if defined(DUK_CBOR_TEXT_STRINGS)
+	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x60U);
+#elif defined(DUK_CBOR_BYTE_STRINGS)
+	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
+#else
+	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len,
+	                        (DUK_LIKELY(duk_unicode_is_utf8_compatible(str, len) != 0) ? 0x60U : 0x40U));
+#endif
+	duk__cbor_encode_ensure(enc_ctx, len);
+	p = enc_ctx->ptr;
+	duk_memcpy((void *) p, (const void *) str, len);
+	p += len;
+	enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) {
+	duk_uint8_t *buf;
+	duk_size_t len;
+	duk_uint8_t *p;
+	duk_size_t i;
+	duk_size_t off_ib;
+	duk_uint32_t count;
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	duk__cbor_encode_objarr_entry(enc_ctx);
+
+	/* XXX: Support for specific built-ins like Date and RegExp. */
+	if (duk_is_array(enc_ctx->thr, -1)) {
+		/* Shortest encoding for arrays >= 256 in length is actually
+		 * the indefinite length one (3 or more bytes vs. 2 bytes).
+		 * We still use the definite length version because it is
+		 * more decoding friendly.
+		 */
+		len = duk_get_length(enc_ctx->thr, -1);
+		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x80U);
+		for (i = 0; i < len; i++) {
+			duk_get_prop_index(enc_ctx->thr, -1, (duk_uarridx_t) i);
+			duk__cbor_encode_value(enc_ctx);
+		}
+	} else if (duk_is_buffer_data(enc_ctx->thr, -1)) {
+		/* XXX: Tag buffer data?
+		 * XXX: Encode typed arrays as integer arrays rather
+		 * than buffer data as is?
+		 */
+		buf = (duk_uint8_t *) duk_require_buffer_data(enc_ctx->thr, -1, &len);
+		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
+		duk__cbor_encode_ensure(enc_ctx, len);
+		p = enc_ctx->ptr;
+		duk_memcpy_unsafe((void *) p, (const void *) buf, len);
+		p += len;
+		enc_ctx->ptr = p;
+	} else {
+		/* We don't know the number of properties in advance
+		 * but would still like to encode at least small
+		 * objects without indefinite length.  Emit an
+		 * indefinite length byte initially, and if the final
+		 * property count is small enough to also fit in one
+		 * byte, backpatch it later.  Otherwise keep the
+		 * indefinite length.  This works well up to 23
+		 * properties which is practical and good enough.
+		 */
+		off_ib = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);  /* XXX: get_offset? */
+		count = 0U;
+		p = enc_ctx->ptr;
+		*p++ = 0xa0U + 0x1fU;  /* indefinite length */
+		enc_ctx->ptr = p;
+		duk_enum(enc_ctx->thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
+		while (duk_next(enc_ctx->thr, -1, 1 /*get_value*/)) {
+			duk_insert(enc_ctx->thr, -2);  /* [ ... key value ] -> [ ... value key ] */
+			duk__cbor_encode_value(enc_ctx);
+			duk__cbor_encode_value(enc_ctx);
+			count++;
+			if (count == 0U) {
+				duk__cbor_encode_error(enc_ctx);
+			}
+		}
+		duk_pop(enc_ctx->thr);
+		if (count <= 0x17U) {
+			DUK_ASSERT(off_ib < enc_ctx->len);
+			enc_ctx->buf[off_ib] = 0xa0U + (duk_uint8_t) count;
+		} else {
+			duk__cbor_encode_ensure(enc_ctx, 1);
+			p = enc_ctx->ptr;
+			*p++ = 0xffU;  /* break */
+			enc_ctx->ptr = p;
+		}
+	}
+
+	duk__cbor_encode_objarr_exit(enc_ctx);
+}
+
+DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) {
+	duk_uint8_t *buf;
+	duk_size_t len;
+	duk_uint8_t *p;
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	/* Tag buffer data? */
+	buf = (duk_uint8_t *) duk_require_buffer(enc_ctx->thr, -1, &len);
+	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
+	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
+	duk__cbor_encode_ensure(enc_ctx, len);
+	p = enc_ctx->ptr;
+	duk_memcpy_unsafe((void *) p, (const void *) buf, len);
+	p += len;
+	enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_pointer(duk_cbor_encode_context *enc_ctx) {
+	/* Pointers (void *) are challenging to encode.  They can't
+	 * be relied to be even 64-bit integer compatible (there are
+	 * pointer models larger than that), nor can floats encode
+	 * them.  They could be encoded as strings (%p format) but
+	 * that's not portable.  They could be encoded as direct memory
+	 * representations.  Recovering pointers is non-portable in any
+	 * case but it would be nice to be able to detect and recover
+	 * compatible pointers.
+	 *
+	 * For now, encode as "(%p)" string, matching JX.  There doesn't
+	 * seem to be an appropriate tag, so pointers don't currently
+	 * survive a CBOR encode/decode roundtrip intact.
+	 */
+	const char *ptr;
+
+	ptr = duk_to_string(enc_ctx->thr, -1);
+	DUK_ASSERT(ptr != NULL);
+	duk_push_sprintf(enc_ctx->thr, "(%s)", ptr);
+	duk_remove(enc_ctx->thr, -2);
+	duk__cbor_encode_string_top(enc_ctx);
+}
+
+DUK_LOCAL void duk__cbor_encode_lightfunc(duk_cbor_encode_context *enc_ctx) {
+	duk_uint8_t *p;
+
+	/* Caller must ensure space. */
+	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
+
+	/* For now encode as an empty object. */
+	p = enc_ctx->ptr;
+	*p++ = 0xa0U;
+	enc_ctx->ptr = p;
+}
+
+DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) {
+	duk_uint8_t *p;
+
+	/* Encode/decode cycle currently loses some type information.
+	 * This can be improved by registering custom tags with IANA.
+	 */
+
+	/* Reserve space for up to 64-bit types (1 initial byte + 8
+	 * followup bytes).  This allows encoding of integers, floats,
+	 * string/buffer length fields, etc without separate checks
+	 * in each code path.
+	 */
+	duk__cbor_encode_ensure(enc_ctx, 1 + 8);
+
+	switch (duk_get_type(enc_ctx->thr, -1)) {
+	case DUK_TYPE_UNDEFINED: {
+		p = enc_ctx->ptr;
+		*p++ = 0xf7;
+		enc_ctx->ptr = p;
+		break;
+	}
+	case DUK_TYPE_NULL: {
+		p = enc_ctx->ptr;
+		*p++ = 0xf6;
+		enc_ctx->ptr = p;
+		break;
+	}
+	case DUK_TYPE_BOOLEAN: {
+		duk_uint8_t u8 = duk_get_boolean(enc_ctx->thr, -1) ? 0xf5U : 0xf4U;
+		p = enc_ctx->ptr;
+		*p++ = u8;
+		enc_ctx->ptr = p;
+		break;
+	}
+	case DUK_TYPE_NUMBER: {
+		duk__cbor_encode_double(enc_ctx, duk_get_number(enc_ctx->thr, -1));
+		break;
+	}
+	case DUK_TYPE_STRING: {
+		duk__cbor_encode_string_top(enc_ctx);
+		break;
+	}
+	case DUK_TYPE_OBJECT: {
+		duk__cbor_encode_object(enc_ctx);
+		break;
+	}
+	case DUK_TYPE_BUFFER: {
+		duk__cbor_encode_buffer(enc_ctx);
+		break;
+	}
+	case DUK_TYPE_POINTER: {
+		duk__cbor_encode_pointer(enc_ctx);
+		break;
+	}
+	case DUK_TYPE_LIGHTFUNC: {
+		duk__cbor_encode_lightfunc(enc_ctx);
+		break;
+	}
+	case DUK_TYPE_NONE:
+	default:
+		goto fail;
+	}
+
+	duk_pop(enc_ctx->thr);
+	return;
+
+ fail:
+	duk__cbor_encode_error(enc_ctx);
+}
+
+/*
+ *  Decoding
+ */
+
+DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) {
+	(void) duk_type_error(dec_ctx->thr, "cbor decode error");
+}
+
+DUK_LOCAL void duk__cbor_decode_req_stack(duk_cbor_decode_context *dec_ctx) {
+	duk_require_stack(dec_ctx->thr, 4);
+}
+
+DUK_LOCAL void duk__cbor_decode_objarr_entry(duk_cbor_decode_context *dec_ctx) {
+	duk_hthread *thr = dec_ctx->thr;
+
+	/* Native stack check in object/array recursion. */
+	duk_native_stack_check(thr);
+
+	duk__cbor_decode_req_stack(dec_ctx);
+
+	DUK_ASSERT(dec_ctx->recursion_depth <= dec_ctx->recursion_limit);
+	if (dec_ctx->recursion_depth >= dec_ctx->recursion_limit) {
+		DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
+		DUK_WO_NORETURN(return;);
+	}
+	dec_ctx->recursion_depth++;
+}
+
+DUK_LOCAL void duk__cbor_decode_objarr_exit(duk_cbor_decode_context *dec_ctx) {
+	DUK_ASSERT(dec_ctx->recursion_depth > 0);
+	dec_ctx->recursion_depth--;
+}
+
+DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx) {
+	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 1U)) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+	return dec_ctx->buf[dec_ctx->off++];
+}
+
+DUK_LOCAL duk_uint16_t duk__cbor_decode_read_u16(duk_cbor_decode_context *dec_ctx) {
+	duk_uint16_t res;
+
+	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 2U)) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+	res = DUK_RAW_READ_U16_BE(dec_ctx->buf + dec_ctx->off);
+	dec_ctx->off += 2;
+	return res;
+}
+
+DUK_LOCAL duk_uint32_t duk__cbor_decode_read_u32(duk_cbor_decode_context *dec_ctx) {
+	duk_uint32_t res;
+
+	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 4U)) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+	res = DUK_RAW_READ_U32_BE(dec_ctx->buf + dec_ctx->off);
+	dec_ctx->off += 4;
+	return res;
+}
+
+DUK_LOCAL duk_uint8_t duk__cbor_decode_peekbyte(duk_cbor_decode_context *dec_ctx) {
+	if (DUK_UNLIKELY(dec_ctx->off >= dec_ctx->len)) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+	return dec_ctx->buf[dec_ctx->off];
+}
+
+DUK_LOCAL void duk__cbor_decode_rewind(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
+	DUK_ASSERT(len <= dec_ctx->off);  /* Caller must ensure. */
+	dec_ctx->off -= len;
+}
+
+#if 0
+DUK_LOCAL void duk__cbor_decode_ensure(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
+	if (dec_ctx->off + len > dec_ctx->len) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+}
+#endif
+
+DUK_LOCAL const duk_uint8_t *duk__cbor_decode_consume(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
+	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
+	if (DUK_LIKELY(dec_ctx->len - dec_ctx->off >= len)) {
+		const duk_uint8_t *res = dec_ctx->buf + dec_ctx->off;
+		dec_ctx->off += len;
+		return res;
+	}
+
+	duk__cbor_decode_error(dec_ctx);  /* Not enough input. */
+	return NULL;
+}
+
+DUK_LOCAL int duk__cbor_decode_checkbreak(duk_cbor_decode_context *dec_ctx) {
+	if (duk__cbor_decode_peekbyte(dec_ctx) == 0xffU) {
+		DUK_ASSERT(dec_ctx->off < dec_ctx->len);
+		dec_ctx->off++;
+#if 0
+		(void) duk__cbor_decode_readbyte(dec_ctx);
+#endif
+		return 1;
+	}
+	return 0;
+}
+
+DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative) {
+	duk_uint8_t ai;
+	duk_uint32_t t, t1, t2;
+#if 0
+	duk_uint64_t t3;
+#endif
+	duk_double_t d1, d2;
+	duk_double_t d;
+
+	ai = ib & 0x1fU;
+	if (ai <= 0x17U) {
+		t = ai;
+		goto shared_exit;
+	}
+
+	switch (ai) {
+	case 0x18U:  /* 1 byte */
+		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
+		goto shared_exit;
+	case 0x19U:  /* 2 byte */
+		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
+		goto shared_exit;
+	case 0x1aU:  /* 4 byte */
+		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+		goto shared_exit;
+	case 0x1bU:  /* 8 byte */
+		/* For uint64 it's important to handle the -1.0 part before
+		 * casting to double: otherwise the adjustment might be lost
+		 * in the cast.  Uses: -1.0 - d <=> -(d + 1.0).
+		 */
+		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+		t2 = t;
+		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+		t1 = t;
+#if 0
+		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
+		if (negative) {
+			if (t3 == DUK_UINT64_MAX) {
+				/* -(0xffff'ffff'ffff'ffffULL + 1) =
+				 * -0x1'0000'0000'0000'0000
+				 *
+				 * >>> -0x10000000000000000
+				 * -18446744073709551616L
+				 */
+				return -18446744073709551616.0;
+			} else {
+				return -((duk_double_t) (t3 + DUK_U64_CONSTANT(1)));
+			}
+		} else {
+			return (duk_double_t) t3;  /* XXX: cast helper */
+		}
+#endif
+#if 0
+		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
+		if (negative) {
+			/* Simpler version: take advantage of the fact that
+			 * 0xffff'ffff'ffff'ffff and 0x1'0000'0000'0000'0000
+			 * both round to 0x1'0000'0000'0000'0000:
+			 * > (0xffffffffffffffff).toString(16)
+			 * '10000000000000000'
+			 * > (0x10000000000000000).toString(16)
+			 * '10000000000000000'
+			 *
+			 * For the DUK_UINT64_MAX case we just skip the +1
+			 * increment to avoid wrapping; the result still
+			 * comes out right for an IEEE double cast.
+			 */
+			if (t3 != DUK_UINT64_MAX) {
+				t3++;
+			}
+			return -((duk_double_t) t3);
+		} else {
+			return (duk_double_t) t3;  /* XXX: cast helper */
+		}
+#endif
+#if 1
+		/* Use two double parts, avoids dependency on 64-bit type.
+		 * Avoid precision loss carefully, especially when dealing
+		 * with the required +1 for negative values.
+		 *
+		 * No fastint check for this path at present.
+		 */
+		d1 = (duk_double_t) t1;  /* XXX: cast helpers */
+		d2 = (duk_double_t) t2 * 4294967296.0;
+		if (negative) {
+			d1 += 1.0;
+		}
+		d = d2 + d1;
+		if (negative) {
+			d = -d;
+		}
+#endif
+		/* XXX: a push and check for fastint API would be nice */
+		duk_push_number(dec_ctx->thr, d);
+		return;
+	}
+
+	duk__cbor_decode_error(dec_ctx);
+	return;
+
+ shared_exit:
+	if (negative) {
+		/* XXX: a push and check for fastint API would be nice */
+		if ((duk_uint_t) t <= (duk_uint_t) -(DUK_INT_MIN + 1)) {
+			duk_push_int(dec_ctx->thr, -1 - ((duk_int_t) t));
+		} else {
+			duk_push_number(dec_ctx->thr, -1.0 - (duk_double_t) t);
+		}
+	} else {
+		duk_push_uint(dec_ctx->thr, (duk_uint_t) t);
+	}
+}
+
+DUK_LOCAL void duk__cbor_decode_skip_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
+	const duk_int8_t skips[32] = {
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, -1, -1, -1, -1
+	};
+	duk_uint8_t ai;
+	duk_int8_t skip;
+
+	ai = ib & 0x1fU;
+	skip = skips[ai];
+	if (DUK_UNLIKELY(skip < 0)) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+	duk__cbor_decode_consume(dec_ctx, (duk_size_t) skip);
+	return;
+}
+
+DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
+	duk_uint8_t ai;
+	duk_uint32_t t;
+
+	ai = ib & 0x1fU;
+	if (ai <= 0x17U) {
+		return (duk_uint32_t) ai;
+	}
+
+	switch (ai) {
+	case 0x18U:  /* 1 byte */
+		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
+		return t;
+	case 0x19U:  /* 2 byte */
+		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
+		return t;
+	case 0x1aU:  /* 4 byte */
+		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+		return t;
+	case 0x1bU:  /* 8 byte */
+		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+		if (t != 0U) {
+			break;
+		}
+		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
+		return t;
+	}
+
+	duk__cbor_decode_error(dec_ctx);
+	return 0U;
+}
+
+DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
+	duk_uint32_t len;
+	duk_uint8_t *buf;
+	const duk_uint8_t *inp;
+	duk_uint8_t ib;
+
+	ib = duk__cbor_decode_readbyte(dec_ctx);
+	if ((ib & 0xe0U) != expected_base) {
+		duk__cbor_decode_error(dec_ctx);
+	}
+	/* Indefinite format is rejected by the following on purpose. */
+	len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+	inp = duk__cbor_decode_consume(dec_ctx, len);
+	/* XXX: duk_push_fixed_buffer_with_data() would be a nice API addition. */
+	buf = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, (duk_size_t) len);
+	duk_memcpy((void *) buf, (const void *) inp, (size_t) len);
+}
+
+DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, duk_idx_t count) {
+	duk_size_t total_size = 0;
+	duk_idx_t top = duk_get_top(dec_ctx->thr);
+	duk_idx_t base = top - count;  /* count is >= 1 */
+	duk_idx_t idx;
+	duk_uint8_t *p = NULL;
+
+	DUK_ASSERT(count >= 1);
+	DUK_ASSERT(top >= count);
+
+	for (;;) {
+		/* First round: compute total size.
+		 * Second round: copy into place.
+		 */
+		for (idx = base; idx < top; idx++) {
+			duk_uint8_t *buf_data;
+			duk_size_t buf_size;
+
+			buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size);
+			if (p != NULL) {
+				duk_memcpy_unsafe((void *) p, (const void *) buf_data, buf_size);
+				p += buf_size;
+			} else {
+				total_size += buf_size;
+				if (DUK_UNLIKELY(total_size < buf_size)) {  /* Wrap check. */
+					duk__cbor_decode_error(dec_ctx);
+				}
+			}
+		}
+
+		if (p != NULL) {
+			break;
+		} else {
+			p = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, total_size);
+			DUK_ASSERT(p != NULL);
+		}
+	}
+
+	duk_replace(dec_ctx->thr, base);
+	duk_pop_n(dec_ctx->thr, count - 1);
+}
+
+DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
+	duk_idx_t count = 0;
+	for (;;) {
+		if (duk__cbor_decode_checkbreak(dec_ctx)) {
+			break;
+		}
+		duk_require_stack(dec_ctx->thr, 1);
+		duk__cbor_decode_buffer(dec_ctx, expected_base);
+		count++;
+		if (DUK_UNLIKELY(count <= 0)) {  /* Wrap check. */
+			duk__cbor_decode_error(dec_ctx);
+		}
+	}
+	if (count == 0) {
+		(void) duk_push_fixed_buffer(dec_ctx->thr, 0);
+	} else if (count > 1) {
+		duk__cbor_decode_join_buffers(dec_ctx, count);
+	}
+}
+
+DUK_LOCAL duk_double_t duk__cbor_decode_half_float(duk_cbor_decode_context *dec_ctx) {
+	duk_double_union u;
+	const duk_uint8_t *inp;
+	duk_int_t expt;
+	duk_uint_t u16;
+	duk_uint_t tmp;
+	duk_double_t res;
+
+	inp = duk__cbor_decode_consume(dec_ctx, 2);
+	u16 = ((duk_uint_t) inp[0] << 8) + (duk_uint_t) inp[1];
+	expt = (duk_int_t) ((u16 >> 10) & 0x1fU) - 15;
+
+	/* Reconstruct IEEE double into little endian order first, then convert
+	 * to host order.
+	 */
+
+	duk_memzero((void *) &u, sizeof(u));
+
+	if (expt == -15) {
+		/* Zero or denormal; but note that half float
+		 * denormals become double normals.
+		 */
+		if ((u16 & 0x03ffU) == 0) {
+			u.uc[7] = inp[0] & 0x80U;
+		} else {
+			/* Create denormal by first creating a double that
+			 * contains the denormal bits and a leading implicit
+			 * 1-bit.  Then subtract away the implicit 1-bit.
+			 *
+			 *    0.mmmmmmmmmm * 2^-14
+			 *    1.mmmmmmmmmm 0.... * 2^-14
+			 *   -1.0000000000 0.... * 2^-14
+			 *
+			 * Double exponent: -14 + 1023 = 0x3f1
+			 */
+			u.uc[7] = 0x3fU;
+			u.uc[6] = 0x10U + (duk_uint8_t) ((u16 >> 6) & 0x0fU);
+			u.uc[5] = (duk_uint8_t) ((u16 << 2) & 0xffU);  /* Mask is really 0xfcU */
+
+			duk_dblunion_little_to_host(&u);
+			res = u.d - 0.00006103515625;  /* 2^(-14) */
+			if (u16 & 0x8000U) {
+				res = -res;
+			}
+			return res;
+		}
+	} else if (expt == 16) {
+		/* +/- Inf or NaN. */
+		if ((u16 & 0x03ffU) == 0) {
+			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
+			u.uc[6] = 0xf0U;
+		} else {
+			/* Create a 'quiet NaN' with highest
+			 * bit set (there are some platforms
+			 * where the NaN payload convention is
+			 * the opposite).  Keep sign.
+			 */
+			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
+			u.uc[6] = 0xf8U;
+		}
+	} else {
+		/* Normal. */
+		tmp = (inp[0] & 0x80U) ? 0x80000000UL : 0UL;
+		tmp += (duk_uint_t) (expt + 1023) << 20;
+		tmp += (duk_uint_t) (inp[0] & 0x03U) << 18;
+		tmp += (duk_uint_t) (inp[1] & 0xffU) << 10;
+		u.uc[7] = (tmp >> 24) & 0xffU;
+		u.uc[6] = (tmp >> 16) & 0xffU;
+		u.uc[5] = (tmp >> 8) & 0xffU;
+		u.uc[4] = (tmp >> 0) & 0xffU;
+	}
+
+	duk_dblunion_little_to_host(&u);
+	return u.d;
+}
+
+DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
+	/* If the CBOR string data is not valid UTF-8 it is technically
+	 * invalid CBOR.  Possible behaviors at least:
+	 *
+	 *   1. Reject the input, i.e. throw TypeError.
+	 *
+	 *   2. Accept the input, but sanitize non-UTF-8 data into UTF-8
+	 *      using U+FFFD replacements.  Also it might make sense to
+	 *      decode non-BMP codepoints into surrogates for better
+	 *      ECMAScript compatibility.
+	 *
+	 *   3. Accept the input as a Duktape string (which are not always
+	 *      valid UTF-8), but reject any input that would create a
+	 *      Symbol representation.
+	 *
+	 * Current behavior is 3.
+	 */
+
+	if (ai == 0x1fU) {
+		duk_uint8_t *buf_data;
+		duk_size_t buf_size;
+
+		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x60U);
+		buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, -1, &buf_size);
+		(void) duk_push_lstring(dec_ctx->thr, (const char *) buf_data, buf_size);
+		duk_remove(dec_ctx->thr, -2);
+	} else {
+		duk_uint32_t len;
+		const duk_uint8_t *inp;
+
+		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+		inp = duk__cbor_decode_consume(dec_ctx, len);
+		(void) duk_push_lstring(dec_ctx->thr, (const char *) inp, (duk_size_t) len);
+	}
+	if (duk_is_symbol(dec_ctx->thr, -1)) {
+		/* Refuse to create Symbols when decoding. */
+		duk__cbor_decode_error(dec_ctx);
+	}
+
+	/* XXX: Here a Duktape API call to convert input -> utf-8 with
+	 * replacements would be nice.
+	 */
+}
+
+DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
+	duk_uint32_t idx, len;
+
+	duk__cbor_decode_objarr_entry(dec_ctx);
+
+	/* Support arrays up to 0xfffffffeU in length.  0xffffffff is
+	 * used as an indefinite length marker.
+	 */
+	if (ai == 0x1fU) {
+		len = 0xffffffffUL;
+	} else {
+		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+		if (len == 0xffffffffUL) {
+			goto failure;
+		}
+	}
+
+	/* XXX: use bare array? */
+	duk_push_array(dec_ctx->thr);
+	for (idx = 0U; ;) {
+		if (len == 0xffffffffUL && duk__cbor_decode_checkbreak(dec_ctx)) {
+			break;
+		}
+		if (idx == len) {
+			if (ai == 0x1fU) {
+				goto failure;
+			}
+			break;
+		}
+		duk__cbor_decode_value(dec_ctx);
+		duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx);
+		idx++;
+		if (idx == 0U) {
+			goto failure;  /* wrapped */
+		}
+	}
+
+#if 0
+ success:
+#endif
+	duk__cbor_decode_objarr_exit(dec_ctx);
+	return 1;
+
+ failure:
+	/* No need to unwind recursion checks, caller will throw. */
+	return 0;
+}
+
+DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
+	duk_uint32_t count;
+
+	duk__cbor_decode_objarr_entry(dec_ctx);
+
+	if (ai == 0x1fU) {
+		count = 0xffffffffUL;
+	} else {
+		count = duk__cbor_decode_aival_uint32(dec_ctx, ib);
+		if (count == 0xffffffffUL) {
+			goto failure;
+		}
+	}
+
+	/* XXX: use bare object? */
+	duk_push_object(dec_ctx->thr);
+	for (;;) {
+		if (count == 0xffffffffUL) {
+			if (duk__cbor_decode_checkbreak(dec_ctx)) {
+				break;
+			}
+		} else {
+			if (count == 0UL) {
+				break;
+			}
+			count--;
+		}
+
+		/* Non-string keys are coerced to strings,
+		 * possibly leading to overwriting previous
+		 * keys.  Last key of a certain coerced name
+		 * wins.  If key is an object, it will coerce
+		 * to '[object Object]' which is consistent
+		 * but potentially misleading.  One alternative
+		 * would be to skip non-string keys.
+		 */
+		duk__cbor_decode_value(dec_ctx);
+		duk__cbor_decode_value(dec_ctx);
+		duk_put_prop(dec_ctx->thr, -3);
+	}
+
+#if 0
+ success:
+#endif
+	duk__cbor_decode_objarr_exit(dec_ctx);
+	return 1;
+
+ failure:
+	/* No need to unwind recursion checks, caller will throw. */
+	return 0;
+}
+
+DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx) {
+	duk_float_union u;
+	const duk_uint8_t *inp;
+	inp = duk__cbor_decode_consume(dec_ctx, 4);
+	duk_memcpy((void *) u.uc, (const void *) inp, 4);
+	duk_fltunion_big_to_host(&u);
+	return (duk_double_t) u.f;
+}
+
+DUK_LOCAL duk_double_t duk__cbor_decode_double(duk_cbor_decode_context *dec_ctx) {
+	duk_double_union u;
+	const duk_uint8_t *inp;
+	inp = duk__cbor_decode_consume(dec_ctx, 8);
+	duk_memcpy((void *) u.uc, (const void *) inp, 8);
+	duk_dblunion_big_to_host(&u);
+	return u.d;
+}
+
+#if defined(DUK_CBOR_DECODE_FASTPATH)
+#define DUK__CBOR_AI  (ib & 0x1fU)
+
+DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
+	duk_uint8_t ib;
+
+	/* Any paths potentially recursing back to duk__cbor_decode_value()
+	 * must perform a Duktape value stack growth check.  Avoid the check
+	 * here for simple paths like primitive values.
+	 */
+
+ reread_initial_byte:
+	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
+
+	ib = duk__cbor_decode_readbyte(dec_ctx);
+
+	/* Full initial byte switch, footprint cost over baseline is ~+1kB. */
+	/* XXX: Force full switch with no range check. */
+
+	switch (ib) {
+	case 0x00U: case 0x01U: case 0x02U: case 0x03U: case 0x04U: case 0x05U: case 0x06U: case 0x07U:
+	case 0x08U: case 0x09U: case 0x0aU: case 0x0bU: case 0x0cU: case 0x0dU: case 0x0eU: case 0x0fU:
+	case 0x10U: case 0x11U: case 0x12U: case 0x13U: case 0x14U: case 0x15U: case 0x16U: case 0x17U:
+		duk_push_uint(dec_ctx->thr, ib);
+		break;
+	case 0x18U: case 0x19U: case 0x1aU: case 0x1bU:
+		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
+		break;
+	case 0x1cU: case 0x1dU: case 0x1eU: case 0x1fU:
+		goto format_error;
+	case 0x20U: case 0x21U: case 0x22U: case 0x23U: case 0x24U: case 0x25U: case 0x26U: case 0x27U:
+	case 0x28U: case 0x29U: case 0x2aU: case 0x2bU: case 0x2cU: case 0x2dU: case 0x2eU: case 0x2fU:
+	case 0x30U: case 0x31U: case 0x32U: case 0x33U: case 0x34U: case 0x35U: case 0x36U: case 0x37U:
+		duk_push_int(dec_ctx->thr, -((duk_int_t) ((ib - 0x20U) + 1U)));
+		break;
+	case 0x38U: case 0x39U: case 0x3aU: case 0x3bU:
+		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
+		break;
+	case 0x3cU: case 0x3dU: case 0x3eU: case 0x3fU:
+		goto format_error;
+	case 0x40U: case 0x41U: case 0x42U: case 0x43U: case 0x44U: case 0x45U: case 0x46U: case 0x47U:
+	case 0x48U: case 0x49U: case 0x4aU: case 0x4bU: case 0x4cU: case 0x4dU: case 0x4eU: case 0x4fU:
+	case 0x50U: case 0x51U: case 0x52U: case 0x53U: case 0x54U: case 0x55U: case 0x56U: case 0x57U:
+		/* XXX: Avoid rewind, we know the length already. */
+		DUK_ASSERT(dec_ctx->off > 0U);
+		dec_ctx->off--;
+		duk__cbor_decode_buffer(dec_ctx, 0x40U);
+		break;
+	case 0x58U: case 0x59U: case 0x5aU: case 0x5bU:
+		/* XXX: Avoid rewind, decode length inline. */
+		DUK_ASSERT(dec_ctx->off > 0U);
+		dec_ctx->off--;
+		duk__cbor_decode_buffer(dec_ctx, 0x40U);
+		break;
+	case 0x5cU: case 0x5dU: case 0x5eU:
+		goto format_error;
+	case 0x5fU:
+		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
+		break;
+	case 0x60U: case 0x61U: case 0x62U: case 0x63U: case 0x64U: case 0x65U: case 0x66U: case 0x67U:
+	case 0x68U: case 0x69U: case 0x6aU: case 0x6bU: case 0x6cU: case 0x6dU: case 0x6eU: case 0x6fU:
+	case 0x70U: case 0x71U: case 0x72U: case 0x73U: case 0x74U: case 0x75U: case 0x76U: case 0x77U:
+		/* XXX: Avoid double decode of length. */
+		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
+		break;
+	case 0x78U: case 0x79U: case 0x7aU: case 0x7bU:
+		/* XXX: Avoid double decode of length. */
+		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
+		break;
+	case 0x7cU: case 0x7dU: case 0x7eU:
+		goto format_error;
+	case 0x7fU:
+		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
+		break;
+	case 0x80U: case 0x81U: case 0x82U: case 0x83U: case 0x84U: case 0x85U: case 0x86U: case 0x87U:
+	case 0x88U: case 0x89U: case 0x8aU: case 0x8bU: case 0x8cU: case 0x8dU: case 0x8eU: case 0x8fU:
+	case 0x90U: case 0x91U: case 0x92U: case 0x93U: case 0x94U: case 0x95U: case 0x96U: case 0x97U:
+		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+			goto format_error;
+		}
+		break;
+	case 0x98U: case 0x99U: case 0x9aU: case 0x9bU:
+		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+			goto format_error;
+		}
+		break;
+	case 0x9cU: case 0x9dU: case 0x9eU:
+		goto format_error;
+	case 0x9fU:
+		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+			goto format_error;
+		}
+		break;
+	case 0xa0U: case 0xa1U: case 0xa2U: case 0xa3U: case 0xa4U: case 0xa5U: case 0xa6U: case 0xa7U:
+	case 0xa8U: case 0xa9U: case 0xaaU: case 0xabU: case 0xacU: case 0xadU: case 0xaeU: case 0xafU:
+	case 0xb0U: case 0xb1U: case 0xb2U: case 0xb3U: case 0xb4U: case 0xb5U: case 0xb6U: case 0xb7U:
+		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+			goto format_error;
+		}
+		break;
+	case 0xb8U: case 0xb9U: case 0xbaU: case 0xbbU:
+		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+			goto format_error;
+		}
+		break;
+	case 0xbcU: case 0xbdU: case 0xbeU:
+		goto format_error;
+	case 0xbfU:
+		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
+			goto format_error;
+		}
+		break;
+	case 0xc0U: case 0xc1U: case 0xc2U: case 0xc3U: case 0xc4U: case 0xc5U: case 0xc6U: case 0xc7U:
+	case 0xc8U: case 0xc9U: case 0xcaU: case 0xcbU: case 0xccU: case 0xcdU: case 0xceU: case 0xcfU:
+	case 0xd0U: case 0xd1U: case 0xd2U: case 0xd3U: case 0xd4U: case 0xd5U: case 0xd6U: case 0xd7U:
+		/* Tag 0-23: drop. */
+		goto reread_initial_byte;
+	case 0xd8U: case 0xd9U: case 0xdaU: case 0xdbU:
+		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
+		goto reread_initial_byte;
+	case 0xdcU: case 0xddU: case 0xdeU: case 0xdfU:
+		goto format_error;
+	case 0xe0U:
+		goto format_error;
+	case 0xe1U:
+		goto format_error;
+	case 0xe2U:
+		goto format_error;
+	case 0xe3U:
+		goto format_error;
+	case 0xe4U:
+		goto format_error;
+	case 0xe5U:
+		goto format_error;
+	case 0xe6U:
+		goto format_error;
+	case 0xe7U:
+		goto format_error;
+	case 0xe8U:
+		goto format_error;
+	case 0xe9U:
+		goto format_error;
+	case 0xeaU:
+		goto format_error;
+	case 0xebU:
+		goto format_error;
+	case 0xecU:
+		goto format_error;
+	case 0xedU:
+		goto format_error;
+	case 0xeeU:
+		goto format_error;
+	case 0xefU:
+		goto format_error;
+	case 0xf0U:
+		goto format_error;
+	case 0xf1U:
+		goto format_error;
+	case 0xf2U:
+		goto format_error;
+	case 0xf3U:
+		goto format_error;
+	case 0xf4U:
+		duk_push_false(dec_ctx->thr);
+		break;
+	case 0xf5U:
+		duk_push_true(dec_ctx->thr);
+		break;
+	case 0xf6U:
+		duk_push_null(dec_ctx->thr);
+		break;
+	case 0xf7U:
+		duk_push_undefined(dec_ctx->thr);
+		break;
+	case 0xf8U:
+		/* Simple value 32-255, nothing defined yet, so reject. */
+		goto format_error;
+	case 0xf9U: {
+		duk_double_t d;
+		d = duk__cbor_decode_half_float(dec_ctx);
+		duk_push_number(dec_ctx->thr, d);
+		break;
+	}
+	case 0xfaU: {
+		duk_double_t d;
+		d = duk__cbor_decode_float(dec_ctx);
+		duk_push_number(dec_ctx->thr, d);
+		break;
+	}
+	case 0xfbU: {
+		duk_double_t d;
+		d = duk__cbor_decode_double(dec_ctx);
+		duk_push_number(dec_ctx->thr, d);
+		break;
+	}
+	case 0xfcU:
+	case 0xfdU:
+	case 0xfeU:
+	case 0xffU:
+		goto format_error;
+	}  /* end switch */
+
+	return;
+
+ format_error:
+	duk__cbor_decode_error(dec_ctx);
+}
+#else  /* DUK_CBOR_DECODE_FASTPATH */
+DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
+	duk_uint8_t ib, mt, ai;
+
+	/* Any paths potentially recursing back to duk__cbor_decode_value()
+	 * must perform a Duktape value stack growth check.  Avoid the check
+	 * here for simple paths like primitive values.
+	 */
+
+ reread_initial_byte:
+	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
+
+	ib = duk__cbor_decode_readbyte(dec_ctx);
+	mt = ib >> 5U;
+	ai = ib & 0x1fU;
+
+	/* Additional information in [24,27] = [0x18,0x1b] has relatively
+	 * uniform handling for all major types: read 1/2/4/8 additional
+	 * bytes.  For major type 7 the 1-byte value is a 'simple type', and
+	 * 2/4/8-byte values are floats.  For other major types the 1/2/4/8
+	 * byte values are integers.  The lengths are uniform, but the typing
+	 * is not.
+	 */
+
+	switch (mt) {
+	case 0U: {  /* unsigned integer */
+		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
+		break;
+	}
+	case 1U: {  /* negative integer */
+		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
+		break;
+	}
+	case 2U: {  /* byte string */
+		if (ai == 0x1fU) {
+			duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
+		} else {
+			duk__cbor_decode_rewind(dec_ctx, 1U);
+			duk__cbor_decode_buffer(dec_ctx, 0x40U);
+		}
+		break;
+	}
+	case 3U: {  /* text string */
+		duk__cbor_decode_string(dec_ctx, ib, ai);
+		break;
+	}
+	case 4U: {  /* array of data items */
+		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, ai) == 0)) {
+			goto format_error;
+		}
+		break;
+	}
+	case 5U: {  /* map of pairs of data items */
+		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, ai) == 0)) {
+			goto format_error;
+		}
+		break;
+	}
+	case 6U: {  /* semantic tagging */
+		/* Tags are ignored now, re-read initial byte.  A tagged
+		 * value may itself be tagged (an unlimited number of times)
+		 * so keep on peeling away tags.
+		 */
+		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
+		goto reread_initial_byte;
+	}
+	case 7U: {  /* floating point numbers, simple data types, break; other */
+		switch (ai) {
+		case 0x14U: {
+			duk_push_false(dec_ctx->thr);
+			break;
+		}
+		case 0x15U: {
+			duk_push_true(dec_ctx->thr);
+			break;
+		}
+		case 0x16U: {
+			duk_push_null(dec_ctx->thr);
+			break;
+		}
+		case 0x17U: {
+			duk_push_undefined(dec_ctx->thr);
+			break;
+		}
+		case 0x18U: {  /* more simple values (1 byte) */
+			/* Simple value encoded in additional byte (none
+			 * are defined so far).  RFC 7049 states that the
+			 * follow-up byte must be 32-255 to minimize
+			 * confusion.  So, a non-shortest encoding like
+			 * f815 (= true, shortest encoding f5) must be
+			 * rejected.  cbor.me tester rejects f815, but
+			 * e.g. Python CBOR binding decodes it as true.
+			 */
+			goto format_error;
+		}
+		case 0x19U: {  /* half-float (2 bytes) */
+			duk_double_t d;
+			d = duk__cbor_decode_half_float(dec_ctx);
+			duk_push_number(dec_ctx->thr, d);
+			break;
+		}
+		case 0x1aU: {  /* float (4 bytes) */
+			duk_double_t d;
+			d = duk__cbor_decode_float(dec_ctx);
+			duk_push_number(dec_ctx->thr, d);
+			break;
+		}
+		case 0x1bU: {  /* double (8 bytes) */
+			duk_double_t d;
+			d = duk__cbor_decode_double(dec_ctx);
+			duk_push_number(dec_ctx->thr, d);
+			break;
+		}
+		case 0xffU:  /* unexpected break */
+		default: {
+			goto format_error;
+		}
+		}  /* end switch */
+		break;
+	}
+	default: {
+		goto format_error;  /* will never actually occur */
+	}
+	}  /* end switch */
+
+	return;
+
+ format_error:
+	duk__cbor_decode_error(dec_ctx);
+}
+#endif  /* DUK_CBOR_DECODE_FASTPATH */
+
+DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
+	duk_cbor_encode_context enc_ctx;
+	duk_uint8_t *buf;
+
+	DUK_UNREF(encode_flags);
+
+	idx = duk_require_normalize_index(thr, idx);
+
+	enc_ctx.thr = thr;
+	enc_ctx.idx_buf = duk_get_top(thr);
+
+	enc_ctx.len = 64;
+	buf = (duk_uint8_t *) duk_push_dynamic_buffer(thr, enc_ctx.len);
+	enc_ctx.ptr = buf;
+	enc_ctx.buf = buf;
+	enc_ctx.buf_end = buf + enc_ctx.len;
+
+	enc_ctx.recursion_depth = 0;
+	enc_ctx.recursion_limit = DUK_USE_CBOR_ENC_RECLIMIT;
+
+	duk_dup(thr, idx);
+	duk__cbor_encode_req_stack(&enc_ctx);
+	duk__cbor_encode_value(&enc_ctx);
+	DUK_ASSERT(enc_ctx.recursion_depth == 0);
+	duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf));
+	duk_replace(thr, idx);
+}
+
+DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
+	duk_cbor_decode_context dec_ctx;
+
+	DUK_UNREF(decode_flags);
+
+	/* Suppress compile warnings for functions only needed with e.g.
+	 * asserts enabled.
+	 */
+	DUK_UNREF(duk__cbor_get_reserve);
+
+	idx = duk_require_normalize_index(thr, idx);
+
+	dec_ctx.thr = thr;
+	dec_ctx.buf = (const duk_uint8_t *) duk_require_buffer_data(thr, idx, &dec_ctx.len);
+	dec_ctx.off = 0;
+	/* dec_ctx.len: set above */
+
+	dec_ctx.recursion_depth = 0;
+	dec_ctx.recursion_limit = DUK_USE_CBOR_DEC_RECLIMIT;
+
+	duk__cbor_decode_req_stack(&dec_ctx);
+	duk__cbor_decode_value(&dec_ctx);
+	DUK_ASSERT(dec_ctx.recursion_depth == 0);
+	if (dec_ctx.off != dec_ctx.len) {
+		(void) duk_type_error(thr, "trailing garbage");
+	}
+
+	duk_replace(thr, idx);
+}
+
+#else  /* DUK_USE_CBOR_SUPPORT */
+
+DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
+	DUK_UNREF(idx);
+	DUK_UNREF(encode_flags);
+	DUK_ERROR_UNSUPPORTED(thr);
+}
+
+DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
+	DUK_UNREF(idx);
+	DUK_UNREF(decode_flags);
+	DUK_ERROR_UNSUPPORTED(thr);
+}
+
+#endif  /* DUK_USE_CBOR_SUPPORT */
+
+/*
+ *  Public APIs
+ */
+
+DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
+	DUK_ASSERT_API_ENTRY(thr);
+	duk__cbor_encode(thr, idx, encode_flags);
+}
+DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
+	DUK_ASSERT_API_ENTRY(thr);
+	duk__cbor_decode(thr, idx, decode_flags);
+}
+
+#if defined(DUK_USE_CBOR_BUILTIN)
+#if defined(DUK_USE_CBOR_SUPPORT)
+DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
+	DUK_ASSERT_TOP(thr, 1);
+
+	duk__cbor_encode(thr, -1, 0 /*flags*/);
+
+	/* Produce an ArrayBuffer by first decoding into a plain buffer which
+	 * mimics a Uint8Array and gettings its .buffer property.
+	 */
+	/* XXX: shortcut */
+	(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_LC_BUFFER);
+	return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
+	DUK_ASSERT_TOP(thr, 1);
+
+	duk__cbor_decode(thr, -1, 0 /*flags*/);
+	return 1;
+}
+#else  /* DUK_USE_CBOR_SUPPORT */
+DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
+	DUK_ERROR_UNSUPPORTED(thr);
+	DUK_WO_NORETURN(return 0;);
+}
+DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
+	DUK_ERROR_UNSUPPORTED(thr);
+	DUK_WO_NORETURN(return 0;);
+}
+#endif  /* DUK_USE_CBOR_SUPPORT */
+#endif  /* DUK_USE_CBOR_BUILTIN */
+
+/* automatic undefs */
+#undef DUK__CBOR_AI
 #line 1 "duk_bi_date.c"
 /*
  *  Date built-ins
@@ -30205,7 +32430,7 @@
 
 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
 	d = DUK_FLOOR(d);  /* remove fractions if present */
-	DUK_ASSERT(DUK_FLOOR(d) == d);
+	DUK_ASSERT(duk_double_equals(DUK_FLOOR(d), d));
 
 	/* The timevalue must be in valid ECMAScript range, but since a local
 	 * time offset can be applied, we need to allow a +/- 24h leeway to
@@ -30224,13 +32449,13 @@
 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
 	}
 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
-	DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
+	DUK_ASSERT(duk_double_equals(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1, d));
 	/* now expected to fit into a 32-bit integer */
 	t1 = (duk_int_t) d1;
 	t2 = (duk_int_t) d2;
 	day_since_epoch = t2;
-	DUK_ASSERT((duk_double_t) t1 == d1);
-	DUK_ASSERT((duk_double_t) t2 == d2);
+	DUK_ASSERT(duk_double_equals((duk_double_t) t1, d1));
+	DUK_ASSERT(duk_double_equals((duk_double_t) t2, d2));
 
 	/* t1 = milliseconds within day (fits 32 bit)
 	 * t2 = day number from epoch (fits 32 bit, may be negative)
@@ -30483,7 +32708,7 @@
 		DUK_WO_NORETURN(return 0.0;);
 	}
 
-	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
 	d = duk_to_number_m1(thr);
 	duk_pop(thr);
 
@@ -30530,9 +32755,13 @@
 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
 	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
 	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */
-	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE);
-
-	/* stack top: new time value, return 1 to allow tail calls */
+
+	/* Must force write because e.g. .setYear() must work even when
+	 * the Date instance is frozen.
+	 */
+	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
+
+	/* Stack top: new time value, return 1 to allow tail calls. */
 	return 1;
 }
 
@@ -31083,7 +33312,7 @@
 	duk_double_t d;
 
 	d = duk_time_get_ecmascript_time_nofrac(thr);
-	DUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */
+	DUK_ASSERT(duk_double_equals(duk__timeclip(d), d));  /* TimeClip() should never be necessary */
 	duk_push_number(thr, d);
 	return 1;
 }
@@ -31301,7 +33530,11 @@
 	d = duk__timeclip(duk_to_number(thr, 0));
 	duk_push_number(thr, d);
 	duk_dup_top(thr);
-	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
+	/* Must force write because .setTime() must work even when
+	 * the Date instance is frozen.
+	 */
+	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
+	/* -> [ timeval this timeval ] */
 
 	return 1;
 }
@@ -31820,7 +34053,6 @@
 	ULARGE_INTEGER tmp2;
 	ULARGE_INTEGER tmp3;
 	FILETIME ft1;
-	BOOL ret;
 
 	/* XXX: handling of timestamps outside Windows supported range.
 	 * How does Windows deal with dates before 1600?  Does windows
@@ -31840,8 +34072,7 @@
 
 	ft1.dwLowDateTime = tmp2.LowPart;
 	ft1.dwHighDateTime = tmp2.HighPart;
-	ret = FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
-	if (!ret) {
+	if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
 		return 0;
 	}
@@ -31864,7 +34095,6 @@
 	FILETIME ft2;
 	ULARGE_INTEGER tmp1;
 	ULARGE_INTEGER tmp2;
-	BOOL ret;
 
 	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
 	 * but without accounting for daylight savings time.  Use this on
@@ -31880,14 +34110,11 @@
 
 	ft1.dwLowDateTime = tmp1.LowPart;
 	ft1.dwHighDateTime = tmp1.HighPart;
-	ret = FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2);
-	if (!ret) {
+	if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
 		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
 		return 0;
 	}
-
-	ret = FileTimeToSystemTime((const FILETIME *) &ft2, &st2);
-	if (!ret) {
+	if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
 		return 0;
 	}
@@ -32749,7 +34976,7 @@
 	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */
 
 	duk_push_this(thr);
-	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
+	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
 	idx_td = duk_get_top_index(thr);
 
 	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
@@ -34229,28 +36456,28 @@
 #define DUK__JSON_STRINGIFY_BUFSIZE 128
 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
 
-DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx);
 #if defined(DUK_USE_JX)
-DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
-#endif
-DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
-DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
-DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx);
+#endif
+DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
+DUK_LOCAL_DECL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
+DUK_LOCAL_DECL void duk__json_dec_string(duk_json_dec_ctx *js_ctx);
 #if defined(DUK_USE_JX)
-DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
-#endif
-DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx);
+#endif
+DUK_LOCAL_DECL void duk__json_dec_number(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_object(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_array(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_value(duk_json_dec_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx);
 
 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
@@ -34261,29 +36488,29 @@
 #endif
 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
 DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);
-DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
-DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
-DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
-DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
-DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
-DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
-DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
-DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
-DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
+DUK_LOCAL_DECL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
+DUK_LOCAL_DECL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__json_enc_object(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL void duk__json_enc_array(duk_json_enc_ctx *js_ctx);
+DUK_LOCAL_DECL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
+DUK_LOCAL_DECL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv);
+DUK_LOCAL_DECL void duk__json_enc_double(duk_json_enc_ctx *js_ctx);
 #if defined(DUK_USE_FASTINT)
-DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
+DUK_LOCAL_DECL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
 #endif
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
-DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
+DUK_LOCAL_DECL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
+DUK_LOCAL_DECL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
-DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
+DUK_LOCAL_DECL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
 #endif
 #endif
 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
-DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
-#endif
-DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
+DUK_LOCAL_DECL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
+#endif
+DUK_LOCAL_DECL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
 
 /*
  *  Helper tables
@@ -34408,7 +36635,7 @@
  *  CESU-8 encodings.
  */
 
-DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx) {
 	/* Shared handler to minimize parser size.  Cause will be
 	 * hidden, unfortunately, but we'll have an offset which
 	 * is often quite enough.
@@ -34418,7 +36645,7 @@
 	DUK_WO_NORETURN(return;);
 }
 
-DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx) {
 	const duk_uint8_t *p;
 	duk_uint8_t t;
 
@@ -34449,24 +36676,24 @@
 }
 
 #if defined(DUK_USE_JX)
-DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx) {
 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
 	return *js_ctx->p;
 }
 #endif
 
-DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx) {
 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
 	return *js_ctx->p++;
 }
 
-DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
-	duk__dec_eat_white(js_ctx);
-	return duk__dec_get(js_ctx);
+DUK_LOCAL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
+	duk__json_dec_eat_white(js_ctx);
+	return duk__json_dec_get(js_ctx);
 }
 
 /* For JX, expressing the whole unsigned 32-bit range matters. */
-DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
+DUK_LOCAL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
 	duk_small_uint_t i;
 	duk_uint_fast32_t res = 0;
 	duk_uint8_t x;
@@ -34475,7 +36702,7 @@
 	for (i = 0; i < n; i++) {
 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
 
-		x = duk__dec_get(js_ctx);
+		x = duk__json_dec_get(js_ctx);
 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
 		                     (long) i, (long) n, (long) res, (long) x));
 
@@ -34494,12 +36721,12 @@
 	return res;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 	return 0;
 }
 
-DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
+DUK_LOCAL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
 	duk_hstring *h;
 	const duk_uint8_t *p;
 	duk_uint8_t x, y;
@@ -34521,7 +36748,7 @@
 		if (x == 0) {
 			break;
 		}
-		y = duk__dec_get(js_ctx);
+		y = duk__json_dec_get(js_ctx);
 		if (x != y) {
 			/* Catches EOF of JSON input. */
 			goto syntax_error;
@@ -34532,18 +36759,18 @@
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 
-DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
+DUK_LOCAL duk_small_int_t duk__json_dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
 	duk_uint_fast32_t cp;
 
 	/* EOF (-1) will be cast to an unsigned value first
 	 * and then re-cast for the switch.  In any case, it
 	 * will match the default case (syntax error).
 	 */
-	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
+	cp = (duk_uint_fast32_t) duk__json_dec_get(js_ctx);
 	switch (cp) {
 	case DUK_ASC_BACKSLASH: break;
 	case DUK_ASC_DOUBLEQUOTE: break;
@@ -34554,13 +36781,13 @@
 	case DUK_ASC_LC_F: cp = 0x0c; break;
 	case DUK_ASC_LC_B: cp = 0x08; break;
 	case DUK_ASC_LC_U: {
-		cp = duk__dec_decode_hex_escape(js_ctx, 4);
+		cp = duk__json_dec_decode_hex_escape(js_ctx, 4);
 		break;
 	}
 #if defined(DUK_USE_JX)
 	case DUK_ASC_UC_U: {
 		if (js_ctx->flag_ext_custom) {
-			cp = duk__dec_decode_hex_escape(js_ctx, 8);
+			cp = duk__json_dec_decode_hex_escape(js_ctx, 8);
 		} else {
 			return 1;  /* syntax error */
 		}
@@ -34568,7 +36795,7 @@
 	}
 	case DUK_ASC_LC_X: {
 		if (js_ctx->flag_ext_custom) {
-			cp = duk__dec_decode_hex_escape(js_ctx, 2);
+			cp = duk__json_dec_decode_hex_escape(js_ctx, 2);
 		} else {
 			return 1;  /* syntax error */
 		}
@@ -34580,12 +36807,12 @@
 		return 1;  /* syntax error */
 	}
 
-	DUK_RAW_WRITE_XUTF8(*ext_p, cp);
+	DUK_RAW_WRITEINC_XUTF8(*ext_p, cp);
 
 	return 0;
 }
 
-DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_string(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_bufwriter_ctx bw_alloc;
 	duk_bufwriter_ctx *bw;
@@ -34644,7 +36871,7 @@
 				 * quite slow but it's uncommon).
 				 */
 				js_ctx->p = p;
-				if (duk__dec_string_escape(js_ctx, &q) != 0) {
+				if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
 					goto syntax_error;
 				}
 				break;
@@ -34661,12 +36888,12 @@
 
 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
 
-		x = duk__dec_get(js_ctx);
+		x = duk__json_dec_get(js_ctx);
 
 		if (x == DUK_ASC_DOUBLEQUOTE) {
 			break;
 		} else if (x == DUK_ASC_BACKSLASH) {
-			if (duk__dec_string_escape(js_ctx, &q) != 0) {
+			if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
 				goto syntax_error;
 			}
 		} else if (x < 0x20) {
@@ -34686,7 +36913,7 @@
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 
@@ -34694,7 +36921,7 @@
 /* Decode a plain string consisting entirely of identifier characters.
  * Used to parse plain keys (e.g. "foo: 123").
  */
-DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	const duk_uint8_t *p;
 	duk_small_int_t x;
@@ -34736,7 +36963,7 @@
 #endif  /* DUK_USE_JX */
 
 #if defined(DUK_USE_JX)
-DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	const duk_uint8_t *p;
 	duk_small_int_t x;
@@ -34783,13 +37010,13 @@
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 #endif  /* DUK_USE_JX */
 
 #if defined(DUK_USE_JX)
-DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	const duk_uint8_t *p;
 	duk_uint8_t *buf;
@@ -34841,13 +37068,13 @@
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 #endif  /* DUK_USE_JX */
 
 /* Parse a number, other than NaN or +/- Infinity */
-DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_number(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	const duk_uint8_t *p_start;
 	const duk_uint8_t *p;
@@ -34903,7 +37130,7 @@
 	                     (duk_tval *) duk_get_tval(thr, -1)));
 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
 	if (duk_is_nan(thr, -1)) {
-		duk__dec_syntax_error(js_ctx);
+		duk__json_dec_syntax_error(js_ctx);
 	}
 	DUK_ASSERT(duk_is_number(thr, -1));
 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
@@ -34912,22 +37139,24 @@
 	/* [ ... num ] */
 }
 
-DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
 
 	/* c recursion check */
 
+	duk_native_stack_check(thr);
+
 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
-		DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);
+		DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
 		DUK_WO_NORETURN(return;);
 	}
 	js_ctx->recursion_depth++;
 }
 
-DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
 	/* c recursion check */
 
 	DUK_ASSERT(js_ctx->recursion_depth > 0);
@@ -34935,14 +37164,14 @@
 	js_ctx->recursion_depth--;
 }
 
-DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_object(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
 	duk_uint8_t x;
 
 	DUK_DDD(DUK_DDDPRINT("parse_object"));
 
-	duk__dec_objarr_entry(js_ctx);
+	duk__json_dec_objarr_entry(js_ctx);
 
 	duk_push_object(thr);
 
@@ -34950,7 +37179,7 @@
 
 	key_count = 0;
 	for (;;) {
-		x = duk__dec_get_nonwhite(js_ctx);
+		x = duk__json_dec_get_nonwhite(js_ctx);
 
 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
 		                     (duk_tval *) duk_get_tval(thr, -1),
@@ -34960,7 +37189,7 @@
 
 		if (x == DUK_ASC_COMMA && key_count > 0) {
 			/* accept comma, expect new value */
-			x = duk__dec_get_nonwhite(js_ctx);
+			x = duk__json_dec_get_nonwhite(js_ctx);
 		} else if (x == DUK_ASC_RCURLY) {
 			/* eat closing brace */
 			break;
@@ -34977,11 +37206,11 @@
 		/* parse key and value */
 
 		if (x == DUK_ASC_DOUBLEQUOTE) {
-			duk__dec_string(js_ctx);
+			duk__json_dec_string(js_ctx);
 #if defined(DUK_USE_JX)
 		} else if (js_ctx->flag_ext_custom &&
 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
-			duk__dec_plain_string(js_ctx);
+			duk__json_dec_plain_string(js_ctx);
 #endif
 		} else {
 			goto syntax_error;
@@ -34989,12 +37218,12 @@
 
 		/* [ ... obj key ] */
 
-		x = duk__dec_get_nonwhite(js_ctx);
+		x = duk__json_dec_get_nonwhite(js_ctx);
 		if (x != DUK_ASC_COLON) {
 			goto syntax_error;
 		}
 
-		duk__dec_value(js_ctx);
+		duk__json_dec_value(js_ctx);
 
 		/* [ ... obj key val ] */
 
@@ -35010,22 +37239,22 @@
 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
 	                     (duk_tval *) duk_get_tval(thr, -1)));
 
-	duk__dec_objarr_exit(js_ctx);
+	duk__json_dec_objarr_exit(js_ctx);
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 
-DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_array(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_uarridx_t arr_idx;
 	duk_uint8_t x;
 
 	DUK_DDD(DUK_DDDPRINT("parse_array"));
 
-	duk__dec_objarr_entry(js_ctx);
+	duk__json_dec_objarr_entry(js_ctx);
 
 	duk_push_array(thr);
 
@@ -35033,7 +37262,7 @@
 
 	arr_idx = 0;
 	for (;;) {
-		x = duk__dec_get_nonwhite(js_ctx);
+		x = duk__json_dec_get_nonwhite(js_ctx);
 
 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
 		                     (duk_tval *) duk_get_tval(thr, -1),
@@ -35049,7 +37278,7 @@
 			break;
 		} else if (arr_idx == 0) {
 			/* accept anything, expect first value (EOF will be
-			 * caught by duk__dec_value() below.
+			 * caught by duk__json_dec_value() below.
 			 */
 			js_ctx->p--;  /* backtrack (safe) */
 		} else {
@@ -35059,7 +37288,7 @@
 
 		/* parse value */
 
-		duk__dec_value(js_ctx);
+		duk__json_dec_value(js_ctx);
 
 		/* [ ... arr val ] */
 
@@ -35078,30 +37307,30 @@
 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
 	                     (duk_tval *) duk_get_tval(thr, -1)));
 
-	duk__dec_objarr_exit(js_ctx);
+	duk__json_dec_objarr_exit(js_ctx);
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 
-DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
+DUK_LOCAL void duk__json_dec_value(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_uint8_t x;
 
-	x = duk__dec_get_nonwhite(js_ctx);
+	x = duk__json_dec_get_nonwhite(js_ctx);
 
 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
 
-	/* Note: duk__dec_req_stridx() backtracks one char */
+	/* Note: duk__json_dec_req_stridx() backtracks one char */
 
 	if (x == DUK_ASC_DOUBLEQUOTE) {
-		duk__dec_string(js_ctx);
+		duk__json_dec_string(js_ctx);
 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
 #if defined(DUK_USE_JX)
-		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
-			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
+		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__json_dec_peek(js_ctx) == DUK_ASC_UC_I) {
+			duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
 			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
 		} else {
 #else
@@ -35109,60 +37338,63 @@
 #endif
 			/* We already ate 'x', so backup one byte. */
 			js_ctx->p--;  /* safe */
-			duk__dec_number(js_ctx);
+			duk__json_dec_number(js_ctx);
 		}
 	} else if (x == DUK_ASC_LC_T) {
-		duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
+		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
 		duk_push_true(thr);
 	} else if (x == DUK_ASC_LC_F) {
-		duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
+		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
 		duk_push_false(thr);
 	} else if (x == DUK_ASC_LC_N) {
-		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
+		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
 		duk_push_null(thr);
 #if defined(DUK_USE_JX)
 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
-		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
+		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
 		duk_push_undefined(thr);
 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
-		duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
+		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
 		duk_push_nan(thr);
 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
-		duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
+		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
-		duk__dec_pointer(js_ctx);
+		duk__json_dec_pointer(js_ctx);
 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
-		duk__dec_buffer(js_ctx);
+		duk__json_dec_buffer(js_ctx);
 #endif
 	} else if (x == DUK_ASC_LCURLY) {
-		duk__dec_object(js_ctx);
+		duk__json_dec_object(js_ctx);
 	} else if (x == DUK_ASC_LBRACKET) {
-		duk__dec_array(js_ctx);
+		duk__json_dec_array(js_ctx);
 	} else {
 		/* catches EOF (NUL) */
 		goto syntax_error;
 	}
 
-	duk__dec_eat_white(js_ctx);
+	duk__json_dec_eat_white(js_ctx);
 
 	/* [ ... val ] */
 	return;
 
  syntax_error:
-	duk__dec_syntax_error(js_ctx);
+	duk__json_dec_syntax_error(js_ctx);
 	DUK_UNREACHABLE();
 }
 
-/* Recursive value reviver, implements the Walk() algorithm.  No C recursion
- * check is done here because the initial parsing step will already ensure
- * there is a reasonable limit on C recursion depth and hence object depth.
- */
-DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
+/* Recursive value reviver, implements the Walk() algorithm.  The parsing
+ * step ensures there is a reasonable depth limit to the input.  However,
+ * the reviver may create more depth by editing object or array entries, so
+ * we have both C recursion limit and native stack checks here.
+ */
+DUK_LOCAL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_hobject *h;
 	duk_uarridx_t i, arr_len;
 
+	duk__json_dec_objarr_entry(js_ctx);
+
 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
 	                     (long) duk_get_top(thr),
 	                     (duk_tval *) duk_get_tval(thr, -2),
@@ -35173,7 +37405,7 @@
 
 	h = duk_get_hobject(thr, -1);
 	if (h != NULL) {
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
+		if (duk_js_isarray_hobject(h)) {
 			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
 			for (i = 0; i < arr_len; i++) {
 				/* [ ... holder name val ] */
@@ -35185,7 +37417,7 @@
 
 				duk_dup_top(thr);
 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
-				duk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
+				duk__json_dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
 
 				if (duk_is_undefined(thr, -1)) {
 					duk_pop(thr);
@@ -35212,7 +37444,7 @@
 				duk_dup_m2(thr);
 
 				/* [ ... holder name val enum obj_key val obj_key ] */
-				duk__dec_reviver_walk(js_ctx);
+				duk__json_dec_reviver_walk(js_ctx);
 
 				/* [ ... holder name val enum obj_key new_elem ] */
 				if (duk_is_undefined(thr, -1)) {
@@ -35241,6 +37473,8 @@
 	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
 	duk_call_method(thr, 2);  /* -> [ ... res ] */
 
+	duk__json_dec_objarr_exit(js_ctx);
+
 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
 }
@@ -35350,7 +37584,7 @@
 	return q;
 }
 
-DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
+DUK_LOCAL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
 	duk_size_t k_len;
 	duk_codepoint_t cp;
@@ -35393,7 +37627,7 @@
 	}
 
  quote_normally:
-	duk__enc_quote_string(js_ctx, k);
+	duk__json_enc_quote_string(js_ctx, k);
 }
 
 /* The Quote(value) operation: quote a string.
@@ -35401,13 +37635,13 @@
  * Stack policy: [ ] -> [ ].
  */
 
-DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
+DUK_LOCAL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
 	duk_hthread *thr = js_ctx->thr;
 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
 	duk_uint8_t *q;
 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
 
-	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
+	DUK_DDD(DUK_DDDPRINT("duk__json_enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
 
 	DUK_ASSERT(h_str != NULL);
 	p_start = DUK_HSTRING_GET_DATA(h_str);
@@ -35524,7 +37758,7 @@
 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
 				} else {
 					/* as is */
-					DUK_RAW_WRITE_XUTF8(q, cp);
+					DUK_RAW_WRITEINC_XUTF8(q, cp);
 				}
 			}
 		}
@@ -35538,7 +37772,7 @@
 /* Encode a double (checked by caller) from stack top.  Stack top may be
  * replaced by serialized string but is not popped (caller does that).
  */
-DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__json_enc_double(duk_json_enc_ctx *js_ctx) {
 	duk_hthread *thr;
 	duk_tval *tv;
 	duk_double_t d;
@@ -35602,7 +37836,7 @@
 
 #if defined(DUK_USE_FASTINT)
 /* Encode a fastint from duk_tval ptr, no value stack effects. */
-DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
+DUK_LOCAL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
 	duk_int64_t v;
 
 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
@@ -35627,7 +37861,7 @@
 
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 #if defined(DUK_USE_HEX_FASTPATH)
-DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
+DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
 	duk_uint8_t *q;
 	duk_uint16_t *q16;
 	duk_small_uint_t x;
@@ -35685,7 +37919,7 @@
 	return q;
 }
 #else  /* DUK_USE_HEX_FASTPATH */
-DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
+DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
 	const duk_uint8_t *p;
 	const duk_uint8_t *p_end;
 	duk_uint8_t *q;
@@ -35704,7 +37938,7 @@
 }
 #endif  /* DUK_USE_HEX_FASTPATH */
 
-DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
+DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
 	duk_hthread *thr;
 	duk_uint8_t *q;
 	duk_size_t space;
@@ -35736,7 +37970,7 @@
 #if defined(DUK_USE_JX)
 	{
 		*q++ = DUK_ASC_PIPE;
-		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+		q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
 		*q++ = DUK_ASC_PIPE;
 
 	}
@@ -35749,7 +37983,7 @@
 		DUK_ASSERT(js_ctx->flag_ext_compatible);
 		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
 		q += 9;
-		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+		q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
 		*q++ = DUK_ASC_DOUBLEQUOTE;
 		*q++ = DUK_ASC_RCURLY;
 	}
@@ -35758,15 +37992,15 @@
 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
 }
 
-DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
-	duk__enc_buffer_data(js_ctx,
+DUK_LOCAL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
+	duk__json_enc_buffer_data(js_ctx,
 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
 }
 #endif  /* DUK_USE_JX || DUK_USE_JC */
 
 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
-DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
+DUK_LOCAL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
 	duk_size_t i, n;
 	const duk_uint8_t *buf;
 	duk_uint8_t *q;
@@ -35790,7 +38024,7 @@
 	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
 		for (i = 0; i < n; i++) {
-			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
+			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
 			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
 			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
 			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
@@ -35806,14 +38040,14 @@
 	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
 
 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
-		duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+		duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
 	}
 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
 }
 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
 
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
+DUK_LOCAL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
 	char buf[64];  /* XXX: how to figure correct size? */
 	const char *fmt;
 
@@ -35851,14 +38085,14 @@
 
 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
-DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
-	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
+DUK_LOCAL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
+	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
 
 	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
 	} else {
 		/* Handle both full and partial slice (as long as covered). */
-		duk__enc_buffer_data(js_ctx,
+		duk__json_enc_buffer_data(js_ctx,
 		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
 		                     (duk_size_t) h_bufobj->length);
 	}
@@ -35870,7 +38104,7 @@
  * directly related to indent depth.
  */
 #if defined(DUK_USE_PREFER_SIZE)
-DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
+DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
 	DUK_ASSERT(js_ctx->h_gap != NULL);
 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
 
@@ -35880,7 +38114,7 @@
 	}
 }
 #else  /* DUK_USE_PREFER_SIZE */
-DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
+DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
 	const duk_uint8_t *gap_data;
 	duk_size_t gap_len;
 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
@@ -35933,13 +38167,14 @@
 #endif  /* DUK_USE_PREFER_SIZE */
 
 /* Shared entry handling for object/array serialization. */
-DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
+DUK_LOCAL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_hobject *h_target;
 	duk_uint_fast32_t i, n;
 
 	*entry_top = duk_get_top(thr);
 
+	duk_native_stack_check(thr);
 	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
 
 	/* Loop check using a hybrid approach: a fixed-size visited[] array
@@ -35977,7 +38212,7 @@
 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
-		DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);
+		DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
 		DUK_WO_NORETURN(return;);
 	}
 	js_ctx->recursion_depth++;
@@ -35987,7 +38222,7 @@
 }
 
 /* Shared exit handling for object/array serialization. */
-DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
+DUK_LOCAL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_hobject *h_target;
 
@@ -36019,7 +38254,7 @@
  *
  * Stack policy: [ object ] -> [ object ].
  */
-DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__json_enc_object(duk_json_enc_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_hstring *h_key;
 	duk_idx_t entry_top;
@@ -36029,9 +38264,9 @@
 	duk_uarridx_t arr_len, i;
 	duk_size_t prev_size;
 
-	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
-
-	duk__enc_objarr_entry(js_ctx, &entry_top);
+	DUK_DDD(DUK_DDDPRINT("duk__json_enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
+
+	duk__json_enc_objarr_entry(js_ctx, &entry_top);
 
 	idx_obj = entry_top - 1;
 
@@ -36073,17 +38308,17 @@
 
 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
-			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
-			duk__enc_key_autoquote(js_ctx, h_key);
+			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+			duk__json_enc_key_autoquote(js_ctx, h_key);
 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
 		} else {
-			duk__enc_key_autoquote(js_ctx, h_key);
+			duk__json_enc_key_autoquote(js_ctx, h_key);
 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
 		}
 
 		/* [ ... key ] */
 
-		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
+		if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_obj) == 0)) {
 			/* Value would yield 'undefined', so skip key altogether.
 			 * Side effects have already happened.
 			 */
@@ -36101,12 +38336,12 @@
 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
-			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
 		}
 	}
 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
 
-	duk__enc_objarr_exit(js_ctx, &entry_top);
+	duk__json_enc_objarr_exit(js_ctx, &entry_top);
 
 	DUK_ASSERT_TOP(thr, entry_top);
 }
@@ -36115,17 +38350,17 @@
  *
  * Stack policy: [ array ] -> [ array ].
  */
-DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
+DUK_LOCAL void duk__json_enc_array(duk_json_enc_ctx *js_ctx) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_idx_t entry_top;
 	duk_idx_t idx_arr;
 	duk_bool_t emitted;
 	duk_uarridx_t i, arr_len;
 
-	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
+	DUK_DDD(DUK_DDDPRINT("duk__json_enc_array: array=%!T",
 	                     (duk_tval *) duk_get_tval(thr, -1)));
 
-	duk__enc_objarr_entry(js_ctx, &entry_top);
+	duk__json_enc_objarr_entry(js_ctx, &entry_top);
 
 	idx_arr = entry_top - 1;
 
@@ -36142,14 +38377,14 @@
 
 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
-			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
 		}
 
 		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */
 
 		/* [ ... key ] */
 
-		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
+		if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_arr) == 0)) {
 			/* Value would normally be omitted, replace with 'null'. */
 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
 		} else {
@@ -36167,12 +38402,12 @@
 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
-			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
 		}
 	}
 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
 
-	duk__enc_objarr_exit(js_ctx, &entry_top);
+	duk__json_enc_objarr_exit(js_ctx, &entry_top);
 
 	DUK_ASSERT_TOP(thr, entry_top);
 }
@@ -36181,14 +38416,14 @@
  *
  * Stack policy: [ ... key ] -> [ ... ]
  */
-DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
+DUK_LOCAL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
 	duk_hthread *thr = js_ctx->thr;
 	duk_tval *tv;
 	duk_tval *tv_holder;
 	duk_tval *tv_key;
 	duk_small_int_t c;
 
-	DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
+	DUK_DDD(DUK_DDDPRINT("duk__json_enc_value: idx_holder=%ld, holder=%!T, key=%!T",
 	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
 	                     (duk_tval *) duk_get_tval(thr, -1)));
 
@@ -36257,8 +38492,8 @@
 			/* With JX/JC a bufferobject gets serialized specially. */
 			duk_hbufobj *h_bufobj;
 			h_bufobj = (duk_hbufobj *) h;
-			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
-			duk__enc_bufobj(js_ctx, h_bufobj);
+			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
+			duk__json_enc_bufobj(js_ctx, h_bufobj);
 			goto pop2_emitted;
 		}
 		/* Otherwise bufferobjects get serialized as normal objects. */
@@ -36288,7 +38523,7 @@
 #endif
 		case DUK_HOBJECT_CLASS_BOOLEAN: {
 			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
-			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
 			duk_remove_m2(thr);
 			break;
 		}
@@ -36354,7 +38589,7 @@
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
 	case DUK_TAG_POINTER: {
-		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
+		duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
 		break;
 	}
 #endif  /* DUK_USE_JX || DUK_USE_JC */
@@ -36364,7 +38599,7 @@
 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
 			goto pop2_undef;
 		}
-		duk__enc_quote_string(js_ctx, h);
+		duk__json_enc_quote_string(js_ctx, h);
 		break;
 	}
 	case DUK_TAG_OBJECT: {
@@ -36376,10 +38611,10 @@
 		 */
 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
 
-		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
-			duk__enc_array(js_ctx);
-		} else {
-			duk__enc_object(js_ctx);
+		if (duk_js_isarray_hobject(h)) {
+			duk__json_enc_array(js_ctx);
+		} else {
+			duk__json_enc_object(js_ctx);
 		}
 		break;
 	}
@@ -36392,7 +38627,7 @@
 	case DUK_TAG_BUFFER: {
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 		if (js_ctx->flag_ext_custom_or_compatible) {
-			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+			duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
 			break;
 		}
 #endif
@@ -36401,7 +38636,7 @@
 		 * to handle realloc side effects correctly.
 		 */
 		duk_to_object(thr, -1);
-		duk__enc_object(js_ctx);
+		duk__json_enc_object(js_ctx);
 		break;
 	}
 	case DUK_TAG_LIGHTFUNC: {
@@ -36420,7 +38655,7 @@
 		/* Number serialization has a significant impact relative to
 		 * other fast path code, so careful fast path for fastints.
 		 */
-		duk__enc_fastint_tval(js_ctx, tv);
+		duk__json_enc_fastint_tval(js_ctx, tv);
 		break;
 #endif
 	default: {
@@ -36430,7 +38665,7 @@
 		/* XXX: A fast path for usual integers would be useful when
 		 * fastint support is not enabled.
 		 */
-		duk__enc_double(js_ctx);
+		duk__json_enc_double(js_ctx);
 		break;
 	}
 	}
@@ -36447,7 +38682,7 @@
 }
 
 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
-DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
+DUK_LOCAL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv) {
 	duk_small_int_t c;
 
 	/* XXX: some kind of external internal type checker?
@@ -36530,7 +38765,7 @@
 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
 			goto emit_undefined;
 		}
-		duk__enc_quote_string(js_ctx, h);
+		duk__json_enc_quote_string(js_ctx, h);
 		break;
 	}
 	case DUK_TAG_OBJECT: {
@@ -36565,7 +38800,7 @@
 
 		obj = DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(obj != NULL);
-		DUK_ASSERT_HOBJECT_VALID(obj);
+		DUK_HOBJECT_ASSERT_VALID(obj);
 
 		/* Once recursion depth is increased, exit path must decrease
 		 * it (though it's OK to abort the fast path).
@@ -36575,7 +38810,7 @@
 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
-			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
+			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_DEC_RECLIMIT);
 			DUK_WO_NORETURN(return 0;);
 		}
 
@@ -36702,11 +38937,11 @@
 
 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
-					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
-					duk__enc_key_autoquote(js_ctx, k);
+					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+					duk__json_enc_key_autoquote(js_ctx, k);
 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
 				} else {
-					duk__enc_key_autoquote(js_ctx, k);
+					duk__json_enc_key_autoquote(js_ctx, k);
 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
 				}
 
@@ -36729,7 +38964,7 @@
 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
-					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
 				}
 			}
 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
@@ -36757,7 +38992,7 @@
 				duk_bool_t has_inherited;
 
 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
-					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
 				}
 
 				if (DUK_LIKELY(i < asize)) {
@@ -36806,7 +39041,7 @@
 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
-					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
+					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
 				}
 			}
 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
@@ -36848,7 +39083,7 @@
 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
 		} else if (c_bit & c_bufobj) {
-			duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
+			duk__json_enc_bufobj(js_ctx, (duk_hbufobj *) obj);
 #endif
 #endif
 		} else if (c_bit & c_abort) {
@@ -36888,7 +39123,7 @@
 
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 		if (js_ctx->flag_ext_custom_or_compatible) {
-			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+			duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
 			break;
 		}
 #endif
@@ -36896,13 +39131,13 @@
 		/* Plain buffers mimic Uint8Arrays, and have enumerable index
 		 * properties.
 		 */
-		duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+		duk__json_enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
 		break;
 	}
 	case DUK_TAG_POINTER: {
 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 		if (js_ctx->flag_ext_custom_or_compatible) {
-			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
+			duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
 			break;
 		} else {
 			goto emit_undefined;
@@ -36924,7 +39159,7 @@
 		/* Number serialization has a significant impact relative to
 		 * other fast path code, so careful fast path for fastints.
 		 */
-		duk__enc_fastint_tval(js_ctx, tv);
+		duk__json_enc_fastint_tval(js_ctx, tv);
 		break;
 	}
 #endif
@@ -36937,7 +39172,7 @@
 
 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
 		duk_push_tval(js_ctx->thr, tv);
-		duk__enc_double(js_ctx);
+		duk__json_enc_double(js_ctx);
 		duk_pop(js_ctx->thr);
 
 #if 0
@@ -37049,14 +39284,15 @@
 	                DUK_HSTRING_GET_BYTELEN(h_text);
 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
 
-	duk__dec_value(js_ctx);  /* -> [ ... value ] */
-
-	/* Trailing whitespace has been eaten by duk__dec_value(), so if
+	duk__json_dec_value(js_ctx);  /* -> [ ... value ] */
+	DUK_ASSERT(js_ctx->recursion_depth == 0);
+
+	/* Trailing whitespace has been eaten by duk__json_dec_value(), so if
 	 * we're not at end of input here, it's a SyntaxError.
 	 */
 
 	if (js_ctx->p != js_ctx->p_end) {
-		duk__dec_syntax_error(js_ctx);
+		duk__json_dec_syntax_error(js_ctx);
 	}
 
 	if (duk_is_callable(thr, idx_reviver)) {
@@ -37074,7 +39310,9 @@
 		                     (duk_tval *) duk_get_tval(thr, -2),
 		                     (duk_tval *) duk_get_tval(thr, -1)));
 
-		duk__dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
+		DUK_ASSERT(js_ctx->recursion_depth == 0);
+		duk__json_dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
+		DUK_ASSERT(js_ctx->recursion_depth == 0);
 		duk_remove_m2(thr);             /* -> [ ... val' ] */
 	} else {
 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
@@ -37212,7 +39450,7 @@
 	if (h != NULL) {
 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
 			js_ctx->h_replacer = h;
-		} else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
+		} else if (duk_js_isarray_hobject(h)) {
 			/* Here the specification requires correct array index enumeration
 			 * which is a bit tricky for sparse arrays (it is handled by the
 			 * enum setup code).  We now enumerate ancestors too, although the
@@ -37222,14 +39460,14 @@
 			duk_uarridx_t plist_idx = 0;
 			duk_small_uint_t enum_flags;
 
-			js_ctx->idx_proplist = duk_push_array(thr);  /* XXX: array internal? */
+			js_ctx->idx_proplist = duk_push_bare_array(thr);
 
 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
 			duk_enum(thr, idx_replacer, enum_flags);
 			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
 				/* [ ... proplist enum_obj key val ] */
-				if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {
+				if (duk__json_enc_allow_into_proplist(duk_get_tval(thr, -1))) {
 					/* XXX: duplicates should be eliminated here */
 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
 					                     (duk_tval *) duk_get_tval(thr, -2),
@@ -37389,7 +39627,7 @@
 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
 	DUK_ASSERT(js_ctx->recursion_depth == 0);
 
-	if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
+	if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
 		/* Result is undefined. */
 		duk_push_undefined(thr);
 	} else {
@@ -37524,7 +39762,7 @@
 	/* fmin() with args -0 and +0 is not guaranteed to return
 	 * -0 as ECMAScript requires.
 	 */
-	if (x == 0 && y == 0) {
+	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
 		duk_double_union du1, du2;
 		du1.d = x;
 		du2.d = y;
@@ -37551,7 +39789,7 @@
 	/* fmax() with args -0 and +0 is not guaranteed to return
 	 * +0 as ECMAScript requires.
 	 */
-	if (x == 0 && y == 0) {
+	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
 			return +0.0;
 		} else {
@@ -37718,10 +39956,11 @@
 	}
 #else
 	/* Some ISO C assumptions. */
-	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);
-	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);
-	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);
-	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);
+
+	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), 0.7853981633974483));
+	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), -0.7853981633974483));
+	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), 2.356194490192345));
+	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), -2.356194490192345));
 #endif
 
 	return DUK_ATAN2(x, y);
@@ -37861,13 +40100,13 @@
 	}
 
 	/* Early return cases. */
-	if (max == DUK_DOUBLE_INFINITY) {
+	if (duk_double_equals(max, DUK_DOUBLE_INFINITY)) {
 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
 		return 1;
 	} else if (found_nan) {
 		duk_push_number(thr, DUK_DOUBLE_NAN);
 		return 1;
-	} else if (max == 0.0) {
+	} else if (duk_double_equals(max, 0.0)) {
 		duk_push_number(thr, 0.0);
 		/* Otherwise we'd divide by zero. */
 		return 1;
@@ -37902,7 +40141,7 @@
 		DUK_ASSERT(duk_is_nan(thr, -1));
 		return 1;  /* NaN input -> return NaN */
 	}
-	if (d == 0.0) {
+	if (duk_double_equals(d, 0.0)) {
 		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
 		return 1;
 	}
@@ -38015,7 +40254,7 @@
 		DUK_ERROR_TYPE(thr, "number expected");
 		DUK_WO_NORETURN(return 0.0;);
 	}
-	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
 	DUK_ASSERT(duk_is_number(thr, -1));
 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
@@ -39135,7 +41374,7 @@
 		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
 		                              DUK_BIDX_POINTER_PROTOTYPE);
 
-		/* Pointer object internal value is immutable */
+		/* Pointer object internal value is immutable. */
 		duk_dup_0(thr);
 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
 	}
@@ -39167,7 +41406,7 @@
 			goto type_error;
 		}
 
-		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
 	} else {
 		goto type_error;
 	}
@@ -39241,7 +41480,7 @@
 	duk_uarridx_t i, len, idx;
 	duk_propdesc desc;
 
-	DUK_ASSERT_CTX_VALID(thr);
+	DUK_CTX_ASSERT_VALID(thr);
 	DUK_ASSERT(h_proxy_target != NULL);
 
 	len = (duk_uarridx_t) duk_get_length(thr, -1);
@@ -39291,7 +41530,9 @@
 		}
 
 		/* [ obj trap_result res_arr propname ] */
-		duk_put_prop_index(thr, -2, idx++);
+		duk_push_uarridx(thr, idx++);
+		duk_insert(thr, -2);
+		duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
 		continue;
 
 	 skip_key:
@@ -39594,8 +41835,8 @@
 	magic = duk_get_current_magic(thr);
 
 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
-		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
-		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
+		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
+		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
 		h_bc = duk_require_hstring(thr, -1);
 		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
 		duk_pop(thr);
@@ -39898,7 +42139,7 @@
 			goto type_error;
 		}
 
-		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
+		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
 		DUK_ASSERT(duk_is_string(thr, -1));
 	} else {
 		goto type_error;
@@ -40316,6 +42557,7 @@
 #endif  /* DUK_USE_REGEXP_SUPPORT */
 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
 			const duk_uint8_t *q_start;               /* match string */
+			duk_size_t p_blen;
 			duk_size_t q_blen;
 
 #if defined(DUK_USE_REGEXP_SUPPORT)
@@ -40324,13 +42566,19 @@
 
 			p_start = DUK_HSTRING_GET_DATA(h_input);
 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+			p_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_input);
 			p = p_start;
 
 			h_search = duk_known_hstring(thr, 0);
 			q_start = DUK_HSTRING_GET_DATA(h_search);
 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
 
+			if (q_blen > p_blen) {
+				break;  /* no match */
+			}
+
 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
+			DUK_ASSERT(p_end >= p);
 
 			match_start_coff = 0;
 
@@ -41145,44 +43393,65 @@
 #if defined(DUK_USE_ES6)
 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
 	duk_int_t magic;
-	duk_hstring *h;
+	duk_hstring *h_target;
+	duk_size_t blen_target;
 	duk_hstring *h_search;
 	duk_size_t blen_search;
-	const duk_uint8_t *p_cmp_start;
-	duk_bool_t result;
-
-	h = duk_push_this_coercible_to_string(thr);
-	DUK_ASSERT(h != NULL);
+	duk_int_t off;
+	duk_bool_t result = 0;
+	duk_size_t blen_left;
+
+	/* Because string byte lengths are in [0,DUK_INT_MAX] it's safe to
+	 * subtract two string lengths without overflow.
+	 */
+	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
+
+	h_target = duk_push_this_coercible_to_string(thr);
+	DUK_ASSERT(h_target != NULL);
 
 	h_search = duk__str_tostring_notregexp(thr, 0);
 	DUK_ASSERT(h_search != NULL);
 
 	magic = duk_get_current_magic(thr);
 
-	p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
+	/* Careful to avoid pointer overflows in the matching logic. */
+
+	blen_target = DUK_HSTRING_GET_BYTELEN(h_target);
 	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
 
+#if 0
+	/* If search string is longer than the target string, we can
+	 * never match.  Could check explicitly, but should be handled
+	 * correctly below.
+	 */
+	if (blen_search > blen_target) {
+		goto finish;
+	}
+#endif
+
+	off = 0;
 	if (duk_is_undefined(thr, 1)) {
 		if (magic) {
-			p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search;
-		} else {
-			/* p_cmp_start already OK */
+			off = (duk_int_t) blen_target - (duk_int_t) blen_search;
+		} else {
+			DUK_ASSERT(off == 0);
 		}
 	} else {
 		duk_int_t len;
 		duk_int_t pos;
 
 		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
-		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
+		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_target);
 		pos = duk_to_int_clamped(thr, 1, 0, len);
 		DUK_ASSERT(pos >= 0 && pos <= len);
 
+		off = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_target, (duk_uint_fast32_t) pos);
 		if (magic) {
-			p_cmp_start -= blen_search;  /* Conceptually subtracted last, but do already here. */
-		}
-		DUK_ASSERT(pos >= 0 && pos <= len);
-
-		p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);
+			off -= (duk_int_t) blen_search;
+		}
+	}
+	if (off < 0 || off > (duk_int_t) blen_target) {
+		goto finish;
 	}
 
 	/* The main comparison can be done using a memcmp() rather than
@@ -41192,16 +43461,18 @@
 	 * comparison range.
 	 */
 
-	result = 0;
-	if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&
-	    (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {
-		if (duk_memcmp((const void *) p_cmp_start,
-		               (const void *) DUK_HSTRING_GET_DATA(h_search),
-		               (size_t) blen_search) == 0) {
+	DUK_ASSERT(off >= 0);
+	DUK_ASSERT((duk_size_t) off <= blen_target);
+	blen_left = blen_target - (duk_size_t) off;
+	if (blen_left >= blen_search) {
+		const duk_uint8_t *p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_target) + off;
+		const duk_uint8_t *p_search = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_search);
+		if (duk_memcmp_unsafe((const void *) p_cmp_start, (const void *) p_search, (size_t) blen_search) == 0) {
 			result = 1;
 		}
 	}
 
+ finish:
 	duk_push_boolean(thr, result);
 	return 1;
 }
@@ -41306,7 +43577,6 @@
 
 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
 	duk_tval *tv;
-	duk_tval tv_val;
 	duk_hobject *h_obj;
 	duk_hstring *h_str;
 
@@ -41320,10 +43590,10 @@
 		h_obj = DUK_TVAL_GET_OBJECT(tv);
 		DUK_ASSERT(h_obj != NULL);
 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
-			if (!duk_hobject_get_internal_value(thr->heap, h_obj, &tv_val)) {
+			tv = duk_hobject_get_internal_value_tval_ptr(thr->heap, h_obj);
+			if (tv == NULL) {
 				return NULL;
 			}
-			tv = &tv_val;
 		} else {
 			return NULL;
 		}
@@ -41540,6 +43810,18 @@
 		duk_pop(thr);
 	}
 
+#if 0
+	/* This check would prevent a heap destruction time finalizer from
+	 * launching a coroutine, which would ensure that during finalization
+	 * 'thr' would always equal heap_thread.  Normal runtime finalizers
+	 * run with ms_running == 0, i.e. outside mark-and-sweep.  See GH-2030.
+	 */
+	if (thr->heap->ms_running) {
+		DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
+		goto state_error;
+	}
+#endif
+
 	/*
 	 *  The error object has been augmented with a traceback and other
 	 *  info from its creation point -- usually another thread.  The
@@ -41811,7 +44093,9 @@
  *     %!T    tagged value (duk_tval *)
  *     %!O    heap object (duk_heaphdr *)
  *     %!I    decoded bytecode instruction
- *     %!C    bytecode instruction opcode name (arg is long)
+ *     %!X    bytecode instruction opcode name (arg is long)
+ *     %!C    catcher (duk_catcher *)
+ *     %!A    activation (duk_activation *)
  *
  *  Everything is serialized in a JSON-like manner.  The default depth is one
  *  level, internal prototype is not followed, and internal properties are not
@@ -42615,6 +44899,47 @@
 	}
 }
 
+DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
+	duk_fixedbuffer *fb = st->fb;
+
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
+
+	if (!cat) {
+		duk_fb_put_cstring(fb, "NULL");
+		return;
+	}
+
+	duk_fb_sprintf(fb, "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
+	               (void *) cat,
+	               (void *) cat->parent, (void *) cat->h_varname, (void *) cat->pc_base,
+		       (long) cat->idx_base, (unsigned long) cat->flags);
+}
+
+
+DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
+	duk_fixedbuffer *fb = st->fb;
+
+	if (duk_fb_is_full(fb)) {
+		return;
+	}
+
+	if (!act) {
+		duk_fb_put_cstring(fb, "NULL");
+		return;
+	}
+
+	/* prev_caller: conditional, omitted on purpose, it's rarely used. */
+	/* prev_line: conditional, omitted on purpose (but would be nice). */
+	duk_fb_sprintf(fb, "[activation ptr=%p tv_func=<omit> func=%p parent=%p var_env=%p lex_env=%p cat=%p curr_pc=%p bottom_byteoff=%ld retval_byteoff=%ld reserve_byteoff=%ld flags=%ld]",
+	               (void *) act,
+	               (void *) act->func, (void *) act->parent, (void *) act->var_env,
+		       (void *) act->lex_env, (void *) act->cat, (void *) act->curr_pc,
+		       (long) act->bottom_byteoff, (long) act->retval_byteoff, (long) act->reserve_byteoff,
+		       (long) act->flags);
+}
+
 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
 	duk_fixedbuffer fb;
 	const char *p = format;
@@ -42699,10 +45024,18 @@
 				duk_instr_t t = va_arg(ap, duk_instr_t);
 				duk__print_instr(&st, t);
 				break;
-			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
+			} else if (got_exclamation && ch == DUK_ASC_UC_X) {
 				long t = va_arg(ap, long);
 				duk__print_opcode(&st, (duk_small_int_t) t);
 				break;
+			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
+				duk_catcher *t = va_arg(ap, duk_catcher *);
+				duk__print_catcher(&st, t);
+				break;
+			} else if (got_exclamation && ch == DUK_ASC_UC_A) {
+				duk_activation *t = va_arg(ap, duk_activation *);
+				duk__print_activation(&st, t);
+				break;
 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
 				duk_size_t fmtlen;
@@ -44365,18 +46698,25 @@
 	 *   - If side effects are possible, add error catching
 	 */
 
-	duk_push_tval(thr, &act->tv_func);
-	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VARMAP);
-	if (duk_is_object(thr, -1)) {
-		duk_enum(thr, -1, 0 /*enum_flags*/);
-		while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
-			varname = duk_known_hstring(thr, -1);
-
-			duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
-			/* [ ... func varmap enum key value this ] */
-			duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
-			duk_debug_write_tval(thr, duk_get_tval(thr, -2));
-			duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
+	if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
+		duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
+		duk_hobject *h_varmap;
+
+		h_varmap = duk_hobject_get_varmap(thr, h_func);
+		if (h_varmap != NULL) {
+			duk_push_hobject(thr, h_varmap);
+			duk_enum(thr, -1, 0 /*enum_flags*/);
+			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
+				varname = duk_known_hstring(thr, -1);
+
+				duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
+				/* [ ... func varmap enum key value this ] */
+				duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
+				duk_debug_write_tval(thr, duk_get_tval(thr, -2));
+				duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
+			}
+		} else {
+			DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
 		}
 	} else {
 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
@@ -45717,7 +48057,7 @@
 		heap->dbg_state_dirty = 1;
 		duk_debug_clear_pause_state(heap);
 		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
-		heap->ms_running = 1;  /* prevent mark-and-sweep, prevent refzero queueing */
+		heap->ms_running = 2;  /* prevent mark-and-sweep, prevent refzero queueing */
 		heap->ms_prevent_count++;
 		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
 		DUK_ASSERT(heap->heap_thread != NULL);
@@ -45729,7 +48069,7 @@
 		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
 		heap->dbg_state_dirty = 1;
 		duk_debug_clear_pause_state(heap);
-		DUK_ASSERT(heap->ms_running == 1);
+		DUK_ASSERT(heap->ms_running == 2);
 		DUK_ASSERT(heap->ms_prevent_count > 0);
 		heap->ms_prevent_count--;
 		heap->ms_running = 0;
@@ -45851,9 +48191,9 @@
 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
 		return;
 	}
-	tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
-	                                                  thr->builtins[DUK_BIDX_DUKTAPE],
-	                                                  DUK_HTHREAD_GET_STRING(thr, stridx_cb));
+	tv_hnd = duk_hobject_find_entry_tval_ptr_stridx(thr->heap,
+	                                                thr->builtins[DUK_BIDX_DUKTAPE],
+	                                                stridx_cb);
 	if (tv_hnd == NULL) {
 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
 		                   (duk_tval *) tv_hnd));
@@ -45952,9 +48292,13 @@
 		arr_size += 2;
 	}
 
-	/* XXX: uninitialized would be OK */
+	/* XXX: Uninitialized would be OK.  Maybe add internal primitive to
+	 * push bare duk_harray with size?
+	 */
 	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
+	duk_clear_prototype(thr, -1);
+	DUK_ASSERT(duk_is_bare_object(thr, -1));
 	DUK_ASSERT(arr_size == 0 || tv != NULL);
 
 	/* Compiler SyntaxErrors (and other errors) come first, and are
@@ -46031,6 +48375,7 @@
 		DUK_ASSERT(a != NULL);
 		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
 		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
+		DUK_ASSERT(duk_is_bare_object(thr, -1));
 	}
 #endif
 
@@ -46186,7 +48531,28 @@
 	                     (duk_tval *) duk_get_tval(thr, -1)));
 
 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
-		duk_push_sprintf(thr, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
+		duk_bool_t at_end;
+
+		/* Best guesstimate that error occurred at end of input, token
+		 * truncated by end of input, etc.
+		 */
+#if 0
+		at_end = (thr->compile_ctx->curr_token.start_offset + 1 >= thr->compile_ctx->lex.input_length);
+		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0 || thr->compile_ctx->lex.window[1].codepoint < 0);
+#endif
+		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0);
+
+		DUK_D(DUK_DPRINT("syntax error, determined at_end=%ld; curr_token.start_offset=%ld, "
+		                 "lex.input_length=%ld, window[0].codepoint=%ld, window[1].codepoint=%ld",
+		                 (long) at_end,
+		                 (long) thr->compile_ctx->curr_token.start_offset,
+		                 (long) thr->compile_ctx->lex.input_length,
+		                 (long) thr->compile_ctx->lex.window[0].codepoint,
+		                 (long) thr->compile_ctx->lex.window[1].codepoint));
+
+		duk_push_sprintf(thr, " (line %ld%s)",
+		                 (long) thr->compile_ctx->curr_token.start_line,
+		                 at_end ? ", end of input" : "");
 		duk_concat(thr, 2);
 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
 	} else {
@@ -46221,9 +48587,9 @@
 #if defined(DUK_USE_TRACEBACKS)
 	/* If tracebacks are enabled, the '_Tracedata' property is the only
 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
-	 * which use '_Tracedata'.
-	 */
-	if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
+	 * which use '_Tracedata'.  (Check _Tracedata only as own property.)
+	 */
+	if (duk_hobject_find_entry_tval_ptr_stridx(thr->heap, obj, DUK_STRIDX_INT_TRACEDATA) != NULL) {
 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
 	} else {
 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
@@ -46893,6 +49259,20 @@
 	DUK_UNREF(heap);
 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
 }
+#line 1 "duk_hbuffer_assert.c"
+/*
+ *  duk_hbuffer assertion helpers
+ */
+
+/* #include duk_internal.h -> already included */
+
+#if defined(DUK_USE_ASSERTIONS)
+
+DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
+	DUK_ASSERT(h != NULL);
+}
+
+#endif  /* DUK_USE_ASSERTIONS */
 #line 1 "duk_hbuffer_ops.c"
 /*
  *  duk_hbuffer operations such as resizing and inserting/appending data to
@@ -47252,15 +49632,19 @@
 	}
 
 	/* Prevent finalize_list processing and mark-and-sweep entirely.
-	 * Setting ms_running = 1 also prevents refzero handling from moving
-	 * objects away from the heap_allocated list (the flag name is a bit
-	 * misleading here).
+	 * Setting ms_running != 0 also prevents refzero handling from moving
+	 * objects away from the heap_allocated list.  The flag name is a bit
+	 * misleading here.
+	 *
+	 * Use a distinct value for ms_running here (== 2) so that assertions
+	 * can detect this situation separate from the normal runtime
+	 * mark-and-sweep case.  This allows better assertions (GH-2030).
 	 */
 	DUK_ASSERT(heap->pf_prevent_count == 0);
+	DUK_ASSERT(heap->ms_running == 0);
+	DUK_ASSERT(heap->ms_prevent_count == 0);
 	heap->pf_prevent_count = 1;
-	DUK_ASSERT(heap->ms_running == 0);
-	heap->ms_running = 1;
-	DUK_ASSERT(heap->ms_prevent_count == 0);
+	heap->ms_running = 2;  /* Use distinguishable value. */
 	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
 
 	curr_limit = 0;  /* suppress warning, not used */
@@ -47321,9 +49705,9 @@
 		}
 	}
 
-	DUK_ASSERT(heap->ms_running == 1);
+	DUK_ASSERT(heap->ms_running == 2);
+	DUK_ASSERT(heap->pf_prevent_count == 1);
 	heap->ms_running = 0;
-	DUK_ASSERT(heap->pf_prevent_count == 1);
 	heap->pf_prevent_count = 0;
 }
 #endif  /* DUK_USE_FINALIZER_SUPPORT */
@@ -48805,6 +51189,7 @@
 
 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
 	DUK_ASSERT(h);
+	DUK_HSTRING_ASSERT_VALID(h);
 
 	/* nothing to process */
 }
@@ -48815,6 +51200,7 @@
 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
 
 	DUK_ASSERT(h);
+	DUK_HOBJECT_ASSERT_VALID(h);
 
 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
 
@@ -48855,7 +51241,7 @@
 		duk_tval *tv, *tv_end;
 		duk_hobject **fn, **fn_end;
 
-		DUK_ASSERT_HCOMPFUNC_VALID(f);
+		DUK_HCOMPFUNC_ASSERT_VALID(f);
 
 		/* 'data' is reachable through every compiled function which
 		 * contains a reference.
@@ -48885,30 +51271,30 @@
 		}
 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
 		duk_hdecenv *e = (duk_hdecenv *) h;
-		DUK_ASSERT_HDECENV_VALID(e);
+		DUK_HDECENV_ASSERT_VALID(e);
 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
 		duk_hobjenv *e = (duk_hobjenv *) h;
-		DUK_ASSERT_HOBJENV_VALID(e);
+		DUK_HOBJENV_ASSERT_VALID(e);
 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
 		duk_hbufobj *b = (duk_hbufobj *) h;
-		DUK_ASSERT_HBUFOBJ_VALID(b);
+		DUK_HBUFOBJ_ASSERT_VALID(b);
 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
-		DUK_ASSERT_HBOUNDFUNC_VALID(f);
+		DUK_HBOUNDFUNC_ASSERT_VALID(f);
 		duk__mark_tval(heap, &f->target);
 		duk__mark_tval(heap, &f->this_binding);
 		duk__mark_tvals(heap, f->args, f->nargs);
 #if defined(DUK_USE_ES6_PROXY)
 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
 		duk_hproxy *p = (duk_hproxy *) h;
-		DUK_ASSERT_HPROXY_VALID(p);
+		DUK_HPROXY_ASSERT_VALID(p);
 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
 #endif  /* DUK_USE_ES6_PROXY */
@@ -48917,7 +51303,7 @@
 		duk_activation *act;
 		duk_tval *tv;
 
-		DUK_ASSERT_HTHREAD_VALID(t);
+		DUK_HTHREAD_ASSERT_VALID(t);
 
 		tv = t->valstack;
 		while (tv < t->valstack_top) {
@@ -48964,6 +51350,7 @@
 		return;
 	}
 
+	DUK_HEAPHDR_ASSERT_VALID(h);
 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
 
 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
@@ -49018,6 +51405,7 @@
 	if (tv == NULL) {
 		return;
 	}
+	DUK_TVAL_ASSERT_VALID(tv);
 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
 		duk_heaphdr *h;
 		h = DUK_TVAL_GET_HEAPHDR(tv);
@@ -49030,6 +51418,7 @@
 	DUK_ASSERT(count == 0 || tv != NULL);
 
 	while (count-- > 0) {
+		DUK_TVAL_ASSERT_VALID(tv);
 		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
 			duk_heaphdr *h;
 			h = DUK_TVAL_GET_HEAPHDR(tv);
@@ -49521,8 +51910,8 @@
 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
 #endif
-				DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
-				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
+				DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
+				DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
 				prev = curr;
 			}
 
@@ -49597,7 +51986,7 @@
 	if (prev != NULL) {
 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
 	}
-	DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
+	DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
 
 #if defined(DUK_USE_DEBUG)
 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
@@ -49732,67 +52121,19 @@
  */
 
 #if defined(DUK_USE_ASSERTIONS)
-DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
-	duk_heaphdr *hdr;
-
-	hdr = heap->heap_allocated;
-	while (hdr) {
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
-		/* may have FINALIZED */
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-
-#if defined(DUK_USE_REFERENCE_COUNTING)
-	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
-#endif
-}
-
-#if defined(DUK_USE_REFERENCE_COUNTING)
-DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
-	duk_heaphdr *hdr = heap->heap_allocated;
-	while (hdr) {
-		/* Cannot really assert much w.r.t. refcounts now. */
-
-		if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
-		    DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
-			/* An object may be in heap_allocated list with a zero
-			 * refcount if it has just been finalized and is waiting
-			 * to be collected by the next cycle.
-			 * (This doesn't currently happen however.)
-			 */
-		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
-			/* An object may be in heap_allocated list with a zero
-			 * refcount also if it is a temporary object created
-			 * during debugger paused state.  It will get collected
-			 * by mark-and-sweep based on its reachability status
-			 * (presumably not reachable because refcount is 0).
-			 */
-		}
-		DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(hdr) >= 0);  /* Unsigned. */
-		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
-	}
-}
-
-DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
+typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
+typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);
+
+DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
 	duk_heaphdr *curr;
+	for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
+		func(heap, curr);
+	}
+}
+
+DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
 	duk_uint32_t i;
 
-	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
-		curr->h_assert_refcount = 0;
-	}
-#if defined(DUK_USE_FINALIZER_SUPPORT)
-	for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
-		curr->h_assert_refcount = 0;
-	}
-#endif
-#if defined(DUK_USE_REFERENCE_COUNTING)
-	for (curr = heap->refzero_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
-		curr->h_assert_refcount = 0;
-	}
-#endif
-
 	for (i = 0; i < heap->st_size; i++) {
 		duk_hstring *h;
 
@@ -49802,12 +52143,93 @@
 		h = heap->strtable[i];
 #endif
 		while (h != NULL) {
-			((duk_heaphdr *) h)->h_assert_refcount = 0;
+			func(heap, h);
 			h = h->hdr.h_next;
 		}
 	}
 }
 
+DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
+	DUK_UNREF(heap);
+	DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(h));
+	DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(h));
+	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h));
+	/* may have FINALIZED */
+}
+DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
+	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
+#if defined(DUK_USE_REFERENCE_COUNTING)
+	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
+#endif
+	/* XXX: Assertions for finalize_list? */
+}
+
+DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
+	DUK_UNREF(heap);
+	DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT(h) || DUK_HEAPHDR_IS_BUFFER(h));
+	duk_heaphdr_assert_valid_subclassed(h);
+}
+DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
+	DUK_UNREF(heap);
+	DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
+	duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
+}
+DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
+	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
+#if defined(DUK_USE_FINALIZER_SUPPORT)
+	duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
+#endif
+#if defined(DUK_USE_REFERENCE_COUNTING)
+	duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
+#endif
+	duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
+}
+
+#if defined(DUK_USE_REFERENCE_COUNTING)
+DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
+	/* Cannot really assert much w.r.t. refcounts now. */
+
+	DUK_UNREF(heap);
+	if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0 &&
+	    DUK_HEAPHDR_HAS_FINALIZED(h)) {
+		/* An object may be in heap_allocated list with a zero
+		 * refcount if it has just been finalized and is waiting
+		 * to be collected by the next cycle.
+		 * (This doesn't currently happen however.)
+		 */
+	} else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
+		/* An object may be in heap_allocated list with a zero
+		 * refcount also if it is a temporary object created
+		 * during debugger paused state.  It will get collected
+		 * by mark-and-sweep based on its reachability status
+		 * (presumably not reachable because refcount is 0).
+		 */
+	}
+	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);  /* Unsigned. */
+}
+DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
+	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
+}
+
+DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
+	DUK_UNREF(heap);
+	h->h_assert_refcount = 0;
+}
+DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
+	DUK_UNREF(heap);
+	((duk_heaphdr *) h)->h_assert_refcount = 0;
+}
+DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
+	duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
+#if defined(DUK_USE_FINALIZER_SUPPORT)
+	duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
+#endif
+#if defined(DUK_USE_REFERENCE_COUNTING)
+	duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
+#endif
+	duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
+}
+
 DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
 	duk_bool_t count_ok;
 	duk_size_t expect_refc;
@@ -49840,32 +52262,21 @@
 	}
 }
 
+DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
+	DUK_UNREF(heap);
+	duk__check_refcount_heaphdr(h);
+}
+DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
+	DUK_UNREF(heap);
+	duk__check_refcount_heaphdr((duk_heaphdr *) h);
+}
 DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
-	duk_heaphdr *curr;
-	duk_uint32_t i;
-
-	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
-		duk__check_refcount_heaphdr(curr);
-	}
+	duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
 #if defined(DUK_USE_FINALIZER_SUPPORT)
-	for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
-		duk__check_refcount_heaphdr(curr);
-	}
-#endif
-
-	for (i = 0; i < heap->st_size; i++) {
-		duk_hstring *h;
-
-#if defined(DUK_USE_STRTAB_PTRCOMP)
-		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
-#else
-		h = heap->strtable[i];
-#endif
-		while (h != NULL) {
-			duk__check_refcount_heaphdr((duk_heaphdr *) h);
-			h = h->hdr.h_next;
-		}
-	}
+	duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
+#endif
+	/* XXX: Assert anything for refzero_list? */
+	duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
 }
 #endif  /* DUK_USE_REFERENCE_COUNTING */
 
@@ -49936,6 +52347,12 @@
 	                 (long) heap->stats_getvar_all));
 	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
 	                 (long) heap->stats_putvar_all));
+	DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
+	                 (long) heap->stats_envrec_delayedcreate,
+	                 (long) heap->stats_envrec_create,
+	                 (long) heap->stats_envrec_newenv,
+	                 (long) heap->stats_envrec_oldenv,
+	                 (long) heap->stats_envrec_pushclosure));
 }
 #endif  /* DUK_USE_DEBUG */
 
@@ -49953,6 +52370,7 @@
 #if defined(DUK_USE_VOLUNTARY_GC)
 	duk_size_t tmp;
 #endif
+	duk_bool_t entry_creating_error;
 
 	DUK_STATS_INC(heap, stats_ms_try_count);
 #if defined(DUK_USE_DEBUG)
@@ -50006,6 +52424,7 @@
 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
 	DUK_ASSERT(heap->ms_recursion_depth == 0);
 	duk__assert_heaphdr_flags(heap);
+	duk__assert_validity(heap);
 #if defined(DUK_USE_REFERENCE_COUNTING)
 	/* Note: heap->refzero_free_running may be true; a refcount
 	 * finalizer may trigger a mark-and-sweep.
@@ -50022,6 +52441,8 @@
 	DUK_ASSERT(heap->ms_running == 0);
 	heap->ms_prevent_count = 1;
 	heap->ms_running = 1;
+	entry_creating_error = heap->creating_error;
+	heap->creating_error = 0;
 
 	/*
 	 *  Free activation/catcher freelists on every mark-and-sweep for now.
@@ -50112,11 +52533,20 @@
 	 *
 	 *  The object insertions go to the front of the list, so they do not
 	 *  cause an infinite loop (they are not compacted).
+	 *
+	 *  At present compaction is not allowed when mark-and-sweep runs
+	 *  during error handling because it involves a duk_safe_call()
+	 *  interfering with error state.
 	 */
 
 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
-		duk__compact_objects(heap);
+		if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
+			DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
+		} else {
+			DUK_D(DUK_DPRINT("object compaction"));
+			duk__compact_objects(heap);
+		}
 	}
 
 	/*
@@ -50140,9 +52570,10 @@
 	 */
 
 	DUK_ASSERT(heap->ms_prevent_count == 1);
+	DUK_ASSERT(heap->ms_running == 1);
 	heap->ms_prevent_count = 0;
-	DUK_ASSERT(heap->ms_running == 1);
 	heap->ms_running = 0;
+	heap->creating_error = entry_creating_error;  /* for nested error handling, see GH-2278 */
 
 	/*
 	 *  Assertions after
@@ -50153,6 +52584,7 @@
 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
 	DUK_ASSERT(heap->ms_recursion_depth == 0);
 	duk__assert_heaphdr_flags(heap);
+	duk__assert_validity(heap);
 #if defined(DUK_USE_REFERENCE_COUNTING)
 	/* Note: heap->refzero_free_running may be true; a refcount
 	 * finalizer may trigger a mark-and-sweep.
@@ -50230,84 +52662,31 @@
 /* #include duk_internal.h -> already included */
 
 /*
- *  Voluntary GC check
- */
-
-#if defined(DUK_USE_VOLUNTARY_GC)
-DUK_LOCAL DUK_INLINE void duk__check_voluntary_gc(duk_heap *heap) {
-	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
-#if defined(DUK_USE_DEBUG)
-		if (heap->ms_prevent_count == 0) {
-			DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
-		} else {
-			DUK_DD(DUK_DDPRINT("gc blocked -> skip voluntary mark-and-sweep now"));
-		}
-#endif
-
-		/* Prevention checks in the call target handle cases where
-		 * voluntary GC is not allowed.  The voluntary GC trigger
-		 * counter is only rewritten if mark-and-sweep actually runs.
-		 */
-		duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_VOLUNTARY /*flags*/);
-	}
-}
-#define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { duk__check_voluntary_gc((heap)); } while (0)
-#else
-#define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */
-#endif  /* DUK_USE_VOLUNTARY_GC */
-
-/*
- *  Allocate memory with garbage collection
- */
-
-DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
+ *  Allocate memory with garbage collection.
+ */
+
+/* Slow path: voluntary GC triggered, first alloc attempt failed, or zero size. */
+DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_alloc_slowpath(duk_heap *heap, duk_size_t size) {
 	void *res;
 	duk_small_int_t i;
 
 	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->alloc_func != NULL);
 	DUK_ASSERT_DISABLE(size >= 0);
 
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
-
-#if defined(DUK_USE_GC_TORTURE)
-	/* Simulate alloc failure on every alloc, except when mark-and-sweep
-	 * is running.
-	 */
-	if (heap->ms_prevent_count == 0) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
-		res = NULL;
-		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->alloc_func(heap->heap_udata, size);
-	if (DUK_LIKELY(res || size == 0)) {
-		/* For zero size allocations NULL is allowed. */
-		return res;
-	}
-#if defined(DUK_USE_GC_TORTURE)
- skip_attempt:
-#endif
-
-	DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
+	if (size == 0) {
+		DUK_D(DUK_DPRINT("zero size alloc in slow path, return NULL"));
+		return NULL;
+	}
+
+	DUK_D(DUK_DPRINT("first alloc attempt failed or voluntary GC limit reached, attempt to gc and retry"));
 
 #if 0
 	/*
-	 *  Avoid a GC if GC is already running.  This can happen at a late
-	 *  stage in a GC when we try to e.g. resize the stringtable
-	 *  or compact objects.
-	 *
-	 *  NOTE: explicit handling isn't actually be needed: if the GC is
-	 *  not allowed, duk_heap_mark_and_sweep() will reject it for every
-	 *  attempt in the loop below, resulting in a NULL same as here.
+	 *  If GC is already running there is no point in attempting a GC
+	 *  because it will be skipped.  This could be checked for explicitly,
+	 *  but it isn't actually needed: the loop below will eventually
+	 *  fail resulting in a NULL.
 	 */
 
 	if (heap->ms_prevent_count != 0) {
@@ -50332,8 +52711,9 @@
 
 		duk_heap_mark_and_sweep(heap, flags);
 
+		DUK_ASSERT(size > 0);
 		res = heap->alloc_func(heap->heap_udata, size);
-		if (res) {
+		if (res != NULL) {
 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
 			                 (long) (i + 1), (long) size));
 			return res;
@@ -50344,10 +52724,56 @@
 	return NULL;
 }
 
-DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
 	void *res;
 
 	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->alloc_func != NULL);
+	DUK_ASSERT_DISABLE(size >= 0);
+
+#if defined(DUK_USE_VOLUNTARY_GC)
+	/* Voluntary periodic GC (if enabled). */
+	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
+		goto slowpath;
+	}
+#endif
+
+#if defined(DUK_USE_GC_TORTURE)
+	/* Simulate alloc failure on every alloc, except when mark-and-sweep
+	 * is running.
+	 */
+	if (heap->ms_prevent_count == 0) {
+		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
+		res = NULL;
+		DUK_UNREF(res);
+		goto slowpath;
+	}
+#endif
+
+	/* Zero-size allocation should happen very rarely (if at all), so
+	 * don't check zero size on NULL; handle it in the slow path
+	 * instead.  This reduces size of inlined code.
+	 */
+	res = heap->alloc_func(heap->heap_udata, size);
+	if (DUK_LIKELY(res != NULL)) {
+		return res;
+	}
+
+ slowpath:
+
+	if (size == 0) {
+		DUK_D(DUK_DPRINT("first alloc attempt returned NULL for zero size alloc, use slow path to deal with it"));
+	} else {
+		DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
+	}
+	return duk__heap_mem_alloc_slowpath(heap, size);
+}
+
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
+	void *res;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->alloc_func != NULL);
 	DUK_ASSERT_DISABLE(size >= 0);
 
 	res = DUK_ALLOC(heap, size);
@@ -50357,24 +52783,37 @@
 	return res;
 }
 
-DUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
 	void *res;
 
 	DUK_ASSERT(thr != NULL);
+	DUK_ASSERT(thr->heap != NULL);
+	DUK_ASSERT(thr->heap->alloc_func != NULL);
+
 	res = duk_heap_mem_alloc(thr->heap, size);
-	if (DUK_LIKELY(res != NULL || size == 0)) {
+	if (DUK_LIKELY(res != NULL)) {
+		return res;
+	} else if (size == 0) {
+		DUK_ASSERT(res == NULL);
 		return res;
 	}
 	DUK_ERROR_ALLOC_FAILED(thr);
 	DUK_WO_NORETURN(return NULL;);
 }
 
-DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
 	void *res;
 
 	DUK_ASSERT(thr != NULL);
-	res = duk_heap_mem_alloc_zeroed(thr->heap, size);
-	if (DUK_LIKELY(res != NULL || size == 0)) {
+	DUK_ASSERT(thr->heap != NULL);
+	DUK_ASSERT(thr->heap->alloc_func != NULL);
+
+	res = duk_heap_mem_alloc(thr->heap, size);
+	if (DUK_LIKELY(res != NULL)) {
+		duk_memzero(res, size);
+		return res;
+	} else if (size == 0) {
+		DUK_ASSERT(res == NULL);
 		return res;
 	}
 	DUK_ERROR_ALLOC_FAILED(thr);
@@ -50382,46 +52821,26 @@
 }
 
 /*
- *  Reallocate memory with garbage collection
- */
-
-DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
+ *  Reallocate memory with garbage collection.
+ */
+
+/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
+DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_slowpath(duk_heap *heap, void *ptr, duk_size_t newsize) {
 	void *res;
 	duk_small_int_t i;
 
 	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->realloc_func != NULL);
 	/* ptr may be NULL */
 	DUK_ASSERT_DISABLE(newsize >= 0);
 
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
-
-#if defined(DUK_USE_GC_TORTURE)
-	/* Simulate alloc failure on every realloc, except when mark-and-sweep
-	 * is running.
-	 */
-	if (heap->ms_prevent_count == 0) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
-		res = NULL;
-		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
-	if (DUK_LIKELY(res || newsize == 0)) {
-		/* For zero size allocations NULL is allowed. */
-		return res;
-	}
-#if defined(DUK_USE_GC_TORTURE)
- skip_attempt:
-#endif
+	/* Newsize was 0 and realloc() returned NULL, this has the semantics
+	 * of free(oldptr), i.e. memory was successfully freed.
+	 */
+	if (newsize == 0) {
+		DUK_D(DUK_DPRINT("zero size realloc in slow path, return NULL"));
+		return NULL;
+	}
 
 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
 
@@ -50452,6 +52871,7 @@
 
 		duk_heap_mark_and_sweep(heap, flags);
 
+		DUK_ASSERT(newsize > 0);
 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
 		if (res || newsize == 0) {
 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
@@ -50464,48 +52884,67 @@
 	return NULL;
 }
 
-/*
- *  Reallocate memory with garbage collection, using a callback to provide
- *  the current allocated pointer.  This variant is used when a mark-and-sweep
- *  (e.g. finalizers) might change the original pointer.
- */
-
-DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
 	void *res;
-	duk_small_int_t i;
 
 	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->realloc_func != NULL);
+	/* ptr may be NULL */
 	DUK_ASSERT_DISABLE(newsize >= 0);
 
-	/*
-	 *  Voluntary periodic GC (if enabled)
-	 */
-
-	DUK__VOLUNTARY_PERIODIC_GC(heap);
-
-	/*
-	 *  First attempt
-	 */
+#if defined(DUK_USE_VOLUNTARY_GC)
+	/* Voluntary periodic GC (if enabled). */
+	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
+		goto slowpath;
+	}
+#endif
 
 #if defined(DUK_USE_GC_TORTURE)
 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
 	 * is running.
 	 */
 	if (heap->ms_prevent_count == 0) {
-		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
+		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
 		res = NULL;
 		DUK_UNREF(res);
-		goto skip_attempt;
-	}
-#endif
-	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
-	if (DUK_LIKELY(res || newsize == 0)) {
-		/* For zero size allocations NULL is allowed. */
+		goto slowpath;
+	}
+#endif
+
+	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
+	if (DUK_LIKELY(res != NULL)) {
 		return res;
 	}
-#if defined(DUK_USE_GC_TORTURE)
- skip_attempt:
-#endif
+
+ slowpath:
+
+	if (newsize == 0) {
+		DUK_D(DUK_DPRINT("first realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
+	} else {
+		DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
+	}
+	return duk__heap_mem_realloc_slowpath(heap, ptr, newsize);
+}
+
+/*
+ *  Reallocate memory with garbage collection, using a callback to provide
+ *  the current allocated pointer.  This variant is used when a mark-and-sweep
+ *  (e.g. finalizers) might change the original pointer.
+ */
+
+/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
+DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_indirect_slowpath(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
+	void *res;
+	duk_small_int_t i;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->realloc_func != NULL);
+	DUK_ASSERT_DISABLE(newsize >= 0);
+
+	if (newsize == 0) {
+		DUK_D(DUK_DPRINT("zero size indirect realloc in slow path, return NULL"));
+		return NULL;
+	}
 
 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
 
@@ -50555,6 +52994,7 @@
 		 * The pointer being reallocated may change after every mark-and-sweep.
 		 */
 
+		DUK_ASSERT(newsize > 0);
 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
 		if (res || newsize == 0) {
 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
@@ -50567,12 +53007,54 @@
 	return NULL;
 }
 
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
+	void *res;
+
+	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->realloc_func != NULL);
+	DUK_ASSERT_DISABLE(newsize >= 0);
+
+#if defined(DUK_USE_VOLUNTARY_GC)
+	/* Voluntary periodic GC (if enabled). */
+	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
+		goto slowpath;
+	}
+#endif
+
+#if defined(DUK_USE_GC_TORTURE)
+	/* Simulate alloc failure on every realloc, except when mark-and-sweep
+	 * is running.
+	 */
+	if (heap->ms_prevent_count == 0) {
+		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
+		res = NULL;
+		DUK_UNREF(res);
+		goto slowpath;
+	}
+#endif
+
+	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
+	if (DUK_LIKELY(res != NULL)) {
+		return res;
+	}
+
+ slowpath:
+
+	if (newsize == 0) {
+		DUK_D(DUK_DPRINT("first indirect realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
+	} else {
+		DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
+	}
+	return duk__heap_mem_realloc_indirect_slowpath(heap, cb, ud, newsize);
+}
+
 /*
  *  Free memory
  */
 
-DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
+DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void duk_heap_mem_free(duk_heap *heap, void *ptr) {
 	DUK_ASSERT(heap != NULL);
+	DUK_ASSERT(heap->free_func != NULL);
 	/* ptr may be NULL */
 
 	/* Must behave like a no-op with NULL and any pointer returned from
@@ -50585,9 +53067,6 @@
 	 * No need to update voluntary GC counter either.
 	 */
 }
-
-/* automatic undefs */
-#undef DUK__VOLUNTARY_PERIODIC_GC
 #line 1 "duk_heap_misc.c"
 /*
  *  Support functions for duk_heap.
@@ -50609,8 +53088,8 @@
 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
 #endif
 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
-	DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
-	DUK_ASSERT_HEAPHDR_LINKS(heap, root);
+	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
+	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
 	heap->heap_allocated = hdr;
 }
 
@@ -50670,8 +53149,8 @@
 	}
 #endif
 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
-	DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
-	DUK_ASSERT_HEAPHDR_LINKS(heap, root);
+	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
+	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
 	heap->finalize_list = hdr;
 }
 #endif  /* DUK_USE_FINALIZER_SUPPORT */
@@ -50770,6 +53249,12 @@
 	heap->curr_thread = new_thr;  /* may be NULL */
 }
 #endif  /* DUK_USE_INTERRUPT_COUNTER */
+
+#if defined(DUK_USE_ASSERTIONS)
+DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
+	DUK_ASSERT(heap != NULL);
+}
+#endif
 #line 1 "duk_heap_refcount.c"
 /*
  *  Reference counting implementation.
@@ -50897,7 +53382,7 @@
 		duk_tval *tv, *tv_end;
 		duk_hobject **funcs, **funcs_end;
 
-		DUK_ASSERT_HCOMPFUNC_VALID(f);
+		DUK_HCOMPFUNC_ASSERT_VALID(f);
 
 		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
@@ -50927,31 +53412,31 @@
 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
 		duk_hdecenv *e = (duk_hdecenv *) h;
-		DUK_ASSERT_HDECENV_VALID(e);
+		DUK_HDECENV_ASSERT_VALID(e);
 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
 		duk_hobjenv *e = (duk_hobjenv *) h;
-		DUK_ASSERT_HOBJENV_VALID(e);
+		DUK_HOBJENV_ASSERT_VALID(e);
 		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
 		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
 		duk_hbufobj *b = (duk_hbufobj *) h;
-		DUK_ASSERT_HBUFOBJ_VALID(b);
+		DUK_HBUFOBJ_ASSERT_VALID(b);
 		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
-		DUK_ASSERT_HBOUNDFUNC_VALID(f);
+		DUK_HBOUNDFUNC_ASSERT_VALID(f);
 		DUK_TVAL_DECREF_NORZ(thr, &f->target);
 		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
 		duk__decref_tvals_norz(thr, f->args, f->nargs);
 #if defined(DUK_USE_ES6_PROXY)
 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
 		duk_hproxy *p = (duk_hproxy *) h;
-		DUK_ASSERT_HPROXY_VALID(p);
+		DUK_HPROXY_ASSERT_VALID(p);
 		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
 		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
 #endif  /* DUK_USE_ES6_PROXY */
@@ -50960,7 +53445,7 @@
 		duk_activation *act;
 		duk_tval *tv;
 
-		DUK_ASSERT_HTHREAD_VALID(t);
+		DUK_HTHREAD_ASSERT_VALID(t);
 
 		tv = t->valstack;
 		while (tv < t->valstack_top) {
@@ -51294,11 +53779,14 @@
 		DUK_ASSERT(thr->heap != NULL); \
 		/* When mark-and-sweep runs, heap_thread must exist. */ \
 		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
-		/* When mark-and-sweep runs, the 'thr' argument always matches heap_thread. \
-		 * This could be used to e.g. suppress check against 'thr' directly (and \
-		 * knowing it would be heap_thread); not really used now. \
+		/* In normal operation finalizers are executed with ms_running == 0 \
+		 * so we should never see ms_running == 1 and thr != heap_thread. \
+		 * In heap destruction finalizers are executed with ms_running != 0 \
+		 * to e.g. prevent refzero; a special value ms_running == 2 is used \
+		 * in that case so it can be distinguished from the normal runtime \
+		 * case, and allows a stronger assertion here (GH-2030). \
 		 */ \
-		DUK_ASSERT(thr->heap->ms_running == 0 || thr == thr->heap->heap_thread); \
+		DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
 		/* We may be called when the heap is initializing and we process \
 		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
 		 * if that's the case. \
@@ -51386,6 +53874,7 @@
 	heap = thr->heap;
 
 	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
+	DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
 	DUK__RZ_SUPPRESS_CHECK();
 
 	switch (htype) {
@@ -52973,6 +55462,85 @@