summaryrefslogtreecommitdiff
path: root/javascript
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2015-12-14 15:47:44 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2015-12-14 15:47:44 +0000
commit91bcaaccfd68f19b0978336083d1409bedd13a4a (patch)
treed025cd7dd3d9405faee2b1318ff3f0f511a04bc4 /javascript
parentd6c34b803926022f1aab6c120cf66b94f39d2bc5 (diff)
downloadnetsurf-91bcaaccfd68f19b0978336083d1409bedd13a4a.tar.gz
netsurf-91bcaaccfd68f19b0978336083d1409bedd13a4a.tar.bz2
Update to duktape snapshot suggested by svaarala.
http://duktape.org/snapshots/duktape-1.3.99-20151209151055-v1.3.0-383-gb7b1c5f-duk-config-improvements.tar.xz
Diffstat (limited to 'javascript')
-rw-r--r--javascript/duktape/duk_config.h3882
-rw-r--r--javascript/duktape/duktape.c4532
-rw-r--r--javascript/duktape/duktape.h40
3 files changed, 5062 insertions, 3392 deletions
diff --git a/javascript/duktape/duk_config.h b/javascript/duktape/duk_config.h
index adf275432..f6ee91cdd 100644
--- a/javascript/duktape/duk_config.h
+++ b/javascript/duktape/duk_config.h
@@ -1,163 +1,105 @@
/*
- * Determine platform features, select feature selection defines
- * (e.g. _XOPEN_SOURCE), include system headers, and define DUK_USE_xxx
- * defines which are (only) checked in Duktape internal code for
- * activated features. Duktape feature selection is based on automatic
- * feature detection, user supplied DUK_OPT_xxx defines, and optionally
- * a "duk_custom.h" user header (if DUK_OPT_HAVE_CUSTOM_H is defined).
+ * duk_config.h configuration header generated by genconfig.py.
*
- * When compiling Duktape, DUK_COMPILING_DUKTAPE is set, and this file
- * is included before any system headers are included. Feature selection
- * defines (e.g. _XOPEN_SOURCE) are defined here before any system headers
- * are included (which is a requirement for system headers to work correctly).
- * This file is responsible for including all system headers and contains
- * all platform dependent cruft in general. When compiling user code,
- * DUK_COMPILING_DUKTAPE is not defined, and we must avoid e.g. defining
- * unnecessary feature selection defines.
+ * Git commit: b7b1c5fd2d1d4550140d57e05a7b32f540082bfa
+ * Git describe: v1.3.0-383-gb7b1c5f
+ * Git branch: duk-config-improvements
*
- * The general order of handling:
- * - Compiler feature detection (require no includes)
- * - Intermediate platform detection (-> easier platform defines)
- * - Platform detection, system includes, byte order detection, etc
- * - ANSI C wrappers (e.g. DUK_MEMCMP), wrappers for constants, etc
- * - DUK_USE_xxx defines are resolved based on input defines
- * - Duktape Date provider settings
- * - Final sanity checks
+ * Supported platforms:
+ * - Mac OSX, iPhone, Darwin
+ * - OpenBSD
+ * - Generic BSD
+ * - Atari ST TOS
+ * - AmigaOS
+ * - Windows
+ * - Flashplayer (Crossbridge)
+ * - QNX
+ * - TI-Nspire
+ * - Emscripten
+ * - Linux
+ * - Solaris
+ * - Generic POSIX
+ * - Cygwin
+ * - Generic UNIX
+ * - Generic fallback
*
- * DUK_F_xxx are internal feature detection macros which should not be
- * used outside this header.
+ * Supported architectures:
+ * - x86
+ * - x64
+ * - x32
+ * - ARM 32-bit
+ * - ARM 64-bit
+ * - MIPS 32-bit
+ * - MIPS 64-bit
+ * - PowerPC 32-bit
+ * - PowerPC 64-bit
+ * - SPARC 32-bit
+ * - SPARC 64-bit
+ * - SuperH
+ * - Motorola 68k
+ * - Emscripten
+ * - Generic
*
- * Useful resources:
+ * Supported compilers:
+ * - Clang
+ * - GCC
+ * - MSVC
+ * - Emscripten
+ * - TinyC
+ * - VBCC
+ * - Bruce's C compiler
+ * - Generic
*
- * http://sourceforge.net/p/predef/wiki/Home/
- * http://sourceforge.net/p/predef/wiki/Architectures/
- * http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor
- * http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types
- *
- * Preprocessor defines available in a particular GCC:
- *
- * gcc -dM -E - </dev/null # http://www.brain-dump.org/blog/entry/107
*/
-#ifndef DUK_CONFIG_H_INCLUDED
+#if !defined(DUK_CONFIG_H_INCLUDED)
#define DUK_CONFIG_H_INCLUDED
/*
- * Compiler features
- */
-
-#undef DUK_F_C99
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-#define DUK_F_C99
-#endif
-
-#undef DUK_F_CPP
-#if defined(__cplusplus)
-#define DUK_F_CPP
-#endif
-
-#undef DUK_F_CPP11
-#if defined(__cplusplus) && (__cplusplus >= 201103L)
-#define DUK_F_CPP11
-#endif
-
-/*
- * Provides the duk_rdtsc() inline function (if available), limited to
- * GCC C99.
- *
- * See: http://www.mcs.anl.gov/~kazutomo/rdtsc.html
+ * Intermediate helper defines
*/
-/* XXX: more accurate detection of what gcc versions work; more inline
- * asm versions for other compilers.
- */
-#if defined(__GNUC__) && defined(__i386__) && defined(DUK_F_C99) && \
- !defined(__cplusplus) /* unsigned long long not standard */
-static __inline__ unsigned long long duk_rdtsc(void) {
- unsigned long long int x;
- __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
- return x;
-}
-#define DUK_USE_RDTSC() duk_rdtsc()
-#elif defined(__GNUC__) && defined(__x86_64__) && defined(DUK_F_C99) && \
- !defined(__cplusplus) /* unsigned long long not standard */
-static __inline__ unsigned long long duk_rdtsc(void) {
- unsigned hi, lo;
- __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
- return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
-}
-#define DUK_USE_RDTSC() duk_rdtsc()
+/* DLL build detection */
+#if defined(DUK_OPT_DLL_BUILD)
+#define DUK_F_DLL_BUILD
+#elif defined(DUK_OPT_NO_DLL_BUILD)
+#undef DUK_F_DLL_BUILD
#else
-/* not available */
-#undef DUK_USE_RDTSC
+/* not configured for DLL build */
+#undef DUK_F_DLL_BUILD
#endif
-/*
- * Intermediate platform, architecture, and compiler detection. These are
- * hopelessly intertwined - e.g. architecture defines depend on compiler etc.
- *
- * Provide easier defines for platforms and compilers which are often tricky
- * or verbose to detect. The intent is not to provide intermediate defines for
- * all features; only if existing feature defines are inconvenient.
- */
-
-/* Intel x86 (32-bit) */
-#if defined(i386) || defined(__i386) || defined(__i386__) || \
- defined(__i486__) || defined(__i586__) || defined(__i686__) || \
- defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \
- defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)
-#define DUK_F_X86
+/* Apple OSX, iOS */
+#if defined(__APPLE__)
+#define DUK_F_APPLE
#endif
-/* AMD64 (64-bit) */
-#if defined(__amd64__) || defined(__amd64) || \
- defined(__x86_64__) || defined(__x86_64) || \
- defined(_M_X64) || defined(_M_AMD64)
-#define DUK_F_X64
+/* OpenBSD */
+#if defined(__OpenBSD__) || defined(__OpenBSD)
+#define DUK_F_OPENBSD
#endif
-/* X32: 64-bit with 32-bit pointers (allows packed tvals). X32 support is
- * not very mature yet.
- *
- * https://sites.google.com/site/x32abi/
- */
-#if defined(DUK_F_X64) && \
- (defined(_ILP32) || defined(__ILP32__))
-#define DUK_F_X32
-/* define only one of: DUK_F_X86, DUK_F_X32, or DUK_F_X64 */
-#undef DUK_F_X64
-#undef DUK_F_X86
+/* NetBSD */
+#if defined(__NetBSD__) || defined(__NetBSD)
+#define DUK_F_NETBSD
#endif
-/* ARM */
-#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM)
-#define DUK_F_ARM
+/* FreeBSD */
+#if defined(__FreeBSD__) || defined(__FreeBSD)
+#define DUK_F_FREEBSD
#endif
-/* MIPS */
-/* Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */
-#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \
- defined(_R3000) || defined(_R4000) || defined(_R5900) || \
- defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \
- defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \
- defined(__mips) || defined(__MIPS__)
-#define DUK_F_MIPS
-#if defined(__LP64__) || defined(__mips64) || defined(__mips64__) || \
- defined(__mips_n64)
-#define DUK_F_MIPS64
-#else
-#define DUK_F_MIPS32
-#endif
+/* BSD variant */
+#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \
+ defined(__bsdi__) || defined(__DragonFly__)
+#define DUK_F_BSD
#endif
-/* SuperH */
-#if defined(__sh__) || \
- defined(__sh1__) || defined(__SH1__) || \
- defined(__sh2__) || defined(__SH2__) || \
- defined(__sh3__) || defined(__SH3__) || \
- defined(__sh4__) || defined(__SH4__) || \
- defined(__sh5__) || defined(__SH5__)
-#define DUK_F_SUPERH
+/* Atari ST TOS. __TOS__ defined by PureC. No platform define in VBCC
+ * apparently, so to use with VBCC user must define __TOS__ manually.
+ */
+#if defined(__TOS__)
+#define DUK_F_TOS
#endif
/* Motorola 68K. Not defined by VBCC, so user must define one of these
@@ -167,40 +109,77 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#define DUK_F_M68K
#endif
+/* AmigaOS. Neither AMIGA nor __amigaos__ is defined on VBCC, so user must
+ * define 'AMIGA' manually when using VBCC.
+ */
+#if defined(AMIGA) || defined(__amigaos__)
+#define DUK_F_AMIGAOS
+#endif
+
/* PowerPC */
#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__)
#define DUK_F_PPC
-#if defined(__PPC64__)
+#if defined(__PPC64__) || defined(__LP64__) || defined(_LP64)
#define DUK_F_PPC64
#else
#define DUK_F_PPC32
#endif
#endif
+/* Windows, both 32-bit and 64-bit */
+#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \
+ defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
+#define DUK_F_WINDOWS
+#if defined(_WIN64) || defined(WIN64)
+#define DUK_F_WIN64
+#else
+#define DUK_F_WIN32
+#endif
+#endif
+
+/* Flash player (e.g. Crossbridge) */
+#if defined(__FLASHPLAYER__)
+#define DUK_F_FLASHPLAYER
+#endif
+
+/* QNX */
+#if defined(__QNX__)
+#define DUK_F_QNX
+#endif
+
+/* TI-Nspire (using Ndless) */
+#if defined(_TINSPIRE)
+#define DUK_F_TINSPIRE
+#endif
+
+/* Emscripten (provided explicitly by user), improve if possible */
+#if defined(EMSCRIPTEN)
+#define DUK_F_EMSCRIPTEN
+#endif
+
+/* BCC (Bruce's C compiler): this is a "torture target" for compilation */
+#if defined(__BCC__) || defined(__BCC_VERSION__)
+#define DUK_F_BCC
+#endif
+
/* Linux */
#if defined(__linux) || defined(__linux__) || defined(linux)
#define DUK_F_LINUX
#endif
-/* FreeBSD */
-#if defined(__FreeBSD__) || defined(__FreeBSD)
-#define DUK_F_FREEBSD
-#endif
-
-/* NetBSD */
-#if defined(__NetBSD__) || defined(__NetBSD)
-#define DUK_F_NETBSD
+/* illumos / Solaris */
+#if defined(__sun) && defined(__SVR4)
+#define DUK_F_SUN
#endif
-/* OpenBSD */
-#if defined(__OpenBSD__) || defined(__OpenBSD)
-#define DUK_F_OPENBSD
+/* POSIX */
+#if defined(__posix)
+#define DUK_F_POSIX
#endif
-/* BSD variant */
-#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \
- defined(__bsdi__) || defined(__DragonFly__)
-#define DUK_F_BSD
+/* Cygwin */
+#if defined(__CYGWIN__)
+#define DUK_F_CYGWIN
#endif
/* Generic Unix (includes Cygwin) */
@@ -209,58 +188,111 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#define DUK_F_UNIX
#endif
-/* Cygwin */
-#if defined(__CYGWIN__)
-#define DUK_F_CYGWIN
+/* stdint.h not available */
+#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
+#if (_MSC_VER < 1700)
+/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
+#define DUK_F_NO_STDINT_H
+#endif
+#endif
+#if !defined(DUK_F_NO_STDINT_H) && (defined(DUK_F_TOS) || defined(DUK_F_BCC))
+#define DUK_F_NO_STDINT_H
#endif
-/* Windows (32-bit or above) */
-#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \
- defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
-#define DUK_F_WINDOWS
+/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),
+ * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.
+ * https://sites.google.com/site/x32abi/
+ */
+#if defined(__amd64__) || defined(__amd64) || \
+ defined(__x86_64__) || defined(__x86_64) || \
+ defined(_M_X64) || defined(_M_AMD64)
+#if defined(__ILP32__) || defined(_ILP32)
+#define DUK_F_X32
+#else
+#define DUK_F_X64
+#endif
+#elif defined(i386) || defined(__i386) || defined(__i386__) || \
+ defined(__i486__) || defined(__i586__) || defined(__i686__) || \
+ defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \
+ defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)
+#if defined(__LP64__) || defined(_LP64)
+/* This should not really happen, but would indicate x64. */
+#define DUK_F_X64
+#else
+#define DUK_F_X86
+#endif
#endif
-#if defined(__APPLE__)
-#define DUK_F_APPLE
+/* ARM */
+#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM)
+#define DUK_F_ARM
+#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__)
+#define DUK_F_ARM64
+#else
+#define DUK_F_ARM32
+#endif
#endif
-/* Atari ST TOS. __TOS__ defined by PureC (which doesn't work as a target now
- * because int is 16-bit, to be fixed). No platform define in VBCC apparently,
- * so to use with VBCC, user must define '__TOS__' manually.
- */
-#if defined(__TOS__)
-#define DUK_F_TOS
+/* MIPS. Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */
+#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \
+ defined(_R3000) || defined(_R4000) || defined(_R5900) || \
+ defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \
+ defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \
+ defined(__mips) || defined(__MIPS__)
+#define DUK_F_MIPS
+#if defined(__LP64__) || defined(_LP64) || defined(__mips64) || \
+ defined(__mips64__) || defined(__mips_n64)
+#define DUK_F_MIPS64
+#else
+#define DUK_F_MIPS32
+#endif
#endif
-/* AmigaOS. Neither AMIGA nor __amigaos__ is defined on VBCC, so user must
- * define 'AMIGA' manually.
- */
-#if defined(AMIGA) || defined(__amigaos__)
-#define DUK_F_AMIGAOS
+/* SPARC */
+#if defined(sparc) || defined(__sparc) || defined(__sparc__)
+#define DUK_F_SPARC
+#if defined(__LP64__) || defined(_LP64)
+#define DUK_F_SPARC64
+#else
+#define DUK_F_SPARC32
+#endif
#endif
-/* Flash player (e.g. Crossbridge) */
-#if defined(__FLASHPLAYER__)
-#define DUK_F_FLASHPLAYER
+/* SuperH */
+#if defined(__sh__) || \
+ defined(__sh1__) || defined(__SH1__) || \
+ defined(__sh2__) || defined(__SH2__) || \
+ defined(__sh3__) || defined(__SH3__) || \
+ defined(__sh4__) || defined(__SH4__) || \
+ defined(__sh5__) || defined(__SH5__)
+#define DUK_F_SUPERH
#endif
-/* Emscripten (provided explicitly by user), improve if possible */
-#if defined(EMSCRIPTEN)
-#define DUK_F_EMSCRIPTEN
+/* Clang */
+#if defined(__clang__)
+#define DUK_F_CLANG
#endif
-/* QNX */
-#if defined(__QNX__)
-#define DUK_F_QNX
+/* C++ */
+#undef DUK_F_CPP
+#if defined(__cplusplus)
+#define DUK_F_CPP
#endif
-/* TI-Nspire (using Ndless) */
-#if defined(_TINSPIRE)
-#define DUK_F_TINSPIRE
+/* C99 or above */
+#undef DUK_F_C99
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define DUK_F_C99
+#endif
+
+/* C++11 or above */
+#undef DUK_F_CPP11
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+#define DUK_F_CPP11
#endif
-/* GCC and GCC version convenience define. */
-#if defined(__GNUC__)
+/* GCC. Clang also defines __GNUC__ so don't detect GCC if using Clang. */
+#if defined(__GNUC__) && !defined(__clang__) && !defined(DUK_F_CLANG)
#define DUK_F_GCC
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */
@@ -270,16 +302,9 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#endif
#endif
-/* Clang */
-#if defined(__clang__)
-#define DUK_F_CLANG
-/* It seems clang also defines __GNUC__, so undo the GCC detection. */
-#if defined(DUK_F_GCC)
-#undef DUK_F_GCC
-#endif
-#if defined(DUK_F_GCC_VERSION)
-#undef DUK_F_GCC_VERSION
-#endif
+/* MinGW. Also GCC flags (DUK_F_GCC) are enabled now. */
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define DUK_F_MINGW
#endif
/* MSVC */
@@ -298,105 +323,25 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#endif
#endif /* _MSC_VER */
-/* MinGW */
-#if defined(__MINGW32__) || defined(__MINGW64__)
-/* NOTE: Also GCC flags are detected (DUK_F_GCC etc). */
-#define DUK_F_MINGW
-#endif
-
-/* BCC (Bruce's C compiler): this is a "torture target" for compilation */
-#if defined(__BCC__) || defined(__BCC_VERSION__)
-#define DUK_F_BCC
+/* TinyC */
+#if defined(__TINYC__)
+/* http://bellard.org/tcc/tcc-doc.html#SEC9 */
+#define DUK_F_TINYC
#endif
+/* VBCC */
#if defined(__VBCC__)
#define DUK_F_VBCC
#endif
-/*
- * Platform detection, system includes, Date provider selection.
- *
- * Feature selection (e.g. _XOPEN_SOURCE) must happen before any system
- * headers are included. This header should avoid providing any feature
- * selection defines when compiling user code (only when compiling Duktape
- * itself). If a feature selection option is required for user code to
- * compile correctly (e.g. it is needed for type detection), it should
- * probably be -checked- here, not defined here.
- *
- * Date provider selection seems a bit out-of-place here, but since
- * the date headers and provider functions are heavily platform
- * specific, there's little point in duplicating the platform if-else
- * ladder. All platform specific Date provider functions are in
- * duk_bi_date.c; here we provide appropriate #defines to enable them,
- * and include all the necessary system headers so that duk_bi_date.c
- * compiles. Date "providers" are:
- *
- * NOW = getting current time (required)
- * TZO = getting local time offset (required)
- * PRS = parse datetime (optional)
- * FMT = format datetime (optional)
- *
- * There's a lot of duplication here, unfortunately, because many
- * platforms have similar (but not identical) headers, Date providers,
- * etc. The duplication could be removed by more complicated nested
- * #ifdefs, but it would then be more difficult to make fixes which
- * affect only a specific platform.
- *
- * XXX: add a way to provide custom functions to provide the critical
- * primitives; this would be convenient when porting to unknown platforms
- * (rather than muck with Duktape internals).
- */
-
-#if defined(DUK_COMPILING_DUKTAPE) && \
- (defined(DUK_F_LINUX) || defined(DUK_F_EMSCRIPTEN))
-/* A more recent Emscripten (2014-05) seems to lack "linux" environment
- * defines, so check for Emscripten explicitly.
- */
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* e.g. getdate_r */
-#endif
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE /* e.g. strptime */
-#endif
-#endif
-
-#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)
-/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */
-#define _XOPEN_SOURCE 600
-#define _POSIX_C_SOURCE 200112L
+/* uclibc */
+#if defined(__UCLIBC__)
+#define DUK_F_UCLIBC
#endif
-#undef DUK_F_MSVC_CRT_SECURE
-#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
-/* http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx
- * http://msdn.microsoft.com/en-us/library/wd3wzwts.aspx
- * Seem to be available since VS2005.
- */
-#if (_MSC_VER >= 1400)
-/* VS2005+, secure CRT functions are preferred. Windows Store applications
- * (and probably others) should use these.
- */
-#define DUK_F_MSVC_CRT_SECURE
-#endif
-#if (_MSC_VER < 1700)
-/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
-#define DUK_F_NO_STDINT_H
-#endif
-/* Initial fix: disable secure CRT related warnings when compiling Duktape
- * itself (must be defined before including Windows headers). Don't define
- * for user code including duktape.h.
+/*
+ * Platform autodetection
*/
-#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-#endif /* DUK_F_WINDOWS && _MSC_VER */
-
-#if defined(DUK_F_TOS) || defined(DUK_F_BCC)
-#define DUK_F_NO_STDINT_H
-#endif
/* Workaround for older C++ compilers before including <inttypes.h>,
* see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366
@@ -408,19 +353,35 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#define __STDC_CONSTANT_MACROS
#endif
-#if defined(__APPLE__)
-/* Mac OSX, iPhone, Darwin */
+#if defined(DUK_F_APPLE)
+/* --- Mac OSX, iPhone, Darwin --- */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <TargetConditionals.h>
#include <architecture/byte_order.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
+
+/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */
+#if TARGET_IPHONE_SIMULATOR
+#define DUK_USE_OS_STRING "iphone-sim"
+#elif TARGET_OS_IPHONE
+#define DUK_USE_OS_STRING "iphone"
+#elif TARGET_OS_MAC
+#define DUK_USE_OS_STRING "ios"
+#else
+#define DUK_USE_OS_STRING "ios-unknown"
+#endif
+
+/* Use _setjmp() on Apple by default, see GH-55. */
+#define DUK_USE_UNDERSCORE_SETJMP
+#define DUK_SETJMP(jb) _setjmp((jb))
+#define DUK_LONGJMP(jb) _longjmp((jb), 1)
#elif defined(DUK_F_OPENBSD)
+/* --- OpenBSD --- */
/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
@@ -428,45 +389,52 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#define DUK_USE_DATE_FMT_STRFTIME
#include <sys/types.h>
#include <sys/endian.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
+
+#define DUK_USE_OS_STRING "openbsd"
#elif defined(DUK_F_BSD)
-/* other BSD */
+/* --- Generic BSD --- */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <sys/types.h>
#include <sys/endian.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
+
+#define DUK_USE_OS_STRING "bsd"
#elif defined(DUK_F_TOS)
-/* Atari ST TOS */
+/* --- Atari ST TOS --- */
#define DUK_USE_DATE_NOW_TIME
#define DUK_USE_DATE_TZO_GMTIME
/* no parsing (not an error) */
#define DUK_USE_DATE_FMT_STRFTIME
-#include <limits.h>
#include <time.h>
+
+#define DUK_USE_OS_STRING "tos"
+
+/* TOS on M68K is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_M68K)
+#define DUK_USE_BYTEORDER 3
+#endif
#elif defined(DUK_F_AMIGAOS)
+/* --- AmigaOS --- */
#if defined(DUK_F_M68K)
/* AmigaOS on M68k */
#define DUK_USE_DATE_NOW_TIME
#define DUK_USE_DATE_TZO_GMTIME
/* no parsing (not an error) */
#define DUK_USE_DATE_FMT_STRFTIME
-#include <limits.h>
#include <time.h>
#elif defined(DUK_F_PPC)
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
-#include <limits.h>
#include <time.h>
#ifndef UINTPTR_MAX
#define UINTPTR_MAX UINT_MAX
@@ -474,7 +442,23 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#else
#error AmigaOS but not M68K/PPC, not supported now
#endif
+
+#define DUK_USE_OS_STRING "amigaos"
+
+/* AmigaOS on M68K or PPC is always big endian. */
+#if !defined(DUK_USE_BYTEORDER) && (defined(DUK_F_M68K) || defined(DUK_F_PPC))
+#define DUK_USE_BYTEORDER 3
+#endif
#elif defined(DUK_F_WINDOWS)
+/* --- Windows --- */
+/* Initial fix: disable secure CRT related warnings when compiling Duktape
+ * itself (must be defined before including Windows headers). Don't define
+ * for user code including duktape.h.
+ */
+#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
/* Windows 32-bit and 64-bit are currently the same. */
/* MSVC does not have sys/param.h */
#define DUK_USE_DATE_NOW_WINDOWS
@@ -484,133 +468,802 @@ static __inline__ unsigned long long duk_rdtsc(void) {
* the ISO 8601 standard format.
*/
#if defined(DUK_COMPILING_DUKTAPE)
+/* Only include when compiling Duktape to avoid polluting application build
+ * with a lot of unnecessary defines.
+ */
#include <windows.h>
#endif
-#include <limits.h>
+
+#define DUK_USE_OS_STRING "windows"
+
+/* On Windows, assume we're little endian. Even Itanium which has a
+ * configurable endianness runs little endian in Windows.
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
#elif defined(DUK_F_FLASHPLAYER)
-/* Crossbridge */
+/* --- Flashplayer (Crossbridge) --- */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <endian.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
+
+#define DUK_USE_OS_STRING "flashplayer"
+
+#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_FLASHPLAYER)
+#define DUK_USE_BYTEORDER 1
+#endif
#elif defined(DUK_F_QNX)
+/* --- QNX --- */
+#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)
+/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */
+#define _XOPEN_SOURCE 600
+#define _POSIX_C_SOURCE 200112L
+#endif
+
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <sys/types.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
+
+#define DUK_USE_OS_STRING "qnx"
#elif defined(DUK_F_TINSPIRE)
+/* --- TI-Nspire --- */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <sys/types.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
-#elif defined(DUK_F_LINUX)
+
+#define DUK_USE_OS_STRING "tinspire"
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE /* e.g. strptime */
+#endif
+#endif /* DUK_COMPILING_DUKTAPE */
+
+#include <sys/types.h>
+#if defined(DUK_F_BCC)
+/* no endian.h */
+#else
+#include <endian.h>
+#endif /* DUK_F_BCC */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdint.h>
+
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "emscripten"
+#elif defined(DUK_F_LINUX)
+/* --- Linux --- */
+#if defined(DUK_COMPILING_DUKTAPE)
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* e.g. getdate_r */
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE /* e.g. strptime */
+#endif
+#endif /* DUK_COMPILING_DUKTAPE */
+
#include <sys/types.h>
#if defined(DUK_F_BCC)
-/* no endian.h */
+/* no endian.h or stdint.h */
#else
#include <endian.h>
+#include <stdint.h>
#endif /* DUK_F_BCC */
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
-#elif defined(__posix)
-/* POSIX */
+
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
+
+#define DUK_USE_OS_STRING "linux"
+#elif defined(DUK_F_SUN)
+/* --- Solaris --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+
#include <sys/types.h>
-#include <endian.h>
-#include <limits.h>
+#include <ast/endian.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
-#elif defined(DUK_F_CYGWIN)
-/* Cygwin -- don't use strptime() for now */
+
+#define DUK_USE_OS_STRING "solaris"
+#elif defined(DUK_F_POSIX)
+/* --- Generic POSIX --- */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <sys/types.h>
#include <endian.h>
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
-#else
-/* Other UNIX, hopefully others */
+
+#define DUK_USE_OS_STRING "posix"
+#elif defined(DUK_F_CYGWIN)
+/* --- Cygwin --- */
+/* don't use strptime() for now */
#define DUK_USE_DATE_NOW_GETTIMEOFDAY
#define DUK_USE_DATE_TZO_GMTIME_R
-#define DUK_USE_DATE_PRS_STRPTIME
#define DUK_USE_DATE_FMT_STRFTIME
#include <sys/types.h>
-#if defined(DUK_F_BCC)
-/* no endian.h */
-#else
#include <endian.h>
-#endif /* DUK_F_BCC */
-#include <limits.h>
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
-#endif
-/* Shared includes */
+#define DUK_USE_UNDERSCORE_SETJMP
+#define DUK_SETJMP(jb) _setjmp((jb))
+#define DUK_LONGJMP(jb) _longjmp((jb), 1)
+
+#define DUK_USE_OS_STRING "windows"
+#elif defined(DUK_F_UNIX)
+/* --- Generic UNIX --- */
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <time.h>
+#include <sys/time.h>
+#define DUK_USE_OS_STRING "unknown"
+#else
+/* --- Generic fallback --- */
+/* The most portable current time provider is time(), but it only has a
+ * one second resolution.
+ */
+#define DUK_USE_DATE_NOW_TIME
+
+/* The most portable way to figure out local time offset is gmtime(),
+ * but it's not thread safe so use with caution.
+ */
+#define DUK_USE_DATE_TZO_GMTIME
+
+/* Avoid custom date parsing and formatting for portability. */
+#undef DUK_USE_DATE_PRS_STRPTIME
+#undef DUK_USE_DATE_FMT_STRFTIME
+
+/* Rely on C89 headers only; time.h must be here. */
+#include <time.h>
+
+#define DUK_USE_OS_STRING "unknown"
+#endif /* autodetect platform */
+
+/* Shared includes: C89 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h> /* varargs */
#include <setjmp.h>
#include <stddef.h> /* e.g. ptrdiff_t */
+#include <math.h>
+#include <limits.h>
+
+/* date.h is omitted, and included per platform */
+
+/* Shared includes: stdint.h is C99 */
#if defined(DUK_F_NO_STDINT_H)
/* stdint.h not available */
#else
-/* Technically C99 (C++11) but found in many systems. Note the workaround
- * above for some C++ compilers (__STDC_LIMIT_MACROS etc).
+/* Technically C99 (C++11) but found in many systems. On some systems
+ * __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS must be defined before
+ * including stdint.h (see above).
*/
#include <stdint.h>
#endif
-#include <math.h>
-#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \
- !defined(DUK_F_BCC)
-/* ULL / LL preprocessor constants should be avoided because they're not
- * always available. With suitable options, some compilers will support
- * 64-bit integer types but won't support ULL / LL preprocessor constants.
- * Assume C99/C++11 environments have these. However, BCC is nominally
- * C99 but doesn't support these constants.
+/*
+ * Architecture autodetection
+ */
+
+#if defined(DUK_F_X86)
+/* --- x86 --- */
+#define DUK_USE_ARCH_STRING "x86"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
*/
-#define DUK_F_ULL_CONSTS
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X64)
+/* --- x64 --- */
+#define DUK_USE_ARCH_STRING "x64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_X32)
+/* --- x32 --- */
+#define DUK_USE_ARCH_STRING "x32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+/* XXX: This is technically not guaranteed because it's possible to configure
+ * an x86 to require aligned accesses with Alignment Check (AC) flag.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 1
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM32)
+/* --- ARM 32-bit --- */
+#define DUK_USE_ARCH_STRING "arm32"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_ARM64)
+/* --- ARM 64-bit --- */
+#define DUK_USE_ARCH_STRING "arm64"
+/* Byte order varies, so rely on autodetect. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS32)
+/* --- MIPS 32-bit --- */
+#define DUK_USE_ARCH_STRING "mips32"
+/* MIPS byte order varies so rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux MIPS except for doubles, which need align by 4. Alignment
+ * requirements vary based on target though.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_MIPS64)
+/* --- MIPS 64-bit --- */
+#define DUK_USE_ARCH_STRING "mips64"
+/* MIPS byte order varies so rely on autodetection. */
+/* Good default is a bit arbitrary because alignment requirements
+ * depend on target. See https://github.com/svaarala/duktape/issues/102.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC32)
+/* --- PowerPC 32-bit --- */
+#define DUK_USE_ARCH_STRING "ppc32"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_PPC64)
+/* --- PowerPC 64-bit --- */
+#define DUK_USE_ARCH_STRING "ppc64"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC32)
+/* --- SPARC 32-bit --- */
+#define DUK_USE_ARCH_STRING "sparc32"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SPARC64)
+/* --- SPARC 64-bit --- */
+#define DUK_USE_ARCH_STRING "sparc64"
+/* SPARC byte order varies so rely on autodetection. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_SUPERH)
+/* --- SuperH --- */
+#define DUK_USE_ARCH_STRING "sh"
+/* Byte order varies, rely on autodetection. */
+/* Based on 'make checkalign' there are no alignment requirements on
+ * Linux SH4, but align by 4 is probably a good basic default.
+ */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 4
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_M68K)
+/* --- Motorola 68k --- */
+#define DUK_USE_ARCH_STRING "m68k"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#define DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_USE_ARCH_STRING "emscripten"
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
+#endif
+#undef DUK_USE_PACKED_TVAL
+#define DUK_F_PACKED_TVAL_PROVIDED
+#else
+/* --- Generic --- */
+/* These are necessary wild guesses. */
+#define DUK_USE_ARCH_STRING "generic"
+/* Rely on autodetection for byte order, alignment, and packed tval. */
+#endif /* autodetect architecture */
/*
- * Detection for specific libc variants (like uclibc) and other libc specific
- * features. Potentially depends on the #includes above.
+ * Compiler autodetection
*/
-#if defined(__UCLIBC__)
-#define DUK_F_UCLIBC
+#if defined(DUK_F_CLANG)
+/* --- Clang --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* Clang: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
#endif
+#define DUK_NORETURN(decl) decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x) __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x) __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE __attribute__((noinline))
+#define DUK_INLINE inline
+#define DUK_ALWAYS_INLINE inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL extern __declspec(dllexport)
+#define DUK_EXTERNAL __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL extern __declspec(dllimport)
+#define DUK_EXTERNAL should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL static
+#define DUK_INTERNAL static
+#else
+#define DUK_INTERNAL_DECL extern
+#define DUK_INTERNAL /*empty*/
+#endif
+#define DUK_LOCAL_DECL static
+#define DUK_LOCAL static
+
+#else
+#define DUK_EXTERNAL_DECL __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL static
+#define DUK_INTERNAL static
+#else
+#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL __attribute__ ((visibility("hidden")))
+#endif
+#define DUK_LOCAL_DECL static
+#define DUK_LOCAL static
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "clang"
+#else
+#define DUK_USE_COMPILER_STRING "clang"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_GCC)
+/* --- GCC --- */
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+/* C99 / C++11 and above: rely on va_copy() which is required. */
+#define DUK_VA_COPY(dest,src) va_copy(dest,src)
+#else
+/* GCC: assume we have __va_copy() in non-C99 mode. */
+#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
+/* since gcc-2.5 */
+#define DUK_NORETURN(decl) decl __attribute__((noreturn))
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* since gcc-4.5 */
+#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0)
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
+/* GCC: test not very accurate; enable only in relatively recent builds
+ * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
+ */
+#define DUK_LIKELY(x) __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x) __builtin_expect((x), 0)
+#endif
+
+#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \
+ defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 30101)
+#define DUK_NOINLINE __attribute__((noinline))
+#define DUK_INLINE inline
+#define DUK_ALWAYS_INLINE inline __attribute__((always_inline))
+#endif
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL extern __declspec(dllexport)
+#define DUK_EXTERNAL __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL extern __declspec(dllimport)
+#define DUK_EXTERNAL should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL static
+#define DUK_INTERNAL static
+#else
+#define DUK_INTERNAL_DECL extern
+#define DUK_INTERNAL /*empty*/
+#endif
+#define DUK_LOCAL_DECL static
+#define DUK_LOCAL static
+
+#elif defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40000)
+#define DUK_EXTERNAL_DECL __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL static
+#define DUK_INTERNAL static
+#else
+#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL __attribute__ ((visibility("hidden")))
+#endif
+#define DUK_LOCAL_DECL static
+#define DUK_LOCAL static
+#endif
+
+#if defined(DUK_F_MINGW)
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "mingw++"
+#else
+#define DUK_USE_COMPILER_STRING "mingw"
+#endif
+#else
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "g++"
+#else
+#define DUK_USE_COMPILER_STRING "gcc"
+#endif
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)
+#define DUK_USE_GCC_PRAGMAS
+#else
+#undef DUK_USE_GCC_PRAGMAS
+#endif
+
+#define DUK_USE_PACK_GCC_ATTR
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_MSVC)
+/* --- MSVC --- */
+/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
+#define DUK_NORETURN(decl) __declspec(noreturn) decl
+
+/* XXX: DUK_UNREACHABLE for msvc? */
+
+#undef DUK_USE_BRANCH_HINTS
+
+/* XXX: DUK_LIKELY, DUK_UNLIKELY for msvc? */
+/* XXX: DUK_NOINLINE, DUK_INLINE, DUK_ALWAYS_INLINE for msvc? */
+
+#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)
+/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
+ * compiling Duktape or the application.
+ */
+#if defined(DUK_COMPILING_DUKTAPE)
+#define DUK_EXTERNAL_DECL extern __declspec(dllexport)
+#define DUK_EXTERNAL __declspec(dllexport)
+#else
+#define DUK_EXTERNAL_DECL extern __declspec(dllimport)
+#define DUK_EXTERNAL should_not_happen
+#endif
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL static
+#define DUK_INTERNAL static
+#else
+#define DUK_INTERNAL_DECL extern
+#define DUK_INTERNAL /*empty*/
+#endif
+#define DUK_LOCAL_DECL static
+#define DUK_LOCAL static
+
+#endif
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "msvc++"
+#else
+#define DUK_USE_COMPILER_STRING "msvc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99)
+#define DUK_USE_VARIADIC_MACROS
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+/* VS2005+ should have variadic macros even when they're not C99. */
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+
+#define DUK_USE_PACK_MSVC_PRAGMA
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define DUK_SNPRINTF snprintf
+#define DUK_VSNPRINTF vsnprintf
+#else
+/* (v)snprintf() is missing before MSVC 2015. Note that _(v)snprintf() does
+ * NOT NUL terminate on truncation, but Duktape code never assumes that.
+ * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+ */
+#define DUK_SNPRINTF _snprintf
+#define DUK_VSNPRINTF _vsnprintf
+#endif
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_EMSCRIPTEN)
+/* --- Emscripten --- */
+#define DUK_NORETURN(decl) decl __attribute__((noreturn))
+
+#if defined(__clang__) && defined(__has_builtin)
+#if __has_builtin(__builtin_unreachable)
+#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while (0)
+#endif
+#endif
+
+#define DUK_USE_BRANCH_HINTS
+#define DUK_LIKELY(x) __builtin_expect((x), 1)
+#define DUK_UNLIKELY(x) __builtin_expect((x), 0)
+
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_NOINLINE __attribute__((noinline))
+#define DUK_INLINE inline
+#define DUK_ALWAYS_INLINE inline __attribute__((always_inline))
+#endif
+
+#define DUK_EXTERNAL_DECL __attribute__ ((visibility("default"))) extern
+#define DUK_EXTERNAL __attribute__ ((visibility("default")))
+#if defined(DUK_SINGLE_FILE)
+#define DUK_INTERNAL_DECL static
+#define DUK_INTERNAL static
+#else
+#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern
+#define DUK_INTERNAL __attribute__ ((visibility("hidden")))
+#endif
+#define DUK_LOCAL_DECL static
+#define DUK_LOCAL static
+
+#define DUK_USE_COMPILER_STRING "emscripten"
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#undef DUK_USE_FLEX_C99
+#undef DUK_USE_FLEX_ZEROSIZE
+#undef DUK_USE_FLEX_ONESIZE
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
+#else
+#define DUK_USE_FLEX_ZEROSIZE
+#endif
+
+#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_PACK_CLANG_ATTR
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_TINYC)
+/* --- TinyC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "tinyc++"
+#else
+#define DUK_USE_COMPILER_STRING "tinyc"
+#endif
+
+/* http://bellard.org/tcc/tcc-doc.html#SEC7 */
+#define DUK_USE_VARIADIC_MACROS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_VBCC)
+/* --- VBCC --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "vbcc-c++"
+#else
+#define DUK_USE_COMPILER_STRING "vbcc"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+#define DUK_USE_FLEX_ZEROSIZE
+#define DUK_USE_PACK_DUMMY_MEMBER
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#elif defined(DUK_F_BCC)
+/* --- Bruce's C compiler --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "bcc++"
+#else
+#define DUK_USE_COMPILER_STRING "bcc"
+#endif
+
+/* XXX */
+#undef DUK_USE_VARIADIC_MACROS
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+
+/* BCC, assume we're on x86. */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 1
+#endif
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#else
+/* --- Generic --- */
+#undef DUK_USE_BRANCH_HINTS
+
+#if defined(DUK_F_CPP)
+#define DUK_USE_COMPILER_STRING "generic-c++"
+#else
+#define DUK_USE_COMPILER_STRING "generic"
+#endif
+
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+
+/* Most portable, wastes space */
+#define DUK_USE_FLEX_ONESIZE
+
+/* Most portable, potentially wastes space */
+#define DUK_USE_PACK_DUMMY_MEMBER
+#define DUK_F_VARIADIC_MACROS_PROVIDED
+#endif /* autodetect compiler */
+
/*
* Wrapper typedefs and constants for integer types, also sanity check types.
*
@@ -654,10 +1307,11 @@ static __inline__ unsigned long long duk_rdtsc(void) {
#error cannot check complement of two
#endif
-/* Pointer size determination based on architecture.
- * XXX: unsure about BCC correctness.
+/* Pointer size determination based on __WORDSIZE or architecture when
+ * that's not available.
*/
#if defined(DUK_F_X86) || defined(DUK_F_X32) || \
+ defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \
defined(DUK_F_BCC) || \
(defined(__WORDSIZE) && (__WORDSIZE == 32))
#define DUK_F_32BIT_PTRS
@@ -1154,11 +1808,9 @@ typedef double duk_double_t;
/* Type for public API calls. */
typedef struct duk_hthread duk_context;
-/*
- * Check whether we should use 64-bit integers
- */
-
-/* Quite incomplete now. Use 64-bit types if detected (C99 or other detection)
+/* Check whether we should use 64-bit integers or not.
+ *
+ * Quite incomplete now. Use 64-bit types if detected (C99 or other detection)
* unless they are known to be unreliable. For instance, 64-bit types are
* available on VBCC but seem to misbehave.
*/
@@ -1169,383 +1821,160 @@ typedef struct duk_hthread duk_context;
#endif
/*
- * Alignment requirement and support for unaligned accesses
- *
- * Assume unaligned accesses are not supported unless specifically allowed
- * in the target platform. Some platforms may support unaligned accesses
- * but alignment to 4 or 8 may still be desirable.
+ * Fill-ins for platform, architecture, and compiler
*/
-#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#undef DUK_USE_ALIGN_BY
-
-#if defined(DUK_F_EMSCRIPTEN)
-/* Required on at least some targets, so use whenever Emscripten used,
- * regardless of compilation target.
- */
-#define DUK_USE_ALIGN_BY 8
-#elif defined(DUK_F_ARM)
-#define DUK_USE_ALIGN_BY 4
-#elif defined(DUK_F_MIPS32)
-/* Based on 'make checkalign' there are no alignment requirements on
- * Linux MIPS except for doubles, which need align by 4. Alignment
- * requirements vary based on target though.
- */
-#define DUK_USE_ALIGN_BY 4
-#elif defined(DUK_F_MIPS64)
-/* Good default is a bit arbitrary because alignment requirements
- * depend on target. See https://github.com/svaarala/duktape/issues/102.
- */
-#define DUK_USE_ALIGN_BY 8
-#elif defined(DUK_F_SUPERH)
-/* Based on 'make checkalign' there are no alignment requirements on
- * Linux SH4, but align by 4 is probably a good basic default.
- */
-#define DUK_USE_ALIGN_BY 4
-#elif defined(DUK_F_X86) || defined(DUK_F_X32) || defined(DUK_F_X64) || \
- defined(DUK_F_BCC)
-/* XXX: This is technically not guaranteed because it's possible to configure
- * an x86 to require aligned accesses with Alignment Check (AC) flag.
- */
-#define DUK_USE_ALIGN_BY 1
-#define DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#else
-/* Unknown, use safe default */
-#define DUK_USE_ALIGN_BY 8
+#if !defined(DUK_SETJMP)
+#define DUK_USE_SETJMP
+#define DUK_SETJMP(jb) setjmp((jb))
+#define DUK_LONGJMP(jb) longjmp((jb), 1)
#endif
-/* User forced alignment to 4 or 8. */
-#if defined(DUK_OPT_FORCE_ALIGN)
-#undef DUK_USE_ALIGN_BY
-#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#if (DUK_OPT_FORCE_ALIGN == 4)
-#define DUK_USE_ALIGN_BY 4
-#elif (DUK_OPT_FORCE_ALIGN == 8)
-#define DUK_USE_ALIGN_BY 8
-#else
-#error invalid DUK_OPT_FORCE_ALIGN value
+typedef FILE duk_file;
+#if !defined(DUK_STDIN)
+#define DUK_STDIN stdin
#endif
+#if !defined(DUK_STDOUT)
+#define DUK_STDOUT stdout
+#endif
+#if !defined(DUK_STDERR)
+#define DUK_STDERR stderr
#endif
-/* Compiler specific hackery needed to force struct size to match aligment,
- * see e.g. duk_hbuffer.h.
- *
- * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
- * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
+/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h
+ * (which is unfortunately named). May sometimes need replacement, e.g.
+ * some compilers don't handle zero length or NULL correctly in realloc().
*/
-#if defined(DUK_F_MSVC)
-#define DUK_USE_PACK_MSVC_PRAGMA
-#elif defined(DUK_F_GCC)
-#define DUK_USE_PACK_GCC_ATTR
-#elif defined(DUK_F_CLANG)
-#define DUK_USE_PACK_CLANG_ATTR
-#else
-#define DUK_USE_PACK_DUMMY_MEMBER
+#if !defined(DUK_ANSI_MALLOC)
+#define DUK_ANSI_MALLOC malloc
#endif
-
-#ifdef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
-#define DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
-#else
-#undef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
+#if !defined(DUK_ANSI_REALLOC)
+#define DUK_ANSI_REALLOC realloc
#endif
-
-/* Object property allocation layout has implications for memory and code
- * footprint and generated code size/speed. The best layout also depends
- * on whether the platform has alignment requirements or benefits from
- * having mostly aligned accesses.
- */
-#undef DUK_USE_HOBJECT_LAYOUT_1
-#undef DUK_USE_HOBJECT_LAYOUT_2
-#undef DUK_USE_HOBJECT_LAYOUT_3
-#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE) && (DUK_USE_ALIGN_BY == 1)
-/* On platforms without any alignment issues, layout 1 is preferable
- * because it compiles to slightly less code and provides direct access
- * to property keys.
- */
-#define DUK_USE_HOBJECT_LAYOUT_1
-#else
-/* On other platforms use layout 2, which requires some padding but
- * is a bit more natural than layout 3 in ordering the entries. Layout
- * 3 is currently not used.
- */
-#define DUK_USE_HOBJECT_LAYOUT_2
+#if !defined(DUK_ANSI_CALLOC)
+#define DUK_ANSI_CALLOC calloc
+#endif
+#if !defined(DUK_ANSI_FREE)
+#define DUK_ANSI_FREE free
#endif
-/*
- * Byte order and double memory layout detection
+/* ANSI C (various versions) and some implementations require that the
+ * pointer arguments to memset(), memcpy(), and memmove() be valid values
+ * even when byte size is 0 (even a NULL pointer is considered invalid in
+ * this context). Zero-size operations as such are allowed, as long as their
+ * pointer arguments point to a valid memory area. The DUK_MEMSET(),
+ * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:
+ * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be
+ * allowed. If these are not fulfilled, a macro wrapper is needed.
*
- * Endianness detection is a major portability hassle because the macros
- * and headers are not standardized. There's even variance across UNIX
- * platforms. Even with "standard" headers, details like underscore count
- * varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used
- * (Crossbridge has a single underscore, for instance).
+ * http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
+ * http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html
*
- * The checks below are structured with this in mind: several approaches are
- * used, and at the end we check if any of them worked. This allows generic
- * approaches to be tried first, and platform/compiler specific hacks tried
- * last. As a last resort, the user can force a specific endianness, as it's
- * not likely that automatic detection will work on the most exotic platforms.
+ * Not sure what's the required behavior when a pointer points just past the
+ * end of a buffer, which often happens in practice (e.g. zero size memmoves).
+ * For example, if allocation size is 3, the following pointer would not
+ * technically point to a valid memory byte:
*
- * Duktape supports little and big endian machines. There's also support
- * for a hybrid used by some ARM machines where integers are little endian
- * but IEEE double values use a mixed order (12345678 -> 43218765). This
- * byte order for doubles is referred to as "mixed endian".
- */
-
-#undef DUK_F_BYTEORDER
-#undef DUK_USE_BYTEORDER_FORCED
-
-/* DUK_F_BYTEORDER is set as an intermediate value when detection
- * succeeds, to one of:
- * 1 = little endian
- * 2 = mixed (arm hybrid) endian
- * 3 = big endian
+ * <-- alloc -->
+ * | 0 | 1 | 2 | .....
+ * ^-- p=3, points after last valid byte (2)
*/
-
-/* For custom platforms allow user to define byteorder explicitly.
- * Since endianness headers are not standardized, this is a useful
- * workaround for custom platforms for which endianness detection
- * is not directly supported. Perhaps custom hardware is used and
- * user cannot submit upstream patches.
+#if !defined(DUK_MEMCPY)
+#if defined(DUK_F_UCLIBC)
+/* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide
+ * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html
*/
-#if defined(DUK_OPT_FORCE_BYTEORDER)
-#if (DUK_OPT_FORCE_BYTEORDER == 1)
-#define DUK_F_BYTEORDER 1
-#elif (DUK_OPT_FORCE_BYTEORDER == 2)
-#define DUK_F_BYTEORDER 2
-#elif (DUK_OPT_FORCE_BYTEORDER == 3)
-#define DUK_F_BYTEORDER 3
+#define DUK_MEMCPY memmove
#else
-#error invalid DUK_OPT_FORCE_BYTEORDER value
+#define DUK_MEMCPY memcpy
#endif
-#define DUK_USE_BYTEORDER_FORCED
-#endif /* DUK_OPT_FORCE_BYTEORDER */
-
-/* More or less standard endianness predefines provided by header files.
- * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER
- * will be big endian, see: http://lists.mysql.com/internals/443.
- */
-#if !defined(DUK_F_BYTEORDER)
-#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \
- defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \
- defined(__LITTLE_ENDIAN__)
-/* Integer little endian */
-#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \
- defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)
-#define DUK_F_BYTEORDER 1
-#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
- defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
-#define DUK_F_BYTEORDER 2
-#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 1
-#else
-/* byte order is little endian but cannot determine IEEE double word order */
-#endif /* float word order */
-#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \
- defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \
- defined(__BIG_ENDIAN__)
-/* Integer big endian */
-#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
- defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
-#define DUK_F_BYTEORDER 3
-#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 3
-#else
-/* byte order is big endian but cannot determine IEEE double word order */
-#endif /* float word order */
-#else
-/* cannot determine byte order */
-#endif /* integer byte order */
-#endif /* !defined(DUK_F_BYTEORDER) */
-
-/* GCC and Clang provide endianness defines as built-in predefines, with
- * leading and trailing double underscores (e.g. __BYTE_ORDER__). See
- * output of "make gccpredefs" and "make clangpredefs". Clang doesn't
- * seem to provide __FLOAT_WORD_ORDER__.
- * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
- */
-#if !defined(DUK_F_BYTEORDER) && defined(__BYTE_ORDER__)
-#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-/* Integer little endian */
-#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
- (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-#define DUK_F_BYTEORDER 1
-#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
- (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define DUK_F_BYTEORDER 2
-#elif !defined(__FLOAT_WORD_ORDER__)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 1
-#else
-/* byte order is little endian but cannot determine IEEE double word order */
-#endif /* float word order */
-#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-/* Integer big endian */
-#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
- (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define DUK_F_BYTEORDER 3
-#elif !defined(__FLOAT_WORD_ORDER__)
-/* Float word order not known, assume not a hybrid. */
-#define DUK_F_BYTEORDER 3
-#else
-/* byte order is big endian but cannot determine IEEE double word order */
-#endif /* float word order */
-#else
-/* cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit
- * integer ordering and is not relevant
- */
-#endif /* integer byte order */
-#endif /* !defined(DUK_F_BYTEORDER) && defined(__BYTE_ORDER__) */
-
-/* Atari ST TOS */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_TOS)
-#define DUK_F_BYTEORDER 3
#endif
-
-/* AmigaOS on M68K or PPC */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_AMIGAOS)
-#if defined(DUK_F_M68K) || defined(DUK_F_PPC)
-#define DUK_F_BYTEORDER 3
+#if !defined(DUK_MEMMOVE)
+#define DUK_MEMMOVE memmove
#endif
+#if !defined(DUK_MEMCMP)
+#define DUK_MEMCMP memcmp
#endif
-
-/* On Windows, assume we're little endian. Even Itanium which has a
- * configurable endianness runs little endian in Windows.
- */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_WINDOWS)
-/* XXX: verify that Windows on ARM is little endian for floating point
- * values too.
- */
-#define DUK_F_BYTEORDER 1
-#endif /* Windows */
-
-/* Crossbridge should work with the standard byteorder #ifdefs. It doesn't
- * provide _FLOAT_WORD_ORDER but the standard approach now covers that case
- * too. This has been left here just in case.
- */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_FLASHPLAYER)
-#define DUK_F_BYTEORDER 1
+#if !defined(DUK_MEMSET)
+#define DUK_MEMSET memset
#endif
-
-/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:
- * $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
- * 67:#define __LITTLEENDIAN__ 1
- * $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
- * 81:#define __BIGENDIAN__ 1
- * $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
- * 70:#define __LITTLEENDIAN__ 1
- */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_QNX)
-/* XXX: ARM hybrid? */
-#if defined(__LITTLEENDIAN__)
-#define DUK_F_BYTEORDER 1
-#elif defined(__BIGENDIAN__)
-#define DUK_F_BYTEORDER 3
+#if !defined(DUK_STRLEN)
+#define DUK_STRLEN strlen
#endif
+#if !defined(DUK_STRCMP)
+#define DUK_STRCMP strcmp
#endif
-
-/* Bruce's C Compiler (BCC), assume we're on x86. */
-#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_BCC)
-#define DUK_F_BYTEORDER 1
+#if !defined(DUK_STRNCMP)
+#define DUK_STRNCMP strncmp
#endif
-
-/* Check whether or not byte order detection worked based on the intermediate
- * define, and define final values. If detection failed, #error out.
- */
-#if defined(DUK_F_BYTEORDER)
-#if (DUK_F_BYTEORDER == 1)
-#define DUK_USE_INTEGER_LE
-#define DUK_USE_DOUBLE_LE
-#elif (DUK_F_BYTEORDER == 2)
-#define DUK_USE_INTEGER_LE /* integer endianness is little on purpose */
-#define DUK_USE_DOUBLE_ME
-#elif (DUK_F_BYTEORDER == 3)
-#define DUK_USE_INTEGER_BE
-#define DUK_USE_DOUBLE_BE
-#else
-#error unsupported: byte order detection failed (internal error, should not happen)
-#endif /* byte order */
-#else
-#error unsupported: byte order detection failed
-#endif /* defined(DUK_F_BYTEORDER) */
-
-/*
- * Check whether or not a packed duk_tval representation is possible.
- * What's basically required is that pointers are 32-bit values
- * (sizeof(void *) == 4). Best effort check, not always accurate.
- * If guess goes wrong, crashes may result; self tests also verify
- * the guess.
- */
-
-#undef DUK_USE_PACKED_TVAL_POSSIBLE
-
-/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_HAVE_INTTYPES) && defined(DUK_UINTPTR_MAX)
-#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_PRINTF)
+#define DUK_PRINTF printf
#endif
+#if !defined(DUK_FPRINTF)
+#define DUK_FPRINTF fprintf
#endif
-
-/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
-#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_SPRINTF)
+#define DUK_SPRINTF sprintf
#endif
+#if !defined(DUK_SNPRINTF)
+/* snprintf() is technically not part of C89 but usually available. */
+#define DUK_SNPRINTF snprintf
#endif
-
-/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)
-#if DUK_SIZE_MAX <= 0xffffffffUL
-#define DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_VSPRINTF)
+#define DUK_VSPRINTF vsprintf
#endif
+#if !defined(DUK_VSNPRINTF)
+/* vsnprintf() is technically not part of C89 but usually available. */
+#define DUK_VSNPRINTF vsnprintf
#endif
-
-/* M68K: packed always possible */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_M68K)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_SSCANF)
+#define DUK_SSCANF sscanf
#endif
-
-/* PPC32: packed always possible */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_PPC32)
-#define DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_VSSCANF)
+#define DUK_VSSCANF vsscanf
#endif
-
-/* With Emscripten, force unpacked duk_tval just to be safe, as it seems to
- * break at least on Firefox (probably IEEE double arithmetic is not 100%
- * supported, especially for NaNs).
- */
-#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_EMSCRIPTEN)
-#undef DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_FOPEN)
+#define DUK_FOPEN fopen
#endif
-
-/* Microsoft Visual Studio 2010 on x64 fails the above rules and tries to
- * use a packed type. Force unpacked on x64 in general.
- */
-#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && defined(DUK_F_X64)
-#undef DUK_USE_PACKED_TVAL_POSSIBLE
+#if !defined(DUK_FCLOSE)
+#define DUK_FCLOSE fclose
#endif
-
-/* GCC/clang inaccurate math would break compliance and probably duk_tval,
- * so refuse to compile. Relax this if -ffast-math is tested to work.
- */
-#if defined(__FAST_MATH__)
-#error __FAST_MATH__ defined, refusing to compile
+#if !defined(DUK_FREAD)
+#define DUK_FREAD fread
+#endif
+#if !defined(DUK_FWRITE)
+#define DUK_FWRITE fwrite
+#endif
+#if !defined(DUK_FSEEK)
+#define DUK_FSEEK fseek
+#endif
+#if !defined(DUK_FTELL)
+#define DUK_FTELL ftell
+#endif
+#if !defined(DUK_FFLUSH)
+#define DUK_FFLUSH fflush
+#endif
+#if !defined(DUK_FPUTC)
+#define DUK_FPUTC fputc
+#endif
+#if !defined(DUK_MEMZERO)
+#define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n))
+#endif
+#if !defined(DUK_ABORT)
+#define DUK_ABORT abort
+#endif
+#if !defined(DUK_EXIT)
+#define DUK_EXIT exit
#endif
-/*
- * Detection of double constants and math related functions. Availability
- * of constants and math functions is a significant porting concern.
- *
- * INFINITY/HUGE_VAL is problematic on GCC-3.3: it causes an overflow warning
- * and there is no pragma in GCC-3.3 to disable it. Using __builtin_inf()
- * avoids this problem for some reason.
- */
-
+#if !defined(DUK_DOUBLE_2TO32)
#define DUK_DOUBLE_2TO32 4294967296.0
+#endif
+#if !defined(DUK_DOUBLE_2TO31)
#define DUK_DOUBLE_2TO31 2147483648.0
+#endif
+#if !defined(DUK_DOUBLE_INFINITY)
#undef DUK_USE_COMPUTED_INFINITY
#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600)
/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */
@@ -1559,11 +1988,12 @@ typedef struct duk_hthread duk_context;
* Use a computed infinity (initialized when a heap is created at the
* latest).
*/
-extern double duk_computed_infinity;
#define DUK_USE_COMPUTED_INFINITY
#define DUK_DOUBLE_INFINITY duk_computed_infinity
#endif
+#endif
+#if !defined(DUK_DOUBLE_NAN)
#undef DUK_USE_COMPUTED_NAN
#if defined(NAN)
#define DUK_DOUBLE_NAN NAN
@@ -1575,10 +2005,10 @@ extern double duk_computed_infinity;
* Use a computed NaN (initialized when a heap is created at the
* latest).
*/
-extern double duk_computed_nan;
#define DUK_USE_COMPUTED_NAN
#define DUK_DOUBLE_NAN duk_computed_nan
#endif
+#endif
/* Many platforms are missing fpclassify() and friends, so use replacements
* if necessary. The replacement constants (FP_NAN etc) can be anything but
@@ -1670,23 +2100,57 @@ extern double duk_computed_nan;
* completeness. Because these are used as function pointers, they need
* to be defined as concrete C functions (not macros).
*/
+#if !defined(DUK_FABS)
#define DUK_FABS fabs
+#endif
+#if !defined(DUK_FMIN)
#define DUK_FMIN fmin
+#endif
+#if !defined(DUK_FMAX)
#define DUK_FMAX fmax
+#endif
+#if !defined(DUK_FLOOR)
#define DUK_FLOOR floor
+#endif
+#if !defined(DUK_CEIL)
#define DUK_CEIL ceil
+#endif
+#if !defined(DUK_FMOD)
#define DUK_FMOD fmod
+#endif
+#if !defined(DUK_POW)
#define DUK_POW pow
+#endif
+#if !defined(DUK_ACOS)
#define DUK_ACOS acos
+#endif
+#if !defined(DUK_ASIN)
#define DUK_ASIN asin
+#endif
+#if !defined(DUK_ATAN)
#define DUK_ATAN atan
+#endif
+#if !defined(DUK_ATAN2)
#define DUK_ATAN2 atan2
+#endif
+#if !defined(DUK_SIN)
#define DUK_SIN sin
+#endif
+#if !defined(DUK_COS)
#define DUK_COS cos
+#endif
+#if !defined(DUK_TAN)
#define DUK_TAN tan
+#endif
+#if !defined(DUK_EXP)
#define DUK_EXP exp
+#endif
+#if !defined(DUK_LOG)
#define DUK_LOG log
+#endif
+#if !defined(DUK_SQRT)
#define DUK_SQRT sqrt
+#endif
/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,
* see test-bug-netbsd-math-pow.js. Use NetBSD specific workaround.
@@ -1709,7 +2173,7 @@ extern double duk_computed_nan;
* The problem goes away by adding 'volatile' to the datetime computations.
* Not sure what the actual triggering conditions are, but using this on
* non-C99 systems solves the known issues and has relatively little cost
- * on other platforms. See bugs/issue-2e9d9c2d761dabaf8136c0897b91a270d1a47147.yaml.
+ * on other platforms.
*/
#undef DUK_USE_PARANOID_DATE_COMPUTATION
#if !defined(DUK_F_C99)
@@ -1717,125 +2181,182 @@ extern double duk_computed_nan;
#endif
/*
- * ANSI C string/memory function wrapper defines to allow easier workarounds.
- * Also convenience macros like DUK_MEMZERO which may be mapped to existing
- * platform function to zero memory (like the deprecated bzero).
- *
- * For instance, some platforms don't support zero-size memcpy correctly,
- * some arcane uclibc versions have a buggy memcpy (but working memmove)
- * and so on. Such broken platforms can be dealt with here.
- *
- * NOTE: ANSI C (various versions) and some implementations require that the
- * pointer arguments to memset(), memcpy(), and memmove() be valid values
- * even when byte size is 0 (even a NULL pointer is considered invalid in
- * this context). Zero-size operations as such are allowed, as long as their
- * pointer arguments point to a valid memory area. The DUK_MEMSET(),
- * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:
- * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be
- * allowed. If these are not fulfilled, a macro wrapper is needed.
- *
- * http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
- * http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html
+ * Byte order and double memory layout detection
*
- * Not sure what's the required behavior when a pointer points just past the
- * end of a buffer, which often happens in practice (e.g. zero size memmoves).
- * For example, if allocation size is 3, the following pointer would not
- * technically point to a valid memory byte:
+ * Endianness detection is a major portability hassle because the macros
+ * and headers are not standardized. There's even variance across UNIX
+ * platforms. Even with "standard" headers, details like underscore count
+ * varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used
+ * (Crossbridge has a single underscore, for instance).
*
- * <-- alloc -->
- * | 0 | 1 | 2 | .....
- * ^-- p=3, points after last valid byte (2)
+ * The checks below are structured with this in mind: several approaches are
+ * used, and at the end we check if any of them worked. This allows generic
+ * approaches to be tried first, and platform/compiler specific hacks tried
+ * last. As a last resort, the user can force a specific endianness, as it's
+ * not likely that automatic detection will work on the most exotic platforms.
*
- * If this is a practical issue, wrappers are again needed.
- */
-
-typedef FILE duk_file;
-#define DUK_STDIN stdin
-#define DUK_STDOUT stdout
-#define DUK_STDERR stderr
-
-/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h
- * (which is unfortunately named).
+ * Duktape supports little and big endian machines. There's also support
+ * for a hybrid used by some ARM machines where integers are little endian
+ * but IEEE double values use a mixed order (12345678 -> 43218765). This
+ * byte order for doubles is referred to as "mixed endian".
*/
-#define DUK_ANSI_MALLOC malloc
-#define DUK_ANSI_REALLOC realloc
-#define DUK_ANSI_CALLOC calloc
-#define DUK_ANSI_FREE free
-/* Old uclibcs have a broken memcpy so use memmove instead (this is overly
- * wide now on purpose):
- * http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html
+/* For custom platforms allow user to define byteorder explicitly.
+ * Since endianness headers are not standardized, this is a useful
+ * workaround for custom platforms for which endianness detection
+ * is not directly supported. Perhaps custom hardware is used and
+ * user cannot submit upstream patches.
*/
-#if defined(DUK_F_UCLIBC)
-#define DUK_MEMCPY memmove
+#if defined(DUK_OPT_FORCE_BYTEORDER)
+#undef DUK_USE_BYTEORDER
+#if (DUK_OPT_FORCE_BYTEORDER == 1)
+#define DUK_USE_BYTEORDER 1
+#elif (DUK_OPT_FORCE_BYTEORDER == 2)
+#define DUK_USE_BYTEORDER 2
+#elif (DUK_OPT_FORCE_BYTEORDER == 3)
+#define DUK_USE_BYTEORDER 3
#else
-#define DUK_MEMCPY memcpy
+#error invalid DUK_OPT_FORCE_BYTEORDER value
#endif
+#endif /* DUK_OPT_FORCE_BYTEORDER */
-#define DUK_MEMMOVE memmove
-#define DUK_MEMCMP memcmp
-#define DUK_MEMSET memset
-#define DUK_STRLEN strlen
-#define DUK_STRCMP strcmp
-#define DUK_STRNCMP strncmp
-#define DUK_PRINTF printf
-#define DUK_FPRINTF fprintf
-#define DUK_SPRINTF sprintf
+/* GCC and Clang provide endianness defines as built-in predefines, with
+ * leading and trailing double underscores (e.g. __BYTE_ORDER__). See
+ * output of "make gccpredefs" and "make clangpredefs". Clang doesn't
+ * seem to provide __FLOAT_WORD_ORDER__; assume not mixed endian for clang.
+ * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+ */
+#if !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__)
+#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
+#else
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif /* float word order */
+#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER__)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif /* float word order */
+#else
+/* Cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit
+ * integer ordering and is not relevant.
+ */
+#endif /* integer byte order */
+#endif /* !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) */
-#if defined(DUK_F_MSVC)
-/* _snprintf() does NOT NUL terminate on truncation, but Duktape code never
- * assumes that.
- * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+/* More or less standard endianness predefines provided by header files.
+ * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER
+ * will be big endian, see: http://lists.mysql.com/internals/443.
+ * On some platforms some defines may be present with an empty value which
+ * causes comparisons to fail: https://github.com/svaarala/duktape/issues/453.
*/
-#define DUK_SNPRINTF _snprintf
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \
+ defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \
+ defined(__LITTLE_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \
+ defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+ defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 2
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 1
#else
-#define DUK_SNPRINTF snprintf
+/* Byte order is little endian but cannot determine IEEE double word order. */
+#endif /* float word order */
+#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \
+ defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \
+ defined(__BIG_ENDIAN__)
+#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \
+ defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)
+#define DUK_USE_BYTEORDER 3
+#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)
+/* Float word order not known, assume not a hybrid. */
+#define DUK_USE_BYTEORDER 3
+#else
+/* Byte order is big endian but cannot determine IEEE double word order. */
+#endif /* float word order */
+#else
+/* Cannot determine byte order. */
+#endif /* integer byte order */
+#endif /* !defined(DUK_USE_BYTEORDER) */
+
+/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:
+ * $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ * 67:#define __LITTLEENDIAN__ 1
+ * $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ * 81:#define __BIGENDIAN__ 1
+ * $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian
+ * 70:#define __LITTLEENDIAN__ 1
+ */
+#if !defined(DUK_USE_BYTEORDER)
+#if defined(__LITTLEENDIAN__)
+#define DUK_USE_BYTEORDER 1
+#elif defined(__BIGENDIAN__)
+#define DUK_USE_BYTEORDER 3
+#endif
#endif
-#define DUK_VSPRINTF vsprintf
+/*
+ * Alignment requirement and support for unaligned accesses
+ *
+ * Assume unaligned accesses are not supported unless specifically allowed
+ * in the target platform. Some platforms may support unaligned accesses
+ * but alignment to 4 or 8 may still be desirable.
+ */
-#if defined(DUK_F_MSVC)
-#if (_MSC_VER < 1600)
-/* Older MSVC version are missing vsnprintf() but have _vsnprintf(). */
-#define DUK_VSNPRINTF _vsnprintf
-#else
-#define DUK_VSNPRINTF vsnprintf
+/* If not provided, use safe default for alignment. */
+#if !defined(DUK_USE_ALIGN_BY)
+#define DUK_USE_ALIGN_BY 8
#endif
-#else
-#define DUK_VSNPRINTF vsnprintf
-#endif /* DUK_F_MSVC */
-#define DUK_SSCANF sscanf
-#define DUK_VSSCANF vsscanf
-#define DUK_FOPEN fopen
-#define DUK_FCLOSE fclose
-#define DUK_FREAD fread
-#define DUK_FWRITE fwrite
-#define DUK_FSEEK fseek
-#define DUK_FTELL ftell
-#define DUK_FFLUSH fflush
-#define DUK_FPUTC fputc
-
-#define DUK_MEMZERO(p,n) \
- DUK_MEMSET((p), 0, (n))
+/* User forced alignment to 4 or 8. */
+#if defined(DUK_OPT_FORCE_ALIGN)
+#undef DUK_USE_ALIGN_BY
+#if (DUK_OPT_FORCE_ALIGN == 4)
+#define DUK_USE_ALIGN_BY 4
+#elif (DUK_OPT_FORCE_ALIGN == 8)
+#define DUK_USE_ALIGN_BY 8
+#else
+#error invalid DUK_OPT_FORCE_ALIGN value
+#endif
+#endif
-/*
- * Vararg macro wrappers. We need va_copy() which is defined in C99 / C++11,
- * so an awkward replacement is needed for pre-C99 / pre-C++11 environments.
- * This will quite likely need portability hacks for some non-C99 environments.
+/* Compiler specific hackery needed to force struct size to match aligment,
+ * see e.g. duk_hbuffer.h.
+ *
+ * http://stackoverflow.com/questions/11130109/c-struct-size-alignment
+ * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment
*/
+#if !(defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_GCC_ATTR) || \
+ defined(DUK_USE_PACK_CLANG_ATTR) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
+#endif
+#if !defined(DUK_VA_COPY)
+/* We need va_copy() which is defined in C99 / C++11, so an awkward
+ * replacement is needed for pre-C99 / pre-C++11 environments. This
+ * will quite likely need portability hacks for some non-C99
+ * environments.
+ */
#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
/* C99 / C++11 and above: rely on va_copy() which is required.
* Omit parenthesis on macro right side on purpose to minimize differences
* to direct use.
*/
#define DUK_VA_COPY(dest,src) va_copy(dest,src)
-#elif defined(DUK_F_GCC) || defined(DUK_F_CLANG)
-/* GCC: assume we have __va_copy() in non-C99 mode, which should be correct
- * for even quite old GCC versions. Clang matches GCC behavior.
- */
-#define DUK_VA_COPY(dest,src) __va_copy(dest,src)
#else
/* Pre-C99: va_list type is implementation dependent. This replacement
* assumes it is a plain value so that a simple assignment will work.
@@ -1844,156 +2365,48 @@ typedef FILE duk_file;
*/
#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0)
#endif
+#endif
-/*
- * Miscellaneous ANSI C or other platform wrappers.
- */
-
-#define DUK_ABORT abort
-#define DUK_EXIT exit
-
-/*
- * Avoiding platform function pointers.
- *
- * On some platforms built-in functions may be implemented as macros or
- * inline functions, so they can't be necessarily addressed by function
- * pointers. This is certainly the case with some platform "polyfills"
- * which provide missing C99/C++11 functions through macros, and may be
- * the case with VS2013 (see GH-17).
- */
-
-/* This is now the default: the cost in footprint is negligible. */
-#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
-
-/*
- * Macro hackery to convert e.g. __LINE__ to a string without formatting,
- * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
- */
-
-#define DUK_F_STRINGIFY_HELPER(x) #x
-#define DUK_MACRO_STRINGIFY(x) DUK_F_STRINGIFY_HELPER(x)
-
-/*
- * Cause segfault macro.
- *
- * This is optionally used by panic handling to cause the program to segfault
- * (instead of e.g. abort()) on panic. Valgrind will then indicate the C
- * call stack leading to the panic.
- */
-
-#define DUK_CAUSE_SEGFAULT() do { \
- *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; \
- } while (0)
-
-/*
- * Macro for suppressing warnings for potentially unreferenced variables.
- * The variables can be actually unreferenced or unreferenced in some
- * specific cases only; for instance, if a variable is only debug printed,
- * it is unreferenced when debug printing is disabled.
- *
- * (Introduced here because it's potentially compiler specific.)
- */
-
-#define DUK_UNREF(x) do { \
- (void) (x); \
- } while (0)
-
-/*
- * DUK_NORETURN: macro for declaring a 'noreturn' function.
- * Unfortunately the noreturn declaration may appear in various
- * places of a function declaration, so the solution is to wrap
- * the entire declaration inside the macro. Compiler support
- * for using a noreturn declaration on function pointers varies;
- * this macro must only be used for actual function declarations.
- *
- * http://gcc.gnu.org/onlinedocs/gcc-4.3.2//gcc/Function-Attributes.html
- * http://clang.llvm.org/docs/LanguageExtensions.html
+#if !defined(DUK_MACRO_STRINGIFY)
+/* Macro hackery to convert e.g. __LINE__ to a string without formatting,
+ * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
*/
+#define DUK_MACRO_STRINGIFY_HELPER(x) #x
+#define DUK_MACRO_STRINGIFY(x) DUK_MACRO_STRINGIFY_HELPER(x)
+#endif
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)
-/* since gcc-2.5 */
-#define DUK_NORETURN(decl) decl __attribute__((noreturn))
-#elif defined(__clang__)
-/* syntax same as gcc */
-#define DUK_NORETURN(decl) decl __attribute__((noreturn))
-#elif defined(DUK_F_MSVC)
-/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */
-#define DUK_NORETURN(decl) __declspec(noreturn) decl
-#else
-/* Don't know how to declare a noreturn function, so don't do it; this
- * may cause some spurious compilation warnings (e.g. "variable used
- * uninitialized").
+#if !defined(DUK_CAUSE_SEGFAULT)
+/* This is optionally used by panic handling to cause the program to segfault
+ * (instead of e.g. abort()) on panic. Valgrind will then indicate the C
+ * call stack leading to the panic.
*/
-#define DUK_NORETURN(decl) decl
+#define DUK_CAUSE_SEGFAULT() do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0)
#endif
-
-/*
- * Macro for stating that a certain line cannot be reached.
- *
- * http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Other-Builtins.html#Other-Builtins
- * http://clang.llvm.org/docs/LanguageExtensions.html
+#if !defined(DUK_UNREF)
+/* Macro for suppressing warnings for potentially unreferenced variables.
+ * The variables can be actually unreferenced or unreferenced in some
+ * specific cases only; for instance, if a variable is only debug printed,
+ * it is unreferenced when debug printing is disabled.
*/
-
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
-/* since gcc-4.5 */
-#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while(0)
-#elif defined(__clang__) && defined(__has_builtin)
-#if __has_builtin(__builtin_unreachable)
-/* same as gcc */
-#define DUK_UNREACHABLE() do { __builtin_unreachable(); } while(0)
+#define DUK_UNREF(x) do { (void) (x); } while (0)
#endif
-#else
-/* unknown */
+#if !defined(DUK_NORETURN)
+#define DUK_NORETURN(decl) decl
#endif
-
#if !defined(DUK_UNREACHABLE)
/* Don't know how to declare unreachable point, so don't do it; this
* may cause some spurious compilation warnings (e.g. "variable used
* uninitialized").
*/
-#define DUK_UNREACHABLE() /* unreachable */
+#define DUK_UNREACHABLE() do { } while (0)
#endif
-
-/*
- * Likely and unlikely branches. Using these is not at all a clear cut case,
- * so the selection is a two-step process: (1) DUK_USE_BRANCH_HINTS is set
- * if the architecture, compiler etc make it useful to use the hints, and (2)
- * a separate check determines how to do them.
- *
- * These macros expect the argument to be a relational expression with an
- * integer value. If used with pointers, you should use an explicit check
- * like:
- *
- * if (DUK_LIKELY(ptr != NULL)) { ... }
- *
- * instead of:
- *
- * if (DUK_LIKELY(ptr)) { ... }
- *
- * http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html (__builtin_expect)
- */
-
-/* pretty much a placeholder now */
-#if defined(DUK_F_GCC)
-#define DUK_USE_BRANCH_HINTS
-#elif defined(DUK_F_CLANG)
-#define DUK_USE_BRANCH_HINTS
-#else
-#undef DUK_USE_BRANCH_HINTS
-#endif
-
-#if defined(DUK_USE_BRANCH_HINTS)
-#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)
-/* GCC: test not very accurate; enable only in relatively recent builds
- * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
+#if !defined(DUK_LOSE_CONST)
+/* Convert any input pointer into a "void *", losing a const qualifier.
+ * This is not fully portable because casting through duk_uintptr_t may
+ * not work on all architectures (e.g. those with long, segmented pointers).
*/
-#define DUK_LIKELY(x) __builtin_expect((x), 1)
-#define DUK_UNLIKELY(x) __builtin_expect((x), 0)
-#elif defined(DUK_F_CLANG)
-#define DUK_LIKELY(x) __builtin_expect((x), 1)
-#define DUK_UNLIKELY(x) __builtin_expect((x), 0)
+#define DUK_LOSE_CONST(src) ((void *) (duk_uintptr_t) (src))
#endif
-#endif /* DUK_USE_BRANCH_HINTS */
#if !defined(DUK_LIKELY)
#define DUK_LIKELY(x) (x)
@@ -2002,1041 +2415,957 @@ typedef FILE duk_file;
#define DUK_UNLIKELY(x) (x)
#endif
-/*
- * Function inlining control
- *
- * DUK_NOINLINE: avoid inlining a function.
- * DUK_INLINE: suggest inlining a function.
- * DUK_ALWAYS_INLINE: force inlining for critical functions.
- *
- * Apply to function definition only (not declaration).
- */
-
-#if defined(DUK_F_CLANG) && (defined(DUK_F_C99) || defined(DUK_F_CPP11))
-#define DUK_NOINLINE __attribute__((noinline))
-#define DUK_INLINE inline
-#define DUK_ALWAYS_INLINE inline __attribute__((always_inline))
-#elif defined(DUK_F_GCC) && defined(DUK_F_GCC_VERSION) && (defined(DUK_F_C99) || defined(DUK_F_CPP11))
-#if (DUK_F_GCC_VERSION >= 30101)
-#define DUK_NOINLINE __attribute__((noinline))
-#define DUK_INLINE inline
-#define DUK_ALWAYS_INLINE inline __attribute__((always_inline))
-#endif
-#endif
-
#if !defined(DUK_NOINLINE)
#define DUK_NOINLINE /*nop*/
-#define DUK_INLINE /*nop*/
-#define DUK_ALWAYS_INLINE /*nop*/
#endif
-
-/* Temporary workaround for GH-323: avoid inlining control when
- * compiling from multiple sources, as it causes compiler trouble.
- */
-#if !defined(DUK_SINGLE_FILE)
-#undef DUK_NOINLINE
-#undef DUK_INLINE
-#undef DUK_ALWAYS_INLINE
-#define DUK_NOINLINE /*nop*/
+#if !defined(DUK_INLINE)
#define DUK_INLINE /*nop*/
+#endif
+#if !defined(DUK_ALWAYS_INLINE)
#define DUK_ALWAYS_INLINE /*nop*/
#endif
-/*
- * Symbol visibility macros
- *
- * To avoid C++ declaration issues (see GH-63):
- *
- * - Don't use DUK_LOCAL_DECL for local -data symbols- so that you don't
- * end up with both a "static" declaration and a definition.
- *
- * - Wrap any DUK_INTERNAL_DECL with a '#if !defined(DUK_SINGLE_FILE)'
- * so that the internal declarations (which would map to "static" in
- * a single file distribution) get dropped.
- */
-
-/* XXX: user override for these? user override for just using the default visibility macros? */
-/* XXX: separate macros for function and data may be necessary at some point. */
-
-#if defined(DUK_F_GCC_VERSION)
-#if (DUK_F_GCC_VERSION >= 40000) && !(defined(DUK_F_MINGW) || defined(DUK_F_CYGWIN))
-/* Might work on earlier versions too but limit to GCC 4+.
- * MinGW should use Windows specific __declspec or no visibility attributes at all,
- * otherwise: "warning: visibility attribute not supported in this configuration; ignored".
- * Same applies to Cygwin GCC.
- */
-#define DUK_F_GCC_SYMBOL_VISIBILITY
-#endif
-#endif
-#if defined(DUK_F_CLANG) && !defined(DUK_F_GCC_SYMBOL_VISIBILITY)
-#define DUK_F_GCC_SYMBOL_VISIBILITY
+#if !defined(DUK_EXTERNAL_DECL)
+#define DUK_EXTERNAL_DECL extern
#endif
-#if defined(DUK_OPT_DLL_BUILD) && defined(_WIN32) && (defined(_MSC_VER) || defined(__GNUC__))
-/* __declspec(dllexport) and __declspec(dllimport) only for Windows DLL build.
- * MSVC: any minimum version?
- * MinGW: no minimum version, even gcc-2.95.3 supported dllimport/dllexport.
-*/
-#define DUK_F_MSVC_DLL_SYMBOL_VISIBILITY
+#if !defined(DUK_EXTERNAL)
+#define DUK_EXTERNAL /*empty*/
#endif
-
-#if defined(DUK_F_GCC_SYMBOL_VISIBILITY)
-/* GCC 4+ visibility attributes. */
-#define DUK_EXTERNAL_DECL __attribute__ ((visibility("default"))) extern
-#define DUK_EXTERNAL __attribute__ ((visibility("default")))
+#if !defined(DUK_INTERNAL_DECL)
#if defined(DUK_SINGLE_FILE)
#define DUK_INTERNAL_DECL static
-#define DUK_INTERNAL static
#else
-#define DUK_INTERNAL_DECL __attribute__ ((visibility("hidden"))) extern
-#define DUK_INTERNAL __attribute__ ((visibility("hidden")))
+#define DUK_INTERNAL_DECL extern
#endif
-#elif defined(DUK_F_MSVC_DLL_SYMBOL_VISIBILITY)
-/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're
- * compiling Duktape or the application.
- */
-#if defined(DUK_COMPILING_DUKTAPE)
-#define DUK_EXTERNAL_DECL extern __declspec(dllexport)
-#define DUK_EXTERNAL __declspec(dllexport)
-#else
-#define DUK_EXTERNAL_DECL extern __declspec(dllimport)
-#define DUK_EXTERNAL should_not_happen
#endif
+#if !defined(DUK_INTERNAL)
#if defined(DUK_SINGLE_FILE)
-#define DUK_INTERNAL_DECL static
#define DUK_INTERNAL static
#else
-#define DUK_INTERNAL_DECL extern
#define DUK_INTERNAL /*empty*/
#endif
-#else
-/* Default visibility. */
-#define DUK_EXTERNAL_DECL extern
-#define DUK_EXTERNAL /*empty*/
-#if defined(DUK_SINGLE_FILE)
-#define DUK_INTERNAL_DECL static
-#define DUK_INTERNAL static
-#else /* DUK_SINGLE_FILE */
-#define DUK_INTERNAL_DECL extern
-#define DUK_INTERNAL /*empty*/
#endif
-#endif
-
-/* For now, these are shared. */
+#if !defined(DUK_LOCAL_DECL)
#define DUK_LOCAL_DECL static
+#endif
+#if !defined(DUK_LOCAL)
#define DUK_LOCAL static
+#endif
-/*
- * __FILE__, __LINE__, __func__ are wrapped. Especially __func__ is a
- * problem because it is not available even in some compilers which try
- * to be C99 compatible (e.g. VBCC with -c99 option).
- */
-
+#if !defined(DUK_FILE_MACRO)
#define DUK_FILE_MACRO __FILE__
-
+#endif
+#if !defined(DUK_LINE_MACRO)
#define DUK_LINE_MACRO __LINE__
-
-#if !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC)
+#endif
+#if !defined(DUK_FUNC_MACRO)
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
#define DUK_FUNC_MACRO __func__
+#elif defined(__FUNCTION__)
+#define DUK_FUNC_MACRO __FUNCTION__
#else
#define DUK_FUNC_MACRO "unknown"
#endif
+#endif
-/*
- * Byteswap macros
- *
- * These are here so that inline assembly or other platform functions can be
- * used if available.
- */
-
+#if !defined(DUK_BSWAP32)
#define DUK_BSWAP32(x) \
((((duk_uint32_t) (x)) >> 24) | \
((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \
((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \
(((duk_uint32_t) (x)) << 24))
-
+#endif
+#if !defined(DUK_BSWAP16)
#define DUK_BSWAP16(x) \
((duk_uint16_t) (x) >> 8) | \
((duk_uint16_t) (x) << 8)
-
-/*
- * Architecture string, human readable value exposed in Duktape.env
- */
-
-#if defined(DUK_F_X86)
-#define DUK_USE_ARCH_STRING "x86"
-#elif defined(DUK_F_X32)
-#define DUK_USE_ARCH_STRING "x32"
-#elif defined(DUK_F_X64)
-#define DUK_USE_ARCH_STRING "x64"
-#elif defined(DUK_F_ARM)
-#define DUK_USE_ARCH_STRING "arm"
-#elif defined(DUK_F_MIPS32)
-#define DUK_USE_ARCH_STRING "mips32"
-#elif defined(DUK_F_MIPS64)
-#define DUK_USE_ARCH_STRING "mips64"
-#elif defined(DUK_F_SUPERH)
-#define DUK_USE_ARCH_STRING "sh"
-#elif defined(DUK_F_PPC)
-#define DUK_USE_ARCH_STRING "ppc"
-#elif defined(DUK_F_M68K)
-#define DUK_USE_ARCH_STRING "m68k"
-#elif defined(DUK_F_FLASHPLAYER)
-#define DUK_USE_ARCH_STRING "flashplayer"
-#elif defined(DUK_F_EMSCRIPTEN)
-#define DUK_USE_ARCH_STRING "emscripten"
-#else
-#define DUK_USE_ARCH_STRING "unknown"
#endif
-/*
- * OS string, human readable value exposed in Duktape.env
- */
+/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */
+#if !defined(DUK_F_VARIADIC_MACROS_PROVIDED)
+#undef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_F_C99) || defined(DUK_F_CPP11)
+#define DUK_USE_VARIADIC_MACROS
+#endif
+#endif
-#if defined(DUK_F_LINUX)
-#define DUK_USE_OS_STRING "linux"
-#elif defined(__APPLE__)
-/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */
-#if TARGET_IPHONE_SIMULATOR
-#define DUK_USE_OS_STRING "iphone-sim"
-#elif TARGET_OS_IPHONE
-#define DUK_USE_OS_STRING "iphone"
-#elif TARGET_OS_MAC
-#define DUK_USE_OS_STRING "ios"
+#if !(defined(DUK_USE_FLEX_C99) || defined(DUK_USE_FLEX_ZEROSIZE) || defined(DUK_USE_FLEX_ONESIZE))
+#if defined(DUK_F_C99)
+#define DUK_USE_FLEX_C99
#else
-#define DUK_USE_OS_STRING "ios-unknown"
+#define DUK_USE_FLEX_ZEROSIZE /* Not standard but common enough */
#endif
-#elif defined(DUK_F_FREEBSD)
-#define DUK_USE_OS_STRING "freebsd"
-#elif defined(DUK_F_OPENBSD)
-#define DUK_USE_OS_STRING "openbsd"
-#elif defined(DUK_F_NETBSD)
-#define DUK_USE_OS_STRING "netbsd"
-#elif defined(DUK_F_BSD)
-#define DUK_USE_OS_STRING "bsd"
-#elif defined(DUK_F_UNIX)
-#define DUK_USE_OS_STRING "unix"
-#elif defined(DUK_F_WINDOWS)
-#define DUK_USE_OS_STRING "windows"
-#elif defined(DUK_F_TOS)
-#define DUK_USE_OS_STRING "tos"
-#elif defined(DUK_F_AMIGAOS)
-#define DUK_USE_OS_STRING "amigaos"
-#elif defined(DUK_F_QNX)
-#define DUK_USE_OS_STRING "qnx"
-#elif defined(DUK_F_TINSPIRE)
-#define DUK_USE_OS_STRING "tinspire"
-#else
-#define DUK_USE_OS_STRING "unknown"
#endif
-/*
- * Compiler string, human readable value exposed in Duktape.env
- */
-
-#if defined(DUK_F_MINGW)
-#define DUK_USE_COMPILER_STRING "mingw"
-#elif defined(DUK_F_GCC)
-#if defined(DUK_F_CPP)
-#define DUK_USE_COMPILER_STRING "g++"
-#else
-#define DUK_USE_COMPILER_STRING "gcc"
+#if !(defined(DUK_USE_PACK_GCC_ATTR) || defined(DUK_USE_PACK_CLANG_ATTR) || \
+ defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_DUMMY_MEMBER))
+#define DUK_USE_PACK_DUMMY_MEMBER
#endif
-#elif defined(DUK_F_CLANG)
-#define DUK_USE_COMPILER_STRING "clang"
-#elif defined(DUK_F_MSVC)
-#define DUK_USE_COMPILER_STRING "msvc"
-#elif defined(DUK_F_VBCC)
-#define DUK_USE_COMPILER_STRING "vbcc"
-#else
-#define DUK_USE_COMPILER_STRING "unknown"
+
+#if 0 /* not defined by default */
+#undef DUK_USE_GCC_PRAGMAS
#endif
-/*
- * Target info string
+/* Workaround for GH-323: avoid inlining control when compiling from
+ * multiple sources, as it causes compiler portability trouble.
*/
-
-#if defined(DUK_OPT_TARGET_INFO)
-#define DUK_USE_TARGET_INFO DUK_OPT_TARGET_INFO
-#else
-#define DUK_USE_TARGET_INFO "unknown"
+#if !defined(DUK_SINGLE_FILE)
+#undef DUK_NOINLINE
+#undef DUK_INLINE
+#undef DUK_ALWAYS_INLINE
+#define DUK_NOINLINE /*nop*/
+#define DUK_INLINE /*nop*/
+#define DUK_ALWAYS_INLINE /*nop*/
#endif
/*
- * Long control transfer, setjmp/longjmp or alternatives
- *
- * Signal mask is not saved (when that can be communicated to the platform)
+ * Check whether or not a packed duk_tval representation is possible.
+ * What's basically required is that pointers are 32-bit values
+ * (sizeof(void *) == 4). Best effort check, not always accurate.
+ * If guess goes wrong, crashes may result; self tests also verify
+ * the guess.
*/
-/* dummy non-zero value to be used as an argument for longjmp(), see man longjmp */
-#define DUK_LONGJMP_DUMMY_VALUE 1
+/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */
+#if !defined(DUK_F_PACKED_TVAL_PROVIDED)
+#undef DUK_F_PACKED_TVAL_POSSIBLE
-#if defined(DUK_OPT_SETJMP)
-#define DUK_USE_SETJMP
-#elif defined(DUK_OPT_UNDERSCORE_SETJMP)
-#define DUK_USE_UNDERSCORE_SETJMP
-#elif defined(DUK_OPT_SIGSETJMP)
-#define DUK_USE_SIGSETJMP
-#elif defined(__APPLE__)
-/* Use _setjmp() on Apple by default, see GH-55. */
-#define DUK_USE_UNDERSCORE_SETJMP
-#else
-/* The most portable default is setjmp(). */
-#define DUK_USE_SETJMP
+/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
#endif
-#if defined(DUK_USE_UNDERSCORE_SETJMP)
-#define DUK_SETJMP(jb) _setjmp((jb))
-#define DUK_LONGJMP(jb) _longjmp((jb), DUK_LONGJMP_DUMMY_VALUE)
-#elif defined(DUK_USE_SIGSETJMP)
-#define DUK_SETJMP(jb) sigsetjmp((jb), 0 /*savesigs*/)
-#define DUK_LONGJMP(jb) siglongjmp((jb), DUK_LONGJMP_DUMMY_VALUE)
-#elif defined(DUK_USE_SETJMP)
-#define DUK_SETJMP(jb) setjmp((jb))
-#define DUK_LONGJMP(jb) longjmp((jb), DUK_LONGJMP_DUMMY_VALUE)
-#else
-#error internal error
+/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
+#if (DUK_UINTPTR_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
#endif
-/*
- * Speed/size and other performance options
- */
+/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */
+#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)
+#if (DUK_SIZE_MAX <= 0xffffffffUL)
+#define DUK_F_PACKED_TVAL_POSSIBLE
+#endif
+#endif
-/* Use fast ("inline") refcount operations instead of calling out to helpers
- * by default. The difference in binary size is small (~1kB on x64).
- */
-#define DUK_USE_FAST_REFCOUNT_DEFAULT
+#undef DUK_USE_PACKED_TVAL
+#if defined(DUK_F_PACKED_TVAL_POSSIBLE)
+#define DUK_USE_PACKED_TVAL
+#endif
-/* Assert for valstack space but don't check for it in non-assert build.
- * Valstack overruns (writing beyond checked space) is memory unsafe and
- * potentially a segfault. Produces a smaller and faster binary.
- * (In practice the speed difference is small with -O3 so default to
- * safer behavior for now.)
- */
-#undef DUK_USE_VALSTACK_UNSAFE
+#undef DUK_F_PACKED_TVAL_POSSIBLE
+#endif /* DUK_F_PACKED_TVAL_PROVIDED */
-/* Catch-all flag which can be used to choose between variant algorithms
- * where a speed-size tradeoff exists (e.g. lookup tables). When it really
- * matters, specific use flags may be appropriate.
+/* Feature option forcing. */
+#if defined(DUK_OPT_NO_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#elif defined(DUK_OPT_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#define DUK_USE_PACKED_TVAL
+#endif
+/* Object property allocation layout has implications for memory and code
+ * footprint and generated code size/speed. The best layout also depends
+ * on whether the platform has alignment requirements or benefits from
+ * having mostly aligned accesses.
*/
-#undef DUK_USE_PREFER_SIZE
-
-/* Use a sliding window for lexer; slightly larger footprint, slightly faster. */
-#define DUK_USE_LEXER_SLIDING_WINDOW
+#undef DUK_USE_HOBJECT_LAYOUT_1
+#undef DUK_USE_HOBJECT_LAYOUT_2
+#undef DUK_USE_HOBJECT_LAYOUT_3
+#if (DUK_USE_ALIGN_BY == 1)
+/* On platforms without any alignment issues, layout 1 is preferable
+ * because it compiles to slightly less code and provides direct access
+ * to property keys.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_1
+#else
+/* On other platforms use layout 2, which requires some padding but
+ * is a bit more natural than layout 3 in ordering the entries. Layout
+ * 3 is currently not used.
+ */
+#define DUK_USE_HOBJECT_LAYOUT_2
+#endif
-/* Transparent JSON.stringify() fastpath. */
-#undef DUK_USE_JSON_STRINGIFY_FASTPATH
-#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH)
-#define DUK_USE_JSON_STRINGIFY_FASTPATH
+/* GCC/clang inaccurate math would break compliance and probably duk_tval,
+ * so refuse to compile. Relax this if -ffast-math is tested to work.
+ */
+#if defined(__FAST_MATH__)
+#error __FAST_MATH__ defined, refusing to compile
#endif
/*
- * Tagged type representation (duk_tval)
+ * Feature option handling
*/
-#undef DUK_USE_PACKED_TVAL
-#undef DUK_USE_FULL_TVAL
-
-#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && !defined(DUK_OPT_NO_PACKED_TVAL)
-#define DUK_USE_PACKED_TVAL
+#if !defined(DUK_USE_ALIGN_BY)
+#if defined(DUK_OPT_FORCE_ALIGN)
+#define DUK_USE_ALIGN_BY DUK_OPT_FORCE_ALIGN
+#else
+#define DUK_USE_ALIGN_BY 8
+#endif
#endif
-/* Support for 48-bit signed integer duk_tval with transparent semantics. */
-#undef DUK_USE_FASTINT
-#if defined(DUK_OPT_FASTINT)
-#if !defined(DUK_F_HAVE_64BIT)
-#error DUK_OPT_FASTINT requires 64-bit integer type support at the moment
+#if defined(DUK_OPT_ASSERTIONS)
+#define DUK_USE_ASSERTIONS
+#elif defined(DUK_OPT_NO_ASSERTIONS)
+#undef DUK_USE_ASSERTIONS
+#else
+#undef DUK_USE_ASSERTIONS
#endif
-#define DUK_USE_FASTINT
+
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_AUGMENT_ERROR_CREATE
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_AUGMENT_ERROR_CREATE
+#else
+#define DUK_USE_AUGMENT_ERROR_CREATE
#endif
-/*
- * Memory management options
- */
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_AUGMENT_ERROR_THROW
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_AUGMENT_ERROR_THROW
+#else
+#define DUK_USE_AUGMENT_ERROR_THROW
+#endif
-#define DUK_USE_REFERENCE_COUNTING
-#define DUK_USE_DOUBLE_LINKED_HEAP
-#define DUK_USE_MARK_AND_SWEEP
-#define DUK_USE_MS_STRINGTABLE_RESIZE
+#if defined(DUK_OPT_BROWSER_LIKE)
+#define DUK_USE_BROWSER_LIKE
+#elif defined(DUK_OPT_NO_BROWSER_LIKE)
+#undef DUK_USE_BROWSER_LIKE
+#else
+#define DUK_USE_BROWSER_LIKE
+#endif
-#if defined(DUK_OPT_NO_REFERENCE_COUNTING)
-#undef DUK_USE_REFERENCE_COUNTING
-#undef DUK_USE_DOUBLE_LINKED_HEAP
-/* XXX: undef DUK_USE_MS_STRINGTABLE_RESIZE as it is more expensive
- * with more frequent mark-and-sweeps?
- */
+#if defined(DUK_OPT_BUFFEROBJECT_SUPPORT)
+#define DUK_USE_BUFFEROBJECT_SUPPORT
+#elif defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT)
+#undef DUK_USE_BUFFEROBJECT_SUPPORT
+#else
+#define DUK_USE_BUFFEROBJECT_SUPPORT
#endif
-#if defined(DUK_OPT_NO_MARK_AND_SWEEP)
-#undef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_OPT_BUFLEN16)
+#define DUK_USE_BUFLEN16
+#elif defined(DUK_OPT_NO_BUFLEN16)
+#undef DUK_USE_BUFLEN16
+#else
+#undef DUK_USE_BUFLEN16
#endif
-#if defined(DUK_USE_MARK_AND_SWEEP)
-#define DUK_USE_VOLUNTARY_GC
-#if defined(DUK_OPT_NO_VOLUNTARY_GC)
-#undef DUK_USE_VOLUNTARY_GC
+#if defined(DUK_OPT_BYTECODE_DUMP_SUPPORT)
+#define DUK_USE_BYTECODE_DUMP_SUPPORT
+#elif defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT)
+#undef DUK_USE_BYTECODE_DUMP_SUPPORT
+#else
+#define DUK_USE_BYTECODE_DUMP_SUPPORT
#endif
+
+#if defined(DUK_OPT_COMMONJS_MODULES)
+#define DUK_USE_COMMONJS_MODULES
+#elif defined(DUK_OPT_NO_COMMONJS_MODULES)
+#undef DUK_USE_COMMONJS_MODULES
+#else
+#define DUK_USE_COMMONJS_MODULES
#endif
-#if !defined(DUK_USE_MARK_AND_SWEEP) && !defined(DUK_USE_REFERENCE_COUNTING)
-#error must have either mark-and-sweep or reference counting enabled
+#if defined(DUK_OPT_DATAPTR16)
+#define DUK_USE_DATAPTR16
+#elif defined(DUK_OPT_NO_DATAPTR16)
+#undef DUK_USE_DATAPTR16
+#else
+#undef DUK_USE_DATAPTR16
#endif
-#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)
-#undef DUK_USE_MS_STRINGTABLE_RESIZE
+#if defined(DUK_OPT_DATAPTR_DEC16)
+#define DUK_USE_DATAPTR_DEC16(udata,ptr) DUK_OPT_DATAPTR_DEC16((udata),(ptr))
+#else
+#undef DUK_USE_DATAPTR_DEC16
#endif
-#undef DUK_USE_GC_TORTURE
-#if defined(DUK_OPT_GC_TORTURE)
-#define DUK_USE_GC_TORTURE
+#if defined(DUK_OPT_DATAPTR_ENC16)
+#define DUK_USE_DATAPTR_ENC16(udata,ptr) DUK_OPT_DATAPTR_ENC16((udata),(ptr))
+#else
+#undef DUK_USE_DATAPTR_ENC16
#endif
-/*
- * String table options
- */
+#if defined(DUK_OPT_DDDPRINT)
+#define DUK_USE_DDDPRINT
+#elif defined(DUK_OPT_NO_DDDPRINT)
+#undef DUK_USE_DDDPRINT
+#else
+#undef DUK_USE_DDDPRINT
+#endif
-#if defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE)
-/* Low memory algorithm: separate chaining using arrays, fixed size hash */
-#define DUK_USE_STRTAB_CHAIN
-#define DUK_USE_STRTAB_CHAIN_SIZE DUK_OPT_STRTAB_CHAIN_SIZE
+#if defined(DUK_OPT_DDPRINT)
+#define DUK_USE_DDPRINT
+#elif defined(DUK_OPT_NO_DDPRINT)
+#undef DUK_USE_DDPRINT
#else
-/* Default algorithm: open addressing (probing) */
-#define DUK_USE_STRTAB_PROBE
+#undef DUK_USE_DDPRINT
#endif
-/*
- * Error handling options
- */
+#if defined(DUK_OPT_DEBUG)
+#define DUK_USE_DEBUG
+#elif defined(DUK_OPT_NO_DEBUG)
+#undef DUK_USE_DEBUG
+#else
+#undef DUK_USE_DEBUG
+#endif
-#define DUK_USE_AUGMENT_ERROR_CREATE
-#define DUK_USE_AUGMENT_ERROR_THROW
-#define DUK_USE_TRACEBACKS
-#define DUK_USE_ERRCREATE
-#define DUK_USE_ERRTHROW
+#if defined(DUK_OPT_DEBUGGER_DUMPHEAP)
+#define DUK_USE_DEBUGGER_DUMPHEAP
+#elif defined(DUK_OPT_NO_DEBUGGER_DUMPHEAP)
+#undef DUK_USE_DEBUGGER_DUMPHEAP
+#else
+#undef DUK_USE_DEBUGGER_DUMPHEAP
+#endif
-#define DUK_USE_VERBOSE_ERRORS
+#if defined(DUK_OPT_DEBUGGER_FWD_LOGGING)
+#define DUK_USE_DEBUGGER_FWD_LOGGING
+#elif defined(DUK_OPT_NO_DEBUGGER_FWD_LOGGING)
+#undef DUK_USE_DEBUGGER_FWD_LOGGING
+#else
+#undef DUK_USE_DEBUGGER_FWD_LOGGING
+#endif
-#if defined(DUK_OPT_NO_AUGMENT_ERRORS)
-#undef DUK_USE_AUGMENT_ERROR_CREATE
-#undef DUK_USE_AUGMENT_ERROR_THROW
-#undef DUK_USE_TRACEBACKS
-#undef DUK_USE_ERRCREATE
-#undef DUK_USE_ERRTHROW
-#elif defined(DUK_OPT_NO_TRACEBACKS)
-#undef DUK_USE_TRACEBACKS
+#if defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT)
+#define DUK_USE_DEBUGGER_FWD_PRINTALERT
+#elif defined(DUK_OPT_NO_DEBUGGER_FWD_PRINTALERT)
+#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
+#else
+#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
#endif
-#if defined(DUK_OPT_NO_VERBOSE_ERRORS)
-#undef DUK_USE_VERBOSE_ERRORS
+#if defined(DUK_OPT_DEBUGGER_PAUSE_UNCAUGHT)
+#define DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#elif defined(DUK_OPT_NO_DEBUGGER_PAUSE_UNCAUGHT)
+#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#else
+#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
#endif
-#if defined(DUK_USE_TRACEBACKS)
-#if defined(DUK_OPT_TRACEBACK_DEPTH)
-#define DUK_USE_TRACEBACK_DEPTH DUK_OPT_TRACEBACK_DEPTH
+#if defined(DUK_OPT_DEBUGGER_SUPPORT)
+#define DUK_USE_DEBUGGER_SUPPORT
+#elif defined(DUK_OPT_NO_DEBUGGER_SUPPORT)
+#undef DUK_USE_DEBUGGER_SUPPORT
#else
-#define DUK_USE_TRACEBACK_DEPTH 10
+#undef DUK_USE_DEBUGGER_SUPPORT
#endif
+
+#if defined(DUK_OPT_DEBUGGER_THROW_NOTIFY)
+#define DUK_USE_DEBUGGER_THROW_NOTIFY
+#elif defined(DUK_OPT_NO_DEBUGGER_THROW_NOTIFY)
+#undef DUK_USE_DEBUGGER_THROW_NOTIFY
+#else
+#undef DUK_USE_DEBUGGER_THROW_NOTIFY
#endif
-/* Include messages in executor internal errors. */
-#define DUK_USE_VERBOSE_EXECUTOR_ERRORS
+#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE)
+#define DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#elif defined(DUK_OPT_NO_DEBUGGER_TRANSPORT_TORTURE)
+#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#else
+#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#endif
-/*
- * Execution and debugger options
- */
+#if defined(DUK_OPT_DEBUG_BUFSIZE)
+#define DUK_USE_DEBUG_BUFSIZE DUK_OPT_DEBUG_BUFSIZE
+#else
+#define DUK_USE_DEBUG_BUFSIZE 65536L
+#endif
-#undef DUK_USE_INTERRUPT_COUNTER
-#if defined(DUK_OPT_INTERRUPT_COUNTER)
-#define DUK_USE_INTERRUPT_COUNTER
+#if defined(DUK_OPT_REFERENCE_COUNTING)
+#define DUK_USE_DOUBLE_LINKED_HEAP
+#elif defined(DUK_OPT_NO_REFERENCE_COUNTING)
+#undef DUK_USE_DOUBLE_LINKED_HEAP
+#else
+#define DUK_USE_DOUBLE_LINKED_HEAP
#endif
-#undef DUK_USE_EXEC_TIMEOUT_CHECK
-#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK)
-#define DUK_USE_EXEC_TIMEOUT_CHECK(udata) DUK_OPT_EXEC_TIMEOUT_CHECK((udata))
+#if defined(DUK_OPT_DPRINT)
+#define DUK_USE_DPRINT
+#elif defined(DUK_OPT_NO_DPRINT)
+#undef DUK_USE_DPRINT
+#else
+#undef DUK_USE_DPRINT
#endif
-#undef DUK_USE_DEBUGGER_SUPPORT
-#if defined(DUK_OPT_DEBUGGER_SUPPORT)
-#define DUK_USE_DEBUGGER_SUPPORT
+#if defined(DUK_OPT_DPRINT_COLORS)
+#define DUK_USE_DPRINT_COLORS
+#elif defined(DUK_OPT_NO_DPRINT_COLORS)
+#undef DUK_USE_DPRINT_COLORS
+#else
+#undef DUK_USE_DPRINT_COLORS
#endif
-#undef DUK_USE_DEBUGGER_FWD_PRINTALERT
-#if defined(DUK_OPT_DEBUGGER_SUPPORT) && defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT)
-#define DUK_USE_DEBUGGER_FWD_PRINTALERT
+#if defined(DUK_OPT_DPRINT_RDTSC)
+#define DUK_USE_DPRINT_RDTSC
+#elif defined(DUK_OPT_NO_DPRINT_RDTSC)
+#undef DUK_USE_DPRINT_RDTSC
+#else
+#undef DUK_USE_DPRINT_RDTSC
#endif
-#undef DUK_USE_DEBUGGER_FWD_LOGGING
-#if defined(DUK_OPT_DEBUGGER_SUPPORT) && defined(DUK_OPT_DEBUGGER_FWD_LOGGING)
-#define DUK_USE_DEBUGGER_FWD_LOGGING
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_ERRCREATE
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_ERRCREATE
+#else
+#define DUK_USE_ERRCREATE
#endif
-/* DumpHeap is optional because it's not always needed and has a relatively
- * large footprint.
- */
-#undef DUK_USE_DEBUGGER_DUMPHEAP
-#if defined(DUK_OPT_DEBUGGER_DUMPHEAP)
-#define DUK_USE_DEBUGGER_DUMPHEAP
+#if defined(DUK_OPT_AUGMENT_ERRORS)
+#define DUK_USE_ERRTHROW
+#elif defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_ERRTHROW
+#else
+#define DUK_USE_ERRTHROW
#endif
-#define DUK_USE_DEBUGGER_THROW_NOTIFY
-#if defined(DUK_OPT_NO_DEBUGGER_THROW_NOTIFY)
-#undef DUK_USE_DEBUGGER_THROW_NOTIFY
+#if defined(DUK_OPT_ES6_OBJECT_PROTO_PROPERTY)
+#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#elif defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)
+#undef DUK_USE_ES6_OBJECT_PROTO_PROPERTY
+#else
+#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
#endif
-#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
-#if defined(DUK_OPT_DEBUGGER_PAUSE_UNCAUGHT)
-#define DUK_USE_DEBUGGER_PAUSE_UNCAUGHT
+#if defined(DUK_OPT_ES6_OBJECT_SETPROTOTYPEOF)
+#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#elif defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)
+#undef DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
+#else
+#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
#endif
-/* Debugger transport read/write torture. */
-#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE
-#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE)
-#define DUK_USE_DEBUGGER_TRANSPORT_TORTURE
+#if defined(DUK_OPT_ES6_PROXY)
+#define DUK_USE_ES6_PROXY
+#elif defined(DUK_OPT_NO_ES6_PROXY)
+#undef DUK_USE_ES6_PROXY
+#else
+#define DUK_USE_ES6_PROXY
#endif
-/* For opcodes with indirect indices, check final index against stack size.
- * This should not be necessary because the compiler is trusted, and we don't
- * bound check non-indirect indices either.
- */
#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK
#if defined(DUK_OPT_DEBUG) || defined(DUK_OPT_ASSERTIONS)
/* Enabled with debug/assertions just so that any issues can be caught. */
#define DUK_USE_EXEC_INDIRECT_BOUND_CHECK
#endif
-/*
- * Debug printing and assertion options
- */
+#undef DUK_USE_EXEC_TIMEOUT_CHECK
+#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK)
+#define DUK_USE_EXEC_TIMEOUT_CHECK(udata) DUK_OPT_EXEC_TIMEOUT_CHECK((udata))
+#endif
-#undef DUK_USE_DEBUG
-#undef DUK_USE_DPRINT
-#undef DUK_USE_DDPRINT
-#undef DUK_USE_DDDPRINT
-#undef DUK_USE_DPRINT_RDTSC
-#undef DUK_USE_ASSERTIONS
+#undef DUK_USE_EXTSTR_FREE
+#if defined(DUK_OPT_EXTERNAL_STRINGS) && defined(DUK_OPT_EXTSTR_FREE)
+#define DUK_USE_EXTSTR_FREE(udata,ptr) DUK_OPT_EXTSTR_FREE((udata), (ptr))
+#endif
-/* Global debug enable. Compile must be clean on C99 regardless of whether or
- * not debugging is enabled. On non-C99 platforms compile should be clean with
- * debugging disabled but may produce warnings with debugging enabled (related
- * to debug macro hackery and such).
- */
-#if defined(DUK_OPT_DEBUG)
-#define DUK_USE_DEBUG
+#undef DUK_USE_EXTSTR_INTERN_CHECK
+#if defined(DUK_OPT_EXTERNAL_STRINGS) && defined(DUK_OPT_EXTSTR_INTERN_CHECK)
+#define DUK_USE_EXTSTR_INTERN_CHECK(udata,ptr,len) DUK_OPT_EXTSTR_INTERN_CHECK((udata), (ptr), (len))
#endif
-#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DPRINT)
-#define DUK_USE_DPRINT
+/* Support for 48-bit signed integer duk_tval with transparent semantics. */
+#undef DUK_USE_FASTINT
+#if defined(DUK_OPT_FASTINT)
+#if !defined(DUK_F_HAVE_64BIT)
+#error DUK_OPT_FASTINT requires 64-bit integer type support at the moment
#endif
-#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDPRINT)
-#define DUK_USE_DDPRINT
+#define DUK_USE_FASTINT
#endif
-#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDDPRINT)
-#define DUK_USE_DDDPRINT
+
+#if defined(DUK_OPT_FILE_IO)
+#define DUK_USE_FILE_IO
+#elif defined(DUK_OPT_NO_FILE_IO)
+#undef DUK_USE_FILE_IO
+#else
+#define DUK_USE_FILE_IO
#endif
-#undef DUK_USE_DPRINT_COLORS
-#if defined(DUK_OPT_DPRINT_COLORS)
-#define DUK_USE_DPRINT_COLORS
+#if defined(DUK_OPT_FUNCPTR16)
+#define DUK_USE_FUNCPTR16
+#elif defined(DUK_OPT_NO_FUNCPTR16)
+#undef DUK_USE_FUNCPTR16
+#else
+#undef DUK_USE_FUNCPTR16
#endif
-#if defined(DUK_USE_RDTSC) && defined(DUK_OPT_DPRINT_RDTSC)
-#define DUK_USE_DPRINT_RDTSC
+#if defined(DUK_OPT_FUNCPTR_DEC16)
+#define DUK_USE_FUNCPTR_DEC16(udata,ptr) DUK_OPT_FUNCPTR_DEC16((udata),(ptr))
#else
-#undef DUK_USE_DPRINT_RDTSC
+#undef DUK_USE_FUNCPTR_DEC16
#endif
-#if defined(DUK_OPT_ASSERTIONS)
-#define DUK_USE_ASSERTIONS
+#if defined(DUK_OPT_FUNCPTR_ENC16)
+#define DUK_USE_FUNCPTR_ENC16(udata,ptr) DUK_OPT_FUNCPTR_ENC16((udata),(ptr))
+#else
+#undef DUK_USE_FUNCPTR_ENC16
#endif
-/* The static buffer for debug printing is quite large by default, so there
- * is an option to shrink it manually for constrained builds.
- */
-#if defined(DUK_OPT_DEBUG_BUFSIZE)
-#define DUK_USE_DEBUG_BUFSIZE DUK_OPT_DEBUG_BUFSIZE
+#if defined(DUK_OPT_GC_TORTURE)
+#define DUK_USE_GC_TORTURE
+#elif defined(DUK_OPT_NO_GC_TORTURE)
+#undef DUK_USE_GC_TORTURE
#else
-#define DUK_USE_DEBUG_BUFSIZE 65536L
+#undef DUK_USE_GC_TORTURE
#endif
-/*
- * Ecmascript features / compliance options
- */
+#if defined(DUK_OPT_HEAPPTR16)
+#define DUK_USE_HEAPPTR16
+#elif defined(DUK_OPT_NO_HEAPPTR16)
+#undef DUK_USE_HEAPPTR16
+#else
+#undef DUK_USE_HEAPPTR16
+#endif
-#if defined(DUK_F_BCC)
-/* Math built-in is stubbed out on BCC to allow compiler torture testing. */
+#if defined(DUK_OPT_HEAPPTR_DEC16)
+#define DUK_USE_HEAPPTR_DEC16(udata,ptr) DUK_OPT_HEAPPTR_DEC16((udata),(ptr))
#else
-#define DUK_USE_MATH_BUILTIN
+#undef DUK_USE_HEAPPTR_DEC16
#endif
-#define DUK_USE_STRICT_DECL
-#if defined(DUK_OPT_NO_STRICT_DECL)
-#undef DUK_USE_STRICT_DECL
+#if defined(DUK_OPT_HEAPPTR_ENC16)
+#define DUK_USE_HEAPPTR_ENC16(udata,ptr) DUK_OPT_HEAPPTR_ENC16((udata),(ptr))
+#else
+#undef DUK_USE_HEAPPTR_ENC16
#endif
-#define DUK_USE_REGEXP_SUPPORT
-#if defined(DUK_OPT_NO_REGEXP_SUPPORT)
-#undef DUK_USE_REGEXP_SUPPORT
+/* For now, hash part is dropped if and only if 16-bit object fields are used. */
+#define DUK_USE_HOBJECT_HASH_PART
+#if defined(DUK_OPT_OBJSIZES16)
+#undef DUK_USE_HOBJECT_HASH_PART
#endif
-#undef DUK_USE_STRICT_UTF8_SOURCE
-#if defined(DUK_OPT_STRICT_UTF8_SOURCE)
-#define DUK_USE_STRICT_UTF8_SOURCE
+#if defined(DUK_OPT_EXTERNAL_STRINGS)
+#define DUK_USE_HSTRING_EXTDATA
+#elif defined(DUK_OPT_NO_EXTERNAL_STRINGS)
+#undef DUK_USE_HSTRING_EXTDATA
+#else
+#undef DUK_USE_HSTRING_EXTDATA
#endif
-#define DUK_USE_OCTAL_SUPPORT
-#if defined(DUK_OPT_NO_OCTAL_SUPPORT)
-#undef DUK_USE_OCTAL_SUPPORT
+#if defined(DUK_OPT_INTERRUPT_COUNTER)
+#define DUK_USE_INTERRUPT_COUNTER
+#elif defined(DUK_OPT_NO_INTERRUPT_COUNTER)
+#undef DUK_USE_INTERRUPT_COUNTER
+#else
+#undef DUK_USE_INTERRUPT_COUNTER
#endif
-#define DUK_USE_SOURCE_NONBMP
-#if defined(DUK_OPT_NO_SOURCE_NONBMP)
-#undef DUK_USE_SOURCE_NONBMP
+#if defined(DUK_OPT_JC)
+#define DUK_USE_JC
+#elif defined(DUK_OPT_NO_JC)
+#undef DUK_USE_JC
+#else
+#define DUK_USE_JC
#endif
-#define DUK_USE_BROWSER_LIKE
-#if defined(DUK_OPT_NO_BROWSER_LIKE)
-#undef DUK_USE_BROWSER_LIKE
+#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH)
+#define DUK_USE_JSON_STRINGIFY_FASTPATH
+#elif defined(DUK_OPT_NO_JSON_STRINGIFY_FASTPATH)
+#undef DUK_USE_JSON_STRINGIFY_FASTPATH
+#else
+#undef DUK_USE_JSON_STRINGIFY_FASTPATH
#endif
-/* E5/E5.1 Section B features. */
-#define DUK_USE_SECTION_B
-#if defined(DUK_OPT_NO_SECTION_B)
-#undef DUK_USE_SECTION_B
+#if defined(DUK_OPT_JX)
+#define DUK_USE_JX
+#elif defined(DUK_OPT_NO_JX)
+#undef DUK_USE_JX
+#else
+#define DUK_USE_JX
#endif
-/* Non-standard regexp parsing features. */
-#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#if defined(DUK_OPT_LIGHTFUNC_BUILTINS)
+#define DUK_USE_LIGHTFUNC_BUILTINS
+#elif defined(DUK_OPT_NO_LIGHTFUNC_BUILTINS)
+#undef DUK_USE_LIGHTFUNC_BUILTINS
+#else
+#undef DUK_USE_LIGHTFUNC_BUILTINS
+#endif
-/* Treat function statements (function declarations outside top level of
- * Program or FunctionBody) same as normal function declarations. This is
- * also V8 behavior. See test-dev-func-decl-outside-top.js.
- */
-#define DUK_USE_NONSTD_FUNC_STMT
-#if defined(DUK_OPT_NO_NONSTD_FUNC_STMT)
-#undef DUK_USE_NONSTD_FUNC_STMT
+#if defined(DUK_OPT_MARK_AND_SWEEP)
+#define DUK_USE_MARK_AND_SWEEP
+#elif defined(DUK_OPT_NO_MARK_AND_SWEEP)
+#undef DUK_USE_MARK_AND_SWEEP
+#else
+#define DUK_USE_MARK_AND_SWEEP
#endif
-/* Array.prototype.splice() non-standard but real world compatible behavior
- * when deleteCount is omitted.
- */
-#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
-#if defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)
-#undef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#if defined(DUK_OPT_MS_STRINGTABLE_RESIZE)
+#define DUK_USE_MS_STRINGTABLE_RESIZE
+#elif defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)
+#undef DUK_USE_MS_STRINGTABLE_RESIZE
+#else
+#define DUK_USE_MS_STRINGTABLE_RESIZE
#endif
-/* Array.prototype.concat() non-standard but real world compatible behavior
- * for non-existent trailing elements.
- */
+#if defined(DUK_OPT_NONSTD_ARRAY_CONCAT_TRAILER)
#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
-#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER)
+#elif defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER)
#undef DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
+#else
+#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER
#endif
-/* Array.prototype.map() non-standard but real world compatible behavior
- * for non-existent trailing elements.
- */
+#if defined(DUK_OPT_NONSTD_ARRAY_MAP_TRAILER)
#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
-#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER)
+#elif defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER)
#undef DUK_USE_NONSTD_ARRAY_MAP_TRAILER
+#else
+#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER
#endif
-/* Non-standard 'caller' property for function instances, see
- * test-bi-function-nonstd-caller-prop.js.
- */
-#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
-#define DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
-#endif
-
-/* Non-standard Object.prototype.__proto__ (ES6), see
- * test-bi-object-proto-__proto__.js.
- */
-#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY
-#if defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)
-#undef DUK_USE_ES6_OBJECT_PROTO_PROPERTY
-#endif
-
-/* Non-standard Object.setPrototypeOf (ES6), see
- * test-bi-object-setprototypeof.js.
- */
-#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
-#if defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)
-#undef DUK_USE_ES6_OBJECT_SETPROTOTYPEOF
-#endif
-
-/* ES6 Proxy object (subset for now). */
-#define DUK_USE_ES6_PROXY
-#if defined(DUK_OPT_NO_ES6_PROXY)
-#undef DUK_USE_ES6_PROXY
+#if defined(DUK_OPT_NONSTD_ARRAY_SPLICE_DELCOUNT)
+#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#elif defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)
+#undef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
+#else
+#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
#endif
-/* Record pc-to-line information. */
-#define DUK_USE_PC2LINE
-#if defined(DUK_OPT_NO_PC2LINE)
-#undef DUK_USE_PC2LINE
+#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
+#define DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#elif defined(DUK_OPT_NO_NONSTD_FUNC_CALLER_PROPERTY)
+#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
+#else
+#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
#endif
-/* Non-standard function 'source' property. */
-#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY)
#define DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#elif defined(DUK_OPT_NO_NONSTD_FUNC_SOURCE_PROPERTY)
+#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
+#else
+#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY
#endif
-/* CommonJS modules */
-#define DUK_USE_COMMONJS_MODULES
-#if defined(DUK_OPT_NO_COMMONJS_MODULES)
-#undef DUK_USE_COMMONJS_MODULES
+#if defined(DUK_OPT_NONSTD_FUNC_STMT)
+#define DUK_USE_NONSTD_FUNC_STMT
+#elif defined(DUK_OPT_NO_NONSTD_FUNC_STMT)
+#undef DUK_USE_NONSTD_FUNC_STMT
+#else
+#define DUK_USE_NONSTD_FUNC_STMT
#endif
-/* Additional key argument to setter/getter calls when triggered by property
- * accesses.
- */
-
+#if defined(DUK_OPT_NONSTD_ACCESSOR_KEY_ARGUMENT)
#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
-#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
-#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#elif defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
#undef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
-#undef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#else
+#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
#endif
-/* JSON escaping of U+2028 and U+2029.
- */
-
+#if defined(DUK_OPT_NONSTD_JSON_ESC_U2028_U2029)
#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029
-#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029)
+#elif defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029)
#undef DUK_USE_NONSTD_JSON_ESC_U2028_U2029
+#else
+#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029
#endif
-/* Allow 32-bit codepoints in String.fromCharCode. */
-#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
-#if defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT)
-#undef DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#if defined(DUK_OPT_NONSTD_REGEXP_DOLLAR_ESCAPE)
+#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#elif defined(DUK_OPT_NO_NONSTD_REGEXP_DOLLAR_ESCAPE)
+#undef DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
+#else
+#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
#endif
-/* Non-standard array fast path write behavior: when writing to numeric
- * indexes of an Array instance, assume Array.prototype doesn't have
- * conflicting properties (e.g. a non-writable property "7").
- */
-#define DUK_USE_NONSTD_ARRAY_WRITE
-#if defined(DUK_OPT_NO_NONSTD_ARRAY_WRITE)
-#undef DUK_USE_NONSTD_ARRAY_WRITE
+#if defined(DUK_OPT_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#elif defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)
+#undef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
+#else
+#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
#endif
-/* Node.js Buffer and Khronos/ES6 typed array support. */
-#define DUK_USE_BUFFEROBJECT_SUPPORT
-#if defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT)
-#undef DUK_USE_BUFFEROBJECT_SUPPORT
+#if defined(DUK_OPT_NONSTD_STRING_FROMCHARCODE_32BIT)
+#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#elif defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT)
+#undef DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
+#else
+#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT
#endif
-/*
- * Optional C API options
- */
-
-#define DUK_USE_BYTECODE_DUMP_SUPPORT
-#if defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT)
-#undef DUK_USE_BYTECODE_DUMP_SUPPORT
+#if defined(DUK_OPT_OBJSIZES16)
+#define DUK_USE_OBJSIZES16
+#elif defined(DUK_OPT_NO_OBJSIZES16)
+#undef DUK_USE_OBJSIZES16
+#else
+#undef DUK_USE_OBJSIZES16
#endif
-/*
- * Tailcalls
- */
-
-/* Tailcalls are enabled by default. The non-standard function 'caller'
- * property feature conflicts with tailcalls quite severely so tailcalls
- * are disabled if the 'caller' property is enabled.
- */
-#define DUK_USE_TAILCALL
-#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
-#undef DUK_USE_TAILCALL
+#if defined(DUK_OPT_OCTAL_SUPPORT)
+#define DUK_USE_OCTAL_SUPPORT
+#elif defined(DUK_OPT_NO_OCTAL_SUPPORT)
+#undef DUK_USE_OCTAL_SUPPORT
+#else
+#define DUK_USE_OCTAL_SUPPORT
#endif
-/*
- * Ecmascript compiler
- */
-
-/* Ensure final bytecode never exceeds a certain byte size and never uses
- * line numbers above a certain limit. This ensures that there is no need
- * to deal with unbounded ranges in e.g. pc2line data structures. For now,
- * limits are set so that signed 32-bit values can represent line number
- * and byte offset with room to spare.
- */
-#define DUK_USE_ESBC_LIMITS
-#define DUK_USE_ESBC_MAX_LINENUMBER 0x7fff0000L
-#define DUK_USE_ESBC_MAX_BYTES 0x7fff0000L
-
-#undef DUK_USE_SHUFFLE_TORTURE
-#if defined(DUK_OPT_SHUFFLE_TORTURE)
-#define DUK_USE_SHUFFLE_TORTURE
+#if defined(DUK_OPT_PACKED_TVAL)
+#define DUK_USE_PACKED_TVAL
+#elif defined(DUK_OPT_NO_PACKED_TVAL)
+#undef DUK_USE_PACKED_TVAL
+#else
+#undef DUK_USE_PACKED_TVAL
#endif
-/*
- * User panic handler, panic exit behavior for default panic handler
- */
+#undef DUK_USE_PANIC_ABORT
+#if !defined(DUK_OPT_SEGFAULT_ON_PANIC)
+#define DUK_USE_PANIC_ABORT
+#endif
#undef DUK_USE_PANIC_HANDLER
#if defined(DUK_OPT_PANIC_HANDLER)
#define DUK_USE_PANIC_HANDLER(code,msg) DUK_OPT_PANIC_HANDLER((code),(msg))
#endif
-#undef DUK_USE_PANIC_ABORT
-#undef DUK_USE_PANIC_EXIT
#undef DUK_USE_PANIC_SEGFAULT
-
#if defined(DUK_OPT_SEGFAULT_ON_PANIC)
#define DUK_USE_PANIC_SEGFAULT
-#else
-#define DUK_USE_PANIC_ABORT
#endif
-/*
- * File I/O support. This is now used in a few API calls to e.g. push
- * a string from file contents or eval a file. For portability it must
- * be possible to disable I/O altogether.
- */
-
-#undef DUK_USE_FILE_IO
-#if !defined(DUK_OPT_NO_FILE_IO)
-#define DUK_USE_FILE_IO
+#if defined(DUK_OPT_PARANOID_ERRORS)
+#define DUK_USE_PARANOID_ERRORS
+#elif defined(DUK_OPT_NO_PARANOID_ERRORS)
+#undef DUK_USE_PARANOID_ERRORS
+#else
+#undef DUK_USE_PARANOID_ERRORS
#endif
-/*
- * Optional run-time self tests executed when a heap is created. Some
- * platform/compiler issues cannot be determined at compile time. One
- * particular example is the bug described in misc/clang_aliasing.c.
- */
-
-#undef DUK_USE_SELF_TESTS
-#if defined(DUK_OPT_SELF_TESTS)
-#define DUK_USE_SELF_TESTS
+#if defined(DUK_OPT_PC2LINE)
+#define DUK_USE_PC2LINE
+#elif defined(DUK_OPT_NO_PC2LINE)
+#undef DUK_USE_PC2LINE
+#else
+#define DUK_USE_PC2LINE
#endif
-/* Double aliasing testcase fails when Emscripten-generated code is run
- * on Firefox. This is not fatal because it only affects packed duk_tval
- * which we avoid with Emscripten.
- */
-#undef DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
-#if defined(DUK_F_EMSCRIPTEN)
-#define DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
+#if defined(DUK_OPT_REFCOUNT16)
+#define DUK_USE_REFCOUNT16
+#elif defined(DUK_OPT_NO_REFCOUNT16)
+#undef DUK_USE_REFCOUNT16
+#else
+#undef DUK_USE_REFCOUNT16
#endif
-/*
- * Codecs
- */
-
-#define DUK_USE_JX
-#if defined(DUK_OPT_NO_JX)
-#undef DUK_USE_JX
+#if defined(DUK_OPT_REFERENCE_COUNTING)
+#define DUK_USE_REFERENCE_COUNTING
+#elif defined(DUK_OPT_NO_REFERENCE_COUNTING)
+#undef DUK_USE_REFERENCE_COUNTING
+#else
+#define DUK_USE_REFERENCE_COUNTING
#endif
-#define DUK_USE_JC
-#if defined(DUK_OPT_NO_JC)
-#undef DUK_USE_JC
+#if defined(DUK_OPT_REGEXP_CANON_WORKAROUND)
+#define DUK_USE_REGEXP_CANON_WORKAROUND
+#elif defined(DUK_OPT_NO_REGEXP_CANON_WORKAROUND)
+#undef DUK_USE_REGEXP_CANON_WORKAROUND
+#else
+#undef DUK_USE_REGEXP_CANON_WORKAROUND
#endif
-/*
- * InitJS code
- */
-
-/* Always use the built-in InitJS code for now. */
-#define DUK_USE_BUILTIN_INITJS
-
-/* User provided InitJS. */
-#undef DUK_USE_USER_INITJS
-#if defined(DUK_OPT_USER_INITJS)
-#define DUK_USE_USER_INITJS (DUK_OPT_USER_INITJS)
+#if defined(DUK_OPT_REGEXP_SUPPORT)
+#define DUK_USE_REGEXP_SUPPORT
+#elif defined(DUK_OPT_NO_REGEXP_SUPPORT)
+#undef DUK_USE_REGEXP_SUPPORT
+#else
+#define DUK_USE_REGEXP_SUPPORT
#endif
-/*
- * External string data support
- *
- * Allow duk_hstrings to store data also behind an external pointer (see
- * duk_hstring_external). This increases code size slightly but is useful
- * in low memory environments where memory is more limited than flash.
- */
-
-#undef DUK_USE_HSTRING_EXTDATA
-#if defined(DUK_OPT_EXTERNAL_STRINGS)
-#define DUK_USE_HSTRING_EXTDATA
+#if defined(DUK_OPT_SECTION_B)
+#define DUK_USE_SECTION_B
+#elif defined(DUK_OPT_NO_SECTION_B)
+#undef DUK_USE_SECTION_B
+#else
+#define DUK_USE_SECTION_B
#endif
-#undef DUK_USE_EXTSTR_INTERN_CHECK
-#if defined(DUK_OPT_EXTERNAL_STRINGS) && defined(DUK_OPT_EXTSTR_INTERN_CHECK)
-#define DUK_USE_EXTSTR_INTERN_CHECK(udata,ptr,len) DUK_OPT_EXTSTR_INTERN_CHECK((udata), (ptr), (len))
+#if defined(DUK_OPT_SELF_TESTS)
+#define DUK_USE_SELF_TESTS
+#elif defined(DUK_OPT_NO_SELF_TESTS)
+#undef DUK_USE_SELF_TESTS
+#else
+#undef DUK_USE_SELF_TESTS
#endif
-#undef DUK_USE_EXTSTR_FREE
-#if defined(DUK_OPT_EXTERNAL_STRINGS) && defined(DUK_OPT_EXTSTR_FREE)
-#define DUK_USE_EXTSTR_FREE(udata,ptr) DUK_OPT_EXTSTR_FREE((udata), (ptr))
+#if defined(DUK_OPT_SETJMP)
+#define DUK_USE_SETJMP
+#elif defined(DUK_OPT_NO_SETJMP)
+#undef DUK_USE_SETJMP
+#else
+#define DUK_USE_SETJMP
#endif
-/*
- * Lightweight functions
- */
-
-/* Force built-ins to use lightfunc function pointers when possible. This
- * makes the built-in functions non-compliant with respect to their property
- * values and such, but is very useful in low memory environments (can save
- * around 14kB of initial RAM footprint).
- */
-#undef DUK_USE_LIGHTFUNC_BUILTINS
-#if defined(DUK_OPT_LIGHTFUNC_BUILTINS)
-#define DUK_USE_LIGHTFUNC_BUILTINS
+#if defined(DUK_OPT_SHUFFLE_TORTURE)
+#define DUK_USE_SHUFFLE_TORTURE
+#elif defined(DUK_OPT_NO_SHUFFLE_TORTURE)
+#undef DUK_USE_SHUFFLE_TORTURE
+#else
+#undef DUK_USE_SHUFFLE_TORTURE
#endif
-/*
- * Pointer compression and 16-bit header fields for low memory environments
- */
-
-#undef DUK_USE_HEAPPTR16
-#undef DUK_USE_HEAPPTR_ENC16
-#undef DUK_USE_HEAPPTR_DEC16
-#if defined(DUK_OPT_HEAPPTR16) && defined(DUK_OPT_HEAPPTR_ENC16) && defined(DUK_OPT_HEAPPTR_DEC16)
-#define DUK_USE_HEAPPTR16
-#define DUK_USE_HEAPPTR_ENC16(udata,ptr) DUK_OPT_HEAPPTR_ENC16((udata),(ptr))
-#define DUK_USE_HEAPPTR_DEC16(udata,ptr) DUK_OPT_HEAPPTR_DEC16((udata),(ptr))
+#if defined(DUK_OPT_SIGSETJMP)
+#define DUK_USE_SIGSETJMP
+#elif defined(DUK_OPT_NO_SIGSETJMP)
+#undef DUK_USE_SIGSETJMP
+#else
+#undef DUK_USE_SIGSETJMP
#endif
-#undef DUK_USE_DATAPTR16
-#undef DUK_USE_DATAPTR_ENC16
-#undef DUK_USE_DATAPTR_DEC16
-#if defined(DUK_OPT_DATAPTR16) && defined(DUK_OPT_DATAPTR_ENC16) && defined(DUK_OPT_DATAPTR_DEC16)
-#define DUK_USE_DATAPTR16
-#define DUK_USE_DATAPTR_ENC16(udata,ptr) DUK_OPT_DATAPTR_ENC16((udata),(ptr))
-#define DUK_USE_DATAPTR_DEC16(udata,ptr) DUK_OPT_DATAPTR_DEC16((udata),(ptr))
+#if defined(DUK_OPT_SOURCE_NONBMP)
+#define DUK_USE_SOURCE_NONBMP
+#elif defined(DUK_OPT_NO_SOURCE_NONBMP)
+#undef DUK_USE_SOURCE_NONBMP
+#else
+#define DUK_USE_SOURCE_NONBMP
#endif
-#undef DUK_USE_FUNCPTR16
-#undef DUK_USE_FUNCPTR_ENC16
-#undef DUK_USE_FUNCPTR_DEC16
-#if defined(DUK_OPT_FUNCPTR16) && defined(DUK_OPT_FUNCPTR_ENC16) && defined(DUK_OPT_FUNCPTR_DEC16)
-#define DUK_USE_FUNCPTR16
-#define DUK_USE_FUNCPTR_ENC16(udata,ptr) DUK_OPT_FUNCPTR_ENC16((udata),(ptr))
-#define DUK_USE_FUNCPTR_DEC16(udata,ptr) DUK_OPT_FUNCPTR_DEC16((udata),(ptr))
+#if defined(DUK_OPT_STRHASH16)
+#define DUK_USE_STRHASH16
+#elif defined(DUK_OPT_NO_STRHASH16)
+#undef DUK_USE_STRHASH16
+#else
+#undef DUK_USE_STRHASH16
#endif
-#undef DUK_USE_REFCOUNT16
-#if defined(DUK_OPT_REFCOUNT16)
-#define DUK_USE_REFCOUNT16
+#if defined(DUK_OPT_STRICT_DECL)
+#define DUK_USE_STRICT_DECL
+#elif defined(DUK_OPT_NO_STRICT_DECL)
+#undef DUK_USE_STRICT_DECL
+#else
+#define DUK_USE_STRICT_DECL
#endif
-#undef DUK_USE_STRHASH16
-#if defined(DUK_OPT_STRHASH16)
-#define DUK_USE_STRHASH16
+#if defined(DUK_OPT_STRICT_UTF8_SOURCE)
+#define DUK_USE_STRICT_UTF8_SOURCE
+#elif defined(DUK_OPT_NO_STRICT_UTF8_SOURCE)
+#undef DUK_USE_STRICT_UTF8_SOURCE
+#else
+#undef DUK_USE_STRICT_UTF8_SOURCE
#endif
-#undef DUK_USE_STRLEN16
#if defined(DUK_OPT_STRLEN16)
#define DUK_USE_STRLEN16
+#elif defined(DUK_OPT_NO_STRLEN16)
+#undef DUK_USE_STRLEN16
+#else
+#undef DUK_USE_STRLEN16
#endif
-#undef DUK_USE_BUFLEN16
-#if defined(DUK_OPT_BUFLEN16)
-#define DUK_USE_BUFLEN16
+#undef DUK_USE_STRTAB_CHAIN
+#if defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE)
+#define DUK_USE_STRTAB_CHAIN
#endif
-#undef DUK_USE_OBJSIZES16
-#if defined(DUK_OPT_OBJSIZES16)
-#define DUK_USE_OBJSIZES16
+#undef DUK_USE_STRTAB_CHAIN_SIZE
+#if defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE)
+/* Low memory algorithm: separate chaining using arrays, fixed size hash */
+#define DUK_USE_STRTAB_CHAIN_SIZE DUK_OPT_STRTAB_CHAIN_SIZE
#endif
-/* For now, hash part is dropped if and only if 16-bit object fields are used. */
-#define DUK_USE_HOBJECT_HASH_PART
-#if defined(DUK_USE_OBJSIZES16)
-#undef DUK_USE_HOBJECT_HASH_PART
+#undef DUK_USE_STRTAB_PROBE
+#if !(defined(DUK_OPT_STRTAB_CHAIN) && defined(DUK_OPT_STRTAB_CHAIN_SIZE))
+#define DUK_USE_STRTAB_PROBE
#endif
-/*
- * Miscellaneous
- */
-
-/* Convenience define: 32-bit pointers. 32-bit platforms are an important
- * footprint optimization target, and this define allows e.g. struct sizes
- * to be organized for compactness.
- */
-#undef DUK_USE_32BIT_PTRS
-#if defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)
-#if DUK_UINTPTR_MAX <= 0xffffffffUL
-#define DUK_USE_32BIT_PTRS
-#endif
+#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)
+#undef DUK_USE_TAILCALL
+#else
+#define DUK_USE_TAILCALL
#endif
-#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
-#undef DUK_USE_EXPLICIT_NULL_INIT
-
-#define DUK_USE_ZERO_BUFFER_DATA
-#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA)
-#undef DUK_USE_ZERO_BUFFER_DATA
+#if defined(DUK_OPT_TARGET_INFO)
+#define DUK_USE_TARGET_INFO DUK_OPT_TARGET_INFO
+#else
+#define DUK_USE_TARGET_INFO "unknown"
#endif
-#undef DUK_USE_VARIADIC_MACROS
-#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))
-#define DUK_USE_VARIADIC_MACROS
-#endif
-#if defined(_MSC_VER) && !defined(DUK_USE_VARIADIC_MACROS)
-#if (_MSC_VER >= 1400)
-/* VS2005+ should have variadic macros even when they're not C99. */
-#define DUK_USE_VARIADIC_MACROS
+#if defined(DUK_OPT_NO_AUGMENT_ERRORS)
+#undef DUK_USE_TRACEBACKS
+#elif defined(DUK_OPT_NO_TRACEBACKS)
+#undef DUK_USE_TRACEBACKS
+#else
+#define DUK_USE_TRACEBACKS
#endif
+
+#if defined(DUK_OPT_TRACEBACK_DEPTH)
+#define DUK_USE_TRACEBACK_DEPTH DUK_OPT_TRACEBACK_DEPTH
+#else
+#define DUK_USE_TRACEBACK_DEPTH 10
#endif
-/*
- * Variable size array initialization.
- *
- * Variable size array at the end of a structure is nonportable.
- * There are three alternatives:
- *
- * 1) C99 (flexible array member): char buf[]
- * 2) Compiler specific (e.g. GCC): char buf[0]
- * 3) Portable but wastes memory / complicates allocation: char buf[1]
- */
+#if defined(DUK_OPT_UNDERSCORE_SETJMP)
+#define DUK_USE_UNDERSCORE_SETJMP
+#elif defined(DUK_OPT_NO_UNDERSCORE_SETJMP)
+#undef DUK_USE_UNDERSCORE_SETJMP
+#else
+#undef DUK_USE_UNDERSCORE_SETJMP
+#endif
-/* XXX: Currently unused, only hbuffer.h needed this at some point. */
-#undef DUK_USE_FLEX_C99
-#undef DUK_USE_FLEX_ZEROSIZE
-#undef DUK_USE_FLEX_ONESIZE
-#if defined(DUK_F_C99)
-#define DUK_USE_FLEX_C99
-#elif defined(__GNUC__)
-#define DUK_USE_FLEX_ZEROSIZE
+#if defined(DUK_OPT_DECLARE)
+#define DUK_USE_USER_DECLARE() DUK_OPT_DECLARE
#else
-#define DUK_USE_FLEX_ONESIZE
+#define DUK_USE_USER_DECLARE() /* no user declarations */
#endif
-/*
- * GCC pragmas
- */
+/* User provided InitJS. */
+#undef DUK_USE_USER_INITJS
+#if defined(DUK_OPT_USER_INITJS)
+#define DUK_USE_USER_INITJS (DUK_OPT_USER_INITJS)
+#endif
-/* XXX: GCC pragma inside a function fails in some earlier GCC versions (e.g. gcc 4.5).
- * This is very approximate but allows clean builds for development right now.
- */
-/* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html */
-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)
-#define DUK_USE_GCC_PRAGMAS
+#if defined(DUK_OPT_VERBOSE_ERRORS)
+#define DUK_USE_VERBOSE_ERRORS
+#elif defined(DUK_OPT_NO_VERBOSE_ERRORS)
+#undef DUK_USE_VERBOSE_ERRORS
#else
-#undef DUK_USE_GCC_PRAGMAS
+#define DUK_USE_VERBOSE_ERRORS
#endif
-/*
- * User declarations
- */
+#if defined(DUK_OPT_VOLUNTARY_GC)
+#define DUK_USE_VOLUNTARY_GC
+#elif defined(DUK_OPT_NO_VOLUNTARY_GC)
+#undef DUK_USE_VOLUNTARY_GC
+#else
+#define DUK_USE_VOLUNTARY_GC
+#endif
-#if defined(DUK_OPT_DECLARE)
-#define DUK_USE_USER_DECLARE() DUK_OPT_DECLARE
+#if defined(DUK_OPT_ZERO_BUFFER_DATA)
+#define DUK_USE_ZERO_BUFFER_DATA
+#elif defined(DUK_OPT_NO_ZERO_BUFFER_DATA)
+#undef DUK_USE_ZERO_BUFFER_DATA
#else
-#define DUK_USE_USER_DECLARE() /* no user declarations */
+#define DUK_USE_ZERO_BUFFER_DATA
#endif
/*
* Autogenerated defaults
*/
+#define DUK_USE_AVOID_PLATFORM_FUNCPTRS
+#define DUK_USE_BASE64_FASTPATH
+#define DUK_USE_BUILTIN_INITJS
#define DUK_USE_COMPILER_RECLIMIT 2500
#undef DUK_USE_DATE_FORMAT_STRING
#undef DUK_USE_DATE_GET_LOCAL_TZOFFSET
#undef DUK_USE_DATE_GET_NOW
#undef DUK_USE_DATE_PARSE_STRING
#undef DUK_USE_DATE_PRS_GETDATE
+#define DUK_USE_ESBC_LIMITS
+#define DUK_USE_ESBC_MAX_BYTES 2147418112L
+#define DUK_USE_ESBC_MAX_LINENUMBER 2147418112L
#undef DUK_USE_EXEC_FUN_LOCAL
-#undef DUK_USE_INTEGER_ME
+#undef DUK_USE_EXPLICIT_NULL_INIT
+#define DUK_USE_FAST_REFCOUNT_DEFAULT
+#define DUK_USE_HEX_FASTPATH
#undef DUK_USE_INTERRUPT_DEBUG_FIXUP
#define DUK_USE_JSON_DECNUMBER_FASTPATH
#define DUK_USE_JSON_DECSTRING_FASTPATH
@@ -3044,12 +3373,21 @@ typedef FILE duk_file;
#define DUK_USE_JSON_EATWHITE_FASTPATH
#define DUK_USE_JSON_ENC_RECLIMIT 1000
#define DUK_USE_JSON_QUOTESTRING_FASTPATH
+#define DUK_USE_LEXER_SLIDING_WINDOW
#undef DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE
#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256
+#define DUK_USE_MATH_BUILTIN
#define DUK_USE_NATIVE_CALL_RECLIMIT 1000
+#undef DUK_USE_PANIC_EXIT
+#undef DUK_USE_PREFER_SIZE
+#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS
#undef DUK_USE_REFZERO_FINALIZER_TORTURE
#define DUK_USE_REGEXP_COMPILER_RECLIMIT 10000
#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT 10000
+#undef DUK_USE_STRHASH_DENSE
+#define DUK_USE_STRHASH_SKIP_SHIFT 5
+#undef DUK_USE_VALSTACK_UNSAFE
+#define DUK_USE_VERBOSE_EXECUTOR_ERRORS
/*
* Alternative customization header
@@ -3084,13 +3422,10 @@ typedef FILE duk_file;
#if defined(DUK_USE_DATE_GET_NOW)
/* External provider already defined. */
#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
-DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_gettimeofday((ctx))
#elif defined(DUK_USE_DATE_NOW_TIME)
-DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx);
#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_time((ctx))
#elif defined(DUK_USE_DATE_NOW_WINDOWS)
-DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
#define DUK_USE_DATE_GET_NOW(ctx) duk_bi_date_get_now_windows((ctx))
#else
#error no provider for DUK_USE_DATE_GET_NOW()
@@ -3099,10 +3434,8 @@ DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET)
/* External provider already defined. */
#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
-DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) duk_bi_date_get_local_tzoffset_gmtime((d))
#elif defined(DUK_USE_DATE_TZO_WINDOWS)
-DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d) duk_bi_date_get_local_tzoffset_windows((d))
#else
#error no provider for DUK_USE_DATE_GET_LOCAL_TZOFFSET()
@@ -3111,10 +3444,8 @@ DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t
#if defined(DUK_USE_DATE_PARSE_STRING)
/* External provider already defined. */
#elif defined(DUK_USE_DATE_PRS_STRPTIME)
-DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
#define DUK_USE_DATE_PARSE_STRING(ctx,str) duk_bi_date_parse_string_strptime((ctx), (str))
#elif defined(DUK_USE_DATE_PRS_GETDATE)
-DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
#define DUK_USE_DATE_PARSE_STRING(ctx,str) duk_bi_date_parse_string_getdate((ctx), (str))
#else
/* No provider for DUK_USE_DATE_PARSE_STRING(), fall back to ISO 8601 only. */
@@ -3123,7 +3454,6 @@ DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx,
#if defined(DUK_USE_DATE_FORMAT_STRING)
/* External provider already defined. */
#elif defined(DUK_USE_DATE_FMT_STRFTIME)
-DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
#define DUK_USE_DATE_FORMAT_STRING(ctx,parts,tzoffset,flags) \
duk_bi_date_format_parts_strftime((ctx), (parts), (tzoffset), (flags))
#else
@@ -3133,109 +3463,183 @@ DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx,
#endif /* DUK_COMPILING_DUKTAPE */
/*
- * Sanity check for the final effective internal defines. Also
- * double checks user tweaks made by an optional duk_custom.h header.
- */
-
-/*
- * Deprecated feature options.
- *
- * Catch so that user more easily notices and updates build.
+ * Checks for config option consistency (DUK_USE_xxx)
*/
-#if defined(DUK_OPT_NO_FUNC_STMT)
-#error DUK_OPT_NO_FUNC_STMT is deprecated, use DUK_OPT_NO_NONSTD_FUNC_STMT
+#if defined(DUK_USE_32BIT_PTRS)
+#error unsupported config option used (option has been removed): DUK_USE_32BIT_PTRS
#endif
-
-#if defined(DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY)
-#error DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY is deprecated, use DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY
+#if defined(DUK_USE_ALIGN_4)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_4
#endif
-
-#if defined(DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY)
-#error DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY is deprecated, use DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY
+#if defined(DUK_USE_ALIGN_8)
+#error unsupported config option used (option has been removed): DUK_USE_ALIGN_8
#endif
-
-#if defined(DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT)
-#error DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT is deprecated, use DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT
+#if defined(DUK_USE_BYTEORDER_FORCED)
+#error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED
#endif
-
-#if defined(DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY)
-#error DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY is deprecated, use DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY
+#if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing)
#endif
-
-#if defined(DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF)
-#error DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF is deprecated, use DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF
+#if defined(DUK_USE_DATAPTR_ENC16) && !defined(DUK_USE_DATAPTR16)
+#error config option DUK_USE_DATAPTR_ENC16 requires option DUK_USE_DATAPTR16 (which is missing)
#endif
-
-#if defined(DUK_OPT_NO_JSONX)
-#error DUK_OPT_NO_JSONX is deprecated, use DUK_OPT_NO_JX
+#if defined(DUK_USE_DEBUGGER_DUMPHEAP) && !defined(DUK_USE_DEBUGGER_SUPPORT)
+#error config option DUK_USE_DEBUGGER_DUMPHEAP requires option DUK_USE_DEBUGGER_SUPPORT (which is missing)
#endif
-
-#if defined(DUK_OPT_NO_JSONC)
-#error DUK_OPT_NO_JSONC is deprecated, use DUK_OPT_NO_JC
+#if defined(DUK_USE_DEBUGGER_FWD_LOGGING) && !defined(DUK_USE_DEBUGGER_SUPPORT)
+#error config option DUK_USE_DEBUGGER_FWD_LOGGING requires option DUK_USE_DEBUGGER_SUPPORT (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_FWD_PRINTALERT) && !defined(DUK_USE_DEBUGGER_SUPPORT)
+#error config option DUK_USE_DEBUGGER_FWD_PRINTALERT requires option DUK_USE_DEBUGGER_SUPPORT (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) && !defined(DUK_USE_DEBUGGER_SUPPORT)
+#error config option DUK_USE_DEBUGGER_PAUSE_UNCAUGHT requires option DUK_USE_DEBUGGER_SUPPORT (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_DEBUGGER_SUPPORT requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) && !defined(DUK_USE_DEBUGGER_SUPPORT)
+#error config option DUK_USE_DEBUGGER_THROW_NOTIFY requires option DUK_USE_DEBUGGER_SUPPORT (which is missing)
+#endif
+#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE) && !defined(DUK_USE_DEBUGGER_SUPPORT)
+#error config option DUK_USE_DEBUGGER_TRANSPORT_TORTURE requires option DUK_USE_DEBUGGER_SUPPORT (which is missing)
+#endif
+#if defined(DUK_USE_DEEP_C_STACK)
+#error unsupported config option used (option has been removed): DUK_USE_DEEP_C_STACK
+#endif
+#if defined(DUK_USE_DOUBLE_BE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_BE
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_LE
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_ME)
+#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME)
+#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_ME
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_LE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_LE (which is also defined)
+#endif
+#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_BE)
+#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_BE (which is also defined)
#endif
-
-/*
- * Debug print consistency
- */
-
#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG)
-#error DUK_USE_DPRINT without DUK_USE_DEBUG
+#error config option DUK_USE_DPRINT requires option DUK_USE_DEBUG (which is missing)
#endif
-
-#if defined(DUK_USE_DDPRINT) && !defined(DUK_USE_DEBUG)
-#error DUK_USE_DDPRINT without DUK_USE_DEBUG
+#if defined(DUK_USE_ESBC_MAX_BYTES) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_BYTES requires option DUK_USE_ESBC_LIMITS (which is missing)
#endif
-
-#if defined(DUK_USE_DDDPRINT) && !defined(DUK_USE_DEBUG)
-#error DUK_USE_DDDPRINT without DUK_USE_DEBUG
+#if defined(DUK_USE_ESBC_MAX_LINENUMBER) && !defined(DUK_USE_ESBC_LIMITS)
+#error config option DUK_USE_ESBC_MAX_LINENUMBER requires option DUK_USE_ESBC_LIMITS (which is missing)
+#endif
+#if defined(DUK_USE_EXEC_TIMEOUT_CHECK) && !defined(DUK_USE_INTERRUPT_COUNTER)
+#error config option DUK_USE_EXEC_TIMEOUT_CHECK requires option DUK_USE_INTERRUPT_COUNTER (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_FREE) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_FREE requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_EXTSTR_INTERN_CHECK) && !defined(DUK_USE_HSTRING_EXTDATA)
+#error config option DUK_USE_EXTSTR_INTERN_CHECK requires option DUK_USE_HSTRING_EXTDATA (which is missing)
+#endif
+#if defined(DUK_USE_FULL_TVAL)
+#error unsupported config option used (option has been removed): DUK_USE_FULL_TVAL
+#endif
+#if defined(DUK_USE_FUNCPTR_DEC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_DEC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_FUNCPTR_ENC16) && !defined(DUK_USE_FUNCPTR16)
+#error config option DUK_USE_FUNCPTR_ENC16 requires option DUK_USE_FUNCPTR16 (which is missing)
+#endif
+#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
+#error unsupported config option used (option has been removed): DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
#endif
-
#if defined(DUK_USE_HEAPPTR16) && defined(DUK_USE_DEBUG)
-/* Debug code doesn't have access to 'heap' so it cannot decode pointers. */
-#error debug printing cannot currently be used with heap pointer compression
+#error config option DUK_USE_HEAPPTR16 conflicts with option DUK_USE_DEBUG (which is also defined)
#endif
-
-/*
- * Debugger consistency
- */
-
-#if defined(DUK_USE_DEBUGGER_SUPPORT)
-#if !defined(DUK_USE_INTERRUPT_COUNTER)
-#error DUK_USE_INTERRUPT_COUNTER is needed when debugger support is enabled
+#if defined(DUK_USE_HEAPPTR_DEC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_DEC16 requires option DUK_USE_HEAPPTR16 (which is missing)
#endif
-#if !defined(DUK_USE_PC2LINE)
-#error DUK_USE_PC2LINE is needed when debugger support is enabled
+#if defined(DUK_USE_HEAPPTR_ENC16) && !defined(DUK_USE_HEAPPTR16)
+#error config option DUK_USE_HEAPPTR_ENC16 requires option DUK_USE_HEAPPTR16 (which is missing)
#endif
+#if defined(DUK_USE_INTEGER_BE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_BE
#endif
-
-/*
- * Garbage collection consistency
- */
-
-#if defined(DUK_USE_REFERENCE_COUNTING) && !defined(DUK_USE_DOUBLE_LINKED_HEAP)
-#error DUK_USE_REFERENCE_COUNTING defined without DUK_USE_DOUBLE_LINKED_HEAP
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_LE (which is also defined)
#endif
-
-#if defined(DUK_USE_GC_TORTURE) && !defined(DUK_USE_MARK_AND_SWEEP)
-#error DUK_USE_GC_TORTURE defined without DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
#endif
-
-/*
- * Low memory feature consistency
- */
-
-#if defined(DUK_USE_OBJSIZES16)
-#if defined(DUK_USE_HOBJECT_HASH_PART)
-#error DUK_USE_OBJSIZES16 assumes DUK_USE_HOBJECT_HASH_PART is not defined
+#if defined(DUK_USE_INTEGER_LE)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_LE
#endif
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_BE (which is also defined)
#endif
-
-#if defined(DUK_USE_STRTAB_CHAIN) && defined(DUK_USE_STRTAB_PROBE)
-#error both DUK_USE_STRTAB_CHAIN and DUK_USE_STRTAB_PROBE defined
+#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_ME)
+#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_ME (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME)
+#error unsupported config option used (option has been removed): DUK_USE_INTEGER_ME
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_LE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_LE (which is also defined)
+#endif
+#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_BE)
+#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_BE (which is also defined)
+#endif
+#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)
+#error unsupported config option used (option has been removed): DUK_USE_NO_DOUBLE_ALIASING_SELFTEST
#endif
-#if !defined(DUK_USE_STRTAB_CHAIN) && !defined(DUK_USE_STRTAB_PROBE)
-#error neither DUK_USE_STRTAB_CHAIN nor DUK_USE_STRTAB_PROBE is defined
+#if defined(DUK_USE_PACKED_TVAL_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_PACKED_TVAL_POSSIBLE
#endif
+#if defined(DUK_USE_RDTSC)
+#error unsupported config option used (option has been removed): DUK_USE_RDTSC
+#endif
+#if defined(DUK_USE_STRTAB_CHAIN_SIZE) && !defined(DUK_USE_STRTAB_CHAIN)
+#error config option DUK_USE_STRTAB_CHAIN_SIZE requires option DUK_USE_STRTAB_CHAIN (which is missing)
+#endif
+#if defined(DUK_USE_TAILCALL) && defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
+#error config option DUK_USE_TAILCALL conflicts with option DUK_USE_NONSTD_FUNC_CALLER_PROPERTY (which is also defined)
+#endif
+#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+#error unsupported config option used (option has been removed): DUK_USE_UNALIGNED_ACCESSES_POSSIBLE
+#endif
+
+/*
+ * Convert DUK_USE_BYTEORDER, from whatever source, into currently used
+ * internal defines. If detection failed, #error out.
+ */
+
+#if defined(DUK_USE_BYTEORDER)
+#if (DUK_USE_BYTEORDER == 1)
+#define DUK_USE_INTEGER_LE
+#define DUK_USE_DOUBLE_LE
+#elif (DUK_USE_BYTEORDER == 2)
+#define DUK_USE_INTEGER_LE /* integer endianness is little on purpose */
+#define DUK_USE_DOUBLE_ME
+#elif (DUK_USE_BYTEORDER == 3)
+#define DUK_USE_INTEGER_BE
+#define DUK_USE_DOUBLE_BE
+#else
+#error unsupported: byte order invalid
+#endif /* byte order */
+#else
+#error unsupported: byte order detection failed
+#endif /* defined(DUK_USE_BYTEORDER) */
#endif /* DUK_CONFIG_H_INCLUDED */
diff --git a/javascript/duktape/duktape.c b/javascript/duktape/duktape.c
index 530a27aea..184767de4 100644
--- a/javascript/duktape/duktape.c
+++ b/javascript/duktape/duktape.c
@@ -1,10 +1,8 @@
-// Omit from static analysis.
-#ifndef __clang_analyzer__
/*
* Single source autogenerated distributable for Duktape 1.3.99.
- * Git commit 40453939c5a5aa16898d19bbac4d02f77196cc8b (v1.3.0-138-g4045393).
- * Git branch regexp-canonicalize-lookup.
+ * Git commit b7b1c5fd2d1d4550140d57e05a7b32f540082bfa (v1.3.0-383-gb7b1c5f).
+ * Git branch duk-config-improvements.
*
* See Duktape AUTHORS.rst and LICENSE.txt for copyright and
* licensing information.
@@ -158,23 +156,31 @@ DUK_USE_USER_DECLARE()
#ifndef DUK_REPLACEMENTS_H_INCLUDED
#define DUK_REPLACEMENTS_H_INCLUDED
-#ifdef DUK_USE_REPL_FPCLASSIFY
+#if defined(DUK_USE_COMPUTED_INFINITY)
+DUK_INTERNAL_DECL double duk_computed_infinity;
+#endif
+
+#if defined(DUK_USE_COMPUTED_NAN)
+DUK_INTERNAL_DECL double duk_computed_nan;
+#endif
+
+#if defined(DUK_USE_REPL_FPCLASSIFY)
DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
#endif
-#ifdef DUK_USE_REPL_SIGNBIT
+#if defined(DUK_USE_REPL_SIGNBIT)
DUK_INTERNAL_DECL int duk_repl_signbit(double x);
#endif
-#ifdef DUK_USE_REPL_ISFINITE
+#if defined(DUK_USE_REPL_ISFINITE)
DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
#endif
-#ifdef DUK_USE_REPL_ISNAN
+#if defined(DUK_USE_REPL_ISNAN)
DUK_INTERNAL_DECL int duk_repl_isnan(double x);
#endif
-#ifdef DUK_USE_REPL_ISINF
+#if defined(DUK_USE_REPL_ISINF)
DUK_INTERNAL_DECL int duk_repl_isinf(double x);
#endif
@@ -727,11 +733,11 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_STRIDX_TRY 389 /* 'try' */
#define DUK_STRIDX_TYPEOF 390 /* 'typeof' */
#define DUK_STRIDX_VAR 391 /* 'var' */
-#define DUK_STRIDX_VOID 392 /* 'void' */
-#define DUK_STRIDX_WHILE 393 /* 'while' */
-#define DUK_STRIDX_WITH 394 /* 'with' */
-#define DUK_STRIDX_CLASS 395 /* 'class' */
-#define DUK_STRIDX_CONST 396 /* 'const' */
+#define DUK_STRIDX_CONST 392 /* 'const' */
+#define DUK_STRIDX_VOID 393 /* 'void' */
+#define DUK_STRIDX_WHILE 394 /* 'while' */
+#define DUK_STRIDX_WITH 395 /* 'with' */
+#define DUK_STRIDX_CLASS 396 /* 'class' */
#define DUK_STRIDX_ENUM 397 /* 'enum' */
#define DUK_STRIDX_EXPORT 398 /* 'export' */
#define DUK_STRIDX_EXTENDS 399 /* 'extends' */
@@ -1534,6 +1540,8 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
#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_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_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_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
@@ -1542,8 +1550,6 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
#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_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_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_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
@@ -1586,16 +1592,16 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_STRIDX_END_RESERVED 414 /* exclusive endpoint */
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[147];
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1952];
#ifdef DUK_USE_BUILTIN_INITJS
-DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[1757];
+DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187];
#endif /* DUK_USE_BUILTIN_INITJS */
#endif /* !DUK_SINGLE_FILE */
#define DUK_BUILTINS_DATA_LENGTH 1952
#ifdef DUK_USE_BUILTIN_INITJS
-#define DUK_BUILTIN_INITJS_DATA_LENGTH 1757
+#define DUK_BUILTIN_INITJS_DATA_LENGTH 187
#endif /* DUK_USE_BUILTIN_INITJS */
#define DUK_BIDX_GLOBAL 0
@@ -2072,11 +2078,11 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_STRIDX_TRY 389 /* 'try' */
#define DUK_STRIDX_TYPEOF 390 /* 'typeof' */
#define DUK_STRIDX_VAR 391 /* 'var' */
-#define DUK_STRIDX_VOID 392 /* 'void' */
-#define DUK_STRIDX_WHILE 393 /* 'while' */
-#define DUK_STRIDX_WITH 394 /* 'with' */
-#define DUK_STRIDX_CLASS 395 /* 'class' */
-#define DUK_STRIDX_CONST 396 /* 'const' */
+#define DUK_STRIDX_CONST 392 /* 'const' */
+#define DUK_STRIDX_VOID 393 /* 'void' */
+#define DUK_STRIDX_WHILE 394 /* 'while' */
+#define DUK_STRIDX_WITH 395 /* 'with' */
+#define DUK_STRIDX_CLASS 396 /* 'class' */
#define DUK_STRIDX_ENUM 397 /* 'enum' */
#define DUK_STRIDX_EXPORT 398 /* 'export' */
#define DUK_STRIDX_EXTENDS 399 /* 'extends' */
@@ -2879,6 +2885,8 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
#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_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_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_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
@@ -2887,8 +2895,6 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
#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_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_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_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
@@ -2931,16 +2937,16 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_STRIDX_END_RESERVED 414 /* exclusive endpoint */
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[147];
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1952];
#ifdef DUK_USE_BUILTIN_INITJS
-DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[1757];
+DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187];
#endif /* DUK_USE_BUILTIN_INITJS */
#endif /* !DUK_SINGLE_FILE */
#define DUK_BUILTINS_DATA_LENGTH 1952
#ifdef DUK_USE_BUILTIN_INITJS
-#define DUK_BUILTIN_INITJS_DATA_LENGTH 1757
+#define DUK_BUILTIN_INITJS_DATA_LENGTH 187
#endif /* DUK_USE_BUILTIN_INITJS */
#define DUK_BIDX_GLOBAL 0
@@ -3417,11 +3423,11 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_STRIDX_TRY 389 /* 'try' */
#define DUK_STRIDX_TYPEOF 390 /* 'typeof' */
#define DUK_STRIDX_VAR 391 /* 'var' */
-#define DUK_STRIDX_VOID 392 /* 'void' */
-#define DUK_STRIDX_WHILE 393 /* 'while' */
-#define DUK_STRIDX_WITH 394 /* 'with' */
-#define DUK_STRIDX_CLASS 395 /* 'class' */
-#define DUK_STRIDX_CONST 396 /* 'const' */
+#define DUK_STRIDX_CONST 392 /* 'const' */
+#define DUK_STRIDX_VOID 393 /* 'void' */
+#define DUK_STRIDX_WHILE 394 /* 'while' */
+#define DUK_STRIDX_WITH 395 /* 'with' */
+#define DUK_STRIDX_CLASS 396 /* 'class' */
#define DUK_STRIDX_ENUM 397 /* 'enum' */
#define DUK_STRIDX_EXPORT 398 /* 'export' */
#define DUK_STRIDX_EXTENDS 399 /* 'extends' */
@@ -4224,6 +4230,8 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
#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_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_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_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
@@ -4232,8 +4240,6 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
#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_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_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_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
@@ -4276,16 +4282,16 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624];
#define DUK_STRIDX_END_RESERVED 414 /* exclusive endpoint */
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[147];
+DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1952];
#ifdef DUK_USE_BUILTIN_INITJS
-DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[1757];
+DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187];
#endif /* DUK_USE_BUILTIN_INITJS */
#endif /* !DUK_SINGLE_FILE */
#define DUK_BUILTINS_DATA_LENGTH 1952
#ifdef DUK_USE_BUILTIN_INITJS
-#define DUK_BUILTIN_INITJS_DATA_LENGTH 1757
+#define DUK_BUILTIN_INITJS_DATA_LENGTH 187
#endif /* DUK_USE_BUILTIN_INITJS */
#define DUK_BIDX_GLOBAL 0
@@ -4834,9 +4840,17 @@ struct duk_bufwriter_ctx {
*/
#if !defined(DUK_SINGLE_FILE)
-DUK_INTERNAL_DECL duk_uint8_t duk_lc_digits[36];
-DUK_INTERNAL_DECL duk_uint8_t duk_uc_nybbles[16];
-DUK_INTERNAL_DECL duk_int8_t duk_hex_dectab[256];
+DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
+DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
+DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
+#if defined(DUK_USE_HEX_FASTPATH)
+DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
+DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
+#endif
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
+DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
+#endif
#endif /* !DUK_SINGLE_FILE */
/* Note: assumes that duk_util_probe_steps size is 32 */
@@ -4846,7 +4860,9 @@ DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
#endif /* !DUK_SINGLE_FILE */
#endif
+#if defined(DUK_USE_STRHASH_DENSE)
DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
+#endif
#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
@@ -4934,20 +4950,23 @@ DUK_INTERNAL_DECL const char *duk_str_not_configurable;
#endif /* !DUK_SINGLE_FILE */
#define DUK_STR_INVALID_CONTEXT duk_str_invalid_context
-#define DUK_STR_INVALID_INDEX duk_str_invalid_index
+#define DUK_STR_INVALID_INDEX duk_str_invalid_call_args
#define DUK_STR_PUSH_BEYOND_ALLOC_STACK duk_str_push_beyond_alloc_stack
-#define DUK_STR_NOT_UNDEFINED duk_str_not_undefined
-#define DUK_STR_NOT_NULL duk_str_not_null
-#define DUK_STR_NOT_BOOLEAN duk_str_not_boolean
-#define DUK_STR_NOT_NUMBER duk_str_not_number
-#define DUK_STR_NOT_STRING duk_str_not_string
-#define DUK_STR_NOT_POINTER duk_str_not_pointer
-#define DUK_STR_NOT_BUFFER duk_str_not_buffer
+#define DUK_STR_NOT_UNDEFINED duk_str_unexpected_type
+#define DUK_STR_NOT_NULL duk_str_unexpected_type
+#define DUK_STR_NOT_BOOLEAN duk_str_unexpected_type
+#define DUK_STR_NOT_NUMBER duk_str_unexpected_type
+#define DUK_STR_NOT_STRING duk_str_unexpected_type
+#define DUK_STR_NOT_OBJECT duk_str_unexpected_type
+#define DUK_STR_NOT_POINTER duk_str_unexpected_type
+#define DUK_STR_NOT_BUFFER duk_str_not_buffer /* still in use with verbose messages */
#define DUK_STR_UNEXPECTED_TYPE duk_str_unexpected_type
-#define DUK_STR_NOT_THREAD duk_str_not_thread
-#define DUK_STR_NOT_COMPILEDFUNCTION duk_str_not_compiledfunction
-#define DUK_STR_NOT_NATIVEFUNCTION duk_str_not_nativefunction
-#define DUK_STR_NOT_C_FUNCTION duk_str_not_c_function
+#define DUK_STR_NOT_THREAD duk_str_unexpected_type
+#define DUK_STR_NOT_COMPILEDFUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_NATIVEFUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_C_FUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_FUNCTION duk_str_unexpected_type
+#define DUK_STR_NOT_REGEXP duk_str_unexpected_type
#define DUK_STR_DEFAULTVALUE_COERCE_FAILED duk_str_defaultvalue_coerce_failed
#define DUK_STR_NUMBER_OUTSIDE_RANGE duk_str_number_outside_range
#define DUK_STR_NOT_OBJECT_COERCIBLE duk_str_not_object_coercible
@@ -4968,20 +4987,9 @@ DUK_INTERNAL_DECL const char *duk_str_not_configurable;
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const char *duk_str_invalid_context;
-DUK_INTERNAL_DECL const char *duk_str_invalid_index;
DUK_INTERNAL_DECL const char *duk_str_push_beyond_alloc_stack;
-DUK_INTERNAL_DECL const char *duk_str_not_undefined;
-DUK_INTERNAL_DECL const char *duk_str_not_null;
-DUK_INTERNAL_DECL const char *duk_str_not_boolean;
-DUK_INTERNAL_DECL const char *duk_str_not_number;
-DUK_INTERNAL_DECL const char *duk_str_not_string;
-DUK_INTERNAL_DECL const char *duk_str_not_pointer;
DUK_INTERNAL_DECL const char *duk_str_not_buffer;
DUK_INTERNAL_DECL const char *duk_str_unexpected_type;
-DUK_INTERNAL_DECL const char *duk_str_not_thread;
-DUK_INTERNAL_DECL const char *duk_str_not_compiledfunction;
-DUK_INTERNAL_DECL const char *duk_str_not_nativefunction;
-DUK_INTERNAL_DECL const char *duk_str_not_c_function;
DUK_INTERNAL_DECL const char *duk_str_defaultvalue_coerce_failed;
DUK_INTERNAL_DECL const char *duk_str_number_outside_range;
DUK_INTERNAL_DECL const char *duk_str_not_object_coercible;
@@ -5453,13 +5461,13 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo
#define DUK_TOK_TRY 22
#define DUK_TOK_TYPEOF 23
#define DUK_TOK_VAR 24
-#define DUK_TOK_VOID 25
-#define DUK_TOK_WHILE 26
-#define DUK_TOK_WITH 27
+#define DUK_TOK_CONST 25
+#define DUK_TOK_VOID 26
+#define DUK_TOK_WHILE 27
+#define DUK_TOK_WITH 28
/* reserved words: future reserved words */
-#define DUK_TOK_CLASS 28
-#define DUK_TOK_CONST 29
+#define DUK_TOK_CLASS 29
#define DUK_TOK_ENUM 30
#define DUK_TOK_EXPORT 31
#define DUK_TOK_EXTENDS 32
@@ -6158,11 +6166,6 @@ DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hack
* Packed 8-byte representation
*/
-/* sanity */
-#if !defined(DUK_USE_PACKED_TVAL_POSSIBLE)
-#error packed representation not supported
-#endif
-
/* use duk_double_union as duk_tval directly */
typedef union duk_double_union duk_tval;
@@ -7108,13 +7111,13 @@ struct duk_heaphdr_string {
} while (0)
/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
- * etc, so it's very important for performance.
+ * etc, so it's very important for performance. Measure when changing.
*
* NOTE: the source and destination duk_tval pointers may be the same, and
* the macros MUST deal with that correctly.
*/
-/* Original idiom used. */
+/* Original idiom used, minimal code size. */
#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
@@ -7124,84 +7127,23 @@ struct duk_heaphdr_string {
DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
-#if 0 /* XXX: to optimize and measure */
-/* Original idiom but with forced fast refcount macros. */
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT0F(thr,tvptr_dst,tvptr_src) do { \
- duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
- DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
- DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_TVAL_INCREF_FAST((thr), tv__src); \
- DUK_TVAL_DECREF_FAST((thr), &tv__tmp); /* side effects */ \
- } while (0)
-
-/* Use 'h__obj' temporary to avoid a full duk_tval copy. */
+/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
+ * fast incref/decref macros.
+ */
#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
- if (DUK_TVAL_IS_HEAP_ALLOCATED(tv__dst)) { \
- h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
- DUK_ASSERT(h__obj != NULL); \
- } else { \
- h__obj = NULL; \
- } \
- DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_TVAL_INCREF((thr), tv__src); \
- if (h__obj != NULL) { \
- DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
- } \
- } while (0)
-
-/* Use 'h__obj' temporary to avoid a full duk_tval copy. */
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT1A(thr,tvptr_dst,tvptr_src) do { \
- duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
- if (DUK_UNLIKELY(DUK_TVAL_IS_HEAP_ALLOCATED(tv__dst))) { \
- h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
- DUK_ASSERT(h__obj != NULL); \
- } else { \
- h__obj = NULL; \
- } \
- DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
DUK_TVAL_INCREF_FAST((thr), tv__src); \
- if (DUK_UNLIKELY(h__obj != NULL)) { \
- DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
- } \
- } while (0)
-
-/* Avoid rechecking 'h__obj'. */
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT2(thr,tvptr_dst,tvptr_src) do { \
- duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
if (DUK_TVAL_IS_HEAP_ALLOCATED(tv__dst)) { \
h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
DUK_ASSERT(h__obj != NULL); \
DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_TVAL_INCREF((thr), tv__src); \
DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
} else { \
DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_TVAL_INCREF((thr), tv__src); \
} \
} while (0)
-/* Avoid rechecking 'h__obj'. */
-#define DUK_TVAL_SET_TVAL_UPDREF_ALT3(thr,tvptr_dst,tvptr_src) do { \
- duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
- tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
- if (DUK_UNLIKELY(DUK_TVAL_IS_HEAP_ALLOCATED(tv__dst))) { \
- h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
- DUK_ASSERT(h__obj != NULL); \
- DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_TVAL_INCREF_FAST((thr), tv__src); \
- DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
- } else { \
- DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
- DUK_TVAL_INCREF_FAST((thr), tv__src); \
- } \
- } while (0)
-#endif
-
/* XXX: no optimized variants yet */
#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
@@ -7224,8 +7166,8 @@ struct duk_heaphdr_string {
#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
/* Optimized for speed. */
-#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
-#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
+#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
+#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
#else
/* Optimized for size. */
@@ -7421,6 +7363,10 @@ duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
duk_size_t min_new_size,
duk_small_uint_t flags);
+#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index);
+#endif
+
DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv);
@@ -7462,13 +7408,6 @@ DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx);
#define duk_push_size_t(ctx,val) \
duk_push_uint((ctx), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
-/* internal helper for looking up a tagged type */
-#define DUK_GETTAGGED_FLAG_ALLOW_NULL (1L << 24)
-#define DUK_GETTAGGED_FLAG_CHECK_CLASS (1L << 25)
-#define DUK_GETTAGGED_CLASS_SHIFT 16
-
-DUK_INTERNAL_DECL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag);
-
DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index);
@@ -7476,10 +7415,7 @@ DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index
DUK_INTERNAL_DECL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index);
-#define duk_get_hobject_with_class(ctx,index,classnum) \
- ((duk_hobject *) duk_get_tagged_heaphdr_raw((ctx), (index), \
- DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL | \
- DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT)))
+DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
#if 0 /* This would be pointless: unexpected type and lightfunc would both return NULL */
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
@@ -7494,6 +7430,10 @@ DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index)
#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index);
#endif
+DUK_INTERNAL_DECL void duk_to_object_class_string_top(duk_context *ctx);
+#if !defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL_DECL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h);
+#endif
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
@@ -7509,10 +7449,7 @@ DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t i
DUK_INTERNAL_DECL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index);
-#define duk_require_hobject_with_class(ctx,index,classnum) \
- ((duk_hobject *) duk_get_tagged_heaphdr_raw((ctx), (index), \
- DUK_TAG_OBJECT | \
- DUK_GETTAGGED_FLAG_CHECK_CLASS | ((classnum) << DUK_GETTAGGED_CLASS_SHIFT)))
+DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index);
@@ -7540,6 +7477,11 @@ DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv);
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv);
DUK_INTERNAL_DECL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
+#if !defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index);
+DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv);
+#endif
+
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [val] */
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [val] -> [] */
DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [] */
@@ -9806,6 +9748,7 @@ DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *
#define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING (1 << 2) /* refcount code is processing refzero list */
#define DUK_HEAP_FLAG_ERRHANDLER_RUNNING (1 << 3) /* an error handler (user callback to augment/replace error) is running */
#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1 << 4) /* executor interrupt running (used to avoid nested interrupts) */
+#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1 << 5) /* heap destruction ongoing, finalizer rescue no longer possible */
#define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits))
#define DUK__HEAP_SET_FLAGS(heap,bits) do { \
@@ -9820,18 +9763,21 @@ DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *
#define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
#define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
#define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
#define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
#define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
#define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
#define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
#define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
+#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
/*
* Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
@@ -9856,8 +9802,9 @@ DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *
#define DUK_MS_FLAG_EMERGENCY (1 << 0) /* emergency mode: try extra hard */
#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE (1 << 1) /* don't resize stringtable (but may sweep it); needed during stringtable resize */
-#define DUK_MS_FLAG_NO_FINALIZERS (1 << 2) /* don't run finalizers (which may have arbitrary side effects) */
-#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 3) /* don't compact objects; needed during object property allocation resize */
+#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 2) /* don't compact objects; needed during object property allocation resize */
+#define DUK_MS_FLAG_NO_FINALIZERS (1 << 3) /* don't run finalizers; leave finalizable objects in finalize_list for next round */
+#define DUK_MS_FLAG_SKIP_FINALIZERS (1 << 4) /* don't run finalizers; queue finalizable objects back to heap_allocated */
/*
* Thread switching
@@ -10221,6 +10168,7 @@ struct duk_heap {
duk_bool_t dbg_paused; /* currently paused: talk with debug client until step/resume */
duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
duk_bool_t dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
+ duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
duk_small_uint_t dbg_step_type; /* step type: none, step into, step over, step out */
duk_hthread *dbg_step_thread; /* borrowed; NULL if no step state (NULLed in unwind) */
duk_size_t dbg_step_csindex; /* callstack index */
@@ -10234,6 +10182,10 @@ struct duk_heap {
duk_uint32_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
duk_uint32_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
+
+ /* Used to support single-byte stream lookahead. */
+ duk_bool_t dbg_have_next_byte;
+ duk_uint8_t dbg_next_byte;
#endif
/* string intern table (weak refs) */
@@ -10383,6 +10335,7 @@ DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uin
#define DUK_DBG_CMD_ALERT 0x03
#define DUK_DBG_CMD_LOG 0x04
#define DUK_DBG_CMD_THROW 0x05
+#define DUK_DBG_CMD_DETACHING 0x06
/* Initiated by debug client */
#define DUK_DBG_CMD_BASICINFO 0x10
@@ -10433,7 +10386,7 @@ DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *dat
DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
-DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, const void *ptr);
+DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
#endif
@@ -10448,9 +10401,11 @@ DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uin
DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
-DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
-DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr);
+DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
+DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
+#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
+#endif
DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
@@ -10636,7 +10591,7 @@ DUK_INTERNAL_DECL duk_small_int_t duk_debug_level_stash;
DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
#endif /* DUK_USE_VARIADIC_MACROS */
-DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, duk_uint8_t *buffer, duk_size_t length);
+DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
@@ -10694,9 +10649,9 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* fall back to awkward hacks.
*/
-#ifdef DUK_USE_VERBOSE_ERRORS
+#if defined(DUK_USE_VERBOSE_ERRORS)
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
/* __VA_ARGS__ has comma issues for empty lists, so we mandate at least 1 argument for '...' (format string) */
#define DUK_ERROR(thr,err,...) duk_err_handle_error(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (err), __VA_ARGS__)
@@ -10718,7 +10673,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
#else /* DUK_USE_VERBOSE_ERRORS */
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
#define DUK_ERROR(thr,err,...) duk_err_handle_error((thr), (err))
#define DUK_ERROR_RAW(file,line,thr,err,...) duk_err_handle_error((thr), (err))
@@ -10770,7 +10725,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
* Assert macro: failure causes panic.
*/
-#ifdef DUK_USE_ASSERTIONS
+#if defined(DUK_USE_ASSERTIONS)
/* the message should be a compile time constant without formatting (less risk);
* we don't care about assertion text size because they're not used in production
@@ -10862,11 +10817,54 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
#endif
/*
+ * Error throwing helpers
+ *
+ * The goal is to provide verbose and configurable error messages. Call
+ * sites should be clean in source code and compile to a small footprint.
+ * Small footprint is also useful for performance because small cold paths
+ * reduce code cache pressure.
+ */
+
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_PARANOID_ERRORS)
+/* Verbose but paranoid errors. */
+
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
+ duk_err_require_type_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (index), (expectname)); \
+ } while (0)
+#else
+/* Verbose errors with key/value summaries. */
+
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
+ duk_err_require_type_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (index), (expectname)); \
+ } while (0)
+#endif
+#define DUK_ERROR_API_INDEX(thr,index) do { \
+ duk_err_api_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (index)); \
+ } while (0)
+#define DUK_ERROR_API(thr,msg) do { \
+ duk_err_api(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (msg)); \
+ } while (0)
+#else
+/* Non-verbose errors for low memory targets. */
+
+#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
+ duk_err_require_type_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (lowmemstr)); \
+ } while (0)
+#define DUK_ERROR_API_INDEX(thr,index) do { \
+ duk_err_api_index(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr)); \
+ } while (0)
+#define DUK_ERROR_API(thr,msg) do { \
+ duk_err_api(DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (thr), (msg)); \
+ } while (0)
+#endif
+
+/*
* Prototypes
*/
-#ifdef DUK_USE_VERBOSE_ERRORS
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_VARIADIC_MACROS)
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
#else /* DUK_USE_VARIADIC_MACROS */
#if !defined(DUK_SINGLE_FILE)
@@ -10877,7 +10875,7 @@ DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(const char *filename, d
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
#endif /* DUK_USE_VARIADIC_MACROS */
#else /* DUK_USE_VERBOSE_ERRORS */
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
#else /* DUK_USE_VARIADIC_MACROS */
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_nonverbose1(duk_hthread *thr, duk_errcode_t code, const char *fmt, ...));
@@ -10885,7 +10883,7 @@ DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_nonverbose2(const char
#endif /* DUK_USE_VARIADIC_MACROS */
#endif /* DUK_USE_VERBOSE_ERRORS */
-#ifdef DUK_USE_VERBOSE_ERRORS
+#if defined(DUK_USE_VERBOSE_ERRORS)
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
#else
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
@@ -10900,6 +10898,20 @@ DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthrea
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
#endif
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_PARANOID_ERRORS)
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name));
+#else
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name));
+#endif
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message));
+#else
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *error_msg));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr));
+DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message));
+#endif
+
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg));
@@ -11134,12 +11146,13 @@ extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348];
extern const duk_uint8_t duk_unicode_caseconv_uc[1288];
extern const duk_uint8_t duk_unicode_caseconv_lc[616];
-/* FIXME: CONDITIONAL */
+#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
/*
* Automatically generated by extract_caseconv.py, do not edit!
*/
extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
+#endif
/*
* Extern
@@ -11199,10 +11212,8 @@ DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp)
/* How much stack to require on entry to object/array decode */
#define DUK_JSON_DEC_REQSTACK 32
-/* How large a loop detection stack to use for fast path */
-#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+/* How large a loop detection stack to use */
#define DUK_JSON_ENC_LOOPARRAY 64
-#endif
/* Encoding state. Heap object references are all borrowed. */
typedef struct {
@@ -11210,7 +11221,6 @@ typedef struct {
duk_bufwriter_ctx bw; /* output bufwriter */
duk_hobject *h_replacer; /* replacer function */
duk_hstring *h_gap; /* gap (if empty string, NULL) */
- duk_hstring *h_indent; /* current indent (if gap is NULL, this is NULL) */
duk_idx_t idx_proplist; /* explicit PropertyList */
duk_idx_t idx_loop; /* valstack index of loop detection object */
duk_small_uint_t flags;
@@ -11219,6 +11229,7 @@ typedef struct {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
duk_small_uint_t flag_ext_custom;
duk_small_uint_t flag_ext_compatible;
+ duk_small_uint_t flag_ext_custom_or_compatible;
#endif
duk_int_t recursion_depth;
duk_int_t recursion_limit;
@@ -11230,9 +11241,7 @@ typedef struct {
duk_small_uint_t stridx_custom_posinf;
duk_small_uint_t stridx_custom_function;
#endif
-#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
-#endif
} duk_json_enc_ctx;
typedef struct {
@@ -11245,6 +11254,7 @@ typedef struct {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
duk_small_uint_t flag_ext_custom;
duk_small_uint_t flag_ext_compatible;
+ duk_small_uint_t flag_ext_custom_or_compatible;
#endif
duk_int_t recursion_depth;
duk_int_t recursion_limit;
@@ -11527,6 +11537,31 @@ DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
+/* Built-in providers */
+#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
+#endif
+#if defined(DUK_USE_DATE_NOW_TIME)
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx);
+#endif
+#if defined(DUK_USE_DATE_NOW_WINDOWS)
+DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
+#endif
+#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
+DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
+#endif
+#if defined(DUK_USE_DATE_TZO_WINDOWS)
+DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
+#endif
+#if defined(DUK_USE_DATE_PRS_STRPTIME)
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
+#endif
+#if defined(DUK_USE_DATE_PRS_GETDATE)
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
+#endif
+#if defined(DUK_USE_DATE_FMT_STRFTIME)
+DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
+#endif
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
@@ -11541,7 +11576,9 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
-DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_nop_setter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
+DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
@@ -11696,20 +11733,9 @@ DUK_INTERNAL const char *duk_str_not_writable = "not writable";
DUK_INTERNAL const char *duk_str_not_configurable = "not configurable";
DUK_INTERNAL const char *duk_str_invalid_context = "invalid context";
-DUK_INTERNAL const char *duk_str_invalid_index = "invalid index";
DUK_INTERNAL const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
-DUK_INTERNAL const char *duk_str_not_undefined = "not undefined";
-DUK_INTERNAL const char *duk_str_not_null = "not null";
-DUK_INTERNAL const char *duk_str_not_boolean = "not boolean";
-DUK_INTERNAL const char *duk_str_not_number = "not number";
-DUK_INTERNAL const char *duk_str_not_string = "not string";
-DUK_INTERNAL const char *duk_str_not_pointer = "not pointer";
-DUK_INTERNAL const char *duk_str_not_buffer = "not buffer";
+DUK_INTERNAL const char *duk_str_not_buffer = "not buffer"; /* still in use with verbose messages */
DUK_INTERNAL const char *duk_str_unexpected_type = "unexpected type";
-DUK_INTERNAL const char *duk_str_not_thread = "not thread";
-DUK_INTERNAL const char *duk_str_not_compiledfunction = "not compiledfunction";
-DUK_INTERNAL const char *duk_str_not_nativefunction = "not nativefunction";
-DUK_INTERNAL const char *duk_str_not_c_function = "not c function";
DUK_INTERNAL const char *duk_str_defaultvalue_coerce_failed = "[[DefaultValue]] coerce failed";
DUK_INTERNAL const char *duk_str_number_outside_range = "number outside range";
DUK_INTERNAL const char *duk_str_not_object_coercible = "not object coercible";
@@ -11904,18 +11930,6 @@ DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int
DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
-#ifdef DUK_USE_DPRINT_RDTSC
- DUK_FPRINTF(DUK_STDERR, "%s[%s] <%llu> %s:%ld (%s):%s %s%s\n",
- (const char *) duk__get_term_1(level),
- (const char *) duk__get_level_string(level),
- (unsigned long long) DUK_USE_RDTSC(), /* match the inline asm in duk_features.h */
- (const char *) file,
- (long) line,
- (const char *) func,
- (const char *) duk__get_term_2(level),
- (const char *) duk__debug_buf,
- (const char *) duk__get_term_3(level));
-#else
DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%ld (%s):%s %s%s\n",
(const char *) duk__get_term_1(level),
(const char *) duk__get_level_string(level),
@@ -11925,7 +11939,6 @@ DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int
(const char *) duk__get_term_2(level),
(const char *) duk__debug_buf,
(const char *) duk__get_term_3(level));
-#endif
DUK_FFLUSH(DUK_STDERR);
va_end(ap);
@@ -11947,18 +11960,6 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
-#ifdef DUK_USE_DPRINT_RDTSC
- DUK_FPRINTF(DUK_STDERR, "%s[%s] <%llu> %s:%s (%s):%s %s%s\n",
- (const char *) duk__get_term_1(level),
- (const char *) duk__get_level_string(duk_debug_level_stash),
- (unsigned long long) DUK_USE_RDTSC(), /* match duk_features.h */
- (const char *) duk_debug_file_stash,
- (const char *) duk_debug_line_stash,
- (const char *) duk_debug_func_stash,
- (const char *) duk__get_term_2(level),
- (const char *) duk__debug_buf,
- (const char *) duk__get_term_3(level));
-#else
DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%s (%s):%s %s%s\n",
(const char *) duk__get_term_1(level),
(const char *) duk__get_level_string(duk_debug_level_stash),
@@ -11968,7 +11969,6 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
(const char *) duk__get_term_2(level),
(const char *) duk__debug_buf,
(const char *) duk__get_term_3(level));
-#endif
DUK_FFLUSH(DUK_STDERR);
va_end(ap);
@@ -12112,20 +12112,20 @@ DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = {
32,76,71,64,156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,
147,32,134,226,17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,
52,72,40,144,213,33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,
-98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,74,185,3,45,
-142,133,144,150,68,206,81,44,18,145,68,230,202,100,35,104,195,18,239,116,
-102,114,94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,
-10,80,46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,
-1,40,6,33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,
-17,112,130,44,96,
+98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,
+42,228,12,182,58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,
+94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,
+46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,
+33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,
+130,44,96,
};
/* to convert a heap stridx to a token number, subtract
* DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
*/
-/* native functions: 147 */
-DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
+/* native functions: 149 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
duk_bi_array_constructor,
duk_bi_array_constructor_is_array,
duk_bi_array_prototype_concat,
@@ -12173,9 +12173,11 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
duk_bi_duktape_object_info,
duk_bi_error_constructor_shared,
duk_bi_error_prototype_filename_getter,
+ duk_bi_error_prototype_filename_setter,
duk_bi_error_prototype_linenumber_getter,
- duk_bi_error_prototype_nop_setter,
+ duk_bi_error_prototype_linenumber_setter,
duk_bi_error_prototype_stack_getter,
+ duk_bi_error_prototype_stack_setter,
duk_bi_error_prototype_to_string,
duk_bi_function_constructor,
duk_bi_function_prototype,
@@ -12276,38 +12278,38 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
};
DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
-105,195,75,16,121,40,105,51,14,252,104,52,8,131,72,0,115,225,65,165,236,55,
-243,6,145,32,210,24,210,182,25,249,35,120,216,99,226,13,78,225,116,177,164,
+105,195,75,32,121,40,105,53,14,252,104,54,8,131,72,0,115,225,65,165,244,55,
+243,6,145,32,210,24,210,186,25,249,35,120,216,99,226,13,79,33,116,177,164,
180,44,192,4,202,52,150,220,24,0,169,70,146,219,123,0,23,40,210,91,110,96,
3,37,26,75,109,172,0,108,163,73,109,177,128,14,148,105,45,181,176,1,242,
-144,56,209,32,94,6,167,101,98,80,211,24,1,250,67,72,168,67,232,13,46,128,
-47,162,52,164,0,62,80,163,72,128,61,40,107,26,7,37,20,53,200,131,88,0,66,
-134,185,16,98,80,215,34,11,96,0,138,26,228,65,76,0,69,67,92,136,37,128,6,
-168,107,145,4,48,1,165,13,114,32,118,0,44,161,174,68,12,192,7,148,53,200,
-129,88,1,26,134,165,48,130,80,31,255,241,69,224,0,0,0,0,0,0,124,63,174,32,
+144,56,209,36,94,6,167,133,98,80,211,28,1,250,67,72,168,67,232,13,46,192,
+47,162,52,165,0,62,80,163,72,128,61,40,107,26,7,37,20,53,201,131,88,0,66,
+134,185,48,98,80,215,38,11,96,0,138,26,228,193,76,0,69,67,92,152,37,128,6,
+168,107,147,4,48,1,165,13,114,96,118,0,44,161,174,76,12,192,7,148,53,201,
+129,88,1,26,134,165,80,130,80,31,255,241,69,224,0,0,0,0,0,0,124,63,174,32,
0,0,0,0,0,0,120,63,175,98,7,140,16,116,194,7,12,48,108,196,6,140,80,100,
198,6,12,112,92,200,5,140,149,192,202,91,204,181,184,204,91,76,213,176,206,
90,204,240,84,208,5,13,9,124,210,43,13,24,64,226,131,205,112,56,216,3,77,
152,48,218,130,205,184,40,220,130,77,216,32,222,129,205,248,24,224,129,78,
-25,214,163,226,90,80,145,104,65,37,157,0,150,99,242,89,78,73,100,58,37,140,
-236,150,35,194,88,79,73,96,69,37,125,12,122,188,134,62,0,2,165,68,39,255,
-255,193,43,67,0,0,80,127,192,58,182,216,80,0,21,59,154,64,0,107,76,200,172,
-180,146,176,198,138,187,43,42,204,136,170,181,146,168,214,80,0,26,155,81,
-42,77,4,168,180,20,0,6,160,206,74,123,73,64,0,127,255,4,10,153,219,28,198,
-163,184,130,140,224,10,43,144,40,141,164,161,183,18,132,222,64,161,127,128,
-0,63,225,1,109,74,8,137,71,56,5,4,213,20,3,115,233,249,177,240,80,255,192,
+25,214,164,2,90,81,17,104,67,37,157,8,150,100,18,89,78,201,100,60,37,140,
+244,150,35,226,88,79,201,96,71,37,125,20,122,188,138,62,0,2,165,70,39,255,
+255,193,43,67,0,0,80,127,192,58,182,220,80,0,21,59,170,64,0,107,77,8,172,
+181,146,176,202,138,187,59,42,204,200,170,182,146,168,218,80,0,26,155,97,
+42,77,68,168,181,20,0,6,160,210,74,123,89,64,0,127,255,4,10,153,219,157,70,
+163,185,130,140,228,10,43,160,40,141,228,161,184,18,132,226,64,161,127,128,
+0,63,225,1,109,74,8,137,71,58,5,4,221,20,3,147,233,249,193,240,80,255,192,
6,120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,
131,2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,
207,192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,
88,8,106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,
-135,195,224,127,196,2,87,132,17,82,143,20,10,44,80,36,239,196,147,63,146,
-119,0,125,49,129,52,152,64,154,128,0,201,96,137,36,131,36,142,17,18,40,82,
-77,97,145,33,135,68,130,37,17,247,208,71,159,65,29,125,8,0,12,113,244,32,0,
-49,184,176,70,162,16,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,
-0,81,191,197,140,192,255,255,255,255,255,255,239,127,140,64,1,0,0,0,0,0,0,
-0,139,192,0,0,0,0,0,0,248,127,138,192,0,0,0,0,0,0,240,127,139,64,0,0,0,0,0,
-0,240,255,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,96,37,25,120,148,86,
-16,69,23,73,19,92,36,73,124,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
+135,227,224,127,196,2,87,132,17,82,143,24,10,44,96,36,240,4,147,64,146,119,
+4,125,49,131,52,152,65,154,128,0,201,97,9,36,133,36,142,25,18,40,114,77,98,
+17,33,137,68,130,45,17,247,240,71,159,193,29,127,8,0,12,113,252,32,0,49,
+184,208,70,162,144,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,0,
+81,191,197,140,192,255,255,255,255,255,255,239,127,140,64,1,0,0,0,0,0,0,0,
+139,192,0,0,0,0,0,0,248,127,138,192,0,0,0,0,0,0,240,127,139,64,0,0,0,0,0,0,
+240,255,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,98,37,25,128,148,86,48,
+69,23,201,19,94,36,73,132,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
254,56,18,188,128,0,0,0,0,0,15,135,251,104,228,128,135,18,4,0,6,26,72,16,0,
42,49,32,64,0,225,132,129,0,4,133,146,4,0,21,210,72,16,0,103,65,32,64,1,
220,228,100,162,146,130,20,74,8,72,248,64,2,33,3,225,0,9,131,143,132,0,42,
@@ -12318,9 +12320,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
33,127,0,29,120,144,207,128,15,60,8,103,192,7,221,228,37,0,32,119,16,148,0,
133,218,66,190,0,68,236,33,95,0,35,117,144,191,128,18,58,136,95,192,9,92,
195,225,0,38,114,144,148,0,156,41,31,224,0,15,249,1,138,144,64,192,2,2,225,
-132,221,9,70,112,70,111,198,111,72,0,0,0,0,0,0,0,0,13,198,240,71,19,201,40,
-239,64,10,79,248,0,3,254,72,86,209,5,155,36,17,46,185,137,129,109,203,140,
-11,78,94,96,13,28,200,1,74,255,0,2,127,202,4,218,43,131,100,130,32,5,47,
+132,221,9,70,112,70,111,198,111,72,0,0,0,0,0,0,0,0,13,198,244,71,19,217,40,
+239,128,10,79,248,0,3,254,72,86,209,5,155,36,17,46,185,145,153,109,203,139,
+203,78,96,98,13,28,208,1,74,255,0,2,127,202,4,218,43,131,100,130,32,5,47,
252,0,9,255,44,19,104,173,237,146,8,128,20,207,240,0,39,252,192,77,162,183,
54,72,34,0,83,127,192,0,159,243,65,54,138,218,217,32,136,1,78,255,0,2,127,
206,4,218,43,99,100,130,32,5,63,252,0,9,255,60,19,104,173,109,146,8,128,15,
@@ -12328,126 +12330,51 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
144,26,208,59,206,126,191,144,139,185,143,218,176,63,160,138,217,81,197,
125,207,218,144,3,185,73,133,94,242,246,207,218,112,6,11,81,21,62,200,66,
80,26,80,51,78,223,217,167,168,57,143,218,48,51,78,223,217,167,168,61,143,
-210,104,39,17,158,156,80,0,22,114,113,64,0,153,169,197,0,3,102,40,33,150,
-156,80,0,70,82,113,64,1,89,41,197,0,6,100,39,20,0,29,142,156,80,0,134,50,
-98,243,21,53,121,136,160,144,0,22,26,120,24,73,197,0,9,96,167,20,0,41,128,
-156,80,0,181,250,113,64,3,1,255,254,0,81,20,100,47,145,216,23,255,240,0,11,
-255,248,0,3,255,252,81,252,0,0,0,0,8,4,252,68,0,129,167,1,26,144,9,165,0,
-26,177,199,197,132,30,147,16,120,86,65,217,80,240,232,164,120,114,80,60,52,
-39,32,84,223,192,15,59,30,129,156,115,6,81,160,7,253,40,0,5,81,252,0,1,255,
-78,0,84,113,96,128,0,209,69,128,21,87,240,0,7,253,72,1,81,221,66,0,3,69,
-117,0,85,159,192,0,31,245,97,10,100,0,0,0,0,0,0,0,32,10,164,130,97,221,191,
-113,3,20,146,12,18,200,47,74,30,23,37,15,128,0,143,146,135,192,0,133,169,
-67,224,0,98,196,161,240,0,65,90,80,248,0,41,63,255,194,109,65,11,137,191,
-174,45,153,98,242,229,191,147,102,8,190,94,92,183,242,65,167,114,12,188,
-185,111,228,131,70,29,217,54,105,221,156,0,171,255,128,9,208,68,128,255,
-174,0,25,168,194,64,0,130,177,254,0,0,255,176,1,3,120,186,64,12,13,194,233,
-0,32,54,139,164,0,196,216,46,144,2,19,88,186,64,12,141,66,233,0,34,52,139,
-164,0,140,208,46,144,2,67,56,203,64,12,12,195,45,0,32,50,140,180,0,196,200,
-50,208,2,19,24,203,64,12,140,67,45,0,34,48,140,180,0,140,192,50,208,2,64,
-127,255,128,21,38,73,7,1,132,128,0,133,105,252,19,140,0,0,0,0,0,0,15,3,240,
-25,127,102,0,1,91,127,4,227,0,0,0,0,0,0,3,192,252,6,95,218,128,0,87,31,193,
-56,192,0,0,0,0,0,0,240,63,1,151,246,224,0,21,215,240,78,48,0,0,0,0,0,0,0,
-16,0,101,253,200,0,5,121,252,19,140,0,0,0,0,0,0,0,4,0,25,127,118,0,1,95,
-127,4,227,0,0,0,0,0,0,0,65,0,6,95,222,128,0,88,31,193,56,192,0,0,0,0,0,0,
-16,64,1,151,247,224,0,22,23,240,78,48,0,0,0,0,0,0,4,16,0,101,254,8,0,5,137,
-252,19,140,0,0,0,0,0,0,2,4,0,25,127,134,0,1,99,127,0,89,218,146,20,74,228,
-80,171,17,64,162,132,248,162,64,0,193,255,138,5,137,161,116,38,69,210,0,32,
-152,23,72,0,10,92,93,32,1,41,97,116,128,8,165,69,210,0,50,148,23,72,0,18,
-76,93,32,1,73,33,116,128,9,36,69,210,0,52,144,23,72,0,26,60,93,32,1,104,
-225,116,128,2,35,69,210,0,24,140,23,104,0,42,44,93,160,1,168,161,118,128,
-10,162,69,218,0,58,136,25,98,28,101,160,2,8,97,150,128,0,161,70,90,0,18,
-132,25,104,0,138,12,101,160,3,40,33,150,128,1,32,70,90,0,20,128,25,104,0,
-145,252,101,160,3,71,225,150,128,1,159,70,90,0,22,124,25,104,0,33,236,101,
-160,1,135,161,152,128,2,158,70,98,0,26,120,25,136,0,169,220,102,32,3,180,
-117,150,57,214,0,157,85,98,112,80,137,241,66,128,0,166,213,33,53,24,66,121,
-106,0,
+210,104,40,17,158,160,80,0,22,114,129,64,0,153,170,5,0,3,102,41,33,150,160,
+80,0,70,82,129,64,1,89,42,5,0,6,100,40,20,0,29,142,160,80,0,134,50,114,243,
+21,61,121,136,164,144,0,22,26,136,24,74,5,0,9,96,168,20,0,41,128,160,80,0,
+181,250,129,64,3,1,255,254,0,81,20,132,47,146,88,23,255,240,0,11,255,248,0,
+3,255,252,81,252,0,0,0,0,8,4,252,68,0,129,167,1,26,144,9,165,0,26,177,199,
+197,132,30,147,16,120,86,65,217,80,240,232,164,120,114,80,60,52,39,32,84,
+223,192,15,59,34,129,156,131,6,81,224,7,253,40,0,5,81,252,0,1,255,78,0,84,
+113,96,128,0,209,69,128,21,87,240,0,7,253,72,1,81,221,194,0,3,69,119,0,85,
+159,192,0,31,245,97,10,100,0,0,0,0,0,0,0,32,10,164,130,97,221,191,113,3,20,
+178,12,19,72,47,76,30,23,38,15,128,0,143,147,7,192,0,133,169,131,224,0,98,
+196,193,240,0,65,90,96,248,0,41,63,255,194,109,65,11,137,191,174,45,153,98,
+242,229,191,147,102,8,190,94,92,183,242,65,167,114,12,188,185,111,228,131,
+70,29,217,54,105,221,156,0,171,255,128,9,208,68,128,255,174,0,25,168,194,
+64,0,130,177,254,0,0,255,176,1,3,120,186,64,12,13,194,233,0,32,54,139,164,
+0,196,216,46,144,2,19,88,186,64,12,141,66,233,0,34,52,139,164,0,140,208,46,
+144,2,67,56,203,64,12,12,195,45,0,32,50,140,180,0,196,200,50,208,2,19,24,
+203,64,12,140,67,45,0,34,48,140,180,0,140,192,50,208,2,64,127,255,128,21,
+38,81,7,1,132,128,0,133,105,252,19,140,0,0,0,0,0,0,15,3,240,25,127,102,0,1,
+91,127,4,227,0,0,0,0,0,0,3,192,252,6,95,218,128,0,87,31,193,56,192,0,0,0,0,
+0,0,240,63,1,151,246,224,0,21,215,240,78,48,0,0,0,0,0,0,0,16,0,101,253,200,
+0,5,121,252,19,140,0,0,0,0,0,0,0,4,0,25,127,118,0,1,95,127,4,227,0,0,0,0,0,
+0,0,65,0,6,95,222,128,0,88,31,193,56,192,0,0,0,0,0,0,16,64,1,151,247,224,0,
+22,23,240,78,48,0,0,0,0,0,0,4,16,0,101,254,8,0,5,137,252,19,140,0,0,0,0,0,
+0,2,4,0,25,127,134,0,1,99,127,0,89,218,162,20,75,36,80,172,17,64,166,132,
+248,162,64,0,193,255,138,5,137,161,116,38,69,210,0,32,152,23,72,0,10,92,93,
+32,1,41,97,116,128,8,165,69,210,0,50,148,23,72,0,18,76,93,32,1,73,33,116,
+128,9,36,69,210,0,52,144,23,72,0,26,60,93,32,1,104,225,116,128,2,35,69,210,
+0,24,140,23,104,0,42,44,93,160,1,168,161,118,128,10,162,69,218,0,58,136,25,
+98,28,101,160,2,8,97,150,128,0,161,70,90,0,18,132,25,104,0,138,12,101,160,
+3,40,33,150,128,1,32,70,90,0,20,128,25,104,0,145,252,101,160,3,71,225,150,
+128,1,159,70,90,0,22,124,25,104,0,33,236,101,160,1,135,161,152,128,2,158,
+70,98,0,26,120,25,136,0,169,220,102,32,3,180,117,182,57,214,128,157,87,98,
+112,80,137,241,66,128,0,166,213,161,53,24,66,121,114,0,
};
#ifdef DUK_USE_BUILTIN_INITJS
-DUK_INTERNAL const duk_uint8_t duk_initjs_data[1757] = {
-47,42,10,32,42,32,32,73,110,105,116,32,99,111,100,101,32,102,111,114,32,
-108,101,103,97,99,121,32,99,111,109,112,97,116,105,98,105,108,105,116,121,
-46,10,32,42,10,32,42,32,32,67,111,109,112,97,116,105,98,105,108,105,116,
-121,32,112,114,111,112,101,114,116,105,101,115,32,47,32,119,114,97,112,112,
-101,114,32,102,117,110,99,116,105,111,110,115,32,104,101,114,101,32,97,108,
-108,111,119,32,68,117,107,116,97,112,101,32,116,111,32,114,101,109,97,105,
-110,10,32,42,32,32,99,111,109,112,97,116,105,98,108,101,32,102,111,114,32,
-117,115,101,114,32,99,111,100,101,32,119,104,101,110,32,99,111,114,101,32,
-102,101,97,116,117,114,101,115,32,97,114,101,32,99,104,97,110,103,101,100,
-44,32,119,105,116,104,111,117,116,32,98,117,114,100,101,110,105,110,103,10,
-32,42,32,32,116,104,101,32,109,97,105,110,32,67,32,99,111,100,101,32,119,
-105,116,104,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,115,116,
-117,102,102,46,10,32,42,10,32,42,32,32,84,104,105,115,32,102,105,108,101,
-32,105,115,32,109,105,110,105,102,105,101,100,32,119,105,116,104,32,85,103,
-108,105,102,121,74,83,32,111,114,32,116,104,101,32,99,108,111,115,117,114,
-101,32,99,111,109,112,105,108,101,114,46,32,32,66,111,116,104,32,119,105,
-108,108,10,32,42,32,32,114,101,110,97,109,101,32,118,97,114,105,97,98,108,
-101,115,44,32,114,101,109,111,118,101,32,99,111,109,109,101,110,116,115,44,
-32,97,110,100,32,97,114,101,32,99,108,101,118,101,114,32,101,110,111,117,
-103,104,32,116,111,32,100,114,111,112,32,97,110,121,10,32,42,32,32,34,105,
-102,32,40,102,97,108,115,101,41,32,123,32,46,46,46,32,125,34,32,98,108,111,
-99,107,115,32,97,108,116,111,103,101,116,104,101,114,44,32,115,111,32,116,
-104,97,116,39,115,32,97,110,32,101,102,102,101,99,116,105,118,101,32,119,
-97,121,32,116,111,10,32,42,32,32,100,105,115,97,98,108,101,32,99,117,114,
-114,101,110,116,108,121,32,117,110,110,101,101,100,101,100,32,99,111,100,
-101,46,10,32,42,47,10,10,40,102,117,110,99,116,105,111,110,40,71,44,32,68,
-41,32,123,10,32,32,32,32,39,117,115,101,32,115,116,114,105,99,116,39,59,10,
-10,32,32,32,32,102,117,110,99,116,105,111,110,32,100,101,102,40,111,98,106,
-101,99,116,44,32,110,97,109,101,44,32,118,97,108,117,101,41,32,123,10,32,
-32,32,32,32,32,32,32,79,98,106,101,99,116,46,100,101,102,105,110,101,80,
-114,111,112,101,114,116,121,40,111,98,106,101,99,116,44,32,110,97,109,101,
-44,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,118,97,108,117,101,58,32,
-118,97,108,117,101,44,10,32,32,32,32,32,32,32,32,32,32,32,32,119,114,105,
-116,97,98,108,101,58,32,116,114,117,101,44,10,32,32,32,32,32,32,32,32,32,
-32,32,32,101,110,117,109,101,114,97,98,108,101,58,32,102,97,108,115,101,44,
-10,32,32,32,32,32,32,32,32,32,32,32,32,99,111,110,102,105,103,117,114,97,
-98,108,101,58,32,116,114,117,101,10,32,32,32,32,32,32,32,32,125,41,59,10,
-32,32,32,32,125,10,10,32,32,32,32,102,117,110,99,116,105,111,110,32,100,
-101,102,68,40,110,97,109,101,44,32,118,97,108,117,101,41,32,123,10,32,32,
-32,32,32,32,32,32,100,101,102,40,68,44,32,110,97,109,101,44,32,118,97,108,
-117,101,41,59,10,32,32,32,32,125,10,10,32,32,32,32,47,47,32,67,111,109,112,
-97,116,105,98,105,108,105,116,121,32,102,111,114,32,39,99,111,110,115,111,
-108,101,46,108,111,103,39,46,10,32,32,32,32,105,102,32,40,102,97,108,115,
-101,41,32,123,10,32,32,32,32,32,32,32,32,99,111,110,115,111,108,101,32,61,
-32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,108,111,103,58,32,102,117,
-110,99,116,105,111,110,40,41,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,112,114,105,110,116,40,65,114,114,97,121,46,112,114,111,116,
-111,116,121,112,101,46,106,111,105,110,46,99,97,108,108,40,97,114,103,117,
-109,101,110,116,115,44,32,39,32,39,41,41,59,10,32,32,32,32,32,32,32,32,32,
-32,32,32,125,10,32,32,32,32,32,32,32,32,125,59,10,32,32,32,32,125,10,10,32,
-32,32,32,47,47,32,68,117,107,116,97,112,101,46,108,105,110,101,40,41,32,
-119,97,115,32,114,101,109,111,118,101,100,32,105,110,32,68,117,107,116,97,
-112,101,32,48,46,49,49,46,48,44,32,104,101,114,101,39,115,32,97,110,32,101,
-120,97,109,112,108,101,10,32,32,32,32,47,47,32,114,101,112,108,97,99,101,
-109,101,110,116,32,117,115,101,114,32,99,111,100,101,32,99,111,117,108,100,
-32,117,115,101,46,10,32,32,32,32,105,102,32,40,102,97,108,115,101,41,32,
-123,10,32,32,32,32,32,32,32,32,100,101,102,40,68,44,32,39,108,105,110,101,
-39,44,32,102,117,110,99,116,105,111,110,32,40,41,32,123,10,32,32,32,32,32,
-32,32,32,32,32,32,32,39,117,115,101,32,100,117,107,32,110,111,116,97,105,
-108,39,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,42,32,84,97,105,108,
-32,99,97,108,108,115,32,97,114,101,32,112,114,101,118,101,110,116,101,100,
-32,116,111,32,101,110,115,117,114,101,32,99,97,108,108,105,110,103,32,97,
-99,116,105,118,97,116,105,111,110,32,101,120,105,115,116,115,46,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,42,32,67,97,108,108,32,115,116,97,99,107,
-32,105,110,100,105,99,101,115,58,32,45,49,32,61,32,68,117,107,116,97,112,
-101,46,97,99,116,44,32,45,50,32,61,32,103,101,116,67,117,114,114,101,110,
-116,76,105,110,101,44,32,45,51,32,61,32,99,97,108,108,101,114,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,42,47,10,10,32,32,32,32,32,32,32,32,32,32,32,
-32,114,101,116,117,114,110,32,40,68,117,107,116,97,112,101,46,97,99,116,40,
-45,51,41,32,124,124,32,123,125,41,46,108,105,110,101,78,117,109,98,101,114,
-59,10,32,32,32,32,32,32,32,32,125,41,59,10,32,32,32,32,125,10,10,32,32,32,
-32,47,47,32,76,111,103,103,101,114,32,111,98,106,101,99,116,32,102,111,114,
-32,67,32,99,111,100,101,32,112,114,111,118,105,100,101,100,32,98,121,32,
-105,110,105,116,32,99,111,100,101,32,110,111,119,46,10,32,32,32,32,105,102,
-32,40,116,114,117,101,41,32,123,10,32,32,32,32,32,32,32,32,100,101,102,40,
-68,46,76,111,103,103,101,114,44,32,39,99,108,111,103,39,44,32,110,101,119,
-32,68,46,76,111,103,103,101,114,40,39,67,39,41,41,59,10,32,32,32,32,125,10,
-10,32,32,32,32,47,47,32,84,114,97,99,107,105,110,103,32,116,97,98,108,101,
-32,102,111,114,32,67,111,109,109,111,110,74,83,32,109,111,100,117,108,101,
-32,108,111,97,100,105,110,103,46,10,32,32,32,32,105,102,32,40,116,114,117,
-101,41,32,123,10,32,32,32,32,32,32,32,32,100,101,102,40,68,44,32,39,109,
-111,100,76,111,97,100,101,100,39,44,32,123,125,41,59,10,32,32,32,32,125,10,
-125,41,40,116,104,105,115,44,32,68,117,107,116,97,112,101,41,59,10,0,
+DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = {
+40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
+105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
+102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
+108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
+109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
+108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
+108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
+41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
+125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
};
#endif /* DUK_USE_BUILTIN_INITJS */
#elif defined(DUK_USE_DOUBLE_BE)
@@ -12572,20 +12499,20 @@ DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = {
32,76,71,64,156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,
147,32,134,226,17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,
52,72,40,144,213,33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,
-98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,74,185,3,45,
-142,133,144,150,68,206,81,44,18,145,68,230,202,100,35,104,195,18,239,116,
-102,114,94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,
-10,80,46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,
-1,40,6,33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,
-17,112,130,44,96,
+98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,
+42,228,12,182,58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,
+94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,
+46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,
+33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,
+130,44,96,
};
/* to convert a heap stridx to a token number, subtract
* DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
*/
-/* native functions: 147 */
-DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
+/* native functions: 149 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
duk_bi_array_constructor,
duk_bi_array_constructor_is_array,
duk_bi_array_prototype_concat,
@@ -12633,9 +12560,11 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
duk_bi_duktape_object_info,
duk_bi_error_constructor_shared,
duk_bi_error_prototype_filename_getter,
+ duk_bi_error_prototype_filename_setter,
duk_bi_error_prototype_linenumber_getter,
- duk_bi_error_prototype_nop_setter,
+ duk_bi_error_prototype_linenumber_setter,
duk_bi_error_prototype_stack_getter,
+ duk_bi_error_prototype_stack_setter,
duk_bi_error_prototype_to_string,
duk_bi_function_constructor,
duk_bi_function_prototype,
@@ -12736,38 +12665,38 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
};
DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
-105,195,75,16,121,40,105,51,14,252,104,52,8,131,72,0,115,225,65,165,236,55,
-243,6,145,32,210,24,210,182,25,249,35,120,216,99,226,13,78,225,116,177,164,
+105,195,75,32,121,40,105,53,14,252,104,54,8,131,72,0,115,225,65,165,244,55,
+243,6,145,32,210,24,210,186,25,249,35,120,216,99,226,13,79,33,116,177,164,
180,44,192,4,202,52,150,220,24,0,169,70,146,219,123,0,23,40,210,91,110,96,
3,37,26,75,109,172,0,108,163,73,109,177,128,14,148,105,45,181,176,1,242,
-144,56,209,32,94,6,167,101,98,80,211,24,1,250,67,72,168,67,232,13,46,128,
-47,162,52,164,0,62,80,163,72,128,61,40,107,26,7,37,20,53,200,131,88,0,66,
-134,185,16,98,80,215,34,11,96,0,138,26,228,65,76,0,69,67,92,136,37,128,6,
-168,107,145,4,48,1,165,13,114,32,118,0,44,161,174,68,12,192,7,148,53,200,
-129,88,1,26,134,165,48,130,80,31,255,241,69,224,63,252,0,0,0,0,0,0,46,32,
+144,56,209,36,94,6,167,133,98,80,211,28,1,250,67,72,168,67,232,13,46,192,
+47,162,52,165,0,62,80,163,72,128,61,40,107,26,7,37,20,53,201,131,88,0,66,
+134,185,48,98,80,215,38,11,96,0,138,26,228,193,76,0,69,67,92,152,37,128,6,
+168,107,147,4,48,1,165,13,114,96,118,0,44,161,174,76,12,192,7,148,53,201,
+129,88,1,26,134,165,80,130,80,31,255,241,69,224,63,252,0,0,0,0,0,0,46,32,
63,248,0,0,0,0,0,0,47,98,7,140,16,116,194,7,12,48,108,196,6,140,80,100,198,
6,12,112,92,200,5,140,149,192,202,91,204,181,184,204,91,76,213,176,206,90,
204,240,84,208,5,13,9,124,210,43,13,24,64,226,131,205,112,56,216,3,77,152,
48,218,130,205,184,40,220,130,77,216,32,222,129,205,248,24,224,129,78,25,
-214,163,226,90,80,145,104,65,37,157,0,150,99,242,89,78,73,100,58,37,140,
-236,150,35,194,88,79,73,96,69,37,125,12,122,188,134,62,0,2,165,68,39,255,
-255,193,43,67,0,0,80,127,192,58,182,216,80,0,21,59,154,64,0,107,76,200,172,
-180,146,176,198,138,187,43,42,204,136,170,181,146,168,214,80,0,26,155,81,
-42,77,4,168,180,20,0,6,160,206,74,123,73,64,0,127,255,4,10,153,219,28,198,
-163,184,130,140,224,10,43,144,40,141,164,161,183,18,132,222,64,161,127,128,
-0,63,225,1,109,74,8,137,71,56,5,4,213,20,3,115,233,249,177,240,80,255,192,
-6,120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,
-131,2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,
-207,192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,
-88,8,106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,
-135,195,224,127,196,2,87,132,17,82,143,20,10,44,80,36,239,196,147,63,146,
-119,0,125,49,129,52,152,64,154,128,0,201,96,137,36,131,36,142,17,18,40,82,
-77,97,145,33,135,68,130,37,17,247,208,71,159,65,29,125,8,0,12,113,244,32,0,
-49,184,176,70,162,16,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,
-0,81,191,197,140,192,127,239,255,255,255,255,255,255,140,64,0,0,0,0,0,0,0,
-1,139,192,127,248,0,0,0,0,0,0,138,192,127,240,0,0,0,0,0,0,139,64,255,240,0,
-0,0,0,0,0,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,96,37,25,120,148,86,
-16,69,23,73,19,92,36,73,124,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
+214,164,2,90,81,17,104,67,37,157,8,150,100,18,89,78,201,100,60,37,140,244,
+150,35,226,88,79,201,96,71,37,125,20,122,188,138,62,0,2,165,70,39,255,255,
+193,43,67,0,0,80,127,192,58,182,220,80,0,21,59,170,64,0,107,77,8,172,181,
+146,176,202,138,187,59,42,204,200,170,182,146,168,218,80,0,26,155,97,42,77,
+68,168,181,20,0,6,160,210,74,123,89,64,0,127,255,4,10,153,219,157,70,163,
+185,130,140,228,10,43,160,40,141,228,161,184,18,132,226,64,161,127,128,0,
+63,225,1,109,74,8,137,71,58,5,4,221,20,3,147,233,249,193,240,80,255,192,6,
+120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,131,
+2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,207,
+192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,88,8,
+106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,135,
+227,224,127,196,2,87,132,17,82,143,24,10,44,96,36,240,4,147,64,146,119,4,
+125,49,131,52,152,65,154,128,0,201,97,9,36,133,36,142,25,18,40,114,77,98,
+17,33,137,68,130,45,17,247,240,71,159,193,29,127,8,0,12,113,252,32,0,49,
+184,208,70,162,144,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,0,
+81,191,197,140,192,127,239,255,255,255,255,255,255,140,64,0,0,0,0,0,0,0,1,
+139,192,127,248,0,0,0,0,0,0,138,192,127,240,0,0,0,0,0,0,139,64,255,240,0,0,
+0,0,0,0,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,98,37,25,128,148,86,48,
+69,23,201,19,94,36,73,132,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
254,56,18,188,135,255,128,0,0,0,0,0,11,104,228,128,135,18,4,0,6,26,72,16,0,
42,49,32,64,0,225,132,129,0,4,133,146,4,0,21,210,72,16,0,103,65,32,64,1,
220,228,100,162,146,130,20,74,8,72,248,64,2,33,3,225,0,9,131,143,132,0,42,
@@ -12778,9 +12707,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
33,127,0,29,120,144,207,128,15,60,8,103,192,7,221,228,37,0,32,119,16,148,0,
133,218,66,190,0,68,236,33,95,0,35,117,144,191,128,18,58,136,95,192,9,92,
195,225,0,38,114,144,148,0,156,41,31,224,0,15,249,1,138,144,64,192,2,2,225,
-132,221,9,70,112,70,111,198,111,72,0,0,0,0,0,0,0,0,13,198,240,71,19,201,40,
-239,64,10,79,248,0,3,254,72,86,209,5,155,36,17,46,185,137,129,109,203,140,
-11,78,94,96,13,28,200,1,74,255,0,2,127,202,4,218,43,131,100,130,32,5,47,
+132,221,9,70,112,70,111,198,111,72,0,0,0,0,0,0,0,0,13,198,244,71,19,217,40,
+239,128,10,79,248,0,3,254,72,86,209,5,155,36,17,46,185,145,153,109,203,139,
+203,78,96,98,13,28,208,1,74,255,0,2,127,202,4,218,43,131,100,130,32,5,47,
252,0,9,255,44,19,104,173,237,146,8,128,20,207,240,0,39,252,192,77,162,183,
54,72,34,0,83,127,192,0,159,243,65,54,138,218,217,32,136,1,78,255,0,2,127,
206,4,218,43,99,100,130,32,5,63,252,0,9,255,60,19,104,173,109,146,8,128,15,
@@ -12788,125 +12717,51 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
69,154,208,15,249,139,144,191,190,142,123,218,176,15,253,197,81,217,74,224,
191,154,144,15,246,242,222,197,73,185,67,154,112,16,2,72,126,213,17,11,70,
26,80,15,249,168,39,153,159,206,243,90,48,15,253,168,39,153,159,206,243,82,
-104,39,17,158,156,80,0,22,114,113,64,0,153,169,197,0,3,102,40,33,150,156,
-80,0,70,82,113,64,1,89,41,197,0,6,100,39,20,0,29,142,156,80,0,134,50,98,
-243,21,53,121,136,160,144,0,22,26,120,24,73,197,0,9,96,167,20,0,41,128,156,
-80,0,181,250,113,64,3,1,255,254,0,81,20,100,47,145,216,23,255,240,0,11,255,
-248,0,3,255,252,81,252,4,12,68,248,0,0,0,0,0,129,167,1,26,144,9,165,0,26,
-177,199,197,132,30,147,16,120,86,65,217,80,240,232,164,120,114,80,60,52,39,
-32,84,223,192,15,59,30,129,156,115,6,81,160,7,253,40,0,5,81,252,0,1,255,78,
-0,84,113,96,128,0,209,69,128,21,87,240,0,7,253,72,1,81,221,66,0,3,69,117,0,
-85,159,192,0,31,245,97,10,100,32,0,0,0,0,0,0,0,10,164,130,97,221,191,113,3,
-20,146,12,18,200,47,74,30,23,37,15,128,0,143,146,135,192,0,133,169,67,224,
-0,98,196,161,240,0,65,90,80,248,0,41,63,255,194,109,65,11,137,191,174,45,
-153,98,242,229,191,147,102,8,190,94,92,183,242,65,167,114,12,188,185,111,
-228,131,70,29,217,54,105,221,156,0,171,255,128,9,208,68,128,255,174,0,25,
-168,194,64,0,130,177,254,0,0,255,176,1,3,120,186,64,12,13,194,233,0,32,54,
-139,164,0,196,216,46,144,2,19,88,186,64,12,141,66,233,0,34,52,139,164,0,
-140,208,46,144,2,67,56,203,64,12,12,195,45,0,32,50,140,180,0,196,200,50,
-208,2,19,24,203,64,12,140,67,45,0,34,48,140,180,0,140,192,50,208,2,64,127,
-255,128,21,38,73,7,1,132,128,0,133,105,252,19,140,3,255,0,0,0,0,0,0,0,25,
-127,102,0,1,91,127,4,227,0,255,192,0,0,0,0,0,0,6,95,218,128,0,87,31,193,56,
-192,63,240,0,0,0,0,0,0,1,151,246,224,0,21,215,240,78,48,16,0,0,0,0,0,0,0,0,
-101,253,200,0,5,121,252,19,140,4,0,0,0,0,0,0,0,0,25,127,118,0,1,95,127,4,
-227,1,0,64,0,0,0,0,0,0,6,95,222,128,0,88,31,193,56,192,64,16,0,0,0,0,0,0,1,
-151,247,224,0,22,23,240,78,48,16,4,0,0,0,0,0,0,0,101,254,8,0,5,137,252,19,
-140,4,2,0,0,0,0,0,0,0,25,127,134,0,1,99,127,0,89,218,146,20,74,228,80,171,
-17,64,162,132,248,162,64,0,193,255,138,5,137,161,116,38,69,210,0,32,152,23,
-72,0,10,92,93,32,1,41,97,116,128,8,165,69,210,0,50,148,23,72,0,18,76,93,32,
-1,73,33,116,128,9,36,69,210,0,52,144,23,72,0,26,60,93,32,1,104,225,116,128,
-2,35,69,210,0,24,140,23,104,0,42,44,93,160,1,168,161,118,128,10,162,69,218,
-0,58,136,25,98,28,101,160,2,8,97,150,128,0,161,70,90,0,18,132,25,104,0,138,
-12,101,160,3,40,33,150,128,1,32,70,90,0,20,128,25,104,0,145,252,101,160,3,
-71,225,150,128,1,159,70,90,0,22,124,25,104,0,33,236,101,160,1,135,161,152,
-128,2,158,70,98,0,26,120,25,136,0,169,220,102,32,3,180,117,150,57,214,0,
-157,85,98,112,80,137,241,66,128,0,166,213,33,53,24,66,121,106,0,
+104,40,17,158,160,80,0,22,114,129,64,0,153,170,5,0,3,102,41,33,150,160,80,
+0,70,82,129,64,1,89,42,5,0,6,100,40,20,0,29,142,160,80,0,134,50,114,243,21,
+61,121,136,164,144,0,22,26,136,24,74,5,0,9,96,168,20,0,41,128,160,80,0,181,
+250,129,64,3,1,255,254,0,81,20,132,47,146,88,23,255,240,0,11,255,248,0,3,
+255,252,81,252,4,12,68,248,0,0,0,0,0,129,167,1,26,144,9,165,0,26,177,199,
+197,132,30,147,16,120,86,65,217,80,240,232,164,120,114,80,60,52,39,32,84,
+223,192,15,59,34,129,156,131,6,81,224,7,253,40,0,5,81,252,0,1,255,78,0,84,
+113,96,128,0,209,69,128,21,87,240,0,7,253,72,1,81,221,194,0,3,69,119,0,85,
+159,192,0,31,245,97,10,100,32,0,0,0,0,0,0,0,10,164,130,97,221,191,113,3,20,
+178,12,19,72,47,76,30,23,38,15,128,0,143,147,7,192,0,133,169,131,224,0,98,
+196,193,240,0,65,90,96,248,0,41,63,255,194,109,65,11,137,191,174,45,153,98,
+242,229,191,147,102,8,190,94,92,183,242,65,167,114,12,188,185,111,228,131,
+70,29,217,54,105,221,156,0,171,255,128,9,208,68,128,255,174,0,25,168,194,
+64,0,130,177,254,0,0,255,176,1,3,120,186,64,12,13,194,233,0,32,54,139,164,
+0,196,216,46,144,2,19,88,186,64,12,141,66,233,0,34,52,139,164,0,140,208,46,
+144,2,67,56,203,64,12,12,195,45,0,32,50,140,180,0,196,200,50,208,2,19,24,
+203,64,12,140,67,45,0,34,48,140,180,0,140,192,50,208,2,64,127,255,128,21,
+38,81,7,1,132,128,0,133,105,252,19,140,3,255,0,0,0,0,0,0,0,25,127,102,0,1,
+91,127,4,227,0,255,192,0,0,0,0,0,0,6,95,218,128,0,87,31,193,56,192,63,240,
+0,0,0,0,0,0,1,151,246,224,0,21,215,240,78,48,16,0,0,0,0,0,0,0,0,101,253,
+200,0,5,121,252,19,140,4,0,0,0,0,0,0,0,0,25,127,118,0,1,95,127,4,227,1,0,
+64,0,0,0,0,0,0,6,95,222,128,0,88,31,193,56,192,64,16,0,0,0,0,0,0,1,151,247,
+224,0,22,23,240,78,48,16,4,0,0,0,0,0,0,0,101,254,8,0,5,137,252,19,140,4,2,
+0,0,0,0,0,0,0,25,127,134,0,1,99,127,0,89,218,162,20,75,36,80,172,17,64,166,
+132,248,162,64,0,193,255,138,5,137,161,116,38,69,210,0,32,152,23,72,0,10,
+92,93,32,1,41,97,116,128,8,165,69,210,0,50,148,23,72,0,18,76,93,32,1,73,33,
+116,128,9,36,69,210,0,52,144,23,72,0,26,60,93,32,1,104,225,116,128,2,35,69,
+210,0,24,140,23,104,0,42,44,93,160,1,168,161,118,128,10,162,69,218,0,58,
+136,25,98,28,101,160,2,8,97,150,128,0,161,70,90,0,18,132,25,104,0,138,12,
+101,160,3,40,33,150,128,1,32,70,90,0,20,128,25,104,0,145,252,101,160,3,71,
+225,150,128,1,159,70,90,0,22,124,25,104,0,33,236,101,160,1,135,161,152,128,
+2,158,70,98,0,26,120,25,136,0,169,220,102,32,3,180,117,182,57,214,128,157,
+87,98,112,80,137,241,66,128,0,166,213,161,53,24,66,121,114,0,
};
#ifdef DUK_USE_BUILTIN_INITJS
-DUK_INTERNAL const duk_uint8_t duk_initjs_data[1757] = {
-47,42,10,32,42,32,32,73,110,105,116,32,99,111,100,101,32,102,111,114,32,
-108,101,103,97,99,121,32,99,111,109,112,97,116,105,98,105,108,105,116,121,
-46,10,32,42,10,32,42,32,32,67,111,109,112,97,116,105,98,105,108,105,116,
-121,32,112,114,111,112,101,114,116,105,101,115,32,47,32,119,114,97,112,112,
-101,114,32,102,117,110,99,116,105,111,110,115,32,104,101,114,101,32,97,108,
-108,111,119,32,68,117,107,116,97,112,101,32,116,111,32,114,101,109,97,105,
-110,10,32,42,32,32,99,111,109,112,97,116,105,98,108,101,32,102,111,114,32,
-117,115,101,114,32,99,111,100,101,32,119,104,101,110,32,99,111,114,101,32,
-102,101,97,116,117,114,101,115,32,97,114,101,32,99,104,97,110,103,101,100,
-44,32,119,105,116,104,111,117,116,32,98,117,114,100,101,110,105,110,103,10,
-32,42,32,32,116,104,101,32,109,97,105,110,32,67,32,99,111,100,101,32,119,
-105,116,104,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,115,116,
-117,102,102,46,10,32,42,10,32,42,32,32,84,104,105,115,32,102,105,108,101,
-32,105,115,32,109,105,110,105,102,105,101,100,32,119,105,116,104,32,85,103,
-108,105,102,121,74,83,32,111,114,32,116,104,101,32,99,108,111,115,117,114,
-101,32,99,111,109,112,105,108,101,114,46,32,32,66,111,116,104,32,119,105,
-108,108,10,32,42,32,32,114,101,110,97,109,101,32,118,97,114,105,97,98,108,
-101,115,44,32,114,101,109,111,118,101,32,99,111,109,109,101,110,116,115,44,
-32,97,110,100,32,97,114,101,32,99,108,101,118,101,114,32,101,110,111,117,
-103,104,32,116,111,32,100,114,111,112,32,97,110,121,10,32,42,32,32,34,105,
-102,32,40,102,97,108,115,101,41,32,123,32,46,46,46,32,125,34,32,98,108,111,
-99,107,115,32,97,108,116,111,103,101,116,104,101,114,44,32,115,111,32,116,
-104,97,116,39,115,32,97,110,32,101,102,102,101,99,116,105,118,101,32,119,
-97,121,32,116,111,10,32,42,32,32,100,105,115,97,98,108,101,32,99,117,114,
-114,101,110,116,108,121,32,117,110,110,101,101,100,101,100,32,99,111,100,
-101,46,10,32,42,47,10,10,40,102,117,110,99,116,105,111,110,40,71,44,32,68,
-41,32,123,10,32,32,32,32,39,117,115,101,32,115,116,114,105,99,116,39,59,10,
-10,32,32,32,32,102,117,110,99,116,105,111,110,32,100,101,102,40,111,98,106,
-101,99,116,44,32,110,97,109,101,44,32,118,97,108,117,101,41,32,123,10,32,
-32,32,32,32,32,32,32,79,98,106,101,99,116,46,100,101,102,105,110,101,80,
-114,111,112,101,114,116,121,40,111,98,106,101,99,116,44,32,110,97,109,101,
-44,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,118,97,108,117,101,58,32,
-118,97,108,117,101,44,10,32,32,32,32,32,32,32,32,32,32,32,32,119,114,105,
-116,97,98,108,101,58,32,116,114,117,101,44,10,32,32,32,32,32,32,32,32,32,
-32,32,32,101,110,117,109,101,114,97,98,108,101,58,32,102,97,108,115,101,44,
-10,32,32,32,32,32,32,32,32,32,32,32,32,99,111,110,102,105,103,117,114,97,
-98,108,101,58,32,116,114,117,101,10,32,32,32,32,32,32,32,32,125,41,59,10,
-32,32,32,32,125,10,10,32,32,32,32,102,117,110,99,116,105,111,110,32,100,
-101,102,68,40,110,97,109,101,44,32,118,97,108,117,101,41,32,123,10,32,32,
-32,32,32,32,32,32,100,101,102,40,68,44,32,110,97,109,101,44,32,118,97,108,
-117,101,41,59,10,32,32,32,32,125,10,10,32,32,32,32,47,47,32,67,111,109,112,
-97,116,105,98,105,108,105,116,121,32,102,111,114,32,39,99,111,110,115,111,
-108,101,46,108,111,103,39,46,10,32,32,32,32,105,102,32,40,102,97,108,115,
-101,41,32,123,10,32,32,32,32,32,32,32,32,99,111,110,115,111,108,101,32,61,
-32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,108,111,103,58,32,102,117,
-110,99,116,105,111,110,40,41,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,112,114,105,110,116,40,65,114,114,97,121,46,112,114,111,116,
-111,116,121,112,101,46,106,111,105,110,46,99,97,108,108,40,97,114,103,117,
-109,101,110,116,115,44,32,39,32,39,41,41,59,10,32,32,32,32,32,32,32,32,32,
-32,32,32,125,10,32,32,32,32,32,32,32,32,125,59,10,32,32,32,32,125,10,10,32,
-32,32,32,47,47,32,68,117,107,116,97,112,101,46,108,105,110,101,40,41,32,
-119,97,115,32,114,101,109,111,118,101,100,32,105,110,32,68,117,107,116,97,
-112,101,32,48,46,49,49,46,48,44,32,104,101,114,101,39,115,32,97,110,32,101,
-120,97,109,112,108,101,10,32,32,32,32,47,47,32,114,101,112,108,97,99,101,
-109,101,110,116,32,117,115,101,114,32,99,111,100,101,32,99,111,117,108,100,
-32,117,115,101,46,10,32,32,32,32,105,102,32,40,102,97,108,115,101,41,32,
-123,10,32,32,32,32,32,32,32,32,100,101,102,40,68,44,32,39,108,105,110,101,
-39,44,32,102,117,110,99,116,105,111,110,32,40,41,32,123,10,32,32,32,32,32,
-32,32,32,32,32,32,32,39,117,115,101,32,100,117,107,32,110,111,116,97,105,
-108,39,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,42,32,84,97,105,108,
-32,99,97,108,108,115,32,97,114,101,32,112,114,101,118,101,110,116,101,100,
-32,116,111,32,101,110,115,117,114,101,32,99,97,108,108,105,110,103,32,97,
-99,116,105,118,97,116,105,111,110,32,101,120,105,115,116,115,46,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,42,32,67,97,108,108,32,115,116,97,99,107,
-32,105,110,100,105,99,101,115,58,32,45,49,32,61,32,68,117,107,116,97,112,
-101,46,97,99,116,44,32,45,50,32,61,32,103,101,116,67,117,114,114,101,110,
-116,76,105,110,101,44,32,45,51,32,61,32,99,97,108,108,101,114,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,42,47,10,10,32,32,32,32,32,32,32,32,32,32,32,
-32,114,101,116,117,114,110,32,40,68,117,107,116,97,112,101,46,97,99,116,40,
-45,51,41,32,124,124,32,123,125,41,46,108,105,110,101,78,117,109,98,101,114,
-59,10,32,32,32,32,32,32,32,32,125,41,59,10,32,32,32,32,125,10,10,32,32,32,
-32,47,47,32,76,111,103,103,101,114,32,111,98,106,101,99,116,32,102,111,114,
-32,67,32,99,111,100,101,32,112,114,111,118,105,100,101,100,32,98,121,32,
-105,110,105,116,32,99,111,100,101,32,110,111,119,46,10,32,32,32,32,105,102,
-32,40,116,114,117,101,41,32,123,10,32,32,32,32,32,32,32,32,100,101,102,40,
-68,46,76,111,103,103,101,114,44,32,39,99,108,111,103,39,44,32,110,101,119,
-32,68,46,76,111,103,103,101,114,40,39,67,39,41,41,59,10,32,32,32,32,125,10,
-10,32,32,32,32,47,47,32,84,114,97,99,107,105,110,103,32,116,97,98,108,101,
-32,102,111,114,32,67,111,109,109,111,110,74,83,32,109,111,100,117,108,101,
-32,108,111,97,100,105,110,103,46,10,32,32,32,32,105,102,32,40,116,114,117,
-101,41,32,123,10,32,32,32,32,32,32,32,32,100,101,102,40,68,44,32,39,109,
-111,100,76,111,97,100,101,100,39,44,32,123,125,41,59,10,32,32,32,32,125,10,
-125,41,40,116,104,105,115,44,32,68,117,107,116,97,112,101,41,59,10,0,
+DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = {
+40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
+105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
+102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
+108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
+109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
+108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
+108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
+41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
+125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
};
#endif /* DUK_USE_BUILTIN_INITJS */
#elif defined(DUK_USE_DOUBLE_ME)
@@ -13031,20 +12886,20 @@ DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = {
32,76,71,64,156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,
147,32,134,226,17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,
52,72,40,144,213,33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,
-98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,74,185,3,45,
-142,133,144,150,68,206,81,44,18,145,68,230,202,100,35,104,195,18,239,116,
-102,114,94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,
-10,80,46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,
-1,40,6,33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,
-17,112,130,44,96,
+98,57,38,116,72,179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,
+42,228,12,182,58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,
+94,100,104,228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,
+46,68,82,24,245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,
+33,223,20,84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,
+130,44,96,
};
/* to convert a heap stridx to a token number, subtract
* DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
*/
-/* native functions: 147 */
-DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
+/* native functions: 149 */
+DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
duk_bi_array_constructor,
duk_bi_array_constructor_is_array,
duk_bi_array_prototype_concat,
@@ -13092,9 +12947,11 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
duk_bi_duktape_object_info,
duk_bi_error_constructor_shared,
duk_bi_error_prototype_filename_getter,
+ duk_bi_error_prototype_filename_setter,
duk_bi_error_prototype_linenumber_getter,
- duk_bi_error_prototype_nop_setter,
+ duk_bi_error_prototype_linenumber_setter,
duk_bi_error_prototype_stack_getter,
+ duk_bi_error_prototype_stack_setter,
duk_bi_error_prototype_to_string,
duk_bi_function_constructor,
duk_bi_function_prototype,
@@ -13195,38 +13052,38 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = {
};
DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
-105,195,75,16,121,40,105,51,14,252,104,52,8,131,72,0,115,225,65,165,236,55,
-243,6,145,32,210,24,210,182,25,249,35,120,216,99,226,13,78,225,116,177,164,
+105,195,75,32,121,40,105,53,14,252,104,54,8,131,72,0,115,225,65,165,244,55,
+243,6,145,32,210,24,210,186,25,249,35,120,216,99,226,13,79,33,116,177,164,
180,44,192,4,202,52,150,220,24,0,169,70,146,219,123,0,23,40,210,91,110,96,
3,37,26,75,109,172,0,108,163,73,109,177,128,14,148,105,45,181,176,1,242,
-144,56,209,32,94,6,167,101,98,80,211,24,1,250,67,72,168,67,232,13,46,128,
-47,162,52,164,0,62,80,163,72,128,61,40,107,26,7,37,20,53,200,131,88,0,66,
-134,185,16,98,80,215,34,11,96,0,138,26,228,65,76,0,69,67,92,136,37,128,6,
-168,107,145,4,48,1,165,13,114,32,118,0,44,161,174,68,12,192,7,148,53,200,
-129,88,1,26,134,165,48,130,80,31,255,241,69,224,0,0,124,63,128,0,0,0,46,32,
+144,56,209,36,94,6,167,133,98,80,211,28,1,250,67,72,168,67,232,13,46,192,
+47,162,52,165,0,62,80,163,72,128,61,40,107,26,7,37,20,53,201,131,88,0,66,
+134,185,48,98,80,215,38,11,96,0,138,26,228,193,76,0,69,67,92,152,37,128,6,
+168,107,147,4,48,1,165,13,114,96,118,0,44,161,174,76,12,192,7,148,53,201,
+129,88,1,26,134,165,80,130,80,31,255,241,69,224,0,0,124,63,128,0,0,0,46,32,
0,0,120,63,128,0,0,0,47,98,7,140,16,116,194,7,12,48,108,196,6,140,80,100,
198,6,12,112,92,200,5,140,149,192,202,91,204,181,184,204,91,76,213,176,206,
90,204,240,84,208,5,13,9,124,210,43,13,24,64,226,131,205,112,56,216,3,77,
152,48,218,130,205,184,40,220,130,77,216,32,222,129,205,248,24,224,129,78,
-25,214,163,226,90,80,145,104,65,37,157,0,150,99,242,89,78,73,100,58,37,140,
-236,150,35,194,88,79,73,96,69,37,125,12,122,188,134,62,0,2,165,68,39,255,
-255,193,43,67,0,0,80,127,192,58,182,216,80,0,21,59,154,64,0,107,76,200,172,
-180,146,176,198,138,187,43,42,204,136,170,181,146,168,214,80,0,26,155,81,
-42,77,4,168,180,20,0,6,160,206,74,123,73,64,0,127,255,4,10,153,219,28,198,
-163,184,130,140,224,10,43,144,40,141,164,161,183,18,132,222,64,161,127,128,
-0,63,225,1,109,74,8,137,71,56,5,4,213,20,3,115,233,249,177,240,80,255,192,
+25,214,164,2,90,81,17,104,67,37,157,8,150,100,18,89,78,201,100,60,37,140,
+244,150,35,226,88,79,201,96,71,37,125,20,122,188,138,62,0,2,165,70,39,255,
+255,193,43,67,0,0,80,127,192,58,182,220,80,0,21,59,170,64,0,107,77,8,172,
+181,146,176,202,138,187,59,42,204,200,170,182,146,168,218,80,0,26,155,97,
+42,77,68,168,181,20,0,6,160,210,74,123,89,64,0,127,255,4,10,153,219,157,70,
+163,185,130,140,228,10,43,160,40,141,228,161,184,18,132,226,64,161,127,128,
+0,63,225,1,109,74,8,137,71,58,5,4,221,20,3,147,233,249,193,240,80,255,192,
6,120,2,64,127,195,0,173,28,56,20,96,80,128,0,206,192,143,167,64,164,156,
131,2,112,14,125,55,9,4,216,40,19,80,180,77,3,9,51,13,94,153,7,159,76,64,
207,192,0,102,0,103,255,255,242,240,67,73,112,33,168,0,12,180,16,212,0,10,
88,8,106,0,7,43,4,53,0,4,149,4,31,128,0,202,66,15,255,255,194,137,254,0,50,
-135,195,224,127,196,2,87,132,17,82,143,20,10,44,80,36,239,196,147,63,146,
-119,0,125,49,129,52,152,64,154,128,0,201,96,137,36,131,36,142,17,18,40,82,
-77,97,145,33,135,68,130,37,17,247,208,71,159,65,29,125,8,0,12,113,244,32,0,
-49,184,176,70,162,16,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,
-0,81,191,197,140,192,255,255,239,127,255,255,255,255,140,64,0,0,0,0,1,0,0,
-0,139,192,0,0,248,127,0,0,0,0,138,192,0,0,240,127,0,0,0,0,139,64,0,0,240,
-255,0,0,0,0,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,96,37,25,120,148,86,
-16,69,23,73,19,92,36,73,124,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
+135,227,224,127,196,2,87,132,17,82,143,24,10,44,96,36,240,4,147,64,146,119,
+4,125,49,131,52,152,65,154,128,0,201,97,9,36,133,36,142,25,18,40,114,77,98,
+17,33,137,68,130,45,17,247,240,71,159,193,29,127,8,0,12,113,252,32,0,49,
+184,208,70,162,144,20,95,240,0,7,252,80,37,120,193,81,196,194,0,3,69,19,0,
+81,191,197,140,192,255,255,239,127,255,255,255,255,140,64,0,0,0,0,1,0,0,0,
+139,192,0,0,248,127,0,0,0,0,138,192,0,0,240,127,0,0,0,0,139,64,0,0,240,255,
+0,0,0,0,0,31,241,128,149,224,0,0,0,0,0,0,0,0,13,71,98,37,25,128,148,86,48,
+69,23,201,19,94,36,73,132,129,71,255,0,56,136,233,34,3,223,208,241,192,3,
254,56,18,188,128,0,15,135,240,0,0,0,11,104,228,128,135,18,4,0,6,26,72,16,
0,42,49,32,64,0,225,132,129,0,4,133,146,4,0,21,210,72,16,0,103,65,32,64,1,
220,228,100,162,146,130,20,74,8,72,248,64,2,33,3,225,0,9,131,143,132,0,42,
@@ -13237,9 +13094,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
33,127,0,29,120,144,207,128,15,60,8,103,192,7,221,228,37,0,32,119,16,148,0,
133,218,66,190,0,68,236,33,95,0,35,117,144,191,128,18,58,136,95,192,9,92,
195,225,0,38,114,144,148,0,156,41,31,224,0,15,249,1,138,144,64,192,2,2,225,
-132,221,9,70,112,70,111,198,111,72,0,0,0,0,0,0,0,0,13,198,240,71,19,201,40,
-239,64,10,79,248,0,3,254,72,86,209,5,155,36,17,46,185,137,129,109,203,140,
-11,78,94,96,13,28,200,1,74,255,0,2,127,202,4,218,43,131,100,130,32,5,47,
+132,221,9,70,112,70,111,198,111,72,0,0,0,0,0,0,0,0,13,198,244,71,19,217,40,
+239,128,10,79,248,0,3,254,72,86,209,5,155,36,17,46,185,145,153,109,203,139,
+203,78,96,98,13,28,208,1,74,255,0,2,127,202,4,218,43,131,100,130,32,5,47,
252,0,9,255,44,19,104,173,237,146,8,128,20,207,240,0,39,252,192,77,162,183,
54,72,34,0,83,127,192,0,159,243,65,54,138,218,217,32,136,1,78,255,0,2,127,
206,4,218,43,99,100,130,32,5,63,252,0,9,255,60,19,104,173,109,146,8,128,15,
@@ -13247,126 +13104,51 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[1952] = {
110,218,208,16,139,185,143,251,206,126,191,154,176,17,197,125,207,255,160,
138,217,90,144,30,242,246,207,195,185,73,133,90,112,62,200,66,80,6,11,81,
21,26,80,39,168,57,143,243,78,223,217,154,48,39,168,61,143,243,78,223,217,
-146,104,39,17,158,156,80,0,22,114,113,64,0,153,169,197,0,3,102,40,33,150,
-156,80,0,70,82,113,64,1,89,41,197,0,6,100,39,20,0,29,142,156,80,0,134,50,
-98,243,21,53,121,136,160,144,0,22,26,120,24,73,197,0,9,96,167,20,0,41,128,
-156,80,0,181,250,113,64,3,1,255,254,0,81,20,100,47,145,216,23,255,240,0,11,
-255,248,0,3,255,252,81,252,8,4,252,68,0,0,0,0,0,129,167,1,26,144,9,165,0,
-26,177,199,197,132,30,147,16,120,86,65,217,80,240,232,164,120,114,80,60,52,
-39,32,84,223,192,15,59,30,129,156,115,6,81,160,7,253,40,0,5,81,252,0,1,255,
-78,0,84,113,96,128,0,209,69,128,21,87,240,0,7,253,72,1,81,221,66,0,3,69,
-117,0,85,159,192,0,31,245,97,10,100,0,0,0,32,0,0,0,0,10,164,130,97,221,191,
-113,3,20,146,12,18,200,47,74,30,23,37,15,128,0,143,146,135,192,0,133,169,
-67,224,0,98,196,161,240,0,65,90,80,248,0,41,63,255,194,109,65,11,137,191,
-174,45,153,98,242,229,191,147,102,8,190,94,92,183,242,65,167,114,12,188,
-185,111,228,131,70,29,217,54,105,221,156,0,171,255,128,9,208,68,128,255,
-174,0,25,168,194,64,0,130,177,254,0,0,255,176,1,3,120,186,64,12,13,194,233,
-0,32,54,139,164,0,196,216,46,144,2,19,88,186,64,12,141,66,233,0,34,52,139,
-164,0,140,208,46,144,2,67,56,203,64,12,12,195,45,0,32,50,140,180,0,196,200,
-50,208,2,19,24,203,64,12,140,67,45,0,34,48,140,180,0,140,192,50,208,2,64,
-127,255,128,21,38,73,7,1,132,128,0,133,105,252,19,140,0,0,15,3,240,0,0,0,0,
-25,127,102,0,1,91,127,4,227,0,0,3,192,252,0,0,0,0,6,95,218,128,0,87,31,193,
-56,192,0,0,240,63,0,0,0,0,1,151,246,224,0,21,215,240,78,48,0,0,0,16,0,0,0,
-0,0,101,253,200,0,5,121,252,19,140,0,0,0,4,0,0,0,0,0,25,127,118,0,1,95,127,
-4,227,0,0,0,65,0,0,0,0,0,6,95,222,128,0,88,31,193,56,192,0,0,16,64,0,0,0,0,
-1,151,247,224,0,22,23,240,78,48,0,0,4,16,0,0,0,0,0,101,254,8,0,5,137,252,
-19,140,0,0,2,4,0,0,0,0,0,25,127,134,0,1,99,127,0,89,218,146,20,74,228,80,
-171,17,64,162,132,248,162,64,0,193,255,138,5,137,161,116,38,69,210,0,32,
-152,23,72,0,10,92,93,32,1,41,97,116,128,8,165,69,210,0,50,148,23,72,0,18,
-76,93,32,1,73,33,116,128,9,36,69,210,0,52,144,23,72,0,26,60,93,32,1,104,
-225,116,128,2,35,69,210,0,24,140,23,104,0,42,44,93,160,1,168,161,118,128,
-10,162,69,218,0,58,136,25,98,28,101,160,2,8,97,150,128,0,161,70,90,0,18,
-132,25,104,0,138,12,101,160,3,40,33,150,128,1,32,70,90,0,20,128,25,104,0,
-145,252,101,160,3,71,225,150,128,1,159,70,90,0,22,124,25,104,0,33,236,101,
-160,1,135,161,152,128,2,158,70,98,0,26,120,25,136,0,169,220,102,32,3,180,
-117,150,57,214,0,157,85,98,112,80,137,241,66,128,0,166,213,33,53,24,66,121,
-106,0,
+146,104,40,17,158,160,80,0,22,114,129,64,0,153,170,5,0,3,102,41,33,150,160,
+80,0,70,82,129,64,1,89,42,5,0,6,100,40,20,0,29,142,160,80,0,134,50,114,243,
+21,61,121,136,164,144,0,22,26,136,24,74,5,0,9,96,168,20,0,41,128,160,80,0,
+181,250,129,64,3,1,255,254,0,81,20,132,47,146,88,23,255,240,0,11,255,248,0,
+3,255,252,81,252,8,4,252,68,0,0,0,0,0,129,167,1,26,144,9,165,0,26,177,199,
+197,132,30,147,16,120,86,65,217,80,240,232,164,120,114,80,60,52,39,32,84,
+223,192,15,59,34,129,156,131,6,81,224,7,253,40,0,5,81,252,0,1,255,78,0,84,
+113,96,128,0,209,69,128,21,87,240,0,7,253,72,1,81,221,194,0,3,69,119,0,85,
+159,192,0,31,245,97,10,100,0,0,0,32,0,0,0,0,10,164,130,97,221,191,113,3,20,
+178,12,19,72,47,76,30,23,38,15,128,0,143,147,7,192,0,133,169,131,224,0,98,
+196,193,240,0,65,90,96,248,0,41,63,255,194,109,65,11,137,191,174,45,153,98,
+242,229,191,147,102,8,190,94,92,183,242,65,167,114,12,188,185,111,228,131,
+70,29,217,54,105,221,156,0,171,255,128,9,208,68,128,255,174,0,25,168,194,
+64,0,130,177,254,0,0,255,176,1,3,120,186,64,12,13,194,233,0,32,54,139,164,
+0,196,216,46,144,2,19,88,186,64,12,141,66,233,0,34,52,139,164,0,140,208,46,
+144,2,67,56,203,64,12,12,195,45,0,32,50,140,180,0,196,200,50,208,2,19,24,
+203,64,12,140,67,45,0,34,48,140,180,0,140,192,50,208,2,64,127,255,128,21,
+38,81,7,1,132,128,0,133,105,252,19,140,0,0,15,3,240,0,0,0,0,25,127,102,0,1,
+91,127,4,227,0,0,3,192,252,0,0,0,0,6,95,218,128,0,87,31,193,56,192,0,0,240,
+63,0,0,0,0,1,151,246,224,0,21,215,240,78,48,0,0,0,16,0,0,0,0,0,101,253,200,
+0,5,121,252,19,140,0,0,0,4,0,0,0,0,0,25,127,118,0,1,95,127,4,227,0,0,0,65,
+0,0,0,0,0,6,95,222,128,0,88,31,193,56,192,0,0,16,64,0,0,0,0,1,151,247,224,
+0,22,23,240,78,48,0,0,4,16,0,0,0,0,0,101,254,8,0,5,137,252,19,140,0,0,2,4,
+0,0,0,0,0,25,127,134,0,1,99,127,0,89,218,162,20,75,36,80,172,17,64,166,132,
+248,162,64,0,193,255,138,5,137,161,116,38,69,210,0,32,152,23,72,0,10,92,93,
+32,1,41,97,116,128,8,165,69,210,0,50,148,23,72,0,18,76,93,32,1,73,33,116,
+128,9,36,69,210,0,52,144,23,72,0,26,60,93,32,1,104,225,116,128,2,35,69,210,
+0,24,140,23,104,0,42,44,93,160,1,168,161,118,128,10,162,69,218,0,58,136,25,
+98,28,101,160,2,8,97,150,128,0,161,70,90,0,18,132,25,104,0,138,12,101,160,
+3,40,33,150,128,1,32,70,90,0,20,128,25,104,0,145,252,101,160,3,71,225,150,
+128,1,159,70,90,0,22,124,25,104,0,33,236,101,160,1,135,161,152,128,2,158,
+70,98,0,26,120,25,136,0,169,220,102,32,3,180,117,182,57,214,128,157,87,98,
+112,80,137,241,66,128,0,166,213,161,53,24,66,121,114,0,
};
#ifdef DUK_USE_BUILTIN_INITJS
-DUK_INTERNAL const duk_uint8_t duk_initjs_data[1757] = {
-47,42,10,32,42,32,32,73,110,105,116,32,99,111,100,101,32,102,111,114,32,
-108,101,103,97,99,121,32,99,111,109,112,97,116,105,98,105,108,105,116,121,
-46,10,32,42,10,32,42,32,32,67,111,109,112,97,116,105,98,105,108,105,116,
-121,32,112,114,111,112,101,114,116,105,101,115,32,47,32,119,114,97,112,112,
-101,114,32,102,117,110,99,116,105,111,110,115,32,104,101,114,101,32,97,108,
-108,111,119,32,68,117,107,116,97,112,101,32,116,111,32,114,101,109,97,105,
-110,10,32,42,32,32,99,111,109,112,97,116,105,98,108,101,32,102,111,114,32,
-117,115,101,114,32,99,111,100,101,32,119,104,101,110,32,99,111,114,101,32,
-102,101,97,116,117,114,101,115,32,97,114,101,32,99,104,97,110,103,101,100,
-44,32,119,105,116,104,111,117,116,32,98,117,114,100,101,110,105,110,103,10,
-32,42,32,32,116,104,101,32,109,97,105,110,32,67,32,99,111,100,101,32,119,
-105,116,104,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,115,116,
-117,102,102,46,10,32,42,10,32,42,32,32,84,104,105,115,32,102,105,108,101,
-32,105,115,32,109,105,110,105,102,105,101,100,32,119,105,116,104,32,85,103,
-108,105,102,121,74,83,32,111,114,32,116,104,101,32,99,108,111,115,117,114,
-101,32,99,111,109,112,105,108,101,114,46,32,32,66,111,116,104,32,119,105,
-108,108,10,32,42,32,32,114,101,110,97,109,101,32,118,97,114,105,97,98,108,
-101,115,44,32,114,101,109,111,118,101,32,99,111,109,109,101,110,116,115,44,
-32,97,110,100,32,97,114,101,32,99,108,101,118,101,114,32,101,110,111,117,
-103,104,32,116,111,32,100,114,111,112,32,97,110,121,10,32,42,32,32,34,105,
-102,32,40,102,97,108,115,101,41,32,123,32,46,46,46,32,125,34,32,98,108,111,
-99,107,115,32,97,108,116,111,103,101,116,104,101,114,44,32,115,111,32,116,
-104,97,116,39,115,32,97,110,32,101,102,102,101,99,116,105,118,101,32,119,
-97,121,32,116,111,10,32,42,32,32,100,105,115,97,98,108,101,32,99,117,114,
-114,101,110,116,108,121,32,117,110,110,101,101,100,101,100,32,99,111,100,
-101,46,10,32,42,47,10,10,40,102,117,110,99,116,105,111,110,40,71,44,32,68,
-41,32,123,10,32,32,32,32,39,117,115,101,32,115,116,114,105,99,116,39,59,10,
-10,32,32,32,32,102,117,110,99,116,105,111,110,32,100,101,102,40,111,98,106,
-101,99,116,44,32,110,97,109,101,44,32,118,97,108,117,101,41,32,123,10,32,
-32,32,32,32,32,32,32,79,98,106,101,99,116,46,100,101,102,105,110,101,80,
-114,111,112,101,114,116,121,40,111,98,106,101,99,116,44,32,110,97,109,101,
-44,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,118,97,108,117,101,58,32,
-118,97,108,117,101,44,10,32,32,32,32,32,32,32,32,32,32,32,32,119,114,105,
-116,97,98,108,101,58,32,116,114,117,101,44,10,32,32,32,32,32,32,32,32,32,
-32,32,32,101,110,117,109,101,114,97,98,108,101,58,32,102,97,108,115,101,44,
-10,32,32,32,32,32,32,32,32,32,32,32,32,99,111,110,102,105,103,117,114,97,
-98,108,101,58,32,116,114,117,101,10,32,32,32,32,32,32,32,32,125,41,59,10,
-32,32,32,32,125,10,10,32,32,32,32,102,117,110,99,116,105,111,110,32,100,
-101,102,68,40,110,97,109,101,44,32,118,97,108,117,101,41,32,123,10,32,32,
-32,32,32,32,32,32,100,101,102,40,68,44,32,110,97,109,101,44,32,118,97,108,
-117,101,41,59,10,32,32,32,32,125,10,10,32,32,32,32,47,47,32,67,111,109,112,
-97,116,105,98,105,108,105,116,121,32,102,111,114,32,39,99,111,110,115,111,
-108,101,46,108,111,103,39,46,10,32,32,32,32,105,102,32,40,102,97,108,115,
-101,41,32,123,10,32,32,32,32,32,32,32,32,99,111,110,115,111,108,101,32,61,
-32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,108,111,103,58,32,102,117,
-110,99,116,105,111,110,40,41,32,123,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,112,114,105,110,116,40,65,114,114,97,121,46,112,114,111,116,
-111,116,121,112,101,46,106,111,105,110,46,99,97,108,108,40,97,114,103,117,
-109,101,110,116,115,44,32,39,32,39,41,41,59,10,32,32,32,32,32,32,32,32,32,
-32,32,32,125,10,32,32,32,32,32,32,32,32,125,59,10,32,32,32,32,125,10,10,32,
-32,32,32,47,47,32,68,117,107,116,97,112,101,46,108,105,110,101,40,41,32,
-119,97,115,32,114,101,109,111,118,101,100,32,105,110,32,68,117,107,116,97,
-112,101,32,48,46,49,49,46,48,44,32,104,101,114,101,39,115,32,97,110,32,101,
-120,97,109,112,108,101,10,32,32,32,32,47,47,32,114,101,112,108,97,99,101,
-109,101,110,116,32,117,115,101,114,32,99,111,100,101,32,99,111,117,108,100,
-32,117,115,101,46,10,32,32,32,32,105,102,32,40,102,97,108,115,101,41,32,
-123,10,32,32,32,32,32,32,32,32,100,101,102,40,68,44,32,39,108,105,110,101,
-39,44,32,102,117,110,99,116,105,111,110,32,40,41,32,123,10,32,32,32,32,32,
-32,32,32,32,32,32,32,39,117,115,101,32,100,117,107,32,110,111,116,97,105,
-108,39,59,10,10,32,32,32,32,32,32,32,32,32,32,32,32,47,42,32,84,97,105,108,
-32,99,97,108,108,115,32,97,114,101,32,112,114,101,118,101,110,116,101,100,
-32,116,111,32,101,110,115,117,114,101,32,99,97,108,108,105,110,103,32,97,
-99,116,105,118,97,116,105,111,110,32,101,120,105,115,116,115,46,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,42,32,67,97,108,108,32,115,116,97,99,107,
-32,105,110,100,105,99,101,115,58,32,45,49,32,61,32,68,117,107,116,97,112,
-101,46,97,99,116,44,32,45,50,32,61,32,103,101,116,67,117,114,114,101,110,
-116,76,105,110,101,44,32,45,51,32,61,32,99,97,108,108,101,114,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,42,47,10,10,32,32,32,32,32,32,32,32,32,32,32,
-32,114,101,116,117,114,110,32,40,68,117,107,116,97,112,101,46,97,99,116,40,
-45,51,41,32,124,124,32,123,125,41,46,108,105,110,101,78,117,109,98,101,114,
-59,10,32,32,32,32,32,32,32,32,125,41,59,10,32,32,32,32,125,10,10,32,32,32,
-32,47,47,32,76,111,103,103,101,114,32,111,98,106,101,99,116,32,102,111,114,
-32,67,32,99,111,100,101,32,112,114,111,118,105,100,101,100,32,98,121,32,
-105,110,105,116,32,99,111,100,101,32,110,111,119,46,10,32,32,32,32,105,102,
-32,40,116,114,117,101,41,32,123,10,32,32,32,32,32,32,32,32,100,101,102,40,
-68,46,76,111,103,103,101,114,44,32,39,99,108,111,103,39,44,32,110,101,119,
-32,68,46,76,111,103,103,101,114,40,39,67,39,41,41,59,10,32,32,32,32,125,10,
-10,32,32,32,32,47,47,32,84,114,97,99,107,105,110,103,32,116,97,98,108,101,
-32,102,111,114,32,67,111,109,109,111,110,74,83,32,109,111,100,117,108,101,
-32,108,111,97,100,105,110,103,46,10,32,32,32,32,105,102,32,40,116,114,117,
-101,41,32,123,10,32,32,32,32,32,32,32,32,100,101,102,40,68,44,32,39,109,
-111,100,76,111,97,100,101,100,39,44,32,123,125,41,59,10,32,32,32,32,125,10,
-125,41,40,116,104,105,115,44,32,68,117,107,116,97,112,101,41,59,10,0,
+DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = {
+40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
+105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
+102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
+108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
+109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
+108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
+108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
+41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,123,125,41,
+125,41,40,116,104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
};
#endif /* DUK_USE_BUILTIN_INITJS */
#else
@@ -13381,9 +13163,9 @@ DUK_INTERNAL const duk_uint8_t duk_initjs_data[1757] = {
#define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
-#ifdef DUK_USE_VERBOSE_ERRORS
+#if defined(DUK_USE_VERBOSE_ERRORS)
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
DUK_INTERNAL void duk_err_handle_error(const char *filename, duk_int_t line, duk_hthread *thr, duk_errcode_t code, const char *fmt, ...) {
va_list ap;
char msg[DUK__ERRFMT_BUFSIZE];
@@ -13423,7 +13205,7 @@ DUK_INTERNAL void duk_err_handle_error_stash(duk_hthread *thr, duk_errcode_t cod
#else /* DUK_USE_VERBOSE_ERRORS */
-#ifdef DUK_USE_VARIADIC_MACROS
+#if defined(DUK_USE_VARIADIC_MACROS)
DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
duk_err_create_and_throw(thr, code);
}
@@ -13445,12 +13227,49 @@ DUK_INTERNAL void duk_err_handle_error_nonverbose2(const char *filename, duk_int
#endif /* DUK_USE_VERBOSE_ERRORS */
/*
+ * Error throwing helpers
+ */
+
+#if defined(DUK_USE_VERBOSE_ERRORS)
+#if defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name) {
+ DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
+ expect_name, duk_get_type_name((duk_context *) thr, index), (long) index);
+}
+#else
+DUK_INTERNAL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index, const char *expect_name) {
+ DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
+ expect_name, duk_push_string_readable((duk_context *) thr, index), (long) index);
+}
+#endif
+DUK_INTERNAL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, duk_idx_t index) {
+ DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index));
+}
+DUK_INTERNAL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message) {
+ DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_API_ERROR, message);
+}
+#else
+DUK_INTERNAL void duk_err_require_type_index(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message) {
+ DUK_UNREF(filename); DUK_UNREF(linenumber); DUK_UNREF(message);
+ DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_TYPE_ERROR, message);
+}
+DUK_INTERNAL void duk_err_api_index(const char *filename, duk_int_t linenumber, duk_hthread *thr) {
+ DUK_UNREF(filename); DUK_UNREF(linenumber);
+ DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+}
+DUK_INTERNAL void duk_err_api(const char *filename, duk_int_t linenumber, duk_hthread *thr, const char *message) {
+ DUK_UNREF(filename); DUK_UNREF(linenumber); DUK_UNREF(message);
+ DUK_ERROR_RAW(filename, linenumber, thr, DUK_ERR_API_ERROR, message);
+}
+#endif
+
+/*
* Default fatal error handler
*/
DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
DUK_UNREF(ctx);
-#ifdef DUK_USE_FILE_IO
+#if defined(DUK_USE_FILE_IO)
DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
DUK_FFLUSH(DUK_STDERR);
#else
@@ -13467,7 +13286,7 @@ DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code
#if !defined(DUK_USE_PANIC_HANDLER)
DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
-#ifdef DUK_USE_FILE_IO
+#if defined(DUK_USE_FILE_IO)
DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
#if defined(DUK_USE_PANIC_ABORT)
"calling abort"
@@ -13760,26 +13579,117 @@ DUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr,
return 0;
}
-/* (extended) utf-8 length without codepoint encoding validation, used
- * for string interning (should probably be inlined).
+/* Compute (extended) utf-8 length without codepoint encoding validation,
+ * used for string interning.
+ *
+ * NOTE: This algorithm is performance critical, more so than string hashing
+ * in some cases. It is needed when interning a string and needs to scan
+ * every byte of the string with no skipping. Having an ASCII fast path
+ * is useful if possible in the algorithm. The current algorithms were
+ * chosen from several variants, based on x64 gcc -O2 testing. See:
+ * https://github.com/svaarala/duktape/pull/422
*/
+
+#if defined(DUK_USE_PREFER_SIZE)
+/* Small variant; roughly 150 bytes smaller than the fast variant. */
DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
- const duk_uint8_t *p = data;
- const duk_uint8_t *p_end = data + blen;
- duk_size_t clen = 0;
+ const duk_uint8_t *p;
+ const duk_uint8_t *p_end;
+ duk_size_t ncont;
+ duk_size_t clen;
- while (p < p_end) {
- duk_uint8_t x = *p++;
- if (x < 0x80 || x >= 0xc0) {
- /* 10xxxxxx = continuation chars (0x80...0xbf), above
- * and below that initial bytes.
+ p = data;
+ p_end = data + blen;
+ ncont = 0;
+ while (p != p_end) {
+ duk_uint8_t x;
+ x = *p++;
+ if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
+ ncont++;
+ }
+ }
+
+ DUK_ASSERT(ncont <= blen);
+ clen = blen - ncont;
+ DUK_ASSERT(clen <= blen);
+ return clen;
+}
+#else /* DUK_USE_PREFER_SIZE */
+/* This seems like a good overall approach. Fast path for ASCII in 4 byte
+ * blocks.
+ */
+DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
+ const duk_uint8_t *p;
+ const duk_uint8_t *p_end;
+ const duk_uint32_t *p32_end;
+ const duk_uint32_t *p32;
+ duk_size_t ncont;
+ duk_size_t clen;
+
+ ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
+ p = data;
+ p_end = data + blen;
+ if (blen < 16) {
+ goto skip_fastpath;
+ }
+
+ /* Align 'p' to 4; the input data may have arbitrary alignment.
+ * End of string check not needed because blen >= 16.
+ */
+ while (((duk_uintptr_t) (const void *) p) & 0x03) {
+ duk_uint8_t x;
+ x = *p++;
+ if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
+ ncont++;
+ }
+ }
+
+ /* Full, aligned 4-byte reads. */
+ p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
+ p32 = (const duk_uint32_t *) (const void *) p;
+ while (p32 != (const duk_uint32_t *) p32_end) {
+ duk_uint32_t x;
+ x = *p32++;
+ if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
+ ; /* ASCII fast path */
+ } else {
+ /* Flip highest bit of each byte which changes
+ * the bit pattern 10xxxxxx into 00xxxxxx which
+ * allows an easy bit mask test.
*/
- clen++;
+ x ^= 0x80808080UL;
+ if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
+ ncont++;
+ }
+ if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
+ ncont++;
+ }
+ if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
+ ncont++;
+ }
+ if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
+ ncont++;
+ }
+ }
+ }
+ p = (const duk_uint8_t *) p32;
+ /* Fall through to handle the rest. */
+
+ skip_fastpath:
+ while (p != p_end) {
+ duk_uint8_t x;
+ x = *p++;
+ if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
+ ncont++;
}
}
+ DUK_ASSERT(ncont <= blen);
+ clen = blen - ncont;
+ DUK_ASSERT(clen <= blen);
return clen;
}
+#endif /* DUK_USE_PREFER_SIZE */
/*
* Unicode range matcher
@@ -13814,7 +13724,7 @@ DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_si
duk_codepoint_t prev_re;
DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
- bd_ctx.data = (duk_uint8_t *) unitab;
+ bd_ctx.data = (const duk_uint8_t *) unitab;
bd_ctx.length = (duk_size_t) unilen;
prev_re = 0;
@@ -14359,10 +14269,10 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
/* 1:1 or special conversions, but not locale/context specific: script generated rules */
DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
if (uppercase) {
- bd_ctx.data = (duk_uint8_t *) duk_unicode_caseconv_uc;
+ bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
} else {
- bd_ctx.data = (duk_uint8_t *) duk_unicode_caseconv_lc;
+ bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
}
return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
@@ -14400,7 +14310,7 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_in
/* [ ... input buffer ] */
- p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+ p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
p = p_start;
@@ -14453,14 +14363,15 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_in
*/
DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
-#if 1 /* FIXME */
+#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
/* Fast canonicalization lookup at the cost of 128kB footprint. */
DUK_ASSERT(cp >= 0);
+ DUK_UNREF(thr);
if (DUK_LIKELY(cp < 0x10000L)) {
return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
}
return cp;
-#else
+#else /* DUK_USE_REGEXP_CANON_WORKAROUND */
duk_codepoint_t y;
y = duk__case_transform_helper(thr,
@@ -14478,7 +14389,7 @@ DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr,
}
return y;
-#endif
+#endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
}
/*
@@ -14566,24 +14477,31 @@ DUK_INTERNAL duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
* hex nybble table.
*/
-DUK_INTERNAL duk_uint8_t duk_lc_digits[36] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
- 'w', 'x', 'y', 'z'
+DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
+ DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
+ DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+ DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
+ DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
+ DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
+ DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
+ DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
+ DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
+ DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
};
-DUK_INTERNAL duk_uint8_t duk_uc_nybbles[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
+ DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
+ DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
+ DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
+ DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
};
/*
- * Table for decoding ASCII hex digits, -1 if invalid.
+ * Table for hex decoding ASCII hex digits
*/
-DUK_INTERNAL duk_int8_t duk_hex_dectab[256] = {
+DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
+ /* -1 if invalid */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
@@ -14602,6 +14520,154 @@ DUK_INTERNAL duk_int8_t duk_hex_dectab[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
};
+#if defined(DUK_USE_HEX_FASTPATH)
+/* Preshifted << 4. Must use 16-bit entry to allow negative value signaling. */
+DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
+ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
+ -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
+ -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
+};
+#endif
+
+/*
+ * Table for hex encoding bytes
+ */
+
+#if defined(DUK_USE_HEX_FASTPATH)
+/* Lookup to encode one byte directly into 2 characters:
+ *
+ * def genhextab(bswap):
+ * for i in xrange(256):
+ * t = chr(i).encode('hex')
+ * if bswap:
+ * t = t[1] + t[0]
+ * print('0x' + t.encode('hex') + 'U')
+ * print('big endian'); genhextab(False)
+ * print('little endian'); genhextab(True)
+*/
+DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
+#if defined(DUK_USE_INTEGER_BE)
+ 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
+ 0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
+ 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
+ 0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
+ 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
+ 0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
+ 0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
+ 0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
+ 0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
+ 0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
+ 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
+ 0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
+ 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
+ 0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
+ 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
+ 0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
+ 0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
+ 0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
+ 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
+ 0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
+ 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
+ 0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
+ 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
+ 0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
+ 0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
+ 0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
+ 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
+ 0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
+ 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
+ 0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
+ 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
+ 0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
+#else /* DUK_USE_INTEGER_BE */
+ 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
+ 0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
+ 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
+ 0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
+ 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
+ 0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
+ 0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
+ 0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
+ 0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
+ 0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
+ 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
+ 0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
+ 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
+ 0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
+ 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
+ 0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
+ 0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
+ 0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
+ 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
+ 0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
+ 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
+ 0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
+ 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
+ 0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
+ 0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
+ 0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
+ 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
+ 0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
+ 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
+ 0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
+ 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
+ 0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
+#endif /* DUK_USE_INTEGER_BE */
+};
+#endif /* DUK_USE_HEX_FASTPATH */
+
+/*
+ * Table for base-64 encoding
+ */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* A...P */
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, /* Q...f */
+ 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, /* g...v */
+ 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f /* w.../ */
+};
+#endif /* DUK_USE_BASE64_FASTPATH */
+
+/*
+ * Table for base-64 decoding
+ */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
+ /* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, /* 0x00...0x0f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10...0x1f */
+ -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20...0x2f */
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, /* 0x30...0x3f */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50...0x5f */
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70...0x7f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80...0x8f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90...0x9f */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0...0xaf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0...0xbf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0...0xcf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0...0xdf */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0...0xef */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0...0xff */
+};
+#endif /* DUK_USE_BASE64_FASTPATH */
+
/*
* Arbitrary byteswap for potentially unaligned values
*
@@ -16216,18 +16282,89 @@ DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t mag
* Encoding and decoding basic formats: hex, base64.
*
* These are in-place operations which may allow an optimized implementation.
+ *
+ * Base-64: https://tools.ietf.org/html/rfc4648#section-4
*/
/* include removed: duk_internal.h */
-/* dst length must be exactly ceil(len/3)*4 */
-DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, const duk_uint8_t *src_end,
- duk_uint8_t *dst, duk_uint8_t *dst_end) {
+/* Shared handling for encode/decode argument. Fast path handling for
+ * buffer and string values because they're the most common. In particular,
+ * avoid creating a temporary string or buffer when possible.
+ */
+DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
+ DUK_ASSERT(duk_is_valid_index(ctx, index)); /* checked by caller */
+ if (duk_is_buffer(ctx, index)) {
+ return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len);
+ } else {
+ return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len);
+ }
+}
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
+ duk_uint_t t;
+ duk_size_t n_full, n_full3, n_final;
+ const duk_uint8_t *src_end_fast;
+
+ n_full = srclen / 3; /* full 3-byte -> 4-char conversions */
+ n_full3 = n_full * 3;
+ n_final = srclen - n_full3;
+ DUK_ASSERT_DISABLE(n_final >= 0);
+ DUK_ASSERT(n_final <= 2);
+
+ src_end_fast = src + n_full3;
+ while (DUK_UNLIKELY(src != src_end_fast)) {
+ t = (duk_uint_t) (*src++);
+ t = (t << 8) + (duk_uint_t) (*src++);
+ t = (t << 8) + (duk_uint_t) (*src++);
+
+ *dst++ = duk_base64_enctab[t >> 18];
+ *dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
+ *dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
+ *dst++ = duk_base64_enctab[t & 0x3f];
+
+#if 0 /* Tested: not faster on x64 */
+ /* aaaaaabb bbbbcccc ccdddddd */
+ dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
+ dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
+ dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
+ dst[3] = duk_base64_enctab[src[2] & 0x3f];
+ src += 3; dst += 4;
+#endif
+ }
+
+ switch (n_final) {
+ /* case 0: nop */
+ case 1: {
+ /* XX== */
+ t = (duk_uint_t) (*src++);
+ *dst++ = duk_base64_enctab[t >> 2]; /* XXXXXX-- */
+ *dst++ = duk_base64_enctab[(t << 4) & 0x3f]; /* ------XX */
+ *dst++ = DUK_ASC_EQUALS;
+ *dst++ = DUK_ASC_EQUALS;
+ break;
+ }
+ case 2: {
+ /* XXX= */
+ t = (duk_uint_t) (*src++);
+ t = (t << 8) + (duk_uint_t) (*src++);
+ *dst++ = duk_base64_enctab[t >> 10]; /* XXXXXX-- -------- */
+ *dst++ = duk_base64_enctab[(t >> 4) & 0x3f]; /* ------XX XXXX---- */
+ *dst++ = duk_base64_enctab[(t << 2) & 0x3f]; /* -------- ----XXXX */
+ *dst++ = DUK_ASC_EQUALS;
+ break;
+ }
+ }
+}
+#else /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
duk_small_uint_t i, snip;
- duk_uint_fast32_t t;
+ duk_uint_t t;
duk_uint_fast8_t x, y;
+ const duk_uint8_t *src_end;
- DUK_UNREF(dst_end);
+ src_end = src + srclen;
while (src < src_end) {
/* read 3 bytes into 't', padded by zero */
@@ -16238,7 +16375,7 @@ DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, const duk_uint8
if (src >= src_end) {
snip--;
} else {
- t += (duk_uint_fast32_t) (*src++);
+ t += (duk_uint_t) (*src++);
}
}
@@ -16272,22 +16409,159 @@ DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, const duk_uint8
y = '/';
}
- DUK_ASSERT(dst < dst_end);
*dst++ = (duk_uint8_t) y;
}
}
}
+#endif /* DUK_USE_BASE64_FASTPATH */
+
+#if defined(DUK_USE_BASE64_FASTPATH)
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+ duk_int_t x;
+ duk_int_t t;
+ duk_small_uint_t n_equal;
+ duk_small_uint_t n_chars;
+ const duk_uint8_t *src_end;
+ const duk_uint8_t *src_end_safe;
+
+ src_end = src + srclen;
+ src_end_safe = src_end - 4; /* if 'src < src_end_safe', safe to read 4 bytes */
+
+ /* Innermost fast path processes 4 valid base-64 characters at a time
+ * but bails out on whitespace, padding chars ('=') and invalid chars.
+ * Once the slow path segment has been processed, we return to the
+ * inner fast path again. This handles e.g. base64 with newlines
+ * reasonably well because the majority of a line is in the fast path.
+ */
+ for (;;) {
+ /* Fast path, handle units with just actual encoding characters. */
+
+ while (src <= src_end_safe) {
+ /* The lookup byte is intentionally sign extended to (at least)
+ * 32 bits and then ORed. This ensures that is at least 1 byte
+ * is negative, the highest bit of 't' will be set at the end
+ * and we don't need to check every byte.
+ */
+ DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
+ (const void *) src, (const void *) src_end_safe, (const void *) src_end));
+
+ t = (duk_int_t) duk_base64_dectab[*src++];
+ t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+ t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+ t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
+
+ if (DUK_UNLIKELY(t < 0)) {
+ DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
+ src -= 4;
+ break;
+ }
+
+ DUK_ASSERT(t <= 0xffffffL);
+ DUK_ASSERT((t >> 24) == 0);
+ *dst++ = (duk_uint8_t) (t >> 16);
+ *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+ *dst++ = (duk_uint8_t) (t & 0xff);
+ }
+
+ /* Handle one slow path unit (or finish if we're done). */
+
+ n_equal = 0;
+ n_chars = 0;
+ t = 0;
+ for (;;) {
+ DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
+ (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
+
+ if (DUK_UNLIKELY(src >= src_end)) {
+ goto done; /* two level break */
+ }
+
+ x = duk_base64_dectab[*src++];
+ if (DUK_UNLIKELY(x < 0)) {
+ if (x == -2) {
+ continue; /* allowed ascii whitespace */
+ } else if (x == -3) {
+ n_equal++;
+ t <<= 6;
+ } else {
+ DUK_ASSERT(x == -1);
+ goto error;
+ }
+ } else {
+ DUK_ASSERT(x >= 0 && x <= 63);
+ if (n_equal > 0) {
+ /* Don't allow actual chars after equal sign. */
+ goto error;
+ }
+ t = (t << 6) + x;
+ }
+
+ if (DUK_UNLIKELY(n_chars == 3)) {
+ /* Emit 3 bytes and backtrack if there was padding. There's
+ * always space for the whole 3 bytes so no check needed.
+ */
+ DUK_ASSERT(t <= 0xffffffL);
+ DUK_ASSERT((t >> 24) == 0);
+ *dst++ = (duk_uint8_t) (t >> 16);
+ *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
+ *dst++ = (duk_uint8_t) (t & 0xff);
-DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, const duk_uint8_t *src_end,
- duk_uint8_t *dst, duk_uint8_t *dst_end, duk_uint8_t **out_dst_final) {
- duk_uint_fast32_t t;
+ if (DUK_UNLIKELY(n_equal > 0)) {
+ DUK_ASSERT(n_equal <= 4);
+
+ /* There may be whitespace between the equal signs. */
+ if (n_equal == 1) {
+ /* XXX= */
+ dst -= 1;
+ } else if (n_equal == 2) {
+ /* XX== */
+ dst -= 2;
+ } else {
+ goto error; /* invalid padding */
+ }
+
+ /* Continue parsing after padding, allows concatenated,
+ * padded base64.
+ */
+ }
+ break; /* back to fast loop */
+ } else {
+ n_chars++;
+ }
+ }
+ }
+ done:
+ DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
+ (const void *) src, (const void *) src_end, (long) n_chars));
+
+ DUK_ASSERT(src == src_end);
+
+ if (n_chars != 0) {
+ /* Here we'd have the option of decoding unpadded base64
+ * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
+ * accepted.
+ */
+ goto error;
+ }
+
+ *out_dst_final = dst;
+ return 1;
+
+ error:
+ return 0;
+}
+#else /* DUK_USE_BASE64_FASTPATH */
+DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {
+ duk_uint_t t;
duk_uint_fast8_t x, y;
duk_small_uint_t group_idx;
+ duk_small_uint_t n_equal;
+ const duk_uint8_t *src_end;
- DUK_UNREF(dst_end);
-
+ src_end = src + srclen;
t = 0;
group_idx = 0;
+ n_equal = 0;
while (src < src_end) {
x = *src++;
@@ -16303,42 +16577,14 @@ DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, const duk
} else if (x == '/') {
y = 63;
} else if (x == '=') {
- /* We don't check the zero padding bytes here right now.
- * This seems to be common behavior for base-64 decoders.
+ /* We don't check the zero padding bytes here right now
+ * (that they're actually zero). This seems to be common
+ * behavior for base-64 decoders.
*/
- if (group_idx == 2) {
- /* xx== -> 1 byte, t contains 12 bits, 4 on right are zero */
- t = t >> 4;
- DUK_ASSERT(dst < dst_end);
- *dst++ = (duk_uint8_t) t;
-
- if (src >= src_end) {
- goto error;
- }
- x = *src++;
- if (x != '=') {
- goto error;
- }
- } else if (group_idx == 3) {
- /* xxx= -> 2 bytes, t contains 18 bits, 2 on right are zero */
- t = t >> 2;
- DUK_ASSERT(dst < dst_end);
- *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
- DUK_ASSERT(dst < dst_end);
- *dst++ = (duk_uint8_t) (t & 0xff);
- } else {
- goto error;
- }
-
- /* Here we can choose either to end parsing and ignore
- * whatever follows, or to continue parsing in case
- * multiple (possibly padded) base64 strings have been
- * concatenated. Currently, keep on parsing.
- */
- t = 0;
- group_idx = 0;
- continue;
+ n_equal++;
+ t <<= 6; /* shift in zeroes */
+ goto skip_add;
} else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
/* allow basic ASCII whitespace */
continue;
@@ -16346,16 +16592,38 @@ DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, const duk
goto error;
}
+ if (n_equal > 0) {
+ /* Don't allow mixed padding and actual chars. */
+ goto error;
+ }
t = (t << 6) + y;
+ skip_add:
if (group_idx == 3) {
/* output 3 bytes from 't' */
- DUK_ASSERT(dst < dst_end);
*dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
- DUK_ASSERT(dst < dst_end);
*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
- DUK_ASSERT(dst < dst_end);
*dst++ = (duk_uint8_t) (t & 0xff);
+
+ if (DUK_UNLIKELY(n_equal > 0)) {
+ /* Backtrack. */
+ DUK_ASSERT(n_equal <= 4);
+ if (n_equal == 1) {
+ dst -= 1;
+ } else if (n_equal == 2) {
+ dst -= 2;
+ } else {
+ goto error; /* invalid padding */
+ }
+
+ /* Here we can choose either to end parsing and ignore
+ * whatever follows, or to continue parsing in case
+ * multiple (possibly padded) base64 strings have been
+ * concatenated. Currently, keep on parsing.
+ */
+ n_equal = 0;
+ }
+
t = 0;
group_idx = 0;
} else {
@@ -16377,23 +16645,11 @@ DUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, const duk
error:
return 0;
}
-
-/* Shared handling for encode/decode argument. Fast path handling for
- * buffer and string values because they're the most common. In particular,
- * avoid creating a temporary string or buffer when possible.
- */
-DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
- DUK_ASSERT(duk_is_valid_index(ctx, index)); /* checked by caller */
- if (duk_is_buffer(ctx, index)) {
- return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len);
- } else {
- return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len);
- }
-}
+#endif /* DUK_USE_BASE64_FASTPATH */
DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
- duk_uint8_t *src;
+ const duk_uint8_t *src;
duk_size_t srclen;
duk_size_t dstlen;
duk_uint8_t *dst;
@@ -16406,7 +16662,7 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
*/
index = duk_require_normalize_index(ctx, index);
- src = (duk_uint8_t *) duk_to_buffer(ctx, index, &srclen);
+ src = duk__prep_codec_arg(ctx, index, &srclen);
/* Note: for srclen=0, src may be NULL */
/* Computation must not wrap; this limit works for 32-bit size_t:
@@ -16420,8 +16676,7 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
dstlen = (srclen + 2) / 3 * 4;
dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
- duk__base64_encode_helper((const duk_uint8_t *) src, (const duk_uint8_t *) (src + srclen),
- dst, (dst + dstlen));
+ duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
ret = duk_to_string(ctx, -1);
duk_replace(ctx, index);
@@ -16448,7 +16703,7 @@ DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) {
*/
index = duk_require_normalize_index(ctx, index);
- src = (const duk_uint8_t *) duk_to_lstring(ctx, index, &srclen);
+ src = duk__prep_codec_arg(ctx, index, &srclen);
/* Computation must not wrap, only srclen + 3 is at risk of
* wrapping because after that the number gets smaller.
@@ -16458,12 +16713,11 @@ DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) {
if (srclen > 4294967292UL) {
goto type_error;
}
- dstlen = (srclen + 3) / 4 * 3; /* upper limit */
+ dstlen = (srclen + 3) / 4 * 3; /* upper limit, assuming no whitespace etc */
dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
/* Note: for dstlen=0, dst may be NULL */
- retval = duk__base64_decode_helper((const duk_uint8_t *) src, (const duk_uint8_t *) (src + srclen),
- dst, dst + dstlen, &dst_final);
+ retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
if (!retval) {
goto type_error;
}
@@ -16481,9 +16735,12 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) {
const duk_uint8_t *inp;
duk_size_t len;
duk_size_t i;
- duk_small_uint_t t;
duk_uint8_t *buf;
const char *ret;
+#if defined(DUK_USE_HEX_FASTPATH)
+ duk_size_t len_safe;
+ duk_uint16_t *p16;
+#endif
DUK_ASSERT_CTX_VALID(ctx);
@@ -16495,12 +16752,28 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) {
buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, DUK_BUF_FLAG_NOZERO /*flags*/);
DUK_ASSERT(buf != NULL);
+#if defined(DUK_USE_HEX_FASTPATH)
+ DUK_ASSERT((((duk_uintptr_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
+ p16 = (duk_uint16_t *) (void *) buf;
+ len_safe = len & ~0x03U;
+ for (i = 0; i < len_safe; i += 4) {
+ p16[0] = duk_hex_enctab[inp[i]];
+ p16[1] = duk_hex_enctab[inp[i + 1]];
+ p16[2] = duk_hex_enctab[inp[i + 2]];
+ p16[3] = duk_hex_enctab[inp[i + 3]];
+ p16 += 4;
+ }
+ for (; i < len; i++) {
+ *p16++ = duk_hex_enctab[inp[i]];
+ }
+#else /* DUK_USE_HEX_FASTPATH */
for (i = 0; i < len; i++) {
- /* XXX: by using two 256-entry tables could avoid shifting and masking. */
+ duk_small_uint_t t;
t = (duk_small_uint_t) inp[i];
buf[i*2 + 0] = duk_lc_digits[t >> 4];
buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
}
+#endif /* DUK_USE_HEX_FASTPATH */
/* XXX: Using a string return value forces a string intern which is
* not always necessary. As a rough performance measure, hex encode
@@ -16519,8 +16792,13 @@ DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) {
const duk_uint8_t *inp;
duk_size_t len;
duk_size_t i;
- duk_small_int_t t;
+ duk_int_t t;
duk_uint8_t *buf;
+#if defined(DUK_USE_HEX_FASTPATH)
+ duk_int_t chk;
+ duk_uint8_t *p;
+ duk_size_t len_safe;
+#endif
DUK_ASSERT_CTX_VALID(ctx);
@@ -16536,18 +16814,55 @@ DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) {
buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, DUK_BUF_FLAG_NOZERO /*flags*/);
DUK_ASSERT(buf != NULL);
+#if defined(DUK_USE_HEX_FASTPATH)
+ p = buf;
+ len_safe = len & ~0x07U;
+ for (i = 0; i < len_safe; i += 8) {
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
+ ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+ chk = t;
+ p[0] = (duk_uint8_t) t;
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
+ ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
+ chk |= t;
+ p[1] = (duk_uint8_t) t;
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
+ ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
+ chk |= t;
+ p[2] = (duk_uint8_t) t;
+ t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
+ ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
+ chk |= t;
+ p[3] = (duk_uint8_t) t;
+ p += 4;
+
+ /* Check if any lookup above had a negative result. */
+ if (DUK_UNLIKELY(chk < 0)) {
+ goto type_error;
+ }
+ }
+ for (; i < len; i += 2) {
+ t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
+ ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
+ if (DUK_UNLIKELY(t < 0)) {
+ goto type_error;
+ }
+ *p++ = (duk_uint8_t) t;
+ }
+#else /* DUK_USE_HEX_FASTPATH */
for (i = 0; i < len; i += 2) {
/* For invalid characters the value -1 gets extended to
* at least 16 bits. If either nybble is invalid, the
* resulting 't' will be < 0.
*/
- t = (((duk_small_int_t) duk_hex_dectab[inp[i]]) << 4) |
- ((duk_small_int_t) duk_hex_dectab[inp[i + 1]]);
+ t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
+ ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
if (DUK_UNLIKELY(t < 0)) {
goto type_error;
}
buf[i >> 1] = (duk_uint8_t) t;
}
+#endif /* DUK_USE_HEX_FASTPATH */
duk_replace(ctx, index);
return;
@@ -16696,7 +17011,7 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx) {
* file given to duk_peval_file() or similar, the
* error message is not the best possible.
*/
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_NO_SOURCECODE);
+ DUK_ERROR_API(thr, DUK_STR_NO_SOURCECODE);
}
DUK_ASSERT(h_sourcecode != NULL);
comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
@@ -16838,6 +17153,10 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
const char *str;
duk_size_t len;
+ /* XXX: should there be an error or an automatic detach if
+ * already attached?
+ */
+
DUK_ASSERT_CTX_VALID(ctx);
DUK_ASSERT(read_cb != NULL);
DUK_ASSERT(write_cb != NULL);
@@ -16851,6 +17170,7 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
heap->dbg_write_flush_cb = write_flush_cb;
heap->dbg_detached_cb = detached_cb;
heap->dbg_udata = udata;
+ heap->dbg_have_next_byte = 0;
/* Start in paused state. */
heap->dbg_processing = 0;
@@ -16888,7 +17208,7 @@ DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
- /* Can be called muliple times with no harm. */
+ /* Can be called multiple times with no harm. */
duk_debug_do_detach(thr->heap);
}
@@ -16936,12 +17256,12 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
DUK_UNREF(write_flush_cb);
DUK_UNREF(detached_cb);
DUK_UNREF(udata);
- duk_error(ctx, DUK_ERR_API_ERROR, "no debugger support");
+ DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
}
DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
DUK_ASSERT_CTX_VALID(ctx);
- duk_error(ctx, DUK_ERR_API_ERROR, "no debugger support");
+ DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
}
DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
@@ -17860,23 +18180,25 @@ DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
#endif
/*
- * Helpers
+ * Misc helpers
*/
/* Check that there's room to push one value. */
#if defined(DUK_USE_VALSTACK_UNSAFE)
/* Faster but value stack overruns are memory unsafe. */
-#define DUK__CHECK_SPACE() do { \
+#define DUK__CHECK_SPACE() do { \
DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
} while (0)
#else
-#define DUK__CHECK_SPACE() do { \
- if (thr->valstack_top >= thr->valstack_end) { \
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
+#define DUK__CHECK_SPACE() do { \
+ if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
} \
} while (0)
#endif
+DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag);
+
DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_bool_t require) {
duk_hthread *thr;
duk_tval *tv;
@@ -17938,7 +18260,7 @@ DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_b
error_notnumber:
if (require) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
/* not reachable */
}
return 0;
@@ -17995,7 +18317,7 @@ DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t index, duk
error_notnumber:
if (require) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
/* not reachable */
}
return 0;
@@ -18071,7 +18393,7 @@ DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t i
if (DUK_LIKELY(uindex < vs_size)) {
return (duk_idx_t) uindex;
}
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+ DUK_ERROR_API_INDEX(thr, index);
return 0; /* unreachable */
}
@@ -18129,7 +18451,7 @@ DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) {
if (DUK_LIKELY(uindex < vs_size)) {
return thr->valstack_bottom + uindex;
}
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+ DUK_ERROR_API_INDEX(thr, index);
return NULL;
}
@@ -18149,7 +18471,8 @@ DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index) {
DUK_ASSERT(DUK_INVALID_INDEX < 0);
if (duk_normalize_index(ctx, index) < 0) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+ DUK_ERROR_API_INDEX(thr, index);
+ return; /* unreachable */
}
}
@@ -18202,10 +18525,11 @@ DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index) {
#if defined(DUK_USE_VALSTACK_UNSAFE)
DUK_ASSERT(uindex <= vs_limit);
+ DUK_UNREF(vs_limit);
#else
if (DUK_UNLIKELY(uindex > vs_limit)) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
- return;
+ DUK_ERROR_API_INDEX(thr, index);
+ return; /* unreachable */
}
#endif
DUK_ASSERT(uindex <= vs_limit);
@@ -18284,7 +18608,8 @@ DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx) {
ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
if (DUK_UNLIKELY(ret < 0)) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+ DUK_ERROR_API_INDEX(thr, -1);
+ return 0; /* unreachable */
}
return ret;
}
@@ -18680,7 +19005,8 @@ DUK_EXTERNAL void duk_dup_top(duk_context *ctx) {
DUK__CHECK_SPACE();
if (thr->valstack_top - thr->valstack_bottom <= 0) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_INDEX);
+ DUK_ERROR_API_INDEX(thr, -1);
+ return; /* unreachable */
}
tv_from = thr->valstack_top - 1;
tv_to = thr->valstack_top++;
@@ -18721,7 +19047,7 @@ DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) {
if (nbytes > 0) {
DUK_TVAL_SET_TVAL(&tv_tmp, q);
DUK_ASSERT(nbytes > 0);
- DUK_MEMMOVE((void *) (p + 1), (void *) p, nbytes);
+ DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
DUK_TVAL_SET_TVAL(p, &tv_tmp);
} else {
/* nop: insert top to top */
@@ -18800,7 +19126,7 @@ DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index) {
#endif
nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
- DUK_MEMMOVE(p, p + 1, nbytes); /* zero size not an issue: pointers are valid */
+ DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes); /* zero size not an issue: pointers are valid */
DUK_TVAL_SET_UNDEFINED(q);
thr->valstack_top--;
@@ -18830,13 +19156,13 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx,
DUK_ASSERT(from_ctx != NULL);
if (to_ctx == from_ctx) {
- DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CONTEXT);
+ DUK_ERROR_API(to_thr, DUK_STR_INVALID_CONTEXT);
return;
}
if ((count < 0) ||
(count > (duk_idx_t) to_thr->valstack_max)) {
/* Maximum value check ensures 'nbytes' won't wrap below. */
- DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
+ DUK_ERROR_API(to_thr, DUK_STR_INVALID_COUNT);
return;
}
@@ -18846,18 +19172,18 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx,
}
DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
- DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(to_thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
if (src < (void *) from_thr->valstack_bottom) {
- DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
+ DUK_ERROR_API(to_thr, DUK_STR_INVALID_COUNT);
}
/* copy values (no overlap even if to_ctx == from_ctx; that's not
* allowed now anyway)
*/
DUK_ASSERT(nbytes > 0);
- DUK_MEMCPY((void *) to_thr->valstack_top, src, nbytes);
+ DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
p = to_thr->valstack_top;
to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
@@ -18895,10 +19221,10 @@ DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index) {
tv = duk_get_tval(ctx, index);
if (tv && DUK_TVAL_IS_UNDEFINED(tv)) {
- /* Note: accept both 'actual' and 'unused' undefined */
return;
}
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_UNDEFINED);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "undefined", DUK_STR_NOT_UNDEFINED);
+ return; /* not reachable */
}
DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) {
@@ -18911,7 +19237,7 @@ DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) {
if (tv && DUK_TVAL_IS_NULL(tv)) {
return;
}
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NULL);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "null", DUK_STR_NOT_NULL);
return; /* not reachable */
}
@@ -18942,8 +19268,7 @@ DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) {
DUK_ASSERT(ret == 0 || ret == 1);
return ret;
}
-
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BOOLEAN);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "boolean", DUK_STR_NOT_BOOLEAN);
return 0; /* not reachable */
}
@@ -18987,8 +19312,7 @@ DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index)
DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret);
return ret.d;
}
-
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NUMBER);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
return DUK_DOUBLE_NAN; /* not reachable */
}
@@ -19057,8 +19381,7 @@ DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index,
if (ret) {
return ret;
}
-
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_STRING);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "string", DUK_STR_NOT_STRING);
return NULL; /* not reachable */
}
@@ -19102,8 +19425,7 @@ DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) {
void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
return (void *) p;
}
-
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_POINTER);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "pointer", DUK_STR_NOT_POINTER);
return NULL; /* not reachable */
}
@@ -19146,7 +19468,7 @@ DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_si
}
if (throw_flag) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "buffer", DUK_STR_NOT_BUFFER);
}
return NULL;
}
@@ -19208,7 +19530,7 @@ DUK_LOCAL void *duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, d
fail:
if (throw_flag) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "buffer", DUK_STR_NOT_BUFFER);
}
return NULL;
}
@@ -19221,78 +19543,68 @@ DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, du
return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/);
}
-/* Raw helper for getting a value from the stack, checking its tag, and possible its object class.
- * The tag cannot be a number because numbers don't have an internal tag in the packed representation.
+/* Raw helper for getting a value from the stack, checking its tag.
+ * The tag cannot be a number because numbers don't have an internal
+ * tag in the packed representation.
*/
-DUK_INTERNAL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t flags_and_tag) {
- duk_hthread *thr = (duk_hthread *) ctx;
+
+DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag) {
duk_tval *tv;
- duk_small_uint_t tag = flags_and_tag & 0xffffU; /* tags can be up to 16 bits */
DUK_ASSERT_CTX_VALID(ctx);
tv = duk_get_tval(ctx, index);
if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) {
duk_heaphdr *ret;
-
- /* Note: tag comparison in general doesn't work for numbers,
- * but it does work for everything else (heap objects here).
- */
ret = DUK_TVAL_GET_HEAPHDR(tv);
DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
-
- /* If class check has been requested, tag must also be DUK_TAG_OBJECT.
- * This allows us to just check the class check flag without checking
- * the tag also.
- */
- DUK_ASSERT((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 ||
- tag == DUK_TAG_OBJECT);
-
- if ((flags_and_tag & DUK_GETTAGGED_FLAG_CHECK_CLASS) == 0 || /* no class check */
- (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) ret) == /* or class check matches */
- (duk_int_t) ((flags_and_tag >> DUK_GETTAGGED_CLASS_SHIFT) & 0xff)) {
- return ret;
- }
- }
-
- if (flags_and_tag & DUK_GETTAGGED_FLAG_ALLOW_NULL) {
- return (duk_heaphdr *) NULL;
+ return ret;
}
- /* Formatting the tag number here is not very useful: the tag value
- * is Duktape internal (not the same as DUK_TYPE_xxx) and even depends
- * on the duk_tval layout. If anything, add a human readable type here.
- */
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
- return NULL; /* not reachable */
+ return (duk_heaphdr *) NULL;
}
DUK_INTERNAL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index) {
- return (duk_hstring *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+ return (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
}
DUK_INTERNAL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index) {
- return (duk_hstring *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
+ duk_heaphdr *h;
+ h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
+ if (h == NULL) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "string", DUK_STR_NOT_STRING);
+ }
+ return (duk_hstring *) h;
}
DUK_INTERNAL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index) {
- return (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+ return (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
}
DUK_INTERNAL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index) {
- return (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ duk_heaphdr *h;
+ h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ if (h == NULL) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "object", DUK_STR_NOT_OBJECT);
+ }
+ return (duk_hobject *) h;
}
DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index) {
- return (duk_hbuffer *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+ return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
}
DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index) {
- return (duk_hbuffer *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
+ duk_heaphdr *h;
+ h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
+ if (h == NULL) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "buffer", DUK_STR_NOT_BUFFER);
+ }
+ return (duk_hbuffer *) h;
}
DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
- duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+ duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
h = NULL;
}
@@ -19301,16 +19613,15 @@ DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
DUK_INTERNAL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
- duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
- DUK_ASSERT(h != NULL);
- if (!DUK_HOBJECT_IS_THREAD(h)) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_THREAD);
+ duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ if (!(h != NULL && DUK_HOBJECT_IS_THREAD(h))) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "thread", DUK_STR_NOT_THREAD);
}
return (duk_hthread *) h;
}
DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
- duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+ duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && !DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
h = NULL;
}
@@ -19319,16 +19630,15 @@ DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx,
DUK_INTERNAL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
- duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
- DUK_ASSERT(h != NULL);
- if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_COMPILEDFUNCTION);
+ duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ if (!(h != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(h))) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
}
return (duk_hcompiledfunction *) h;
}
DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index) {
- duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT | DUK_GETTAGGED_FLAG_ALLOW_NULL);
+ duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
if (h != NULL && !DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
h = NULL;
}
@@ -19337,10 +19647,9 @@ DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_
DUK_INTERNAL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index) {
duk_hthread *thr = (duk_hthread *) ctx;
- duk_hobject *h = (duk_hobject *) duk_get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
- DUK_ASSERT(h != NULL);
- if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_NATIVEFUNCTION);
+ duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ if (!(h != NULL && DUK_HOBJECT_IS_NATIVEFUNCTION(h))) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
}
return (duk_hnativefunction *) h;
}
@@ -19379,11 +19688,17 @@ DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t i
ret = duk_get_c_function(ctx, index);
if (!ret) {
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_C_FUNCTION);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
}
return ret;
}
+DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t index) {
+ if (!duk_is_function(ctx, index)) {
+ DUK_ERROR_REQUIRE_TYPE_INDEX((duk_hthread *) ctx, index, "function", DUK_STR_NOT_FUNCTION);
+ }
+}
+
DUK_EXTERNAL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index) {
DUK_ASSERT_CTX_VALID(ctx);
@@ -19427,7 +19742,7 @@ DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index) {
return ret;
}
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "heapobject", DUK_STR_UNEXPECTED_TYPE);
return (void *) NULL; /* not reachable */
}
@@ -19444,7 +19759,7 @@ duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
* to an object). Return value is NULL if value is neither an object nor a
* lightfunc.
*/
-duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) {
+DUK_INTERNAL duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) {
duk_tval *tv;
DUK_ASSERT_CTX_VALID(ctx);
@@ -19477,8 +19792,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx
} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
return NULL;
}
-
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "object", DUK_STR_NOT_OBJECT);
return NULL; /* not reachable */
}
@@ -19499,11 +19813,44 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx,
duk_to_object(ctx, index);
return duk_require_hobject(ctx, index);
}
-
- DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_UNEXPECTED_TYPE);
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "object", DUK_STR_NOT_OBJECT);
return NULL; /* not reachable */
}
+DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
+ duk_hobject *h;
+
+ DUK_ASSERT_CTX_VALID(ctx);
+ DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
+ DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
+
+ h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
+ h = NULL;
+ }
+ return h;
+}
+
+DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
+ duk_hthread *thr;
+ duk_hobject *h;
+
+ DUK_ASSERT_CTX_VALID(ctx);
+ DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
+ DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
+ thr = (duk_hthread *) ctx;
+
+ h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
+ if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
+ duk_hstring *h_class;
+ h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
+ DUK_UNREF(h_class);
+
+ DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
+ }
+ return h;
+}
+
DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
duk_tval *tv;
@@ -19914,6 +20261,50 @@ DUK_EXTERNAL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index)
}
#endif
+/* Coerce top into Object.prototype.toString() output. */
+DUK_INTERNAL void duk_to_object_class_string_top(duk_context *ctx) {
+ duk_hthread *thr;
+ duk_uint_t typemask;
+ duk_hstring *h_strclass;
+
+ DUK_ASSERT_CTX_VALID(ctx);
+ thr = (duk_hthread *) ctx;
+
+ typemask = duk_get_type_mask(ctx, -1);
+ if (typemask & DUK_TYPE_MASK_UNDEFINED) {
+ h_strclass = DUK_HTHREAD_STRING_UC_UNDEFINED(thr);
+ } else if (typemask & DUK_TYPE_MASK_NULL) {
+ h_strclass = DUK_HTHREAD_STRING_UC_NULL(thr);
+ } else {
+ duk_hobject *h_obj;
+
+ duk_to_object(ctx, -1);
+ h_obj = duk_get_hobject(ctx, -1);
+ DUK_ASSERT(h_obj != NULL);
+
+ h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_obj);
+ }
+ DUK_ASSERT(h_strclass != NULL);
+
+ duk_pop(ctx);
+ duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
+}
+
+#if !defined(DUK_USE_PARANOID_ERRORS)
+DUK_INTERNAL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h) {
+ duk_hthread *thr;
+ duk_hstring *h_strclass;
+
+ DUK_ASSERT_CTX_VALID(ctx);
+ DUK_ASSERT(h != NULL);
+ thr = (duk_hthread *) ctx;
+
+ h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h);
+ DUK_ASSERT(h_strclass != NULL);
+ duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
+}
+#endif /* !DUK_USE_PARANOID_ERRORS */
+
/* XXX: other variants like uint, u32 etc */
DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
duk_hthread *thr = (duk_hthread *) ctx;
@@ -20102,8 +20493,10 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size
* duk_to_dynamic_buffer() call.
*/
duk_uint_t tmp;
+ duk_uint8_t *tmp_ptr;
- src_data = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
+ tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
+ src_data = (const duk_uint8_t *) tmp_ptr;
src_size = DUK_HBUFFER_GET_SIZE(h_buf);
tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
@@ -20112,7 +20505,7 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size
/* Note: src_data may be NULL if input is a zero-size
* dynamic buffer.
*/
- dst_data = (duk_uint8_t *) src_data;
+ dst_data = tmp_ptr;
goto skip_copy;
}
} else {
@@ -20131,7 +20524,7 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size
* target buffer is dynamic). Avoid zero-size memcpy()
* with an invalid pointer.
*/
- DUK_MEMCPY(dst_data, src_data, src_size);
+ DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
}
duk_replace(ctx, index);
skip_copy:
@@ -20410,6 +20803,31 @@ DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) {
DUK_UNREACHABLE();
}
+#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
+DUK_LOCAL const char *duk__type_names[] = {
+ "none",
+ "undefined",
+ "null",
+ "boolean",
+ "number",
+ "string",
+ "object",
+ "buffer",
+ "pointer",
+ "lightfunc"
+};
+
+DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index) {
+ duk_int_t type_tag;
+
+ type_tag = duk_get_type(ctx, index);
+ DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
+ DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
+
+ return duk__type_names[type_tag];
+}
+#endif
+
DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) {
DUK_ASSERT_CTX_VALID(ctx);
@@ -20616,12 +21034,6 @@ DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) {
DUK_HOBJECT_FLAG_THREAD);
}
-DUK_EXTERNAL duk_bool_t duk_is_callable(duk_context *ctx, duk_idx_t index) {
- /* XXX: currently same as duk_is_function() */
- DUK_ASSERT_CTX_VALID(ctx);
- return duk_is_function(ctx, index);
-}
-
DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index) {
duk_tval *tv;
@@ -20888,7 +21300,7 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk
/* check stack before interning (avoid hanging temp) */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
/* NULL with zero length represents an empty string; NULL with higher
@@ -20905,7 +21317,7 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk
DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, DUK_STR_STRING_TOO_LONG);
}
- h = duk_heap_string_intern_checked(thr, (duk_uint8_t *) str, (duk_uint32_t) len);
+ h = duk_heap_string_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
DUK_ASSERT(h != NULL);
tv_slot = thr->valstack_top++;
@@ -21164,7 +21576,7 @@ DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ct
duk_hthread *thr = (duk_hthread *) ctx;
DUK_ASSERT_CTX_VALID(ctx);
if (!target_ctx) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
return; /* not reached */
}
duk_push_hobject(ctx, (duk_hobject *) target_ctx);
@@ -21241,7 +21653,7 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va
/* failed, resize and try again */
sz = sz * 2;
if (sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_SPRINTF_TOO_LONG);
+ DUK_ERROR_API(thr, DUK_STR_SPRINTF_TOO_LONG);
}
}
@@ -21281,7 +21693,7 @@ DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobje
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
h = duk_hobject_alloc(thr->heap, hobject_flags_and_class);
@@ -21381,7 +21793,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
obj = duk_hthread_alloc(thr->heap,
@@ -21440,7 +21852,7 @@ DUK_INTERNAL duk_idx_t duk_push_compiledfunction(duk_context *ctx) {
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
/* Template functions are not strictly constructable (they don't
@@ -21481,7 +21893,7 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function fu
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
if (func == NULL) {
goto api_error;
@@ -21517,7 +21929,7 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function fu
return ret;
api_error:
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
return 0; /* not reached */
}
@@ -21578,7 +21990,7 @@ DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function fun
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
@@ -21602,7 +22014,7 @@ DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function fun
return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
api_error:
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
return 0; /* not reached */
}
@@ -21616,7 +22028,7 @@ DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class);
@@ -21859,7 +22271,7 @@ DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_sm
/* check stack first */
if (thr->valstack_top >= thr->valstack_end) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
+ DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
/* Check for maximum buffer length. */
@@ -21892,7 +22304,7 @@ DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
goto push_undefined;
}
- switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
+ switch ((int) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
case DUK_HTYPE_STRING:
duk_push_hstring(ctx, (duk_hstring *) ptr);
break;
@@ -21969,13 +22381,13 @@ DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) {
DUK_ASSERT_CTX_VALID(ctx);
if (DUK_UNLIKELY(count < 0)) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT);
return;
}
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
if (DUK_UNLIKELY((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count)) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_POP_TOO_MANY);
+ DUK_ERROR_API(thr, DUK_STR_POP_TOO_MANY);
}
/*
@@ -22027,7 +22439,7 @@ DUK_EXTERNAL void duk_pop(duk_context *ctx) {
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_POP_TOO_MANY);
+ DUK_ERROR_API(thr, DUK_STR_POP_TOO_MANY);
}
tv = --thr->valstack_top; /* tv points to element just below prev top */
@@ -22063,7 +22475,7 @@ DUK_EXTERNAL void duk_throw(duk_context *ctx) {
DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
if (thr->valstack_top == thr->valstack_bottom) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
}
/* Errors are augmented when they are created, not when they are
@@ -22283,7 +22695,129 @@ DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, du
duk_push_lstring(ctx, (const char *) buf, sz * 2);
}
+#if !defined(DUK_USE_PARANOID_ERRORS)
+/*
+ * Push readable string summarizing duk_tval. The operation is side effect
+ * free and will only throw from internal errors (e.g. out of memory).
+ * This is used by e.g. property access code to summarize a key/base safely,
+ * and is not intended to be fast (but small and safe).
+ */
+
+#define DUK__READABLE_STRING_MAXCHARS 32
+
+/* String sanitizer which escapes ASCII control characters and a few other
+ * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
+ * question marks. No errors are thrown for any input string, except in out
+ * of memory situations.
+ */
+DUK_LOCAL void duk__push_hstring_readable_unicode(duk_context *ctx, duk_hstring *h_input) {
+ duk_hthread *thr;
+ const duk_uint8_t *p, *p_start, *p_end;
+ duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_STRING_MAXCHARS +
+ 2 /*quotes*/ + 3 /*periods*/];
+ duk_uint8_t *q;
+ duk_ucodepoint_t cp;
+ duk_small_uint_t nchars;
+
+ DUK_ASSERT_CTX_VALID(ctx);
+ DUK_ASSERT(h_input != NULL);
+ thr = (duk_hthread *) ctx;
+
+ p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+ p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
+ p = p_start;
+ q = buf;
+
+ nchars = 0;
+ *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
+ for (;;) {
+ if (p >= p_end) {
+ break;
+ }
+ if (nchars == DUK__READABLE_STRING_MAXCHARS) {
+ *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
+ *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
+ *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
+ break;
+ }
+ if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
+ if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
+ DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
+ DUK_ASSERT((cp >> 4) <= 0x0f);
+ *q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
+ *q++ = (duk_uint8_t) DUK_ASC_LC_X;
+ *q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
+ *q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
+ } else {
+ q += duk_unicode_encode_xutf8(cp, q);
+ }
+ } else {
+ p++; /* advance manually */
+ *q++ = (duk_uint8_t) DUK_ASC_QUESTION;
+ }
+ nchars++;
+ }
+ *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
+
+ duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (q - buf));
+}
+
+DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv) {
+ duk_hthread *thr;
+
+ DUK_ASSERT_CTX_VALID(ctx);
+ thr = (duk_hthread *) ctx;
+ DUK_UNREF(thr);
+
+ if (tv == NULL) {
+ duk_push_string(ctx, "none");
+ } else {
+ switch (DUK_TVAL_GET_TAG(tv)) {
+ case DUK_TAG_STRING: {
+ duk__push_hstring_readable_unicode(ctx, DUK_TVAL_GET_STRING(tv));
+ break;
+ }
+ case DUK_TAG_OBJECT: {
+ duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
+ DUK_ASSERT(h != NULL);
+ duk_push_hobject_class_string(ctx, h);
+ break;
+ }
+ case DUK_TAG_BUFFER: {
+ /* XXX: Hex encoded, length limited buffer summary here? */
+ duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
+ DUK_ASSERT(h != NULL);
+ duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
+ break;
+ }
+ case DUK_TAG_POINTER: {
+ /* Surround with parentheses like in JX, ensures NULL pointer
+ * is distinguishable from null value ("(null)" vs "null").
+ */
+ duk_push_tval(ctx, tv);
+ duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
+ duk_remove(ctx, -2);
+ break;
+ }
+ default: {
+ duk_push_tval(ctx, tv);
+ break;
+ }
+ }
+ }
+
+ return duk_to_string(ctx, -1);
+}
+
+DUK_INTERNAL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index) {
+ DUK_ASSERT_CTX_VALID(ctx);
+ return duk_push_string_tval_readable(ctx, duk_get_tval(ctx, index));
+}
+#endif /* !DUK_USE_PARANOID_ERRORS */
+
#undef DUK__CHECK_SPACE
+#undef DUK__PACK_ARGS
+#undef DUK__READABLE_STRING_MAXCHARS
#line 1 "duk_api_string.c"
/*
* String manipulation
@@ -22304,7 +22838,7 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in,
if (DUK_UNLIKELY(count_in <= 0)) {
if (count_in < 0) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT);
return;
}
DUK_ASSERT(count_in == 0);
@@ -22420,7 +22954,7 @@ DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decod
h_input = duk_require_hstring(ctx, index);
DUK_ASSERT(h_input != NULL);
- p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+ p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
p = p_start;
@@ -22451,7 +22985,7 @@ DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char
bw = &bw_alloc;
DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* reasonable output estimate */
- p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+ p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
p = p_start;
@@ -22585,7 +23119,8 @@ DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index) {
DUK_ASSERT(q_end >= q_start);
DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
- (void *) p_start, (void *) p_end, (void *) q_start, (void *) q_end));
+ (const void *) p_start, (const void *) p_end,
+ (const void *) q_start, (const void *) q_end));
if (q_start == p_start && q_end == p_end) {
DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
@@ -23932,9 +24467,7 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) {
DUK_ASSERT_TOP(ctx, 2);
len = duk__push_this_obj_len_u32(ctx);
- if (!duk_is_callable(ctx, 0)) {
- goto type_error;
- }
+ duk_require_callable(ctx, 0);
/* if thisArg not supplied, behave as if undefined was supplied */
if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
@@ -24049,9 +24582,6 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) {
}
return 1;
-
- type_error:
- return DUK_RET_TYPE_ERROR;
}
/*
@@ -24619,7 +25149,7 @@ DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx,
DUK_INTERNAL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
duk_double_union du;
- DUK_MEMCPY((void *) du.uc, (const void *) p, elem_size);
+ DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
switch (h_bufobj->elem_type) {
case DUK_HBUFFEROBJECT_ELEM_UINT8:
@@ -24703,7 +25233,7 @@ DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbuffe
DUK_UNREACHABLE();
}
- DUK_MEMCPY((void *) p, (const void *) du.uc, elem_size);
+ DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
}
/*
@@ -24894,9 +25424,14 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) {
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
+ duk_hthread *thr;
duk_hbufferobject *h_bufobj;
duk_hbuffer *h_val;
+ DUK_ASSERT_CTX_VALID(ctx);
+ thr = (duk_hthread *) ctx;
+ DUK_UNREF(thr);
+
/* XXX: function flag to make this automatic? */
if (!duk_is_constructor_call(ctx)) {
return DUK_RET_TYPE_ERROR;
@@ -24920,6 +25455,14 @@ DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
(void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
DUK_ASSERT(h_val != NULL);
+
+#if !defined(DUK_USE_ZERO_BUFFER_DATA)
+ /* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
+ * is not set.
+ */
+ DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_val));
+ DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) len);
+#endif
}
h_bufobj = duk_push_bufferobject_raw(ctx,
@@ -25131,6 +25674,14 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
elem_length_signed = (duk_int_t) duk_get_length(ctx, 0);
copy_mode = 2;
}
+ } else if (DUK_TVAL_IS_BUFFER(tv)) {
+ /* Accept plain buffer values like array initializers
+ * (new in Duktape 1.4.0).
+ */
+ duk_hbuffer *h_srcbuf;
+ h_srcbuf = DUK_TVAL_GET_BUFFER(tv);
+ elem_length_signed = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_srcbuf);
+ copy_mode = 2; /* XXX: could add fast path for u8 compatible views */
} else {
/* Non-object argument is simply int coerced, matches
* V8 behavior (except for "null", which we coerce to
@@ -25277,6 +25828,13 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
* ambiguity with Float32/Float64 because zero bytes also
* represent 0.0.
*/
+#if !defined(DUK_USE_ZERO_BUFFER_DATA)
+ /* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
+ * is not set.
+ */
+ DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_val));
+ DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) byte_length);
+#endif
DUK_DDD(DUK_DDDPRINT("using no copy"));
break;
@@ -25419,7 +25977,7 @@ DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) {
if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) {
DUK_MEMCPY((void *) buf_slice,
(const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
- slice_length);
+ (size_t) slice_length);
} else {
/* not covered, return all zeroes */
;
@@ -28835,7 +29393,10 @@ DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) {
#if defined(DUK_USE_DATE_NOW_TIME)
/* Not a very good provider: only full seconds are available. */
DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(duk_context *ctx) {
- time_t t = time(NULL);
+ time_t t;
+
+ DUK_UNREF(ctx);
+ t = time(NULL);
return ((duk_double_t) t) * 1000.0;
}
#endif /* DUK_USE_DATE_NOW_TIME */
@@ -28951,6 +29512,13 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
(long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
(long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
+ /* tm_isdst is both an input and an output to mktime(), use 0 to
+ * avoid DST handling in mktime():
+ * - https://github.com/svaarala/duktape/issues/406
+ * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
+ */
+ tms[0].tm_isdst = 0;
+ tms[1].tm_isdst = 0;
t1 = mktime(&tms[0]); /* UTC */
t2 = mktime(&tms[1]); /* local */
if (t1 == (time_t) -1 || t2 == (time_t) -1) {
@@ -28961,11 +29529,6 @@ DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
*/
goto error;
}
- if (tms[1].tm_isdst > 0) {
- t2 += 3600;
- } else if (tms[1].tm_isdst < 0) {
- DUK_D(DUK_DPRINT("tm_isdst is negative: %d", (int) tms[1].tm_isdst));
- }
DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
/* Compute final offset in seconds, positive if local time ahead of
@@ -29612,7 +30175,7 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
return 1;
}
-#ifdef DUK_USE_TRACEBACKS
+#if defined(DUK_USE_TRACEBACKS)
/*
* Traceback handling
@@ -29633,11 +30196,12 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
#define DUK__OUTPUT_TYPE_FILENAME 0
#define DUK__OUTPUT_TYPE_LINENUMBER 1
-DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
+DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_idx_t idx_td;
duk_small_int_t i; /* traceback depth fits into 16 bits */
duk_small_int_t t; /* stack type fits into 16 bits */
+ duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
const char *str_tailcalled = " tailcalled";
const char *str_strict = " strict";
const char *str_construct = " construct";
@@ -29683,6 +30247,8 @@ DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int
* Ecmascript/native function call or lightfunc call
*/
+ count_func++;
+
/* [ ... v1(func) v2(pc+flags) ] */
h_func = duk_get_hobject(ctx, -2); /* NULL for lightfunc */
@@ -29698,11 +30264,16 @@ DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int
/* [ ... v1 v2 name filename ] */
- if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
- return 1;
- } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
- duk_push_int(ctx, line);
- return 1;
+ /* When looking for .fileName/.lineNumber, blame first
+ * function which has a .fileName.
+ */
+ if (duk_is_string(ctx, -1)) {
+ if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
+ return 1;
+ } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
+ duk_push_int(ctx, line);
+ return 1;
+ }
}
h_name = duk_get_hstring(ctx, -2); /* may be NULL */
@@ -29752,6 +30323,9 @@ DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int
/* [ ... v1(filename) v2(line+flags) ] */
+ /* When looking for .fileName/.lineNumber, blame compilation
+ * or C call site unless flagged not to do so.
+ */
if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
duk_pop(ctx);
@@ -29773,7 +30347,7 @@ DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int
}
}
- if (i >= DUK_USE_TRACEBACK_DEPTH * 2) {
+ if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
/* Possibly truncated; there is no explicit truncation
* marker so this is the best we can do.
*/
@@ -29796,20 +30370,20 @@ DUK_LOCAL duk_ret_t duk__traceback_getter_helper(duk_context *ctx, duk_small_int
}
}
-/* XXX: output type could be encoded into native function 'magic' value to
- * save space.
+/* XXX: Output type could be encoded into native function 'magic' value to
+ * save space. For setters the stridx could be encoded into 'magic'.
*/
DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
- return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
+ return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
}
DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
- return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
+ return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
}
DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
- return duk__traceback_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
+ return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
}
#undef DUK__OUTPUT_TYPE_TRACEBACK
@@ -29849,14 +30423,43 @@ DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx
#endif /* DUK_USE_TRACEBACKS */
-DUK_INTERNAL duk_ret_t duk_bi_error_prototype_nop_setter(duk_context *ctx) {
- /* Attempt to write 'stack', 'fileName', 'lineNumber' is a silent no-op.
- * User can use Object.defineProperty() to override this behavior.
+DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key) {
+ /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
+ * user code called Object.defineProperty() to create an overriding
+ * own property. This allows user code to overwrite .fileName etc
+ * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
+ * See https://github.com/svaarala/duktape/issues/387.
*/
- DUK_ASSERT_TOP(ctx, 1); /* fixed arg count */
- DUK_UNREF(ctx);
+
+ DUK_ASSERT_TOP(ctx, 1); /* fixed arg count: value */
+
+ duk_push_this(ctx);
+ duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
+ duk_dup(ctx, 0);
+
+ /* [ ... obj key value ] */
+
+ DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
+ duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
+
+ duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |
+ DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
+ DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
+ DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
return 0;
}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx) {
+ return duk__error_setter_helper(ctx, DUK_STRIDX_STACK);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx) {
+ return duk__error_setter_helper(ctx, DUK_STRIDX_FILE_NAME);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx) {
+ return duk__error_setter_helper(ctx, DUK_STRIDX_LINE_NUMBER);
+}
#line 1 "duk_bi_function.c"
/*
* Function built-ins
@@ -30300,7 +30903,7 @@ typedef struct {
const duk_uint8_t *p_end;
} duk__transform_context;
-typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp);
+typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
/* XXX: refactor and share with other code */
DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
@@ -30320,7 +30923,7 @@ DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small
return t;
}
-DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, void *udata) {
+DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata) {
duk_hthread *thr = (duk_hthread *) ctx;
duk__transform_context tfm_ctx_alloc;
duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
@@ -30348,12 +30951,12 @@ DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback ca
return 1;
}
-DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
+DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
duk_small_int_t len;
duk_codepoint_t cp1, cp2;
duk_small_int_t i, t;
- const duk_uint8_t *unescaped_table = (duk_uint8_t *) udata;
+ const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
* Codepoint range is restricted so this is a slightly too large
@@ -30410,8 +31013,8 @@ DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ct
DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
}
-DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
- const duk_uint8_t *reserved_table = (duk_uint8_t *) udata;
+DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
+ const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
duk_small_uint_t utf8_blen;
duk_codepoint_t min_cp;
duk_small_int_t t; /* must be signed */
@@ -30549,7 +31152,7 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct
}
#ifdef DUK_USE_SECTION_B
-DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
+DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
DUK_UNREF(udata);
DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
@@ -30588,7 +31191,7 @@ DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, v
DUK_ERROR(tfm_ctx->thr, DUK_ERR_TYPE_ERROR, "invalid input");
}
-DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) {
+DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
duk_small_int_t t;
DUK_UNREF(udata);
@@ -30634,6 +31237,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
duk_hobject *outer_var_env;
duk_bool_t this_to_global = 1;
duk_small_uint_t comp_flags;
+ duk_int_t level = -2;
DUK_ASSERT_TOP(ctx, 1);
DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
@@ -30653,15 +31257,26 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
return 1; /* return arg as-is */
}
+#if defined(DUK_USE_DEBUGGER_SUPPORT)
+ /* NOTE: level is used only by the debugger and should never be present
+ * for an Ecmascript eval().
+ */
+ DUK_ASSERT(level == -2); /* by default, use caller's environment */
+ if (duk_get_top(ctx) >= 2 && duk_is_number(ctx, 1)) {
+ level = duk_get_int(ctx, 1);
+ }
+ DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
+#endif
+
/* [ source ] */
comp_flags = DUK_JS_COMPILE_FLAG_EVAL;
act_eval = thr->callstack + thr->callstack_top - 1; /* this function */
- if (thr->callstack_top >= 2) {
+ if (thr->callstack_top >= (duk_size_t) -level) {
/* Have a calling activation, check for direct eval (otherwise
* assume indirect eval.
*/
- act_caller = thr->callstack + thr->callstack_top - 2; /* caller */
+ act_caller = thr->callstack + thr->callstack_top + level; /* caller */
if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
(act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
/* Only direct eval inherits strictness from calling code
@@ -30691,14 +31306,14 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
act = thr->callstack + thr->callstack_top - 1; /* this function */
if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
DUK_ASSERT(thr->callstack_top >= 2);
- act = thr->callstack + thr->callstack_top - 2; /* caller */
+ act = thr->callstack + thr->callstack_top + level; /* caller */
if (act->lex_env == NULL) {
DUK_ASSERT(act->var_env == NULL);
DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
/* this may have side effects, so re-lookup act */
duk_js_init_activation_environment_records_delayed(thr, act);
- act = thr->callstack + thr->callstack_top - 2;
+ act = thr->callstack + thr->callstack_top + level;
}
DUK_ASSERT(act->lex_env != NULL);
DUK_ASSERT(act->var_env != NULL);
@@ -30713,7 +31328,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
"var_env and lex_env to a fresh env, "
"this_binding to caller's this_binding"));
- act = thr->callstack + thr->callstack_top - 2; /* caller */
+ act = thr->callstack + thr->callstack_top + level; /* caller */
act_lex_env = act->lex_env;
act = NULL; /* invalidated */
@@ -30764,7 +31379,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
} else {
duk_tval *tv;
DUK_ASSERT(thr->callstack_top >= 2);
- act = thr->callstack + thr->callstack_top - 2; /* caller */
+ act = thr->callstack + thr->callstack_top + level; /* caller */
tv = thr->valstack + act->idx_bottom - 1; /* this is just beneath bottom */
DUK_ASSERT(tv >= thr->valstack);
duk_push_tval(ctx, tv);
@@ -30789,44 +31404,39 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
*/
DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) {
- duk_bool_t strip_prefix;
duk_int32_t radix;
duk_small_uint_t s2n_flags;
DUK_ASSERT_TOP(ctx, 2);
duk_to_string(ctx, 0);
- strip_prefix = 1;
radix = duk_to_int32(ctx, 1);
+
+ s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
+ DUK_S2N_FLAG_ALLOW_GARBAGE |
+ DUK_S2N_FLAG_ALLOW_PLUS |
+ DUK_S2N_FLAG_ALLOW_MINUS |
+ DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
+ DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
+
+ /* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
+ *
+ * Don't autodetect octals (from leading zeroes), require user code to
+ * provide an explicit radix 8 for parsing octal. See write-up from Mozilla:
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
+ */
+
if (radix != 0) {
if (radix < 2 || radix > 36) {
goto ret_nan;
}
- /* For octal, setting strip_prefix=0 is not necessary, as zero
- * is tolerated anyway:
- *
- * parseInt('123', 8) === parseInt('0123', 8) with or without strip_prefix
- * parseInt('123', 16) === parseInt('0x123', 16) requires strip_prefix = 1
- */
if (radix != 16) {
- strip_prefix = 0;
+ s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
}
} else {
radix = 10;
}
- s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
- DUK_S2N_FLAG_ALLOW_GARBAGE |
- DUK_S2N_FLAG_ALLOW_PLUS |
- DUK_S2N_FLAG_ALLOW_MINUS |
- DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
-#ifdef DUK_USE_OCTAL_SUPPORT
- (strip_prefix ? (DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT | DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) : 0)
-#else
- (strip_prefix ? DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT : 0)
-#endif
- ;
-
duk_dup(ctx, 0);
duk_numconv_parse(ctx, radix, s2n_flags);
return 1;
@@ -30882,28 +31492,28 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) {
*/
DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx) {
- return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (void *) duk__decode_uri_reserved_table);
+ return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx) {
- return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (void *) duk__decode_uri_component_reserved_table);
+ return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx) {
- return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (void *) duk__encode_uriunescaped_table);
+ return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx) {
- return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (void *) duk__encode_uricomponent_unescaped_table);
+ return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
}
#ifdef DUK_USE_SECTION_B
DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
- return duk__transform_helper(ctx, duk__transform_callback_escape, (void *) NULL);
+ return duk__transform_helper(ctx, duk__transform_callback_escape, (const void *) NULL);
}
DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
- return duk__transform_helper(ctx, duk__transform_callback_unescape, (void *) NULL);
+ return duk__transform_helper(ctx, duk__transform_callback_unescape, (const void *) NULL);
}
#else /* DUK_USE_SECTION_B */
DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
@@ -30974,13 +31584,13 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
}
if (sz_buf <= sizeof(buf_stack)) {
- buf = (const duk_uint8_t *) buf_stack;
+ p = (duk_uint8_t *) buf_stack;
} else {
- buf = (const duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf);
- DUK_ASSERT(buf != NULL);
+ p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf);
+ DUK_ASSERT(p != NULL);
}
- p = (duk_uint8_t *) buf;
+ buf = (const duk_uint8_t *) p;
for (i = 0; i < nargs; i++) {
p_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &sz_str);
DUK_ASSERT(p_str != NULL);
@@ -31474,9 +32084,10 @@ DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);
DUK_LOCAL_DECL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key);
+DUK_LOCAL_DECL void duk__enc_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_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top);
-DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top);
+DUK_LOCAL_DECL void duk__enc_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_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
@@ -31486,6 +32097,14 @@ DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
#if defined(DUK_USE_FASTINT)
DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
#endif
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+DUK_LOCAL_DECL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
+DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL_DECL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj);
+#endif
+#endif
+DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth);
/*
* Helper tables
@@ -31700,7 +32319,7 @@ DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx,
DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
duk_hstring *h;
- duk_uint8_t *p;
+ const duk_uint8_t *p;
duk_uint8_t x, y;
/* First character has already been eaten and checked by the caller.
@@ -31713,7 +32332,7 @@ DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t st
h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
DUK_ASSERT(h != NULL);
- p = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
+ p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
for (;;) {
@@ -31996,12 +32615,26 @@ DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
duk_hthread *thr = js_ctx->thr;
duk_context *ctx = (duk_context *) thr;
const duk_uint8_t *p;
+ duk_uint8_t *buf;
+ duk_size_t src_len;
duk_small_int_t x;
/* Caller has already eaten the first character ('|') which we don't need. */
p = js_ctx->p;
+ /* XXX: Would be nice to share the fast path loop from duk_hex_decode()
+ * and avoid creating a temporary buffer. However, there are some
+ * differences which prevent trivial sharing:
+ *
+ * - Pipe char detection
+ * - EOF detection
+ * - Unknown length of input and output
+ *
+ * The best approach here would be a bufwriter and a reasonaly sized
+ * safe inner loop (e.g. 64 output bytes at a time).
+ */
+
for (;;) {
x = *p;
@@ -32017,8 +32650,12 @@ DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
p++;
}
- duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
+ src_len = (duk_size_t) (p - js_ctx->p);
+ buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_len);
+ DUK_ASSERT(buf != NULL);
+ DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
duk_hex_decode(ctx, -1);
+
js_ctx->p = p + 1; /* skip '|' */
/* [ ... buf ] */
@@ -32052,8 +32689,8 @@ DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
x = *p;
DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
- (void *) p_start, (void *) p,
- (void *) js_ctx->p_end, (long) x));
+ (const void *) p_start, (const void *) p,
+ (const void *) js_ctx->p_end, (long) x));
#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
/* This fast path is pretty marginal in practice.
@@ -32552,7 +33189,8 @@ DUK_LOCAL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) {
p = p_start;
DUK_DDD(DUK_DDDPRINT("duk__enc_key_quotes_needed: h_key=%!O, p_start=%p, p_end=%p, p=%p",
- (duk_heaphdr *) h_key, (void *) p_start, (void *) p_end, (void *) p));
+ (duk_heaphdr *) h_key, (const void *) p_start,
+ (const void *) p_end, (const void *) p));
/* Since we only accept ASCII characters, there is no need for
* actual decoding. A non-ASCII character will be >= 0x80 which
@@ -32583,6 +33221,17 @@ DUK_LOCAL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) {
return 0;
}
+DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
+ /* XXX: could reimplement so that we start emitting the key without
+ * quotes and backtrack if we hit a problem character.
+ */
+ if (js_ctx->flag_avoid_key_quotes && !duk__enc_key_quotes_needed(k)) {
+ DUK__EMIT_HSTR(js_ctx, k);
+ } else {
+ duk__enc_quote_string(js_ctx, k);
+ }
+}
+
/* The Quote(value) operation: quote a string.
*
* Stack policy: [ ] -> [ ].
@@ -32757,7 +33406,7 @@ DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
* it would otherwise serialize to '0', not '-0'.
*/
if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
- (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible))) {
+ (js_ctx->flag_ext_custom_or_compatible))) {
duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO); /* '-0' */
} else
#endif /* DUK_USE_JX || DUK_USE_JC */
@@ -32814,35 +33463,306 @@ DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
}
#endif
-/* Shared entry handling for object/array serialization: indent/stepback,
- * loop detection.
+#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_uint8_t *q;
+ duk_uint16_t *q16;
+ duk_small_uint_t x;
+ duk_size_t i, len_safe;
+#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+ duk_bool_t shift_dst;
+#endif
+
+ /* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
+ * For platforms where unaligned accesses are not allowed, shift 'dst'
+ * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
+ * in place. The faster encoding loop makes up the difference.
+ * There's always space for one extra byte because a terminator always
+ * follows the hex data and that's been accounted for by the caller.
+ */
+
+#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+ q16 = (duk_uint16_t *) (void *) dst;
+#else
+ shift_dst = (duk_bool_t) (((duk_uintptr_t) dst) & 0x01U);
+ if (shift_dst) {
+ DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
+ q16 = (duk_uint16_t *) (void *) (dst + 1);
+ } else {
+ DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
+ q16 = (duk_uint16_t *) (void *) dst;
+ }
+ DUK_ASSERT((((duk_uintptr_t) q16) & 0x01U) == 0);
+#endif
+
+ len_safe = src_len & ~0x03U;
+ for (i = 0; i < len_safe; i += 4) {
+ q16[0] = duk_hex_enctab[src[i]];
+ q16[1] = duk_hex_enctab[src[i + 1]];
+ q16[2] = duk_hex_enctab[src[i + 2]];
+ q16[3] = duk_hex_enctab[src[i + 3]];
+ q16 += 4;
+ }
+ q = (duk_uint8_t *) q16;
+
+#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
+ if (shift_dst) {
+ q--;
+ DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
+ DUK_ASSERT(dst + 2 * len_safe == q);
+ }
+#endif
+
+ for (; i < src_len; i++) {
+ x = src[i];
+ *q++ = duk_lc_digits[x >> 4];
+ *q++ = duk_lc_digits[x & 0x0f];
+ }
+
+ 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) {
+ const duk_uint8_t *p;
+ const duk_uint8_t *p_end;
+ duk_uint8_t *q;
+ duk_small_uint_t x;
+
+ p = src;
+ p_end = src + src_len;
+ q = dst;
+ while (p != p_end) {
+ x = *p++;
+ *q++ = duk_lc_digits[x >> 4];
+ *q++ = duk_lc_digits[x & 0x0f];
+ }
+
+ return q;
+}
+#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_hthread *thr;
+ duk_uint8_t *q;
+ duk_size_t space;
+
+ thr = js_ctx->thr;
+
+ DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
+ DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
+
+ /* Buffer values are encoded in (lowercase) hex to make the
+ * binary data readable. Base64 or similar would be more
+ * compact but less readable, and the point of JX/JC
+ * variants is to be as useful to a programmer as possible.
+ */
+
+ /* The #ifdef clutter here needs to handle the three cases:
+ * (1) JX+JC, (2) JX only, (3) JC only.
+ */
+
+ /* Note: space must cater for both JX and JC. */
+ space = 9 + buf_len * 2 + 2;
+ DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
+ DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
+ q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
+
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+ if (js_ctx->flag_ext_custom)
+#endif
+#if defined(DUK_USE_JX)
+ {
+ *q++ = DUK_ASC_PIPE;
+ q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+ *q++ = DUK_ASC_PIPE;
+
+ }
+#endif
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+ else
+#endif
+#if defined(DUK_USE_JC)
+ {
+ DUK_ASSERT(js_ctx->flag_ext_compatible);
+ DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
+ q += 9;
+ q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
+ *q++ = DUK_ASC_DOUBLEQUOTE;
+ *q++ = DUK_ASC_RCURLY;
+ }
+#endif
+
+ DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
+}
+
+DUK_LOCAL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
+ duk__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_JX) || defined(DUK_USE_JC)
+DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
+ char buf[64]; /* XXX: how to figure correct size? */
+ const char *fmt;
+
+ DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
+ DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
+
+ DUK_MEMZERO(buf, sizeof(buf));
+
+ /* The #ifdef clutter here needs to handle the three cases:
+ * (1) JX+JC, (2) JX only, (3) JC only.
+ */
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+ if (js_ctx->flag_ext_custom)
+#endif
+#if defined(DUK_USE_JX)
+ {
+ fmt = ptr ? "(%p)" : "(null)";
+ }
+#endif
+#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
+ else
+#endif
+#if defined(DUK_USE_JC)
+ {
+ DUK_ASSERT(js_ctx->flag_ext_compatible);
+ fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
+ }
+#endif
+
+ /* When ptr == NULL, the format argument is unused. */
+ DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
+ DUK__EMIT_CSTR(js_ctx, buf);
+}
+#endif /* DUK_USE_JX || DUK_USE_JC */
+
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
+DUK_LOCAL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj) {
+ DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
+
+ if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_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_uint8_t *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
+ (duk_size_t) h_bufobj->length);
+ }
+}
+#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
+#endif /* DUK_USE_JX || DUK_USE_JC */
+
+/* Indent helper. Calling code relies on js_ctx->recursion_depth also being
+ * directly related to indent depth.
*/
-DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top) {
+#if defined(DUK_USE_PREFER_SIZE)
+DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
+ DUK_ASSERT(js_ctx->h_gap != NULL);
+ DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
+
+ DUK__EMIT_1(js_ctx, 0x0a);
+ while (depth-- > 0) {
+ DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
+ }
+}
+#else /* DUK_USE_PREFER_SIZE */
+DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
+ const duk_uint8_t *gap_data;
+ duk_size_t gap_len;
+ duk_size_t avail_bytes; /* bytes of indent available for copying */
+ duk_size_t need_bytes; /* bytes of indent still needed */
+ duk_uint8_t *p_start;
+ duk_uint8_t *p;
+
+ DUK_ASSERT(js_ctx->h_gap != NULL);
+ DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
+
+ DUK__EMIT_1(js_ctx, 0x0a);
+ if (DUK_UNLIKELY(depth == 0)) {
+ return;
+ }
+
+ /* To handle deeper indents efficiently, make use of copies we've
+ * already emitted. In effect we can emit a sequence of 1, 2, 4,
+ * 8, etc copies, and then finish the last run. Byte counters
+ * avoid multiply with gap_len on every loop.
+ */
+
+ gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
+ gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
+ DUK_ASSERT(gap_len > 0);
+
+ need_bytes = gap_len * depth;
+ p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
+ p_start = p;
+
+ DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
+ p += gap_len;
+ avail_bytes = gap_len;
+ DUK_ASSERT(need_bytes >= gap_len);
+ need_bytes -= gap_len;
+
+ while (need_bytes >= avail_bytes) {
+ DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
+ p += avail_bytes;
+ need_bytes -= avail_bytes;
+ avail_bytes <<= 1;
+ }
+
+ DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
+ DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
+ p += need_bytes;
+ /*avail_bytes += need_bytes*/
+
+ DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
+}
+#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_context *ctx = (duk_context *) js_ctx->thr;
duk_hobject *h_target;
+ duk_uint_fast32_t i, n;
*entry_top = duk_get_top(ctx);
duk_require_stack(ctx, DUK_JSON_ENC_REQSTACK);
- /* loop check */
+ /* Loop check using a hybrid approach: a fixed-size visited[] array
+ * with overflow in a loop check object.
+ */
h_target = duk_get_hobject(ctx, -1); /* object or array */
DUK_ASSERT(h_target != NULL);
- /* XXX: this check is very expensive, perhaps use a small
- * array to make it faster for at least reasonably shallow
- * objects?
- */
- duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
- duk_dup_top(ctx); /* -> [ ... voidp voidp ] */
- if (duk_has_prop(ctx, js_ctx->idx_loop)) {
- DUK_ERROR((duk_hthread *) ctx, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
+ n = js_ctx->recursion_depth;
+ if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
+ n = DUK_JSON_ENC_LOOPARRAY;
+ }
+ for (i = 0; i < n; i++) {
+ if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
+ DUK_DD(DUK_DDPRINT("slow path loop detect"));
+ DUK_ERROR(js_ctx->thr, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
+ }
+ }
+ if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
+ js_ctx->visiting[js_ctx->recursion_depth] = h_target;
+ } else {
+ duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
+ duk_dup_top(ctx); /* -> [ ... voidp voidp ] */
+ if (duk_has_prop(ctx, js_ctx->idx_loop)) {
+ DUK_ERROR((duk_hthread *) ctx, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
+ }
+ duk_push_true(ctx); /* -> [ ... voidp true ] */
+ duk_put_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
}
- duk_push_true(ctx); /* -> [ ... voidp true ] */
- duk_put_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
- /* c recursion check */
+ /* C recursion check. */
DUK_ASSERT(js_ctx->recursion_depth >= 0);
DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
@@ -32851,71 +33771,34 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_s
}
js_ctx->recursion_depth++;
- /* figure out indent and stepback */
-
- *h_indent = NULL;
- *h_stepback = NULL;
- if (js_ctx->h_gap != NULL) {
- DUK_ASSERT(js_ctx->h_indent != NULL);
-
- *h_stepback = js_ctx->h_indent;
- duk_push_hstring(ctx, js_ctx->h_indent);
- duk_push_hstring(ctx, js_ctx->h_gap);
- duk_concat(ctx, 2);
- js_ctx->h_indent = duk_get_hstring(ctx, -1);
- *h_indent = js_ctx->h_indent;
- DUK_ASSERT(js_ctx->h_indent != NULL);
-
- /* The new indent string is left at value stack top, and will
- * be popped by the shared exit handler.
- */
- } else {
- DUK_ASSERT(js_ctx->h_indent == NULL);
- }
-
DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
(long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
}
/* Shared exit handling for object/array serialization. */
-DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top) {
+DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
duk_context *ctx = (duk_context *) js_ctx->thr;
duk_hobject *h_target;
- DUK_UNREF(h_indent);
-
- if (js_ctx->h_gap != NULL) {
- DUK_ASSERT(js_ctx->h_indent != NULL);
- DUK_ASSERT(*h_stepback != NULL);
- DUK_ASSERT(*h_indent != NULL);
-
- js_ctx->h_indent = *h_stepback; /* previous js_ctx->h_indent */
-
- /* Note: we don't need to pop anything because the duk_set_top()
- * at the end will take care of it.
- */
- } else {
- DUK_ASSERT(js_ctx->h_indent == NULL);
- DUK_ASSERT(*h_stepback == NULL);
- DUK_ASSERT(*h_indent == NULL);
- }
-
- /* c recursion check */
+ /* C recursion check. */
DUK_ASSERT(js_ctx->recursion_depth > 0);
DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
js_ctx->recursion_depth--;
- /* loop check */
+ /* Loop check. */
h_target = duk_get_hobject(ctx, *entry_top - 1); /* original target at entry_top - 1 */
DUK_ASSERT(h_target != NULL);
- /* XXX: this check is very expensive */
- duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
- duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
+ if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
+ /* Previous entry was inside visited[], nothing to do. */
+ } else {
+ duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
+ duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
+ }
- /* restore stack top after unbalanced code paths */
+ /* Restore stack top after unbalanced code paths. */
duk_set_top(ctx, *entry_top);
DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
@@ -32928,8 +33811,6 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_st
*/
DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
duk_context *ctx = (duk_context *) js_ctx->thr;
- duk_hstring *h_stepback;
- duk_hstring *h_indent;
duk_hstring *h_key;
duk_idx_t entry_top;
duk_idx_t idx_obj;
@@ -32940,7 +33821,7 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
- duk__enc_objarr_entry(js_ctx, &h_stepback, &h_indent, &entry_top);
+ duk__enc_objarr_entry(js_ctx, &entry_top);
idx_obj = entry_top - 1;
@@ -32991,21 +33872,16 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
} else {
DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
}
- if (h_indent != NULL) {
- DUK__EMIT_1(js_ctx, 0x0a);
- DUK__EMIT_HSTR(js_ctx, h_indent);
+ if (js_ctx->h_gap != NULL) {
+ DUK_ASSERT(js_ctx->recursion_depth >= 1);
+ duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
}
h_key = duk_get_hstring(ctx, -2);
DUK_ASSERT(h_key != NULL);
- if (js_ctx->flag_avoid_key_quotes && !duk__enc_key_quotes_needed(h_key)) {
- /* emit key as is */
- DUK__EMIT_HSTR(js_ctx, h_key);
- } else {
- duk__enc_quote_string(js_ctx, h_key);
- }
+ duk__enc_key_autoquote(js_ctx, h_key);
- if (h_indent != NULL) {
+ if (js_ctx->h_gap != NULL) {
DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
} else {
DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
@@ -33017,15 +33893,14 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
}
if (!first) {
- if (h_stepback != NULL) {
- DUK_ASSERT(h_indent != NULL);
- DUK__EMIT_1(js_ctx, 0x0a);
- DUK__EMIT_HSTR(js_ctx, h_stepback);
+ if (js_ctx->h_gap != NULL) {
+ DUK_ASSERT(js_ctx->recursion_depth >= 1);
+ duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
}
}
DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
- duk__enc_objarr_exit(js_ctx, &h_stepback, &h_indent, &entry_top);
+ duk__enc_objarr_exit(js_ctx, &entry_top);
DUK_ASSERT_TOP(ctx, entry_top);
}
@@ -33036,8 +33911,6 @@ DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
*/
DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
duk_context *ctx = (duk_context *) js_ctx->thr;
- duk_hstring *h_stepback;
- duk_hstring *h_indent;
duk_idx_t entry_top;
duk_idx_t idx_arr;
duk_bool_t undef;
@@ -33046,7 +33919,7 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
(duk_tval *) duk_get_tval(ctx, -1)));
- duk__enc_objarr_entry(js_ctx, &h_stepback, &h_indent, &entry_top);
+ duk__enc_objarr_entry(js_ctx, &entry_top);
idx_arr = entry_top - 1;
@@ -33056,16 +33929,16 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr);
for (i = 0; i < arr_len; i++) {
- DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, h_indent=%!O, h_stepback=%!O, index=%ld, arr_len=%ld",
- (duk_tval *) duk_get_tval(ctx, idx_arr), (duk_heaphdr *) h_indent,
- (duk_heaphdr *) h_stepback, (long) i, (long) arr_len));
+ DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
+ (duk_tval *) duk_get_tval(ctx, idx_arr),
+ (long) i, (long) arr_len));
if (i > 0) {
DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
}
- if (h_indent != NULL) {
- DUK__EMIT_1(js_ctx, 0x0a);
- DUK__EMIT_HSTR(js_ctx, h_indent);
+ if (js_ctx->h_gap != NULL) {
+ DUK_ASSERT(js_ctx->recursion_depth >= 1);
+ duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
}
/* XXX: duk_push_uint_string() */
@@ -33082,15 +33955,14 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
}
if (arr_len > 0) {
- if (h_stepback != NULL) {
- DUK_ASSERT(h_indent != NULL);
- DUK__EMIT_1(js_ctx, 0x0a);
- DUK__EMIT_HSTR(js_ctx, h_stepback);
+ if (js_ctx->h_gap != NULL) {
+ DUK_ASSERT(js_ctx->recursion_depth >= 1);
+ duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
}
}
DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
- duk__enc_objarr_exit(js_ctx, &h_stepback, &h_indent, &entry_top);
+ duk__enc_objarr_exit(js_ctx, &entry_top);
DUK_ASSERT_TOP(ctx, entry_top);
}
@@ -33290,35 +34162,7 @@ DUK_LOCAL void duk__enc_value2(duk_json_enc_ctx *js_ctx) {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
/* When JX/JC not in use, duk__enc_value1 will block pointer values. */
case DUK_TAG_POINTER: {
- char buf[64]; /* XXX: how to figure correct size? */
- const char *fmt;
- void *ptr = DUK_TVAL_GET_POINTER(tv);
-
- DUK_MEMZERO(buf, sizeof(buf));
-
- /* The #ifdef clutter here needs to handle the three cases:
- * (1) JX+JC, (2) JX only, (3) JC only.
- */
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
- if (js_ctx->flag_ext_custom)
-#endif
-#if defined(DUK_USE_JX)
- {
- fmt = ptr ? "(%p)" : "(null)";
- }
-#endif
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
- else
-#endif
-#if defined(DUK_USE_JC)
- {
- fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
- }
-#endif
-
- /* When ptr == NULL, the format argument is unused. */
- DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
- DUK__EMIT_CSTR(js_ctx, buf);
+ duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
break;
}
#endif /* DUK_USE_JX || DUK_USE_JC */
@@ -33350,59 +34194,7 @@ DUK_LOCAL void duk__enc_value2(duk_json_enc_ctx *js_ctx) {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
/* When JX/JC not in use, duk__enc_value1 will block buffer values. */
case DUK_TAG_BUFFER: {
- /* Buffer values are encoded in (lowercase) hex to make the
- * binary data readable. Base64 or similar would be more
- * compact but less readable, and the point of JX/JC
- * variants is to be as useful to a programmer as possible.
- */
-
- /* The #ifdef clutter here needs to handle the three cases:
- * (1) JX+JC, (2) JX only, (3) JC only.
- */
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
- if (js_ctx->flag_ext_custom)
-#endif
-#if defined(DUK_USE_JX)
- {
- duk_uint8_t *p, *p_end;
- duk_small_uint_t x;
- duk_hbuffer *h;
- duk_uint8_t *q;
- duk_size_t space;
-
- h = DUK_TVAL_GET_BUFFER(tv);
- DUK_ASSERT(h != NULL);
- p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
- p_end = p + DUK_HBUFFER_GET_SIZE(h);
-
- space = 1 + DUK_HBUFFER_GET_SIZE(h) * 2 + 1;
- DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
- DUK_ASSERT((space - 2) / 2 == DUK_HBUFFER_GET_SIZE(h)); /* overflow not possible, buffer limits */
- q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
-
- *q++ = DUK_ASC_PIPE;
- while (p < p_end) {
- x = *p++;
- *q++ = duk_lc_digits[(x >> 4) & 0x0f];
- *q++ = duk_lc_digits[x & 0x0f];
- }
- *q++ = DUK_ASC_PIPE;
-
- DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
- }
-#endif
-#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
- else
-#endif
-#if defined(DUK_USE_JC)
- {
- DUK_ASSERT(js_ctx->flag_ext_compatible);
- duk_hex_encode(ctx, -1);
- DUK__EMIT_CSTR(js_ctx, "{\"_buf\":");
- duk__enc_quote_string(js_ctx, duk_require_hstring(ctx, -1));
- DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
- }
-#endif
+ duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
break;
}
#endif /* DUK_USE_JX || DUK_USE_JC */
@@ -33464,6 +34256,11 @@ DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
/*
* JSON.stringify() fast path
+ *
+ * Otherwise supports full JSON, JX, and JC features, but bails out on any
+ * possible side effect which might change the value being serialized. The
+ * fast path can take advantage of the fact that the value being serialized
+ * is unchanged so that we can walk directly through property tables etc.
*/
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
@@ -33474,19 +34271,22 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
DUK_ASSERT(js_ctx != NULL);
DUK_ASSERT(js_ctx->thr != NULL);
-#if defined(DUK_USE_JX)
- DUK_ASSERT(js_ctx->flag_ext_custom == 0);
-#endif
-#if defined(DUK_USE_JC)
- DUK_ASSERT(js_ctx->flag_ext_compatible == 0);
-#endif
restart_match:
DUK_ASSERT(tv != NULL);
switch (DUK_TVAL_GET_TAG(tv)) {
case DUK_TAG_UNDEFINED: {
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+ if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
+ DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
+ break;
+ } else {
+ goto emit_undefined;
+ }
+#else
goto emit_undefined;
+#endif
}
case DUK_TAG_NULL: {
DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
@@ -33509,7 +34309,8 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
duk_hobject *obj;
duk_tval *tv_val;
duk_bool_t emitted = 0;
- duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef, c_object;
+ duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
+ c_func, c_bufobj, c_object;
/* For objects JSON.stringify() only looks for own, enumerable
* properties which is nice for the fast path here.
@@ -33526,12 +34327,16 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
* execution time for input data with a lot of small objects!).
*/
- obj = DUK_TVAL_GET_OBJECT(tv);
- DUK_ASSERT(obj != NULL);
+ /* XXX: for real world code, could just ignore array inheritance
+ * and only look at array own properties.
+ */
/* We rely on a few object flag / class number relationships here,
* assert for them.
*/
+
+ obj = DUK_TVAL_GET_OBJECT(tv);
+ DUK_ASSERT(obj != NULL);
DUK_ASSERT_HOBJECT_VALID(obj);
/* Once recursion depth is increased, exit path must decrease
@@ -33546,7 +34351,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
}
for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
- if (js_ctx->visiting[i] == obj) {
+ if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
DUK_DD(DUK_DDPRINT("fast path loop detect"));
DUK_ERROR(js_ctx->thr, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT);
}
@@ -33566,6 +34371,9 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
* If an object is a Proxy we also can't avoid side effects
* so abandon.
*/
+ /* XXX: non-callable .toJSON() doesn't need to cause an abort
+ * but does at the moment, probably not worth fixing.
+ */
if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
@@ -33577,15 +34385,38 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
* should be in order of relevancy.
*/
+ /* XXX: move masks to js_ctx? they don't change during one
+ * fast path invocation.
+ */
DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
- c_all = DUK_HOBJECT_CMASK_ALL;
- c_array = DUK_HOBJECT_CMASK_ARRAY;
- c_unbox = DUK_HOBJECT_CMASK_NUMBER |
- DUK_HOBJECT_CMASK_STRING |
- DUK_HOBJECT_CMASK_BOOLEAN;
- c_undef = DUK_HOBJECT_CMASK_FUNCTION |
- DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
- c_object = c_all & ~(c_array | c_unbox | c_undef);
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+ if (js_ctx->flag_ext_custom_or_compatible) {
+ c_all = DUK_HOBJECT_CMASK_ALL;
+ c_array = DUK_HOBJECT_CMASK_ARRAY;
+ c_unbox = DUK_HOBJECT_CMASK_NUMBER |
+ DUK_HOBJECT_CMASK_STRING |
+ DUK_HOBJECT_CMASK_BOOLEAN |
+ DUK_HOBJECT_CMASK_POINTER;
+ c_func = DUK_HOBJECT_CMASK_FUNCTION;
+ c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
+ c_undef = 0;
+ c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
+ }
+ else
+#endif
+ {
+ c_all = DUK_HOBJECT_CMASK_ALL;
+ c_array = DUK_HOBJECT_CMASK_ARRAY;
+ c_unbox = DUK_HOBJECT_CMASK_NUMBER |
+ DUK_HOBJECT_CMASK_STRING |
+ DUK_HOBJECT_CMASK_BOOLEAN;
+ c_func = 0;
+ c_bufobj = 0;
+ c_undef = DUK_HOBJECT_CMASK_FUNCTION |
+ DUK_HOBJECT_CMASK_POINTER |
+ DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
+ c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
+ }
c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj);
if (c_bit & c_object) {
@@ -33626,8 +34457,16 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
- duk__enc_quote_string(js_ctx, k);
- DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
+ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
+
+ duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ duk__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__EMIT_1(js_ctx, DUK_ASC_COLON);
+ }
+
if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
@@ -33643,7 +34482,12 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
*/
if (emitted) {
+ DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
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 - 1);
+ }
}
DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
} else if (c_bit & c_array) {
@@ -33675,6 +34519,10 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
+ if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
+ duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
+ }
+
if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_val))) {
/* Gap in array; check for inherited property,
* bail out if one exists. This should be enough
@@ -33710,11 +34558,16 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
}
if (emitted) {
+ DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
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 - 1);
+ }
}
DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
} else if (c_bit & c_unbox) {
- /* These three boxed types are required to go through
+ /* Certain boxed types are required to go through
* automatic unboxing. Rely on internal value being
* sane (to avoid infinite recursion).
*/
@@ -33726,21 +34579,22 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
DUK_ASSERT(tv_internal != NULL);
DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
DUK_TVAL_IS_NUMBER(tv_internal) ||
- DUK_TVAL_IS_BOOLEAN(tv_internal));
+ DUK_TVAL_IS_BOOLEAN(tv_internal) ||
+ DUK_TVAL_IS_POINTER(tv_internal));
- /* XXX: for JX/JC, special handling for Pointer, and Buffer? */
tv = tv_internal;
+ DUK_ASSERT(js_ctx->recursion_depth > 0);
+ js_ctx->recursion_depth--; /* required to keep recursion depth correct */
goto restart_match;
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+ } else if (c_bit & c_func) {
+ DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
+ } else if (c_bit & c_bufobj) {
+ duk__enc_bufferobject(js_ctx, (duk_hbufferobject *) obj);
+#endif
} else {
DUK_ASSERT((c_bit & c_undef) != 0);
- /* Function objects are treated as "undefined" by JSON.
- *
- * The slow path replaces a buffer object automatically with
- * the binary data which then gets treated like "undefined".
- * Since we don't support buffers here now, treat as "undefined".
- */
-
/* Must decrease recursion depth before returning. */
DUK_ASSERT(js_ctx->recursion_depth > 0);
DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
@@ -33754,13 +34608,34 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du
break;
}
case DUK_TAG_BUFFER: {
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+ if (js_ctx->flag_ext_custom_or_compatible) {
+ duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
+ break;
+ } else {
+ goto emit_undefined;
+ }
+#else
goto emit_undefined;
+#endif
}
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));
+ break;
+ } else {
+ goto emit_undefined;
+ }
+#else
goto emit_undefined;
+#endif
}
case DUK_TAG_LIGHTFUNC: {
/* A lightfunc might also inherit a .toJSON() so just bail out. */
+ /* XXX: Could just lookup .toJSON() and continue in fast path,
+ * as it would almost never be defined.
+ */
DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
goto abort_fastpath;
}
@@ -33868,12 +34743,15 @@ void duk_bi_json_parse_helper(duk_context *ctx,
*/
js_ctx->flags = flags;
-#ifdef DUK_USE_JX
+#if defined(DUK_USE_JX)
js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
#endif
-#ifdef DUK_USE_JC
+#if defined(DUK_USE_JC)
js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
#endif
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+ js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
+#endif
h_text = duk_to_hstring(ctx, idx_value); /* coerce in-place */
DUK_ASSERT(h_text != NULL);
@@ -33882,9 +34760,9 @@ void duk_bi_json_parse_helper(duk_context *ctx,
* valid and points to the string NUL terminator (which is always
* guaranteed for duk_hstrings.
*/
- js_ctx->p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
+ js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
js_ctx->p = js_ctx->p_start;
- js_ctx->p_end = ((duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
+ js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
DUK_HSTRING_GET_BYTELEN(h_text);
DUK_ASSERT(*(js_ctx->p_end) == 0x00);
@@ -33969,7 +34847,6 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
#ifdef DUK_USE_EXPLICIT_NULL_INIT
js_ctx->h_replacer = NULL;
js_ctx->h_gap = NULL;
- js_ctx->h_indent = NULL;
#endif
js_ctx->idx_proplist = -1;
@@ -33986,6 +34863,9 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
#ifdef DUK_USE_JC
js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
#endif
+#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
+ js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
+#endif
/* The #ifdef clutter here handles the JX/JC enable/disable
* combinations properly.
@@ -34131,15 +35011,9 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
/* if gap is empty, behave as if not given at all */
if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) {
js_ctx->h_gap = NULL;
- } else {
- /* set 'indent' only if it will actually increase */
- js_ctx->h_indent = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
}
}
- DUK_ASSERT((js_ctx->h_gap == NULL && js_ctx->h_indent == NULL) ||
- (js_ctx->h_gap != NULL && js_ctx->h_indent != NULL));
-
/* [ ... buf loop (proplist) (gap) ] */
/*
@@ -34148,15 +35022,8 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
*/
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
- /* For now fast path is limited to plain JSON (no JX/JC). This would
- * be easy to fix but must go through value type handling in the fast
- * path.
- */
- if (flags == 0 &&
- js_ctx->h_replacer == NULL &&
- js_ctx->idx_proplist == -1 &&
- js_ctx->h_gap == NULL &&
- js_ctx->h_indent == NULL) {
+ if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
+ js_ctx->idx_proplist == -1) { /* proplist is very rare */
duk_int_t pcall_rc;
#ifdef DUK_USE_MARK_AND_SWEEP
duk_small_uint_t prev_mark_and_sweep_base_flags;
@@ -34206,7 +35073,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
* kept because we'll probably need at least as much as we've
* allocated so far.
*/
- DUK_DD(DUK_DDPRINT("fast path failed, serialize using slow path instead"));
+ DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
js_ctx->recursion_depth = 0;
}
@@ -34221,13 +35088,12 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING);
DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
- "proplist=%!T, gap=%!O, indent=%!O, holder=%!T",
+ "proplist=%!T, gap=%!O, holder=%!T",
(unsigned long) js_ctx->flags,
(duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
(duk_heaphdr *) js_ctx->h_replacer,
(duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
(duk_heaphdr *) js_ctx->h_gap,
- (duk_heaphdr *) js_ctx->h_indent,
(duk_tval *) duk_get_tval(ctx, -1)));
/* serialize the wrapper with empty string key */
@@ -34241,28 +35107,20 @@ void duk_bi_json_stringify_helper(duk_context *ctx,
undef = duk__enc_value1(js_ctx, idx_holder); /* [ ... holder key ] -> [ ... holder key val ] */
DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
- "proplist=%!T, gap=%!O, indent=%!O, holder=%!T",
+ "proplist=%!T, gap=%!O, holder=%!T",
(unsigned long) js_ctx->flags,
(duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
(duk_heaphdr *) js_ctx->h_replacer,
(duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
(duk_heaphdr *) js_ctx->h_gap,
- (duk_heaphdr *) js_ctx->h_indent,
(duk_tval *) duk_get_tval(ctx, -3)));
if (undef) {
- /*
- * Result is undefined
- */
-
+ /* Result is undefined. */
duk_push_undefined(ctx);
} else {
- /*
- * Finish and convert buffer to result string
- */
-
+ /* Finish and convert buffer to result string. */
duk__enc_value2(js_ctx); /* [ ... key val ] -> [ ... ] */
-
DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
}
@@ -34560,18 +35418,18 @@ DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
DUK_ASSERT(buf != NULL);
p = buf;
- DUK_MEMCPY((void *) p, (void *) date_buf, date_len);
+ DUK_MEMCPY((void *) p, (const void *) date_buf, (size_t) date_len);
p += date_len;
*p++ = (duk_uint8_t) DUK_ASC_SPACE;
q = duk__log_level_strings + (entry_lev * 3);
- DUK_MEMCPY((void *) p, (void *) q, (duk_size_t) 3);
+ DUK_MEMCPY((void *) p, (const void *) q, (size_t) 3);
p += 3;
*p++ = (duk_uint8_t) DUK_ASC_SPACE;
arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, -2, &arg_len);
- DUK_MEMCPY((void *) p, (const void *) arg_str, arg_len);
+ DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
p += arg_len;
*p++ = (duk_uint8_t) DUK_ASC_COLON;
@@ -34581,7 +35439,7 @@ DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &arg_len);
DUK_ASSERT(arg_str != NULL);
- DUK_MEMCPY((void *) p, (const void *) arg_str, arg_len);
+ DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
p += arg_len;
}
DUK_ASSERT(buf + tot_len == p);
@@ -35692,6 +36550,12 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
}
}
+ /* XXX: missing trap result validation for non-configurable target keys
+ * (must be present), for non-extensible target all target keys must be
+ * present and no extra keys can be present.
+ * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
+ */
+
/* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
* should be filtered so that only enumerable keys remain. Enumerability
* should be checked with [[GetOwnProperty]] on the original object
@@ -35725,31 +36589,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
}
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx) {
- duk_hthread *thr = (duk_hthread *) ctx;
-
duk_push_this(ctx);
- duk_push_string(ctx, "[object ");
-
- if (duk_is_undefined(ctx, -2)) {
- duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_UNDEFINED);
- } else if (duk_is_null(ctx, -2)) {
- duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_NULL);
- } else {
- duk_hobject *h_this;
- duk_hstring *h_classname;
-
- duk_to_object(ctx, -2);
- h_this = duk_get_hobject(ctx, -2);
- DUK_ASSERT(h_this != NULL);
-
- h_classname = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_this);
- DUK_ASSERT(h_classname != NULL);
-
- duk_push_hstring(ctx, h_classname);
- }
-
- duk_push_string(ctx, "]");
- duk_concat(ctx, 3);
+ duk_to_object_class_string_top(ctx);
return 1;
}
@@ -36534,7 +37375,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx)
if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
DUK_ASSERT(q_blen > 0); /* no issues with memcmp() zero size, even if broken */
- if (DUK_MEMCMP(p, q_start, (duk_size_t) q_blen) == 0) {
+ if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
duk_push_int(ctx, cpos);
return 1;
}
@@ -36744,7 +37585,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) {
while (p <= p_end) {
DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
- if (DUK_MEMCMP((void *) p, (void *) q_start, (size_t) q_blen) == 0) {
+ if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
duk_dup(ctx, 0);
h_match = duk_get_hstring(ctx, -1);
DUK_ASSERT(h_match != NULL);
@@ -37129,7 +37970,7 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx) {
while (p <= p_end) {
DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
- if (DUK_MEMCMP((void *) p, (void *) q_start, (duk_size_t) q_blen) == 0) {
+ if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
/* never an empty match, so step 13.c.iii can't be triggered */
goto found;
}
@@ -37440,9 +38281,9 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx)
prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
/* Zero size compare not an issue with DUK_MEMCMP. */
- rc = (duk_small_int_t) DUK_MEMCMP((const char *) DUK_HSTRING_GET_DATA(h1),
- (const char *) DUK_HSTRING_GET_DATA(h2),
- prefix_len);
+ rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
+ (const void *) DUK_HSTRING_GET_DATA(h2),
+ (size_t) prefix_len);
if (rc < 0) {
ret = -1;
@@ -37639,6 +38480,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_context *ctx) {
/* lj value1: value */
DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
+ DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
thr->heap->lj.iserror = is_error;
@@ -37755,6 +38597,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_context *ctx) {
/* lj value1: value */
DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
+ DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
thr->heap->lj.iserror = is_error;
@@ -37792,7 +38635,7 @@ DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx) {
#ifdef DUK_USE_DEBUG
-DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, duk_uint8_t *buffer, duk_size_t length) {
+DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
duk_size_t avail;
duk_size_t copylen;
@@ -37808,11 +38651,11 @@ DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, duk_uint8_t *buffer, duk
}
DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
- duk_fb_put_bytes(fb, &x, 1);
+ duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
}
DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
- duk_fb_put_bytes(fb, (duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
+ duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
}
DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
@@ -39169,24 +40012,46 @@ typedef union {
* Detach handling
*/
-#define DUK__SET_CONN_BROKEN(thr) do { \
+#define DUK__SET_CONN_BROKEN(thr,reason) do { \
/* For now shared handler is fine. */ \
- duk_debug_do_detach((thr)->heap); \
+ duk__debug_do_detach1((thr)->heap, (reason)); \
} while (0)
-DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
- /* Can be called muliple times with no harm. */
+DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
+ /* Can be called multiple times with no harm. Mark the transport
+ * bad (dbg_read_cb == NULL) and clear state except for the detached
+ * callback and the udata field. The detached callback is delayed
+ * to the message loop so that it can be called between messages;
+ * this avoids corner cases related to immediate debugger reattach
+ * inside the detached callback.
+ */
+
+ if (heap->dbg_detaching) {
+ return;
+ }
+
+ DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
+
+ heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
+
+ if (heap->dbg_write_cb != NULL) {
+ duk_hthread *thr;
+
+ thr = heap->heap_thread;
+ DUK_ASSERT(thr != NULL);
+
+ duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
+ duk_debug_write_int(thr, reason);
+ duk_debug_write_eom(thr);
+ }
heap->dbg_read_cb = NULL;
heap->dbg_write_cb = NULL;
heap->dbg_peek_cb = NULL;
heap->dbg_read_flush_cb = NULL;
heap->dbg_write_flush_cb = NULL;
- if (heap->dbg_detached_cb) {
- heap->dbg_detached_cb(heap->dbg_udata);
- }
- heap->dbg_detached_cb = NULL;
- heap->dbg_udata = NULL;
+ /* heap->dbg_detached_cb: keep */
+ /* heap->dbg_udata: keep */
heap->dbg_processing = 0;
heap->dbg_paused = 0;
heap->dbg_state_dirty = 0;
@@ -39195,6 +40060,7 @@ DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
heap->dbg_step_thread = NULL;
heap->dbg_step_csindex = 0;
heap->dbg_step_startline = 0;
+ heap->dbg_have_next_byte = 0;
/* Ensure there are no stale active breakpoint pointers.
* Breakpoint list is currently kept - we could empty it
@@ -39206,6 +40072,34 @@ DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
}
+DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
+ duk_debug_detached_function detached_cb;
+ void *detached_udata;
+
+ /* Safe to call multiple times. */
+
+ detached_cb = heap->dbg_detached_cb;
+ detached_udata = heap->dbg_udata;
+ heap->dbg_detached_cb = NULL;
+ heap->dbg_udata = NULL;
+
+ if (detached_cb) {
+ /* Careful here: state must be wiped before the call
+ * so that we can cleanly handle a re-attach from
+ * inside the callback.
+ */
+ DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
+ detached_cb(detached_udata);
+ }
+
+ heap->dbg_detaching = 0;
+}
+
+DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
+ duk__debug_do_detach1(heap, 0);
+ duk__debug_do_detach2(heap);
+}
+
/*
* Debug connection peek and flush primitives
*/
@@ -39295,6 +40189,21 @@ DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
* Debug connection read primitives
*/
+/* Peek ahead in the stream one byte. */
+DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
+ /* It is important not to call this if the last byte read was an EOM.
+ * Reading ahead in this scenario would cause unnecessary blocking if
+ * another message is not available.
+ */
+
+ duk_uint8_t x;
+
+ x = duk_debug_read_byte(thr);
+ thr->heap->dbg_have_next_byte = 1;
+ thr->heap->dbg_next_byte = x;
+ return x;
+}
+
/* Read fully. */
DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
duk_heap *heap;
@@ -39311,7 +40220,12 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_
goto fail;
}
+ /* NOTE: length may be zero */
p = data;
+ if (length >= 1 && heap->dbg_have_next_byte) {
+ heap->dbg_have_next_byte = 0;
+ *p++ = heap->dbg_next_byte;
+ }
for (;;) {
left = (duk_size_t) ((data + length) - p);
if (left == 0) {
@@ -39324,8 +40238,9 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_
#endif
got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
if (got == 0 || got > left) {
+ heap->dbg_write_cb = NULL; /* squelch further writes */
DUK_D(DUK_DPRINT("connection error during read, return zero data"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
goto fail;
}
p += got;
@@ -39337,28 +40252,10 @@ DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_
}
DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
- duk_heap *heap;
- duk_size_t got;
duk_uint8_t x;
- DUK_ASSERT(thr != NULL);
- heap = thr->heap;
- DUK_ASSERT(heap != NULL);
-
- if (heap->dbg_read_cb == NULL) {
- DUK_D(DUK_DPRINT("attempt to read 1 bytes in detached state, return zero data"));
- return 0;
- }
-
x = 0; /* just in case callback is broken and won't write 'x' */
- DUK_ASSERT(heap->dbg_read_cb != NULL);
- got = heap->dbg_read_cb(heap->dbg_udata, (char *) (&x), 1);
- if (got != 1) {
- DUK_D(DUK_DPRINT("connection error during read, return zero data"));
- DUK__SET_CONN_BROKEN(thr);
- return 0;
- }
-
+ duk_debug_read_bytes(thr, &x, 1);
return x;
}
@@ -39405,7 +40302,7 @@ DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
}
DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
return 0;
}
@@ -39450,7 +40347,7 @@ DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING); /* always push some string */
return duk_require_hstring(ctx, -1);
}
@@ -39466,9 +40363,9 @@ DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_
return duk_require_hbuffer(ctx, -1);
}
-DUK_LOCAL const void *duk__debug_read_pointer_raw(duk_hthread *thr) {
+DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
duk_small_uint_t x;
- volatile duk__ptr_union pu;
+ duk__ptr_union pu;
DUK_ASSERT(thr != NULL);
@@ -39480,12 +40377,12 @@ DUK_LOCAL const void *duk__debug_read_pointer_raw(duk_hthread *thr) {
#if defined(DUK_USE_INTEGER_LE)
duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
#endif
- return (const void *) pu.p;
+ return (void *) pu.p;
fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
- DUK__SET_CONN_BROKEN(thr);
- return (const void *) NULL;
+ DUK__SET_CONN_BROKEN(thr, 1);
+ return (void *) NULL;
}
DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
@@ -39568,9 +40465,9 @@ DUK_INTERNAL void duk_debug_read_tval(duk_hthread *thr) {
DUK_D(DUK_DPRINT("reading object values unimplemented"));
goto fail;
case 0x1c: {
- const void *ptr;
+ void *ptr;
ptr = duk__debug_read_pointer_raw(thr);
- duk_push_pointer(thr, (void *) ptr);
+ duk_push_pointer(thr, ptr);
break;
}
case 0x1d:
@@ -39592,7 +40489,7 @@ DUK_INTERNAL void duk_debug_read_tval(duk_hthread *thr) {
fail:
DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
}
/*
@@ -39636,8 +40533,9 @@ DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *dat
#endif
got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
if (got == 0 || got > left) {
+ heap->dbg_write_cb = NULL; /* squelch further writes */
DUK_D(DUK_DPRINT("connection error during write"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
return;
}
p += got;
@@ -39661,7 +40559,7 @@ DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
got = heap->dbg_write_cb(heap->dbg_udata, (const char *) (&x), 1);
if (got != 1) {
DUK_D(DUK_DPRINT("connection error during write"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
}
}
@@ -39775,9 +40673,9 @@ DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
(h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
}
-DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, const void *ptr, duk_uint8_t ibyte) {
+DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
duk_uint8_t buf[2];
- volatile duk__ptr_union pu;
+ duk__ptr_union pu;
DUK_ASSERT(thr != NULL);
DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
@@ -39793,19 +40691,19 @@ DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, const void *ptr, d
duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
}
-DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, const void *ptr) {
+DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
duk__debug_write_pointer_raw(thr, ptr, 0x1c);
}
#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
- duk__debug_write_pointer_raw(thr, (const void *) h, 0x1e);
+ duk__debug_write_pointer_raw(thr, (void *) h, 0x1e);
}
#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
duk_uint8_t buf[3];
- volatile duk__ptr_union pu;
+ duk__ptr_union pu;
DUK_ASSERT(thr != NULL);
DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
@@ -39847,7 +40745,7 @@ DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
duk_debug_write_byte(thr, DUK_TVAL_GET_BOOLEAN(tv) ? 0x18 : 0x19);
break;
case DUK_TAG_POINTER:
- duk_debug_write_pointer(thr, (const void *) DUK_TVAL_GET_POINTER(tv));
+ duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
break;
case DUK_TAG_LIGHTFUNC:
DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
@@ -40113,7 +41011,7 @@ DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
return 0;
fail:
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 1);
return 1; /* Pretend like we got EOM */
}
@@ -40128,6 +41026,10 @@ DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
/*
* Process incoming debug requests
+ *
+ * Individual request handlers can push temporaries on the value stack and
+ * rely on duk__debug_process_message() to restore the value stack top
+ * automatically.
*/
DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
@@ -40217,7 +41119,6 @@ DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
}
DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
- duk_context *ctx = (duk_context *) thr;
duk_hstring *filename;
duk_uint32_t linenumber;
duk_small_int_t idx;
@@ -40235,7 +41136,6 @@ DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
} else {
duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
}
- duk_pop(ctx);
}
DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
@@ -40257,16 +41157,27 @@ DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
duk_context *ctx = (duk_context *) thr;
duk_hstring *str;
duk_bool_t rc;
+ duk_int32_t level;
DUK_UNREF(heap);
DUK_D(DUK_DPRINT("debug command GetVar"));
str = duk_debug_read_hstring(thr); /* push to stack */
DUK_ASSERT(str != NULL);
+ if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+ level = duk_debug_read_int(thr); /* optional callstack level */
+ if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+ DUK_D(DUK_DPRINT("invalid callstack level for GetVar"));
+ duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+ return;
+ }
+ } else {
+ level = -1;
+ }
if (thr->callstack_top > 0) {
rc = duk_js_getvar_activation(thr,
- thr->callstack + thr->callstack_top - 1,
+ thr->callstack + thr->callstack_top + level,
str,
0);
} else {
@@ -40283,12 +41194,10 @@ DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
duk_debug_write_int(thr, 1);
DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
- duk_pop_2(ctx);
} else {
duk_debug_write_int(thr, 0);
duk_debug_write_unused(thr);
}
- duk_pop(ctx);
duk_debug_write_eom(thr);
}
@@ -40296,6 +41205,7 @@ DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
duk_context *ctx = (duk_context *) thr;
duk_hstring *str;
duk_tval *tv;
+ duk_int32_t level;
DUK_UNREF(heap);
DUK_D(DUK_DPRINT("debug command PutVar"));
@@ -40305,17 +41215,26 @@ DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
duk_debug_read_tval(thr); /* push to stack */
tv = duk_get_tval(ctx, -1);
DUK_ASSERT(tv != NULL);
+ if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+ level = duk_debug_read_int(thr); /* optional callstack level */
+ if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+ DUK_D(DUK_DPRINT("invalid callstack level for PutVar"));
+ duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+ return;
+ }
+ } else {
+ level = -1;
+ }
if (thr->callstack_top > 0) {
duk_js_putvar_activation(thr,
- thr->callstack + thr->callstack_top - 1,
+ thr->callstack + thr->callstack_top + level,
str,
tv,
0);
} else {
DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore putvar"));
}
- duk_pop_2(ctx);
/* XXX: Current putvar implementation doesn't have a success flag,
* add one and send to debug client?
@@ -40376,15 +41295,28 @@ DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap
DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
duk_context *ctx = (duk_context *) thr;
duk_activation *curr_act;
+ duk_int32_t level;
duk_hstring *varname;
DUK_UNREF(heap);
- duk_debug_write_reply(thr);
- if (thr->callstack_top == 0) {
- goto callstack_empty;
+ if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+ level = duk_debug_read_int(thr); /* optional callstack level */
+ if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+ DUK_D(DUK_DPRINT("invalid callstack level for GetLocals"));
+ duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+ return;
+ }
+ duk_debug_write_reply(thr);
+ } else {
+ duk_debug_write_reply(thr);
+ if (thr->callstack_top == 0) {
+ goto callstack_empty;
+ }
+ level = -1;
}
- curr_act = thr->callstack + thr->callstack_top - 1;
+
+ curr_act = thr->callstack + thr->callstack_top + level;
/* XXX: several nice-to-have improvements here:
* - Use direct reads avoiding value stack operations
@@ -40406,11 +41338,9 @@ DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
duk_pop_3(ctx); /* -> [ ... func varmap enum ] */
}
- duk_pop(ctx);
} else {
DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
}
- duk_pop_2(ctx);
callstack_empty:
duk_debug_write_eom(thr);
@@ -40418,51 +41348,62 @@ DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
duk_context *ctx = (duk_context *) thr;
-
duk_small_uint_t call_flags;
duk_int_t call_ret;
duk_small_int_t eval_err;
-#if defined(DUK_USE_ASSERTIONS)
- duk_idx_t entry_top;
-#endif
+ duk_int32_t level;
DUK_UNREF(heap);
DUK_D(DUK_DPRINT("debug command Eval"));
- /* The eval code must be executed within the current (topmost)
- * activation. For now, use global object eval() function, with
- * the eval considered a 'direct call to eval'.
+ /* The eval code is executed within the lexical environment of a specified
+ * activation. For now, use global object eval() function, with the eval
+ * considered a 'direct call to eval'.
+ *
+ * Callstack level for debug commands only affects scope -- the callstack
+ * as seen by, e.g. Duktape.act() will be the same regardless.
*/
-#if defined(DUK_USE_ASSERTIONS)
- entry_top = duk_get_top(ctx);
-#endif
-
- duk_push_c_function(ctx, duk_bi_global_object_eval, 1 /*nargs*/);
+ /* nargs == 2 so we can pass a callstack level to eval(). */
+ duk_push_c_function(ctx, duk_bi_global_object_eval, 2 /*nargs*/);
duk_push_undefined(ctx); /* 'this' binding shouldn't matter here */
+
(void) duk_debug_read_hstring(thr);
+ if (duk_debug_peek_byte(thr) != DUK_DBG_MARKER_EOM) {
+ level = duk_debug_read_int(thr); /* optional callstack level */
+ if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
+ DUK_D(DUK_DPRINT("invalid callstack level for Eval"));
+ duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
+ return;
+ }
+ }
+ else {
+ level = -1;
+ }
+ DUK_ASSERT(level < 0 && -level <= (duk_int32_t) thr->callstack_top);
+ duk_push_int(ctx, level - 1); /* compensate for eval() call */
- /* [ ... eval "eval" eval_input ] */
+ /* [ ... eval "eval" eval_input level ] */
call_flags = DUK_CALL_FLAG_PROTECTED;
- if (thr->callstack_top >= 1) {
+ if (thr->callstack_top >= (duk_size_t) -level) {
duk_activation *act;
duk_hobject *fun;
- act = thr->callstack + thr->callstack_top - 1;
+ act = thr->callstack + thr->callstack_top + level;
fun = DUK_ACT_GET_FUNC(act);
if (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(fun)) {
/* Direct eval requires that there's a current
* activation and it is an Ecmascript function.
* When Eval is executed from e.g. cooperate API
- * call we'll need to an indirect eval instead.
+ * call we'll need to do an indirect eval instead.
*/
call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
}
}
- call_ret = duk_handle_call(thr, 1 /*num_stack_args*/, call_flags);
+ call_ret = duk_handle_call(thr, 2 /*num_stack_args*/, call_flags);
if (call_ret == DUK_EXEC_SUCCESS) {
eval_err = 0;
@@ -40483,9 +41424,6 @@ DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
duk_debug_write_eom(thr);
- duk_pop(ctx);
-
- DUK_ASSERT(duk_get_top(ctx) == entry_top);
}
DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
@@ -40496,7 +41434,7 @@ DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
duk_debug_write_eom(thr);
DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
- DUK__SET_CONN_BROKEN(thr);
+ DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
}
#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
@@ -40716,17 +41654,24 @@ DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap)
duk_debug_write_eom(thr);
}
+/* Process one debug message. Automatically restore value stack top to its
+ * entry value, so that individual message handlers don't need exact value
+ * stack handling which is convenient.
+ */
DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
duk_context *ctx = (duk_context *) thr;
duk_heap *heap;
duk_uint8_t x;
duk_int32_t cmd;
+ duk_idx_t entry_top;
DUK_ASSERT(thr != NULL);
heap = thr->heap;
DUK_ASSERT(heap != NULL);
DUK_UNREF(ctx);
+ entry_top = duk_get_top(ctx);
+
x = duk_debug_read_byte(thr);
switch (x) {
case DUK_DBG_MARKER_REQUEST: {
@@ -40787,6 +41732,10 @@ DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
break;
}
case DUK_DBG_CMD_DETACH: {
+ /* The actual detached_cb call is postponed to message loop so
+ * we don't need any special precautions here (just skip to EOM
+ * on the already closed connection).
+ */
duk__debug_handle_detach(thr, heap);
break;
}
@@ -40825,11 +41774,15 @@ DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
}
} /* switch initial byte */
+ DUK_ASSERT(duk_get_top(ctx) >= entry_top);
+ duk_set_top(ctx, entry_top);
duk__debug_skip_to_eom(thr);
return;
fail:
- DUK__SET_CONN_BROKEN(thr);
+ DUK_ASSERT(duk_get_top(ctx) >= entry_top);
+ duk_set_top(ctx, entry_top);
+ DUK__SET_CONN_BROKEN(thr, 1);
return;
}
@@ -40939,6 +41892,17 @@ DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t
}
duk__debug_process_message(thr);
+
+ if (thr->heap->dbg_read_cb == NULL) {
+ /* Became detached during message handling (perhaps because
+ * of an error or by an explicit Detach). Call detached
+ * callback here, between messages, to avoid confusing the
+ * broken connection and a possible replacement (which may
+ * be provided by an instant reattach inside the detached
+ * callback).
+ */
+ duk__debug_do_detach2(thr->heap);
+ }
if (thr->heap->dbg_state_dirty) {
/* Executed something that may have affected status,
* resend.
@@ -41025,8 +41989,8 @@ DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_
move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
if (move_size > 0) {
DUK_MEMMOVE((void *) b,
- (void *) (b + 1),
- move_size);
+ (const void *) (b + 1),
+ (size_t) move_size);
}
heap->dbg_breakpoint_count--;
heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
@@ -41201,10 +42165,10 @@ DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_c
#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
/*
- * Add tracedata to an error on the stack top.
+ * Add ._Tracedata to an error on the stack top.
*/
-#ifdef DUK_USE_TRACEBACKS
+#if defined(DUK_USE_TRACEBACKS)
DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
duk_context *ctx = (duk_context *) thr;
duk_small_uint_t depth;
@@ -41232,8 +42196,8 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
duk_push_array(ctx); /* XXX: specify array size, as we know it */
arr_idx = 0;
- /* compiler SyntaxErrors (and other errors) come first; blame the source
- * code file/line primarily.
+ /* Compiler SyntaxErrors (and other errors) come first, and are
+ * blamed by default (not flagged "noblame").
*/
if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
duk_push_hstring(ctx, thr->compile_ctx->h_filename);
@@ -41245,7 +42209,7 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
arr_idx++;
}
- /* filename/line from C macros (__FILE__, __LINE__) are added as an
+ /* Filename/line from C macros (__FILE__, __LINE__) are added as an
* entry with a special format: (string, number). The number contains
* the line and flags.
*/
@@ -41258,7 +42222,9 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
/* XXX: using duk_put_prop_index() would cause obscure error cases when Array.prototype
* has write-protected array index named properties. This was seen as DoubleErrors
* in e.g. some test262 test cases. Using duk_xdef_prop_index() is better but heavier.
- * The best fix is to fill in the tracedata directly into the array part.
+ * The best fix is to fill in the tracedata directly into the array part. There are
+ * no side effect concerns if the array part is allocated directly and only INCREFs
+ * happen after that.
*/
/* [ ... error arr ] */
@@ -41329,34 +42295,22 @@ DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack,
}
#endif /* DUK_USE_TRACEBACKS */
-#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
-DUK_LOCAL void duk__err_augment_builtin_throw(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_int_t noblame_fileline, duk_hobject *obj) {
- duk_context *ctx = (duk_context *) thr;
-#ifdef DUK_USE_ASSERTIONS
+/*
+ * Add .fileName and .lineNumber to an error on the stack top.
+ */
+
+#if !defined(DUK_USE_TRACEBACKS)
+DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
+ duk_context *ctx;
+#if defined(DUK_USE_ASSERTIONS)
duk_int_t entry_top;
#endif
-#ifdef DUK_USE_ASSERTIONS
+ ctx = (duk_context *) thr;
+#if defined(DUK_USE_ASSERTIONS)
entry_top = duk_get_top(ctx);
#endif
- DUK_ASSERT(obj != NULL);
- DUK_UNREF(obj); /* unreferenced w/o tracebacks */
- DUK_UNREF(ctx); /* unreferenced w/ tracebacks */
-
-#ifdef 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))) {
- 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, noblame_fileline);
- }
-#else
/*
* If tracebacks are disabled, 'fileName' and 'lineNumber' are added
* as plain own properties. Since Error.prototype has accessors of
@@ -41366,33 +42320,49 @@ DUK_LOCAL void duk__err_augment_builtin_throw(duk_hthread *thr, duk_hthread *thr
*/
if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
- /* Compiler SyntaxError (or other error) gets the primary blame. */
- duk_push_hstring(ctx, thr->compile_ctx->h_filename);
- duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+ /* Compiler SyntaxError (or other error) gets the primary blame.
+ * Currently no flag to prevent blaming.
+ */
duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
- duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+ duk_push_hstring(ctx, thr->compile_ctx->h_filename);
} else if (c_filename && !noblame_fileline) {
- /* XXX: file/line is disabled in minimal builds, so disable this too
- * when appropriate.
+ /* C call site gets blamed next, unless flagged not to do so.
+ * XXX: file/line is disabled in minimal builds, so disable this
+ * too when appropriate.
*/
- duk_push_string(ctx, c_filename);
- duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
duk_push_int(ctx, c_line);
- duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
- } else if (thr_callstack->callstack_top > 0) {
- duk_activation *act;
- duk_hobject *func;
+ duk_push_string(ctx, c_filename);
+ } else {
+ /* Finally, blame the innermost callstack entry which has a
+ * .fileName property.
+ */
+ duk_small_uint_t depth;
+ duk_int_t i, i_min;
+ duk_uint32_t ecma_line;
- act = thr_callstack->callstack + thr_callstack->callstack_top - 1;
- DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
- func = DUK_ACT_GET_FUNC(act);
- if (func) {
+ depth = DUK_USE_TRACEBACK_DEPTH;
+ i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
+ DUK_ASSERT(i_min >= 0);
+
+ DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
+ for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
+ duk_activation *act;
+ duk_hobject *func;
duk_uint32_t pc;
- /* PC points to next instruction, find offending PC. Note that
+ act = thr_callstack->callstack + i;
+ DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
+
+ func = DUK_ACT_GET_FUNC(act);
+ if (func == NULL) {
+ /* Lightfunc, not blamed now. */
+ continue;
+ }
+
+ /* PC points to next instruction, find offending PC,
* PC == 0 for native code.
*/
- pc = duk_hthread_get_act_prev_pc(thr, act);
+ pc = duk_hthread_get_act_prev_pc(thr, act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
act = NULL; /* invalidated by pushes, so get out of the way */
@@ -41402,31 +42372,126 @@ DUK_LOCAL void duk__err_augment_builtin_throw(duk_hthread *thr, duk_hthread *thr
/* [ ... error func ] */
duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
- duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+ if (!duk_is_string(ctx, -1)) {
+ duk_pop_2(ctx);
+ continue;
+ }
+
+ /* [ ... error func fileName ] */
+ ecma_line = 0;
#if defined(DUK_USE_PC2LINE)
if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
- duk_uint32_t ecma_line;
-#if 0
- duk_push_u32(ctx, pc);
- duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_PC, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAGS_NO_OVERWRITE);
-#endif
- ecma_line = duk_hobject_pc2line_query(ctx, -1, (duk_uint_fast32_t) pc);
- if (ecma_line > 0) {
- duk_push_u32(ctx, (duk_uint32_t) ecma_line); /* -> [ ... error func line ] */
- duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
- }
+ ecma_line = duk_hobject_pc2line_query(ctx, -2, (duk_uint_fast32_t) pc);
} else {
/* Native function, no relevant lineNumber. */
}
#endif /* DUK_USE_PC2LINE */
+ duk_push_u32(ctx, ecma_line);
- duk_pop(ctx);
+ /* [ ... error func fileName lineNumber ] */
+
+ duk_replace(ctx, -3);
+
+ /* [ ... error lineNumber fileName ] */
+ goto define_props;
}
+
+ /* No activation matches, use undefined for both .fileName and
+ * .lineNumber (matches what we do with a _Tracedata based
+ * no-match lookup.
+ */
+ duk_push_undefined(ctx);
+ duk_push_undefined(ctx);
}
-#endif /* DUK_USE_TRACEBACKS */
-#ifdef DUK_USE_ASSERTIONS
+ define_props:
+ /* [ ... error lineNumber fileName ] */
+#if defined(DUK_USE_ASSERTIONS)
+ DUK_ASSERT(duk_get_top(ctx) == entry_top + 2);
+#endif
+ duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+ duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
+}
+#endif /* !DUK_USE_TRACEBACKS */
+
+/*
+ * Add line number to a compiler error.
+ */
+
+DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
+ duk_context *ctx;
+
+ /* Append a "(line NNN)" to the "message" property of any error
+ * thrown during compilation. Usually compilation errors are
+ * SyntaxErrors but they can also be out-of-memory errors and
+ * the like.
+ */
+
+ /* [ ... error ] */
+
+ ctx = (duk_context *) thr;
+ DUK_ASSERT(duk_is_object(ctx, -1));
+
+ if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
+ return;
+ }
+
+ DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
+ (duk_tval *) duk_get_tval(ctx, -1)));
+
+ if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_MESSAGE)) {
+ duk_push_sprintf(ctx, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
+ duk_concat(ctx, 2);
+ duk_put_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
+ } else {
+ duk_pop(ctx);
+ }
+
+ DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
+ (duk_tval *) duk_get_tval(ctx, -1)));
+}
+
+/*
+ * Augment an error being created using Duktape specific properties
+ * like _Tracedata or .fileName/.lineNumber.
+ */
+
+#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
+DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_int_t noblame_fileline, duk_hobject *obj) {
+ duk_context *ctx = (duk_context *) thr;
+#if defined(DUK_USE_ASSERTIONS)
+ duk_int_t entry_top;
+#endif
+
+#if defined(DUK_USE_ASSERTIONS)
+ entry_top = duk_get_top(ctx);
+#endif
+ DUK_ASSERT(obj != NULL);
+
+ DUK_UNREF(obj); /* unreferenced w/o tracebacks */
+ DUK_UNREF(ctx); /* unreferenced w/o asserts */
+
+ duk__add_compiler_error_line(thr);
+
+#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))) {
+ 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, noblame_fileline);
+ }
+#else
+ /* Without tracebacks the concrete .fileName and .lineNumber need
+ * to be added directly.
+ */
+ duk__add_fileline(thr, thr_callstack, c_filename, c_line, noblame_fileline);
+#endif
+
+#if defined(DUK_USE_ASSERTIONS)
DUK_ASSERT(duk_get_top(ctx) == entry_top);
#endif
}
@@ -41487,7 +42552,7 @@ DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *th
}
if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
- duk__err_augment_builtin_throw(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
+ duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
} else {
DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
}
@@ -41554,7 +42619,8 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
* catcher. Protected calls or finally blocks aren't considered catching.
*/
-#if defined(DUK_USE_DEBUGGER_SUPPORT)
+#if defined(DUK_USE_DEBUGGER_SUPPORT) && \
+ (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT))
DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
/*
* XXX: As noted above, a protected API call won't be counted as a
@@ -41578,7 +42644,7 @@ DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
}
return 0;
}
-#endif /* DUK_USE_DEBUGGER_SUPPORT */
+#endif /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */
/*
* Get prototype object for an integer error code.
@@ -42231,7 +43297,7 @@ DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
}
}
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_LOCAL void duk__free_refzero_list(duk_heap *heap) {
duk_heaphdr *curr;
duk_heaphdr *next;
@@ -42247,7 +43313,7 @@ DUK_LOCAL void duk__free_refzero_list(duk_heap *heap) {
}
#endif
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
DUK_LOCAL void duk__free_markandsweep_finalize_list(duk_heap *heap) {
duk_heaphdr *curr;
duk_heaphdr *next;
@@ -42271,16 +43337,17 @@ DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
duk_hthread *thr;
duk_heaphdr *curr;
-#ifdef DUK_USE_DEBUG
- duk_size_t count_obj = 0;
-#endif
+ duk_uint_t round_no;
+ duk_size_t count_all;
+ duk_size_t count_finalized;
+ duk_size_t curr_limit;
DUK_ASSERT(heap != NULL);
DUK_ASSERT(heap->heap_thread != NULL);
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
#endif
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep not running -> must be empty */
#endif
@@ -42290,30 +43357,74 @@ DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
thr = heap->heap_thread;
DUK_ASSERT(thr != NULL);
- curr = heap->heap_allocated;
- while (curr) {
- if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
- /* Only objects in heap_allocated may have finalizers. Check that
- * the object itself has a _Finalizer property so that we don't
- * execute finalizers for e.g. Proxy objects.
- */
- DUK_ASSERT(thr != NULL);
- DUK_ASSERT(curr != NULL);
+ /* Prevent mark-and-sweep for the pending finalizers, also prevents
+ * refzero handling from moving objects away from the heap_allocated
+ * list.
+ */
+ DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
+ DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
- if (duk_hobject_hasprop_raw(thr, (duk_hobject *) curr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
- duk_hobject_run_finalizer(thr, (duk_hobject *) curr);
+ curr_limit = 0; /* suppress warning, not used */
+ for (round_no = 0; ; round_no++) {
+ curr = heap->heap_allocated;
+ count_all = 0;
+ count_finalized = 0;
+ while (curr) {
+ count_all++;
+ if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
+ /* Only objects in heap_allocated may have finalizers. Check that
+ * the object itself has a _Finalizer property (own or inherited)
+ * so that we don't execute finalizers for e.g. Proxy objects.
+ */
+ DUK_ASSERT(thr != NULL);
+ DUK_ASSERT(curr != NULL);
+
+ if (duk_hobject_hasprop_raw(thr, (duk_hobject *) curr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
+ if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
+ DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
+ duk_hobject_run_finalizer(thr, (duk_hobject *) curr);
+ count_finalized++;
+ }
+ }
}
-#ifdef DUK_USE_DEBUG
- count_obj++;
-#endif
+ curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
+ }
+
+ /* Each round of finalizer execution may spawn new finalizable objects
+ * which is normal behavior for some applications. Allow multiple
+ * rounds of finalization, but use a shrinking limit based on the
+ * first round to detect the case where a runaway finalizer creates
+ * an unbounded amount of new finalizable objects. Finalizer rescue
+ * is not supported: the semantics are unclear because most of the
+ * objects being finalized here are already reachable. The finalizer
+ * is given a boolean to indicate that rescue is not possible.
+ *
+ * See discussion in: https://github.com/svaarala/duktape/pull/473
+ */
+
+ if (round_no == 0) {
+ /* Cannot wrap: each object is at least 8 bytes so count is
+ * at most 1/8 of that.
+ */
+ curr_limit = count_all * 2;
+ } else {
+ curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
+ }
+ DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
+ (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
+
+ if (count_finalized == 0) {
+ DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
+ break;
+ }
+ if (count_finalized >= curr_limit) {
+ DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
+ break;
}
- curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
}
- /* Note: count includes all objects, not only those with an actual finalizer. */
-#ifdef DUK_USE_DEBUG
- DUK_D(DUK_DPRINT("checked %ld objects for finalizers before freeing heap", (long) count_obj));
-#endif
+ DUK_ASSERT(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
+ DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
}
DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
@@ -42327,6 +43438,9 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
/* Detach a debugger if attached (can be called multiple times)
* safely.
*/
+ /* XXX: Add a flag to reject an attempt to re-attach? Otherwise
+ * the detached callback may immediately reattach.
+ */
duk_debug_do_detach(heap);
#endif
@@ -42334,18 +43448,30 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
* objects, and regardless of whether or not mark-and-sweep is
* enabled. This gives finalizers the chance to free any native
* resources like file handles, allocations made outside Duktape,
- * etc.
+ * etc. This is quite tricky to get right, so that all finalizer
+ * guarantees are honored.
*
* XXX: this perhaps requires an execution time limit.
*/
DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
-#ifdef DUK_USE_MARK_AND_SWEEP
- /* run mark-and-sweep a few times just in case (unreachable
- * object finalizers run already here)
- */
+#if defined(DUK_USE_MARK_AND_SWEEP)
+ /* Run mark-and-sweep a few times just in case (unreachable object
+ * finalizers run already here). The last round must rescue objects
+ * from the previous round without running any more finalizers. This
+ * ensures rescued objects get their FINALIZED flag cleared so that
+ * their finalizer is called once more in forced finalization to
+ * satisfy finalizer guarantees. However, we don't want to run any
+ * more finalizer because that'd required one more loop, and so on.
+ */
+ DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
duk_heap_mark_and_sweep(heap, 0);
+ DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
duk_heap_mark_and_sweep(heap, 0);
+ DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
+ duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS); /* skip finalizers; queue finalizable objects to heap_allocated */
#endif
+
+ DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* rescue no longer supported */
duk__free_run_finalizers(heap);
/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
@@ -42355,12 +43481,12 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
duk__free_allocated(heap);
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
duk__free_refzero_list(heap);
#endif
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap));
duk__free_markandsweep_finalize_list(heap);
#endif
@@ -42507,7 +43633,7 @@ DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
return 1;
}
-#ifdef DUK_USE_DEBUG
+#if defined(DUK_USE_DEBUG)
#define DUK__DUMPSZ(t) do { \
DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
} while (0)
@@ -42521,18 +43647,18 @@ DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
(long) (a), (long) (b), \
(double) (a), (double) (b))); \
- } while(0)
+ } while (0)
#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b) do { \
DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
(unsigned long) (a), (unsigned long) (b), \
(double) (a), (double) (b))); \
- } while(0)
+ } while (0)
#define DUK__DUMPLM_SIGNED(t) do { \
DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
- } while(0)
+ } while (0)
#define DUK__DUMPLM_UNSIGNED(t) do { \
DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
- } while(0)
+ } while (0)
DUK_LOCAL void duk__dump_type_sizes(void) {
DUK_D(DUK_DPRINT("sizeof()"));
@@ -42694,19 +43820,27 @@ DUK_LOCAL void duk__dump_type_limits(void) {
DUK_LOCAL void duk__dump_misc_options(void) {
DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
+ DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
+ DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
+ DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
#if defined(DUK_USE_PACKED_TVAL)
DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
#else
DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
#endif
+#if defined(DUK_USE_VARIADIC_MACROS)
+ DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
+#else
+ DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
+#endif
#if defined(DUK_USE_INTEGER_LE)
- DUK_D(DUK_DPRINT("Integer endianness: little"));
+ DUK_D(DUK_DPRINT("integer endianness: little"));
#elif defined(DUK_USE_INTEGER_ME)
- DUK_D(DUK_DPRINT("Integer endianness: mixed"));
+ DUK_D(DUK_DPRINT("integer endianness: mixed"));
#elif defined(DUK_USE_INTEGER_BE)
- DUK_D(DUK_DPRINT("Integer endianness: big"));
+ DUK_D(DUK_DPRINT("integer endianness: big"));
#else
- DUK_D(DUK_DPRINT("Integer endianness: ???"));
+ DUK_D(DUK_DPRINT("integer endianness: ???"));
#endif
#if defined(DUK_USE_DOUBLE_LE)
DUK_D(DUK_DPRINT("IEEE double endianness: little"));
@@ -42737,7 +43871,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
* Debug dump type sizes
*/
-#ifdef DUK_USE_DEBUG
+#if defined(DUK_USE_DEBUG)
duk__dump_misc_options();
duk__dump_type_sizes();
duk__dump_type_limits();
@@ -42746,7 +43880,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
/*
* If selftests enabled, run them as early as possible
*/
-#ifdef DUK_USE_SELF_TESTS
+#if defined(DUK_USE_SELF_TESTS)
DUK_D(DUK_DPRINT("running self tests"));
duk_selftest_run_tests();
DUK_D(DUK_DPRINT("self tests passed"));
@@ -42756,7 +43890,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
* Computed values (e.g. INFINITY)
*/
-#ifdef DUK_USE_COMPUTED_NAN
+#if defined(DUK_USE_COMPUTED_NAN)
do {
/* Workaround for some exotic platforms where NAN is missing
* and the expression (0.0 / 0.0) does NOT result in a NaN.
@@ -42772,7 +43906,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
} while (0);
#endif
-#ifdef DUK_USE_COMPUTED_INFINITY
+#if defined(DUK_USE_COMPUTED_INFINITY)
do {
/* Similar workaround for INFINITY. */
volatile double dbl1 = 1.0;
@@ -42799,14 +43933,14 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
DUK_MEMZERO(res, sizeof(*res));
/* explicit NULL inits */
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
res->heap_udata = NULL;
res->heap_allocated = NULL;
-#ifdef DUK_USE_REFERENCE_COUNTING
+#if defined(DUK_USE_REFERENCE_COUNTING)
res->refzero_list = NULL;
res->refzero_list_tail = NULL;
#endif
-#ifdef DUK_USE_MARK_AND_SWEEP
+#if defined(DUK_USE_MARK_AND_SWEEP)
res->finalize_list = NULL;
#endif
res->heap_thread = NULL;
@@ -42869,8 +44003,11 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
*/
res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
res->rnd_state = (duk_uint32_t) (duk_intptr_t) res;
+#if !defined(DUK_USE_STRHASH_DENSE)
+ res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
+#endif
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
res->lj.jmpbuf_ptr = NULL;
#endif
DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
@@ -42888,7 +44025,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#if defined(DUK_USE_STRTAB_CHAIN)
DUK_MEMZERO(res->strtable, sizeof(duk_strtab_entry) * DUK_STRTAB_CHAIN_SIZE);
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
{
duk_small_uint_t i;
for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
@@ -42919,7 +44056,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
}
#endif /* DUK_USE_HEAPPTR16 */
res->st_size = DUK_STRTAB_INITIAL_SIZE;
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
{
duk_small_uint_t i;
DUK_ASSERT(res->st_size == DUK_STRTAB_INITIAL_SIZE);
@@ -42944,7 +44081,7 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
* Init stringcache
*/
-#ifdef DUK_USE_EXPLICIT_NULL_INIT
+#if defined(DUK_USE_EXPLICIT_NULL_INIT)
{
duk_small_uint_t i;
for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
@@ -43014,11 +44151,23 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
#line 1 "duk_heap_hashstring.c"
/*
* String hash computation (interning).
+ *
+ * String hashing is performance critical because a string hash is computed
+ * for all new strings which are candidates to be added to the string table.
+ * However, strings actually added to the string table go through a codepoint
+ * length calculation which dominates performance because it goes through
+ * every byte of the input string (but only for strings added).
+ *
+ * The string hash algorithm should be fast, but on the other hand provide
+ * good enough hashes to ensure both string table and object property table
+ * hash tables work reasonably well (i.e., there aren't too many collisions
+ * with real world inputs). Unless the hash is cryptographic, it's always
+ * possible to craft inputs with maximal hash collisions.
*/
/* include removed: duk_internal.h */
-/* constants for duk_hashstring() */
+#if defined(DUK_USE_STRHASH_DENSE)
#define DUK__STRHASH_SHORTSTRING 4096L
#define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
#define DUK__STRHASH_BLOCKSIZE 256L
@@ -43026,25 +44175,21 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
duk_uint32_t hash;
- /*
- * Sampling long strings by byte skipping (like Lua does) is potentially
- * a cache problem. Here we do 'block skipping' instead for long strings:
- * hash an initial part, and then sample the rest of the string with
- * reasonably sized chunks.
- *
- * Skip should depend on length and bound the total time to roughly
- * logarithmic.
+ /* Use Murmurhash2 directly for short strings, and use "block skipping"
+ * for long strings: hash an initial part and then sample the rest of
+ * the string with reasonably sized chunks. An initial offset for the
+ * sampling is computed based on a hash of the initial part of the string;
+ * this is done to (usually) avoid the case where all long strings have
+ * certain offset ranges which are never sampled.
*
- * With current values:
+ * Skip should depend on length and bound the total time to roughly
+ * logarithmic. With current values:
*
- * 1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
- * 1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
+ * 1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
+ * 1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
*
- * After an initial part has been hashed, an offset is applied before
- * starting the sampling. The initial offset is computed from the
- * hash of the initial part of the string. The idea is to avoid the
- * case that all long strings have certain offset ranges that are never
- * sampled.
+ * XXX: It would be better to compute the skip offset more "smoothly"
+ * instead of having a few boundary values.
*/
/* note: mixing len into seed improves hashing when skipping */
@@ -43082,6 +44227,44 @@ DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t
#endif
return hash;
}
+
+#undef DUK__STRHASH_SHORTSTRING
+#undef DUK__STRHASH_MEDIUMSTRING
+#undef DUK__STRHASH_BLOCKSIZE
+#else /* DUK_USE_STRHASH_DENSE */
+DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
+ duk_uint32_t hash;
+ duk_size_t step;
+ duk_size_t off;
+
+ /* Slightly modified "Bernstein hash" from:
+ *
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
+ *
+ * Modifications: string skipping and reverse direction similar to
+ * Lua 5.1.5, and different hash initializer.
+ *
+ * The reverse direction ensures last byte it always included in the
+ * hash which is a good default as changing parts of the string are
+ * more often in the suffix than in the prefix.
+ */
+
+ hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
+ step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
+ for (off = len; off >= step; off -= step) {
+ DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
+ hash = (hash * 33) + str[off - 1];
+ }
+
+#if defined(DUK_USE_STRHASH16)
+ /* Truncate to 16 bits here, so that a computed hash can be compared
+ * against a hash stored in a 16-bit field.
+ */
+ hash &= 0x0000ffffUL;
+#endif
+ return hash;
+}
+#endif /* DUK_USE_STRHASH_DENSE */
#line 1 "duk_heap_markandsweep.c"
/*
* Mark-and-sweep garbage collection.
@@ -43940,7 +45123,7 @@ DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_
* Run (object) finalizers in the "to be finalized" work list.
*/
-DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap) {
+DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags) {
duk_heaphdr *curr;
duk_heaphdr *next;
#ifdef DUK_USE_DEBUG
@@ -43963,13 +45146,22 @@ DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap) {
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
- /* run the finalizer */
- duk_hobject_run_finalizer(thr, (duk_hobject *) curr); /* must never longjmp */
-
- /* mark FINALIZED, for next mark-and-sweep (will collect unless has become reachable;
- * prevent running finalizer again if reachable)
- */
- DUK_HEAPHDR_SET_FINALIZED(curr);
+ if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
+ /* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
+ * Next mark-and-sweep will collect the object unless it has
+ * become reachable (i.e. rescued). FINALIZED prevents the
+ * finalizer from being executed again before that.
+ */
+ duk_hobject_run_finalizer(thr, (duk_hobject *) curr); /* must never longjmp */
+ DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
+ } else {
+ /* Used during heap destruction: don't actually run finalizers
+ * because we're heading into forced finalization. Instead,
+ * queue finalizable objects back to the heap_allocated list.
+ */
+ DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
+ }
/* queue back to heap_allocated */
next = DUK_HEAPHDR_GET_NEXT(heap, curr);
@@ -44406,7 +45598,7 @@ DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t
if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
} else {
- duk__run_object_finalizers(heap);
+ duk__run_object_finalizers(heap, flags);
}
/*
@@ -45210,10 +46402,9 @@ DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr) {
* objects and must be safe (not throw any errors, ever).
*/
- /* XXX: If object has FINALIZED, it was finalized by mark-and-sweep on
- * its previous run. Any point in running finalizer again here? If
- * finalization semantics is changed so that finalizer is only run once,
- * checking for FINALIZED would happen here.
+ /* An object may have FINALIZED here if it was finalized by mark-and-sweep
+ * on a previous run and refcount then decreased to zero. We won't run the
+ * finalizer again here.
*/
/* A finalizer is looked up from the object and up its prototype chain
@@ -45226,6 +46417,7 @@ DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr) {
DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
duk_hobject_run_finalizer(thr, obj); /* must never longjmp */
+ DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1)); /* duk_hobject_run_finalizer() sets */
DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
@@ -45266,6 +46458,9 @@ DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr) {
if (rescued) {
/* yes -> move back to heap allocated */
DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
+ DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h1));
+ DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));
+ DUK_HEAPHDR_CLEAR_FINALIZED(h1);
DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
DUK_HEAPHDR_SET_NEXT(heap, h1, heap->heap_allocated);
heap->heap_allocated = h1;
@@ -45319,22 +46514,25 @@ DUK_INTERNAL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
heap = thr->heap;
DUK_DDD(DUK_DDDPRINT("refzero %p: %!O", (void *) h, (duk_heaphdr *) h));
-#ifdef DUK_USE_MARK_AND_SWEEP
/*
* If mark-and-sweep is running, don't process 'refzero' situations at all.
* They may happen because mark-and-sweep needs to finalize refcounts for
* each object it sweeps. Otherwise the target objects of swept objects
* would have incorrect refcounts.
*
+ * This check must be enabled also when mark-and-sweep support has been
+ * disabled: the flag is also used in heap destruction when running
+ * finalizers for remaining objects, and the flag prevents objects from
+ * being moved around in heap linked lists.
+ *
* Note: mark-and-sweep could use a separate decref handler to avoid coming
* here at all. However, mark-and-sweep may also call finalizers, which
* can do arbitrary operations and would use this decref variant anyway.
*/
- if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
+ if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap))) {
DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h));
return;
}
-#endif
switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
case DUK_HTYPE_STRING:
@@ -45531,9 +46729,13 @@ DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h
/*
* String scanning helpers
+ *
+ * All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
+ * considered to contribute a character. This must match how string
+ * character length is computed.
*/
-DUK_LOCAL duk_uint8_t *duk__scan_forwards(duk_uint8_t *p, duk_uint8_t *q, duk_uint_fast32_t n) {
+DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
while (n > 0) {
for (;;) {
p++;
@@ -45549,7 +46751,7 @@ DUK_LOCAL duk_uint8_t *duk__scan_forwards(duk_uint8_t *p, duk_uint8_t *q, duk_ui
return p;
}
-DUK_LOCAL duk_uint8_t *duk__scan_backwards(duk_uint8_t *p, duk_uint8_t *q, duk_uint_fast32_t n) {
+DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
while (n > 0) {
for (;;) {
p--;
@@ -45584,9 +46786,9 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
duk_small_int_t i;
duk_bool_t use_cache;
duk_uint_fast32_t dist_start, dist_end, dist_sce;
- duk_uint8_t *p_start;
- duk_uint8_t *p_end;
- duk_uint8_t *p_found;
+ const duk_uint8_t *p_start;
+ const duk_uint8_t *p_end;
+ const duk_uint8_t *p_found;
if (char_offset > DUK_HSTRING_GET_CHARLEN(h)) {
goto error;
@@ -45653,8 +46855,8 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
dist_end = DUK_HSTRING_GET_CHARLEN(h) - char_offset;
dist_sce = 0; DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
- p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
- p_end = (duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
+ p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
+ p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
p_found = NULL;
if (sce) {
@@ -45765,7 +46967,7 @@ DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *t
tmp = *sce;
DUK_MEMMOVE((void *) (&heap->strcache[1]),
- (void *) (&heap->strcache[0]),
+ (const void *) (&heap->strcache[0]),
(size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
heap->strcache[0] = tmp;
@@ -46040,7 +47242,7 @@ DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk
duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
DUK_ASSERT(h != NULL);
if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
- DUK_MEMCMP(str, DUK_HSTRING_GET_DATA(h), blen) == 0) {
+ DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
return h;
}
}
@@ -46053,7 +47255,7 @@ DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk
duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[i]);
DUK_ASSERT(h != NULL);
if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
- DUK_MEMCMP(str, DUK_HSTRING_GET_DATA(h), blen) == 0) {
+ DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
return h;
}
}
@@ -46078,7 +47280,7 @@ DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk
if (e->listlen == 0) {
if (e->u.str != NULL &&
DUK_HSTRING_GET_BYTELEN(e->u.str) == blen &&
- DUK_MEMCMP(str, DUK_HSTRING_GET_DATA(e->u.str), blen) == 0) {
+ DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e->u.str), (size_t) blen) == 0) {
return e->u.str;
}
} else {
@@ -46087,7 +47289,7 @@ DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk
for (i = 0, n = e->listlen; i < n; i++) {
if (lst[i] != NULL &&
DUK_HSTRING_GET_BYTELEN(lst[i]) == blen &&
- DUK_MEMCMP(str, DUK_HSTRING_GET_DATA(lst[i]), blen) == 0) {
+ DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(lst[i]), (size_t) blen) == 0) {
return lst[i];
}
}
@@ -46339,7 +47541,7 @@ DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_hstri
return NULL;
}
if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
- if (DUK_MEMCMP(str, DUK_HSTRING_GET_DATA(e), blen) == 0) {
+ if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
(long) i, (long) step, (long) size));
return e;
@@ -47241,7 +48443,7 @@ DUK_LOCAL void duk__sort_array_indices(duk_hthread *thr, duk_hobject *h_obj) {
(long) (p_curr - p_insert), (void *) h_curr));
DUK_MEMMOVE((void *) (p_insert + 1),
- (void *) p_insert,
+ (const void *) p_insert,
(size_t) ((p_curr - p_insert) * sizeof(duk_hstring *)));
*p_insert = h_curr;
/* keep val_highest */
@@ -47747,7 +48949,10 @@ DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_sma
/* include removed: duk_internal.h */
DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx) {
+ duk_hthread *thr;
+
DUK_ASSERT(ctx != NULL);
+ thr = (duk_hthread *) ctx;
DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
@@ -47765,9 +48970,10 @@ DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx) {
DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
return 0;
}
- duk_dup(ctx, -2); /* -> [... obj finalizer obj] */
+ duk_dup(ctx, -2);
+ duk_push_boolean(ctx, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
- duk_call(ctx, 1); /* -> [... obj retval] */
+ duk_call(ctx, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
return 0;
@@ -47800,6 +49006,20 @@ DUK_INTERNAL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj)
* may trigger an error (getter may throw one, for instance).
*/
+ if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
+ DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
+ return;
+ }
+ DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
+ if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
+ /* This shouldn't happen; call sites should avoid looking up
+ * _Finalizer "through" a Proxy, but ignore if we come here
+ * with a Proxy to avoid finalizer re-entry.
+ */
+ DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
+ return;
+ }
+
/* XXX: use a NULL error handler for the finalizer call? */
DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
@@ -49469,6 +50689,11 @@ DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap,
DUK_ASSERT(heap != NULL);
DUK_ASSERT(obj != NULL);
+ /* This is not strictly necessary, but avoids compiler warnings; e.g.
+ * gcc won't reliably detect that no uninitialized data is read below.
+ */
+ DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
+
if (duk_hobject_get_internal_value(heap, obj, &tv)) {
duk_hstring *h;
DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
@@ -50367,7 +51592,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
case DUK_TAG_NULL: {
/* Note: unconditional throw */
DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
+#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+ DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
+ duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
return 0;
}
@@ -51402,7 +52632,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
/* Note: unconditional throw */
DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
(duk_tval *) tv_obj));
+#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+ DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
+ duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
return 0;
}
@@ -52159,7 +53394,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
fail_base_primitive:
DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
if (throw_flag) {
+#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+ DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
+ duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
}
duk_pop(ctx); /* remove key */
return 0;
@@ -52521,7 +53761,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
fail_invalid_base_uncond:
/* Note: unconditional throw */
DUK_ASSERT(duk_get_top(ctx) == entry_top);
+#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_BASE);
+#else
+ DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
+ duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
+#endif
return 0;
fail_proxy_rejected:
@@ -54041,7 +55286,8 @@ DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk
p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
p = p_start + boff;
DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
- (void *) p_start, (void *) p_end, (void *) p));
+ (const void *) p_start, (const void *) p_end,
+ (const void *) p));
/* This may throw an error though not for valid E5 strings. */
cp = duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
@@ -54476,9 +55722,6 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk_c_function c_func_getter;
duk_c_function c_func_setter;
- /* XXX: this is a bit awkward because there is no exposed helper
- * in the API style, only this internal helper.
- */
DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, stridx=%ld, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
(long) i, (long) stridx, (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags));
@@ -54487,7 +55730,7 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0); /* always 0 args */
duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1); /* always 1 arg */
- /* XXX: magic for getter/setter? */
+ /* XXX: magic for getter/setter? use duk_def_prop()? */
prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR; /* accessor flag not encoded explicitly */
duk_hobject_define_accessor_internal(thr,
@@ -54683,9 +55926,6 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
#else
"?"
#endif
-#if defined(DUK_USE_BYTEORDER_FORCED)
- "f"
-#endif
" "
/* Packed or unpacked tval */
#if defined(DUK_USE_PACKED_TVAL)
@@ -56124,7 +57364,12 @@ duk_hobject *duk__nonbound_func_lookup(duk_context *ctx,
return func;
not_callable_error:
+ DUK_ASSERT(tv_func != NULL);
+#if defined(DUK_USE_PARANOID_ERRORS)
DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_CALLABLE);
+#else
+ DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(ctx, tv_func));
+#endif
DUK_UNREACHABLE();
return NULL; /* never executed */
}
@@ -56245,7 +57490,7 @@ duk_int_t duk_handle_call(duk_hthread *thr,
duk_instr_t **entry_ptr_curr_pc;
volatile duk_bool_t need_setjmp;
duk_jmpbuf * volatile old_jmpbuf_ptr = NULL; /* ptr is volatile (not the target) */
- volatile duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
+ duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
duk_idx_t idx_args; /* valstack index of start of args (arg1) (relative to entry valstack_bottom) */
duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
@@ -56341,7 +57586,7 @@ duk_int_t duk_handle_call(duk_hthread *thr,
* call the fatal error handler.
*/
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
}
/*
@@ -56806,7 +58051,7 @@ duk_int_t duk_handle_call(duk_hthread *thr,
duk_error_throw_from_negative_rc(thr, rc);
DUK_UNREACHABLE();
} else if (rc > 1) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, "c function returned invalid rc");
+ DUK_ERROR_API(thr, "c function returned invalid rc");
}
DUK_ASSERT(rc == 0 || rc == 1);
@@ -57201,7 +58446,7 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
* call the fatal error handler.
*/
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
}
/* setjmp catchpoint setup */
@@ -57353,7 +58598,7 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr,
DUK_ASSERT(rc >= 0);
if (duk_get_top(ctx) < rc) {
- DUK_ERROR(thr, DUK_ERR_API_ERROR, "not enough stack values for safe_call rc");
+ DUK_ERROR_API(thr, "not enough stack values for safe_call rc");
}
duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);
@@ -57536,7 +58781,7 @@ duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr,
if (idx_func < 0 || idx_args < 0) {
/* XXX: assert? compiler is responsible for this never happening */
- DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS);
+ DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
}
/*
@@ -58093,7 +59338,7 @@ DUK_LOCAL_DECL duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *co
/* statement parsing */
DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
-DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
+DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
@@ -58185,11 +59430,11 @@ DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
+ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
- DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
@@ -61681,9 +62926,17 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
case DUK_TOK_PERIOD: {
/* Property access expressions are critical for correct LHS ordering,
* see comments in duk__expr()!
+ *
+ * A conservative approach would be to use duk__ivalue_totempconst()
+ * for 'left'. However, allowing a reg-bound variable seems safe here
+ * and is nice because "foo.bar" is a common expression. If the ivalue
+ * is used in an expression a GETPROP will occur before any changes to
+ * the base value can occur. If the ivalue is used as an assignment
+ * LHS, the assignment code will ensure the base value is safe from
+ * RHS mutation.
*/
- /* XXX: this now coerces an identifier into a GETVAR to a temp, which
+ /* XXX: This now coerces an identifier into a GETVAR to a temp, which
* causes an extra LDREG in call setup. It's sufficient to coerce to a
* unary ivalue?
*/
@@ -61714,13 +62967,22 @@ DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_i
/* XXX: optimize temp reg use */
/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
-
/* XXX: coerce to regs? it might be better for enumeration use, where the
* same PROP ivalue is used multiple times. Or perhaps coerce PROP further
* there?
*/
+ /* XXX: for simple cases like x['y'] an unnecessary LDREG is
+ * emitted for the base value; could avoid it if we knew that
+ * the key expression is safe (e.g. just a single literal).
+ */
- duk__ivalue_toplain(comp_ctx, left);
+ /* The 'left' value must not be a register bound variable
+ * because it may be mutated during the rest of the expression
+ * and E5.1 Section 11.2.1 specifies the order of evaluation
+ * so that the base value is evaluated first.
+ * See: test-bug-nested-prop-mutate.js.
+ */
+ duk__ivalue_totempconst(comp_ctx, left);
duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
@@ -62558,8 +63820,9 @@ DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
*/
#define DUK__EXPR_RBP_MASK 0xff
-#define DUK__EXPR_FLAG_REJECT_IN (1 << 8)
-#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9)
+#define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
+#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
+#define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
/* main expression parser function */
DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
@@ -62833,6 +64096,11 @@ DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
(duk_regconst_t) reg_val,
rc_varname);
}
+ } else {
+ if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
+ /* Used for minimal 'const': initializer required. */
+ goto syntax_error;
+ }
}
duk_pop(ctx); /* pop varname */
@@ -62846,7 +64114,7 @@ DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res,
DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_INVALID_VAR_DECLARATION);
}
-DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
+DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
duk_reg_t reg_varbind;
duk_regconst_t rc_varname;
@@ -62854,7 +64122,7 @@ DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
for (;;) {
/* rc_varname and reg_varbind are ignored here */
- duk__parse_var_decl(comp_ctx, res, 0, &reg_varbind, &rc_varname);
+ duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
break;
@@ -64135,9 +65403,15 @@ DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_
stmt_flags = 0;
break;
}
+ case DUK_TOK_CONST: {
+ DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
+ duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
+ stmt_flags = DUK__HAS_TERM;
+ break;
+ }
case DUK_TOK_VAR: {
DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
- duk__parse_var_stmt(comp_ctx, res);
+ duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
stmt_flags = DUK__HAS_TERM;
break;
}
@@ -65644,37 +66918,9 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer
prev_ctx = thr->compile_ctx;
thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
safe_rc = duk_safe_call(ctx, duk__js_compile_raw, 2 /*nargs*/, 1 /*nret*/);
- thr->compile_ctx = prev_ctx;
+ thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
if (safe_rc != DUK_EXEC_SUCCESS) {
- /* Append a "(line NNN)" to the "message" property of any
- * error thrown during compilation. Usually compilation
- * errors are SyntaxErrors but they can also be out-of-memory
- * errors and the like.
- *
- * Source file/line are added to tracedata directly by
- * duk_error_augment.c based on thr->compile_ctx.
- */
-
- /* [ ... error ] */
-
- DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
- (duk_tval *) duk_get_tval(ctx, -1)));
- if (duk_is_object(ctx, -1)) {
- /* XXX: Now that fileName and lineNumber are set, this is
- * unnecessary. Remove in Duktape 1.3.0?
- */
-
- if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_MESSAGE)) {
- duk_push_sprintf(ctx, " (line %ld)", (long) comp_stk.comp_ctx_alloc.curr_token.start_line);
- duk_concat(ctx, 2);
- duk_put_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
- } else {
- duk_pop(ctx);
- }
- }
- DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
- (duk_tval *) duk_get_tval(ctx, -1)));
duk_throw(ctx);
}
@@ -70732,7 +71978,7 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
DUK_ASSERT(len_x == len_y);
DUK_ASSERT(len_x == 0 || buf_x != NULL);
DUK_ASSERT(len_y == 0 || buf_y != NULL);
- return (DUK_MEMCMP(buf_x, buf_y, len_x) == 0) ? 1 : 0;
+ return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
}
}
case DUK_TAG_LIGHTFUNC: {
@@ -70811,20 +72057,20 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d
duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
duk_size_t len_x = DUK_HSTRING_GET_BYTELEN(h_x);
duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
- void *buf_x;
- void *buf_y;
+ const void *buf_x;
+ const void *buf_y;
if (len_x != len_y) {
return 0;
}
- buf_x = (void *) DUK_HSTRING_GET_DATA(h_x);
- buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
+ buf_x = (const void *) DUK_HSTRING_GET_DATA(h_x);
+ buf_y = (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
/* if len_x == len_y == 0, buf_x and/or buf_y may
* be NULL, but that's OK.
*/
DUK_ASSERT(len_x == len_y);
DUK_ASSERT(len_x == 0 || buf_x != NULL);
DUK_ASSERT(len_y == 0 || buf_y != NULL);
- return (DUK_MEMCMP(buf_x, buf_y, len_x) == 0) ? 1 : 0;
+ return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
}
/* Boolean/any -> coerce boolean to number and try again. If boolean is
@@ -70887,19 +72133,12 @@ DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const
prefix_len = (len1 <= len2 ? len1 : len2);
- /* XXX: this special case can now be removed with DUK_MEMCMP */
- /* memcmp() should return zero (equal) for zero length, but avoid
- * it because there are some platform specific bugs. Don't use
- * strncmp() because it stops comparing at a NUL.
+ /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
+ * inputs so no zero length check is needed.
*/
-
- if (prefix_len == 0) {
- rc = 0;
- } else {
- rc = DUK_MEMCMP((const char *) buf1,
- (const char *) buf2,
- prefix_len);
- }
+ rc = DUK_MEMCMP((const void *) buf1,
+ (const void *) buf2,
+ (size_t) prefix_len);
if (rc < 0) {
return -1;
@@ -73781,7 +75020,7 @@ DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count
keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
DUK_MEMMOVE((void *) lex_ctx->window,
(const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
- (duk_size_t) keep_bytes);
+ (size_t) keep_bytes);
cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
@@ -75496,7 +76735,7 @@ DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
if (n == 0) {
return;
}
- DUK_MEMCPY((void *) x->v, (void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
+ DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
}
DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
@@ -76058,7 +77297,7 @@ DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x
}
len = (duk_size_t) ((buf + 32) - p);
- DUK_MEMMOVE((void *) buf, (void *) p, (size_t) len);
+ DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
return len;
}
@@ -76527,7 +77766,7 @@ DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify
if (p == &nc_ctx->digits[0]) {
DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
- (void *) (&nc_ctx->digits[0]),
+ (const void *) (&nc_ctx->digits[0]),
(size_t) (sizeof(char) * nc_ctx->count));
nc_ctx->digits[0] = 1; /* don't increase 'count' */
nc_ctx->k++; /* position of highest digit changed */
@@ -77298,7 +78537,7 @@ DUK_INTERNAL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk
DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
"dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
- (void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
+ (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
(long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
(long) dig_expt, (long) dig_lzero, (long) dig_prec));
DUK__BI_PRINT("f", &nc_ctx->f);
@@ -79420,9 +80659,9 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
re_ctx.thr = thr;
- re_ctx.input = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
+ re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
- re_ctx.bytecode = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
+ re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
re_ctx.saved = NULL;
re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
@@ -79519,8 +80758,8 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
DUK_ASSERT(re_ctx.recursion_depth == 0);
DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
- (long) char_offset, (void *) sp, (void *) re_ctx.input,
- (void *) re_ctx.input_end));
+ (long) char_offset, (const void *) sp,
+ (const void *) re_ctx.input, (const void *) re_ctx.input_end));
/*
* Note:
@@ -79627,7 +80866,7 @@ DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_
duk_hstring *h_saved;
duk_push_lstring(ctx,
- (char *) re_ctx.saved[i],
+ (const char *) re_ctx.saved[i],
(duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
h_saved = duk_get_hstring(ctx, -1);
DUK_ASSERT(h_saved != NULL);
@@ -79719,15 +80958,15 @@ DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
/* include removed: duk_internal.h */
-#ifdef DUK_USE_COMPUTED_NAN
+#if defined(DUK_USE_COMPUTED_NAN)
DUK_INTERNAL double duk_computed_nan;
#endif
-#ifdef DUK_USE_COMPUTED_INFINITY
+#if defined(DUK_USE_COMPUTED_INFINITY)
DUK_INTERNAL double duk_computed_infinity;
#endif
-#ifdef DUK_USE_REPL_FPCLASSIFY
+#if defined(DUK_USE_REPL_FPCLASSIFY)
DUK_INTERNAL int duk_repl_fpclassify(double x) {
duk_double_union u;
duk_uint_fast16_t expt;
@@ -79759,7 +80998,7 @@ DUK_INTERNAL int duk_repl_fpclassify(double x) {
}
#endif
-#ifdef DUK_USE_REPL_SIGNBIT
+#if defined(DUK_USE_REPL_SIGNBIT)
DUK_INTERNAL int duk_repl_signbit(double x) {
duk_double_union u;
u.d = x;
@@ -79767,7 +81006,7 @@ DUK_INTERNAL int duk_repl_signbit(double x) {
}
#endif
-#ifdef DUK_USE_REPL_ISFINITE
+#if defined(DUK_USE_REPL_ISFINITE)
DUK_INTERNAL int duk_repl_isfinite(double x) {
int c = DUK_FPCLASSIFY(x);
if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
@@ -79778,14 +81017,14 @@ DUK_INTERNAL int duk_repl_isfinite(double x) {
}
#endif
-#ifdef DUK_USE_REPL_ISNAN
+#if defined(DUK_USE_REPL_ISNAN)
DUK_INTERNAL int duk_repl_isnan(double x) {
int c = DUK_FPCLASSIFY(x);
return (c == DUK_FP_NAN);
}
#endif
-#ifdef DUK_USE_REPL_ISINF
+#if defined(DUK_USE_REPL_ISINF)
DUK_INTERNAL int duk_repl_isinf(double x) {
int c = DUK_FPCLASSIFY(x);
return (c == DUK_FP_INFINITE);
@@ -79811,13 +81050,13 @@ typedef union {
} duk__test_double_union;
#define DUK__DBLUNION_CMP_TRUE(a,b) do { \
- if (DUK_MEMCMP((void *) (a), (void *) (b), sizeof(duk__test_double_union)) != 0) { \
+ if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares false (expected true)"); \
} \
} while (0)
#define DUK__DBLUNION_CMP_FALSE(a,b) do { \
- if (DUK_MEMCMP((void *) (a), (void *) (b), sizeof(duk__test_double_union)) == 0) { \
+ if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares true (expected false)"); \
} \
} while (0)
@@ -79877,7 +81116,11 @@ DUK_LOCAL void duk__selftest_packed_tval(void) {
DUK_LOCAL void duk__selftest_twos_complement(void) {
volatile int test;
test = -1;
- if (((duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
+
+ /* Note that byte order doesn't affect this test: all bytes in
+ * 'test' will be 0xFF for two's complement.
+ */
+ if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic");
}
}
@@ -79998,15 +81241,12 @@ DUK_LOCAL void duk__selftest_double_aliasing(void) {
* It's not an issue because the failure should only affect packed
* duk_tval representation, which is not used with Emscripten.
*/
-#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)
-#if defined(DUK_USE_PACKED_TVAL)
-#error inconsistent defines: skipping double aliasing selftest when using packed duk_tval
-#endif
+#if !defined(DUK_USE_PACKED_TVAL)
+ DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
return;
#endif
- /* Test signaling NaN and alias assignment in all
- * endianness combinations.
+ /* Test signaling NaN and alias assignment in all endianness combinations.
*/
/* little endian */
@@ -80033,7 +81273,7 @@ DUK_LOCAL void duk__selftest_double_aliasing(void) {
*/
DUK_LOCAL void duk__selftest_double_zero_sign(void) {
- volatile duk__test_double_union a, b;
+ duk__test_double_union a, b;
a.d = 0.0;
b.d = -a.d;
@@ -80587,7 +81827,7 @@ const duk_uint8_t duk_unicode_caseconv_lc[616] = {
141,2,101,2,2,97,0,52,129,131,128,
};
-/* FIXME: CONDITIONAL */
+#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
/*
* Automatically generated by extract_caseconv.py, do not edit!
*/
@@ -85876,6 +87116,7 @@ const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,
65534,65535,
};
+#endif
#line 1 "duk_util_bitdecoder.c"
/*
* Bitstream decoder.
@@ -86105,7 +87346,7 @@ DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw
p_base = bw->p_base;
DUK_MEMCPY((void *) bw->p,
(const void *) (p_base + src_off),
- (duk_size_t) len);
+ (size_t) len);
bw->p += len;
}
@@ -86138,10 +87379,10 @@ DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *b
DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
DUK_MEMMOVE((void *) (p_base + dst_off + len),
(const void *) (p_base + dst_off),
- (duk_size_t) move_sz);
+ (size_t) move_sz);
DUK_MEMCPY((void *) (p_base + dst_off),
(const void *) buf,
- (duk_size_t) len);
+ (size_t) len);
bw->p += len;
}
@@ -86186,10 +87427,10 @@ DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *b
DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
DUK_MEMMOVE((void *) (p_base + dst_off + len),
(const void *) (p_base + dst_off),
- (duk_size_t) move_sz);
+ (size_t) move_sz);
DUK_MEMCPY((void *) (p_base + dst_off),
(const void *) (p_base + src_off),
- (duk_size_t) len);
+ (size_t) len);
bw->p += len;
}
@@ -86223,7 +87464,7 @@ DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter
move_sz = buf_sz - off;
p_dst = p_base + off + len;
p_src = p_base + off;
- DUK_MEMMOVE((void *) p_dst, (const void *) p_src, move_sz);
+ DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
return p_src; /* point to start of 'reserved area' */
}
@@ -86257,7 +87498,7 @@ DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *b
move_sz = (duk_size_t) (bw->p - p_src);
DUK_MEMMOVE((void *) p_dst,
(const void *) p_src,
- move_sz);
+ (size_t) move_sz);
bw->p -= len;
}
@@ -86278,7 +87519,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p)
duk_uint16_t x;
} u;
- DUK_MEMCPY((void *) u.b, (const void *) (*p), 2);
+ DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
u.x = DUK_NTOH16(u.x);
*p += 2;
return u.x;
@@ -86290,7 +87531,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p)
duk_uint32_t x;
} u;
- DUK_MEMCPY((void *) u.b, (const void *) (*p), 4);
+ DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
u.x = DUK_NTOH32(u.x);
*p += 4;
return u.x;
@@ -86303,10 +87544,10 @@ DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t *
duk_uint32_t x;
} u;
- DUK_MEMCPY((void *) u.b, (const void *) (*p), 4);
+ DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
u.x = DUK_NTOH32(u.x);
du.ui[DUK_DBL_IDX_UI0] = u.x;
- DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), 4);
+ DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
u.x = DUK_NTOH32(u.x);
du.ui[DUK_DBL_IDX_UI1] = u.x;
*p += 8;
@@ -86321,7 +87562,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_ui
} u;
u.x = DUK_HTON16(val);
- DUK_MEMCPY((void *) (*p), (const void *) u.b, 2);
+ DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
*p += 2;
}
@@ -86332,7 +87573,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_ui
} u;
u.x = DUK_HTON32(val);
- DUK_MEMCPY((void *) (*p), (const void *) u.b, 4);
+ DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
*p += 4;
}
@@ -86346,10 +87587,10 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk
du.d = val;
u.x = du.ui[DUK_DBL_IDX_UI0];
u.x = DUK_HTON32(u.x);
- DUK_MEMCPY((void *) (*p), (const void *) u.b, 4);
+ DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
u.x = du.ui[DUK_DBL_IDX_UI1];
u.x = DUK_HTON32(u.x);
- DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, 4);
+ DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
*p += 8;
}
#line 1 "duk_util_hashbytes.c"
@@ -86364,6 +87605,7 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk
/* include removed: duk_internal.h */
+#if defined(DUK_USE_STRHASH_DENSE)
/* 'magic' constants for Murmurhash2 */
#define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
#define DUK__MAGIC_R 24
@@ -86378,7 +87620,7 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t
* OK as long as it is consistent for a build.
*/
#ifdef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
- duk_uint32_t k = *((duk_uint32_t *) (void *) data);
+ duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
#else
duk_uint32_t k = ((duk_uint32_t) data[0]) |
(((duk_uint32_t) data[1]) << 8) |
@@ -86408,6 +87650,7 @@ DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t
return h;
}
+#endif /* DUK_USE_STRHASH_DENSE */
#line 1 "duk_util_tinyrandom.c"
/*
* A tiny random number generator.
@@ -86472,4 +87715,3 @@ DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
return t;
}
-#endif
diff --git a/javascript/duktape/duktape.h b/javascript/duktape/duktape.h
index 6fba18d8b..d672edeba 100644
--- a/javascript/duktape/duktape.h
+++ b/javascript/duktape/duktape.h
@@ -5,8 +5,8 @@
* include guard. Other parts of the header are Duktape
* internal and related to platform/compiler/feature detection.
*
- * Git commit 40453939c5a5aa16898d19bbac4d02f77196cc8b (v1.3.0-138-g4045393).
- * Git branch regexp-canonicalize-lookup.
+ * Git commit b7b1c5fd2d1d4550140d57e05a7b32f540082bfa (v1.3.0-383-gb7b1c5f).
+ * Git branch duk-config-improvements.
*
* See Duktape AUTHORS.rst and LICENSE.txt for copyright and
* licensing information.
@@ -218,9 +218,9 @@ struct duk_number_list_entry {
* which Duktape snapshot was used. Not available in the Ecmascript
* environment.
*/
-#define DUK_GIT_COMMIT "40453939c5a5aa16898d19bbac4d02f77196cc8b"
-#define DUK_GIT_DESCRIBE "v1.3.0-138-g4045393"
-#define DUK_GIT_BRANCH "regexp-canonicalize-lookup"
+#define DUK_GIT_COMMIT "b7b1c5fd2d1d4550140d57e05a7b32f540082bfa"
+#define DUK_GIT_DESCRIBE "v1.3.0-383-gb7b1c5f"
+#define DUK_GIT_BRANCH "duk-config-improvements"
/* Duktape debug protocol version used by this build. */
#define DUK_DEBUG_PROTOCOL_VERSION 1
@@ -242,6 +242,7 @@ struct duk_number_list_entry {
#define DUK_API_ENTRY_STACK 64
/* Value types, used by e.g. duk_get_type() */
+#define DUK_TYPE_MIN 0
#define DUK_TYPE_NONE 0 /* no value, e.g. invalid index */
#define DUK_TYPE_UNDEFINED 1 /* Ecmascript undefined */
#define DUK_TYPE_NULL 2 /* Ecmascript null */
@@ -252,6 +253,7 @@ struct duk_number_list_entry {
#define DUK_TYPE_BUFFER 7 /* fixed or dynamic, garbage collected byte buffer */
#define DUK_TYPE_POINTER 8 /* raw void pointer */
#define DUK_TYPE_LIGHTFUNC 9 /* lightweight function pointer */
+#define DUK_TYPE_MAX 9
/* Value mask types, used by e.g. duk_get_type_mask() */
#define DUK_TYPE_MASK_NONE (1 << DUK_TYPE_NONE)
@@ -301,6 +303,12 @@ struct duk_number_list_entry {
#define DUK_DEFPROP_HAVE_GETTER (1 << 7) /* set getter (given on value stack) */
#define DUK_DEFPROP_HAVE_SETTER (1 << 8) /* set setter (given on value stack) */
#define DUK_DEFPROP_FORCE (1 << 9) /* force change if possible, may still fail for e.g. virtual properties */
+#define DUK_DEFPROP_SET_WRITABLE (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE)
+#define DUK_DEFPROP_CLEAR_WRITABLE DUK_DEFPROP_HAVE_WRITABLE
+#define DUK_DEFPROP_SET_ENUMERABLE (DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE)
+#define DUK_DEFPROP_CLEAR_ENUMERABLE DUK_DEFPROP_HAVE_ENUMERABLE
+#define DUK_DEFPROP_SET_CONFIGURABLE (DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE)
+#define DUK_DEFPROP_CLEAR_CONFIGURABLE DUK_DEFPROP_HAVE_CONFIGURABLE
/* Flags for duk_push_thread_raw() */
#define DUK_THREAD_NEW_GLOBAL_ENV (1 << 0) /* create a new global environment */
@@ -615,7 +623,8 @@ DUK_EXTERNAL_DECL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_id
DUK_EXTERNAL_DECL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index);
DUK_EXTERNAL_DECL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index);
-DUK_EXTERNAL_DECL duk_bool_t duk_is_callable(duk_context *ctx, duk_idx_t index);
+#define duk_is_callable(ctx,index) \
+ duk_is_function((ctx), (index))
DUK_EXTERNAL_DECL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index);
DUK_EXTERNAL_DECL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index);
DUK_EXTERNAL_DECL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t index);
@@ -642,6 +651,18 @@ DUK_EXTERNAL_DECL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t
DUK_EXTERNAL_DECL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index);
#define duk_is_error(ctx,index) \
(duk_get_error_code((ctx), (index)) != 0)
+#define duk_is_eval_error(ctx,index) \
+ (duk_get_error_code((ctx), (index)) == DUK_ERR_EVAL_ERROR)
+#define duk_is_range_error(ctx,index) \
+ (duk_get_error_code((ctx), (index)) == DUK_ERR_RANGE_ERROR)
+#define duk_is_reference_error(ctx,index) \
+ (duk_get_error_code((ctx), (index)) == DUK_ERR_REFERENCE_ERROR)
+#define duk_is_syntax_error(ctx,index) \
+ (duk_get_error_code((ctx), (index)) == DUK_ERR_SYNTAX_ERROR)
+#define duk_is_type_error(ctx,index) \
+ (duk_get_error_code((ctx), (index)) == DUK_ERR_TYPE_ERROR)
+#define duk_is_uri_error(ctx,index) \
+ (duk_get_error_code((ctx), (index)) == DUK_ERR_URI_ERROR)
/*
* Get operations: no coercion, returns default value for invalid
@@ -686,6 +707,9 @@ DUK_EXTERNAL_DECL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t inde
DUK_EXTERNAL_DECL void *duk_require_pointer(duk_context *ctx, duk_idx_t index);
DUK_EXTERNAL_DECL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index);
DUK_EXTERNAL_DECL duk_context *duk_require_context(duk_context *ctx, duk_idx_t index);
+DUK_EXTERNAL_DECL void duk_require_function(duk_context *ctx, duk_idx_t index);
+#define duk_require_callable(ctx,index) \
+ duk_require_function((ctx), (index))
DUK_EXTERNAL_DECL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index);
#define duk_require_object_coercible(ctx,index) \
@@ -1207,13 +1231,13 @@ DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx);
union duk_double_union {
double d;
float f[2];
-#ifdef DUK_USE_64BIT_OPS
+#if defined(DUK_USE_64BIT_OPS)
duk_uint64_t ull[1];
#endif
duk_uint32_t ui[2];
duk_uint16_t us[4];
duk_uint8_t uc[8];
-#ifdef DUK_USE_PACKED_TVAL_POSSIBLE
+#if defined(DUK_USE_PACKED_TVAL)
void *vp[2]; /* used by packed duk_tval, assumes sizeof(void *) == 4 */
#endif
};