From b4d26fd1606ad50aa136ba27efe87bbcdf396c81 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Wed, 12 Aug 2015 08:40:35 +0200 Subject: Take tip of the fix-cast-align-warnings branch from Sami to see if it helps --- javascript/duktape/duk_config.h | 3199 ++++++++ javascript/duktape/duktape.c | 16130 +++++++++++++++++++++++++++----------- javascript/duktape/duktape.h | 3357 +------- 3 files changed, 14811 insertions(+), 7875 deletions(-) create mode 100644 javascript/duktape/duk_config.h (limited to 'javascript') diff --git a/javascript/duktape/duk_config.h b/javascript/duktape/duk_config.h new file mode 100644 index 000000000..e21bc9292 --- /dev/null +++ b/javascript/duktape/duk_config.h @@ -0,0 +1,3199 @@ +/* + * 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). + * + * 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. + * + * 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 + * + * DUK_F_xxx are internal feature detection macros which should not be + * used outside this header. + * + * Useful resources: + * + * 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 - = 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 + */ + +/* 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() +#else +/* not available */ +#undef DUK_USE_RDTSC +#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 +#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 +#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 +#endif + +/* ARM */ +#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) +#define DUK_F_ARM +#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 +#endif + +/* SuperH */ +#if defined(__sh__) || \ + defined(__sh1__) || defined(__SH1__) || \ + defined(__sh2__) || defined(__SH2__) || \ + defined(__sh3__) || defined(__SH3__) || \ + defined(__sh4__) || defined(__SH4__) || \ + defined(__sh5__) || defined(__SH5__) +#define DUK_F_SUPERH +#endif + +/* Motorola 68K. Not defined by VBCC, so user must define one of these + * manually when using VBCC. + */ +#if defined(__m68k__) || defined(M68000) || defined(__MC68K__) +#define DUK_F_M68K +#endif + +/* PowerPC */ +#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__) +#define DUK_F_PPC +#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 +#endif + +/* OpenBSD */ +#if defined(__OpenBSD__) || defined(__OpenBSD) +#define DUK_F_OPENBSD +#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 + +/* Generic Unix (includes Cygwin) */ +#if defined(__unix) || defined(__unix__) || defined(unix) || \ + defined(DUK_F_LINUX) || defined(DUK_F_BSD) +#define DUK_F_UNIX +#endif + +/* Cygwin */ +#if defined(__CYGWIN__) +#define DUK_F_CYGWIN +#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 +#endif + +#if defined(__APPLE__) +#define DUK_F_APPLE +#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 +#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 +#endif + +/* Flash player (e.g. Crossbridge) */ +#if defined(__FLASHPLAYER__) +#define DUK_F_FLASHPLAYER +#endif + +/* Emscripten (provided explicitly by user), improve if possible */ +#if defined(EMSCRIPTEN) +#define DUK_F_EMSCRIPTEN +#endif + +/* QNX */ +#if defined(__QNX__) +#define DUK_F_QNX +#endif + +/* TI-Nspire (using Ndless) */ +#if defined(_TINSPIRE) +#define DUK_F_TINSPIRE +#endif + +/* GCC and GCC version convenience define. */ +#if defined(__GNUC__) +#define DUK_F_GCC +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */ +#define DUK_F_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__) +#else +#error cannot figure out gcc version +#endif +#endif + +/* 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 +#endif + +/* MSVC */ +#if defined(_MSC_VER) +/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx + * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g. + * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp + */ +#define DUK_F_MSVC +#if defined(_MSC_FULL_VER) +#if (_MSC_FULL_VER > 100000000) +#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER +#else +#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10) +#endif +#endif +#endif /* _MSC_VER */ + +/* 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 +#endif + +#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 +#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. + */ +#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 , + * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366 + */ +#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS) +#define __STDC_LIMIT_MACROS +#endif +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) +#define __STDC_CONSTANT_MACROS +#endif + +#if defined(__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 +#include +#include +#include +#include +#include +#elif defined(DUK_F_OPENBSD) +/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_PRS_STRPTIME +#define DUK_USE_DATE_FMT_STRFTIME +#include +#include +#include +#include +#include +#include +#elif defined(DUK_F_BSD) +/* other 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 +#include +#include +#include +#include +#include +#elif defined(DUK_F_TOS) +/* Atari ST TOS */ +#define DUK_USE_DATE_NOW_TIME +#define DUK_USE_DATE_TZO_GMTIME +/* no parsing (not an error) */ +#define DUK_USE_DATE_FMT_STRFTIME +#include +#include +#elif defined(DUK_F_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 +#include +#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 +#include +#ifndef UINTPTR_MAX +#define UINTPTR_MAX UINT_MAX +#endif +#else +#error AmigaOS but not M68K/PPC, not supported now +#endif +#elif defined(DUK_F_WINDOWS) +/* Windows 32-bit and 64-bit are currently the same. */ +/* MSVC does not have sys/param.h */ +#define DUK_USE_DATE_NOW_WINDOWS +#define DUK_USE_DATE_TZO_WINDOWS +/* Note: PRS and FMT are intentionally left undefined for now. This means + * there is no platform specific date parsing/formatting but there is still + * the ISO 8601 standard format. + */ +#include +#include +#elif defined(DUK_F_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 +#include +#include +#include +#include +#elif defined(DUK_F_QNX) +#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 +#include +#include +#include +#include +#elif defined(DUK_F_TINSPIRE) +#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 +#include +#include +#include +#include +#elif defined(DUK_F_LINUX) +#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 +#if defined(DUK_F_BCC) +/* no endian.h */ +#else +#include +#endif /* DUK_F_BCC */ +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#elif defined(DUK_F_CYGWIN) +/* Cygwin -- don't use strptime() for now */ +#define DUK_USE_DATE_NOW_GETTIMEOFDAY +#define DUK_USE_DATE_TZO_GMTIME_R +#define DUK_USE_DATE_FMT_STRFTIME +#include +#include +#include +#include +#include +#include +#else +/* Other UNIX, hopefully others */ +#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 +#if defined(DUK_F_BCC) +/* no endian.h */ +#else +#include +#endif /* DUK_F_BCC */ +#include +#include +#include +#include +#endif + +/* Shared includes */ +#include +#include +#include +#include /* varargs */ +#include +#include /* e.g. ptrdiff_t */ +#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). + */ +#include +#endif +#include + +#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. + */ +#define DUK_F_ULL_CONSTS +#endif + +/* + * Detection for specific libc variants (like uclibc) and other libc specific + * features. Potentially depends on the #includes above. + */ + +#if defined(__UCLIBC__) +#define DUK_F_UCLIBC +#endif + +/* + * Wrapper typedefs and constants for integer types, also sanity check types. + * + * C99 typedefs are quite good but not always available, and we want to avoid + * forcibly redefining the C99 typedefs. So, there are Duktape wrappers for + * all C99 typedefs and Duktape code should only use these typedefs. Type + * detection when C99 is not supported is best effort and may end up detecting + * some types incorrectly. + * + * Pointer sizes are a portability problem: pointers to different types may + * have a different size and function pointers are very difficult to manage + * portably. + * + * http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types + * + * Note: there's an interesting corner case when trying to define minimum + * signed integer value constants which leads to the current workaround of + * defining e.g. -0x80000000 as (-0x7fffffffL - 1L). See doc/code-issues.txt + * for a longer discussion. + * + * Note: avoid typecasts and computations in macro integer constants as they + * can then no longer be used in macro relational expressions (such as + * #if DUK_SIZE_MAX < 0xffffffffUL). There is internal code which relies on + * being able to compare DUK_SIZE_MAX against a limit. + */ + +/* XXX: add feature options to force basic types from outside? */ + +#if !defined(INT_MAX) +#error INT_MAX not defined +#endif + +/* Check that architecture is two's complement, standard C allows e.g. + * INT_MIN to be -2**31+1 (instead of -2**31). + */ +#if defined(INT_MAX) && defined(INT_MIN) +#if INT_MAX != -(INT_MIN + 1) +#error platform does not seem complement of two +#endif +#else +#error cannot check complement of two +#endif + +/* Pointer size determination based on architecture. + * XXX: unsure about BCC correctness. + */ +#if defined(DUK_F_X86) || defined(DUK_F_X32) || \ + defined(DUK_F_BCC) || \ + (defined(__WORDSIZE) && (__WORDSIZE == 32)) +#define DUK_F_32BIT_PTRS +#elif defined(DUK_F_X64) || \ + (defined(__WORDSIZE) && (__WORDSIZE == 64)) +#define DUK_F_64BIT_PTRS +#else +/* not sure, not needed with C99 anyway */ +#endif + +/* Intermediate define for 'have inttypes.h' */ +#undef DUK_F_HAVE_INTTYPES +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)) +/* vbcc + AmigaOS has C99 but no inttypes.h */ +#define DUK_F_HAVE_INTTYPES +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +/* C++11 apparently ratified stdint.h */ +#define DUK_F_HAVE_INTTYPES +#endif + +/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise + * through automatic detection. + */ +#if defined(DUK_F_HAVE_INTTYPES) +/* C99 or compatible */ + +#define DUK_F_HAVE_64BIT +#include + +typedef uint8_t duk_uint8_t; +typedef int8_t duk_int8_t; +typedef uint16_t duk_uint16_t; +typedef int16_t duk_int16_t; +typedef uint32_t duk_uint32_t; +typedef int32_t duk_int32_t; +typedef uint64_t duk_uint64_t; +typedef int64_t duk_int64_t; +typedef uint_least8_t duk_uint_least8_t; +typedef int_least8_t duk_int_least8_t; +typedef uint_least16_t duk_uint_least16_t; +typedef int_least16_t duk_int_least16_t; +typedef uint_least32_t duk_uint_least32_t; +typedef int_least32_t duk_int_least32_t; +typedef uint_least64_t duk_uint_least64_t; +typedef int_least64_t duk_int_least64_t; +typedef uint_fast8_t duk_uint_fast8_t; +typedef int_fast8_t duk_int_fast8_t; +typedef uint_fast16_t duk_uint_fast16_t; +typedef int_fast16_t duk_int_fast16_t; +typedef uint_fast32_t duk_uint_fast32_t; +typedef int_fast32_t duk_int_fast32_t; +typedef uint_fast64_t duk_uint_fast64_t; +typedef int_fast64_t duk_int_fast64_t; +typedef uintptr_t duk_uintptr_t; +typedef intptr_t duk_intptr_t; +typedef uintmax_t duk_uintmax_t; +typedef intmax_t duk_intmax_t; + +#define DUK_UINT8_MIN 0 +#define DUK_UINT8_MAX UINT8_MAX +#define DUK_INT8_MIN INT8_MIN +#define DUK_INT8_MAX INT8_MAX +#define DUK_UINT_LEAST8_MIN 0 +#define DUK_UINT_LEAST8_MAX UINT_LEAST8_MAX +#define DUK_INT_LEAST8_MIN INT_LEAST8_MIN +#define DUK_INT_LEAST8_MAX INT_LEAST8_MAX +#define DUK_UINT_FAST8_MIN 0 +#define DUK_UINT_FAST8_MAX UINT_FAST8_MAX +#define DUK_INT_FAST8_MIN INT_FAST8_MIN +#define DUK_INT_FAST8_MAX INT_FAST8_MAX +#define DUK_UINT16_MIN 0 +#define DUK_UINT16_MAX UINT16_MAX +#define DUK_INT16_MIN INT16_MIN +#define DUK_INT16_MAX INT16_MAX +#define DUK_UINT_LEAST16_MIN 0 +#define DUK_UINT_LEAST16_MAX UINT_LEAST16_MAX +#define DUK_INT_LEAST16_MIN INT_LEAST16_MIN +#define DUK_INT_LEAST16_MAX INT_LEAST16_MAX +#define DUK_UINT_FAST16_MIN 0 +#define DUK_UINT_FAST16_MAX UINT_FAST16_MAX +#define DUK_INT_FAST16_MIN INT_FAST16_MIN +#define DUK_INT_FAST16_MAX INT_FAST16_MAX +#define DUK_UINT32_MIN 0 +#define DUK_UINT32_MAX UINT32_MAX +#define DUK_INT32_MIN INT32_MIN +#define DUK_INT32_MAX INT32_MAX +#define DUK_UINT_LEAST32_MIN 0 +#define DUK_UINT_LEAST32_MAX UINT_LEAST32_MAX +#define DUK_INT_LEAST32_MIN INT_LEAST32_MIN +#define DUK_INT_LEAST32_MAX INT_LEAST32_MAX +#define DUK_UINT_FAST32_MIN 0 +#define DUK_UINT_FAST32_MAX UINT_FAST32_MAX +#define DUK_INT_FAST32_MIN INT_FAST32_MIN +#define DUK_INT_FAST32_MAX INT_FAST32_MAX +#define DUK_UINT64_MIN 0 +#define DUK_UINT64_MAX UINT64_MAX +#define DUK_INT64_MIN INT64_MIN +#define DUK_INT64_MAX INT64_MAX +#define DUK_UINT_LEAST64_MIN 0 +#define DUK_UINT_LEAST64_MAX UINT_LEAST64_MAX +#define DUK_INT_LEAST64_MIN INT_LEAST64_MIN +#define DUK_INT_LEAST64_MAX INT_LEAST64_MAX +#define DUK_UINT_FAST64_MIN 0 +#define DUK_UINT_FAST64_MAX UINT_FAST64_MAX +#define DUK_INT_FAST64_MIN INT_FAST64_MIN +#define DUK_INT_FAST64_MAX INT_FAST64_MAX + +#define DUK_UINTPTR_MIN 0 +#define DUK_UINTPTR_MAX UINTPTR_MAX +#define DUK_INTPTR_MIN INTPTR_MIN +#define DUK_INTPTR_MAX INTPTR_MAX + +#define DUK_UINTMAX_MIN 0 +#define DUK_UINTMAX_MAX UINTMAX_MAX +#define DUK_INTMAX_MIN INTMAX_MIN +#define DUK_INTMAX_MAX INTMAX_MAX + +#define DUK_SIZE_MIN 0 +#define DUK_SIZE_MAX SIZE_MAX +#undef DUK_SIZE_MAX_COMPUTED + +#else /* C99 types */ + +/* When C99 types are not available, we use heuristic detection to get + * the basic 8, 16, 32, and (possibly) 64 bit types. The fast/least + * types are then assumed to be exactly the same for now: these could + * be improved per platform but C99 types are very often now available. + * 64-bit types are not available on all platforms; this is OK at least + * on 32-bit platforms. + * + * This detection code is necessarily a bit hacky and can provide typedefs + * and defines that won't work correctly on some exotic platform. + */ + +#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \ + (defined(UCHAR_MAX) && (UCHAR_MAX == 255)) +typedef unsigned char duk_uint8_t; +typedef signed char duk_int8_t; +#else +#error cannot detect 8-bit type +#endif + +#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL) +typedef unsigned short duk_uint16_t; +typedef signed short duk_int16_t; +#elif defined(UINT_MAX) && (UINT_MAX == 65535UL) +/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */ +typedef unsigned int duk_uint16_t; +typedef signed int duk_int16_t; +#else +#error cannot detect 16-bit type +#endif + +#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL) +typedef unsigned int duk_uint32_t; +typedef signed int duk_int32_t; +#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL) +/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */ +typedef unsigned long duk_uint32_t; +typedef signed long duk_int32_t; +#else +#error cannot detect 32-bit type +#endif + +/* 64-bit type detection is a bit tricky. + * + * ULLONG_MAX is a standard define. __LONG_LONG_MAX__ and __ULONG_LONG_MAX__ + * are used by at least GCC (even if system headers don't provide ULLONG_MAX). + * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__. + * + * ULL / LL constants are rejected / warned about by some compilers, even if + * the compiler has a 64-bit type and the compiler/system headers provide an + * unsupported constant (ULL/LL)! Try to avoid using ULL / LL constants. + * As a side effect we can only check that e.g. ULONG_MAX is larger than 32 + * bits but can't be sure it is exactly 64 bits. Self tests will catch such + * cases. + */ +#undef DUK_F_HAVE_64BIT +#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX) +#if (ULONG_MAX > 4294967295UL) +#define DUK_F_HAVE_64BIT +typedef unsigned long duk_uint64_t; +typedef signed long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX) +#if (ULLONG_MAX > 4294967295UL) +#define DUK_F_HAVE_64BIT +typedef unsigned long long duk_uint64_t; +typedef signed long long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__) +#if (__ULONG_LONG_MAX__ > 4294967295UL) +#define DUK_F_HAVE_64BIT +typedef unsigned long long duk_uint64_t; +typedef signed long long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__) +#if (__LONG_LONG_MAX__ > 2147483647L) +#define DUK_F_HAVE_64BIT +typedef unsigned long long duk_uint64_t; +typedef signed long long duk_int64_t; +#endif +#endif +#if !defined(DUK_F_HAVE_64BIT) && \ + (defined(DUK_F_MINGW) || defined(DUK_F_MSVC)) +/* Both MinGW and MSVC have a 64-bit type. */ +#define DUK_F_HAVE_64BIT +typedef unsigned long duk_uint64_t; +typedef signed long duk_int64_t; +#endif +#if !defined(DUK_F_HAVE_64BIT) +/* cannot detect 64-bit type, not always needed so don't error */ +#endif + +typedef duk_uint8_t duk_uint_least8_t; +typedef duk_int8_t duk_int_least8_t; +typedef duk_uint16_t duk_uint_least16_t; +typedef duk_int16_t duk_int_least16_t; +typedef duk_uint32_t duk_uint_least32_t; +typedef duk_int32_t duk_int_least32_t; +typedef duk_uint8_t duk_uint_fast8_t; +typedef duk_int8_t duk_int_fast8_t; +typedef duk_uint16_t duk_uint_fast16_t; +typedef duk_int16_t duk_int_fast16_t; +typedef duk_uint32_t duk_uint_fast32_t; +typedef duk_int32_t duk_int_fast32_t; +#if defined(DUK_F_HAVE_64BIT) +typedef duk_uint64_t duk_uint_least64_t; +typedef duk_int64_t duk_int_least64_t; +typedef duk_uint64_t duk_uint_fast64_t; +typedef duk_int64_t duk_int_fast64_t; +#endif +#if defined(DUK_F_HAVE_64BIT) +typedef duk_uint64_t duk_uintmax_t; +typedef duk_int64_t duk_intmax_t; +#else +typedef duk_uint32_t duk_uintmax_t; +typedef duk_int32_t duk_intmax_t; +#endif + +/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and + * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are + * -not- portable. See code-issues.txt for a detailed discussion. + */ +#define DUK_UINT8_MIN 0UL +#define DUK_UINT8_MAX 0xffUL +#define DUK_INT8_MIN (-0x80L) +#define DUK_INT8_MAX 0x7fL +#define DUK_UINT_LEAST8_MIN 0UL +#define DUK_UINT_LEAST8_MAX 0xffUL +#define DUK_INT_LEAST8_MIN (-0x80L) +#define DUK_INT_LEAST8_MAX 0x7fL +#define DUK_UINT_FAST8_MIN 0UL +#define DUK_UINT_FAST8_MAX 0xffUL +#define DUK_INT_FAST8_MIN (-0x80L) +#define DUK_INT_FAST8_MAX 0x7fL +#define DUK_UINT16_MIN 0UL +#define DUK_UINT16_MAX 0xffffUL +#define DUK_INT16_MIN (-0x7fffL - 1L) +#define DUK_INT16_MAX 0x7fffL +#define DUK_UINT_LEAST16_MIN 0UL +#define DUK_UINT_LEAST16_MAX 0xffffUL +#define DUK_INT_LEAST16_MIN (-0x7fffL - 1L) +#define DUK_INT_LEAST16_MAX 0x7fffL +#define DUK_UINT_FAST16_MIN 0UL +#define DUK_UINT_FAST16_MAX 0xffffUL +#define DUK_INT_FAST16_MIN (-0x7fffL - 1L) +#define DUK_INT_FAST16_MAX 0x7fffL +#define DUK_UINT32_MIN 0UL +#define DUK_UINT32_MAX 0xffffffffUL +#define DUK_INT32_MIN (-0x7fffffffL - 1L) +#define DUK_INT32_MAX 0x7fffffffL +#define DUK_UINT_LEAST32_MIN 0UL +#define DUK_UINT_LEAST32_MAX 0xffffffffUL +#define DUK_INT_LEAST32_MIN (-0x7fffffffL - 1L) +#define DUK_INT_LEAST32_MAX 0x7fffffffL +#define DUK_UINT_FAST32_MIN 0UL +#define DUK_UINT_FAST32_MAX 0xffffffffUL +#define DUK_INT_FAST32_MIN (-0x7fffffffL - 1L) +#define DUK_INT_FAST32_MAX 0x7fffffffL + +/* 64-bit constants. Since LL / ULL constants are not always available, + * use computed values. These values can't be used in preprocessor + * comparisons; flag them as such. + */ +#if defined(DUK_F_HAVE_64BIT) +#define DUK_UINT64_MIN ((duk_uint64_t) 0) +#define DUK_UINT64_MAX ((duk_uint64_t) -1) +#define DUK_INT64_MIN ((duk_int64_t) (~(DUK_UINT64_MAX >> 1))) +#define DUK_INT64_MAX ((duk_int64_t) (DUK_UINT64_MAX >> 1)) +#define DUK_UINT_LEAST64_MIN DUK_UINT64_MIN +#define DUK_UINT_LEAST64_MAX DUK_UINT64_MAX +#define DUK_INT_LEAST64_MIN DUK_INT64_MIN +#define DUK_INT_LEAST64_MAX DUK_INT64_MAX +#define DUK_UINT_FAST64_MIN DUK_UINT64_MIN +#define DUK_UINT_FAST64_MAX DUK_UINT64_MAX +#define DUK_INT_FAST64_MIN DUK_INT64_MIN +#define DUK_INT_FAST64_MAX DUK_INT64_MAX +#define DUK_UINT64_MIN_COMPUTED +#define DUK_UINT64_MAX_COMPUTED +#define DUK_INT64_MIN_COMPUTED +#define DUK_INT64_MAX_COMPUTED +#define DUK_UINT_LEAST64_MIN_COMPUTED +#define DUK_UINT_LEAST64_MAX_COMPUTED +#define DUK_INT_LEAST64_MIN_COMPUTED +#define DUK_INT_LEAST64_MAX_COMPUTED +#define DUK_UINT_FAST64_MIN_COMPUTED +#define DUK_UINT_FAST64_MAX_COMPUTED +#define DUK_INT_FAST64_MIN_COMPUTED +#define DUK_INT_FAST64_MAX_COMPUTED +#endif + +#if defined(DUK_F_HAVE_64BIT) +#define DUK_UINTMAX_MIN DUK_UINT64_MIN +#define DUK_UINTMAX_MAX DUK_UINT64_MAX +#define DUK_INTMAX_MIN DUK_INT64_MIN +#define DUK_INTMAX_MAX DUK_INT64_MAX +#define DUK_UINTMAX_MIN_COMPUTED +#define DUK_UINTMAX_MAX_COMPUTED +#define DUK_INTMAX_MIN_COMPUTED +#define DUK_INTMAX_MAX_COMPUTED +#else +#define DUK_UINTMAX_MIN 0UL +#define DUK_UINTMAX_MAX 0xffffffffUL +#define DUK_INTMAX_MIN (-0x7fffffffL - 1L) +#define DUK_INTMAX_MAX 0x7fffffffL +#endif + +/* This detection is not very reliable. */ +#if defined(DUK_F_32BIT_PTRS) +typedef duk_int32_t duk_intptr_t; +typedef duk_uint32_t duk_uintptr_t; +#define DUK_UINTPTR_MIN DUK_UINT32_MIN +#define DUK_UINTPTR_MAX DUK_UINT32_MAX +#define DUK_INTPTR_MIN DUK_INT32_MIN +#define DUK_INTPTR_MAX DUK_INT32_MAX +#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT) +typedef duk_int64_t duk_intptr_t; +typedef duk_uint64_t duk_uintptr_t; +#define DUK_UINTPTR_MIN DUK_UINT64_MIN +#define DUK_UINTPTR_MAX DUK_UINT64_MAX +#define DUK_INTPTR_MIN DUK_INT64_MIN +#define DUK_INTPTR_MAX DUK_INT64_MAX +#define DUK_UINTPTR_MIN_COMPUTED +#define DUK_UINTPTR_MAX_COMPUTED +#define DUK_INTPTR_MIN_COMPUTED +#define DUK_INTPTR_MAX_COMPUTED +#else +#error cannot determine intptr type +#endif + +/* SIZE_MAX may be missing so use an approximate value for it. */ +#undef DUK_SIZE_MAX_COMPUTED +#if !defined(SIZE_MAX) +#define DUK_SIZE_MAX_COMPUTED +#define SIZE_MAX ((size_t) (-1)) +#endif +#define DUK_SIZE_MIN 0 +#define DUK_SIZE_MAX SIZE_MAX + +#endif /* C99 types */ + +/* A few types are assumed to always exist. */ +typedef size_t duk_size_t; +typedef ptrdiff_t duk_ptrdiff_t; + +/* The best type for an "all around int" in Duktape internals is "at least + * 32 bit signed integer" which is most convenient. Same for unsigned type. + * Prefer 'int' when large enough, as it is almost always a convenient type. + */ +#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL) +typedef int duk_int_t; +typedef unsigned int duk_uint_t; +#define DUK_INT_MIN INT_MIN +#define DUK_INT_MAX INT_MAX +#define DUK_UINT_MIN 0 +#define DUK_UINT_MAX UINT_MAX +#else +typedef duk_int_fast32_t duk_int_t; +typedef duk_uint_fast32_t duk_uint_t; +#define DUK_INT_MIN DUK_INT_FAST32_MIN +#define DUK_INT_MAX DUK_INT_FAST32_MAX +#define DUK_UINT_MIN DUK_UINT_FAST32_MIN +#define DUK_UINT_MAX DUK_UINT_FAST32_MAX +#endif + +/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this + * distinction matters for the CPU. These types are used mainly in the + * executor where it might really matter. + */ +typedef duk_int_fast32_t duk_int_fast_t; +typedef duk_uint_fast32_t duk_uint_fast_t; +#define DUK_INT_FAST_MIN DUK_INT_FAST32_MIN +#define DUK_INT_FAST_MAX DUK_INT_FAST32_MAX +#define DUK_UINT_FAST_MIN DUK_UINT_FAST32_MIN +#define DUK_UINT_FAST_MAX DUK_UINT_FAST32_MAX + +/* Small integers (16 bits or more) can fall back to the 'int' type, but + * have a typedef so they are marked "small" explicitly. + */ +typedef int duk_small_int_t; +typedef unsigned int duk_small_uint_t; +#define DUK_SMALL_INT_MIN INT_MIN +#define DUK_SMALL_INT_MAX INT_MAX +#define DUK_SMALL_UINT_MIN 0 +#define DUK_SMALL_UINT_MAX UINT_MAX + +/* Fast variants of small integers, again for really fast paths like the + * executor. + */ +typedef duk_int_fast16_t duk_small_int_fast_t; +typedef duk_uint_fast16_t duk_small_uint_fast_t; +#define DUK_SMALL_INT_FAST_MIN DUK_INT_FAST16_MIN +#define DUK_SMALL_INT_FAST_MAX DUK_INT_FAST16_MAX +#define DUK_SMALL_UINT_FAST_MIN DUK_UINT_FAST16_MIN +#define DUK_SMALL_UINT_FAST_MAX DUK_UINT_FAST16_MAX + +/* Boolean values are represented with the platform 'int'. */ +typedef duk_small_int_t duk_bool_t; +#define DUK_BOOL_MIN DUK_SMALL_INT_MIN +#define DUK_BOOL_MAX DUK_SMALL_INT_MAX + +/* Index values must have at least 32-bit signed range. */ +typedef duk_int_t duk_idx_t; +#define DUK_IDX_MIN DUK_INT_MIN +#define DUK_IDX_MAX DUK_INT_MAX + +/* Array index values, could be exact 32 bits. + * Currently no need for signed duk_arridx_t. + */ +typedef duk_uint_t duk_uarridx_t; +#define DUK_UARRIDX_MIN DUK_UINT_MIN +#define DUK_UARRIDX_MAX DUK_UINT_MAX + +/* Duktape/C function return value, platform int is enough for now to + * represent 0, 1, or negative error code. Must be compatible with + * assigning truth values (e.g. duk_ret_t rc = (foo == bar);). + */ +typedef duk_small_int_t duk_ret_t; +#define DUK_RET_MIN DUK_SMALL_INT_MIN +#define DUK_RET_MAX DUK_SMALL_INT_MAX + +/* Error codes are represented with platform int. High bits are used + * for flags and such, so 32 bits are needed. + */ +typedef duk_int_t duk_errcode_t; +#define DUK_ERRCODE_MIN DUK_INT_MIN +#define DUK_ERRCODE_MAX DUK_INT_MAX + +/* Codepoint type. Must be 32 bits or more because it is used also for + * internal codepoints. The type is signed because negative codepoints + * are used as internal markers (e.g. to mark EOF or missing argument). + * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to + * ensure duk_uint32_t casts back and forth nicely. Almost everything + * else uses the signed one. + */ +typedef duk_int_t duk_codepoint_t; +typedef duk_uint_t duk_ucodepoint_t; +#define DUK_CODEPOINT_MIN DUK_INT_MIN +#define DUK_CODEPOINT_MAX DUK_INT_MAX +#define DUK_UCODEPOINT_MIN DUK_UINT_MIN +#define DUK_UCODEPOINT_MAX DUK_UINT_MAX + +/* IEEE float/double typedef. */ +typedef float duk_float_t; +typedef double duk_double_t; + +/* We're generally assuming that we're working on a platform with a 32-bit + * address space. If DUK_SIZE_MAX is a typecast value (which is necessary + * if SIZE_MAX is missing), the check must be avoided because the + * preprocessor can't do a comparison. + */ +#if !defined(DUK_SIZE_MAX) +#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX +#elif !defined(DUK_SIZE_MAX_COMPUTED) +#if DUK_SIZE_MAX < 0xffffffffUL +/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value + * which seems incorrect if size_t is (at least) an unsigned 32-bit type. + * However, it doesn't seem useful to error out compilation if this is the + * case. + */ +#endif +#endif + +/* Type for public API calls. */ +typedef struct duk_hthread duk_context; + +/* + * Check whether we should use 64-bit integers + */ + +/* Quite incomplete now. Use 64-bit types if detected (C99 or other detection) + * unless they are known to be unreliable. For instance, 64-bit types are + * available on VBCC but seem to misbehave. + */ +#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC) +#define DUK_USE_64BIT_OPS +#else +#undef DUK_USE_64BIT_OPS +#endif + +/* + * 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. + */ + +#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 +#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 +#endif +#endif + +/* Compiler specific hackery needed to force struct size to match aligment, + * see e.g. duk_hbuffer.h. + * + * http://stackoverflow.com/questions/11130109/c-struct-size-alignment + * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment + */ +#if defined(DUK_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 +#endif + +#ifdef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE +#define DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS +#else +#undef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS +#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 +#endif + +/* + * Byte order and double memory layout detection + * + * Endianness detection is a major portability hassle because the macros + * and headers are not standardized. There's even variance across UNIX + * platforms. Even with "standard" headers, details like underscore count + * varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used + * (Crossbridge has a single underscore, for instance). + * + * The checks below are structured with this in mind: several approaches are + * used, and at the end we check if any of them worked. This allows generic + * approaches to be tried first, and platform/compiler specific hacks tried + * last. As a last resort, the user can force a specific endianness, as it's + * not likely that automatic detection will work on the most exotic platforms. + * + * Duktape supports little and big endian machines. There's also support + * for a hybrid used by some ARM machines where integers are little endian + * but IEEE double values use a mixed order (12345678 -> 43218765). This + * byte order for doubles is referred to as "mixed endian". + */ + +#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 + */ + +/* For custom platforms allow user to define byteorder explicitly. + * Since endianness headers are not standardized, this is a useful + * workaround for custom platforms for which endianness detection + * is not directly supported. Perhaps custom hardware is used and + * user cannot submit upstream patches. + */ +#if defined(DUK_OPT_FORCE_BYTEORDER) +#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 +#else +#error invalid DUK_OPT_FORCE_BYTEORDER value +#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 +#endif +#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 +#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 - + * | 0 | 1 | 2 | ..... + * ^-- p=3, points after last valid byte (2) + * + * 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). + */ +#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 + */ +#if defined(DUK_F_UCLIBC) +#define DUK_MEMCPY memmove +#else +#define DUK_MEMCPY memcpy +#endif + +#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 + +#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 + */ +#define DUK_SNPRINTF _snprintf +#else +#define DUK_SNPRINTF snprintf +#endif + +#define DUK_VSPRINTF vsprintf + +#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 +#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)) + +/* + * 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. + */ + +#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. + * This is not the case on all platforms (it may be a single-array element, + * for instance). + */ +#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0) +#endif + +/* + * 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_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"). + */ +#define DUK_NORETURN(decl) decl +#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_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) +#endif +#else +/* unknown */ +#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 */ +#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) + */ +#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) +#endif +#endif /* DUK_USE_BRANCH_HINTS */ + +#if !defined(DUK_LIKELY) +#define DUK_LIKELY(x) (x) +#endif +#if !defined(DUK_UNLIKELY) +#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 + +/* + * 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 +#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 +#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_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 +#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_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. */ +#define DUK_LOCAL_DECL static +#define DUK_LOCAL static + +/* + * __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). + */ + +#define DUK_FILE_MACRO __FILE__ + +#define DUK_LINE_MACRO __LINE__ + +#if !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) +#define DUK_FUNC_MACRO __func__ +#else +#define DUK_FUNC_MACRO "unknown" +#endif + +/* + * Byteswap macros + * + * These are here so that inline assembly or other platform functions can be + * used if available. + */ + +#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)) + +#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 + */ + +#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" +#else +#define DUK_USE_OS_STRING "ios-unknown" +#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" +#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" +#endif + +/* + * Long control transfer, setjmp/longjmp or alternatives + * + * Signal mask is not saved (when that can be communicated to the platform) + */ + +/* dummy non-zero value to be used as an argument for longjmp(), see man longjmp */ +#define DUK_LONGJMP_DUMMY_VALUE 1 + +#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 +#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 +#endif + +/* + * Target info string + */ + +#if defined(DUK_OPT_TARGET_INFO) +#define DUK_USE_TARGET_INFO DUK_OPT_TARGET_INFO +#else +#define DUK_USE_TARGET_INFO "unknown" +#endif + +/* + * Speed/size and other performance options + */ + +/* 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 + +/* 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 + +/* 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. + */ +#define DUK_USE_PREFER_SIZE + +/* Use a sliding window for lexer; slightly larger footprint, slightly faster. */ +#define DUK_USE_LEXER_SLIDING_WINDOW + +/* + * Tagged type representation (duk_tval) + */ + +#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 +#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 +#endif +#define DUK_USE_FASTINT +#endif + +/* + * Memory management options + */ + +#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_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? + */ +#endif + +#if defined(DUK_OPT_NO_MARK_AND_SWEEP) +#undef DUK_USE_MARK_AND_SWEEP +#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 +#endif +#endif + +#if !defined(DUK_USE_MARK_AND_SWEEP) && !defined(DUK_USE_REFERENCE_COUNTING) +#error must have either mark-and-sweep or reference counting enabled +#endif + +#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE) +#undef DUK_USE_MS_STRINGTABLE_RESIZE +#endif + +#undef DUK_USE_GC_TORTURE +#if defined(DUK_OPT_GC_TORTURE) +#define DUK_USE_GC_TORTURE +#endif + +/* + * String table options + */ + +#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 +#else +/* Default algorithm: open addressing (probing) */ +#define DUK_USE_STRTAB_PROBE +#endif + +/* + * Error handling options + */ + +#define DUK_USE_AUGMENT_ERROR_CREATE +#define DUK_USE_AUGMENT_ERROR_THROW +#define DUK_USE_TRACEBACKS +#define DUK_USE_ERRCREATE +#define DUK_USE_ERRTHROW + +#define DUK_USE_VERBOSE_ERRORS + +#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 +#endif + +#if defined(DUK_OPT_NO_VERBOSE_ERRORS) +#undef DUK_USE_VERBOSE_ERRORS +#endif + +#if defined(DUK_USE_TRACEBACKS) +#if defined(DUK_OPT_TRACEBACK_DEPTH) +#define DUK_USE_TRACEBACK_DEPTH DUK_OPT_TRACEBACK_DEPTH +#else +#define DUK_USE_TRACEBACK_DEPTH 10 +#endif +#endif + +/* Include messages in executor internal errors. */ +#define DUK_USE_VERBOSE_EXECUTOR_ERRORS + +/* + * Execution and debugger options + */ + +#undef DUK_USE_INTERRUPT_COUNTER +#if defined(DUK_OPT_INTERRUPT_COUNTER) +#define DUK_USE_INTERRUPT_COUNTER +#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)) +#endif + +#undef DUK_USE_DEBUGGER_SUPPORT +#if defined(DUK_OPT_DEBUGGER_SUPPORT) +#define DUK_USE_DEBUGGER_SUPPORT +#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 +#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 +#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 +#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 +#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_DEBUG +#undef DUK_USE_DPRINT +#undef DUK_USE_DDPRINT +#undef DUK_USE_DDDPRINT +#undef DUK_USE_DPRINT_RDTSC +#undef DUK_USE_ASSERTIONS + +/* 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 +#endif + +#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DPRINT) +#define DUK_USE_DPRINT +#endif +#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDPRINT) +#define DUK_USE_DDPRINT +#endif +#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDDPRINT) +#define DUK_USE_DDDPRINT +#endif + +#undef DUK_USE_DPRINT_COLORS +#if defined(DUK_OPT_DPRINT_COLORS) +#define DUK_USE_DPRINT_COLORS +#endif + +#if defined(DUK_USE_RDTSC) && defined(DUK_OPT_DPRINT_RDTSC) +#define DUK_USE_DPRINT_RDTSC +#else +#undef DUK_USE_DPRINT_RDTSC +#endif + +#if defined(DUK_OPT_ASSERTIONS) +#define DUK_USE_ASSERTIONS +#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 +#else +#define DUK_USE_DEBUG_BUFSIZE 65536L +#endif + +/* + * Ecmascript features / compliance options + */ + +#if defined(DUK_F_BCC) +/* Math built-in is stubbed out on BCC to allow compiler torture testing. */ +#else +#define DUK_USE_MATH_BUILTIN +#endif + +#define DUK_USE_STRICT_DECL +#if defined(DUK_OPT_NO_STRICT_DECL) +#undef DUK_USE_STRICT_DECL +#endif + +#define DUK_USE_REGEXP_SUPPORT +#if defined(DUK_OPT_NO_REGEXP_SUPPORT) +#undef DUK_USE_REGEXP_SUPPORT +#endif + +#undef DUK_USE_STRICT_UTF8_SOURCE +#if defined(DUK_OPT_STRICT_UTF8_SOURCE) +#define DUK_USE_STRICT_UTF8_SOURCE +#endif + +#define DUK_USE_OCTAL_SUPPORT +#if defined(DUK_OPT_NO_OCTAL_SUPPORT) +#undef DUK_USE_OCTAL_SUPPORT +#endif + +#define DUK_USE_SOURCE_NONBMP +#if defined(DUK_OPT_NO_SOURCE_NONBMP) +#undef DUK_USE_SOURCE_NONBMP +#endif + +#define DUK_USE_BROWSER_LIKE +#if defined(DUK_OPT_NO_BROWSER_LIKE) +#undef DUK_USE_BROWSER_LIKE +#endif + +/* E5/E5.1 Section B features. */ +#define DUK_USE_SECTION_B +#if defined(DUK_OPT_NO_SECTION_B) +#undef DUK_USE_SECTION_B +#endif + +/* Non-standard regexp parsing features. */ +#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE + +/* 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 +#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 +#endif + +/* Array.prototype.concat() non-standard but real world compatible behavior + * for non-existent trailing elements. + */ +#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER +#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER) +#undef DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER +#endif + +/* Array.prototype.map() non-standard but real world compatible behavior + * for non-existent trailing elements. + */ +#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER +#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER) +#undef 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 +#endif + +/* Record pc-to-line information. */ +#define DUK_USE_PC2LINE +#if defined(DUK_OPT_NO_PC2LINE) +#undef DUK_USE_PC2LINE +#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 +#endif + +/* CommonJS modules */ +#define DUK_USE_COMMONJS_MODULES +#if defined(DUK_OPT_NO_COMMONJS_MODULES) +#undef DUK_USE_COMMONJS_MODULES +#endif + +/* Additional key argument to setter/getter calls when triggered by property + * accesses. + */ + +#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT +#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT +#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT) +#undef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT +#undef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT +#endif + +/* JSON escaping of U+2028 and U+2029. + */ + +#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029 +#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029) +#undef 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 +#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 +#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 +#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 +#endif + +/* + * Deep vs. shallow stack. + * + * Some embedded platforms have very shallow stack (e.g. 64kB); default to + * a shallow stack on unknown platforms or known embedded platforms. + */ + +#if defined(DUK_F_LINUX) || defined(DUK_F_BSD) || defined(DUK_F_WINDOWS) || \ + defined(DUK_F_APPLE) || defined(DUK_OPT_DEEP_C_STACK) +#define DUK_USE_DEEP_C_STACK +#else +#undef DUK_USE_DEEP_C_STACK +#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 +#endif + +/* + * User panic handler, panic exit behavior for default panic handler + */ + +#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 +#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 +#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 +#endif + +/* + * Codecs + */ + +#define DUK_USE_JX +#if defined(DUK_OPT_NO_JX) +#undef DUK_USE_JX +#endif + +#define DUK_USE_JC +#if defined(DUK_OPT_NO_JC) +#undef DUK_USE_JC +#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) +#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 +#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)) +#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)) +#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 +#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)) +#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)) +#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)) +#endif + +#undef DUK_USE_REFCOUNT16 +#if defined(DUK_OPT_REFCOUNT16) +#define DUK_USE_REFCOUNT16 +#endif + +#undef DUK_USE_STRHASH16 +#if defined(DUK_OPT_STRHASH16) +#define DUK_USE_STRHASH16 +#endif + +#undef DUK_USE_STRLEN16 +#if defined(DUK_OPT_STRLEN16) +#define DUK_USE_STRLEN16 +#endif + +#undef DUK_USE_BUFLEN16 +#if defined(DUK_OPT_BUFLEN16) +#define DUK_USE_BUFLEN16 +#endif + +#undef DUK_USE_OBJSIZES16 +#if defined(DUK_OPT_OBJSIZES16) +#define DUK_USE_OBJSIZES16 +#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 +#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 +#endif + +#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS +#undef DUK_USE_EXPLICIT_NULL_INIT + +#if !defined(DUK_USE_PACKED_TVAL) +#define DUK_USE_EXPLICIT_NULL_INIT +#endif + +#define DUK_USE_ZERO_BUFFER_DATA +#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA) +#undef DUK_USE_ZERO_BUFFER_DATA +#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 +#endif +#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] + */ + +/* 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 +#else +#define DUK_USE_FLEX_ONESIZE +#endif + +/* + * GCC pragmas + */ + +/* 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 +#else +#undef DUK_USE_GCC_PRAGMAS +#endif + +/* + * Date provider selection + * + * User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll + * rely on an external provider. If this is not done, revert to previous + * behavior and use Unix/Windows built-in provider. + */ + +#if defined(DUK_COMPILING_DUKTAPE) + +#if defined(DUK_USE_DATE_GET_NOW) +/* External provider already defined. */ +#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY) +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() +#endif + +#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET) +/* External provider already defined. */ +#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME) +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() +#endif + +#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. */ +#endif + +#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 +/* No provider for DUK_USE_DATE_FORMAT_STRING(), fall back to ISO 8601 only. */ +#endif + +#endif /* DUK_COMPILING_DUKTAPE */ + +/* + * User declarations + */ + +#if defined(DUK_OPT_DECLARE) +#define DUK_USE_USER_DECLARE() DUK_OPT_DECLARE +#else +#define DUK_USE_USER_DECLARE() /* no user declarations */ +#endif + +/* + * Autogenerated defaults + */ + +#undef DUK_USE_DATE_PRS_GETDATE +#undef DUK_USE_INTEGER_ME +#define DUK_USE_JSON_DECNUMBER_FASTPATH +#define DUK_USE_JSON_DECSTRING_FASTPATH +#define DUK_USE_JSON_EATWHITE_FASTPATH +#define DUK_USE_JSON_QUOTESTRING_FASTPATH +#undef DUK_USE_JSON_STRINGIFY_FASTPATH + +/* + * Alternative customization header + * + * If you want to modify the final DUK_USE_xxx flags directly (without + * using the available DUK_OPT_xxx flags), define DUK_OPT_HAVE_CUSTOM_H + * and tweak the final flags there. + */ + +#if defined(DUK_OPT_HAVE_CUSTOM_H) +#include "duk_custom.h" +#endif + +/* + * You may add overriding #define/#undef directives below for + * customization. You of course cannot un-#include or un-typedef + * anything; these require direct changes above. + */ + +/* __OVERRIDE_DEFINES__ */ + +/* + * 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. + */ + +#if defined(DUK_OPT_NO_FUNC_STMT) +#error DUK_OPT_NO_FUNC_STMT is deprecated, use DUK_OPT_NO_NONSTD_FUNC_STMT +#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 +#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 +#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 +#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 +#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 +#endif + +#if defined(DUK_OPT_NO_JSONX) +#error DUK_OPT_NO_JSONX is deprecated, use DUK_OPT_NO_JX +#endif + +#if defined(DUK_OPT_NO_JSONC) +#error DUK_OPT_NO_JSONC is deprecated, use DUK_OPT_NO_JC +#endif + +/* + * Debug print consistency + */ + +#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG) +#error DUK_USE_DPRINT without DUK_USE_DEBUG +#endif + +#if defined(DUK_USE_DDPRINT) && !defined(DUK_USE_DEBUG) +#error DUK_USE_DDPRINT without DUK_USE_DEBUG +#endif + +#if defined(DUK_USE_DDDPRINT) && !defined(DUK_USE_DEBUG) +#error DUK_USE_DDDPRINT without DUK_USE_DEBUG +#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 +#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 +#endif +#if !defined(DUK_USE_PC2LINE) +#error DUK_USE_PC2LINE is needed when debugger support is enabled +#endif +#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 +#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 +#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 +#endif +#endif + +#if defined(DUK_USE_STRTAB_CHAIN) && defined(DUK_USE_STRTAB_PROBE) +#error both DUK_USE_STRTAB_CHAIN and DUK_USE_STRTAB_PROBE defined +#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 +#endif + +#endif /* DUK_CONFIG_H_INCLUDED */ diff --git a/javascript/duktape/duktape.c b/javascript/duktape/duktape.c index b05b95c39..d3133f578 100644 --- a/javascript/duktape/duktape.c +++ b/javascript/duktape/duktape.c @@ -1,6 +1,6 @@ /* - * Single file autogenerated distributable for Duktape 1.2.3. - * Git commit 0605a18660dbae486c62a42a33fabd034c8623ff (v1.2.3). + * Single file autogenerated distributable for Duktape 1.2.99. + * Git commit 2a41d0a38eef5edfe8691cf09427b6ee8a3ad5c9 (v1.2.0-310-g2a41d0a). * * See Duktape AUTHORS.rst and LICENSE.txt for copyright and * licensing information. @@ -33,7 +33,6 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. -* */ /* AUTHORS.rst */ /* @@ -62,6 +61,7 @@ * * Andreas \u00d6man * * L\u00e1szl\u00f3 Lang\u00f3 * * Legimet +* * Karl Skomski * * Other contributions * =================== @@ -86,7 +86,7 @@ * * Josh Engebretson (https://github.com/JoshEngebretson) * * Remo Eichenberger (https://github.com/remoe) * * Mamod Mehyar (https://github.com/mamod) -* * David Demelier (https://github.com/hftmarkand) +* * David Demelier (https://github.com/markand) * * Tim Caswell (https://github.com/creationix) * * Mitchell Blank Jr (https://github.com/mitchblank) * * https://github.com/yushli @@ -96,6 +96,8 @@ * * Bruce E. Pascoe (https://github.com/fatcerberus) * * https://github.com/Kelledin * * https://github.com/sstruchtrup +* * Michael Drake (https://github.com/tlsa) +* * https://github.com/chris-y * * If you are accidentally missing from this list, send me an e-mail * (``sami.vaarala@iki.fi``) and I'll fix the omission. @@ -130,7 +132,7 @@ /* * User declarations, e.g. prototypes for user functions used by Duktape - * macros. Concretely, if DUK_OPT_PANIC_HANDLER is used and the macro + * macros. Concretely, if DUK_USE_PANIC_HANDLER is used and the macro * value calls a user function, it needs to be declared for Duktape * compilation to avoid warnings. */ @@ -219,6 +221,7 @@ struct duk_hobject; struct duk_hcompiledfunction; struct duk_hnativefunction; struct duk_hthread; +struct duk_hbufferobject; struct duk_hbuffer; struct duk_hbuffer_fixed; struct duk_hbuffer_dynamic; @@ -242,11 +245,13 @@ struct duk_fixedbuffer; struct duk_bitdecoder_ctx; struct duk_bitencoder_ctx; +struct duk_bufwriter_ctx; struct duk_token; struct duk_re_token; struct duk_lexer_point; struct duk_lexer_ctx; +struct duk_lexer_codepoint; struct duk_compiler_instr; struct duk_compiler_func; @@ -265,6 +270,7 @@ typedef struct duk_hstring_external duk_hstring_external; typedef struct duk_hobject duk_hobject; typedef struct duk_hcompiledfunction duk_hcompiledfunction; typedef struct duk_hnativefunction duk_hnativefunction; +typedef struct duk_hbufferobject duk_hbufferobject; typedef struct duk_hthread duk_hthread; typedef struct duk_hbuffer duk_hbuffer; typedef struct duk_hbuffer_fixed duk_hbuffer_fixed; @@ -289,11 +295,13 @@ typedef struct duk_fixedbuffer duk_fixedbuffer; typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx; typedef struct duk_bitencoder_ctx duk_bitencoder_ctx; +typedef struct duk_bufwriter_ctx duk_bufwriter_ctx; typedef struct duk_token duk_token; typedef struct duk_re_token duk_re_token; typedef struct duk_lexer_point duk_lexer_point; typedef struct duk_lexer_ctx duk_lexer_ctx; +typedef struct duk_lexer_codepoint duk_lexer_codepoint; typedef struct duk_compiler_instr duk_compiler_instr; typedef struct duk_compiler_func duk_compiler_func; @@ -313,348 +321,426 @@ typedef struct duk_re_compiler_ctx duk_re_compiler_ctx; #if defined(DUK_USE_DOUBLE_LE) #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; +DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_STRDATA_DATA_LENGTH 1943 +#define DUK_STRDATA_DATA_LENGTH 2624 #define DUK_STRDATA_MAX_STRLEN 24 #define DUK_STRIDX_UC_LOGGER 0 /* 'Logger' */ #define DUK_STRIDX_UC_THREAD 1 /* 'Thread' */ #define DUK_STRIDX_UC_POINTER 2 /* 'Pointer' */ -#define DUK_STRIDX_UC_BUFFER 3 /* 'Buffer' */ -#define DUK_STRIDX_DEC_ENV 4 /* 'DecEnv' */ -#define DUK_STRIDX_OBJ_ENV 5 /* 'ObjEnv' */ -#define DUK_STRIDX_EMPTY_STRING 6 /* '' */ -#define DUK_STRIDX_GLOBAL 7 /* 'global' */ -#define DUK_STRIDX_UC_ARGUMENTS 8 /* 'Arguments' */ -#define DUK_STRIDX_JSON 9 /* 'JSON' */ -#define DUK_STRIDX_MATH 10 /* 'Math' */ -#define DUK_STRIDX_UC_ERROR 11 /* 'Error' */ -#define DUK_STRIDX_REG_EXP 12 /* 'RegExp' */ -#define DUK_STRIDX_DATE 13 /* 'Date' */ -#define DUK_STRIDX_UC_NUMBER 14 /* 'Number' */ -#define DUK_STRIDX_UC_BOOLEAN 15 /* 'Boolean' */ -#define DUK_STRIDX_UC_STRING 16 /* 'String' */ -#define DUK_STRIDX_ARRAY 17 /* 'Array' */ -#define DUK_STRIDX_UC_FUNCTION 18 /* 'Function' */ -#define DUK_STRIDX_UC_OBJECT 19 /* 'Object' */ -#define DUK_STRIDX_UC_NULL 20 /* 'Null' */ -#define DUK_STRIDX_UC_UNDEFINED 21 /* 'Undefined' */ -#define DUK_STRIDX_JSON_EXT_FUNCTION2 22 /* '{_func:true}' */ -#define DUK_STRIDX_JSON_EXT_FUNCTION1 23 /* '{"_func":true}' */ -#define DUK_STRIDX_JSON_EXT_NEGINF 24 /* '{"_ninf":true}' */ -#define DUK_STRIDX_JSON_EXT_POSINF 25 /* '{"_inf":true}' */ -#define DUK_STRIDX_JSON_EXT_NAN 26 /* '{"_nan":true}' */ -#define DUK_STRIDX_JSON_EXT_UNDEFINED 27 /* '{"_undef":true}' */ -#define DUK_STRIDX_TO_LOG_STRING 28 /* 'toLogString' */ -#define DUK_STRIDX_CLOG 29 /* 'clog' */ -#define DUK_STRIDX_LC_L 30 /* 'l' */ -#define DUK_STRIDX_LC_N 31 /* 'n' */ -#define DUK_STRIDX_LC_FATAL 32 /* 'fatal' */ -#define DUK_STRIDX_LC_ERROR 33 /* 'error' */ -#define DUK_STRIDX_LC_WARN 34 /* 'warn' */ -#define DUK_STRIDX_LC_DEBUG 35 /* 'debug' */ -#define DUK_STRIDX_LC_TRACE 36 /* 'trace' */ -#define DUK_STRIDX_RAW 37 /* 'raw' */ -#define DUK_STRIDX_FMT 38 /* 'fmt' */ -#define DUK_STRIDX_CURRENT 39 /* 'current' */ -#define DUK_STRIDX_RESUME 40 /* 'resume' */ -#define DUK_STRIDX_COMPACT 41 /* 'compact' */ -#define DUK_STRIDX_JC 42 /* 'jc' */ -#define DUK_STRIDX_JX 43 /* 'jx' */ -#define DUK_STRIDX_BASE64 44 /* 'base64' */ -#define DUK_STRIDX_HEX 45 /* 'hex' */ -#define DUK_STRIDX_DEC 46 /* 'dec' */ -#define DUK_STRIDX_ENC 47 /* 'enc' */ -#define DUK_STRIDX_FIN 48 /* 'fin' */ -#define DUK_STRIDX_GC 49 /* 'gc' */ -#define DUK_STRIDX_ACT 50 /* 'act' */ -#define DUK_STRIDX_LC_INFO 51 /* 'info' */ -#define DUK_STRIDX_VERSION 52 /* 'version' */ -#define DUK_STRIDX_ENV 53 /* 'env' */ -#define DUK_STRIDX_MOD_LOADED 54 /* 'modLoaded' */ -#define DUK_STRIDX_MOD_SEARCH 55 /* 'modSearch' */ -#define DUK_STRIDX_ERR_THROW 56 /* 'errThrow' */ -#define DUK_STRIDX_ERR_CREATE 57 /* 'errCreate' */ -#define DUK_STRIDX_COMPILE 58 /* 'compile' */ -#define DUK_STRIDX_INT_REGBASE 59 /* '\x00Regbase' */ -#define DUK_STRIDX_INT_THREAD 60 /* '\x00Thread' */ -#define DUK_STRIDX_INT_HANDLER 61 /* '\x00Handler' */ -#define DUK_STRIDX_INT_FINALIZER 62 /* '\x00Finalizer' */ -#define DUK_STRIDX_INT_CALLEE 63 /* '\x00Callee' */ -#define DUK_STRIDX_INT_MAP 64 /* '\x00Map' */ -#define DUK_STRIDX_INT_ARGS 65 /* '\x00Args' */ -#define DUK_STRIDX_INT_THIS 66 /* '\x00This' */ -#define DUK_STRIDX_INT_PC2LINE 67 /* '\x00Pc2line' */ -#define DUK_STRIDX_INT_SOURCE 68 /* '\x00Source' */ -#define DUK_STRIDX_INT_VARENV 69 /* '\x00Varenv' */ -#define DUK_STRIDX_INT_LEXENV 70 /* '\x00Lexenv' */ -#define DUK_STRIDX_INT_VARMAP 71 /* '\x00Varmap' */ -#define DUK_STRIDX_INT_FORMALS 72 /* '\x00Formals' */ -#define DUK_STRIDX_INT_BYTECODE 73 /* '\x00Bytecode' */ -#define DUK_STRIDX_INT_NEXT 74 /* '\x00Next' */ -#define DUK_STRIDX_INT_TARGET 75 /* '\x00Target' */ -#define DUK_STRIDX_INT_VALUE 76 /* '\x00Value' */ -#define DUK_STRIDX_LC_POINTER 77 /* 'pointer' */ -#define DUK_STRIDX_LC_BUFFER 78 /* 'buffer' */ -#define DUK_STRIDX_INT_TRACEDATA 79 /* '\x00Tracedata' */ -#define DUK_STRIDX_LINE_NUMBER 80 /* 'lineNumber' */ -#define DUK_STRIDX_FILE_NAME 81 /* 'fileName' */ -#define DUK_STRIDX_PC 82 /* 'pc' */ -#define DUK_STRIDX_STACK 83 /* 'stack' */ -#define DUK_STRIDX_THROW_TYPE_ERROR 84 /* 'ThrowTypeError' */ -#define DUK_STRIDX_DUKTAPE 85 /* 'Duktape' */ -#define DUK_STRIDX_ID 86 /* 'id' */ -#define DUK_STRIDX_REQUIRE 87 /* 'require' */ -#define DUK_STRIDX___PROTO__ 88 /* '__proto__' */ -#define DUK_STRIDX_SET_PROTOTYPE_OF 89 /* 'setPrototypeOf' */ -#define DUK_STRIDX_OWN_KEYS 90 /* 'ownKeys' */ -#define DUK_STRIDX_ENUMERATE 91 /* 'enumerate' */ -#define DUK_STRIDX_DELETE_PROPERTY 92 /* 'deleteProperty' */ -#define DUK_STRIDX_HAS 93 /* 'has' */ -#define DUK_STRIDX_PROXY 94 /* 'Proxy' */ -#define DUK_STRIDX_CALLEE 95 /* 'callee' */ -#define DUK_STRIDX_INVALID_DATE 96 /* 'Invalid Date' */ -#define DUK_STRIDX_BRACKETED_ELLIPSIS 97 /* '[...]' */ -#define DUK_STRIDX_NEWLINE_TAB 98 /* '\n\t' */ -#define DUK_STRIDX_SPACE 99 /* ' ' */ -#define DUK_STRIDX_COMMA 100 /* ',' */ -#define DUK_STRIDX_MINUS_ZERO 101 /* '-0' */ -#define DUK_STRIDX_PLUS_ZERO 102 /* '+0' */ -#define DUK_STRIDX_ZERO 103 /* '0' */ -#define DUK_STRIDX_MINUS_INFINITY 104 /* '-Infinity' */ -#define DUK_STRIDX_PLUS_INFINITY 105 /* '+Infinity' */ -#define DUK_STRIDX_INFINITY 106 /* 'Infinity' */ -#define DUK_STRIDX_LC_OBJECT 107 /* 'object' */ -#define DUK_STRIDX_LC_STRING 108 /* 'string' */ -#define DUK_STRIDX_LC_NUMBER 109 /* 'number' */ -#define DUK_STRIDX_LC_BOOLEAN 110 /* 'boolean' */ -#define DUK_STRIDX_LC_UNDEFINED 111 /* 'undefined' */ -#define DUK_STRIDX_STRINGIFY 112 /* 'stringify' */ -#define DUK_STRIDX_TAN 113 /* 'tan' */ -#define DUK_STRIDX_SQRT 114 /* 'sqrt' */ -#define DUK_STRIDX_SIN 115 /* 'sin' */ -#define DUK_STRIDX_ROUND 116 /* 'round' */ -#define DUK_STRIDX_RANDOM 117 /* 'random' */ -#define DUK_STRIDX_POW 118 /* 'pow' */ -#define DUK_STRIDX_MIN 119 /* 'min' */ -#define DUK_STRIDX_MAX 120 /* 'max' */ -#define DUK_STRIDX_LOG 121 /* 'log' */ -#define DUK_STRIDX_FLOOR 122 /* 'floor' */ -#define DUK_STRIDX_EXP 123 /* 'exp' */ -#define DUK_STRIDX_COS 124 /* 'cos' */ -#define DUK_STRIDX_CEIL 125 /* 'ceil' */ -#define DUK_STRIDX_ATAN2 126 /* 'atan2' */ -#define DUK_STRIDX_ATAN 127 /* 'atan' */ -#define DUK_STRIDX_ASIN 128 /* 'asin' */ -#define DUK_STRIDX_ACOS 129 /* 'acos' */ -#define DUK_STRIDX_ABS 130 /* 'abs' */ -#define DUK_STRIDX_SQRT2 131 /* 'SQRT2' */ -#define DUK_STRIDX_SQRT1_2 132 /* 'SQRT1_2' */ -#define DUK_STRIDX_PI 133 /* 'PI' */ -#define DUK_STRIDX_LOG10E 134 /* 'LOG10E' */ -#define DUK_STRIDX_LOG2E 135 /* 'LOG2E' */ -#define DUK_STRIDX_LN2 136 /* 'LN2' */ -#define DUK_STRIDX_LN10 137 /* 'LN10' */ -#define DUK_STRIDX_E 138 /* 'E' */ -#define DUK_STRIDX_MESSAGE 139 /* 'message' */ -#define DUK_STRIDX_NAME 140 /* 'name' */ -#define DUK_STRIDX_INPUT 141 /* 'input' */ -#define DUK_STRIDX_INDEX 142 /* 'index' */ -#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 143 /* '(?:)' */ -#define DUK_STRIDX_LAST_INDEX 144 /* 'lastIndex' */ -#define DUK_STRIDX_MULTILINE 145 /* 'multiline' */ -#define DUK_STRIDX_IGNORE_CASE 146 /* 'ignoreCase' */ -#define DUK_STRIDX_SOURCE 147 /* 'source' */ -#define DUK_STRIDX_TEST 148 /* 'test' */ -#define DUK_STRIDX_EXEC 149 /* 'exec' */ -#define DUK_STRIDX_TO_GMT_STRING 150 /* 'toGMTString' */ -#define DUK_STRIDX_SET_YEAR 151 /* 'setYear' */ -#define DUK_STRIDX_GET_YEAR 152 /* 'getYear' */ -#define DUK_STRIDX_TO_JSON 153 /* 'toJSON' */ -#define DUK_STRIDX_TO_ISO_STRING 154 /* 'toISOString' */ -#define DUK_STRIDX_TO_UTC_STRING 155 /* 'toUTCString' */ -#define DUK_STRIDX_SET_UTC_FULL_YEAR 156 /* 'setUTCFullYear' */ -#define DUK_STRIDX_SET_FULL_YEAR 157 /* 'setFullYear' */ -#define DUK_STRIDX_SET_UTC_MONTH 158 /* 'setUTCMonth' */ -#define DUK_STRIDX_SET_MONTH 159 /* 'setMonth' */ -#define DUK_STRIDX_SET_UTC_DATE 160 /* 'setUTCDate' */ -#define DUK_STRIDX_SET_DATE 161 /* 'setDate' */ -#define DUK_STRIDX_SET_UTC_HOURS 162 /* 'setUTCHours' */ -#define DUK_STRIDX_SET_HOURS 163 /* 'setHours' */ -#define DUK_STRIDX_SET_UTC_MINUTES 164 /* 'setUTCMinutes' */ -#define DUK_STRIDX_SET_MINUTES 165 /* 'setMinutes' */ -#define DUK_STRIDX_SET_UTC_SECONDS 166 /* 'setUTCSeconds' */ -#define DUK_STRIDX_SET_SECONDS 167 /* 'setSeconds' */ -#define DUK_STRIDX_SET_UTC_MILLISECONDS 168 /* 'setUTCMilliseconds' */ -#define DUK_STRIDX_SET_MILLISECONDS 169 /* 'setMilliseconds' */ -#define DUK_STRIDX_SET_TIME 170 /* 'setTime' */ -#define DUK_STRIDX_GET_TIMEZONE_OFFSET 171 /* 'getTimezoneOffset' */ -#define DUK_STRIDX_GET_UTC_MILLISECONDS 172 /* 'getUTCMilliseconds' */ -#define DUK_STRIDX_GET_MILLISECONDS 173 /* 'getMilliseconds' */ -#define DUK_STRIDX_GET_UTC_SECONDS 174 /* 'getUTCSeconds' */ -#define DUK_STRIDX_GET_SECONDS 175 /* 'getSeconds' */ -#define DUK_STRIDX_GET_UTC_MINUTES 176 /* 'getUTCMinutes' */ -#define DUK_STRIDX_GET_MINUTES 177 /* 'getMinutes' */ -#define DUK_STRIDX_GET_UTC_HOURS 178 /* 'getUTCHours' */ -#define DUK_STRIDX_GET_HOURS 179 /* 'getHours' */ -#define DUK_STRIDX_GET_UTC_DAY 180 /* 'getUTCDay' */ -#define DUK_STRIDX_GET_DAY 181 /* 'getDay' */ -#define DUK_STRIDX_GET_UTC_DATE 182 /* 'getUTCDate' */ -#define DUK_STRIDX_GET_DATE 183 /* 'getDate' */ -#define DUK_STRIDX_GET_UTC_MONTH 184 /* 'getUTCMonth' */ -#define DUK_STRIDX_GET_MONTH 185 /* 'getMonth' */ -#define DUK_STRIDX_GET_UTC_FULL_YEAR 186 /* 'getUTCFullYear' */ -#define DUK_STRIDX_GET_FULL_YEAR 187 /* 'getFullYear' */ -#define DUK_STRIDX_GET_TIME 188 /* 'getTime' */ -#define DUK_STRIDX_TO_LOCALE_TIME_STRING 189 /* 'toLocaleTimeString' */ -#define DUK_STRIDX_TO_LOCALE_DATE_STRING 190 /* 'toLocaleDateString' */ -#define DUK_STRIDX_TO_TIME_STRING 191 /* 'toTimeString' */ -#define DUK_STRIDX_TO_DATE_STRING 192 /* 'toDateString' */ -#define DUK_STRIDX_NOW 193 /* 'now' */ -#define DUK_STRIDX_UTC 194 /* 'UTC' */ -#define DUK_STRIDX_PARSE 195 /* 'parse' */ -#define DUK_STRIDX_TO_PRECISION 196 /* 'toPrecision' */ -#define DUK_STRIDX_TO_EXPONENTIAL 197 /* 'toExponential' */ -#define DUK_STRIDX_TO_FIXED 198 /* 'toFixed' */ -#define DUK_STRIDX_POSITIVE_INFINITY 199 /* 'POSITIVE_INFINITY' */ -#define DUK_STRIDX_NEGATIVE_INFINITY 200 /* 'NEGATIVE_INFINITY' */ -#define DUK_STRIDX_NAN 201 /* 'NaN' */ -#define DUK_STRIDX_MIN_VALUE 202 /* 'MIN_VALUE' */ -#define DUK_STRIDX_MAX_VALUE 203 /* 'MAX_VALUE' */ -#define DUK_STRIDX_SUBSTR 204 /* 'substr' */ -#define DUK_STRIDX_TRIM 205 /* 'trim' */ -#define DUK_STRIDX_TO_LOCALE_UPPER_CASE 206 /* 'toLocaleUpperCase' */ -#define DUK_STRIDX_TO_UPPER_CASE 207 /* 'toUpperCase' */ -#define DUK_STRIDX_TO_LOCALE_LOWER_CASE 208 /* 'toLocaleLowerCase' */ -#define DUK_STRIDX_TO_LOWER_CASE 209 /* 'toLowerCase' */ -#define DUK_STRIDX_SUBSTRING 210 /* 'substring' */ -#define DUK_STRIDX_SPLIT 211 /* 'split' */ -#define DUK_STRIDX_SEARCH 212 /* 'search' */ -#define DUK_STRIDX_REPLACE 213 /* 'replace' */ -#define DUK_STRIDX_MATCH 214 /* 'match' */ -#define DUK_STRIDX_LOCALE_COMPARE 215 /* 'localeCompare' */ -#define DUK_STRIDX_CHAR_CODE_AT 216 /* 'charCodeAt' */ -#define DUK_STRIDX_CHAR_AT 217 /* 'charAt' */ -#define DUK_STRIDX_FROM_CHAR_CODE 218 /* 'fromCharCode' */ -#define DUK_STRIDX_REDUCE_RIGHT 219 /* 'reduceRight' */ -#define DUK_STRIDX_REDUCE 220 /* 'reduce' */ -#define DUK_STRIDX_FILTER 221 /* 'filter' */ -#define DUK_STRIDX_MAP 222 /* 'map' */ -#define DUK_STRIDX_FOR_EACH 223 /* 'forEach' */ -#define DUK_STRIDX_SOME 224 /* 'some' */ -#define DUK_STRIDX_EVERY 225 /* 'every' */ -#define DUK_STRIDX_LAST_INDEX_OF 226 /* 'lastIndexOf' */ -#define DUK_STRIDX_INDEX_OF 227 /* 'indexOf' */ -#define DUK_STRIDX_UNSHIFT 228 /* 'unshift' */ -#define DUK_STRIDX_SPLICE 229 /* 'splice' */ -#define DUK_STRIDX_SORT 230 /* 'sort' */ -#define DUK_STRIDX_SLICE 231 /* 'slice' */ -#define DUK_STRIDX_SHIFT 232 /* 'shift' */ -#define DUK_STRIDX_REVERSE 233 /* 'reverse' */ -#define DUK_STRIDX_PUSH 234 /* 'push' */ -#define DUK_STRIDX_POP 235 /* 'pop' */ -#define DUK_STRIDX_JOIN 236 /* 'join' */ -#define DUK_STRIDX_CONCAT 237 /* 'concat' */ -#define DUK_STRIDX_IS_ARRAY 238 /* 'isArray' */ -#define DUK_STRIDX_LC_ARGUMENTS 239 /* 'arguments' */ -#define DUK_STRIDX_CALLER 240 /* 'caller' */ -#define DUK_STRIDX_BIND 241 /* 'bind' */ -#define DUK_STRIDX_CALL 242 /* 'call' */ -#define DUK_STRIDX_APPLY 243 /* 'apply' */ -#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE 244 /* 'propertyIsEnumerable' */ -#define DUK_STRIDX_IS_PROTOTYPE_OF 245 /* 'isPrototypeOf' */ -#define DUK_STRIDX_HAS_OWN_PROPERTY 246 /* 'hasOwnProperty' */ -#define DUK_STRIDX_VALUE_OF 247 /* 'valueOf' */ -#define DUK_STRIDX_TO_LOCALE_STRING 248 /* 'toLocaleString' */ -#define DUK_STRIDX_TO_STRING 249 /* 'toString' */ -#define DUK_STRIDX_CONSTRUCTOR 250 /* 'constructor' */ -#define DUK_STRIDX_SET 251 /* 'set' */ -#define DUK_STRIDX_GET 252 /* 'get' */ -#define DUK_STRIDX_ENUMERABLE 253 /* 'enumerable' */ -#define DUK_STRIDX_CONFIGURABLE 254 /* 'configurable' */ -#define DUK_STRIDX_WRITABLE 255 /* 'writable' */ -#define DUK_STRIDX_VALUE 256 /* 'value' */ -#define DUK_STRIDX_KEYS 257 /* 'keys' */ -#define DUK_STRIDX_IS_EXTENSIBLE 258 /* 'isExtensible' */ -#define DUK_STRIDX_IS_FROZEN 259 /* 'isFrozen' */ -#define DUK_STRIDX_IS_SEALED 260 /* 'isSealed' */ -#define DUK_STRIDX_PREVENT_EXTENSIONS 261 /* 'preventExtensions' */ -#define DUK_STRIDX_FREEZE 262 /* 'freeze' */ -#define DUK_STRIDX_SEAL 263 /* 'seal' */ -#define DUK_STRIDX_DEFINE_PROPERTIES 264 /* 'defineProperties' */ -#define DUK_STRIDX_DEFINE_PROPERTY 265 /* 'defineProperty' */ -#define DUK_STRIDX_CREATE 266 /* 'create' */ -#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES 267 /* 'getOwnPropertyNames' */ -#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR 268 /* 'getOwnPropertyDescriptor' */ -#define DUK_STRIDX_GET_PROTOTYPE_OF 269 /* 'getPrototypeOf' */ -#define DUK_STRIDX_PROTOTYPE 270 /* 'prototype' */ -#define DUK_STRIDX_LENGTH 271 /* 'length' */ -#define DUK_STRIDX_ALERT 272 /* 'alert' */ -#define DUK_STRIDX_PRINT 273 /* 'print' */ -#define DUK_STRIDX_UNESCAPE 274 /* 'unescape' */ -#define DUK_STRIDX_ESCAPE 275 /* 'escape' */ -#define DUK_STRIDX_ENCODE_URI_COMPONENT 276 /* 'encodeURIComponent' */ -#define DUK_STRIDX_ENCODE_URI 277 /* 'encodeURI' */ -#define DUK_STRIDX_DECODE_URI_COMPONENT 278 /* 'decodeURIComponent' */ -#define DUK_STRIDX_DECODE_URI 279 /* 'decodeURI' */ -#define DUK_STRIDX_IS_FINITE 280 /* 'isFinite' */ -#define DUK_STRIDX_IS_NAN 281 /* 'isNaN' */ -#define DUK_STRIDX_PARSE_FLOAT 282 /* 'parseFloat' */ -#define DUK_STRIDX_PARSE_INT 283 /* 'parseInt' */ -#define DUK_STRIDX_EVAL 284 /* 'eval' */ -#define DUK_STRIDX_URI_ERROR 285 /* 'URIError' */ -#define DUK_STRIDX_TYPE_ERROR 286 /* 'TypeError' */ -#define DUK_STRIDX_SYNTAX_ERROR 287 /* 'SyntaxError' */ -#define DUK_STRIDX_REFERENCE_ERROR 288 /* 'ReferenceError' */ -#define DUK_STRIDX_RANGE_ERROR 289 /* 'RangeError' */ -#define DUK_STRIDX_EVAL_ERROR 290 /* 'EvalError' */ -#define DUK_STRIDX_BREAK 291 /* 'break' */ -#define DUK_STRIDX_CASE 292 /* 'case' */ -#define DUK_STRIDX_CATCH 293 /* 'catch' */ -#define DUK_STRIDX_CONTINUE 294 /* 'continue' */ -#define DUK_STRIDX_DEBUGGER 295 /* 'debugger' */ -#define DUK_STRIDX_DEFAULT 296 /* 'default' */ -#define DUK_STRIDX_DELETE 297 /* 'delete' */ -#define DUK_STRIDX_DO 298 /* 'do' */ -#define DUK_STRIDX_ELSE 299 /* 'else' */ -#define DUK_STRIDX_FINALLY 300 /* 'finally' */ -#define DUK_STRIDX_FOR 301 /* 'for' */ -#define DUK_STRIDX_LC_FUNCTION 302 /* 'function' */ -#define DUK_STRIDX_IF 303 /* 'if' */ -#define DUK_STRIDX_IN 304 /* 'in' */ -#define DUK_STRIDX_INSTANCEOF 305 /* 'instanceof' */ -#define DUK_STRIDX_NEW 306 /* 'new' */ -#define DUK_STRIDX_RETURN 307 /* 'return' */ -#define DUK_STRIDX_SWITCH 308 /* 'switch' */ -#define DUK_STRIDX_THIS 309 /* 'this' */ -#define DUK_STRIDX_THROW 310 /* 'throw' */ -#define DUK_STRIDX_TRY 311 /* 'try' */ -#define DUK_STRIDX_TYPEOF 312 /* 'typeof' */ -#define DUK_STRIDX_VAR 313 /* 'var' */ -#define DUK_STRIDX_VOID 314 /* 'void' */ -#define DUK_STRIDX_WHILE 315 /* 'while' */ -#define DUK_STRIDX_WITH 316 /* 'with' */ -#define DUK_STRIDX_CLASS 317 /* 'class' */ -#define DUK_STRIDX_CONST 318 /* 'const' */ -#define DUK_STRIDX_ENUM 319 /* 'enum' */ -#define DUK_STRIDX_EXPORT 320 /* 'export' */ -#define DUK_STRIDX_EXTENDS 321 /* 'extends' */ -#define DUK_STRIDX_IMPORT 322 /* 'import' */ -#define DUK_STRIDX_SUPER 323 /* 'super' */ -#define DUK_STRIDX_LC_NULL 324 /* 'null' */ -#define DUK_STRIDX_TRUE 325 /* 'true' */ -#define DUK_STRIDX_FALSE 326 /* 'false' */ -#define DUK_STRIDX_IMPLEMENTS 327 /* 'implements' */ -#define DUK_STRIDX_INTERFACE 328 /* 'interface' */ -#define DUK_STRIDX_LET 329 /* 'let' */ -#define DUK_STRIDX_PACKAGE 330 /* 'package' */ -#define DUK_STRIDX_PRIVATE 331 /* 'private' */ -#define DUK_STRIDX_PROTECTED 332 /* 'protected' */ -#define DUK_STRIDX_PUBLIC 333 /* 'public' */ -#define DUK_STRIDX_STATIC 334 /* 'static' */ -#define DUK_STRIDX_YIELD 335 /* 'yield' */ +#define DUK_STRIDX_DEC_ENV 3 /* 'DecEnv' */ +#define DUK_STRIDX_OBJ_ENV 4 /* 'ObjEnv' */ +#define DUK_STRIDX_FLOAT64_ARRAY 5 /* 'Float64Array' */ +#define DUK_STRIDX_FLOAT32_ARRAY 6 /* 'Float32Array' */ +#define DUK_STRIDX_UINT32_ARRAY 7 /* 'Uint32Array' */ +#define DUK_STRIDX_INT32_ARRAY 8 /* 'Int32Array' */ +#define DUK_STRIDX_UINT16_ARRAY 9 /* 'Uint16Array' */ +#define DUK_STRIDX_INT16_ARRAY 10 /* 'Int16Array' */ +#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 11 /* 'Uint8ClampedArray' */ +#define DUK_STRIDX_UINT8_ARRAY 12 /* 'Uint8Array' */ +#define DUK_STRIDX_INT8_ARRAY 13 /* 'Int8Array' */ +#define DUK_STRIDX_DATA_VIEW 14 /* 'DataView' */ +#define DUK_STRIDX_ARRAY_BUFFER 15 /* 'ArrayBuffer' */ +#define DUK_STRIDX_UC_BUFFER 16 /* 'Buffer' */ +#define DUK_STRIDX_EMPTY_STRING 17 /* '' */ +#define DUK_STRIDX_GLOBAL 18 /* 'global' */ +#define DUK_STRIDX_UC_ARGUMENTS 19 /* 'Arguments' */ +#define DUK_STRIDX_JSON 20 /* 'JSON' */ +#define DUK_STRIDX_MATH 21 /* 'Math' */ +#define DUK_STRIDX_UC_ERROR 22 /* 'Error' */ +#define DUK_STRIDX_REG_EXP 23 /* 'RegExp' */ +#define DUK_STRIDX_DATE 24 /* 'Date' */ +#define DUK_STRIDX_UC_NUMBER 25 /* 'Number' */ +#define DUK_STRIDX_UC_BOOLEAN 26 /* 'Boolean' */ +#define DUK_STRIDX_UC_STRING 27 /* 'String' */ +#define DUK_STRIDX_ARRAY 28 /* 'Array' */ +#define DUK_STRIDX_UC_FUNCTION 29 /* 'Function' */ +#define DUK_STRIDX_UC_OBJECT 30 /* 'Object' */ +#define DUK_STRIDX_UC_NULL 31 /* 'Null' */ +#define DUK_STRIDX_UC_UNDEFINED 32 /* 'Undefined' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION2 33 /* '{_func:true}' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION1 34 /* '{"_func":true}' */ +#define DUK_STRIDX_JSON_EXT_NEGINF 35 /* '{"_ninf":true}' */ +#define DUK_STRIDX_JSON_EXT_POSINF 36 /* '{"_inf":true}' */ +#define DUK_STRIDX_JSON_EXT_NAN 37 /* '{"_nan":true}' */ +#define DUK_STRIDX_JSON_EXT_UNDEFINED 38 /* '{"_undef":true}' */ +#define DUK_STRIDX_TO_LOG_STRING 39 /* 'toLogString' */ +#define DUK_STRIDX_CLOG 40 /* 'clog' */ +#define DUK_STRIDX_LC_L 41 /* 'l' */ +#define DUK_STRIDX_LC_N 42 /* 'n' */ +#define DUK_STRIDX_LC_FATAL 43 /* 'fatal' */ +#define DUK_STRIDX_LC_ERROR 44 /* 'error' */ +#define DUK_STRIDX_LC_WARN 45 /* 'warn' */ +#define DUK_STRIDX_LC_DEBUG 46 /* 'debug' */ +#define DUK_STRIDX_LC_TRACE 47 /* 'trace' */ +#define DUK_STRIDX_RAW 48 /* 'raw' */ +#define DUK_STRIDX_FMT 49 /* 'fmt' */ +#define DUK_STRIDX_CURRENT 50 /* 'current' */ +#define DUK_STRIDX_RESUME 51 /* 'resume' */ +#define DUK_STRIDX_COMPACT 52 /* 'compact' */ +#define DUK_STRIDX_JC 53 /* 'jc' */ +#define DUK_STRIDX_JX 54 /* 'jx' */ +#define DUK_STRIDX_BASE64 55 /* 'base64' */ +#define DUK_STRIDX_HEX 56 /* 'hex' */ +#define DUK_STRIDX_DEC 57 /* 'dec' */ +#define DUK_STRIDX_ENC 58 /* 'enc' */ +#define DUK_STRIDX_FIN 59 /* 'fin' */ +#define DUK_STRIDX_GC 60 /* 'gc' */ +#define DUK_STRIDX_ACT 61 /* 'act' */ +#define DUK_STRIDX_LC_INFO 62 /* 'info' */ +#define DUK_STRIDX_VERSION 63 /* 'version' */ +#define DUK_STRIDX_ENV 64 /* 'env' */ +#define DUK_STRIDX_MOD_LOADED 65 /* 'modLoaded' */ +#define DUK_STRIDX_MOD_SEARCH 66 /* 'modSearch' */ +#define DUK_STRIDX_ERR_THROW 67 /* 'errThrow' */ +#define DUK_STRIDX_ERR_CREATE 68 /* 'errCreate' */ +#define DUK_STRIDX_COMPILE 69 /* 'compile' */ +#define DUK_STRIDX_INT_REGBASE 70 /* '\x00Regbase' */ +#define DUK_STRIDX_INT_THREAD 71 /* '\x00Thread' */ +#define DUK_STRIDX_INT_HANDLER 72 /* '\x00Handler' */ +#define DUK_STRIDX_INT_FINALIZER 73 /* '\x00Finalizer' */ +#define DUK_STRIDX_INT_CALLEE 74 /* '\x00Callee' */ +#define DUK_STRIDX_INT_MAP 75 /* '\x00Map' */ +#define DUK_STRIDX_INT_ARGS 76 /* '\x00Args' */ +#define DUK_STRIDX_INT_THIS 77 /* '\x00This' */ +#define DUK_STRIDX_INT_PC2LINE 78 /* '\x00Pc2line' */ +#define DUK_STRIDX_INT_SOURCE 79 /* '\x00Source' */ +#define DUK_STRIDX_INT_VARENV 80 /* '\x00Varenv' */ +#define DUK_STRIDX_INT_LEXENV 81 /* '\x00Lexenv' */ +#define DUK_STRIDX_INT_VARMAP 82 /* '\x00Varmap' */ +#define DUK_STRIDX_INT_FORMALS 83 /* '\x00Formals' */ +#define DUK_STRIDX_INT_BYTECODE 84 /* '\x00Bytecode' */ +#define DUK_STRIDX_INT_NEXT 85 /* '\x00Next' */ +#define DUK_STRIDX_INT_TARGET 86 /* '\x00Target' */ +#define DUK_STRIDX_INT_VALUE 87 /* '\x00Value' */ +#define DUK_STRIDX_LC_POINTER 88 /* 'pointer' */ +#define DUK_STRIDX_INT_TRACEDATA 89 /* '\x00Tracedata' */ +#define DUK_STRIDX_LINE_NUMBER 90 /* 'lineNumber' */ +#define DUK_STRIDX_FILE_NAME 91 /* 'fileName' */ +#define DUK_STRIDX_PC 92 /* 'pc' */ +#define DUK_STRIDX_STACK 93 /* 'stack' */ +#define DUK_STRIDX_THROW_TYPE_ERROR 94 /* 'ThrowTypeError' */ +#define DUK_STRIDX_DUKTAPE 95 /* 'Duktape' */ +#define DUK_STRIDX_SET_FLOAT64 96 /* 'setFloat64' */ +#define DUK_STRIDX_SET_FLOAT32 97 /* 'setFloat32' */ +#define DUK_STRIDX_SET_UINT32 98 /* 'setUint32' */ +#define DUK_STRIDX_SET_INT32 99 /* 'setInt32' */ +#define DUK_STRIDX_SET_UINT16 100 /* 'setUint16' */ +#define DUK_STRIDX_SET_INT16 101 /* 'setInt16' */ +#define DUK_STRIDX_SET_UINT8 102 /* 'setUint8' */ +#define DUK_STRIDX_SET_INT8 103 /* 'setInt8' */ +#define DUK_STRIDX_GET_FLOAT64 104 /* 'getFloat64' */ +#define DUK_STRIDX_GET_FLOAT32 105 /* 'getFloat32' */ +#define DUK_STRIDX_GET_UINT32 106 /* 'getUint32' */ +#define DUK_STRIDX_GET_INT32 107 /* 'getInt32' */ +#define DUK_STRIDX_GET_UINT16 108 /* 'getUint16' */ +#define DUK_STRIDX_GET_INT16 109 /* 'getInt16' */ +#define DUK_STRIDX_GET_UINT8 110 /* 'getUint8' */ +#define DUK_STRIDX_GET_INT8 111 /* 'getInt8' */ +#define DUK_STRIDX_SUBARRAY 112 /* 'subarray' */ +#define DUK_STRIDX_BYTES_PER_ELEMENT 113 /* 'BYTES_PER_ELEMENT' */ +#define DUK_STRIDX_BYTE_OFFSET 114 /* 'byteOffset' */ +#define DUK_STRIDX_LC_BUFFER 115 /* 'buffer' */ +#define DUK_STRIDX_IS_VIEW 116 /* 'isView' */ +#define DUK_STRIDX_DATA 117 /* 'data' */ +#define DUK_STRIDX_TYPE 118 /* 'type' */ +#define DUK_STRIDX_WRITE_INT_BE 119 /* 'writeIntBE' */ +#define DUK_STRIDX_WRITE_INT_LE 120 /* 'writeIntLE' */ +#define DUK_STRIDX_WRITE_UINT_BE 121 /* 'writeUIntBE' */ +#define DUK_STRIDX_WRITE_UINT_LE 122 /* 'writeUIntLE' */ +#define DUK_STRIDX_WRITE_DOUBLE_BE 123 /* 'writeDoubleBE' */ +#define DUK_STRIDX_WRITE_DOUBLE_LE 124 /* 'writeDoubleLE' */ +#define DUK_STRIDX_WRITE_FLOAT_BE 125 /* 'writeFloatBE' */ +#define DUK_STRIDX_WRITE_FLOAT_LE 126 /* 'writeFloatLE' */ +#define DUK_STRIDX_WRITE_INT32_BE 127 /* 'writeInt32BE' */ +#define DUK_STRIDX_WRITE_INT32_LE 128 /* 'writeInt32LE' */ +#define DUK_STRIDX_WRITE_UINT32_BE 129 /* 'writeUInt32BE' */ +#define DUK_STRIDX_WRITE_UINT32_LE 130 /* 'writeUInt32LE' */ +#define DUK_STRIDX_WRITE_INT16_BE 131 /* 'writeInt16BE' */ +#define DUK_STRIDX_WRITE_INT16_LE 132 /* 'writeInt16LE' */ +#define DUK_STRIDX_WRITE_UINT16_BE 133 /* 'writeUInt16BE' */ +#define DUK_STRIDX_WRITE_UINT16_LE 134 /* 'writeUInt16LE' */ +#define DUK_STRIDX_WRITE_INT8 135 /* 'writeInt8' */ +#define DUK_STRIDX_WRITE_UINT8 136 /* 'writeUInt8' */ +#define DUK_STRIDX_READ_INT_BE 137 /* 'readIntBE' */ +#define DUK_STRIDX_READ_INT_LE 138 /* 'readIntLE' */ +#define DUK_STRIDX_READ_UINT_BE 139 /* 'readUIntBE' */ +#define DUK_STRIDX_READ_UINT_LE 140 /* 'readUIntLE' */ +#define DUK_STRIDX_READ_DOUBLE_BE 141 /* 'readDoubleBE' */ +#define DUK_STRIDX_READ_DOUBLE_LE 142 /* 'readDoubleLE' */ +#define DUK_STRIDX_READ_FLOAT_BE 143 /* 'readFloatBE' */ +#define DUK_STRIDX_READ_FLOAT_LE 144 /* 'readFloatLE' */ +#define DUK_STRIDX_READ_INT32_BE 145 /* 'readInt32BE' */ +#define DUK_STRIDX_READ_INT32_LE 146 /* 'readInt32LE' */ +#define DUK_STRIDX_READ_UINT32_BE 147 /* 'readUInt32BE' */ +#define DUK_STRIDX_READ_UINT32_LE 148 /* 'readUInt32LE' */ +#define DUK_STRIDX_READ_INT16_BE 149 /* 'readInt16BE' */ +#define DUK_STRIDX_READ_INT16_LE 150 /* 'readInt16LE' */ +#define DUK_STRIDX_READ_UINT16_BE 151 /* 'readUInt16BE' */ +#define DUK_STRIDX_READ_UINT16_LE 152 /* 'readUInt16LE' */ +#define DUK_STRIDX_READ_INT8 153 /* 'readInt8' */ +#define DUK_STRIDX_READ_UINT8 154 /* 'readUInt8' */ +#define DUK_STRIDX_COPY 155 /* 'copy' */ +#define DUK_STRIDX_EQUALS 156 /* 'equals' */ +#define DUK_STRIDX_FILL 157 /* 'fill' */ +#define DUK_STRIDX_WRITE 158 /* 'write' */ +#define DUK_STRIDX_COMPARE 159 /* 'compare' */ +#define DUK_STRIDX_BYTE_LENGTH 160 /* 'byteLength' */ +#define DUK_STRIDX_IS_BUFFER 161 /* 'isBuffer' */ +#define DUK_STRIDX_IS_ENCODING 162 /* 'isEncoding' */ +#define DUK_STRIDX_EXPORTS 163 /* 'exports' */ +#define DUK_STRIDX_ID 164 /* 'id' */ +#define DUK_STRIDX_REQUIRE 165 /* 'require' */ +#define DUK_STRIDX___PROTO__ 166 /* '__proto__' */ +#define DUK_STRIDX_SET_PROTOTYPE_OF 167 /* 'setPrototypeOf' */ +#define DUK_STRIDX_OWN_KEYS 168 /* 'ownKeys' */ +#define DUK_STRIDX_ENUMERATE 169 /* 'enumerate' */ +#define DUK_STRIDX_DELETE_PROPERTY 170 /* 'deleteProperty' */ +#define DUK_STRIDX_HAS 171 /* 'has' */ +#define DUK_STRIDX_PROXY 172 /* 'Proxy' */ +#define DUK_STRIDX_CALLEE 173 /* 'callee' */ +#define DUK_STRIDX_INVALID_DATE 174 /* 'Invalid Date' */ +#define DUK_STRIDX_BRACKETED_ELLIPSIS 175 /* '[...]' */ +#define DUK_STRIDX_NEWLINE_TAB 176 /* '\n\t' */ +#define DUK_STRIDX_SPACE 177 /* ' ' */ +#define DUK_STRIDX_COMMA 178 /* ',' */ +#define DUK_STRIDX_MINUS_ZERO 179 /* '-0' */ +#define DUK_STRIDX_PLUS_ZERO 180 /* '+0' */ +#define DUK_STRIDX_ZERO 181 /* '0' */ +#define DUK_STRIDX_MINUS_INFINITY 182 /* '-Infinity' */ +#define DUK_STRIDX_PLUS_INFINITY 183 /* '+Infinity' */ +#define DUK_STRIDX_INFINITY 184 /* 'Infinity' */ +#define DUK_STRIDX_LC_OBJECT 185 /* 'object' */ +#define DUK_STRIDX_LC_STRING 186 /* 'string' */ +#define DUK_STRIDX_LC_NUMBER 187 /* 'number' */ +#define DUK_STRIDX_LC_BOOLEAN 188 /* 'boolean' */ +#define DUK_STRIDX_LC_UNDEFINED 189 /* 'undefined' */ +#define DUK_STRIDX_STRINGIFY 190 /* 'stringify' */ +#define DUK_STRIDX_TAN 191 /* 'tan' */ +#define DUK_STRIDX_SQRT 192 /* 'sqrt' */ +#define DUK_STRIDX_SIN 193 /* 'sin' */ +#define DUK_STRIDX_ROUND 194 /* 'round' */ +#define DUK_STRIDX_RANDOM 195 /* 'random' */ +#define DUK_STRIDX_POW 196 /* 'pow' */ +#define DUK_STRIDX_MIN 197 /* 'min' */ +#define DUK_STRIDX_MAX 198 /* 'max' */ +#define DUK_STRIDX_LOG 199 /* 'log' */ +#define DUK_STRIDX_FLOOR 200 /* 'floor' */ +#define DUK_STRIDX_EXP 201 /* 'exp' */ +#define DUK_STRIDX_COS 202 /* 'cos' */ +#define DUK_STRIDX_CEIL 203 /* 'ceil' */ +#define DUK_STRIDX_ATAN2 204 /* 'atan2' */ +#define DUK_STRIDX_ATAN 205 /* 'atan' */ +#define DUK_STRIDX_ASIN 206 /* 'asin' */ +#define DUK_STRIDX_ACOS 207 /* 'acos' */ +#define DUK_STRIDX_ABS 208 /* 'abs' */ +#define DUK_STRIDX_SQRT2 209 /* 'SQRT2' */ +#define DUK_STRIDX_SQRT1_2 210 /* 'SQRT1_2' */ +#define DUK_STRIDX_PI 211 /* 'PI' */ +#define DUK_STRIDX_LOG10E 212 /* 'LOG10E' */ +#define DUK_STRIDX_LOG2E 213 /* 'LOG2E' */ +#define DUK_STRIDX_LN2 214 /* 'LN2' */ +#define DUK_STRIDX_LN10 215 /* 'LN10' */ +#define DUK_STRIDX_E 216 /* 'E' */ +#define DUK_STRIDX_MESSAGE 217 /* 'message' */ +#define DUK_STRIDX_NAME 218 /* 'name' */ +#define DUK_STRIDX_INPUT 219 /* 'input' */ +#define DUK_STRIDX_INDEX 220 /* 'index' */ +#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 221 /* '(?:)' */ +#define DUK_STRIDX_LAST_INDEX 222 /* 'lastIndex' */ +#define DUK_STRIDX_MULTILINE 223 /* 'multiline' */ +#define DUK_STRIDX_IGNORE_CASE 224 /* 'ignoreCase' */ +#define DUK_STRIDX_SOURCE 225 /* 'source' */ +#define DUK_STRIDX_TEST 226 /* 'test' */ +#define DUK_STRIDX_EXEC 227 /* 'exec' */ +#define DUK_STRIDX_TO_GMT_STRING 228 /* 'toGMTString' */ +#define DUK_STRIDX_SET_YEAR 229 /* 'setYear' */ +#define DUK_STRIDX_GET_YEAR 230 /* 'getYear' */ +#define DUK_STRIDX_TO_JSON 231 /* 'toJSON' */ +#define DUK_STRIDX_TO_ISO_STRING 232 /* 'toISOString' */ +#define DUK_STRIDX_TO_UTC_STRING 233 /* 'toUTCString' */ +#define DUK_STRIDX_SET_UTC_FULL_YEAR 234 /* 'setUTCFullYear' */ +#define DUK_STRIDX_SET_FULL_YEAR 235 /* 'setFullYear' */ +#define DUK_STRIDX_SET_UTC_MONTH 236 /* 'setUTCMonth' */ +#define DUK_STRIDX_SET_MONTH 237 /* 'setMonth' */ +#define DUK_STRIDX_SET_UTC_DATE 238 /* 'setUTCDate' */ +#define DUK_STRIDX_SET_DATE 239 /* 'setDate' */ +#define DUK_STRIDX_SET_UTC_HOURS 240 /* 'setUTCHours' */ +#define DUK_STRIDX_SET_HOURS 241 /* 'setHours' */ +#define DUK_STRIDX_SET_UTC_MINUTES 242 /* 'setUTCMinutes' */ +#define DUK_STRIDX_SET_MINUTES 243 /* 'setMinutes' */ +#define DUK_STRIDX_SET_UTC_SECONDS 244 /* 'setUTCSeconds' */ +#define DUK_STRIDX_SET_SECONDS 245 /* 'setSeconds' */ +#define DUK_STRIDX_SET_UTC_MILLISECONDS 246 /* 'setUTCMilliseconds' */ +#define DUK_STRIDX_SET_MILLISECONDS 247 /* 'setMilliseconds' */ +#define DUK_STRIDX_SET_TIME 248 /* 'setTime' */ +#define DUK_STRIDX_GET_TIMEZONE_OFFSET 249 /* 'getTimezoneOffset' */ +#define DUK_STRIDX_GET_UTC_MILLISECONDS 250 /* 'getUTCMilliseconds' */ +#define DUK_STRIDX_GET_MILLISECONDS 251 /* 'getMilliseconds' */ +#define DUK_STRIDX_GET_UTC_SECONDS 252 /* 'getUTCSeconds' */ +#define DUK_STRIDX_GET_SECONDS 253 /* 'getSeconds' */ +#define DUK_STRIDX_GET_UTC_MINUTES 254 /* 'getUTCMinutes' */ +#define DUK_STRIDX_GET_MINUTES 255 /* 'getMinutes' */ +#define DUK_STRIDX_GET_UTC_HOURS 256 /* 'getUTCHours' */ +#define DUK_STRIDX_GET_HOURS 257 /* 'getHours' */ +#define DUK_STRIDX_GET_UTC_DAY 258 /* 'getUTCDay' */ +#define DUK_STRIDX_GET_DAY 259 /* 'getDay' */ +#define DUK_STRIDX_GET_UTC_DATE 260 /* 'getUTCDate' */ +#define DUK_STRIDX_GET_DATE 261 /* 'getDate' */ +#define DUK_STRIDX_GET_UTC_MONTH 262 /* 'getUTCMonth' */ +#define DUK_STRIDX_GET_MONTH 263 /* 'getMonth' */ +#define DUK_STRIDX_GET_UTC_FULL_YEAR 264 /* 'getUTCFullYear' */ +#define DUK_STRIDX_GET_FULL_YEAR 265 /* 'getFullYear' */ +#define DUK_STRIDX_GET_TIME 266 /* 'getTime' */ +#define DUK_STRIDX_TO_LOCALE_TIME_STRING 267 /* 'toLocaleTimeString' */ +#define DUK_STRIDX_TO_LOCALE_DATE_STRING 268 /* 'toLocaleDateString' */ +#define DUK_STRIDX_TO_TIME_STRING 269 /* 'toTimeString' */ +#define DUK_STRIDX_TO_DATE_STRING 270 /* 'toDateString' */ +#define DUK_STRIDX_NOW 271 /* 'now' */ +#define DUK_STRIDX_UTC 272 /* 'UTC' */ +#define DUK_STRIDX_PARSE 273 /* 'parse' */ +#define DUK_STRIDX_TO_PRECISION 274 /* 'toPrecision' */ +#define DUK_STRIDX_TO_EXPONENTIAL 275 /* 'toExponential' */ +#define DUK_STRIDX_TO_FIXED 276 /* 'toFixed' */ +#define DUK_STRIDX_POSITIVE_INFINITY 277 /* 'POSITIVE_INFINITY' */ +#define DUK_STRIDX_NEGATIVE_INFINITY 278 /* 'NEGATIVE_INFINITY' */ +#define DUK_STRIDX_NAN 279 /* 'NaN' */ +#define DUK_STRIDX_MIN_VALUE 280 /* 'MIN_VALUE' */ +#define DUK_STRIDX_MAX_VALUE 281 /* 'MAX_VALUE' */ +#define DUK_STRIDX_SUBSTR 282 /* 'substr' */ +#define DUK_STRIDX_TRIM 283 /* 'trim' */ +#define DUK_STRIDX_TO_LOCALE_UPPER_CASE 284 /* 'toLocaleUpperCase' */ +#define DUK_STRIDX_TO_UPPER_CASE 285 /* 'toUpperCase' */ +#define DUK_STRIDX_TO_LOCALE_LOWER_CASE 286 /* 'toLocaleLowerCase' */ +#define DUK_STRIDX_TO_LOWER_CASE 287 /* 'toLowerCase' */ +#define DUK_STRIDX_SUBSTRING 288 /* 'substring' */ +#define DUK_STRIDX_SPLIT 289 /* 'split' */ +#define DUK_STRIDX_SEARCH 290 /* 'search' */ +#define DUK_STRIDX_REPLACE 291 /* 'replace' */ +#define DUK_STRIDX_MATCH 292 /* 'match' */ +#define DUK_STRIDX_LOCALE_COMPARE 293 /* 'localeCompare' */ +#define DUK_STRIDX_CHAR_CODE_AT 294 /* 'charCodeAt' */ +#define DUK_STRIDX_CHAR_AT 295 /* 'charAt' */ +#define DUK_STRIDX_FROM_CHAR_CODE 296 /* 'fromCharCode' */ +#define DUK_STRIDX_REDUCE_RIGHT 297 /* 'reduceRight' */ +#define DUK_STRIDX_REDUCE 298 /* 'reduce' */ +#define DUK_STRIDX_FILTER 299 /* 'filter' */ +#define DUK_STRIDX_MAP 300 /* 'map' */ +#define DUK_STRIDX_FOR_EACH 301 /* 'forEach' */ +#define DUK_STRIDX_SOME 302 /* 'some' */ +#define DUK_STRIDX_EVERY 303 /* 'every' */ +#define DUK_STRIDX_LAST_INDEX_OF 304 /* 'lastIndexOf' */ +#define DUK_STRIDX_INDEX_OF 305 /* 'indexOf' */ +#define DUK_STRIDX_UNSHIFT 306 /* 'unshift' */ +#define DUK_STRIDX_SPLICE 307 /* 'splice' */ +#define DUK_STRIDX_SORT 308 /* 'sort' */ +#define DUK_STRIDX_SLICE 309 /* 'slice' */ +#define DUK_STRIDX_SHIFT 310 /* 'shift' */ +#define DUK_STRIDX_REVERSE 311 /* 'reverse' */ +#define DUK_STRIDX_PUSH 312 /* 'push' */ +#define DUK_STRIDX_POP 313 /* 'pop' */ +#define DUK_STRIDX_JOIN 314 /* 'join' */ +#define DUK_STRIDX_CONCAT 315 /* 'concat' */ +#define DUK_STRIDX_IS_ARRAY 316 /* 'isArray' */ +#define DUK_STRIDX_LC_ARGUMENTS 317 /* 'arguments' */ +#define DUK_STRIDX_CALLER 318 /* 'caller' */ +#define DUK_STRIDX_BIND 319 /* 'bind' */ +#define DUK_STRIDX_CALL 320 /* 'call' */ +#define DUK_STRIDX_APPLY 321 /* 'apply' */ +#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE 322 /* 'propertyIsEnumerable' */ +#define DUK_STRIDX_IS_PROTOTYPE_OF 323 /* 'isPrototypeOf' */ +#define DUK_STRIDX_HAS_OWN_PROPERTY 324 /* 'hasOwnProperty' */ +#define DUK_STRIDX_VALUE_OF 325 /* 'valueOf' */ +#define DUK_STRIDX_TO_LOCALE_STRING 326 /* 'toLocaleString' */ +#define DUK_STRIDX_TO_STRING 327 /* 'toString' */ +#define DUK_STRIDX_CONSTRUCTOR 328 /* 'constructor' */ +#define DUK_STRIDX_SET 329 /* 'set' */ +#define DUK_STRIDX_GET 330 /* 'get' */ +#define DUK_STRIDX_ENUMERABLE 331 /* 'enumerable' */ +#define DUK_STRIDX_CONFIGURABLE 332 /* 'configurable' */ +#define DUK_STRIDX_WRITABLE 333 /* 'writable' */ +#define DUK_STRIDX_VALUE 334 /* 'value' */ +#define DUK_STRIDX_KEYS 335 /* 'keys' */ +#define DUK_STRIDX_IS_EXTENSIBLE 336 /* 'isExtensible' */ +#define DUK_STRIDX_IS_FROZEN 337 /* 'isFrozen' */ +#define DUK_STRIDX_IS_SEALED 338 /* 'isSealed' */ +#define DUK_STRIDX_PREVENT_EXTENSIONS 339 /* 'preventExtensions' */ +#define DUK_STRIDX_FREEZE 340 /* 'freeze' */ +#define DUK_STRIDX_SEAL 341 /* 'seal' */ +#define DUK_STRIDX_DEFINE_PROPERTIES 342 /* 'defineProperties' */ +#define DUK_STRIDX_DEFINE_PROPERTY 343 /* 'defineProperty' */ +#define DUK_STRIDX_CREATE 344 /* 'create' */ +#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES 345 /* 'getOwnPropertyNames' */ +#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR 346 /* 'getOwnPropertyDescriptor' */ +#define DUK_STRIDX_GET_PROTOTYPE_OF 347 /* 'getPrototypeOf' */ +#define DUK_STRIDX_PROTOTYPE 348 /* 'prototype' */ +#define DUK_STRIDX_LENGTH 349 /* 'length' */ +#define DUK_STRIDX_ALERT 350 /* 'alert' */ +#define DUK_STRIDX_PRINT 351 /* 'print' */ +#define DUK_STRIDX_UNESCAPE 352 /* 'unescape' */ +#define DUK_STRIDX_ESCAPE 353 /* 'escape' */ +#define DUK_STRIDX_ENCODE_URI_COMPONENT 354 /* 'encodeURIComponent' */ +#define DUK_STRIDX_ENCODE_URI 355 /* 'encodeURI' */ +#define DUK_STRIDX_DECODE_URI_COMPONENT 356 /* 'decodeURIComponent' */ +#define DUK_STRIDX_DECODE_URI 357 /* 'decodeURI' */ +#define DUK_STRIDX_IS_FINITE 358 /* 'isFinite' */ +#define DUK_STRIDX_IS_NAN 359 /* 'isNaN' */ +#define DUK_STRIDX_PARSE_FLOAT 360 /* 'parseFloat' */ +#define DUK_STRIDX_PARSE_INT 361 /* 'parseInt' */ +#define DUK_STRIDX_EVAL 362 /* 'eval' */ +#define DUK_STRIDX_URI_ERROR 363 /* 'URIError' */ +#define DUK_STRIDX_TYPE_ERROR 364 /* 'TypeError' */ +#define DUK_STRIDX_SYNTAX_ERROR 365 /* 'SyntaxError' */ +#define DUK_STRIDX_REFERENCE_ERROR 366 /* 'ReferenceError' */ +#define DUK_STRIDX_RANGE_ERROR 367 /* 'RangeError' */ +#define DUK_STRIDX_EVAL_ERROR 368 /* 'EvalError' */ +#define DUK_STRIDX_BREAK 369 /* 'break' */ +#define DUK_STRIDX_CASE 370 /* 'case' */ +#define DUK_STRIDX_CATCH 371 /* 'catch' */ +#define DUK_STRIDX_CONTINUE 372 /* 'continue' */ +#define DUK_STRIDX_DEBUGGER 373 /* 'debugger' */ +#define DUK_STRIDX_DEFAULT 374 /* 'default' */ +#define DUK_STRIDX_DELETE 375 /* 'delete' */ +#define DUK_STRIDX_DO 376 /* 'do' */ +#define DUK_STRIDX_ELSE 377 /* 'else' */ +#define DUK_STRIDX_FINALLY 378 /* 'finally' */ +#define DUK_STRIDX_FOR 379 /* 'for' */ +#define DUK_STRIDX_LC_FUNCTION 380 /* 'function' */ +#define DUK_STRIDX_IF 381 /* 'if' */ +#define DUK_STRIDX_IN 382 /* 'in' */ +#define DUK_STRIDX_INSTANCEOF 383 /* 'instanceof' */ +#define DUK_STRIDX_NEW 384 /* 'new' */ +#define DUK_STRIDX_RETURN 385 /* 'return' */ +#define DUK_STRIDX_SWITCH 386 /* 'switch' */ +#define DUK_STRIDX_THIS 387 /* 'this' */ +#define DUK_STRIDX_THROW 388 /* 'throw' */ +#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_ENUM 397 /* 'enum' */ +#define DUK_STRIDX_EXPORT 398 /* 'export' */ +#define DUK_STRIDX_EXTENDS 399 /* 'extends' */ +#define DUK_STRIDX_IMPORT 400 /* 'import' */ +#define DUK_STRIDX_SUPER 401 /* 'super' */ +#define DUK_STRIDX_LC_NULL 402 /* 'null' */ +#define DUK_STRIDX_TRUE 403 /* 'true' */ +#define DUK_STRIDX_FALSE 404 /* 'false' */ +#define DUK_STRIDX_IMPLEMENTS 405 /* 'implements' */ +#define DUK_STRIDX_INTERFACE 406 /* 'interface' */ +#define DUK_STRIDX_LET 407 /* 'let' */ +#define DUK_STRIDX_PACKAGE 408 /* 'package' */ +#define DUK_STRIDX_PRIVATE 409 /* 'private' */ +#define DUK_STRIDX_PROTECTED 410 /* 'protected' */ +#define DUK_STRIDX_PUBLIC 411 /* 'public' */ +#define DUK_STRIDX_STATIC 412 /* 'static' */ +#define DUK_STRIDX_YIELD 413 /* 'yield' */ #define DUK_HEAP_STRING_UC_LOGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_LOGGER) #define DUK_HTHREAD_STRING_UC_LOGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_LOGGER) @@ -662,12 +748,34 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD) #define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER) #define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER) -#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) -#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) #define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV) #define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV) #define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV) #define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV) +#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY) +#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY) +#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY) +#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY) +#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY) +#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY) +#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW) +#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW) +#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) +#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) #define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING) #define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING) #define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL) @@ -812,8 +920,6 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE) #define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER) #define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER) -#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER) -#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER) #define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA) #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA) #define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER) @@ -828,6 +934,142 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_THROW_TYPE_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW_TYPE_ERROR) #define DUK_HEAP_STRING_DUKTAPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DUKTAPE) #define DUK_HTHREAD_STRING_DUKTAPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DUKTAPE) +#define DUK_HEAP_STRING_SET_FLOAT64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT64) +#define DUK_HTHREAD_STRING_SET_FLOAT64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT64) +#define DUK_HEAP_STRING_SET_FLOAT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT32) +#define DUK_HTHREAD_STRING_SET_FLOAT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT32) +#define DUK_HEAP_STRING_SET_UINT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT32) +#define DUK_HTHREAD_STRING_SET_UINT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT32) +#define DUK_HEAP_STRING_SET_INT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT32) +#define DUK_HTHREAD_STRING_SET_INT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT32) +#define DUK_HEAP_STRING_SET_UINT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT16) +#define DUK_HTHREAD_STRING_SET_UINT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT16) +#define DUK_HEAP_STRING_SET_INT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT16) +#define DUK_HTHREAD_STRING_SET_INT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT16) +#define DUK_HEAP_STRING_SET_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT8) +#define DUK_HTHREAD_STRING_SET_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT8) +#define DUK_HEAP_STRING_SET_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT8) +#define DUK_HTHREAD_STRING_SET_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT8) +#define DUK_HEAP_STRING_GET_FLOAT64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT64) +#define DUK_HTHREAD_STRING_GET_FLOAT64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT64) +#define DUK_HEAP_STRING_GET_FLOAT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT32) +#define DUK_HTHREAD_STRING_GET_FLOAT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT32) +#define DUK_HEAP_STRING_GET_UINT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT32) +#define DUK_HTHREAD_STRING_GET_UINT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT32) +#define DUK_HEAP_STRING_GET_INT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT32) +#define DUK_HTHREAD_STRING_GET_INT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT32) +#define DUK_HEAP_STRING_GET_UINT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT16) +#define DUK_HTHREAD_STRING_GET_UINT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT16) +#define DUK_HEAP_STRING_GET_INT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT16) +#define DUK_HTHREAD_STRING_GET_INT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT16) +#define DUK_HEAP_STRING_GET_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT8) +#define DUK_HTHREAD_STRING_GET_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT8) +#define DUK_HEAP_STRING_GET_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT8) +#define DUK_HTHREAD_STRING_GET_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT8) +#define DUK_HEAP_STRING_SUBARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUBARRAY) +#define DUK_HTHREAD_STRING_SUBARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUBARRAY) +#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT) +#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT) +#define DUK_HEAP_STRING_BYTE_OFFSET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET) +#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET) +#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER) +#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER) +#define DUK_HEAP_STRING_IS_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_VIEW) +#define DUK_HTHREAD_STRING_IS_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_VIEW) +#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA) +#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA) +#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE) +#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE) +#define DUK_HEAP_STRING_WRITE_INT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_BE) +#define DUK_HTHREAD_STRING_WRITE_INT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_BE) +#define DUK_HEAP_STRING_WRITE_INT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_LE) +#define DUK_HTHREAD_STRING_WRITE_INT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_LE) +#define DUK_HEAP_STRING_WRITE_UINT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_BE) +#define DUK_HEAP_STRING_WRITE_UINT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_LE) +#define DUK_HEAP_STRING_WRITE_DOUBLE_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_BE) +#define DUK_HTHREAD_STRING_WRITE_DOUBLE_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_BE) +#define DUK_HEAP_STRING_WRITE_DOUBLE_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_LE) +#define DUK_HTHREAD_STRING_WRITE_DOUBLE_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_LE) +#define DUK_HEAP_STRING_WRITE_FLOAT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_BE) +#define DUK_HTHREAD_STRING_WRITE_FLOAT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_BE) +#define DUK_HEAP_STRING_WRITE_FLOAT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_LE) +#define DUK_HTHREAD_STRING_WRITE_FLOAT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_LE) +#define DUK_HEAP_STRING_WRITE_INT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_BE) +#define DUK_HTHREAD_STRING_WRITE_INT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_BE) +#define DUK_HEAP_STRING_WRITE_INT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_LE) +#define DUK_HTHREAD_STRING_WRITE_INT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_LE) +#define DUK_HEAP_STRING_WRITE_UINT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_BE) +#define DUK_HEAP_STRING_WRITE_UINT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_LE) +#define DUK_HEAP_STRING_WRITE_INT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_BE) +#define DUK_HTHREAD_STRING_WRITE_INT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_BE) +#define DUK_HEAP_STRING_WRITE_INT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_LE) +#define DUK_HTHREAD_STRING_WRITE_INT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_LE) +#define DUK_HEAP_STRING_WRITE_UINT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_BE) +#define DUK_HEAP_STRING_WRITE_UINT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_LE) +#define DUK_HEAP_STRING_WRITE_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT8) +#define DUK_HTHREAD_STRING_WRITE_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT8) +#define DUK_HEAP_STRING_WRITE_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT8) +#define DUK_HTHREAD_STRING_WRITE_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT8) +#define DUK_HEAP_STRING_READ_INT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_BE) +#define DUK_HTHREAD_STRING_READ_INT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_BE) +#define DUK_HEAP_STRING_READ_INT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_LE) +#define DUK_HTHREAD_STRING_READ_INT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_LE) +#define DUK_HEAP_STRING_READ_UINT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_BE) +#define DUK_HTHREAD_STRING_READ_UINT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_BE) +#define DUK_HEAP_STRING_READ_UINT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_LE) +#define DUK_HTHREAD_STRING_READ_UINT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_LE) +#define DUK_HEAP_STRING_READ_DOUBLE_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_BE) +#define DUK_HTHREAD_STRING_READ_DOUBLE_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_BE) +#define DUK_HEAP_STRING_READ_DOUBLE_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_LE) +#define DUK_HTHREAD_STRING_READ_DOUBLE_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_LE) +#define DUK_HEAP_STRING_READ_FLOAT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_BE) +#define DUK_HTHREAD_STRING_READ_FLOAT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_BE) +#define DUK_HEAP_STRING_READ_FLOAT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_LE) +#define DUK_HTHREAD_STRING_READ_FLOAT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_LE) +#define DUK_HEAP_STRING_READ_INT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_BE) +#define DUK_HTHREAD_STRING_READ_INT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_BE) +#define DUK_HEAP_STRING_READ_INT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_LE) +#define DUK_HTHREAD_STRING_READ_INT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_LE) +#define DUK_HEAP_STRING_READ_UINT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_BE) +#define DUK_HTHREAD_STRING_READ_UINT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_BE) +#define DUK_HEAP_STRING_READ_UINT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_LE) +#define DUK_HTHREAD_STRING_READ_UINT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_LE) +#define DUK_HEAP_STRING_READ_INT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_BE) +#define DUK_HTHREAD_STRING_READ_INT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_BE) +#define DUK_HEAP_STRING_READ_INT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_LE) +#define DUK_HTHREAD_STRING_READ_INT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_LE) +#define DUK_HEAP_STRING_READ_UINT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_BE) +#define DUK_HTHREAD_STRING_READ_UINT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_BE) +#define DUK_HEAP_STRING_READ_UINT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_LE) +#define DUK_HTHREAD_STRING_READ_UINT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_LE) +#define DUK_HEAP_STRING_READ_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT8) +#define DUK_HTHREAD_STRING_READ_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT8) +#define DUK_HEAP_STRING_READ_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT8) +#define DUK_HTHREAD_STRING_READ_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT8) +#define DUK_HEAP_STRING_COPY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COPY) +#define DUK_HTHREAD_STRING_COPY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COPY) +#define DUK_HEAP_STRING_EQUALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EQUALS) +#define DUK_HTHREAD_STRING_EQUALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EQUALS) +#define DUK_HEAP_STRING_FILL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILL) +#define DUK_HTHREAD_STRING_FILL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILL) +#define DUK_HEAP_STRING_WRITE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE) +#define DUK_HTHREAD_STRING_WRITE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE) +#define DUK_HEAP_STRING_COMPARE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPARE) +#define DUK_HTHREAD_STRING_COMPARE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPARE) +#define DUK_HEAP_STRING_BYTE_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH) +#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH) +#define DUK_HEAP_STRING_IS_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_BUFFER) +#define DUK_HTHREAD_STRING_IS_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_BUFFER) +#define DUK_HEAP_STRING_IS_ENCODING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_ENCODING) +#define DUK_HTHREAD_STRING_IS_ENCODING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_ENCODING) +#define DUK_HEAP_STRING_EXPORTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS) +#define DUK_HTHREAD_STRING_EXPORTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS) #define DUK_HEAP_STRING_ID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID) #define DUK_HTHREAD_STRING_ID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID) #define DUK_HEAP_STRING_REQUIRE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE) @@ -1329,21 +1571,21 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD) #define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD) -#define DUK_HEAP_NUM_STRINGS 336 +#define DUK_HEAP_NUM_STRINGS 414 -#define DUK_STRIDX_START_RESERVED 291 -#define DUK_STRIDX_START_STRICT_RESERVED 327 -#define DUK_STRIDX_END_RESERVED 336 /* exclusive endpoint */ +#define DUK_STRIDX_START_RESERVED 369 +#define DUK_STRIDX_START_STRICT_RESERVED 405 +#define DUK_STRIDX_END_RESERVED 414 /* exclusive endpoint */ #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[128]; -DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1341]; +DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[147]; +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[187]; #endif /* DUK_USE_BUILTIN_INITJS */ #endif /* !DUK_SINGLE_FILE */ -#define DUK_BUILTINS_DATA_LENGTH 1341 +#define DUK_BUILTINS_DATA_LENGTH 1952 #ifdef DUK_USE_BUILTIN_INITJS #define DUK_BUILTIN_INITJS_DATA_LENGTH 187 #endif /* DUK_USE_BUILTIN_INITJS */ @@ -1394,353 +1636,456 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187]; #define DUK_BIDX_LOGGER_CONSTRUCTOR 43 #define DUK_BIDX_LOGGER_PROTOTYPE 44 #define DUK_BIDX_DOUBLE_ERROR 45 - -#define DUK_NUM_BUILTINS 46 +#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR 46 +#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 47 +#define DUK_BIDX_DATAVIEW_CONSTRUCTOR 48 +#define DUK_BIDX_DATAVIEW_PROTOTYPE 49 +#define DUK_BIDX_TYPEDARRAY_PROTOTYPE 50 +#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR 51 +#define DUK_BIDX_INT8ARRAY_PROTOTYPE 52 +#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR 53 +#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 54 +#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR 55 +#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 56 +#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR 57 +#define DUK_BIDX_INT16ARRAY_PROTOTYPE 58 +#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR 59 +#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 60 +#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR 61 +#define DUK_BIDX_INT32ARRAY_PROTOTYPE 62 +#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR 63 +#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 64 +#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR 65 +#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 66 +#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR 67 +#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 68 +#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR 69 +#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 70 + +#define DUK_NUM_BUILTINS 71 #elif defined(DUK_USE_DOUBLE_BE) #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; +DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_STRDATA_DATA_LENGTH 1943 +#define DUK_STRDATA_DATA_LENGTH 2624 #define DUK_STRDATA_MAX_STRLEN 24 #define DUK_STRIDX_UC_LOGGER 0 /* 'Logger' */ #define DUK_STRIDX_UC_THREAD 1 /* 'Thread' */ #define DUK_STRIDX_UC_POINTER 2 /* 'Pointer' */ -#define DUK_STRIDX_UC_BUFFER 3 /* 'Buffer' */ -#define DUK_STRIDX_DEC_ENV 4 /* 'DecEnv' */ -#define DUK_STRIDX_OBJ_ENV 5 /* 'ObjEnv' */ -#define DUK_STRIDX_EMPTY_STRING 6 /* '' */ -#define DUK_STRIDX_GLOBAL 7 /* 'global' */ -#define DUK_STRIDX_UC_ARGUMENTS 8 /* 'Arguments' */ -#define DUK_STRIDX_JSON 9 /* 'JSON' */ -#define DUK_STRIDX_MATH 10 /* 'Math' */ -#define DUK_STRIDX_UC_ERROR 11 /* 'Error' */ -#define DUK_STRIDX_REG_EXP 12 /* 'RegExp' */ -#define DUK_STRIDX_DATE 13 /* 'Date' */ -#define DUK_STRIDX_UC_NUMBER 14 /* 'Number' */ -#define DUK_STRIDX_UC_BOOLEAN 15 /* 'Boolean' */ -#define DUK_STRIDX_UC_STRING 16 /* 'String' */ -#define DUK_STRIDX_ARRAY 17 /* 'Array' */ -#define DUK_STRIDX_UC_FUNCTION 18 /* 'Function' */ -#define DUK_STRIDX_UC_OBJECT 19 /* 'Object' */ -#define DUK_STRIDX_UC_NULL 20 /* 'Null' */ -#define DUK_STRIDX_UC_UNDEFINED 21 /* 'Undefined' */ -#define DUK_STRIDX_JSON_EXT_FUNCTION2 22 /* '{_func:true}' */ -#define DUK_STRIDX_JSON_EXT_FUNCTION1 23 /* '{"_func":true}' */ -#define DUK_STRIDX_JSON_EXT_NEGINF 24 /* '{"_ninf":true}' */ -#define DUK_STRIDX_JSON_EXT_POSINF 25 /* '{"_inf":true}' */ -#define DUK_STRIDX_JSON_EXT_NAN 26 /* '{"_nan":true}' */ -#define DUK_STRIDX_JSON_EXT_UNDEFINED 27 /* '{"_undef":true}' */ -#define DUK_STRIDX_TO_LOG_STRING 28 /* 'toLogString' */ -#define DUK_STRIDX_CLOG 29 /* 'clog' */ -#define DUK_STRIDX_LC_L 30 /* 'l' */ -#define DUK_STRIDX_LC_N 31 /* 'n' */ -#define DUK_STRIDX_LC_FATAL 32 /* 'fatal' */ -#define DUK_STRIDX_LC_ERROR 33 /* 'error' */ -#define DUK_STRIDX_LC_WARN 34 /* 'warn' */ -#define DUK_STRIDX_LC_DEBUG 35 /* 'debug' */ -#define DUK_STRIDX_LC_TRACE 36 /* 'trace' */ -#define DUK_STRIDX_RAW 37 /* 'raw' */ -#define DUK_STRIDX_FMT 38 /* 'fmt' */ -#define DUK_STRIDX_CURRENT 39 /* 'current' */ -#define DUK_STRIDX_RESUME 40 /* 'resume' */ -#define DUK_STRIDX_COMPACT 41 /* 'compact' */ -#define DUK_STRIDX_JC 42 /* 'jc' */ -#define DUK_STRIDX_JX 43 /* 'jx' */ -#define DUK_STRIDX_BASE64 44 /* 'base64' */ -#define DUK_STRIDX_HEX 45 /* 'hex' */ -#define DUK_STRIDX_DEC 46 /* 'dec' */ -#define DUK_STRIDX_ENC 47 /* 'enc' */ -#define DUK_STRIDX_FIN 48 /* 'fin' */ -#define DUK_STRIDX_GC 49 /* 'gc' */ -#define DUK_STRIDX_ACT 50 /* 'act' */ -#define DUK_STRIDX_LC_INFO 51 /* 'info' */ -#define DUK_STRIDX_VERSION 52 /* 'version' */ -#define DUK_STRIDX_ENV 53 /* 'env' */ -#define DUK_STRIDX_MOD_LOADED 54 /* 'modLoaded' */ -#define DUK_STRIDX_MOD_SEARCH 55 /* 'modSearch' */ -#define DUK_STRIDX_ERR_THROW 56 /* 'errThrow' */ -#define DUK_STRIDX_ERR_CREATE 57 /* 'errCreate' */ -#define DUK_STRIDX_COMPILE 58 /* 'compile' */ -#define DUK_STRIDX_INT_REGBASE 59 /* '\x00Regbase' */ -#define DUK_STRIDX_INT_THREAD 60 /* '\x00Thread' */ -#define DUK_STRIDX_INT_HANDLER 61 /* '\x00Handler' */ -#define DUK_STRIDX_INT_FINALIZER 62 /* '\x00Finalizer' */ -#define DUK_STRIDX_INT_CALLEE 63 /* '\x00Callee' */ -#define DUK_STRIDX_INT_MAP 64 /* '\x00Map' */ -#define DUK_STRIDX_INT_ARGS 65 /* '\x00Args' */ -#define DUK_STRIDX_INT_THIS 66 /* '\x00This' */ -#define DUK_STRIDX_INT_PC2LINE 67 /* '\x00Pc2line' */ -#define DUK_STRIDX_INT_SOURCE 68 /* '\x00Source' */ -#define DUK_STRIDX_INT_VARENV 69 /* '\x00Varenv' */ -#define DUK_STRIDX_INT_LEXENV 70 /* '\x00Lexenv' */ -#define DUK_STRIDX_INT_VARMAP 71 /* '\x00Varmap' */ -#define DUK_STRIDX_INT_FORMALS 72 /* '\x00Formals' */ -#define DUK_STRIDX_INT_BYTECODE 73 /* '\x00Bytecode' */ -#define DUK_STRIDX_INT_NEXT 74 /* '\x00Next' */ -#define DUK_STRIDX_INT_TARGET 75 /* '\x00Target' */ -#define DUK_STRIDX_INT_VALUE 76 /* '\x00Value' */ -#define DUK_STRIDX_LC_POINTER 77 /* 'pointer' */ -#define DUK_STRIDX_LC_BUFFER 78 /* 'buffer' */ -#define DUK_STRIDX_INT_TRACEDATA 79 /* '\x00Tracedata' */ -#define DUK_STRIDX_LINE_NUMBER 80 /* 'lineNumber' */ -#define DUK_STRIDX_FILE_NAME 81 /* 'fileName' */ -#define DUK_STRIDX_PC 82 /* 'pc' */ -#define DUK_STRIDX_STACK 83 /* 'stack' */ -#define DUK_STRIDX_THROW_TYPE_ERROR 84 /* 'ThrowTypeError' */ -#define DUK_STRIDX_DUKTAPE 85 /* 'Duktape' */ -#define DUK_STRIDX_ID 86 /* 'id' */ -#define DUK_STRIDX_REQUIRE 87 /* 'require' */ -#define DUK_STRIDX___PROTO__ 88 /* '__proto__' */ -#define DUK_STRIDX_SET_PROTOTYPE_OF 89 /* 'setPrototypeOf' */ -#define DUK_STRIDX_OWN_KEYS 90 /* 'ownKeys' */ -#define DUK_STRIDX_ENUMERATE 91 /* 'enumerate' */ -#define DUK_STRIDX_DELETE_PROPERTY 92 /* 'deleteProperty' */ -#define DUK_STRIDX_HAS 93 /* 'has' */ -#define DUK_STRIDX_PROXY 94 /* 'Proxy' */ -#define DUK_STRIDX_CALLEE 95 /* 'callee' */ -#define DUK_STRIDX_INVALID_DATE 96 /* 'Invalid Date' */ -#define DUK_STRIDX_BRACKETED_ELLIPSIS 97 /* '[...]' */ -#define DUK_STRIDX_NEWLINE_TAB 98 /* '\n\t' */ -#define DUK_STRIDX_SPACE 99 /* ' ' */ -#define DUK_STRIDX_COMMA 100 /* ',' */ -#define DUK_STRIDX_MINUS_ZERO 101 /* '-0' */ -#define DUK_STRIDX_PLUS_ZERO 102 /* '+0' */ -#define DUK_STRIDX_ZERO 103 /* '0' */ -#define DUK_STRIDX_MINUS_INFINITY 104 /* '-Infinity' */ -#define DUK_STRIDX_PLUS_INFINITY 105 /* '+Infinity' */ -#define DUK_STRIDX_INFINITY 106 /* 'Infinity' */ -#define DUK_STRIDX_LC_OBJECT 107 /* 'object' */ -#define DUK_STRIDX_LC_STRING 108 /* 'string' */ -#define DUK_STRIDX_LC_NUMBER 109 /* 'number' */ -#define DUK_STRIDX_LC_BOOLEAN 110 /* 'boolean' */ -#define DUK_STRIDX_LC_UNDEFINED 111 /* 'undefined' */ -#define DUK_STRIDX_STRINGIFY 112 /* 'stringify' */ -#define DUK_STRIDX_TAN 113 /* 'tan' */ -#define DUK_STRIDX_SQRT 114 /* 'sqrt' */ -#define DUK_STRIDX_SIN 115 /* 'sin' */ -#define DUK_STRIDX_ROUND 116 /* 'round' */ -#define DUK_STRIDX_RANDOM 117 /* 'random' */ -#define DUK_STRIDX_POW 118 /* 'pow' */ -#define DUK_STRIDX_MIN 119 /* 'min' */ -#define DUK_STRIDX_MAX 120 /* 'max' */ -#define DUK_STRIDX_LOG 121 /* 'log' */ -#define DUK_STRIDX_FLOOR 122 /* 'floor' */ -#define DUK_STRIDX_EXP 123 /* 'exp' */ -#define DUK_STRIDX_COS 124 /* 'cos' */ -#define DUK_STRIDX_CEIL 125 /* 'ceil' */ -#define DUK_STRIDX_ATAN2 126 /* 'atan2' */ -#define DUK_STRIDX_ATAN 127 /* 'atan' */ -#define DUK_STRIDX_ASIN 128 /* 'asin' */ -#define DUK_STRIDX_ACOS 129 /* 'acos' */ -#define DUK_STRIDX_ABS 130 /* 'abs' */ -#define DUK_STRIDX_SQRT2 131 /* 'SQRT2' */ -#define DUK_STRIDX_SQRT1_2 132 /* 'SQRT1_2' */ -#define DUK_STRIDX_PI 133 /* 'PI' */ -#define DUK_STRIDX_LOG10E 134 /* 'LOG10E' */ -#define DUK_STRIDX_LOG2E 135 /* 'LOG2E' */ -#define DUK_STRIDX_LN2 136 /* 'LN2' */ -#define DUK_STRIDX_LN10 137 /* 'LN10' */ -#define DUK_STRIDX_E 138 /* 'E' */ -#define DUK_STRIDX_MESSAGE 139 /* 'message' */ -#define DUK_STRIDX_NAME 140 /* 'name' */ -#define DUK_STRIDX_INPUT 141 /* 'input' */ -#define DUK_STRIDX_INDEX 142 /* 'index' */ -#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 143 /* '(?:)' */ -#define DUK_STRIDX_LAST_INDEX 144 /* 'lastIndex' */ -#define DUK_STRIDX_MULTILINE 145 /* 'multiline' */ -#define DUK_STRIDX_IGNORE_CASE 146 /* 'ignoreCase' */ -#define DUK_STRIDX_SOURCE 147 /* 'source' */ -#define DUK_STRIDX_TEST 148 /* 'test' */ -#define DUK_STRIDX_EXEC 149 /* 'exec' */ -#define DUK_STRIDX_TO_GMT_STRING 150 /* 'toGMTString' */ -#define DUK_STRIDX_SET_YEAR 151 /* 'setYear' */ -#define DUK_STRIDX_GET_YEAR 152 /* 'getYear' */ -#define DUK_STRIDX_TO_JSON 153 /* 'toJSON' */ -#define DUK_STRIDX_TO_ISO_STRING 154 /* 'toISOString' */ -#define DUK_STRIDX_TO_UTC_STRING 155 /* 'toUTCString' */ -#define DUK_STRIDX_SET_UTC_FULL_YEAR 156 /* 'setUTCFullYear' */ -#define DUK_STRIDX_SET_FULL_YEAR 157 /* 'setFullYear' */ -#define DUK_STRIDX_SET_UTC_MONTH 158 /* 'setUTCMonth' */ -#define DUK_STRIDX_SET_MONTH 159 /* 'setMonth' */ -#define DUK_STRIDX_SET_UTC_DATE 160 /* 'setUTCDate' */ -#define DUK_STRIDX_SET_DATE 161 /* 'setDate' */ -#define DUK_STRIDX_SET_UTC_HOURS 162 /* 'setUTCHours' */ -#define DUK_STRIDX_SET_HOURS 163 /* 'setHours' */ -#define DUK_STRIDX_SET_UTC_MINUTES 164 /* 'setUTCMinutes' */ -#define DUK_STRIDX_SET_MINUTES 165 /* 'setMinutes' */ -#define DUK_STRIDX_SET_UTC_SECONDS 166 /* 'setUTCSeconds' */ -#define DUK_STRIDX_SET_SECONDS 167 /* 'setSeconds' */ -#define DUK_STRIDX_SET_UTC_MILLISECONDS 168 /* 'setUTCMilliseconds' */ -#define DUK_STRIDX_SET_MILLISECONDS 169 /* 'setMilliseconds' */ -#define DUK_STRIDX_SET_TIME 170 /* 'setTime' */ -#define DUK_STRIDX_GET_TIMEZONE_OFFSET 171 /* 'getTimezoneOffset' */ -#define DUK_STRIDX_GET_UTC_MILLISECONDS 172 /* 'getUTCMilliseconds' */ -#define DUK_STRIDX_GET_MILLISECONDS 173 /* 'getMilliseconds' */ -#define DUK_STRIDX_GET_UTC_SECONDS 174 /* 'getUTCSeconds' */ -#define DUK_STRIDX_GET_SECONDS 175 /* 'getSeconds' */ -#define DUK_STRIDX_GET_UTC_MINUTES 176 /* 'getUTCMinutes' */ -#define DUK_STRIDX_GET_MINUTES 177 /* 'getMinutes' */ -#define DUK_STRIDX_GET_UTC_HOURS 178 /* 'getUTCHours' */ -#define DUK_STRIDX_GET_HOURS 179 /* 'getHours' */ -#define DUK_STRIDX_GET_UTC_DAY 180 /* 'getUTCDay' */ -#define DUK_STRIDX_GET_DAY 181 /* 'getDay' */ -#define DUK_STRIDX_GET_UTC_DATE 182 /* 'getUTCDate' */ -#define DUK_STRIDX_GET_DATE 183 /* 'getDate' */ -#define DUK_STRIDX_GET_UTC_MONTH 184 /* 'getUTCMonth' */ -#define DUK_STRIDX_GET_MONTH 185 /* 'getMonth' */ -#define DUK_STRIDX_GET_UTC_FULL_YEAR 186 /* 'getUTCFullYear' */ -#define DUK_STRIDX_GET_FULL_YEAR 187 /* 'getFullYear' */ -#define DUK_STRIDX_GET_TIME 188 /* 'getTime' */ -#define DUK_STRIDX_TO_LOCALE_TIME_STRING 189 /* 'toLocaleTimeString' */ -#define DUK_STRIDX_TO_LOCALE_DATE_STRING 190 /* 'toLocaleDateString' */ -#define DUK_STRIDX_TO_TIME_STRING 191 /* 'toTimeString' */ -#define DUK_STRIDX_TO_DATE_STRING 192 /* 'toDateString' */ -#define DUK_STRIDX_NOW 193 /* 'now' */ -#define DUK_STRIDX_UTC 194 /* 'UTC' */ -#define DUK_STRIDX_PARSE 195 /* 'parse' */ -#define DUK_STRIDX_TO_PRECISION 196 /* 'toPrecision' */ -#define DUK_STRIDX_TO_EXPONENTIAL 197 /* 'toExponential' */ -#define DUK_STRIDX_TO_FIXED 198 /* 'toFixed' */ -#define DUK_STRIDX_POSITIVE_INFINITY 199 /* 'POSITIVE_INFINITY' */ -#define DUK_STRIDX_NEGATIVE_INFINITY 200 /* 'NEGATIVE_INFINITY' */ -#define DUK_STRIDX_NAN 201 /* 'NaN' */ -#define DUK_STRIDX_MIN_VALUE 202 /* 'MIN_VALUE' */ -#define DUK_STRIDX_MAX_VALUE 203 /* 'MAX_VALUE' */ -#define DUK_STRIDX_SUBSTR 204 /* 'substr' */ -#define DUK_STRIDX_TRIM 205 /* 'trim' */ -#define DUK_STRIDX_TO_LOCALE_UPPER_CASE 206 /* 'toLocaleUpperCase' */ -#define DUK_STRIDX_TO_UPPER_CASE 207 /* 'toUpperCase' */ -#define DUK_STRIDX_TO_LOCALE_LOWER_CASE 208 /* 'toLocaleLowerCase' */ -#define DUK_STRIDX_TO_LOWER_CASE 209 /* 'toLowerCase' */ -#define DUK_STRIDX_SUBSTRING 210 /* 'substring' */ -#define DUK_STRIDX_SPLIT 211 /* 'split' */ -#define DUK_STRIDX_SEARCH 212 /* 'search' */ -#define DUK_STRIDX_REPLACE 213 /* 'replace' */ -#define DUK_STRIDX_MATCH 214 /* 'match' */ -#define DUK_STRIDX_LOCALE_COMPARE 215 /* 'localeCompare' */ -#define DUK_STRIDX_CHAR_CODE_AT 216 /* 'charCodeAt' */ -#define DUK_STRIDX_CHAR_AT 217 /* 'charAt' */ -#define DUK_STRIDX_FROM_CHAR_CODE 218 /* 'fromCharCode' */ -#define DUK_STRIDX_REDUCE_RIGHT 219 /* 'reduceRight' */ -#define DUK_STRIDX_REDUCE 220 /* 'reduce' */ -#define DUK_STRIDX_FILTER 221 /* 'filter' */ -#define DUK_STRIDX_MAP 222 /* 'map' */ -#define DUK_STRIDX_FOR_EACH 223 /* 'forEach' */ -#define DUK_STRIDX_SOME 224 /* 'some' */ -#define DUK_STRIDX_EVERY 225 /* 'every' */ -#define DUK_STRIDX_LAST_INDEX_OF 226 /* 'lastIndexOf' */ -#define DUK_STRIDX_INDEX_OF 227 /* 'indexOf' */ -#define DUK_STRIDX_UNSHIFT 228 /* 'unshift' */ -#define DUK_STRIDX_SPLICE 229 /* 'splice' */ -#define DUK_STRIDX_SORT 230 /* 'sort' */ -#define DUK_STRIDX_SLICE 231 /* 'slice' */ -#define DUK_STRIDX_SHIFT 232 /* 'shift' */ -#define DUK_STRIDX_REVERSE 233 /* 'reverse' */ -#define DUK_STRIDX_PUSH 234 /* 'push' */ -#define DUK_STRIDX_POP 235 /* 'pop' */ -#define DUK_STRIDX_JOIN 236 /* 'join' */ -#define DUK_STRIDX_CONCAT 237 /* 'concat' */ -#define DUK_STRIDX_IS_ARRAY 238 /* 'isArray' */ -#define DUK_STRIDX_LC_ARGUMENTS 239 /* 'arguments' */ -#define DUK_STRIDX_CALLER 240 /* 'caller' */ -#define DUK_STRIDX_BIND 241 /* 'bind' */ -#define DUK_STRIDX_CALL 242 /* 'call' */ -#define DUK_STRIDX_APPLY 243 /* 'apply' */ -#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE 244 /* 'propertyIsEnumerable' */ -#define DUK_STRIDX_IS_PROTOTYPE_OF 245 /* 'isPrototypeOf' */ -#define DUK_STRIDX_HAS_OWN_PROPERTY 246 /* 'hasOwnProperty' */ -#define DUK_STRIDX_VALUE_OF 247 /* 'valueOf' */ -#define DUK_STRIDX_TO_LOCALE_STRING 248 /* 'toLocaleString' */ -#define DUK_STRIDX_TO_STRING 249 /* 'toString' */ -#define DUK_STRIDX_CONSTRUCTOR 250 /* 'constructor' */ -#define DUK_STRIDX_SET 251 /* 'set' */ -#define DUK_STRIDX_GET 252 /* 'get' */ -#define DUK_STRIDX_ENUMERABLE 253 /* 'enumerable' */ -#define DUK_STRIDX_CONFIGURABLE 254 /* 'configurable' */ -#define DUK_STRIDX_WRITABLE 255 /* 'writable' */ -#define DUK_STRIDX_VALUE 256 /* 'value' */ -#define DUK_STRIDX_KEYS 257 /* 'keys' */ -#define DUK_STRIDX_IS_EXTENSIBLE 258 /* 'isExtensible' */ -#define DUK_STRIDX_IS_FROZEN 259 /* 'isFrozen' */ -#define DUK_STRIDX_IS_SEALED 260 /* 'isSealed' */ -#define DUK_STRIDX_PREVENT_EXTENSIONS 261 /* 'preventExtensions' */ -#define DUK_STRIDX_FREEZE 262 /* 'freeze' */ -#define DUK_STRIDX_SEAL 263 /* 'seal' */ -#define DUK_STRIDX_DEFINE_PROPERTIES 264 /* 'defineProperties' */ -#define DUK_STRIDX_DEFINE_PROPERTY 265 /* 'defineProperty' */ -#define DUK_STRIDX_CREATE 266 /* 'create' */ -#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES 267 /* 'getOwnPropertyNames' */ -#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR 268 /* 'getOwnPropertyDescriptor' */ -#define DUK_STRIDX_GET_PROTOTYPE_OF 269 /* 'getPrototypeOf' */ -#define DUK_STRIDX_PROTOTYPE 270 /* 'prototype' */ -#define DUK_STRIDX_LENGTH 271 /* 'length' */ -#define DUK_STRIDX_ALERT 272 /* 'alert' */ -#define DUK_STRIDX_PRINT 273 /* 'print' */ -#define DUK_STRIDX_UNESCAPE 274 /* 'unescape' */ -#define DUK_STRIDX_ESCAPE 275 /* 'escape' */ -#define DUK_STRIDX_ENCODE_URI_COMPONENT 276 /* 'encodeURIComponent' */ -#define DUK_STRIDX_ENCODE_URI 277 /* 'encodeURI' */ -#define DUK_STRIDX_DECODE_URI_COMPONENT 278 /* 'decodeURIComponent' */ -#define DUK_STRIDX_DECODE_URI 279 /* 'decodeURI' */ -#define DUK_STRIDX_IS_FINITE 280 /* 'isFinite' */ -#define DUK_STRIDX_IS_NAN 281 /* 'isNaN' */ -#define DUK_STRIDX_PARSE_FLOAT 282 /* 'parseFloat' */ -#define DUK_STRIDX_PARSE_INT 283 /* 'parseInt' */ -#define DUK_STRIDX_EVAL 284 /* 'eval' */ -#define DUK_STRIDX_URI_ERROR 285 /* 'URIError' */ -#define DUK_STRIDX_TYPE_ERROR 286 /* 'TypeError' */ -#define DUK_STRIDX_SYNTAX_ERROR 287 /* 'SyntaxError' */ -#define DUK_STRIDX_REFERENCE_ERROR 288 /* 'ReferenceError' */ -#define DUK_STRIDX_RANGE_ERROR 289 /* 'RangeError' */ -#define DUK_STRIDX_EVAL_ERROR 290 /* 'EvalError' */ -#define DUK_STRIDX_BREAK 291 /* 'break' */ -#define DUK_STRIDX_CASE 292 /* 'case' */ -#define DUK_STRIDX_CATCH 293 /* 'catch' */ -#define DUK_STRIDX_CONTINUE 294 /* 'continue' */ -#define DUK_STRIDX_DEBUGGER 295 /* 'debugger' */ -#define DUK_STRIDX_DEFAULT 296 /* 'default' */ -#define DUK_STRIDX_DELETE 297 /* 'delete' */ -#define DUK_STRIDX_DO 298 /* 'do' */ -#define DUK_STRIDX_ELSE 299 /* 'else' */ -#define DUK_STRIDX_FINALLY 300 /* 'finally' */ -#define DUK_STRIDX_FOR 301 /* 'for' */ -#define DUK_STRIDX_LC_FUNCTION 302 /* 'function' */ -#define DUK_STRIDX_IF 303 /* 'if' */ -#define DUK_STRIDX_IN 304 /* 'in' */ -#define DUK_STRIDX_INSTANCEOF 305 /* 'instanceof' */ -#define DUK_STRIDX_NEW 306 /* 'new' */ -#define DUK_STRIDX_RETURN 307 /* 'return' */ -#define DUK_STRIDX_SWITCH 308 /* 'switch' */ -#define DUK_STRIDX_THIS 309 /* 'this' */ -#define DUK_STRIDX_THROW 310 /* 'throw' */ -#define DUK_STRIDX_TRY 311 /* 'try' */ -#define DUK_STRIDX_TYPEOF 312 /* 'typeof' */ -#define DUK_STRIDX_VAR 313 /* 'var' */ -#define DUK_STRIDX_VOID 314 /* 'void' */ -#define DUK_STRIDX_WHILE 315 /* 'while' */ -#define DUK_STRIDX_WITH 316 /* 'with' */ -#define DUK_STRIDX_CLASS 317 /* 'class' */ -#define DUK_STRIDX_CONST 318 /* 'const' */ -#define DUK_STRIDX_ENUM 319 /* 'enum' */ -#define DUK_STRIDX_EXPORT 320 /* 'export' */ -#define DUK_STRIDX_EXTENDS 321 /* 'extends' */ -#define DUK_STRIDX_IMPORT 322 /* 'import' */ -#define DUK_STRIDX_SUPER 323 /* 'super' */ -#define DUK_STRIDX_LC_NULL 324 /* 'null' */ -#define DUK_STRIDX_TRUE 325 /* 'true' */ -#define DUK_STRIDX_FALSE 326 /* 'false' */ -#define DUK_STRIDX_IMPLEMENTS 327 /* 'implements' */ -#define DUK_STRIDX_INTERFACE 328 /* 'interface' */ -#define DUK_STRIDX_LET 329 /* 'let' */ -#define DUK_STRIDX_PACKAGE 330 /* 'package' */ -#define DUK_STRIDX_PRIVATE 331 /* 'private' */ -#define DUK_STRIDX_PROTECTED 332 /* 'protected' */ -#define DUK_STRIDX_PUBLIC 333 /* 'public' */ -#define DUK_STRIDX_STATIC 334 /* 'static' */ -#define DUK_STRIDX_YIELD 335 /* 'yield' */ +#define DUK_STRIDX_DEC_ENV 3 /* 'DecEnv' */ +#define DUK_STRIDX_OBJ_ENV 4 /* 'ObjEnv' */ +#define DUK_STRIDX_FLOAT64_ARRAY 5 /* 'Float64Array' */ +#define DUK_STRIDX_FLOAT32_ARRAY 6 /* 'Float32Array' */ +#define DUK_STRIDX_UINT32_ARRAY 7 /* 'Uint32Array' */ +#define DUK_STRIDX_INT32_ARRAY 8 /* 'Int32Array' */ +#define DUK_STRIDX_UINT16_ARRAY 9 /* 'Uint16Array' */ +#define DUK_STRIDX_INT16_ARRAY 10 /* 'Int16Array' */ +#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 11 /* 'Uint8ClampedArray' */ +#define DUK_STRIDX_UINT8_ARRAY 12 /* 'Uint8Array' */ +#define DUK_STRIDX_INT8_ARRAY 13 /* 'Int8Array' */ +#define DUK_STRIDX_DATA_VIEW 14 /* 'DataView' */ +#define DUK_STRIDX_ARRAY_BUFFER 15 /* 'ArrayBuffer' */ +#define DUK_STRIDX_UC_BUFFER 16 /* 'Buffer' */ +#define DUK_STRIDX_EMPTY_STRING 17 /* '' */ +#define DUK_STRIDX_GLOBAL 18 /* 'global' */ +#define DUK_STRIDX_UC_ARGUMENTS 19 /* 'Arguments' */ +#define DUK_STRIDX_JSON 20 /* 'JSON' */ +#define DUK_STRIDX_MATH 21 /* 'Math' */ +#define DUK_STRIDX_UC_ERROR 22 /* 'Error' */ +#define DUK_STRIDX_REG_EXP 23 /* 'RegExp' */ +#define DUK_STRIDX_DATE 24 /* 'Date' */ +#define DUK_STRIDX_UC_NUMBER 25 /* 'Number' */ +#define DUK_STRIDX_UC_BOOLEAN 26 /* 'Boolean' */ +#define DUK_STRIDX_UC_STRING 27 /* 'String' */ +#define DUK_STRIDX_ARRAY 28 /* 'Array' */ +#define DUK_STRIDX_UC_FUNCTION 29 /* 'Function' */ +#define DUK_STRIDX_UC_OBJECT 30 /* 'Object' */ +#define DUK_STRIDX_UC_NULL 31 /* 'Null' */ +#define DUK_STRIDX_UC_UNDEFINED 32 /* 'Undefined' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION2 33 /* '{_func:true}' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION1 34 /* '{"_func":true}' */ +#define DUK_STRIDX_JSON_EXT_NEGINF 35 /* '{"_ninf":true}' */ +#define DUK_STRIDX_JSON_EXT_POSINF 36 /* '{"_inf":true}' */ +#define DUK_STRIDX_JSON_EXT_NAN 37 /* '{"_nan":true}' */ +#define DUK_STRIDX_JSON_EXT_UNDEFINED 38 /* '{"_undef":true}' */ +#define DUK_STRIDX_TO_LOG_STRING 39 /* 'toLogString' */ +#define DUK_STRIDX_CLOG 40 /* 'clog' */ +#define DUK_STRIDX_LC_L 41 /* 'l' */ +#define DUK_STRIDX_LC_N 42 /* 'n' */ +#define DUK_STRIDX_LC_FATAL 43 /* 'fatal' */ +#define DUK_STRIDX_LC_ERROR 44 /* 'error' */ +#define DUK_STRIDX_LC_WARN 45 /* 'warn' */ +#define DUK_STRIDX_LC_DEBUG 46 /* 'debug' */ +#define DUK_STRIDX_LC_TRACE 47 /* 'trace' */ +#define DUK_STRIDX_RAW 48 /* 'raw' */ +#define DUK_STRIDX_FMT 49 /* 'fmt' */ +#define DUK_STRIDX_CURRENT 50 /* 'current' */ +#define DUK_STRIDX_RESUME 51 /* 'resume' */ +#define DUK_STRIDX_COMPACT 52 /* 'compact' */ +#define DUK_STRIDX_JC 53 /* 'jc' */ +#define DUK_STRIDX_JX 54 /* 'jx' */ +#define DUK_STRIDX_BASE64 55 /* 'base64' */ +#define DUK_STRIDX_HEX 56 /* 'hex' */ +#define DUK_STRIDX_DEC 57 /* 'dec' */ +#define DUK_STRIDX_ENC 58 /* 'enc' */ +#define DUK_STRIDX_FIN 59 /* 'fin' */ +#define DUK_STRIDX_GC 60 /* 'gc' */ +#define DUK_STRIDX_ACT 61 /* 'act' */ +#define DUK_STRIDX_LC_INFO 62 /* 'info' */ +#define DUK_STRIDX_VERSION 63 /* 'version' */ +#define DUK_STRIDX_ENV 64 /* 'env' */ +#define DUK_STRIDX_MOD_LOADED 65 /* 'modLoaded' */ +#define DUK_STRIDX_MOD_SEARCH 66 /* 'modSearch' */ +#define DUK_STRIDX_ERR_THROW 67 /* 'errThrow' */ +#define DUK_STRIDX_ERR_CREATE 68 /* 'errCreate' */ +#define DUK_STRIDX_COMPILE 69 /* 'compile' */ +#define DUK_STRIDX_INT_REGBASE 70 /* '\x00Regbase' */ +#define DUK_STRIDX_INT_THREAD 71 /* '\x00Thread' */ +#define DUK_STRIDX_INT_HANDLER 72 /* '\x00Handler' */ +#define DUK_STRIDX_INT_FINALIZER 73 /* '\x00Finalizer' */ +#define DUK_STRIDX_INT_CALLEE 74 /* '\x00Callee' */ +#define DUK_STRIDX_INT_MAP 75 /* '\x00Map' */ +#define DUK_STRIDX_INT_ARGS 76 /* '\x00Args' */ +#define DUK_STRIDX_INT_THIS 77 /* '\x00This' */ +#define DUK_STRIDX_INT_PC2LINE 78 /* '\x00Pc2line' */ +#define DUK_STRIDX_INT_SOURCE 79 /* '\x00Source' */ +#define DUK_STRIDX_INT_VARENV 80 /* '\x00Varenv' */ +#define DUK_STRIDX_INT_LEXENV 81 /* '\x00Lexenv' */ +#define DUK_STRIDX_INT_VARMAP 82 /* '\x00Varmap' */ +#define DUK_STRIDX_INT_FORMALS 83 /* '\x00Formals' */ +#define DUK_STRIDX_INT_BYTECODE 84 /* '\x00Bytecode' */ +#define DUK_STRIDX_INT_NEXT 85 /* '\x00Next' */ +#define DUK_STRIDX_INT_TARGET 86 /* '\x00Target' */ +#define DUK_STRIDX_INT_VALUE 87 /* '\x00Value' */ +#define DUK_STRIDX_LC_POINTER 88 /* 'pointer' */ +#define DUK_STRIDX_INT_TRACEDATA 89 /* '\x00Tracedata' */ +#define DUK_STRIDX_LINE_NUMBER 90 /* 'lineNumber' */ +#define DUK_STRIDX_FILE_NAME 91 /* 'fileName' */ +#define DUK_STRIDX_PC 92 /* 'pc' */ +#define DUK_STRIDX_STACK 93 /* 'stack' */ +#define DUK_STRIDX_THROW_TYPE_ERROR 94 /* 'ThrowTypeError' */ +#define DUK_STRIDX_DUKTAPE 95 /* 'Duktape' */ +#define DUK_STRIDX_SET_FLOAT64 96 /* 'setFloat64' */ +#define DUK_STRIDX_SET_FLOAT32 97 /* 'setFloat32' */ +#define DUK_STRIDX_SET_UINT32 98 /* 'setUint32' */ +#define DUK_STRIDX_SET_INT32 99 /* 'setInt32' */ +#define DUK_STRIDX_SET_UINT16 100 /* 'setUint16' */ +#define DUK_STRIDX_SET_INT16 101 /* 'setInt16' */ +#define DUK_STRIDX_SET_UINT8 102 /* 'setUint8' */ +#define DUK_STRIDX_SET_INT8 103 /* 'setInt8' */ +#define DUK_STRIDX_GET_FLOAT64 104 /* 'getFloat64' */ +#define DUK_STRIDX_GET_FLOAT32 105 /* 'getFloat32' */ +#define DUK_STRIDX_GET_UINT32 106 /* 'getUint32' */ +#define DUK_STRIDX_GET_INT32 107 /* 'getInt32' */ +#define DUK_STRIDX_GET_UINT16 108 /* 'getUint16' */ +#define DUK_STRIDX_GET_INT16 109 /* 'getInt16' */ +#define DUK_STRIDX_GET_UINT8 110 /* 'getUint8' */ +#define DUK_STRIDX_GET_INT8 111 /* 'getInt8' */ +#define DUK_STRIDX_SUBARRAY 112 /* 'subarray' */ +#define DUK_STRIDX_BYTES_PER_ELEMENT 113 /* 'BYTES_PER_ELEMENT' */ +#define DUK_STRIDX_BYTE_OFFSET 114 /* 'byteOffset' */ +#define DUK_STRIDX_LC_BUFFER 115 /* 'buffer' */ +#define DUK_STRIDX_IS_VIEW 116 /* 'isView' */ +#define DUK_STRIDX_DATA 117 /* 'data' */ +#define DUK_STRIDX_TYPE 118 /* 'type' */ +#define DUK_STRIDX_WRITE_INT_BE 119 /* 'writeIntBE' */ +#define DUK_STRIDX_WRITE_INT_LE 120 /* 'writeIntLE' */ +#define DUK_STRIDX_WRITE_UINT_BE 121 /* 'writeUIntBE' */ +#define DUK_STRIDX_WRITE_UINT_LE 122 /* 'writeUIntLE' */ +#define DUK_STRIDX_WRITE_DOUBLE_BE 123 /* 'writeDoubleBE' */ +#define DUK_STRIDX_WRITE_DOUBLE_LE 124 /* 'writeDoubleLE' */ +#define DUK_STRIDX_WRITE_FLOAT_BE 125 /* 'writeFloatBE' */ +#define DUK_STRIDX_WRITE_FLOAT_LE 126 /* 'writeFloatLE' */ +#define DUK_STRIDX_WRITE_INT32_BE 127 /* 'writeInt32BE' */ +#define DUK_STRIDX_WRITE_INT32_LE 128 /* 'writeInt32LE' */ +#define DUK_STRIDX_WRITE_UINT32_BE 129 /* 'writeUInt32BE' */ +#define DUK_STRIDX_WRITE_UINT32_LE 130 /* 'writeUInt32LE' */ +#define DUK_STRIDX_WRITE_INT16_BE 131 /* 'writeInt16BE' */ +#define DUK_STRIDX_WRITE_INT16_LE 132 /* 'writeInt16LE' */ +#define DUK_STRIDX_WRITE_UINT16_BE 133 /* 'writeUInt16BE' */ +#define DUK_STRIDX_WRITE_UINT16_LE 134 /* 'writeUInt16LE' */ +#define DUK_STRIDX_WRITE_INT8 135 /* 'writeInt8' */ +#define DUK_STRIDX_WRITE_UINT8 136 /* 'writeUInt8' */ +#define DUK_STRIDX_READ_INT_BE 137 /* 'readIntBE' */ +#define DUK_STRIDX_READ_INT_LE 138 /* 'readIntLE' */ +#define DUK_STRIDX_READ_UINT_BE 139 /* 'readUIntBE' */ +#define DUK_STRIDX_READ_UINT_LE 140 /* 'readUIntLE' */ +#define DUK_STRIDX_READ_DOUBLE_BE 141 /* 'readDoubleBE' */ +#define DUK_STRIDX_READ_DOUBLE_LE 142 /* 'readDoubleLE' */ +#define DUK_STRIDX_READ_FLOAT_BE 143 /* 'readFloatBE' */ +#define DUK_STRIDX_READ_FLOAT_LE 144 /* 'readFloatLE' */ +#define DUK_STRIDX_READ_INT32_BE 145 /* 'readInt32BE' */ +#define DUK_STRIDX_READ_INT32_LE 146 /* 'readInt32LE' */ +#define DUK_STRIDX_READ_UINT32_BE 147 /* 'readUInt32BE' */ +#define DUK_STRIDX_READ_UINT32_LE 148 /* 'readUInt32LE' */ +#define DUK_STRIDX_READ_INT16_BE 149 /* 'readInt16BE' */ +#define DUK_STRIDX_READ_INT16_LE 150 /* 'readInt16LE' */ +#define DUK_STRIDX_READ_UINT16_BE 151 /* 'readUInt16BE' */ +#define DUK_STRIDX_READ_UINT16_LE 152 /* 'readUInt16LE' */ +#define DUK_STRIDX_READ_INT8 153 /* 'readInt8' */ +#define DUK_STRIDX_READ_UINT8 154 /* 'readUInt8' */ +#define DUK_STRIDX_COPY 155 /* 'copy' */ +#define DUK_STRIDX_EQUALS 156 /* 'equals' */ +#define DUK_STRIDX_FILL 157 /* 'fill' */ +#define DUK_STRIDX_WRITE 158 /* 'write' */ +#define DUK_STRIDX_COMPARE 159 /* 'compare' */ +#define DUK_STRIDX_BYTE_LENGTH 160 /* 'byteLength' */ +#define DUK_STRIDX_IS_BUFFER 161 /* 'isBuffer' */ +#define DUK_STRIDX_IS_ENCODING 162 /* 'isEncoding' */ +#define DUK_STRIDX_EXPORTS 163 /* 'exports' */ +#define DUK_STRIDX_ID 164 /* 'id' */ +#define DUK_STRIDX_REQUIRE 165 /* 'require' */ +#define DUK_STRIDX___PROTO__ 166 /* '__proto__' */ +#define DUK_STRIDX_SET_PROTOTYPE_OF 167 /* 'setPrototypeOf' */ +#define DUK_STRIDX_OWN_KEYS 168 /* 'ownKeys' */ +#define DUK_STRIDX_ENUMERATE 169 /* 'enumerate' */ +#define DUK_STRIDX_DELETE_PROPERTY 170 /* 'deleteProperty' */ +#define DUK_STRIDX_HAS 171 /* 'has' */ +#define DUK_STRIDX_PROXY 172 /* 'Proxy' */ +#define DUK_STRIDX_CALLEE 173 /* 'callee' */ +#define DUK_STRIDX_INVALID_DATE 174 /* 'Invalid Date' */ +#define DUK_STRIDX_BRACKETED_ELLIPSIS 175 /* '[...]' */ +#define DUK_STRIDX_NEWLINE_TAB 176 /* '\n\t' */ +#define DUK_STRIDX_SPACE 177 /* ' ' */ +#define DUK_STRIDX_COMMA 178 /* ',' */ +#define DUK_STRIDX_MINUS_ZERO 179 /* '-0' */ +#define DUK_STRIDX_PLUS_ZERO 180 /* '+0' */ +#define DUK_STRIDX_ZERO 181 /* '0' */ +#define DUK_STRIDX_MINUS_INFINITY 182 /* '-Infinity' */ +#define DUK_STRIDX_PLUS_INFINITY 183 /* '+Infinity' */ +#define DUK_STRIDX_INFINITY 184 /* 'Infinity' */ +#define DUK_STRIDX_LC_OBJECT 185 /* 'object' */ +#define DUK_STRIDX_LC_STRING 186 /* 'string' */ +#define DUK_STRIDX_LC_NUMBER 187 /* 'number' */ +#define DUK_STRIDX_LC_BOOLEAN 188 /* 'boolean' */ +#define DUK_STRIDX_LC_UNDEFINED 189 /* 'undefined' */ +#define DUK_STRIDX_STRINGIFY 190 /* 'stringify' */ +#define DUK_STRIDX_TAN 191 /* 'tan' */ +#define DUK_STRIDX_SQRT 192 /* 'sqrt' */ +#define DUK_STRIDX_SIN 193 /* 'sin' */ +#define DUK_STRIDX_ROUND 194 /* 'round' */ +#define DUK_STRIDX_RANDOM 195 /* 'random' */ +#define DUK_STRIDX_POW 196 /* 'pow' */ +#define DUK_STRIDX_MIN 197 /* 'min' */ +#define DUK_STRIDX_MAX 198 /* 'max' */ +#define DUK_STRIDX_LOG 199 /* 'log' */ +#define DUK_STRIDX_FLOOR 200 /* 'floor' */ +#define DUK_STRIDX_EXP 201 /* 'exp' */ +#define DUK_STRIDX_COS 202 /* 'cos' */ +#define DUK_STRIDX_CEIL 203 /* 'ceil' */ +#define DUK_STRIDX_ATAN2 204 /* 'atan2' */ +#define DUK_STRIDX_ATAN 205 /* 'atan' */ +#define DUK_STRIDX_ASIN 206 /* 'asin' */ +#define DUK_STRIDX_ACOS 207 /* 'acos' */ +#define DUK_STRIDX_ABS 208 /* 'abs' */ +#define DUK_STRIDX_SQRT2 209 /* 'SQRT2' */ +#define DUK_STRIDX_SQRT1_2 210 /* 'SQRT1_2' */ +#define DUK_STRIDX_PI 211 /* 'PI' */ +#define DUK_STRIDX_LOG10E 212 /* 'LOG10E' */ +#define DUK_STRIDX_LOG2E 213 /* 'LOG2E' */ +#define DUK_STRIDX_LN2 214 /* 'LN2' */ +#define DUK_STRIDX_LN10 215 /* 'LN10' */ +#define DUK_STRIDX_E 216 /* 'E' */ +#define DUK_STRIDX_MESSAGE 217 /* 'message' */ +#define DUK_STRIDX_NAME 218 /* 'name' */ +#define DUK_STRIDX_INPUT 219 /* 'input' */ +#define DUK_STRIDX_INDEX 220 /* 'index' */ +#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 221 /* '(?:)' */ +#define DUK_STRIDX_LAST_INDEX 222 /* 'lastIndex' */ +#define DUK_STRIDX_MULTILINE 223 /* 'multiline' */ +#define DUK_STRIDX_IGNORE_CASE 224 /* 'ignoreCase' */ +#define DUK_STRIDX_SOURCE 225 /* 'source' */ +#define DUK_STRIDX_TEST 226 /* 'test' */ +#define DUK_STRIDX_EXEC 227 /* 'exec' */ +#define DUK_STRIDX_TO_GMT_STRING 228 /* 'toGMTString' */ +#define DUK_STRIDX_SET_YEAR 229 /* 'setYear' */ +#define DUK_STRIDX_GET_YEAR 230 /* 'getYear' */ +#define DUK_STRIDX_TO_JSON 231 /* 'toJSON' */ +#define DUK_STRIDX_TO_ISO_STRING 232 /* 'toISOString' */ +#define DUK_STRIDX_TO_UTC_STRING 233 /* 'toUTCString' */ +#define DUK_STRIDX_SET_UTC_FULL_YEAR 234 /* 'setUTCFullYear' */ +#define DUK_STRIDX_SET_FULL_YEAR 235 /* 'setFullYear' */ +#define DUK_STRIDX_SET_UTC_MONTH 236 /* 'setUTCMonth' */ +#define DUK_STRIDX_SET_MONTH 237 /* 'setMonth' */ +#define DUK_STRIDX_SET_UTC_DATE 238 /* 'setUTCDate' */ +#define DUK_STRIDX_SET_DATE 239 /* 'setDate' */ +#define DUK_STRIDX_SET_UTC_HOURS 240 /* 'setUTCHours' */ +#define DUK_STRIDX_SET_HOURS 241 /* 'setHours' */ +#define DUK_STRIDX_SET_UTC_MINUTES 242 /* 'setUTCMinutes' */ +#define DUK_STRIDX_SET_MINUTES 243 /* 'setMinutes' */ +#define DUK_STRIDX_SET_UTC_SECONDS 244 /* 'setUTCSeconds' */ +#define DUK_STRIDX_SET_SECONDS 245 /* 'setSeconds' */ +#define DUK_STRIDX_SET_UTC_MILLISECONDS 246 /* 'setUTCMilliseconds' */ +#define DUK_STRIDX_SET_MILLISECONDS 247 /* 'setMilliseconds' */ +#define DUK_STRIDX_SET_TIME 248 /* 'setTime' */ +#define DUK_STRIDX_GET_TIMEZONE_OFFSET 249 /* 'getTimezoneOffset' */ +#define DUK_STRIDX_GET_UTC_MILLISECONDS 250 /* 'getUTCMilliseconds' */ +#define DUK_STRIDX_GET_MILLISECONDS 251 /* 'getMilliseconds' */ +#define DUK_STRIDX_GET_UTC_SECONDS 252 /* 'getUTCSeconds' */ +#define DUK_STRIDX_GET_SECONDS 253 /* 'getSeconds' */ +#define DUK_STRIDX_GET_UTC_MINUTES 254 /* 'getUTCMinutes' */ +#define DUK_STRIDX_GET_MINUTES 255 /* 'getMinutes' */ +#define DUK_STRIDX_GET_UTC_HOURS 256 /* 'getUTCHours' */ +#define DUK_STRIDX_GET_HOURS 257 /* 'getHours' */ +#define DUK_STRIDX_GET_UTC_DAY 258 /* 'getUTCDay' */ +#define DUK_STRIDX_GET_DAY 259 /* 'getDay' */ +#define DUK_STRIDX_GET_UTC_DATE 260 /* 'getUTCDate' */ +#define DUK_STRIDX_GET_DATE 261 /* 'getDate' */ +#define DUK_STRIDX_GET_UTC_MONTH 262 /* 'getUTCMonth' */ +#define DUK_STRIDX_GET_MONTH 263 /* 'getMonth' */ +#define DUK_STRIDX_GET_UTC_FULL_YEAR 264 /* 'getUTCFullYear' */ +#define DUK_STRIDX_GET_FULL_YEAR 265 /* 'getFullYear' */ +#define DUK_STRIDX_GET_TIME 266 /* 'getTime' */ +#define DUK_STRIDX_TO_LOCALE_TIME_STRING 267 /* 'toLocaleTimeString' */ +#define DUK_STRIDX_TO_LOCALE_DATE_STRING 268 /* 'toLocaleDateString' */ +#define DUK_STRIDX_TO_TIME_STRING 269 /* 'toTimeString' */ +#define DUK_STRIDX_TO_DATE_STRING 270 /* 'toDateString' */ +#define DUK_STRIDX_NOW 271 /* 'now' */ +#define DUK_STRIDX_UTC 272 /* 'UTC' */ +#define DUK_STRIDX_PARSE 273 /* 'parse' */ +#define DUK_STRIDX_TO_PRECISION 274 /* 'toPrecision' */ +#define DUK_STRIDX_TO_EXPONENTIAL 275 /* 'toExponential' */ +#define DUK_STRIDX_TO_FIXED 276 /* 'toFixed' */ +#define DUK_STRIDX_POSITIVE_INFINITY 277 /* 'POSITIVE_INFINITY' */ +#define DUK_STRIDX_NEGATIVE_INFINITY 278 /* 'NEGATIVE_INFINITY' */ +#define DUK_STRIDX_NAN 279 /* 'NaN' */ +#define DUK_STRIDX_MIN_VALUE 280 /* 'MIN_VALUE' */ +#define DUK_STRIDX_MAX_VALUE 281 /* 'MAX_VALUE' */ +#define DUK_STRIDX_SUBSTR 282 /* 'substr' */ +#define DUK_STRIDX_TRIM 283 /* 'trim' */ +#define DUK_STRIDX_TO_LOCALE_UPPER_CASE 284 /* 'toLocaleUpperCase' */ +#define DUK_STRIDX_TO_UPPER_CASE 285 /* 'toUpperCase' */ +#define DUK_STRIDX_TO_LOCALE_LOWER_CASE 286 /* 'toLocaleLowerCase' */ +#define DUK_STRIDX_TO_LOWER_CASE 287 /* 'toLowerCase' */ +#define DUK_STRIDX_SUBSTRING 288 /* 'substring' */ +#define DUK_STRIDX_SPLIT 289 /* 'split' */ +#define DUK_STRIDX_SEARCH 290 /* 'search' */ +#define DUK_STRIDX_REPLACE 291 /* 'replace' */ +#define DUK_STRIDX_MATCH 292 /* 'match' */ +#define DUK_STRIDX_LOCALE_COMPARE 293 /* 'localeCompare' */ +#define DUK_STRIDX_CHAR_CODE_AT 294 /* 'charCodeAt' */ +#define DUK_STRIDX_CHAR_AT 295 /* 'charAt' */ +#define DUK_STRIDX_FROM_CHAR_CODE 296 /* 'fromCharCode' */ +#define DUK_STRIDX_REDUCE_RIGHT 297 /* 'reduceRight' */ +#define DUK_STRIDX_REDUCE 298 /* 'reduce' */ +#define DUK_STRIDX_FILTER 299 /* 'filter' */ +#define DUK_STRIDX_MAP 300 /* 'map' */ +#define DUK_STRIDX_FOR_EACH 301 /* 'forEach' */ +#define DUK_STRIDX_SOME 302 /* 'some' */ +#define DUK_STRIDX_EVERY 303 /* 'every' */ +#define DUK_STRIDX_LAST_INDEX_OF 304 /* 'lastIndexOf' */ +#define DUK_STRIDX_INDEX_OF 305 /* 'indexOf' */ +#define DUK_STRIDX_UNSHIFT 306 /* 'unshift' */ +#define DUK_STRIDX_SPLICE 307 /* 'splice' */ +#define DUK_STRIDX_SORT 308 /* 'sort' */ +#define DUK_STRIDX_SLICE 309 /* 'slice' */ +#define DUK_STRIDX_SHIFT 310 /* 'shift' */ +#define DUK_STRIDX_REVERSE 311 /* 'reverse' */ +#define DUK_STRIDX_PUSH 312 /* 'push' */ +#define DUK_STRIDX_POP 313 /* 'pop' */ +#define DUK_STRIDX_JOIN 314 /* 'join' */ +#define DUK_STRIDX_CONCAT 315 /* 'concat' */ +#define DUK_STRIDX_IS_ARRAY 316 /* 'isArray' */ +#define DUK_STRIDX_LC_ARGUMENTS 317 /* 'arguments' */ +#define DUK_STRIDX_CALLER 318 /* 'caller' */ +#define DUK_STRIDX_BIND 319 /* 'bind' */ +#define DUK_STRIDX_CALL 320 /* 'call' */ +#define DUK_STRIDX_APPLY 321 /* 'apply' */ +#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE 322 /* 'propertyIsEnumerable' */ +#define DUK_STRIDX_IS_PROTOTYPE_OF 323 /* 'isPrototypeOf' */ +#define DUK_STRIDX_HAS_OWN_PROPERTY 324 /* 'hasOwnProperty' */ +#define DUK_STRIDX_VALUE_OF 325 /* 'valueOf' */ +#define DUK_STRIDX_TO_LOCALE_STRING 326 /* 'toLocaleString' */ +#define DUK_STRIDX_TO_STRING 327 /* 'toString' */ +#define DUK_STRIDX_CONSTRUCTOR 328 /* 'constructor' */ +#define DUK_STRIDX_SET 329 /* 'set' */ +#define DUK_STRIDX_GET 330 /* 'get' */ +#define DUK_STRIDX_ENUMERABLE 331 /* 'enumerable' */ +#define DUK_STRIDX_CONFIGURABLE 332 /* 'configurable' */ +#define DUK_STRIDX_WRITABLE 333 /* 'writable' */ +#define DUK_STRIDX_VALUE 334 /* 'value' */ +#define DUK_STRIDX_KEYS 335 /* 'keys' */ +#define DUK_STRIDX_IS_EXTENSIBLE 336 /* 'isExtensible' */ +#define DUK_STRIDX_IS_FROZEN 337 /* 'isFrozen' */ +#define DUK_STRIDX_IS_SEALED 338 /* 'isSealed' */ +#define DUK_STRIDX_PREVENT_EXTENSIONS 339 /* 'preventExtensions' */ +#define DUK_STRIDX_FREEZE 340 /* 'freeze' */ +#define DUK_STRIDX_SEAL 341 /* 'seal' */ +#define DUK_STRIDX_DEFINE_PROPERTIES 342 /* 'defineProperties' */ +#define DUK_STRIDX_DEFINE_PROPERTY 343 /* 'defineProperty' */ +#define DUK_STRIDX_CREATE 344 /* 'create' */ +#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES 345 /* 'getOwnPropertyNames' */ +#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR 346 /* 'getOwnPropertyDescriptor' */ +#define DUK_STRIDX_GET_PROTOTYPE_OF 347 /* 'getPrototypeOf' */ +#define DUK_STRIDX_PROTOTYPE 348 /* 'prototype' */ +#define DUK_STRIDX_LENGTH 349 /* 'length' */ +#define DUK_STRIDX_ALERT 350 /* 'alert' */ +#define DUK_STRIDX_PRINT 351 /* 'print' */ +#define DUK_STRIDX_UNESCAPE 352 /* 'unescape' */ +#define DUK_STRIDX_ESCAPE 353 /* 'escape' */ +#define DUK_STRIDX_ENCODE_URI_COMPONENT 354 /* 'encodeURIComponent' */ +#define DUK_STRIDX_ENCODE_URI 355 /* 'encodeURI' */ +#define DUK_STRIDX_DECODE_URI_COMPONENT 356 /* 'decodeURIComponent' */ +#define DUK_STRIDX_DECODE_URI 357 /* 'decodeURI' */ +#define DUK_STRIDX_IS_FINITE 358 /* 'isFinite' */ +#define DUK_STRIDX_IS_NAN 359 /* 'isNaN' */ +#define DUK_STRIDX_PARSE_FLOAT 360 /* 'parseFloat' */ +#define DUK_STRIDX_PARSE_INT 361 /* 'parseInt' */ +#define DUK_STRIDX_EVAL 362 /* 'eval' */ +#define DUK_STRIDX_URI_ERROR 363 /* 'URIError' */ +#define DUK_STRIDX_TYPE_ERROR 364 /* 'TypeError' */ +#define DUK_STRIDX_SYNTAX_ERROR 365 /* 'SyntaxError' */ +#define DUK_STRIDX_REFERENCE_ERROR 366 /* 'ReferenceError' */ +#define DUK_STRIDX_RANGE_ERROR 367 /* 'RangeError' */ +#define DUK_STRIDX_EVAL_ERROR 368 /* 'EvalError' */ +#define DUK_STRIDX_BREAK 369 /* 'break' */ +#define DUK_STRIDX_CASE 370 /* 'case' */ +#define DUK_STRIDX_CATCH 371 /* 'catch' */ +#define DUK_STRIDX_CONTINUE 372 /* 'continue' */ +#define DUK_STRIDX_DEBUGGER 373 /* 'debugger' */ +#define DUK_STRIDX_DEFAULT 374 /* 'default' */ +#define DUK_STRIDX_DELETE 375 /* 'delete' */ +#define DUK_STRIDX_DO 376 /* 'do' */ +#define DUK_STRIDX_ELSE 377 /* 'else' */ +#define DUK_STRIDX_FINALLY 378 /* 'finally' */ +#define DUK_STRIDX_FOR 379 /* 'for' */ +#define DUK_STRIDX_LC_FUNCTION 380 /* 'function' */ +#define DUK_STRIDX_IF 381 /* 'if' */ +#define DUK_STRIDX_IN 382 /* 'in' */ +#define DUK_STRIDX_INSTANCEOF 383 /* 'instanceof' */ +#define DUK_STRIDX_NEW 384 /* 'new' */ +#define DUK_STRIDX_RETURN 385 /* 'return' */ +#define DUK_STRIDX_SWITCH 386 /* 'switch' */ +#define DUK_STRIDX_THIS 387 /* 'this' */ +#define DUK_STRIDX_THROW 388 /* 'throw' */ +#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_ENUM 397 /* 'enum' */ +#define DUK_STRIDX_EXPORT 398 /* 'export' */ +#define DUK_STRIDX_EXTENDS 399 /* 'extends' */ +#define DUK_STRIDX_IMPORT 400 /* 'import' */ +#define DUK_STRIDX_SUPER 401 /* 'super' */ +#define DUK_STRIDX_LC_NULL 402 /* 'null' */ +#define DUK_STRIDX_TRUE 403 /* 'true' */ +#define DUK_STRIDX_FALSE 404 /* 'false' */ +#define DUK_STRIDX_IMPLEMENTS 405 /* 'implements' */ +#define DUK_STRIDX_INTERFACE 406 /* 'interface' */ +#define DUK_STRIDX_LET 407 /* 'let' */ +#define DUK_STRIDX_PACKAGE 408 /* 'package' */ +#define DUK_STRIDX_PRIVATE 409 /* 'private' */ +#define DUK_STRIDX_PROTECTED 410 /* 'protected' */ +#define DUK_STRIDX_PUBLIC 411 /* 'public' */ +#define DUK_STRIDX_STATIC 412 /* 'static' */ +#define DUK_STRIDX_YIELD 413 /* 'yield' */ #define DUK_HEAP_STRING_UC_LOGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_LOGGER) #define DUK_HTHREAD_STRING_UC_LOGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_LOGGER) @@ -1748,12 +2093,34 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD) #define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER) #define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER) -#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) -#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) #define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV) #define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV) #define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV) #define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV) +#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY) +#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY) +#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY) +#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY) +#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY) +#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY) +#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW) +#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW) +#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) +#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) #define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING) #define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING) #define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL) @@ -1898,8 +2265,6 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE) #define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER) #define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER) -#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER) -#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER) #define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA) #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA) #define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER) @@ -1914,6 +2279,142 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_THROW_TYPE_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW_TYPE_ERROR) #define DUK_HEAP_STRING_DUKTAPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DUKTAPE) #define DUK_HTHREAD_STRING_DUKTAPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DUKTAPE) +#define DUK_HEAP_STRING_SET_FLOAT64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT64) +#define DUK_HTHREAD_STRING_SET_FLOAT64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT64) +#define DUK_HEAP_STRING_SET_FLOAT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT32) +#define DUK_HTHREAD_STRING_SET_FLOAT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT32) +#define DUK_HEAP_STRING_SET_UINT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT32) +#define DUK_HTHREAD_STRING_SET_UINT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT32) +#define DUK_HEAP_STRING_SET_INT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT32) +#define DUK_HTHREAD_STRING_SET_INT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT32) +#define DUK_HEAP_STRING_SET_UINT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT16) +#define DUK_HTHREAD_STRING_SET_UINT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT16) +#define DUK_HEAP_STRING_SET_INT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT16) +#define DUK_HTHREAD_STRING_SET_INT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT16) +#define DUK_HEAP_STRING_SET_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT8) +#define DUK_HTHREAD_STRING_SET_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT8) +#define DUK_HEAP_STRING_SET_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT8) +#define DUK_HTHREAD_STRING_SET_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT8) +#define DUK_HEAP_STRING_GET_FLOAT64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT64) +#define DUK_HTHREAD_STRING_GET_FLOAT64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT64) +#define DUK_HEAP_STRING_GET_FLOAT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT32) +#define DUK_HTHREAD_STRING_GET_FLOAT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT32) +#define DUK_HEAP_STRING_GET_UINT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT32) +#define DUK_HTHREAD_STRING_GET_UINT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT32) +#define DUK_HEAP_STRING_GET_INT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT32) +#define DUK_HTHREAD_STRING_GET_INT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT32) +#define DUK_HEAP_STRING_GET_UINT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT16) +#define DUK_HTHREAD_STRING_GET_UINT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT16) +#define DUK_HEAP_STRING_GET_INT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT16) +#define DUK_HTHREAD_STRING_GET_INT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT16) +#define DUK_HEAP_STRING_GET_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT8) +#define DUK_HTHREAD_STRING_GET_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT8) +#define DUK_HEAP_STRING_GET_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT8) +#define DUK_HTHREAD_STRING_GET_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT8) +#define DUK_HEAP_STRING_SUBARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUBARRAY) +#define DUK_HTHREAD_STRING_SUBARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUBARRAY) +#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT) +#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT) +#define DUK_HEAP_STRING_BYTE_OFFSET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET) +#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET) +#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER) +#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER) +#define DUK_HEAP_STRING_IS_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_VIEW) +#define DUK_HTHREAD_STRING_IS_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_VIEW) +#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA) +#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA) +#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE) +#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE) +#define DUK_HEAP_STRING_WRITE_INT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_BE) +#define DUK_HTHREAD_STRING_WRITE_INT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_BE) +#define DUK_HEAP_STRING_WRITE_INT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_LE) +#define DUK_HTHREAD_STRING_WRITE_INT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_LE) +#define DUK_HEAP_STRING_WRITE_UINT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_BE) +#define DUK_HEAP_STRING_WRITE_UINT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_LE) +#define DUK_HEAP_STRING_WRITE_DOUBLE_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_BE) +#define DUK_HTHREAD_STRING_WRITE_DOUBLE_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_BE) +#define DUK_HEAP_STRING_WRITE_DOUBLE_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_LE) +#define DUK_HTHREAD_STRING_WRITE_DOUBLE_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_LE) +#define DUK_HEAP_STRING_WRITE_FLOAT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_BE) +#define DUK_HTHREAD_STRING_WRITE_FLOAT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_BE) +#define DUK_HEAP_STRING_WRITE_FLOAT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_LE) +#define DUK_HTHREAD_STRING_WRITE_FLOAT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_LE) +#define DUK_HEAP_STRING_WRITE_INT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_BE) +#define DUK_HTHREAD_STRING_WRITE_INT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_BE) +#define DUK_HEAP_STRING_WRITE_INT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_LE) +#define DUK_HTHREAD_STRING_WRITE_INT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_LE) +#define DUK_HEAP_STRING_WRITE_UINT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_BE) +#define DUK_HEAP_STRING_WRITE_UINT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_LE) +#define DUK_HEAP_STRING_WRITE_INT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_BE) +#define DUK_HTHREAD_STRING_WRITE_INT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_BE) +#define DUK_HEAP_STRING_WRITE_INT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_LE) +#define DUK_HTHREAD_STRING_WRITE_INT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_LE) +#define DUK_HEAP_STRING_WRITE_UINT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_BE) +#define DUK_HEAP_STRING_WRITE_UINT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_LE) +#define DUK_HEAP_STRING_WRITE_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT8) +#define DUK_HTHREAD_STRING_WRITE_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT8) +#define DUK_HEAP_STRING_WRITE_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT8) +#define DUK_HTHREAD_STRING_WRITE_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT8) +#define DUK_HEAP_STRING_READ_INT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_BE) +#define DUK_HTHREAD_STRING_READ_INT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_BE) +#define DUK_HEAP_STRING_READ_INT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_LE) +#define DUK_HTHREAD_STRING_READ_INT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_LE) +#define DUK_HEAP_STRING_READ_UINT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_BE) +#define DUK_HTHREAD_STRING_READ_UINT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_BE) +#define DUK_HEAP_STRING_READ_UINT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_LE) +#define DUK_HTHREAD_STRING_READ_UINT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_LE) +#define DUK_HEAP_STRING_READ_DOUBLE_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_BE) +#define DUK_HTHREAD_STRING_READ_DOUBLE_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_BE) +#define DUK_HEAP_STRING_READ_DOUBLE_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_LE) +#define DUK_HTHREAD_STRING_READ_DOUBLE_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_LE) +#define DUK_HEAP_STRING_READ_FLOAT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_BE) +#define DUK_HTHREAD_STRING_READ_FLOAT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_BE) +#define DUK_HEAP_STRING_READ_FLOAT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_LE) +#define DUK_HTHREAD_STRING_READ_FLOAT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_LE) +#define DUK_HEAP_STRING_READ_INT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_BE) +#define DUK_HTHREAD_STRING_READ_INT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_BE) +#define DUK_HEAP_STRING_READ_INT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_LE) +#define DUK_HTHREAD_STRING_READ_INT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_LE) +#define DUK_HEAP_STRING_READ_UINT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_BE) +#define DUK_HTHREAD_STRING_READ_UINT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_BE) +#define DUK_HEAP_STRING_READ_UINT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_LE) +#define DUK_HTHREAD_STRING_READ_UINT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_LE) +#define DUK_HEAP_STRING_READ_INT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_BE) +#define DUK_HTHREAD_STRING_READ_INT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_BE) +#define DUK_HEAP_STRING_READ_INT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_LE) +#define DUK_HTHREAD_STRING_READ_INT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_LE) +#define DUK_HEAP_STRING_READ_UINT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_BE) +#define DUK_HTHREAD_STRING_READ_UINT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_BE) +#define DUK_HEAP_STRING_READ_UINT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_LE) +#define DUK_HTHREAD_STRING_READ_UINT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_LE) +#define DUK_HEAP_STRING_READ_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT8) +#define DUK_HTHREAD_STRING_READ_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT8) +#define DUK_HEAP_STRING_READ_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT8) +#define DUK_HTHREAD_STRING_READ_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT8) +#define DUK_HEAP_STRING_COPY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COPY) +#define DUK_HTHREAD_STRING_COPY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COPY) +#define DUK_HEAP_STRING_EQUALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EQUALS) +#define DUK_HTHREAD_STRING_EQUALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EQUALS) +#define DUK_HEAP_STRING_FILL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILL) +#define DUK_HTHREAD_STRING_FILL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILL) +#define DUK_HEAP_STRING_WRITE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE) +#define DUK_HTHREAD_STRING_WRITE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE) +#define DUK_HEAP_STRING_COMPARE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPARE) +#define DUK_HTHREAD_STRING_COMPARE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPARE) +#define DUK_HEAP_STRING_BYTE_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH) +#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH) +#define DUK_HEAP_STRING_IS_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_BUFFER) +#define DUK_HTHREAD_STRING_IS_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_BUFFER) +#define DUK_HEAP_STRING_IS_ENCODING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_ENCODING) +#define DUK_HTHREAD_STRING_IS_ENCODING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_ENCODING) +#define DUK_HEAP_STRING_EXPORTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS) +#define DUK_HTHREAD_STRING_EXPORTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS) #define DUK_HEAP_STRING_ID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID) #define DUK_HTHREAD_STRING_ID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID) #define DUK_HEAP_STRING_REQUIRE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE) @@ -2415,21 +2916,21 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD) #define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD) -#define DUK_HEAP_NUM_STRINGS 336 +#define DUK_HEAP_NUM_STRINGS 414 -#define DUK_STRIDX_START_RESERVED 291 -#define DUK_STRIDX_START_STRICT_RESERVED 327 -#define DUK_STRIDX_END_RESERVED 336 /* exclusive endpoint */ +#define DUK_STRIDX_START_RESERVED 369 +#define DUK_STRIDX_START_STRICT_RESERVED 405 +#define DUK_STRIDX_END_RESERVED 414 /* exclusive endpoint */ #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[128]; -DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1341]; +DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[147]; +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[187]; #endif /* DUK_USE_BUILTIN_INITJS */ #endif /* !DUK_SINGLE_FILE */ -#define DUK_BUILTINS_DATA_LENGTH 1341 +#define DUK_BUILTINS_DATA_LENGTH 1952 #ifdef DUK_USE_BUILTIN_INITJS #define DUK_BUILTIN_INITJS_DATA_LENGTH 187 #endif /* DUK_USE_BUILTIN_INITJS */ @@ -2480,353 +2981,456 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187]; #define DUK_BIDX_LOGGER_CONSTRUCTOR 43 #define DUK_BIDX_LOGGER_PROTOTYPE 44 #define DUK_BIDX_DOUBLE_ERROR 45 - -#define DUK_NUM_BUILTINS 46 +#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR 46 +#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 47 +#define DUK_BIDX_DATAVIEW_CONSTRUCTOR 48 +#define DUK_BIDX_DATAVIEW_PROTOTYPE 49 +#define DUK_BIDX_TYPEDARRAY_PROTOTYPE 50 +#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR 51 +#define DUK_BIDX_INT8ARRAY_PROTOTYPE 52 +#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR 53 +#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 54 +#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR 55 +#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 56 +#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR 57 +#define DUK_BIDX_INT16ARRAY_PROTOTYPE 58 +#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR 59 +#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 60 +#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR 61 +#define DUK_BIDX_INT32ARRAY_PROTOTYPE 62 +#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR 63 +#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 64 +#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR 65 +#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 66 +#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR 67 +#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 68 +#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR 69 +#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 70 + +#define DUK_NUM_BUILTINS 71 #elif defined(DUK_USE_DOUBLE_ME) #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; +DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[2624]; #endif /* !DUK_SINGLE_FILE */ -#define DUK_STRDATA_DATA_LENGTH 1943 +#define DUK_STRDATA_DATA_LENGTH 2624 #define DUK_STRDATA_MAX_STRLEN 24 #define DUK_STRIDX_UC_LOGGER 0 /* 'Logger' */ #define DUK_STRIDX_UC_THREAD 1 /* 'Thread' */ #define DUK_STRIDX_UC_POINTER 2 /* 'Pointer' */ -#define DUK_STRIDX_UC_BUFFER 3 /* 'Buffer' */ -#define DUK_STRIDX_DEC_ENV 4 /* 'DecEnv' */ -#define DUK_STRIDX_OBJ_ENV 5 /* 'ObjEnv' */ -#define DUK_STRIDX_EMPTY_STRING 6 /* '' */ -#define DUK_STRIDX_GLOBAL 7 /* 'global' */ -#define DUK_STRIDX_UC_ARGUMENTS 8 /* 'Arguments' */ -#define DUK_STRIDX_JSON 9 /* 'JSON' */ -#define DUK_STRIDX_MATH 10 /* 'Math' */ -#define DUK_STRIDX_UC_ERROR 11 /* 'Error' */ -#define DUK_STRIDX_REG_EXP 12 /* 'RegExp' */ -#define DUK_STRIDX_DATE 13 /* 'Date' */ -#define DUK_STRIDX_UC_NUMBER 14 /* 'Number' */ -#define DUK_STRIDX_UC_BOOLEAN 15 /* 'Boolean' */ -#define DUK_STRIDX_UC_STRING 16 /* 'String' */ -#define DUK_STRIDX_ARRAY 17 /* 'Array' */ -#define DUK_STRIDX_UC_FUNCTION 18 /* 'Function' */ -#define DUK_STRIDX_UC_OBJECT 19 /* 'Object' */ -#define DUK_STRIDX_UC_NULL 20 /* 'Null' */ -#define DUK_STRIDX_UC_UNDEFINED 21 /* 'Undefined' */ -#define DUK_STRIDX_JSON_EXT_FUNCTION2 22 /* '{_func:true}' */ -#define DUK_STRIDX_JSON_EXT_FUNCTION1 23 /* '{"_func":true}' */ -#define DUK_STRIDX_JSON_EXT_NEGINF 24 /* '{"_ninf":true}' */ -#define DUK_STRIDX_JSON_EXT_POSINF 25 /* '{"_inf":true}' */ -#define DUK_STRIDX_JSON_EXT_NAN 26 /* '{"_nan":true}' */ -#define DUK_STRIDX_JSON_EXT_UNDEFINED 27 /* '{"_undef":true}' */ -#define DUK_STRIDX_TO_LOG_STRING 28 /* 'toLogString' */ -#define DUK_STRIDX_CLOG 29 /* 'clog' */ -#define DUK_STRIDX_LC_L 30 /* 'l' */ -#define DUK_STRIDX_LC_N 31 /* 'n' */ -#define DUK_STRIDX_LC_FATAL 32 /* 'fatal' */ -#define DUK_STRIDX_LC_ERROR 33 /* 'error' */ -#define DUK_STRIDX_LC_WARN 34 /* 'warn' */ -#define DUK_STRIDX_LC_DEBUG 35 /* 'debug' */ -#define DUK_STRIDX_LC_TRACE 36 /* 'trace' */ -#define DUK_STRIDX_RAW 37 /* 'raw' */ -#define DUK_STRIDX_FMT 38 /* 'fmt' */ -#define DUK_STRIDX_CURRENT 39 /* 'current' */ -#define DUK_STRIDX_RESUME 40 /* 'resume' */ -#define DUK_STRIDX_COMPACT 41 /* 'compact' */ -#define DUK_STRIDX_JC 42 /* 'jc' */ -#define DUK_STRIDX_JX 43 /* 'jx' */ -#define DUK_STRIDX_BASE64 44 /* 'base64' */ -#define DUK_STRIDX_HEX 45 /* 'hex' */ -#define DUK_STRIDX_DEC 46 /* 'dec' */ -#define DUK_STRIDX_ENC 47 /* 'enc' */ -#define DUK_STRIDX_FIN 48 /* 'fin' */ -#define DUK_STRIDX_GC 49 /* 'gc' */ -#define DUK_STRIDX_ACT 50 /* 'act' */ -#define DUK_STRIDX_LC_INFO 51 /* 'info' */ -#define DUK_STRIDX_VERSION 52 /* 'version' */ -#define DUK_STRIDX_ENV 53 /* 'env' */ -#define DUK_STRIDX_MOD_LOADED 54 /* 'modLoaded' */ -#define DUK_STRIDX_MOD_SEARCH 55 /* 'modSearch' */ -#define DUK_STRIDX_ERR_THROW 56 /* 'errThrow' */ -#define DUK_STRIDX_ERR_CREATE 57 /* 'errCreate' */ -#define DUK_STRIDX_COMPILE 58 /* 'compile' */ -#define DUK_STRIDX_INT_REGBASE 59 /* '\x00Regbase' */ -#define DUK_STRIDX_INT_THREAD 60 /* '\x00Thread' */ -#define DUK_STRIDX_INT_HANDLER 61 /* '\x00Handler' */ -#define DUK_STRIDX_INT_FINALIZER 62 /* '\x00Finalizer' */ -#define DUK_STRIDX_INT_CALLEE 63 /* '\x00Callee' */ -#define DUK_STRIDX_INT_MAP 64 /* '\x00Map' */ -#define DUK_STRIDX_INT_ARGS 65 /* '\x00Args' */ -#define DUK_STRIDX_INT_THIS 66 /* '\x00This' */ -#define DUK_STRIDX_INT_PC2LINE 67 /* '\x00Pc2line' */ -#define DUK_STRIDX_INT_SOURCE 68 /* '\x00Source' */ -#define DUK_STRIDX_INT_VARENV 69 /* '\x00Varenv' */ -#define DUK_STRIDX_INT_LEXENV 70 /* '\x00Lexenv' */ -#define DUK_STRIDX_INT_VARMAP 71 /* '\x00Varmap' */ -#define DUK_STRIDX_INT_FORMALS 72 /* '\x00Formals' */ -#define DUK_STRIDX_INT_BYTECODE 73 /* '\x00Bytecode' */ -#define DUK_STRIDX_INT_NEXT 74 /* '\x00Next' */ -#define DUK_STRIDX_INT_TARGET 75 /* '\x00Target' */ -#define DUK_STRIDX_INT_VALUE 76 /* '\x00Value' */ -#define DUK_STRIDX_LC_POINTER 77 /* 'pointer' */ -#define DUK_STRIDX_LC_BUFFER 78 /* 'buffer' */ -#define DUK_STRIDX_INT_TRACEDATA 79 /* '\x00Tracedata' */ -#define DUK_STRIDX_LINE_NUMBER 80 /* 'lineNumber' */ -#define DUK_STRIDX_FILE_NAME 81 /* 'fileName' */ -#define DUK_STRIDX_PC 82 /* 'pc' */ -#define DUK_STRIDX_STACK 83 /* 'stack' */ -#define DUK_STRIDX_THROW_TYPE_ERROR 84 /* 'ThrowTypeError' */ -#define DUK_STRIDX_DUKTAPE 85 /* 'Duktape' */ -#define DUK_STRIDX_ID 86 /* 'id' */ -#define DUK_STRIDX_REQUIRE 87 /* 'require' */ -#define DUK_STRIDX___PROTO__ 88 /* '__proto__' */ -#define DUK_STRIDX_SET_PROTOTYPE_OF 89 /* 'setPrototypeOf' */ -#define DUK_STRIDX_OWN_KEYS 90 /* 'ownKeys' */ -#define DUK_STRIDX_ENUMERATE 91 /* 'enumerate' */ -#define DUK_STRIDX_DELETE_PROPERTY 92 /* 'deleteProperty' */ -#define DUK_STRIDX_HAS 93 /* 'has' */ -#define DUK_STRIDX_PROXY 94 /* 'Proxy' */ -#define DUK_STRIDX_CALLEE 95 /* 'callee' */ -#define DUK_STRIDX_INVALID_DATE 96 /* 'Invalid Date' */ -#define DUK_STRIDX_BRACKETED_ELLIPSIS 97 /* '[...]' */ -#define DUK_STRIDX_NEWLINE_TAB 98 /* '\n\t' */ -#define DUK_STRIDX_SPACE 99 /* ' ' */ -#define DUK_STRIDX_COMMA 100 /* ',' */ -#define DUK_STRIDX_MINUS_ZERO 101 /* '-0' */ -#define DUK_STRIDX_PLUS_ZERO 102 /* '+0' */ -#define DUK_STRIDX_ZERO 103 /* '0' */ -#define DUK_STRIDX_MINUS_INFINITY 104 /* '-Infinity' */ -#define DUK_STRIDX_PLUS_INFINITY 105 /* '+Infinity' */ -#define DUK_STRIDX_INFINITY 106 /* 'Infinity' */ -#define DUK_STRIDX_LC_OBJECT 107 /* 'object' */ -#define DUK_STRIDX_LC_STRING 108 /* 'string' */ -#define DUK_STRIDX_LC_NUMBER 109 /* 'number' */ -#define DUK_STRIDX_LC_BOOLEAN 110 /* 'boolean' */ -#define DUK_STRIDX_LC_UNDEFINED 111 /* 'undefined' */ -#define DUK_STRIDX_STRINGIFY 112 /* 'stringify' */ -#define DUK_STRIDX_TAN 113 /* 'tan' */ -#define DUK_STRIDX_SQRT 114 /* 'sqrt' */ -#define DUK_STRIDX_SIN 115 /* 'sin' */ -#define DUK_STRIDX_ROUND 116 /* 'round' */ -#define DUK_STRIDX_RANDOM 117 /* 'random' */ -#define DUK_STRIDX_POW 118 /* 'pow' */ -#define DUK_STRIDX_MIN 119 /* 'min' */ -#define DUK_STRIDX_MAX 120 /* 'max' */ -#define DUK_STRIDX_LOG 121 /* 'log' */ -#define DUK_STRIDX_FLOOR 122 /* 'floor' */ -#define DUK_STRIDX_EXP 123 /* 'exp' */ -#define DUK_STRIDX_COS 124 /* 'cos' */ -#define DUK_STRIDX_CEIL 125 /* 'ceil' */ -#define DUK_STRIDX_ATAN2 126 /* 'atan2' */ -#define DUK_STRIDX_ATAN 127 /* 'atan' */ -#define DUK_STRIDX_ASIN 128 /* 'asin' */ -#define DUK_STRIDX_ACOS 129 /* 'acos' */ -#define DUK_STRIDX_ABS 130 /* 'abs' */ -#define DUK_STRIDX_SQRT2 131 /* 'SQRT2' */ -#define DUK_STRIDX_SQRT1_2 132 /* 'SQRT1_2' */ -#define DUK_STRIDX_PI 133 /* 'PI' */ -#define DUK_STRIDX_LOG10E 134 /* 'LOG10E' */ -#define DUK_STRIDX_LOG2E 135 /* 'LOG2E' */ -#define DUK_STRIDX_LN2 136 /* 'LN2' */ -#define DUK_STRIDX_LN10 137 /* 'LN10' */ -#define DUK_STRIDX_E 138 /* 'E' */ -#define DUK_STRIDX_MESSAGE 139 /* 'message' */ -#define DUK_STRIDX_NAME 140 /* 'name' */ -#define DUK_STRIDX_INPUT 141 /* 'input' */ -#define DUK_STRIDX_INDEX 142 /* 'index' */ -#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 143 /* '(?:)' */ -#define DUK_STRIDX_LAST_INDEX 144 /* 'lastIndex' */ -#define DUK_STRIDX_MULTILINE 145 /* 'multiline' */ -#define DUK_STRIDX_IGNORE_CASE 146 /* 'ignoreCase' */ -#define DUK_STRIDX_SOURCE 147 /* 'source' */ -#define DUK_STRIDX_TEST 148 /* 'test' */ -#define DUK_STRIDX_EXEC 149 /* 'exec' */ -#define DUK_STRIDX_TO_GMT_STRING 150 /* 'toGMTString' */ -#define DUK_STRIDX_SET_YEAR 151 /* 'setYear' */ -#define DUK_STRIDX_GET_YEAR 152 /* 'getYear' */ -#define DUK_STRIDX_TO_JSON 153 /* 'toJSON' */ -#define DUK_STRIDX_TO_ISO_STRING 154 /* 'toISOString' */ -#define DUK_STRIDX_TO_UTC_STRING 155 /* 'toUTCString' */ -#define DUK_STRIDX_SET_UTC_FULL_YEAR 156 /* 'setUTCFullYear' */ -#define DUK_STRIDX_SET_FULL_YEAR 157 /* 'setFullYear' */ -#define DUK_STRIDX_SET_UTC_MONTH 158 /* 'setUTCMonth' */ -#define DUK_STRIDX_SET_MONTH 159 /* 'setMonth' */ -#define DUK_STRIDX_SET_UTC_DATE 160 /* 'setUTCDate' */ -#define DUK_STRIDX_SET_DATE 161 /* 'setDate' */ -#define DUK_STRIDX_SET_UTC_HOURS 162 /* 'setUTCHours' */ -#define DUK_STRIDX_SET_HOURS 163 /* 'setHours' */ -#define DUK_STRIDX_SET_UTC_MINUTES 164 /* 'setUTCMinutes' */ -#define DUK_STRIDX_SET_MINUTES 165 /* 'setMinutes' */ -#define DUK_STRIDX_SET_UTC_SECONDS 166 /* 'setUTCSeconds' */ -#define DUK_STRIDX_SET_SECONDS 167 /* 'setSeconds' */ -#define DUK_STRIDX_SET_UTC_MILLISECONDS 168 /* 'setUTCMilliseconds' */ -#define DUK_STRIDX_SET_MILLISECONDS 169 /* 'setMilliseconds' */ -#define DUK_STRIDX_SET_TIME 170 /* 'setTime' */ -#define DUK_STRIDX_GET_TIMEZONE_OFFSET 171 /* 'getTimezoneOffset' */ -#define DUK_STRIDX_GET_UTC_MILLISECONDS 172 /* 'getUTCMilliseconds' */ -#define DUK_STRIDX_GET_MILLISECONDS 173 /* 'getMilliseconds' */ -#define DUK_STRIDX_GET_UTC_SECONDS 174 /* 'getUTCSeconds' */ -#define DUK_STRIDX_GET_SECONDS 175 /* 'getSeconds' */ -#define DUK_STRIDX_GET_UTC_MINUTES 176 /* 'getUTCMinutes' */ -#define DUK_STRIDX_GET_MINUTES 177 /* 'getMinutes' */ -#define DUK_STRIDX_GET_UTC_HOURS 178 /* 'getUTCHours' */ -#define DUK_STRIDX_GET_HOURS 179 /* 'getHours' */ -#define DUK_STRIDX_GET_UTC_DAY 180 /* 'getUTCDay' */ -#define DUK_STRIDX_GET_DAY 181 /* 'getDay' */ -#define DUK_STRIDX_GET_UTC_DATE 182 /* 'getUTCDate' */ -#define DUK_STRIDX_GET_DATE 183 /* 'getDate' */ -#define DUK_STRIDX_GET_UTC_MONTH 184 /* 'getUTCMonth' */ -#define DUK_STRIDX_GET_MONTH 185 /* 'getMonth' */ -#define DUK_STRIDX_GET_UTC_FULL_YEAR 186 /* 'getUTCFullYear' */ -#define DUK_STRIDX_GET_FULL_YEAR 187 /* 'getFullYear' */ -#define DUK_STRIDX_GET_TIME 188 /* 'getTime' */ -#define DUK_STRIDX_TO_LOCALE_TIME_STRING 189 /* 'toLocaleTimeString' */ -#define DUK_STRIDX_TO_LOCALE_DATE_STRING 190 /* 'toLocaleDateString' */ -#define DUK_STRIDX_TO_TIME_STRING 191 /* 'toTimeString' */ -#define DUK_STRIDX_TO_DATE_STRING 192 /* 'toDateString' */ -#define DUK_STRIDX_NOW 193 /* 'now' */ -#define DUK_STRIDX_UTC 194 /* 'UTC' */ -#define DUK_STRIDX_PARSE 195 /* 'parse' */ -#define DUK_STRIDX_TO_PRECISION 196 /* 'toPrecision' */ -#define DUK_STRIDX_TO_EXPONENTIAL 197 /* 'toExponential' */ -#define DUK_STRIDX_TO_FIXED 198 /* 'toFixed' */ -#define DUK_STRIDX_POSITIVE_INFINITY 199 /* 'POSITIVE_INFINITY' */ -#define DUK_STRIDX_NEGATIVE_INFINITY 200 /* 'NEGATIVE_INFINITY' */ -#define DUK_STRIDX_NAN 201 /* 'NaN' */ -#define DUK_STRIDX_MIN_VALUE 202 /* 'MIN_VALUE' */ -#define DUK_STRIDX_MAX_VALUE 203 /* 'MAX_VALUE' */ -#define DUK_STRIDX_SUBSTR 204 /* 'substr' */ -#define DUK_STRIDX_TRIM 205 /* 'trim' */ -#define DUK_STRIDX_TO_LOCALE_UPPER_CASE 206 /* 'toLocaleUpperCase' */ -#define DUK_STRIDX_TO_UPPER_CASE 207 /* 'toUpperCase' */ -#define DUK_STRIDX_TO_LOCALE_LOWER_CASE 208 /* 'toLocaleLowerCase' */ -#define DUK_STRIDX_TO_LOWER_CASE 209 /* 'toLowerCase' */ -#define DUK_STRIDX_SUBSTRING 210 /* 'substring' */ -#define DUK_STRIDX_SPLIT 211 /* 'split' */ -#define DUK_STRIDX_SEARCH 212 /* 'search' */ -#define DUK_STRIDX_REPLACE 213 /* 'replace' */ -#define DUK_STRIDX_MATCH 214 /* 'match' */ -#define DUK_STRIDX_LOCALE_COMPARE 215 /* 'localeCompare' */ -#define DUK_STRIDX_CHAR_CODE_AT 216 /* 'charCodeAt' */ -#define DUK_STRIDX_CHAR_AT 217 /* 'charAt' */ -#define DUK_STRIDX_FROM_CHAR_CODE 218 /* 'fromCharCode' */ -#define DUK_STRIDX_REDUCE_RIGHT 219 /* 'reduceRight' */ -#define DUK_STRIDX_REDUCE 220 /* 'reduce' */ -#define DUK_STRIDX_FILTER 221 /* 'filter' */ -#define DUK_STRIDX_MAP 222 /* 'map' */ -#define DUK_STRIDX_FOR_EACH 223 /* 'forEach' */ -#define DUK_STRIDX_SOME 224 /* 'some' */ -#define DUK_STRIDX_EVERY 225 /* 'every' */ -#define DUK_STRIDX_LAST_INDEX_OF 226 /* 'lastIndexOf' */ -#define DUK_STRIDX_INDEX_OF 227 /* 'indexOf' */ -#define DUK_STRIDX_UNSHIFT 228 /* 'unshift' */ -#define DUK_STRIDX_SPLICE 229 /* 'splice' */ -#define DUK_STRIDX_SORT 230 /* 'sort' */ -#define DUK_STRIDX_SLICE 231 /* 'slice' */ -#define DUK_STRIDX_SHIFT 232 /* 'shift' */ -#define DUK_STRIDX_REVERSE 233 /* 'reverse' */ -#define DUK_STRIDX_PUSH 234 /* 'push' */ -#define DUK_STRIDX_POP 235 /* 'pop' */ -#define DUK_STRIDX_JOIN 236 /* 'join' */ -#define DUK_STRIDX_CONCAT 237 /* 'concat' */ -#define DUK_STRIDX_IS_ARRAY 238 /* 'isArray' */ -#define DUK_STRIDX_LC_ARGUMENTS 239 /* 'arguments' */ -#define DUK_STRIDX_CALLER 240 /* 'caller' */ -#define DUK_STRIDX_BIND 241 /* 'bind' */ -#define DUK_STRIDX_CALL 242 /* 'call' */ -#define DUK_STRIDX_APPLY 243 /* 'apply' */ -#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE 244 /* 'propertyIsEnumerable' */ -#define DUK_STRIDX_IS_PROTOTYPE_OF 245 /* 'isPrototypeOf' */ -#define DUK_STRIDX_HAS_OWN_PROPERTY 246 /* 'hasOwnProperty' */ -#define DUK_STRIDX_VALUE_OF 247 /* 'valueOf' */ -#define DUK_STRIDX_TO_LOCALE_STRING 248 /* 'toLocaleString' */ -#define DUK_STRIDX_TO_STRING 249 /* 'toString' */ -#define DUK_STRIDX_CONSTRUCTOR 250 /* 'constructor' */ -#define DUK_STRIDX_SET 251 /* 'set' */ -#define DUK_STRIDX_GET 252 /* 'get' */ -#define DUK_STRIDX_ENUMERABLE 253 /* 'enumerable' */ -#define DUK_STRIDX_CONFIGURABLE 254 /* 'configurable' */ -#define DUK_STRIDX_WRITABLE 255 /* 'writable' */ -#define DUK_STRIDX_VALUE 256 /* 'value' */ -#define DUK_STRIDX_KEYS 257 /* 'keys' */ -#define DUK_STRIDX_IS_EXTENSIBLE 258 /* 'isExtensible' */ -#define DUK_STRIDX_IS_FROZEN 259 /* 'isFrozen' */ -#define DUK_STRIDX_IS_SEALED 260 /* 'isSealed' */ -#define DUK_STRIDX_PREVENT_EXTENSIONS 261 /* 'preventExtensions' */ -#define DUK_STRIDX_FREEZE 262 /* 'freeze' */ -#define DUK_STRIDX_SEAL 263 /* 'seal' */ -#define DUK_STRIDX_DEFINE_PROPERTIES 264 /* 'defineProperties' */ -#define DUK_STRIDX_DEFINE_PROPERTY 265 /* 'defineProperty' */ -#define DUK_STRIDX_CREATE 266 /* 'create' */ -#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES 267 /* 'getOwnPropertyNames' */ -#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR 268 /* 'getOwnPropertyDescriptor' */ -#define DUK_STRIDX_GET_PROTOTYPE_OF 269 /* 'getPrototypeOf' */ -#define DUK_STRIDX_PROTOTYPE 270 /* 'prototype' */ -#define DUK_STRIDX_LENGTH 271 /* 'length' */ -#define DUK_STRIDX_ALERT 272 /* 'alert' */ -#define DUK_STRIDX_PRINT 273 /* 'print' */ -#define DUK_STRIDX_UNESCAPE 274 /* 'unescape' */ -#define DUK_STRIDX_ESCAPE 275 /* 'escape' */ -#define DUK_STRIDX_ENCODE_URI_COMPONENT 276 /* 'encodeURIComponent' */ -#define DUK_STRIDX_ENCODE_URI 277 /* 'encodeURI' */ -#define DUK_STRIDX_DECODE_URI_COMPONENT 278 /* 'decodeURIComponent' */ -#define DUK_STRIDX_DECODE_URI 279 /* 'decodeURI' */ -#define DUK_STRIDX_IS_FINITE 280 /* 'isFinite' */ -#define DUK_STRIDX_IS_NAN 281 /* 'isNaN' */ -#define DUK_STRIDX_PARSE_FLOAT 282 /* 'parseFloat' */ -#define DUK_STRIDX_PARSE_INT 283 /* 'parseInt' */ -#define DUK_STRIDX_EVAL 284 /* 'eval' */ -#define DUK_STRIDX_URI_ERROR 285 /* 'URIError' */ -#define DUK_STRIDX_TYPE_ERROR 286 /* 'TypeError' */ -#define DUK_STRIDX_SYNTAX_ERROR 287 /* 'SyntaxError' */ -#define DUK_STRIDX_REFERENCE_ERROR 288 /* 'ReferenceError' */ -#define DUK_STRIDX_RANGE_ERROR 289 /* 'RangeError' */ -#define DUK_STRIDX_EVAL_ERROR 290 /* 'EvalError' */ -#define DUK_STRIDX_BREAK 291 /* 'break' */ -#define DUK_STRIDX_CASE 292 /* 'case' */ -#define DUK_STRIDX_CATCH 293 /* 'catch' */ -#define DUK_STRIDX_CONTINUE 294 /* 'continue' */ -#define DUK_STRIDX_DEBUGGER 295 /* 'debugger' */ -#define DUK_STRIDX_DEFAULT 296 /* 'default' */ -#define DUK_STRIDX_DELETE 297 /* 'delete' */ -#define DUK_STRIDX_DO 298 /* 'do' */ -#define DUK_STRIDX_ELSE 299 /* 'else' */ -#define DUK_STRIDX_FINALLY 300 /* 'finally' */ -#define DUK_STRIDX_FOR 301 /* 'for' */ -#define DUK_STRIDX_LC_FUNCTION 302 /* 'function' */ -#define DUK_STRIDX_IF 303 /* 'if' */ -#define DUK_STRIDX_IN 304 /* 'in' */ -#define DUK_STRIDX_INSTANCEOF 305 /* 'instanceof' */ -#define DUK_STRIDX_NEW 306 /* 'new' */ -#define DUK_STRIDX_RETURN 307 /* 'return' */ -#define DUK_STRIDX_SWITCH 308 /* 'switch' */ -#define DUK_STRIDX_THIS 309 /* 'this' */ -#define DUK_STRIDX_THROW 310 /* 'throw' */ -#define DUK_STRIDX_TRY 311 /* 'try' */ -#define DUK_STRIDX_TYPEOF 312 /* 'typeof' */ -#define DUK_STRIDX_VAR 313 /* 'var' */ -#define DUK_STRIDX_VOID 314 /* 'void' */ -#define DUK_STRIDX_WHILE 315 /* 'while' */ -#define DUK_STRIDX_WITH 316 /* 'with' */ -#define DUK_STRIDX_CLASS 317 /* 'class' */ -#define DUK_STRIDX_CONST 318 /* 'const' */ -#define DUK_STRIDX_ENUM 319 /* 'enum' */ -#define DUK_STRIDX_EXPORT 320 /* 'export' */ -#define DUK_STRIDX_EXTENDS 321 /* 'extends' */ -#define DUK_STRIDX_IMPORT 322 /* 'import' */ -#define DUK_STRIDX_SUPER 323 /* 'super' */ -#define DUK_STRIDX_LC_NULL 324 /* 'null' */ -#define DUK_STRIDX_TRUE 325 /* 'true' */ -#define DUK_STRIDX_FALSE 326 /* 'false' */ -#define DUK_STRIDX_IMPLEMENTS 327 /* 'implements' */ -#define DUK_STRIDX_INTERFACE 328 /* 'interface' */ -#define DUK_STRIDX_LET 329 /* 'let' */ -#define DUK_STRIDX_PACKAGE 330 /* 'package' */ -#define DUK_STRIDX_PRIVATE 331 /* 'private' */ -#define DUK_STRIDX_PROTECTED 332 /* 'protected' */ -#define DUK_STRIDX_PUBLIC 333 /* 'public' */ -#define DUK_STRIDX_STATIC 334 /* 'static' */ -#define DUK_STRIDX_YIELD 335 /* 'yield' */ +#define DUK_STRIDX_DEC_ENV 3 /* 'DecEnv' */ +#define DUK_STRIDX_OBJ_ENV 4 /* 'ObjEnv' */ +#define DUK_STRIDX_FLOAT64_ARRAY 5 /* 'Float64Array' */ +#define DUK_STRIDX_FLOAT32_ARRAY 6 /* 'Float32Array' */ +#define DUK_STRIDX_UINT32_ARRAY 7 /* 'Uint32Array' */ +#define DUK_STRIDX_INT32_ARRAY 8 /* 'Int32Array' */ +#define DUK_STRIDX_UINT16_ARRAY 9 /* 'Uint16Array' */ +#define DUK_STRIDX_INT16_ARRAY 10 /* 'Int16Array' */ +#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 11 /* 'Uint8ClampedArray' */ +#define DUK_STRIDX_UINT8_ARRAY 12 /* 'Uint8Array' */ +#define DUK_STRIDX_INT8_ARRAY 13 /* 'Int8Array' */ +#define DUK_STRIDX_DATA_VIEW 14 /* 'DataView' */ +#define DUK_STRIDX_ARRAY_BUFFER 15 /* 'ArrayBuffer' */ +#define DUK_STRIDX_UC_BUFFER 16 /* 'Buffer' */ +#define DUK_STRIDX_EMPTY_STRING 17 /* '' */ +#define DUK_STRIDX_GLOBAL 18 /* 'global' */ +#define DUK_STRIDX_UC_ARGUMENTS 19 /* 'Arguments' */ +#define DUK_STRIDX_JSON 20 /* 'JSON' */ +#define DUK_STRIDX_MATH 21 /* 'Math' */ +#define DUK_STRIDX_UC_ERROR 22 /* 'Error' */ +#define DUK_STRIDX_REG_EXP 23 /* 'RegExp' */ +#define DUK_STRIDX_DATE 24 /* 'Date' */ +#define DUK_STRIDX_UC_NUMBER 25 /* 'Number' */ +#define DUK_STRIDX_UC_BOOLEAN 26 /* 'Boolean' */ +#define DUK_STRIDX_UC_STRING 27 /* 'String' */ +#define DUK_STRIDX_ARRAY 28 /* 'Array' */ +#define DUK_STRIDX_UC_FUNCTION 29 /* 'Function' */ +#define DUK_STRIDX_UC_OBJECT 30 /* 'Object' */ +#define DUK_STRIDX_UC_NULL 31 /* 'Null' */ +#define DUK_STRIDX_UC_UNDEFINED 32 /* 'Undefined' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION2 33 /* '{_func:true}' */ +#define DUK_STRIDX_JSON_EXT_FUNCTION1 34 /* '{"_func":true}' */ +#define DUK_STRIDX_JSON_EXT_NEGINF 35 /* '{"_ninf":true}' */ +#define DUK_STRIDX_JSON_EXT_POSINF 36 /* '{"_inf":true}' */ +#define DUK_STRIDX_JSON_EXT_NAN 37 /* '{"_nan":true}' */ +#define DUK_STRIDX_JSON_EXT_UNDEFINED 38 /* '{"_undef":true}' */ +#define DUK_STRIDX_TO_LOG_STRING 39 /* 'toLogString' */ +#define DUK_STRIDX_CLOG 40 /* 'clog' */ +#define DUK_STRIDX_LC_L 41 /* 'l' */ +#define DUK_STRIDX_LC_N 42 /* 'n' */ +#define DUK_STRIDX_LC_FATAL 43 /* 'fatal' */ +#define DUK_STRIDX_LC_ERROR 44 /* 'error' */ +#define DUK_STRIDX_LC_WARN 45 /* 'warn' */ +#define DUK_STRIDX_LC_DEBUG 46 /* 'debug' */ +#define DUK_STRIDX_LC_TRACE 47 /* 'trace' */ +#define DUK_STRIDX_RAW 48 /* 'raw' */ +#define DUK_STRIDX_FMT 49 /* 'fmt' */ +#define DUK_STRIDX_CURRENT 50 /* 'current' */ +#define DUK_STRIDX_RESUME 51 /* 'resume' */ +#define DUK_STRIDX_COMPACT 52 /* 'compact' */ +#define DUK_STRIDX_JC 53 /* 'jc' */ +#define DUK_STRIDX_JX 54 /* 'jx' */ +#define DUK_STRIDX_BASE64 55 /* 'base64' */ +#define DUK_STRIDX_HEX 56 /* 'hex' */ +#define DUK_STRIDX_DEC 57 /* 'dec' */ +#define DUK_STRIDX_ENC 58 /* 'enc' */ +#define DUK_STRIDX_FIN 59 /* 'fin' */ +#define DUK_STRIDX_GC 60 /* 'gc' */ +#define DUK_STRIDX_ACT 61 /* 'act' */ +#define DUK_STRIDX_LC_INFO 62 /* 'info' */ +#define DUK_STRIDX_VERSION 63 /* 'version' */ +#define DUK_STRIDX_ENV 64 /* 'env' */ +#define DUK_STRIDX_MOD_LOADED 65 /* 'modLoaded' */ +#define DUK_STRIDX_MOD_SEARCH 66 /* 'modSearch' */ +#define DUK_STRIDX_ERR_THROW 67 /* 'errThrow' */ +#define DUK_STRIDX_ERR_CREATE 68 /* 'errCreate' */ +#define DUK_STRIDX_COMPILE 69 /* 'compile' */ +#define DUK_STRIDX_INT_REGBASE 70 /* '\x00Regbase' */ +#define DUK_STRIDX_INT_THREAD 71 /* '\x00Thread' */ +#define DUK_STRIDX_INT_HANDLER 72 /* '\x00Handler' */ +#define DUK_STRIDX_INT_FINALIZER 73 /* '\x00Finalizer' */ +#define DUK_STRIDX_INT_CALLEE 74 /* '\x00Callee' */ +#define DUK_STRIDX_INT_MAP 75 /* '\x00Map' */ +#define DUK_STRIDX_INT_ARGS 76 /* '\x00Args' */ +#define DUK_STRIDX_INT_THIS 77 /* '\x00This' */ +#define DUK_STRIDX_INT_PC2LINE 78 /* '\x00Pc2line' */ +#define DUK_STRIDX_INT_SOURCE 79 /* '\x00Source' */ +#define DUK_STRIDX_INT_VARENV 80 /* '\x00Varenv' */ +#define DUK_STRIDX_INT_LEXENV 81 /* '\x00Lexenv' */ +#define DUK_STRIDX_INT_VARMAP 82 /* '\x00Varmap' */ +#define DUK_STRIDX_INT_FORMALS 83 /* '\x00Formals' */ +#define DUK_STRIDX_INT_BYTECODE 84 /* '\x00Bytecode' */ +#define DUK_STRIDX_INT_NEXT 85 /* '\x00Next' */ +#define DUK_STRIDX_INT_TARGET 86 /* '\x00Target' */ +#define DUK_STRIDX_INT_VALUE 87 /* '\x00Value' */ +#define DUK_STRIDX_LC_POINTER 88 /* 'pointer' */ +#define DUK_STRIDX_INT_TRACEDATA 89 /* '\x00Tracedata' */ +#define DUK_STRIDX_LINE_NUMBER 90 /* 'lineNumber' */ +#define DUK_STRIDX_FILE_NAME 91 /* 'fileName' */ +#define DUK_STRIDX_PC 92 /* 'pc' */ +#define DUK_STRIDX_STACK 93 /* 'stack' */ +#define DUK_STRIDX_THROW_TYPE_ERROR 94 /* 'ThrowTypeError' */ +#define DUK_STRIDX_DUKTAPE 95 /* 'Duktape' */ +#define DUK_STRIDX_SET_FLOAT64 96 /* 'setFloat64' */ +#define DUK_STRIDX_SET_FLOAT32 97 /* 'setFloat32' */ +#define DUK_STRIDX_SET_UINT32 98 /* 'setUint32' */ +#define DUK_STRIDX_SET_INT32 99 /* 'setInt32' */ +#define DUK_STRIDX_SET_UINT16 100 /* 'setUint16' */ +#define DUK_STRIDX_SET_INT16 101 /* 'setInt16' */ +#define DUK_STRIDX_SET_UINT8 102 /* 'setUint8' */ +#define DUK_STRIDX_SET_INT8 103 /* 'setInt8' */ +#define DUK_STRIDX_GET_FLOAT64 104 /* 'getFloat64' */ +#define DUK_STRIDX_GET_FLOAT32 105 /* 'getFloat32' */ +#define DUK_STRIDX_GET_UINT32 106 /* 'getUint32' */ +#define DUK_STRIDX_GET_INT32 107 /* 'getInt32' */ +#define DUK_STRIDX_GET_UINT16 108 /* 'getUint16' */ +#define DUK_STRIDX_GET_INT16 109 /* 'getInt16' */ +#define DUK_STRIDX_GET_UINT8 110 /* 'getUint8' */ +#define DUK_STRIDX_GET_INT8 111 /* 'getInt8' */ +#define DUK_STRIDX_SUBARRAY 112 /* 'subarray' */ +#define DUK_STRIDX_BYTES_PER_ELEMENT 113 /* 'BYTES_PER_ELEMENT' */ +#define DUK_STRIDX_BYTE_OFFSET 114 /* 'byteOffset' */ +#define DUK_STRIDX_LC_BUFFER 115 /* 'buffer' */ +#define DUK_STRIDX_IS_VIEW 116 /* 'isView' */ +#define DUK_STRIDX_DATA 117 /* 'data' */ +#define DUK_STRIDX_TYPE 118 /* 'type' */ +#define DUK_STRIDX_WRITE_INT_BE 119 /* 'writeIntBE' */ +#define DUK_STRIDX_WRITE_INT_LE 120 /* 'writeIntLE' */ +#define DUK_STRIDX_WRITE_UINT_BE 121 /* 'writeUIntBE' */ +#define DUK_STRIDX_WRITE_UINT_LE 122 /* 'writeUIntLE' */ +#define DUK_STRIDX_WRITE_DOUBLE_BE 123 /* 'writeDoubleBE' */ +#define DUK_STRIDX_WRITE_DOUBLE_LE 124 /* 'writeDoubleLE' */ +#define DUK_STRIDX_WRITE_FLOAT_BE 125 /* 'writeFloatBE' */ +#define DUK_STRIDX_WRITE_FLOAT_LE 126 /* 'writeFloatLE' */ +#define DUK_STRIDX_WRITE_INT32_BE 127 /* 'writeInt32BE' */ +#define DUK_STRIDX_WRITE_INT32_LE 128 /* 'writeInt32LE' */ +#define DUK_STRIDX_WRITE_UINT32_BE 129 /* 'writeUInt32BE' */ +#define DUK_STRIDX_WRITE_UINT32_LE 130 /* 'writeUInt32LE' */ +#define DUK_STRIDX_WRITE_INT16_BE 131 /* 'writeInt16BE' */ +#define DUK_STRIDX_WRITE_INT16_LE 132 /* 'writeInt16LE' */ +#define DUK_STRIDX_WRITE_UINT16_BE 133 /* 'writeUInt16BE' */ +#define DUK_STRIDX_WRITE_UINT16_LE 134 /* 'writeUInt16LE' */ +#define DUK_STRIDX_WRITE_INT8 135 /* 'writeInt8' */ +#define DUK_STRIDX_WRITE_UINT8 136 /* 'writeUInt8' */ +#define DUK_STRIDX_READ_INT_BE 137 /* 'readIntBE' */ +#define DUK_STRIDX_READ_INT_LE 138 /* 'readIntLE' */ +#define DUK_STRIDX_READ_UINT_BE 139 /* 'readUIntBE' */ +#define DUK_STRIDX_READ_UINT_LE 140 /* 'readUIntLE' */ +#define DUK_STRIDX_READ_DOUBLE_BE 141 /* 'readDoubleBE' */ +#define DUK_STRIDX_READ_DOUBLE_LE 142 /* 'readDoubleLE' */ +#define DUK_STRIDX_READ_FLOAT_BE 143 /* 'readFloatBE' */ +#define DUK_STRIDX_READ_FLOAT_LE 144 /* 'readFloatLE' */ +#define DUK_STRIDX_READ_INT32_BE 145 /* 'readInt32BE' */ +#define DUK_STRIDX_READ_INT32_LE 146 /* 'readInt32LE' */ +#define DUK_STRIDX_READ_UINT32_BE 147 /* 'readUInt32BE' */ +#define DUK_STRIDX_READ_UINT32_LE 148 /* 'readUInt32LE' */ +#define DUK_STRIDX_READ_INT16_BE 149 /* 'readInt16BE' */ +#define DUK_STRIDX_READ_INT16_LE 150 /* 'readInt16LE' */ +#define DUK_STRIDX_READ_UINT16_BE 151 /* 'readUInt16BE' */ +#define DUK_STRIDX_READ_UINT16_LE 152 /* 'readUInt16LE' */ +#define DUK_STRIDX_READ_INT8 153 /* 'readInt8' */ +#define DUK_STRIDX_READ_UINT8 154 /* 'readUInt8' */ +#define DUK_STRIDX_COPY 155 /* 'copy' */ +#define DUK_STRIDX_EQUALS 156 /* 'equals' */ +#define DUK_STRIDX_FILL 157 /* 'fill' */ +#define DUK_STRIDX_WRITE 158 /* 'write' */ +#define DUK_STRIDX_COMPARE 159 /* 'compare' */ +#define DUK_STRIDX_BYTE_LENGTH 160 /* 'byteLength' */ +#define DUK_STRIDX_IS_BUFFER 161 /* 'isBuffer' */ +#define DUK_STRIDX_IS_ENCODING 162 /* 'isEncoding' */ +#define DUK_STRIDX_EXPORTS 163 /* 'exports' */ +#define DUK_STRIDX_ID 164 /* 'id' */ +#define DUK_STRIDX_REQUIRE 165 /* 'require' */ +#define DUK_STRIDX___PROTO__ 166 /* '__proto__' */ +#define DUK_STRIDX_SET_PROTOTYPE_OF 167 /* 'setPrototypeOf' */ +#define DUK_STRIDX_OWN_KEYS 168 /* 'ownKeys' */ +#define DUK_STRIDX_ENUMERATE 169 /* 'enumerate' */ +#define DUK_STRIDX_DELETE_PROPERTY 170 /* 'deleteProperty' */ +#define DUK_STRIDX_HAS 171 /* 'has' */ +#define DUK_STRIDX_PROXY 172 /* 'Proxy' */ +#define DUK_STRIDX_CALLEE 173 /* 'callee' */ +#define DUK_STRIDX_INVALID_DATE 174 /* 'Invalid Date' */ +#define DUK_STRIDX_BRACKETED_ELLIPSIS 175 /* '[...]' */ +#define DUK_STRIDX_NEWLINE_TAB 176 /* '\n\t' */ +#define DUK_STRIDX_SPACE 177 /* ' ' */ +#define DUK_STRIDX_COMMA 178 /* ',' */ +#define DUK_STRIDX_MINUS_ZERO 179 /* '-0' */ +#define DUK_STRIDX_PLUS_ZERO 180 /* '+0' */ +#define DUK_STRIDX_ZERO 181 /* '0' */ +#define DUK_STRIDX_MINUS_INFINITY 182 /* '-Infinity' */ +#define DUK_STRIDX_PLUS_INFINITY 183 /* '+Infinity' */ +#define DUK_STRIDX_INFINITY 184 /* 'Infinity' */ +#define DUK_STRIDX_LC_OBJECT 185 /* 'object' */ +#define DUK_STRIDX_LC_STRING 186 /* 'string' */ +#define DUK_STRIDX_LC_NUMBER 187 /* 'number' */ +#define DUK_STRIDX_LC_BOOLEAN 188 /* 'boolean' */ +#define DUK_STRIDX_LC_UNDEFINED 189 /* 'undefined' */ +#define DUK_STRIDX_STRINGIFY 190 /* 'stringify' */ +#define DUK_STRIDX_TAN 191 /* 'tan' */ +#define DUK_STRIDX_SQRT 192 /* 'sqrt' */ +#define DUK_STRIDX_SIN 193 /* 'sin' */ +#define DUK_STRIDX_ROUND 194 /* 'round' */ +#define DUK_STRIDX_RANDOM 195 /* 'random' */ +#define DUK_STRIDX_POW 196 /* 'pow' */ +#define DUK_STRIDX_MIN 197 /* 'min' */ +#define DUK_STRIDX_MAX 198 /* 'max' */ +#define DUK_STRIDX_LOG 199 /* 'log' */ +#define DUK_STRIDX_FLOOR 200 /* 'floor' */ +#define DUK_STRIDX_EXP 201 /* 'exp' */ +#define DUK_STRIDX_COS 202 /* 'cos' */ +#define DUK_STRIDX_CEIL 203 /* 'ceil' */ +#define DUK_STRIDX_ATAN2 204 /* 'atan2' */ +#define DUK_STRIDX_ATAN 205 /* 'atan' */ +#define DUK_STRIDX_ASIN 206 /* 'asin' */ +#define DUK_STRIDX_ACOS 207 /* 'acos' */ +#define DUK_STRIDX_ABS 208 /* 'abs' */ +#define DUK_STRIDX_SQRT2 209 /* 'SQRT2' */ +#define DUK_STRIDX_SQRT1_2 210 /* 'SQRT1_2' */ +#define DUK_STRIDX_PI 211 /* 'PI' */ +#define DUK_STRIDX_LOG10E 212 /* 'LOG10E' */ +#define DUK_STRIDX_LOG2E 213 /* 'LOG2E' */ +#define DUK_STRIDX_LN2 214 /* 'LN2' */ +#define DUK_STRIDX_LN10 215 /* 'LN10' */ +#define DUK_STRIDX_E 216 /* 'E' */ +#define DUK_STRIDX_MESSAGE 217 /* 'message' */ +#define DUK_STRIDX_NAME 218 /* 'name' */ +#define DUK_STRIDX_INPUT 219 /* 'input' */ +#define DUK_STRIDX_INDEX 220 /* 'index' */ +#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 221 /* '(?:)' */ +#define DUK_STRIDX_LAST_INDEX 222 /* 'lastIndex' */ +#define DUK_STRIDX_MULTILINE 223 /* 'multiline' */ +#define DUK_STRIDX_IGNORE_CASE 224 /* 'ignoreCase' */ +#define DUK_STRIDX_SOURCE 225 /* 'source' */ +#define DUK_STRIDX_TEST 226 /* 'test' */ +#define DUK_STRIDX_EXEC 227 /* 'exec' */ +#define DUK_STRIDX_TO_GMT_STRING 228 /* 'toGMTString' */ +#define DUK_STRIDX_SET_YEAR 229 /* 'setYear' */ +#define DUK_STRIDX_GET_YEAR 230 /* 'getYear' */ +#define DUK_STRIDX_TO_JSON 231 /* 'toJSON' */ +#define DUK_STRIDX_TO_ISO_STRING 232 /* 'toISOString' */ +#define DUK_STRIDX_TO_UTC_STRING 233 /* 'toUTCString' */ +#define DUK_STRIDX_SET_UTC_FULL_YEAR 234 /* 'setUTCFullYear' */ +#define DUK_STRIDX_SET_FULL_YEAR 235 /* 'setFullYear' */ +#define DUK_STRIDX_SET_UTC_MONTH 236 /* 'setUTCMonth' */ +#define DUK_STRIDX_SET_MONTH 237 /* 'setMonth' */ +#define DUK_STRIDX_SET_UTC_DATE 238 /* 'setUTCDate' */ +#define DUK_STRIDX_SET_DATE 239 /* 'setDate' */ +#define DUK_STRIDX_SET_UTC_HOURS 240 /* 'setUTCHours' */ +#define DUK_STRIDX_SET_HOURS 241 /* 'setHours' */ +#define DUK_STRIDX_SET_UTC_MINUTES 242 /* 'setUTCMinutes' */ +#define DUK_STRIDX_SET_MINUTES 243 /* 'setMinutes' */ +#define DUK_STRIDX_SET_UTC_SECONDS 244 /* 'setUTCSeconds' */ +#define DUK_STRIDX_SET_SECONDS 245 /* 'setSeconds' */ +#define DUK_STRIDX_SET_UTC_MILLISECONDS 246 /* 'setUTCMilliseconds' */ +#define DUK_STRIDX_SET_MILLISECONDS 247 /* 'setMilliseconds' */ +#define DUK_STRIDX_SET_TIME 248 /* 'setTime' */ +#define DUK_STRIDX_GET_TIMEZONE_OFFSET 249 /* 'getTimezoneOffset' */ +#define DUK_STRIDX_GET_UTC_MILLISECONDS 250 /* 'getUTCMilliseconds' */ +#define DUK_STRIDX_GET_MILLISECONDS 251 /* 'getMilliseconds' */ +#define DUK_STRIDX_GET_UTC_SECONDS 252 /* 'getUTCSeconds' */ +#define DUK_STRIDX_GET_SECONDS 253 /* 'getSeconds' */ +#define DUK_STRIDX_GET_UTC_MINUTES 254 /* 'getUTCMinutes' */ +#define DUK_STRIDX_GET_MINUTES 255 /* 'getMinutes' */ +#define DUK_STRIDX_GET_UTC_HOURS 256 /* 'getUTCHours' */ +#define DUK_STRIDX_GET_HOURS 257 /* 'getHours' */ +#define DUK_STRIDX_GET_UTC_DAY 258 /* 'getUTCDay' */ +#define DUK_STRIDX_GET_DAY 259 /* 'getDay' */ +#define DUK_STRIDX_GET_UTC_DATE 260 /* 'getUTCDate' */ +#define DUK_STRIDX_GET_DATE 261 /* 'getDate' */ +#define DUK_STRIDX_GET_UTC_MONTH 262 /* 'getUTCMonth' */ +#define DUK_STRIDX_GET_MONTH 263 /* 'getMonth' */ +#define DUK_STRIDX_GET_UTC_FULL_YEAR 264 /* 'getUTCFullYear' */ +#define DUK_STRIDX_GET_FULL_YEAR 265 /* 'getFullYear' */ +#define DUK_STRIDX_GET_TIME 266 /* 'getTime' */ +#define DUK_STRIDX_TO_LOCALE_TIME_STRING 267 /* 'toLocaleTimeString' */ +#define DUK_STRIDX_TO_LOCALE_DATE_STRING 268 /* 'toLocaleDateString' */ +#define DUK_STRIDX_TO_TIME_STRING 269 /* 'toTimeString' */ +#define DUK_STRIDX_TO_DATE_STRING 270 /* 'toDateString' */ +#define DUK_STRIDX_NOW 271 /* 'now' */ +#define DUK_STRIDX_UTC 272 /* 'UTC' */ +#define DUK_STRIDX_PARSE 273 /* 'parse' */ +#define DUK_STRIDX_TO_PRECISION 274 /* 'toPrecision' */ +#define DUK_STRIDX_TO_EXPONENTIAL 275 /* 'toExponential' */ +#define DUK_STRIDX_TO_FIXED 276 /* 'toFixed' */ +#define DUK_STRIDX_POSITIVE_INFINITY 277 /* 'POSITIVE_INFINITY' */ +#define DUK_STRIDX_NEGATIVE_INFINITY 278 /* 'NEGATIVE_INFINITY' */ +#define DUK_STRIDX_NAN 279 /* 'NaN' */ +#define DUK_STRIDX_MIN_VALUE 280 /* 'MIN_VALUE' */ +#define DUK_STRIDX_MAX_VALUE 281 /* 'MAX_VALUE' */ +#define DUK_STRIDX_SUBSTR 282 /* 'substr' */ +#define DUK_STRIDX_TRIM 283 /* 'trim' */ +#define DUK_STRIDX_TO_LOCALE_UPPER_CASE 284 /* 'toLocaleUpperCase' */ +#define DUK_STRIDX_TO_UPPER_CASE 285 /* 'toUpperCase' */ +#define DUK_STRIDX_TO_LOCALE_LOWER_CASE 286 /* 'toLocaleLowerCase' */ +#define DUK_STRIDX_TO_LOWER_CASE 287 /* 'toLowerCase' */ +#define DUK_STRIDX_SUBSTRING 288 /* 'substring' */ +#define DUK_STRIDX_SPLIT 289 /* 'split' */ +#define DUK_STRIDX_SEARCH 290 /* 'search' */ +#define DUK_STRIDX_REPLACE 291 /* 'replace' */ +#define DUK_STRIDX_MATCH 292 /* 'match' */ +#define DUK_STRIDX_LOCALE_COMPARE 293 /* 'localeCompare' */ +#define DUK_STRIDX_CHAR_CODE_AT 294 /* 'charCodeAt' */ +#define DUK_STRIDX_CHAR_AT 295 /* 'charAt' */ +#define DUK_STRIDX_FROM_CHAR_CODE 296 /* 'fromCharCode' */ +#define DUK_STRIDX_REDUCE_RIGHT 297 /* 'reduceRight' */ +#define DUK_STRIDX_REDUCE 298 /* 'reduce' */ +#define DUK_STRIDX_FILTER 299 /* 'filter' */ +#define DUK_STRIDX_MAP 300 /* 'map' */ +#define DUK_STRIDX_FOR_EACH 301 /* 'forEach' */ +#define DUK_STRIDX_SOME 302 /* 'some' */ +#define DUK_STRIDX_EVERY 303 /* 'every' */ +#define DUK_STRIDX_LAST_INDEX_OF 304 /* 'lastIndexOf' */ +#define DUK_STRIDX_INDEX_OF 305 /* 'indexOf' */ +#define DUK_STRIDX_UNSHIFT 306 /* 'unshift' */ +#define DUK_STRIDX_SPLICE 307 /* 'splice' */ +#define DUK_STRIDX_SORT 308 /* 'sort' */ +#define DUK_STRIDX_SLICE 309 /* 'slice' */ +#define DUK_STRIDX_SHIFT 310 /* 'shift' */ +#define DUK_STRIDX_REVERSE 311 /* 'reverse' */ +#define DUK_STRIDX_PUSH 312 /* 'push' */ +#define DUK_STRIDX_POP 313 /* 'pop' */ +#define DUK_STRIDX_JOIN 314 /* 'join' */ +#define DUK_STRIDX_CONCAT 315 /* 'concat' */ +#define DUK_STRIDX_IS_ARRAY 316 /* 'isArray' */ +#define DUK_STRIDX_LC_ARGUMENTS 317 /* 'arguments' */ +#define DUK_STRIDX_CALLER 318 /* 'caller' */ +#define DUK_STRIDX_BIND 319 /* 'bind' */ +#define DUK_STRIDX_CALL 320 /* 'call' */ +#define DUK_STRIDX_APPLY 321 /* 'apply' */ +#define DUK_STRIDX_PROPERTY_IS_ENUMERABLE 322 /* 'propertyIsEnumerable' */ +#define DUK_STRIDX_IS_PROTOTYPE_OF 323 /* 'isPrototypeOf' */ +#define DUK_STRIDX_HAS_OWN_PROPERTY 324 /* 'hasOwnProperty' */ +#define DUK_STRIDX_VALUE_OF 325 /* 'valueOf' */ +#define DUK_STRIDX_TO_LOCALE_STRING 326 /* 'toLocaleString' */ +#define DUK_STRIDX_TO_STRING 327 /* 'toString' */ +#define DUK_STRIDX_CONSTRUCTOR 328 /* 'constructor' */ +#define DUK_STRIDX_SET 329 /* 'set' */ +#define DUK_STRIDX_GET 330 /* 'get' */ +#define DUK_STRIDX_ENUMERABLE 331 /* 'enumerable' */ +#define DUK_STRIDX_CONFIGURABLE 332 /* 'configurable' */ +#define DUK_STRIDX_WRITABLE 333 /* 'writable' */ +#define DUK_STRIDX_VALUE 334 /* 'value' */ +#define DUK_STRIDX_KEYS 335 /* 'keys' */ +#define DUK_STRIDX_IS_EXTENSIBLE 336 /* 'isExtensible' */ +#define DUK_STRIDX_IS_FROZEN 337 /* 'isFrozen' */ +#define DUK_STRIDX_IS_SEALED 338 /* 'isSealed' */ +#define DUK_STRIDX_PREVENT_EXTENSIONS 339 /* 'preventExtensions' */ +#define DUK_STRIDX_FREEZE 340 /* 'freeze' */ +#define DUK_STRIDX_SEAL 341 /* 'seal' */ +#define DUK_STRIDX_DEFINE_PROPERTIES 342 /* 'defineProperties' */ +#define DUK_STRIDX_DEFINE_PROPERTY 343 /* 'defineProperty' */ +#define DUK_STRIDX_CREATE 344 /* 'create' */ +#define DUK_STRIDX_GET_OWN_PROPERTY_NAMES 345 /* 'getOwnPropertyNames' */ +#define DUK_STRIDX_GET_OWN_PROPERTY_DESCRIPTOR 346 /* 'getOwnPropertyDescriptor' */ +#define DUK_STRIDX_GET_PROTOTYPE_OF 347 /* 'getPrototypeOf' */ +#define DUK_STRIDX_PROTOTYPE 348 /* 'prototype' */ +#define DUK_STRIDX_LENGTH 349 /* 'length' */ +#define DUK_STRIDX_ALERT 350 /* 'alert' */ +#define DUK_STRIDX_PRINT 351 /* 'print' */ +#define DUK_STRIDX_UNESCAPE 352 /* 'unescape' */ +#define DUK_STRIDX_ESCAPE 353 /* 'escape' */ +#define DUK_STRIDX_ENCODE_URI_COMPONENT 354 /* 'encodeURIComponent' */ +#define DUK_STRIDX_ENCODE_URI 355 /* 'encodeURI' */ +#define DUK_STRIDX_DECODE_URI_COMPONENT 356 /* 'decodeURIComponent' */ +#define DUK_STRIDX_DECODE_URI 357 /* 'decodeURI' */ +#define DUK_STRIDX_IS_FINITE 358 /* 'isFinite' */ +#define DUK_STRIDX_IS_NAN 359 /* 'isNaN' */ +#define DUK_STRIDX_PARSE_FLOAT 360 /* 'parseFloat' */ +#define DUK_STRIDX_PARSE_INT 361 /* 'parseInt' */ +#define DUK_STRIDX_EVAL 362 /* 'eval' */ +#define DUK_STRIDX_URI_ERROR 363 /* 'URIError' */ +#define DUK_STRIDX_TYPE_ERROR 364 /* 'TypeError' */ +#define DUK_STRIDX_SYNTAX_ERROR 365 /* 'SyntaxError' */ +#define DUK_STRIDX_REFERENCE_ERROR 366 /* 'ReferenceError' */ +#define DUK_STRIDX_RANGE_ERROR 367 /* 'RangeError' */ +#define DUK_STRIDX_EVAL_ERROR 368 /* 'EvalError' */ +#define DUK_STRIDX_BREAK 369 /* 'break' */ +#define DUK_STRIDX_CASE 370 /* 'case' */ +#define DUK_STRIDX_CATCH 371 /* 'catch' */ +#define DUK_STRIDX_CONTINUE 372 /* 'continue' */ +#define DUK_STRIDX_DEBUGGER 373 /* 'debugger' */ +#define DUK_STRIDX_DEFAULT 374 /* 'default' */ +#define DUK_STRIDX_DELETE 375 /* 'delete' */ +#define DUK_STRIDX_DO 376 /* 'do' */ +#define DUK_STRIDX_ELSE 377 /* 'else' */ +#define DUK_STRIDX_FINALLY 378 /* 'finally' */ +#define DUK_STRIDX_FOR 379 /* 'for' */ +#define DUK_STRIDX_LC_FUNCTION 380 /* 'function' */ +#define DUK_STRIDX_IF 381 /* 'if' */ +#define DUK_STRIDX_IN 382 /* 'in' */ +#define DUK_STRIDX_INSTANCEOF 383 /* 'instanceof' */ +#define DUK_STRIDX_NEW 384 /* 'new' */ +#define DUK_STRIDX_RETURN 385 /* 'return' */ +#define DUK_STRIDX_SWITCH 386 /* 'switch' */ +#define DUK_STRIDX_THIS 387 /* 'this' */ +#define DUK_STRIDX_THROW 388 /* 'throw' */ +#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_ENUM 397 /* 'enum' */ +#define DUK_STRIDX_EXPORT 398 /* 'export' */ +#define DUK_STRIDX_EXTENDS 399 /* 'extends' */ +#define DUK_STRIDX_IMPORT 400 /* 'import' */ +#define DUK_STRIDX_SUPER 401 /* 'super' */ +#define DUK_STRIDX_LC_NULL 402 /* 'null' */ +#define DUK_STRIDX_TRUE 403 /* 'true' */ +#define DUK_STRIDX_FALSE 404 /* 'false' */ +#define DUK_STRIDX_IMPLEMENTS 405 /* 'implements' */ +#define DUK_STRIDX_INTERFACE 406 /* 'interface' */ +#define DUK_STRIDX_LET 407 /* 'let' */ +#define DUK_STRIDX_PACKAGE 408 /* 'package' */ +#define DUK_STRIDX_PRIVATE 409 /* 'private' */ +#define DUK_STRIDX_PROTECTED 410 /* 'protected' */ +#define DUK_STRIDX_PUBLIC 411 /* 'public' */ +#define DUK_STRIDX_STATIC 412 /* 'static' */ +#define DUK_STRIDX_YIELD 413 /* 'yield' */ #define DUK_HEAP_STRING_UC_LOGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_LOGGER) #define DUK_HTHREAD_STRING_UC_LOGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_LOGGER) @@ -2834,12 +3438,34 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD) #define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER) #define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER) -#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) -#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) #define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV) #define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV) #define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV) #define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV) +#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY) +#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY) +#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY) +#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY) +#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY) +#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY) +#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY) +#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY) +#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY) +#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY) +#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY) +#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY) +#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW) +#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW) +#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER) +#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER) +#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER) #define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING) #define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING) #define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL) @@ -2984,8 +3610,6 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE) #define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER) #define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER) -#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER) -#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER) #define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA) #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA) #define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER) @@ -3000,6 +3624,142 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HTHREAD_STRING_THROW_TYPE_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW_TYPE_ERROR) #define DUK_HEAP_STRING_DUKTAPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DUKTAPE) #define DUK_HTHREAD_STRING_DUKTAPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DUKTAPE) +#define DUK_HEAP_STRING_SET_FLOAT64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT64) +#define DUK_HTHREAD_STRING_SET_FLOAT64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT64) +#define DUK_HEAP_STRING_SET_FLOAT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_FLOAT32) +#define DUK_HTHREAD_STRING_SET_FLOAT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_FLOAT32) +#define DUK_HEAP_STRING_SET_UINT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT32) +#define DUK_HTHREAD_STRING_SET_UINT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT32) +#define DUK_HEAP_STRING_SET_INT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT32) +#define DUK_HTHREAD_STRING_SET_INT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT32) +#define DUK_HEAP_STRING_SET_UINT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT16) +#define DUK_HTHREAD_STRING_SET_UINT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT16) +#define DUK_HEAP_STRING_SET_INT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT16) +#define DUK_HTHREAD_STRING_SET_INT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT16) +#define DUK_HEAP_STRING_SET_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_UINT8) +#define DUK_HTHREAD_STRING_SET_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_UINT8) +#define DUK_HEAP_STRING_SET_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_INT8) +#define DUK_HTHREAD_STRING_SET_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_INT8) +#define DUK_HEAP_STRING_GET_FLOAT64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT64) +#define DUK_HTHREAD_STRING_GET_FLOAT64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT64) +#define DUK_HEAP_STRING_GET_FLOAT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_FLOAT32) +#define DUK_HTHREAD_STRING_GET_FLOAT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_FLOAT32) +#define DUK_HEAP_STRING_GET_UINT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT32) +#define DUK_HTHREAD_STRING_GET_UINT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT32) +#define DUK_HEAP_STRING_GET_INT32(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT32) +#define DUK_HTHREAD_STRING_GET_INT32(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT32) +#define DUK_HEAP_STRING_GET_UINT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT16) +#define DUK_HTHREAD_STRING_GET_UINT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT16) +#define DUK_HEAP_STRING_GET_INT16(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT16) +#define DUK_HTHREAD_STRING_GET_INT16(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT16) +#define DUK_HEAP_STRING_GET_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_UINT8) +#define DUK_HTHREAD_STRING_GET_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_UINT8) +#define DUK_HEAP_STRING_GET_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET_INT8) +#define DUK_HTHREAD_STRING_GET_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET_INT8) +#define DUK_HEAP_STRING_SUBARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUBARRAY) +#define DUK_HTHREAD_STRING_SUBARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUBARRAY) +#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT) +#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT) +#define DUK_HEAP_STRING_BYTE_OFFSET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET) +#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET) +#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER) +#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER) +#define DUK_HEAP_STRING_IS_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_VIEW) +#define DUK_HTHREAD_STRING_IS_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_VIEW) +#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA) +#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA) +#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE) +#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE) +#define DUK_HEAP_STRING_WRITE_INT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_BE) +#define DUK_HTHREAD_STRING_WRITE_INT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_BE) +#define DUK_HEAP_STRING_WRITE_INT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT_LE) +#define DUK_HTHREAD_STRING_WRITE_INT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT_LE) +#define DUK_HEAP_STRING_WRITE_UINT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_BE) +#define DUK_HEAP_STRING_WRITE_UINT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT_LE) +#define DUK_HEAP_STRING_WRITE_DOUBLE_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_BE) +#define DUK_HTHREAD_STRING_WRITE_DOUBLE_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_BE) +#define DUK_HEAP_STRING_WRITE_DOUBLE_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_DOUBLE_LE) +#define DUK_HTHREAD_STRING_WRITE_DOUBLE_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_DOUBLE_LE) +#define DUK_HEAP_STRING_WRITE_FLOAT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_BE) +#define DUK_HTHREAD_STRING_WRITE_FLOAT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_BE) +#define DUK_HEAP_STRING_WRITE_FLOAT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_FLOAT_LE) +#define DUK_HTHREAD_STRING_WRITE_FLOAT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_FLOAT_LE) +#define DUK_HEAP_STRING_WRITE_INT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_BE) +#define DUK_HTHREAD_STRING_WRITE_INT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_BE) +#define DUK_HEAP_STRING_WRITE_INT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT32_LE) +#define DUK_HTHREAD_STRING_WRITE_INT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT32_LE) +#define DUK_HEAP_STRING_WRITE_UINT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_BE) +#define DUK_HEAP_STRING_WRITE_UINT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT32_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT32_LE) +#define DUK_HEAP_STRING_WRITE_INT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_BE) +#define DUK_HTHREAD_STRING_WRITE_INT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_BE) +#define DUK_HEAP_STRING_WRITE_INT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT16_LE) +#define DUK_HTHREAD_STRING_WRITE_INT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT16_LE) +#define DUK_HEAP_STRING_WRITE_UINT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_BE) +#define DUK_HTHREAD_STRING_WRITE_UINT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_BE) +#define DUK_HEAP_STRING_WRITE_UINT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT16_LE) +#define DUK_HTHREAD_STRING_WRITE_UINT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT16_LE) +#define DUK_HEAP_STRING_WRITE_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_INT8) +#define DUK_HTHREAD_STRING_WRITE_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_INT8) +#define DUK_HEAP_STRING_WRITE_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE_UINT8) +#define DUK_HTHREAD_STRING_WRITE_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE_UINT8) +#define DUK_HEAP_STRING_READ_INT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_BE) +#define DUK_HTHREAD_STRING_READ_INT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_BE) +#define DUK_HEAP_STRING_READ_INT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT_LE) +#define DUK_HTHREAD_STRING_READ_INT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT_LE) +#define DUK_HEAP_STRING_READ_UINT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_BE) +#define DUK_HTHREAD_STRING_READ_UINT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_BE) +#define DUK_HEAP_STRING_READ_UINT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT_LE) +#define DUK_HTHREAD_STRING_READ_UINT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT_LE) +#define DUK_HEAP_STRING_READ_DOUBLE_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_BE) +#define DUK_HTHREAD_STRING_READ_DOUBLE_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_BE) +#define DUK_HEAP_STRING_READ_DOUBLE_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_DOUBLE_LE) +#define DUK_HTHREAD_STRING_READ_DOUBLE_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_DOUBLE_LE) +#define DUK_HEAP_STRING_READ_FLOAT_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_BE) +#define DUK_HTHREAD_STRING_READ_FLOAT_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_BE) +#define DUK_HEAP_STRING_READ_FLOAT_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_FLOAT_LE) +#define DUK_HTHREAD_STRING_READ_FLOAT_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_FLOAT_LE) +#define DUK_HEAP_STRING_READ_INT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_BE) +#define DUK_HTHREAD_STRING_READ_INT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_BE) +#define DUK_HEAP_STRING_READ_INT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT32_LE) +#define DUK_HTHREAD_STRING_READ_INT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT32_LE) +#define DUK_HEAP_STRING_READ_UINT32_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_BE) +#define DUK_HTHREAD_STRING_READ_UINT32_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_BE) +#define DUK_HEAP_STRING_READ_UINT32_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT32_LE) +#define DUK_HTHREAD_STRING_READ_UINT32_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT32_LE) +#define DUK_HEAP_STRING_READ_INT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_BE) +#define DUK_HTHREAD_STRING_READ_INT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_BE) +#define DUK_HEAP_STRING_READ_INT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT16_LE) +#define DUK_HTHREAD_STRING_READ_INT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT16_LE) +#define DUK_HEAP_STRING_READ_UINT16_BE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_BE) +#define DUK_HTHREAD_STRING_READ_UINT16_BE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_BE) +#define DUK_HEAP_STRING_READ_UINT16_LE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT16_LE) +#define DUK_HTHREAD_STRING_READ_UINT16_LE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT16_LE) +#define DUK_HEAP_STRING_READ_INT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_INT8) +#define DUK_HTHREAD_STRING_READ_INT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_INT8) +#define DUK_HEAP_STRING_READ_UINT8(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_READ_UINT8) +#define DUK_HTHREAD_STRING_READ_UINT8(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_READ_UINT8) +#define DUK_HEAP_STRING_COPY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COPY) +#define DUK_HTHREAD_STRING_COPY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COPY) +#define DUK_HEAP_STRING_EQUALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EQUALS) +#define DUK_HTHREAD_STRING_EQUALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EQUALS) +#define DUK_HEAP_STRING_FILL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILL) +#define DUK_HTHREAD_STRING_FILL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILL) +#define DUK_HEAP_STRING_WRITE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITE) +#define DUK_HTHREAD_STRING_WRITE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITE) +#define DUK_HEAP_STRING_COMPARE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPARE) +#define DUK_HTHREAD_STRING_COMPARE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPARE) +#define DUK_HEAP_STRING_BYTE_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH) +#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH) +#define DUK_HEAP_STRING_IS_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_BUFFER) +#define DUK_HTHREAD_STRING_IS_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_BUFFER) +#define DUK_HEAP_STRING_IS_ENCODING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IS_ENCODING) +#define DUK_HTHREAD_STRING_IS_ENCODING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IS_ENCODING) +#define DUK_HEAP_STRING_EXPORTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS) +#define DUK_HTHREAD_STRING_EXPORTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS) #define DUK_HEAP_STRING_ID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID) #define DUK_HTHREAD_STRING_ID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID) #define DUK_HEAP_STRING_REQUIRE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE) @@ -3501,21 +4261,21 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1943]; #define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD) #define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD) -#define DUK_HEAP_NUM_STRINGS 336 +#define DUK_HEAP_NUM_STRINGS 414 -#define DUK_STRIDX_START_RESERVED 291 -#define DUK_STRIDX_START_STRICT_RESERVED 327 -#define DUK_STRIDX_END_RESERVED 336 /* exclusive endpoint */ +#define DUK_STRIDX_START_RESERVED 369 +#define DUK_STRIDX_START_STRICT_RESERVED 405 +#define DUK_STRIDX_END_RESERVED 414 /* exclusive endpoint */ #if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[128]; -DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[1341]; +DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[147]; +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[187]; #endif /* DUK_USE_BUILTIN_INITJS */ #endif /* !DUK_SINGLE_FILE */ -#define DUK_BUILTINS_DATA_LENGTH 1341 +#define DUK_BUILTINS_DATA_LENGTH 1952 #ifdef DUK_USE_BUILTIN_INITJS #define DUK_BUILTIN_INITJS_DATA_LENGTH 187 #endif /* DUK_USE_BUILTIN_INITJS */ @@ -3566,8 +4326,33 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187]; #define DUK_BIDX_LOGGER_CONSTRUCTOR 43 #define DUK_BIDX_LOGGER_PROTOTYPE 44 #define DUK_BIDX_DOUBLE_ERROR 45 - -#define DUK_NUM_BUILTINS 46 +#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR 46 +#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 47 +#define DUK_BIDX_DATAVIEW_CONSTRUCTOR 48 +#define DUK_BIDX_DATAVIEW_PROTOTYPE 49 +#define DUK_BIDX_TYPEDARRAY_PROTOTYPE 50 +#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR 51 +#define DUK_BIDX_INT8ARRAY_PROTOTYPE 52 +#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR 53 +#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 54 +#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR 55 +#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 56 +#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR 57 +#define DUK_BIDX_INT16ARRAY_PROTOTYPE 58 +#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR 59 +#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 60 +#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR 61 +#define DUK_BIDX_INT32ARRAY_PROTOTYPE 62 +#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR 63 +#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 64 +#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR 65 +#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 66 +#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR 67 +#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 68 +#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR 69 +#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 70 + +#define DUK_NUM_BUILTINS 71 #else #error invalid endianness defines @@ -3575,6 +4360,527 @@ DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[187]; #endif /* DUK_BUILTINS_H_INCLUDED */ #line 50 "duk_internal.h" +#line 1 "duk_util.h" +/* + * Utilities + */ + +#ifndef DUK_UTIL_H_INCLUDED +#define DUK_UTIL_H_INCLUDED + +#define DUK_UTIL_MIN_HASH_PRIME 17 /* must match genhashsizes.py */ + +#define DUK_UTIL_GET_HASH_PROBE_STEP(hash) (duk_util_probe_steps[(hash) & 0x1f]) + +/* + * Endian conversion + */ + +#if defined(DUK_USE_INTEGER_LE) +#define DUK_HTON32(x) DUK_BSWAP32((x)) +#define DUK_NTOH32(x) DUK_BSWAP32((x)) +#define DUK_HTON16(x) DUK_BSWAP16((x)) +#define DUK_NTOH16(x) DUK_BSWAP16((x)) +#elif defined(DUK_USE_INTEGER_BE) +#define DUK_HTON32(x) (x) +#define DUK_NTOH32(x) (x) +#define DUK_HTON16(x) (x) +#define DUK_NTOH16(x) (x) +#else +#error internal error, endianness defines broken +#endif + +/* + * Bitstream decoder + */ + +struct duk_bitdecoder_ctx { + const duk_uint8_t *data; + duk_size_t offset; + duk_size_t length; + duk_uint32_t currval; + duk_small_int_t currbits; +}; + +/* + * Bitstream encoder + */ + +struct duk_bitencoder_ctx { + duk_uint8_t *data; + duk_size_t offset; + duk_size_t length; + duk_uint32_t currval; + duk_small_int_t currbits; + duk_small_int_t truncated; +}; + +/* + * Raw write/read macros for big endian, unaligned basic values. + * Caller ensures there's enough space. The macros update the pointer + * argument automatically on resizes. The idiom seems a bit odd, but + * leads to compact code. + */ + +#define DUK_RAW_WRITE_U8(ptr,val) do { \ + *(ptr)++ = (duk_uint8_t) (val); \ + } while (0) +#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val)) +#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val)) +#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val)) +#define DUK_RAW_WRITE_XUTF8(ptr,val) do { \ + /* 'ptr' is evaluated both as LHS and RHS. */ \ + duk_uint8_t *duk__ptr; \ + duk_small_int_t duk__len; \ + duk__ptr = (duk_uint8_t *) (ptr); \ + duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \ + duk__ptr += duk__len; \ + (ptr) = duk__ptr; \ + } while (0) +#define DUK_RAW_WRITE_CESU8(ptr,val) do { \ + /* 'ptr' is evaluated both as LHS and RHS. */ \ + duk_uint8_t *duk__ptr; \ + duk_small_int_t duk__len; \ + duk__ptr = (duk_uint8_t *) (ptr); \ + duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \ + duk__ptr += duk__len; \ + (ptr) = duk__ptr; \ + } while (0) + +#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++)) +#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr)); +#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr)); +#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr)); + +/* + * Buffer writer (dynamic buffer only) + * + * Helper for writing to a dynamic buffer with a concept of a "spare" area + * to reduce resizes. You can ensure there is enough space beforehand and + * then write for a while without further checks, relying on a stable data + * pointer. Spare handling is automatic so call sites only indicate how + * much data they need right now. + * + * There are several ways to write using bufwriter. The best approach + * depends mainly on how much performance matters over code footprint. + * The key issues are (1) ensuring there is space and (2) keeping the + * pointers consistent. Fast code should ensure space for multiple writes + * with one ensure call. Fastest inner loop code can temporarily borrow + * the 'p' pointer but must write it back eventually. + * + * Be careful to ensure all macro arguments (other than static pointers like + * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if + * necessary (if that's not possible, there should be a note near the macro). + * Buffer write arguments often contain arithmetic etc so this is + * particularly important here. + */ + +/* XXX: Migrate bufwriter and other read/write helpers to its own header? */ + +struct duk_bufwriter_ctx { + duk_uint8_t *p; + duk_uint8_t *p_base; + duk_uint8_t *p_limit; + duk_hbuffer_dynamic *buf; +}; + +#define DUK_BW_SPARE_ADD 64 +#define DUK_BW_SPARE_SHIFT 4 /* 2^4 -> 1/16 = 6.25% spare */ + +/* Initialization and finalization (compaction), converting to other types. */ + +#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \ + duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \ + } while (0) +#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \ + duk_bw_init((thr), (bw_ctx), (buf)); \ + } while (0) +#define DUK_BW_COMPACT(thr,bw_ctx) do { \ + /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \ + duk_bw_compact((thr), (bw_ctx)); \ + } while (0) +#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \ + duk_push_lstring((duk_context *) (thr), \ + (const char *) (bw_ctx)->p_base, \ + (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \ + } while (0) +/* Pointers may be NULL for a while when 'buf' size is zero and before any + * ENSURE calls have been made. Once an ENSURE has been made, the pointers + * are required to be non-NULL so that it's always valid to use memcpy() and + * memmove(), even for zero size. + */ +#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \ + DUK_ASSERT_EXPR((bw_ctx) != NULL && \ + (bw_ctx)->buf != NULL && \ + ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \ + ((bw_ctx)->p != NULL && \ + (bw_ctx)->p_base != NULL && \ + (bw_ctx)->p_limit != NULL && \ + (bw_ctx)->p_limit >= (bw_ctx)->p_base && \ + (bw_ctx)->p >= (bw_ctx)->p_base && \ + (bw_ctx)->p <= (bw_ctx)->p_limit))) +#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \ + DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \ + } while (0) + +/* Working with the pointer and current size. */ + +#define DUK_BW_GET_PTR(thr,bw_ctx) \ + ((bw_ctx)->p) +#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \ + (bw_ctx)->p = (ptr); \ + } while (0) +#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \ + (bw_ctx)->p += (delta); \ + } while (0) +#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \ + ((bw_ctx)->p_base) +#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \ + ((bw_ctx)->p_limit) +#define DUK_BW_GET_SIZE(thr,bw_ctx) \ + ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)) +#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \ + DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \ + (bw_ctx)->p = (bw_ctx)->p_base + (sz); \ + } while (0) +#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \ + /* Reset to zero size, keep current limit. */ \ + (bw_ctx)->p = (bw_ctx)->p_base; \ + } while (0) +#define DUK_BW_GET_BUFFER(thr,bw_ctx) \ + ((bw_ctx)->buf) + +/* Ensuring (reserving) space. */ + +#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \ + duk_size_t duk__sz, duk__space; \ + DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \ + duk__sz = (sz); \ + duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \ + if (duk__space < duk__sz) { \ + (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \ + } \ + } while (0) +/* NOTE: Multiple evaluation of 'ptr' in this macro. */ +/* XXX: Rework to use an always-inline function? */ +#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \ + (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \ + (ptr) : \ + ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz)))) +#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \ + DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p) +#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \ + (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \ + DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz))) +#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \ + DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \ + } while (0) + +/* Miscellaneous. */ + +#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \ + (bw_ctx)->p = (ptr); \ + duk_bw_compact((thr), (bw_ctx)); \ + } while (0) + +/* Fast write calls which assume you control the spare beforehand. + * Multibyte write variants exist and use a temporary write pointer + * because byte writes alias with anything: with a stored pointer + * explicit pointer load/stores get generated (e.g. gcc -Os). + */ + +#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \ + *(bw_ctx)->p++ = (duk_uint8_t) (val); \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + *duk__p++ = (duk_uint8_t) (val4); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + *duk__p++ = (duk_uint8_t) (val4); \ + *duk__p++ = (duk_uint8_t) (val5); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \ + duk_uint8_t *duk__p; \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \ + duk__p = (bw_ctx)->p; \ + *duk__p++ = (duk_uint8_t) (val1); \ + *duk__p++ = (duk_uint8_t) (val2); \ + *duk__p++ = (duk_uint8_t) (val3); \ + *duk__p++ = (duk_uint8_t) (val4); \ + *duk__p++ = (duk_uint8_t) (val5); \ + *duk__p++ = (duk_uint8_t) (val6); \ + (bw_ctx)->p = duk__p; \ + } while (0) +#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \ + duk_ucodepoint_t duk__cp; \ + duk_small_int_t duk__enc_len; \ + duk__cp = (cp); \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \ + duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \ + (bw_ctx)->p += duk__enc_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \ + duk_ucodepoint_t duk__cp; \ + duk_small_int_t duk__enc_len; \ + duk__cp = (duk_ucodepoint_t) (cp); \ + DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \ + duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \ + (bw_ctx)->p += duk__enc_len; \ + } while (0) +/* XXX: add temporary duk__p pointer here too; sharing */ +#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \ + const void *duk__valptr; \ + duk_size_t duk__valsz; \ + duk__valptr = (const void *) (valptr); \ + duk__valsz = (duk_size_t) (valsz); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \ + (bw_ctx)->p += duk__valsz; \ + } while (0) +#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \ + const duk_uint8_t *duk__val; \ + duk_size_t duk__val_len; \ + duk__val = (const duk_uint8_t *) (val); \ + duk__val_len = DUK_STRLEN((const char *) duk__val); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) + +/* Append bytes from a slice already in the buffer. */ +#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \ + duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len)) + +/* Insert bytes in the middle of the buffer from an external buffer. */ +#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \ + duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len)) + +/* Insert bytes in the middle of the buffer from a slice already + * in the buffer. Source offset is interpreted "before" the operation. + */ +#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \ + duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len)) + +/* Insert a reserved area somewhere in the buffer; caller fills it. + * Evaluates to a (duk_uint_t *) pointing to the start of the reserved + * area for convenience. + */ +#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \ + duk_bw_insert_raw_area((thr), (bw), (off), (len)) + +/* Remove a slice from inside buffer. */ +#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \ + duk_bw_remove_raw_slice((thr), (bw), (off), (len)) + +/* Safe write calls which will ensure space first. */ + +#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 1); \ + DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 2); \ + DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 3); \ + DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 4); \ + DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 5); \ + DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), 6); \ + DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \ + DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \ + } while (0) +#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \ + DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \ + DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \ + } while (0) +/* XXX: add temporary duk__p pointer here too; sharing */ +#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \ + const void *duk__valptr; \ + duk_size_t duk__valsz; \ + duk__valptr = (const void *) (valptr); \ + duk__valsz = (duk_size_t) (valsz); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \ + (bw_ctx)->p += duk__valsz; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \ + const duk_uint8_t *duk__val; \ + duk_size_t duk__val_len; \ + duk__val = (const duk_uint8_t *) (val); \ + duk__val_len = DUK_STRLEN((const char *) duk__val); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) +#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \ + duk_size_t duk__val_len; \ + duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \ + DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \ + DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \ + (bw_ctx)->p += duk__val_len; \ + } while (0) + +#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \ + duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len)) +#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \ + duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len)) +#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \ + duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len)) +#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \ + /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \ + duk_bw_insert_ensure_area((thr), (bw), (off), (len)) +#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \ + /* No difference between raw/ensure because the buffer shrinks. */ \ + DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len)) + +/* + * Externs and prototypes + */ + +#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]; +#endif /* !DUK_SINGLE_FILE */ + +/* Note: assumes that duk_util_probe_steps size is 32 */ +#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE) +#if !defined(DUK_SINGLE_FILE) +DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32]; +#endif /* !DUK_SINGLE_FILE */ +#endif + +DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed); + +#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); +#endif + +DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits); +DUK_INTERNAL_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx); +DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value); + +DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits); +DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx); + +DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n); +DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr); + +DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf); +DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size); +DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz); +DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx); +DUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len); +DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); +DUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); +DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len); +/* No duk_bw_remove_ensure_slice(), functionality would be identical. */ + +DUK_ALWAYS_INLINE DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p); +DUK_ALWAYS_INLINE DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p); +DUK_ALWAYS_INLINE DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p); +DUK_ALWAYS_INLINE DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val); +DUK_ALWAYS_INLINE DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val); +DUK_ALWAYS_INLINE DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val); + +#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */ +DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len); +#endif + +#endif /* DUK_UTIL_H_INCLUDED */ #line 1 "duk_strings.h" /* * Shared error messages: declarations and macros @@ -3631,9 +4937,7 @@ DUK_INTERNAL_DECL const char *duk_str_not_configurable; #define DUK_STR_NOT_BUFFER duk_str_not_buffer #define DUK_STR_UNEXPECTED_TYPE duk_str_unexpected_type #define DUK_STR_NOT_THREAD duk_str_not_thread -#if 0 /*unused*/ #define DUK_STR_NOT_COMPILEDFUNCTION duk_str_not_compiledfunction -#endif #define DUK_STR_NOT_NATIVEFUNCTION duk_str_not_nativefunction #define DUK_STR_NOT_C_FUNCTION duk_str_not_c_function #define DUK_STR_DEFAULTVALUE_COERCE_FAILED duk_str_defaultvalue_coerce_failed @@ -3642,19 +4946,16 @@ DUK_INTERNAL_DECL const char *duk_str_not_configurable; #define DUK_STR_STRING_TOO_LONG duk_str_string_too_long #define DUK_STR_BUFFER_TOO_LONG duk_str_buffer_too_long #define DUK_STR_SPRINTF_TOO_LONG duk_str_sprintf_too_long -#define DUK_STR_OBJECT_ALLOC_FAILED duk_str_object_alloc_failed -#define DUK_STR_THREAD_ALLOC_FAILED duk_str_thread_alloc_failed -#define DUK_STR_FUNC_ALLOC_FAILED duk_str_func_alloc_failed -#define DUK_STR_BUFFER_ALLOC_FAILED duk_str_buffer_alloc_failed +#define DUK_STR_ALLOC_FAILED duk_str_alloc_failed #define DUK_STR_POP_TOO_MANY duk_str_pop_too_many #define DUK_STR_BUFFER_NOT_DYNAMIC duk_str_buffer_not_dynamic #define DUK_STR_FAILED_TO_EXTEND_VALSTACK duk_str_failed_to_extend_valstack -#define DUK_STR_BASE64_ENCODE_FAILED duk_str_base64_encode_failed -#define DUK_STR_BASE64_DECODE_FAILED duk_str_base64_decode_failed -#define DUK_STR_HEX_DECODE_FAILED duk_str_hex_decode_failed +#define DUK_STR_ENCODE_FAILED duk_str_encode_failed +#define DUK_STR_DECODE_FAILED duk_str_decode_failed #define DUK_STR_NO_SOURCECODE duk_str_no_sourcecode #define DUK_STR_CONCAT_RESULT_TOO_LONG duk_str_concat_result_too_long #define DUK_STR_UNIMPLEMENTED duk_str_unimplemented +#define DUK_STR_UNSUPPORTED duk_str_unsupported #define DUK_STR_ARRAY_LENGTH_OVER_2G duk_str_array_length_over_2g #if !defined(DUK_SINGLE_FILE) @@ -3670,9 +4971,7 @@ 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; -#if 0 /*unused*/ DUK_INTERNAL_DECL const char *duk_str_not_compiledfunction; -#endif 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; @@ -3681,19 +4980,16 @@ DUK_INTERNAL_DECL const char *duk_str_not_object_coercible; DUK_INTERNAL_DECL const char *duk_str_string_too_long; DUK_INTERNAL_DECL const char *duk_str_buffer_too_long; DUK_INTERNAL_DECL const char *duk_str_sprintf_too_long; -DUK_INTERNAL_DECL const char *duk_str_object_alloc_failed; -DUK_INTERNAL_DECL const char *duk_str_thread_alloc_failed; -DUK_INTERNAL_DECL const char *duk_str_func_alloc_failed; -DUK_INTERNAL_DECL const char *duk_str_buffer_alloc_failed; +DUK_INTERNAL_DECL const char *duk_str_alloc_failed; DUK_INTERNAL_DECL const char *duk_str_pop_too_many; DUK_INTERNAL_DECL const char *duk_str_buffer_not_dynamic; DUK_INTERNAL_DECL const char *duk_str_failed_to_extend_valstack; -DUK_INTERNAL_DECL const char *duk_str_base64_encode_failed; -DUK_INTERNAL_DECL const char *duk_str_base64_decode_failed; -DUK_INTERNAL_DECL const char *duk_str_hex_decode_failed; +DUK_INTERNAL_DECL const char *duk_str_encode_failed; +DUK_INTERNAL_DECL const char *duk_str_decode_failed; DUK_INTERNAL_DECL const char *duk_str_no_sourcecode; DUK_INTERNAL_DECL const char *duk_str_concat_result_too_long; DUK_INTERNAL_DECL const char *duk_str_unimplemented; +DUK_INTERNAL_DECL const char *duk_str_unsupported; DUK_INTERNAL_DECL const char *duk_str_array_length_over_2g; #endif /* !DUK_SINGLE_FILE */ @@ -4113,149 +5409,146 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo #define DUK_LEXER_SETPOINT(ctx,pt) duk_lexer_setpoint((ctx), (pt)) -#define DUK_LEXER_GETPOINT(ctx,pt) do { (pt)->offset = (ctx)->offsets[0]; \ - (pt)->line = (ctx)->lines[0]; } while (0) +#define DUK_LEXER_GETPOINT(ctx,pt) do { (pt)->offset = (ctx)->window[0].offset; \ + (pt)->line = (ctx)->window[0].line; } while (0) /* currently 6 characters of lookup are actually needed (duk_lexer.c) */ -#define DUK_LEXER_WINDOW_SIZE 8 +#define DUK_LEXER_WINDOW_SIZE 6 +#if defined(DUK_USE_LEXER_SLIDING_WINDOW) +#define DUK_LEXER_BUFFER_SIZE 64 +#endif #define DUK_TOK_MINVAL 0 /* returned after EOF (infinite amount) */ #define DUK_TOK_EOF 0 -/* line terminator or multi-line comment with internal lineterm (E5 Sections 7.3, 7.4) */ -#define DUK_TOK_LINETERM 1 - -/* single-line comment or multi-line comment without internal lineterm (E5 Section 7.4) */ -#define DUK_TOK_COMMENT 2 - /* identifier names (E5 Section 7.6) */ -#define DUK_TOK_IDENTIFIER 3 +#define DUK_TOK_IDENTIFIER 1 /* reserved words: keywords */ -#define DUK_TOK_START_RESERVED 4 -#define DUK_TOK_BREAK 4 -#define DUK_TOK_CASE 5 -#define DUK_TOK_CATCH 6 -#define DUK_TOK_CONTINUE 7 -#define DUK_TOK_DEBUGGER 8 -#define DUK_TOK_DEFAULT 9 -#define DUK_TOK_DELETE 10 -#define DUK_TOK_DO 11 -#define DUK_TOK_ELSE 12 -#define DUK_TOK_FINALLY 13 -#define DUK_TOK_FOR 14 -#define DUK_TOK_FUNCTION 15 -#define DUK_TOK_IF 16 -#define DUK_TOK_IN 17 -#define DUK_TOK_INSTANCEOF 18 -#define DUK_TOK_NEW 19 -#define DUK_TOK_RETURN 20 -#define DUK_TOK_SWITCH 21 -#define DUK_TOK_THIS 22 -#define DUK_TOK_THROW 23 -#define DUK_TOK_TRY 24 -#define DUK_TOK_TYPEOF 25 -#define DUK_TOK_VAR 26 -#define DUK_TOK_VOID 27 -#define DUK_TOK_WHILE 28 -#define DUK_TOK_WITH 29 +#define DUK_TOK_START_RESERVED 2 +#define DUK_TOK_BREAK 2 +#define DUK_TOK_CASE 3 +#define DUK_TOK_CATCH 4 +#define DUK_TOK_CONTINUE 5 +#define DUK_TOK_DEBUGGER 6 +#define DUK_TOK_DEFAULT 7 +#define DUK_TOK_DELETE 8 +#define DUK_TOK_DO 9 +#define DUK_TOK_ELSE 10 +#define DUK_TOK_FINALLY 11 +#define DUK_TOK_FOR 12 +#define DUK_TOK_FUNCTION 13 +#define DUK_TOK_IF 14 +#define DUK_TOK_IN 15 +#define DUK_TOK_INSTANCEOF 16 +#define DUK_TOK_NEW 17 +#define DUK_TOK_RETURN 18 +#define DUK_TOK_SWITCH 19 +#define DUK_TOK_THIS 20 +#define DUK_TOK_THROW 21 +#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 /* reserved words: future reserved words */ -#define DUK_TOK_CLASS 30 -#define DUK_TOK_CONST 31 -#define DUK_TOK_ENUM 32 -#define DUK_TOK_EXPORT 33 -#define DUK_TOK_EXTENDS 34 -#define DUK_TOK_IMPORT 35 -#define DUK_TOK_SUPER 36 +#define DUK_TOK_CLASS 28 +#define DUK_TOK_CONST 29 +#define DUK_TOK_ENUM 30 +#define DUK_TOK_EXPORT 31 +#define DUK_TOK_EXTENDS 32 +#define DUK_TOK_IMPORT 33 +#define DUK_TOK_SUPER 34 /* "null", "true", and "false" are always reserved words. * Note that "get" and "set" are not! */ -#define DUK_TOK_NULL 37 -#define DUK_TOK_TRUE 38 -#define DUK_TOK_FALSE 39 +#define DUK_TOK_NULL 35 +#define DUK_TOK_TRUE 36 +#define DUK_TOK_FALSE 37 /* reserved words: additional future reserved words in strict mode */ -#define DUK_TOK_START_STRICT_RESERVED 40 /* inclusive */ -#define DUK_TOK_IMPLEMENTS 40 -#define DUK_TOK_INTERFACE 41 -#define DUK_TOK_LET 42 -#define DUK_TOK_PACKAGE 43 -#define DUK_TOK_PRIVATE 44 -#define DUK_TOK_PROTECTED 45 -#define DUK_TOK_PUBLIC 46 -#define DUK_TOK_STATIC 47 -#define DUK_TOK_YIELD 48 - -#define DUK_TOK_END_RESERVED 49 /* exclusive */ +#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */ +#define DUK_TOK_IMPLEMENTS 38 +#define DUK_TOK_INTERFACE 39 +#define DUK_TOK_LET 40 +#define DUK_TOK_PACKAGE 41 +#define DUK_TOK_PRIVATE 42 +#define DUK_TOK_PROTECTED 43 +#define DUK_TOK_PUBLIC 44 +#define DUK_TOK_STATIC 45 +#define DUK_TOK_YIELD 46 + +#define DUK_TOK_END_RESERVED 47 /* exclusive */ /* "get" and "set" are tokens but NOT ReservedWords. They are currently * parsed and identifiers and these defines are actually now unused. */ -#define DUK_TOK_GET 49 -#define DUK_TOK_SET 50 +#define DUK_TOK_GET 47 +#define DUK_TOK_SET 48 /* punctuators (unlike the spec, also includes "/" and "/=") */ -#define DUK_TOK_LCURLY 51 -#define DUK_TOK_RCURLY 52 -#define DUK_TOK_LBRACKET 53 -#define DUK_TOK_RBRACKET 54 -#define DUK_TOK_LPAREN 55 -#define DUK_TOK_RPAREN 56 -#define DUK_TOK_PERIOD 57 -#define DUK_TOK_SEMICOLON 58 -#define DUK_TOK_COMMA 59 -#define DUK_TOK_LT 60 -#define DUK_TOK_GT 61 -#define DUK_TOK_LE 62 -#define DUK_TOK_GE 63 -#define DUK_TOK_EQ 64 -#define DUK_TOK_NEQ 65 -#define DUK_TOK_SEQ 66 -#define DUK_TOK_SNEQ 67 -#define DUK_TOK_ADD 68 -#define DUK_TOK_SUB 69 -#define DUK_TOK_MUL 70 -#define DUK_TOK_DIV 71 -#define DUK_TOK_MOD 72 -#define DUK_TOK_INCREMENT 73 -#define DUK_TOK_DECREMENT 74 -#define DUK_TOK_ALSHIFT 75 /* named "arithmetic" because result is signed */ -#define DUK_TOK_ARSHIFT 76 -#define DUK_TOK_RSHIFT 77 -#define DUK_TOK_BAND 78 -#define DUK_TOK_BOR 79 -#define DUK_TOK_BXOR 80 -#define DUK_TOK_LNOT 81 -#define DUK_TOK_BNOT 82 -#define DUK_TOK_LAND 83 -#define DUK_TOK_LOR 84 -#define DUK_TOK_QUESTION 85 -#define DUK_TOK_COLON 86 -#define DUK_TOK_EQUALSIGN 87 -#define DUK_TOK_ADD_EQ 88 -#define DUK_TOK_SUB_EQ 89 -#define DUK_TOK_MUL_EQ 90 -#define DUK_TOK_DIV_EQ 91 -#define DUK_TOK_MOD_EQ 92 -#define DUK_TOK_ALSHIFT_EQ 93 -#define DUK_TOK_ARSHIFT_EQ 94 -#define DUK_TOK_RSHIFT_EQ 95 -#define DUK_TOK_BAND_EQ 96 -#define DUK_TOK_BOR_EQ 97 -#define DUK_TOK_BXOR_EQ 98 +#define DUK_TOK_LCURLY 49 +#define DUK_TOK_RCURLY 50 +#define DUK_TOK_LBRACKET 51 +#define DUK_TOK_RBRACKET 52 +#define DUK_TOK_LPAREN 53 +#define DUK_TOK_RPAREN 54 +#define DUK_TOK_PERIOD 55 +#define DUK_TOK_SEMICOLON 56 +#define DUK_TOK_COMMA 57 +#define DUK_TOK_LT 58 +#define DUK_TOK_GT 59 +#define DUK_TOK_LE 60 +#define DUK_TOK_GE 61 +#define DUK_TOK_EQ 62 +#define DUK_TOK_NEQ 63 +#define DUK_TOK_SEQ 64 +#define DUK_TOK_SNEQ 65 +#define DUK_TOK_ADD 66 +#define DUK_TOK_SUB 67 +#define DUK_TOK_MUL 68 +#define DUK_TOK_DIV 69 +#define DUK_TOK_MOD 70 +#define DUK_TOK_INCREMENT 71 +#define DUK_TOK_DECREMENT 72 +#define DUK_TOK_ALSHIFT 73 /* named "arithmetic" because result is signed */ +#define DUK_TOK_ARSHIFT 74 +#define DUK_TOK_RSHIFT 75 +#define DUK_TOK_BAND 76 +#define DUK_TOK_BOR 77 +#define DUK_TOK_BXOR 78 +#define DUK_TOK_LNOT 79 +#define DUK_TOK_BNOT 80 +#define DUK_TOK_LAND 81 +#define DUK_TOK_LOR 82 +#define DUK_TOK_QUESTION 83 +#define DUK_TOK_COLON 84 +#define DUK_TOK_EQUALSIGN 85 +#define DUK_TOK_ADD_EQ 86 +#define DUK_TOK_SUB_EQ 87 +#define DUK_TOK_MUL_EQ 88 +#define DUK_TOK_DIV_EQ 89 +#define DUK_TOK_MOD_EQ 90 +#define DUK_TOK_ALSHIFT_EQ 91 +#define DUK_TOK_ARSHIFT_EQ 92 +#define DUK_TOK_RSHIFT_EQ 93 +#define DUK_TOK_BAND_EQ 94 +#define DUK_TOK_BOR_EQ 95 +#define DUK_TOK_BXOR_EQ 96 /* literals (E5 Section 7.8), except null, true, false, which are treated * like reserved words (above). */ -#define DUK_TOK_NUMBER 99 -#define DUK_TOK_STRING 100 -#define DUK_TOK_REGEXP 101 +#define DUK_TOK_NUMBER 97 +#define DUK_TOK_STRING 98 +#define DUK_TOK_REGEXP 99 -#define DUK_TOK_MAXVAL 101 /* inclusive */ +#define DUK_TOK_MAXVAL 99 /* inclusive */ /* Convert heap string index to a token (reserved words) */ #define DUK_STRIDX_TO_TOK(x) ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED) @@ -4427,17 +5720,19 @@ typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepo #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21 #define DUK_RETOK_ATOM_END_GROUP 22 -/* constants for duk_lexer_ctx.buf */ -#define DUK_LEXER_TEMP_BUF_INITIAL 64 +/* Constants for duk_lexer_ctx.buf. */ #define DUK_LEXER_TEMP_BUF_LIMIT 256 -/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack. */ +/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack. + * Some fields (like num, str1, str2) are only valid for specific token types and may have + * stale values otherwise. + */ struct duk_token { duk_small_int_t t; /* token type (with reserved word identification) */ duk_small_int_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */ duk_double_t num; /* numeric value of token */ duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */ - duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot1_idx) */ + duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */ duk_size_t start_offset; /* start byte offset of token in lexer input */ duk_int_t start_line; /* start line of token (first char) */ duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */ @@ -4462,22 +5757,34 @@ struct duk_lexer_point { duk_int_t line; }; +/* Lexer codepoint with additional info like offset/line number */ +struct duk_lexer_codepoint { + duk_codepoint_t codepoint; + duk_size_t offset; + duk_int_t line; +}; + /* Lexer context. Same context is used for Ecmascript and Regexp parsing. */ struct duk_lexer_ctx { +#if defined(DUK_USE_LEXER_SLIDING_WINDOW) + duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */ + duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE]; +#else + duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */ +#endif + duk_hthread *thr; /* thread; minimizes argument passing */ const duk_uint8_t *input; /* input string (may be a user pointer) */ duk_size_t input_length; /* input byte length */ duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */ - - duk_codepoint_t window[DUK_LEXER_WINDOW_SIZE]; /* window of unicode code points */ - duk_size_t offsets[DUK_LEXER_WINDOW_SIZE]; /* input byte offset for each char */ - duk_int_t lines[DUK_LEXER_WINDOW_SIZE]; /* input lines for each char */ duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */ + duk_idx_t slot1_idx; /* valstack slot for 1st token value */ duk_idx_t slot2_idx; /* valstack slot for 2nd token value */ duk_idx_t buf_idx; /* valstack slot for temp buffer */ - duk_hbuffer_dynamic *buf; /* temp accumulation buffer (on valstack) */ + duk_hbuffer_dynamic *buf; /* temp accumulation buffer */ + duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */ duk_int_t token_count; /* number of tokens parsed */ duk_int_t token_limit; /* maximum token count before error (sanity backstop) */ @@ -4621,8 +5928,10 @@ struct duk_compiler_func { * platforms (e.g. if int is 32 bits and pointers are 64 bits). */ + duk_bufwriter_ctx bw_code; /* bufwriter for code */ + duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */ - duk_hbuffer_dynamic *h_code; /* C array of duk_compiler_instr */ + /* h_code: held in bw_code */ duk_hobject *h_consts; /* array */ duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2] * offset/line points to closing brace to allow skipping on pass 2 @@ -4637,7 +5946,7 @@ struct duk_compiler_func { duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */ /* value stack indices for tracking objects */ - duk_idx_t code_idx; + /* code_idx: not needed */ duk_idx_t consts_idx; duk_idx_t funcs_idx; duk_idx_t decls_idx; @@ -4808,7 +6117,7 @@ struct duk_re_compiler_ctx { duk_uint32_t re_flags; duk_lexer_ctx lex; duk_re_token curr_token; - duk_hbuffer_dynamic *buf; + duk_bufwriter_ctx bw; duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */ duk_uint32_t highest_backref; duk_uint32_t recursion_depth; @@ -5064,8 +6373,7 @@ typedef union duk_double_union duk_tval; #define DUK_TVAL_IS_HEAP_ALLOCATED(v) (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING) #if defined(DUK_USE_FASTINT) -/* Inlining is only effective in a single file build. */ -DUK_INTERNAL_DECL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv); +DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv); #endif #else /* DUK_USE_PACKED_TVAL */ @@ -5282,11 +6590,10 @@ struct duk_tval_struct { #define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING) #if defined(DUK_USE_FASTINT) -/* Inlining is only effective in a single file build. */ #if 0 -DUK_INTERNAL_DECL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv); +DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv); #endif -DUK_INTERNAL_DECL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv); +DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv); #endif #endif /* DUK_USE_PACKED_TVAL */ @@ -5661,6 +6968,8 @@ struct duk_heaphdr_string { #define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) #define DUK_HNATIVEFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) #define DUK_HNATIVEFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HBUFFEROBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) +#define DUK_HBUFFEROBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) #define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj) #define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj) @@ -5702,6 +7011,8 @@ struct duk_heaphdr_string { #define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) do {} while (0) /* nop */ #define DUK_HNATIVEFUNCTION_INCREF(thr,h) do {} while (0) /* nop */ #define DUK_HNATIVEFUNCTION_DECREF(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFEROBJECT_INCREF(thr,h) do {} while (0) /* nop */ +#define DUK_HBUFFEROBJECT_DECREF(thr,h) do {} while (0) /* nop */ #define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */ #define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */ #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */ @@ -5756,6 +7067,18 @@ DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_context *ct /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */ DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx); +/* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must + * make sure there's an active callstack entry. Note that the returned pointer + * is unstable with regards to side effects. + */ +DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx); + +/* XXX: add fastint support? */ +#define duk_push_u64(ctx,val) \ + duk_push_number((ctx), (duk_double_t) (val)) +#define duk_push_i64(ctx,val) \ + duk_push_number((ctx), (duk_double_t) (val)) + /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */ #define duk_push_u32(ctx,val) \ duk_push_uint((ctx), (duk_uint_t) (val)) @@ -5802,14 +7125,13 @@ DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index) DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */ DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval); DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval); +DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index); DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index); DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index); DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index); DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index); -#if 0 /*unused */ DUK_INTERNAL_DECL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index); -#endif DUK_INTERNAL_DECL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index); #define duk_require_hobject_with_class(ctx,index,classnum) \ @@ -5844,6 +7166,7 @@ DUK_INTERNAL_DECL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz); DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv); DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv); +DUK_INTERNAL_DECL duk_hbufferobject *duk_push_bufferobject(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx); DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [val] */ DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [val] -> [] */ @@ -6109,21 +7432,20 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_FLAG_BOUND DUK_HEAPHDR_USER_FLAG(2) /* object established using Function.prototype.bind() */ #define DUK_HOBJECT_FLAG_COMPILEDFUNCTION DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompiledfunction) */ #define DUK_HOBJECT_FLAG_NATIVEFUNCTION DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnativefunction) */ -#define DUK_HOBJECT_FLAG_THREAD DUK_HEAPHDR_USER_FLAG(6) /* object is a thread (duk_hthread) */ -#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(7) /* object has an array part (a_size may still be 0) */ -#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(8) /* function: function object is strict */ -#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(9) /* function: function must not be tailcalled */ -#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(10) /* function: create new environment when called (see duk_hcompiledfunction) */ -#define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(11) /* function: create binding for func name (function templates only, used for named function expressions) */ -#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(12) /* function: create an arguments object on function call */ -#define DUK_HOBJECT_FLAG_ENVRECCLOSED DUK_HEAPHDR_USER_FLAG(13) /* envrec: (declarative) record is closed */ -#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(14) /* 'Array' object, array length and index exotic behavior */ -#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(15) /* 'String' object, array index exotic behavior */ -#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(16) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */ -#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC DUK_HEAPHDR_USER_FLAG(17) /* Duktape/C (nativefunction) object, exotic 'length' */ -#define DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ DUK_HEAPHDR_USER_FLAG(18) /* 'Buffer' object, array index exotic behavior, virtual 'length' */ +#define DUK_HOBJECT_FLAG_BUFFEROBJECT DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufferobject) (always exotic) */ +#define DUK_HOBJECT_FLAG_THREAD DUK_HEAPHDR_USER_FLAG(7) /* object is a thread (duk_hthread) */ +#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */ +#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */ +#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tailcalled */ +#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompiledfunction) */ +#define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(12) /* function: create binding for func name (function templates only, used for named function expressions) */ +#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */ +#define DUK_HOBJECT_FLAG_ENVRECCLOSED DUK_HEAPHDR_USER_FLAG(14) /* envrec: (declarative) record is closed */ +#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */ +#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */ +#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */ +#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC DUK_HEAPHDR_USER_FLAG(18) /* Duktape/C (nativefunction) object, exotic 'length' */ #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(19) /* 'Proxy' object */ -/* bit 20 unused */ #define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(21) #define DUK_HOBJECT_FLAG_CLASS_BITS 5 @@ -6133,6 +7455,9 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v) \ DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v)) +#define DUK_HOBJECT_GET_CLASS_MASK(h) \ + (1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)) + /* Macro for creating flag initializer from a class number. * Unsigned type cast is needed to avoid warnings about coercing * a signed integer to an unsigned one; the largest class values @@ -6157,9 +7482,68 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_CLASS_GLOBAL 13 #define DUK_HOBJECT_CLASS_OBJENV 14 /* custom */ #define DUK_HOBJECT_CLASS_DECENV 15 /* custom */ -#define DUK_HOBJECT_CLASS_BUFFER 16 /* custom */ +#define DUK_HOBJECT_CLASS_BUFFER 16 /* custom; implies DUK_HOBJECT_IS_BUFFEROBJECT */ #define DUK_HOBJECT_CLASS_POINTER 17 /* custom */ -#define DUK_HOBJECT_CLASS_THREAD 18 /* custom */ +#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */ +#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFFEROBJECT */ +#define DUK_HOBJECT_CLASS_DATAVIEW 20 +#define DUK_HOBJECT_CLASS_INT8ARRAY 21 +#define DUK_HOBJECT_CLASS_UINT8ARRAY 22 +#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23 +#define DUK_HOBJECT_CLASS_INT16ARRAY 24 +#define DUK_HOBJECT_CLASS_UINT16ARRAY 25 +#define DUK_HOBJECT_CLASS_INT32ARRAY 26 +#define DUK_HOBJECT_CLASS_UINT32ARRAY 27 +#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28 +#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29 +#define DUK_HOBJECT_CLASS_MAX 29 + +/* class masks */ +#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL) +#define DUK_HOBJECT_CMASK_UNUSED (1UL << DUK_HOBJECT_CLASS_UNUSED) +#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS) +#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY) +#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN) +#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE) +#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR) +#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION) +#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON) +#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH) +#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER) +#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT) +#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP) +#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING) +#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL) +#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV) +#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV) +#define DUK_HOBJECT_CMASK_BUFFER (1UL << DUK_HOBJECT_CLASS_BUFFER) +#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER) +#define DUK_HOBJECT_CMASK_THREAD (1UL << DUK_HOBJECT_CLASS_THREAD) +#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER) +#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW) +#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY) +#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY) +#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY) +#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY) +#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY) +#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY) +#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY) +#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY) +#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY) + +#define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS \ + (DUK_HOBJECT_CMASK_BUFFER | \ + DUK_HOBJECT_CMASK_ARRAYBUFFER | \ + DUK_HOBJECT_CMASK_DATAVIEW | \ + DUK_HOBJECT_CMASK_INT8ARRAY | \ + DUK_HOBJECT_CMASK_UINT8ARRAY | \ + DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \ + DUK_HOBJECT_CMASK_INT16ARRAY | \ + DUK_HOBJECT_CMASK_UINT16ARRAY | \ + DUK_HOBJECT_CMASK_INT32ARRAY | \ + DUK_HOBJECT_CMASK_UINT32ARRAY | \ + DUK_HOBJECT_CMASK_FLOAT32ARRAY | \ + DUK_HOBJECT_CMASK_FLOAT64ARRAY) #define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV) #define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV) @@ -6167,6 +7551,7 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_IS_ARRAY(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY) #define DUK_HOBJECT_IS_COMPILEDFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION) #define DUK_HOBJECT_IS_NATIVEFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION) +#define DUK_HOBJECT_IS_BUFFEROBJECT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT) #define DUK_HOBJECT_IS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD) #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \ @@ -6188,7 +7573,7 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \ DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \ DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \ - DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ | \ + DUK_HOBJECT_FLAG_BUFFEROBJECT | \ DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS) @@ -6198,6 +7583,7 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_HAS_BOUND(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND) #define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION) #define DUK_HOBJECT_HAS_NATIVEFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION) +#define DUK_HOBJECT_HAS_BUFFEROBJECT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT) #define DUK_HOBJECT_HAS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD) #define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART) #define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT) @@ -6210,7 +7596,6 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ) #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS) #define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC) -#define DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ) #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) #define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE) @@ -6218,6 +7603,7 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_SET_BOUND(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND) #define DUK_HOBJECT_SET_COMPILEDFUNCTION(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION) #define DUK_HOBJECT_SET_NATIVEFUNCTION(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION) +#define DUK_HOBJECT_SET_BUFFEROBJECT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT) #define DUK_HOBJECT_SET_THREAD(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD) #define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART) #define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT) @@ -6230,7 +7616,6 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ) #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS) #define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC) -#define DUK_HOBJECT_SET_EXOTIC_BUFFEROBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ) #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE) @@ -6238,6 +7623,7 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_CLEAR_BOUND(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND) #define DUK_HOBJECT_CLEAR_COMPILEDFUNCTION(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION) #define DUK_HOBJECT_CLEAR_NATIVEFUNCTION(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION) +#define DUK_HOBJECT_CLEAR_BUFFEROBJECT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT) #define DUK_HOBJECT_CLEAR_THREAD(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD) #define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART) #define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT) @@ -6250,7 +7636,6 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ) #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS) #define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC) -#define DUK_HOBJECT_CLEAR_EXOTIC_BUFFEROBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ) #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ) /* flags used for property attributes in duk_propdesc and packed flags */ @@ -6283,6 +7668,31 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr DUK_PROPDESC_FLAG_ENUMERABLE | \ DUK_PROPDESC_FLAG_CONFIGURABLE) +/* + * Macro for object validity check + * + * Assert for currently guaranteed relations between flags, for instance. + */ + +#define DUK_ASSERT_HOBJECT_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \ + DUK_ASSERT(!DUK_HOBJECT_IS_BUFFEROBJECT((h)) || \ + (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_BUFFER || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \ + DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \ + } while (0) + /* * Macros to access the 'props' allocation. */ @@ -6297,32 +7707,32 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_GET_PROPS(heap,h) \ ((h)->props) #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \ - (h)->props = (x); \ + (h)->props = (duk_uint8_t *) (x); \ } while (0) #endif #if defined(DUK_USE_HOBJECT_LAYOUT_1) /* LAYOUT 1 */ #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \ - ((duk_hstring **) ( \ + ((duk_hstring **) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) \ )) #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \ - ((duk_propvalue *) ( \ + ((duk_propvalue *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \ )) #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \ - ((duk_uint8_t *) ( \ + ((duk_uint8_t *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \ )) #define DUK_HOBJECT_A_GET_BASE(heap,h) \ - ((duk_tval *) ( \ + ((duk_tval *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \ )) #define DUK_HOBJECT_H_GET_BASE(heap,h) \ - ((duk_uint32_t *) ( \ + ((duk_uint32_t *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ @@ -6334,42 +7744,44 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr (n_hash) * sizeof(duk_uint32_t) \ ) #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \ - (set_e_k) = (duk_hstring **) (p_base); \ - (set_e_pv) = (duk_propvalue *) ((set_e_k) + (n_ent)); \ - (set_e_f) = (duk_uint8_t *) ((set_e_pv) + (n_ent)); \ - (set_a) = (duk_tval *) ((set_e_f) + (n_ent)); \ - (set_h) = (duk_uint32_t *) ((set_a) + (n_arr)); \ + (set_e_k) = (duk_hstring **) (void *) (p_base); \ + (set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \ + (set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \ + (set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \ + (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \ } while (0) #elif defined(DUK_USE_HOBJECT_LAYOUT_2) /* LAYOUT 2 */ -#if defined(DUK_USE_ALIGN_4) +#if (DUK_USE_ALIGN_BY == 4) #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03) -#elif defined(DUK_USE_ALIGN_8) +#elif (DUK_USE_ALIGN_BY == 8) #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07) -#else +#elif (DUK_USE_ALIGN_BY == 1) #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0 +#else +#error invalid DUK_USE_ALIGN_BY #endif #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \ - ((duk_hstring **) ( \ + ((duk_hstring **) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \ )) #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \ - ((duk_propvalue *) ( \ + ((duk_propvalue *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) \ )) #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \ - ((duk_uint8_t *) ( \ + ((duk_uint8_t *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \ )) #define DUK_HOBJECT_A_GET_BASE(heap,h) \ - ((duk_tval *) ( \ + ((duk_tval *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \ )) #define DUK_HOBJECT_H_GET_BASE(heap,h) \ - ((duk_uint32_t *) ( \ + ((duk_uint32_t *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \ DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \ @@ -6383,40 +7795,40 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr (n_hash) * sizeof(duk_uint32_t) \ ) #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \ - (set_e_pv) = (duk_propvalue *) (p_base); \ - (set_e_k) = (duk_hstring **) ((set_e_pv) + (n_ent)); \ - (set_e_f) = (duk_uint8_t *) ((set_e_k) + (n_ent)); \ - (set_a) = (duk_tval *) (((duk_uint8_t *) (set_e_f)) + \ + (set_e_pv) = (duk_propvalue *) (void *) (p_base); \ + (set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \ + (set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \ + (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \ sizeof(duk_uint8_t) * (n_ent) + \ DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \ - (set_h) = (duk_uint32_t *) ((set_a) + (n_arr)); \ + (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \ } while (0) #elif defined(DUK_USE_HOBJECT_LAYOUT_3) /* LAYOUT 3 */ #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \ - ((duk_hstring **) ( \ + ((duk_hstring **) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ )) #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \ - ((duk_propvalue *) ( \ + ((duk_propvalue *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) \ )) #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \ - ((duk_uint8_t *) ( \ + ((duk_uint8_t *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \ DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \ )) #define DUK_HOBJECT_A_GET_BASE(heap,h) \ - ((duk_tval *) ( \ + ((duk_tval *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \ )) #define DUK_HOBJECT_H_GET_BASE(heap,h) \ - ((duk_uint32_t *) ( \ + ((duk_uint32_t *) (void *) ( \ DUK_HOBJECT_GET_PROPS((heap), (h)) + \ DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \ DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \ @@ -6428,11 +7840,11 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr (n_hash) * sizeof(duk_uint32_t) \ ) #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash) do { \ - (set_e_pv) = (duk_propvalue *) (p_base); \ - (set_a) = (duk_tval *) ((set_e_pv) + (n_ent)); \ - (set_e_k) = (duk_hstring **) ((set_a) + (n_arr)); \ - (set_h) = (duk_uint32_t *) ((set_e_k) + (n_ent)); \ - (set_e_f) = (duk_uint8_t *) ((set_h) + (n_hash)); \ + (set_e_pv) = (duk_propvalue *) (void *) (p_base); \ + (set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \ + (set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \ + (set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \ + (set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \ } while (0) #else #error invalid hobject layout defines @@ -6628,12 +8040,14 @@ DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr #define DUK_HOBJECT_A_ABANDON_LIMIT 2 /* 25%, i.e. less than 25% used -> abandon */ /* internal align target for props allocation, must be 2*n for some n */ -#if defined(DUK_USE_ALIGN_4) +#if (DUK_USE_ALIGN_BY == 4) #define DUK_HOBJECT_ALIGN_TARGET 4 -#elif defined(DUK_USE_ALIGN_8) +#elif (DUK_USE_ALIGN_BY == 8) #define DUK_HOBJECT_ALIGN_TARGET 8 -#else +#elif (DUK_USE_ALIGN_BY == 1) #define DUK_HOBJECT_ALIGN_TARGET 1 +#else +#error invalid DUK_USE_ALIGN_BY #endif /* controls for minimum entry part growth */ @@ -6807,6 +8221,7 @@ DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_u #endif DUK_INTERNAL_DECL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags); DUK_INTERNAL_DECL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags); +DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags); DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags); /* low-level property functions */ @@ -6815,6 +8230,12 @@ DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *h DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs); DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i); +/* XXX: when optimizing for guaranteed property slots, use a guaranteed + * slot for internal value; this call can then access it directly. + */ +#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \ + duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap))) + /* core property functions */ DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key); DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag); @@ -6859,7 +8280,6 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, /* internal properties */ DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv); DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj); -DUK_INTERNAL_DECL duk_hbuffer *duk_hobject_get_internal_value_buffer(duk_heap *heap, duk_hobject *obj); /* hobject management functions */ DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj); @@ -6867,6 +8287,7 @@ DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject * /* ES6 proxy */ #if defined(DUK_USE_ES6_PROXY) DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler); +DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj); #endif /* enumeration */ @@ -6909,23 +8330,23 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *t #if defined(DUK_USE_HEAPPTR16) #define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \ - ((duk_hbuffer_fixed *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16)) + ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16)) #define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \ (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ } while (0) #define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h) \ - ((duk_hobject **) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16))) + ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16))) #define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v) do { \ (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ } while (0) #define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h) \ - ((duk_instr_t *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16))) + ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16))) #define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v) do { \ (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ } while (0) #else #define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \ - ((duk_hbuffer_fixed *) (h)->data) + ((duk_hbuffer_fixed *) (void *) (h)->data) #define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \ (h)->data = (duk_hbuffer *) (v); \ } while (0) @@ -6950,7 +8371,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *t DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap,h) \ - ((duk_tval *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), (h))) + ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), (h))) #define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap,h) \ DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h)) @@ -6959,14 +8380,14 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *t DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h)) #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap,h) \ - ((duk_tval *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))) + ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))) #define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap,h) \ - ((duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))) + ((duk_hobject **) (void *) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))) /* XXX: double evaluation of DUK_HCOMPILEDFUNCTION_GET_DATA() */ #define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap,h) \ - ((duk_instr_t *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \ + ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \ DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA((heap), h)))) #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap,h) \ @@ -7163,6 +8584,137 @@ struct duk_hnativefunction { }; #endif /* DUK_HNATIVEFUNCTION_H_INCLUDED */ +#line 1 "duk_hbufferobject.h" +/* + * Heap Buffer object representation. Used for all Buffer variants. + */ + +#ifndef DUK_HBUFFEROBJECT_H_INCLUDED +#define DUK_HBUFFEROBJECT_H_INCLUDED + +/* All element accessors are host endian now (driven by TypedArray spec). */ +#define DUK_HBUFFEROBJECT_ELEM_UINT8 0 +#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED 1 +#define DUK_HBUFFEROBJECT_ELEM_INT8 2 +#define DUK_HBUFFEROBJECT_ELEM_UINT16 3 +#define DUK_HBUFFEROBJECT_ELEM_INT16 4 +#define DUK_HBUFFEROBJECT_ELEM_UINT32 5 +#define DUK_HBUFFEROBJECT_ELEM_INT32 6 +#define DUK_HBUFFEROBJECT_ELEM_FLOAT32 7 +#define DUK_HBUFFEROBJECT_ELEM_FLOAT64 8 +#define DUK_HBUFFEROBJECT_ELEM_MAX 8 + +#define DUK_ASSERT_HBUFFEROBJECT_VALID(h) do { \ + DUK_ASSERT((h) != NULL); \ + DUK_ASSERT((h)->shift <= 3); \ + DUK_ASSERT((h)->elem_type <= DUK_HBUFFEROBJECT_ELEM_MAX); \ + DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8) || \ + ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) || \ + ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT8) || \ + ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT16) || \ + ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT16) || \ + ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT32) || \ + ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT32) || \ + ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT32) || \ + ((h)->shift == 3 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT64)); \ + DUK_ASSERT((h)->is_view == 0 || (h)->is_view == 1); \ + DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) (h))); \ + if ((h)->buf == NULL) { \ + DUK_ASSERT((h)->offset == 0); \ + DUK_ASSERT((h)->length == 0); \ + } else { \ + /* No assertions for offset or length; in particular, \ + * it's OK for length to be longer than underlying \ + * buffer. \ + */ \ + } \ + } while (0) + +/* Get the current data pointer (caller must ensure buf != NULL) as a + * duk_uint8_t ptr. + */ +#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap,h) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset)) + +/* True if slice is full, i.e. offset is zero and length covers the entire + * buffer. This status may change independently of the duk_hbufferobject if + * the underlying buffer is dynamic and changes without the hbufferobject + * being changed. + */ +#define DUK_HBUFFEROBJECT_FULL_SLICE(h) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf))) + +/* Validate that the whole slice [0,length[ is contained in the underlying + * buffer. Caller must ensure 'buf' != NULL. + */ +#define DUK_HBUFFEROBJECT_VALID_SLICE(h) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf))) + +/* Validate byte read/write for virtual 'offset', i.e. check that the + * offset, taking into account h->offset, is within the underlying + * buffer size. This is a safety check which is needed to ensure + * that even a misconfigured duk_hbufferobject never causes memory + * unsafe behavior (e.g. if an underlying dynamic buffer changes + * after being setup). Caller must ensure 'buf' != NULL. + */ +#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_INCL(h,off) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf))) + +#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h,off) \ + (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \ + ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf))) + +/* Clamp an input byte length (already assumed to be within the nominal + * duk_hbufferobject 'length') to the current dynamic buffer limits to + * yield a byte length limit that's safe for memory accesses. This value + * can be invalidated by any side effect because it may trigger a user + * callback that resizes the underlying buffer. + */ +#define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h,len) \ + (DUK_ASSERT_EXPR((h) != NULL), \ + duk_hbufferobject_clamp_bytelength((h), (len))) + +struct duk_hbufferobject { + /* Shared object part. */ + duk_hobject obj; + + /* Underlying buffer (refcounted), may be NULL. */ + duk_hbuffer *buf; + + /* Slice and accessor information. + * + * Because the underlying buffer may be dynamic, these may be + * invalidated by the buffer being modified so that both offset + * and length should be validated before every access. Behavior + * when the underlying buffer has changed doesn't need to be clean: + * virtual 'length' doesn't need to be affected, reads can return + * zero/NaN, and writes can be ignored. + * + * Note that a data pointer cannot be precomputed because 'buf' may + * be dynamic and its pointer unstable. + */ + + duk_uint_t offset; /* byte offset to buf */ + duk_uint_t length; /* byte index limit for element access, exclusive */ + duk_uint8_t shift; /* element size shift: + * 0 = u8/i8 + * 1 = u16/i16 + * 2 = u32/i32/float + * 3 = double + */ + duk_uint8_t elem_type; /* element type */ + duk_uint8_t is_view; +}; + +DUK_INTERNAL_DECL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len); +DUK_INTERNAL_DECL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size); +DUK_INTERNAL_DECL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size); + +#endif /* DUK_HBUFFEROBJECT_H_INCLUDED */ #line 1 "duk_hthread.h" /* * Heap thread object representation. @@ -7304,6 +8856,35 @@ struct duk_hnativefunction { #define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */ #define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */ +/* Executor interrupt default interval when nothing else requires a + * smaller value. The default interval must be small enough to allow + * for reasonable execution timeout checking but large enough to keep + * impact on execution performance low. + */ +#if defined(DUK_USE_INTERRUPT_COUNTER) +#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L) +#endif + +/* + * Assert context is valid: non-NULL pointer, fields look sane. + * + * This is used by public API call entrypoints to catch invalid 'ctx' pointers + * as early as possible; invalid 'ctx' pointers cause very odd and difficult to + * diagnose behavior so it's worth checking even when the check is not 100%. + */ + +#define DUK_ASSERT_CTX_VALID(ctx) do { \ + DUK_ASSERT((ctx) != NULL); \ + DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (ctx)) == DUK_HTYPE_OBJECT); \ + DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (ctx))); \ + DUK_ASSERT(((duk_hthread *) (ctx))->unused1 == 0); \ + DUK_ASSERT(((duk_hthread *) (ctx))->unused2 == 0); \ + DUK_ASSERT(((duk_hthread *) (ctx))->valstack != NULL); \ + DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack); \ + DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack); \ + DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack_bottom); \ + } while (0) + /* * Struct defines */ @@ -7420,15 +9001,16 @@ struct duk_hthread { /* current compiler state (if any), used for augmenting SyntaxErrors */ duk_compiler_ctx *compile_ctx; -#ifdef DUK_USE_INTERRUPT_COUNTER +#if defined(DUK_USE_INTERRUPT_COUNTER) /* Interrupt counter for triggering a slow path check for execution - * timeout, debugger interaction such as breakpoints, etc. This is - * actually a value copied from the heap structure into the current - * thread to be more convenient for the bytecode executor inner loop. - * The final value is copied back to the heap structure on a thread - * switch by DUK_HEAP_SWITCH_THREAD(). + * timeout, debugger interaction such as breakpoints, etc. The value + * is valid for the current running thread, and both the init and + * counter values are copied whenever a thread switch occurs. It's + * important for the counter to be conveniently accessible for the + * bytecode executor inner loop for performance reasons. */ - duk_int_t interrupt_counter; + duk_int_t interrupt_counter; /* countdown state */ + duk_int_t interrupt_init; /* start value for current countdown */ #endif /* Builtin-objects; may or may not be shared with other threads, @@ -7505,14 +9087,17 @@ DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) /* Impose a maximum buffer length for now. Restricted artificially to * ensure resize computations or adding a heap header length won't - * overflow size_t. The limit should be synchronized with - * DUK_HSTRING_MAX_BYTELEN. + * overflow size_t and that a signed duk_int_t can hold a buffer + * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN. */ #if defined(DUK_USE_BUFLEN16) #define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL) #else -#define DUK_HBUFFER_MAX_BYTELEN (0x7fffffffUL) +/* Intentionally not 0x7fffffffUL; at least JSON code expects that + * 2*len + 2 fits in 32 bits. + */ +#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL) #endif /* @@ -7555,37 +9140,14 @@ DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv)) #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv)) -#if defined(DUK_USE_BUFLEN16) && defined(DUK_USE_HEAPPTR16) -/* alloc_size16 stored in duk_heaphdr h_extra16, available with pointer compression. */ -#define DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(x) ((duk_size_t) ((x)->hdr.h_extra16)) -#define DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(x,v) do { \ - (x)->hdr.h_extra16 = (duk_uint16_t) (v); \ - } while (0) -#elif defined(DUK_USE_BUFLEN16) -/* alloc_size16 stored in an explicit 16-bit fields. */ -#define DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(x) ((duk_size_t) ((x)->alloc_size16)) -#define DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(x,v) do { \ - (x)->alloc_size16 = (duk_uint16_t) (v); \ - } while (0) -#else -/* normal case */ -#define DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(x) ((x)->alloc_size) -#define DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(x,v) do { \ - (x)->alloc_size = (v); \ - } while (0) -#endif - -#define DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(x) \ - (duk_size_t) (DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE((x)) - DUK_HBUFFER_DYNAMIC_GET_SIZE((x))) - #if defined(DUK_USE_HEAPPTR16) #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \ - ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (x)->curr_alloc16)) + ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16)) #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \ - (x)->curr_alloc16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ + ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \ } while (0) #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \ - (x)->curr_alloc16 = 0; /* assume 0 <=> NULL */ \ + ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \ } while (0) #else #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc) @@ -7606,10 +9168,6 @@ DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \ ) -/* Growth parameters for dynamic buffers. */ -#define DUK_HBUFFER_SPARE_ADD 16 -#define DUK_HBUFFER_SPARE_DIVISOR 16 /* 2^4 -> 1/16 = 6.25% spare */ - /* * Structs */ @@ -7649,7 +9207,7 @@ struct duk_hbuffer { */ }; -#if defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_MSVC_PRAGMA) +#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) #pragma pack(push, 8) #endif struct duk_hbuffer_fixed { @@ -7668,12 +9226,14 @@ struct duk_hbuffer_fixed { duk_size_t size; #endif } s; -#if defined(DUK_USE_ALIGN_4) +#if (DUK_USE_ALIGN_BY == 4) duk_uint32_t dummy_for_align4; -#elif defined(DUK_USE_ALIGN_8) +#elif (DUK_USE_ALIGN_BY == 8) duk_double_t dummy_for_align8; -#else +#elif (DUK_USE_ALIGN_BY == 1) /* no extra padding */ +#else +#error invalid DUK_USE_ALIGN_BY #endif } u; @@ -7690,13 +9250,13 @@ struct duk_hbuffer_fixed { * dynamic buffer). */ } -#if defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_GCC_ATTR) +#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR) __attribute__ ((aligned (8))) -#elif defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_CLANG_ATTR) +#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR) __attribute__ ((aligned (8))) #endif ; -#if defined(DUK_USE_ALIGN_8) && defined(DUK_USE_PACK_MSVC_PRAGMA) +#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA) #pragma pack(pop) #endif @@ -7709,16 +9269,8 @@ struct duk_hbuffer_dynamic { duk_size_t size; #endif -#if defined(DUK_USE_BUFLEN16) && defined(DUK_USE_HEAPPTR16) - /* Stored in duk_heaphdr h_extra16. */ -#elif defined(DUK_USE_BUFLEN16) - duk_uint16_t alloc_size16; -#else - duk_size_t alloc_size; -#endif - #if defined(DUK_USE_HEAPPTR16) - duk_uint16_t curr_alloc16; + /* Stored in duk_heaphdr h_extra16. */ #else void *curr_alloc; /* may be NULL if alloc_size == 0 */ #endif @@ -7741,37 +9293,8 @@ DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */ /* dynamic buffer ops */ -DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size, duk_size_t new_alloc_size); +DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size); DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf); -#if 0 /*unused*/ -DUK_INTERNAL_DECL void duk_hbuffer_compact(duk_hthread *thr, duk_hbuffer_dynamic *buf); -#endif -DUK_INTERNAL_DECL void duk_hbuffer_append_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, const duk_uint8_t *data, duk_size_t length); -DUK_INTERNAL_DECL void duk_hbuffer_append_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint8_t byte); -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_append_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, const char *str); -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_append_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_hstring *str); -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_append_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint); -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_append_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint); -#if 0 -DUK_INTERNAL_DECL void duk_hbuffer_append_native_u32(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint32_t val); -#endif -DUK_INTERNAL_DECL void duk_hbuffer_insert_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, const duk_uint8_t *data, duk_size_t length); -#if 0 /*unused*/ -DUK_INTERNAL_DECL void duk_hbuffer_insert_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_uint8_t byte); -#endif -#if 0 /*unused*/ -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_insert_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, const char *str); -#endif -#if 0 /*unused*/ -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_insert_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_hstring *str); -#endif -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_insert_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint); -#if 0 /*unused*/ -DUK_INTERNAL_DECL duk_size_t duk_hbuffer_insert_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint); -#endif -DUK_INTERNAL_DECL void duk_hbuffer_remove_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_size_t length); -DUK_INTERNAL_DECL void duk_hbuffer_insert_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t dst_offset, duk_size_t src_offset, duk_size_t length); -DUK_INTERNAL_DECL void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t src_offset, duk_size_t length); #endif /* DUK_HBUFFER_H_INCLUDED */ #line 1 "duk_heap.h" @@ -7925,14 +9448,6 @@ DUK_INTERNAL_DECL void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dy /* helper to insert a (non-string) heap object into heap allocated list */ #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap),(hdr)) -/* Executor interrupt default interval when nothing else requires a - * smaller value. The default interval must be small enough to allow - * for reasonable execution timeout checking. - */ -#if defined(DUK_USE_INTERRUPT_COUNTER) -#define DUK_HEAP_INTCTR_DEFAULT (256L * 1024L) -#endif - /* * Stringtable */ @@ -8208,9 +9723,6 @@ struct duk_heap { /* heap level "stash" object (e.g., various reachability roots) */ duk_hobject *heap_object; - /* heap level temporary log formatting buffer */ - duk_hbuffer_dynamic *log_buffer; - /* duk_handle_call / duk_handle_safe_call recursion depth limiting */ duk_int_t call_recursion_depth; duk_int_t call_recursion_limit; @@ -8221,10 +9733,13 @@ struct duk_heap { /* rnd_state for duk_util_tinyrandom.c */ duk_uint32_t rnd_state; - /* interrupt counter */ -#if defined(DUK_USE_INTERRUPT_COUNTER) - duk_int_t interrupt_init; /* start value for current countdown */ - duk_int_t interrupt_counter; /* countdown state (mirrored in current thread state) */ + /* For manual debugging: instruction count based on executor and + * interrupt counter book-keeping. Inspect debug logs to see how + * they match up. + */ +#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG) + duk_int_t inst_count_exec; + duk_int_t inst_count_interrupt; #endif /* debugger */ @@ -8764,7 +10279,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb); * Panic error * * Panic errors are not relative to either a heap or a thread, and cause - * DUK_PANIC() macro to be invoked. Unlesa a user provides DUK_OPT_PANIC_HANDLER, + * DUK_PANIC() macro to be invoked. Unless a user provides DUK_USE_PANIC_HANDLER, * DUK_PANIC() calls a helper which prints out the error and causes a process * exit. * @@ -8801,16 +10316,32 @@ DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb); } \ } while (0) +/* Assertion compatible inside a comma expression, evaluates to void. + * Currently not compatible with DUK_USE_PANIC_HANDLER() which may have + * a statement block. + */ +#if defined(DUK_USE_PANIC_HANDLER) +/* XXX: resolve macro definition issue or call through a helper function? */ +#define DUK_ASSERT_EXPR(x) ((void) 0) +#else +#define DUK_ASSERT_EXPR(x) \ + ((void) ((x) ? 0 : (DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \ + "assertion failed: " #x \ + " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0))) +#endif + #else /* DUK_USE_ASSERTIONS */ -#define DUK_ASSERT(x) do { /* assertion omitted */ } while(0) +#define DUK_ASSERT(x) do { /* assertion omitted */ } while (0) + +#define DUK_ASSERT_EXPR(x) ((void) 0) #endif /* DUK_USE_ASSERTIONS */ /* this variant is used when an assert would generate a compile warning by * being always true (e.g. >= 0 comparison for an unsigned value */ -#define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while(0) +#define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while (0) /* * Assertion helpers @@ -8914,81 +10445,6 @@ DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_in DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code); #endif /* DUK_ERROR_H_INCLUDED */ -#line 1 "duk_util.h" -/* - * Utilities - */ - -#ifndef DUK_UTIL_H_INCLUDED -#define DUK_UTIL_H_INCLUDED - -#define DUK_UTIL_MIN_HASH_PRIME 17 /* must match genhashsizes.py */ - -#define DUK_UTIL_GET_HASH_PROBE_STEP(hash) (duk_util_probe_steps[(hash) & 0x1f]) - -/* - * Bitstream decoder - */ - -struct duk_bitdecoder_ctx { - const duk_uint8_t *data; - duk_size_t offset; - duk_size_t length; - duk_uint32_t currval; - duk_small_int_t currbits; -}; - -/* - * Bitstream encoder - */ - -struct duk_bitencoder_ctx { - duk_uint8_t *data; - duk_size_t offset; - duk_size_t length; - duk_uint32_t currval; - duk_small_int_t currbits; - duk_small_int_t truncated; -}; - -/* - * Externs and prototypes - */ - -#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]; -#endif /* !DUK_SINGLE_FILE */ - -/* Note: assumes that duk_util_probe_steps size is 32 */ -#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE) -#if !defined(DUK_SINGLE_FILE) -DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32]; -#endif /* !DUK_SINGLE_FILE */ -#endif - -DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed); - -#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); -#endif - -DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits); -DUK_INTERNAL_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx); -DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value); - -DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits); -DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx); - -DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n); -DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr); - -#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */ -DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len); -#endif - -#endif /* DUK_UTIL_H_INCLUDED */ #line 1 "duk_unicode.h" /* * Unicode helpers @@ -9001,8 +10457,10 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len); * UTF-8 / XUTF-8 / CESU-8 constants */ -#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */ -#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */ +#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */ +#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */ +#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */ +#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */ /* * Useful Unicode codepoints @@ -9228,6 +10686,9 @@ DUK_INTERNAL_DECL duk_uint16_t duk_unicode_re_ranges_not_wordchar[10]; */ DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp); +#if defined(DUK_USE_ASSERTIONS) +DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp); +#endif DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out); DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out); DUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp); @@ -9261,10 +10722,10 @@ DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp) #endif /* Encoding/decoding flags */ -#define DUK_JSON_FLAG_ASCII_ONLY (1 << 0) /* escape any non-ASCII characters */ -#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1 << 1) /* avoid key quotes when key is an ASCII Identifier */ -#define DUK_JSON_FLAG_EXT_CUSTOM (1 << 2) /* extended types: custom encoding */ -#define DUK_JSON_FLAG_EXT_COMPATIBLE (1 << 3) /* extended types: compatible encoding */ +#define DUK_JSON_FLAG_ASCII_ONLY (1 << 0) /* escape any non-ASCII characters */ +#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1 << 1) /* avoid key quotes when key is an ASCII Identifier */ +#define DUK_JSON_FLAG_EXT_CUSTOM (1 << 2) /* extended types: custom encoding */ +#define DUK_JSON_FLAG_EXT_COMPATIBLE (1 << 3) /* extended types: compatible encoding */ /* How much stack to require on entry to object/array encode */ #define DUK_JSON_ENC_REQSTACK 32 @@ -9272,10 +10733,15 @@ 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) +#define DUK_JSON_ENC_LOOPARRAY 64 +#endif + /* Encoding state. Heap object references are all borrowed. */ typedef struct { duk_hthread *thr; - duk_hbuffer_dynamic *h_buf; + 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) */ @@ -9298,6 +10764,9 @@ 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 { @@ -9351,7 +10820,11 @@ DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv); DUK_INTERNAL_DECL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx); DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h); DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags); +DUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2); DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2); +#if 0 /* unused */ +DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2); +#endif DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags); DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y); DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y); @@ -9518,11 +10991,6 @@ DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix */ #define DUK_BI_DATE_ISO8601_BUFSIZE 48 -/* Buffer size for "short log message" which use a heap-level pre-allocated - * dynamic buffer to reduce memory churn. - */ -#define DUK_BI_LOGGER_SHORT_MSG_LIMIT 256 - /* Maximum length of CommonJS module identifier to resolve. Length includes * both current module ID, requested (possibly relative) module ID, and a * slash in between. @@ -9549,8 +11017,30 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ct DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx); +/* XXX: naming is inconsistent with other builtins, "prototype" not used as + * part of function name. + */ DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx); +DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx); @@ -9564,8 +11054,13 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_contex DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx); /* Helpers exposed for internal use */ -DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now(duk_context *ctx); +DUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags); +DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags); DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf); +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); 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); @@ -9674,7 +11169,7 @@ DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx); DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx); -/* Note: present even if DUK_OPT_NO_SECTION_B given because genbuiltins.py +/* Note: present even if DUK_USE_SECTION_B undefined given because genbuiltins.py * will point to it. */ DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx); @@ -9710,7 +11205,7 @@ DUK_INTERNAL_DECL void duk_selftest_run_tests(void); #endif #endif /* DUK_SELFTEST_H_INCLUDED */ -#line 76 "duk_internal.h" +#line 77 "duk_internal.h" #endif /* DUK_INTERNAL_H_INCLUDED */ #line 1 "duk_strings.c" @@ -9718,7 +11213,8 @@ DUK_INTERNAL_DECL void duk_selftest_run_tests(void); * Shared error message strings * * To minimize code footprint, try to share error messages inside Duktape - * code. + * code. Modern compilers will do this automatically anyway, this is mostly + * for older compilers. */ /* include removed: duk_internal.h */ @@ -9745,9 +11241,7 @@ 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_unexpected_type = "unexpected type"; DUK_INTERNAL const char *duk_str_not_thread = "not thread"; -#if 0 /*unused*/ DUK_INTERNAL const char *duk_str_not_compiledfunction = "not compiledfunction"; -#endif 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"; @@ -9756,19 +11250,16 @@ DUK_INTERNAL const char *duk_str_not_object_coercible = "not object coercible"; DUK_INTERNAL const char *duk_str_string_too_long = "string too long"; DUK_INTERNAL const char *duk_str_buffer_too_long = "buffer too long"; DUK_INTERNAL const char *duk_str_sprintf_too_long = "sprintf message too long"; -DUK_INTERNAL const char *duk_str_object_alloc_failed = "object alloc failed"; -DUK_INTERNAL const char *duk_str_thread_alloc_failed = "thread alloc failed"; -DUK_INTERNAL const char *duk_str_func_alloc_failed = "func alloc failed"; -DUK_INTERNAL const char *duk_str_buffer_alloc_failed = "buffer alloc failed"; +DUK_INTERNAL const char *duk_str_alloc_failed = "alloc failed"; DUK_INTERNAL const char *duk_str_pop_too_many = "attempt to pop too many entries"; DUK_INTERNAL const char *duk_str_buffer_not_dynamic = "buffer is not dynamic"; DUK_INTERNAL const char *duk_str_failed_to_extend_valstack = "failed to extend valstack"; -DUK_INTERNAL const char *duk_str_base64_encode_failed = "base64 encode failed"; -DUK_INTERNAL const char *duk_str_base64_decode_failed = "base64 decode failed"; -DUK_INTERNAL const char *duk_str_hex_decode_failed = "hex decode failed"; +DUK_INTERNAL const char *duk_str_encode_failed = "encode failed"; +DUK_INTERNAL const char *duk_str_decode_failed = "decode failed"; DUK_INTERNAL const char *duk_str_no_sourcecode = "no sourcecode"; DUK_INTERNAL const char *duk_str_concat_result_too_long = "concat result too long"; DUK_INTERNAL const char *duk_str_unimplemented = "unimplemented"; +DUK_INTERNAL const char *duk_str_unsupported = "unsupported"; DUK_INTERNAL const char *duk_str_array_length_over_2g = "array length over 2G"; /* JSON */ @@ -9951,7 +11442,7 @@ DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int 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_rdtsc(), /* match the inline asm in duk_features.h */ + (unsigned long long) DUK_USE_RDTSC(), /* match the inline asm in duk_features.h */ (const char *) file, (long) line, (const char *) func, @@ -9994,7 +11485,7 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) { 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_rdtsc(), /* match duk_features.h */ + (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, @@ -10034,108 +11525,141 @@ DUK_INTERNAL void duk_debug_log(const char *fmt, ...) { /* include removed: duk_internal.h */ #if defined(DUK_USE_DOUBLE_LE) -DUK_INTERNAL const duk_uint8_t duk_strings_data[1943] = { -55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,26,20,164,137, -186,50,11,164,109,77,215,5,61,35,106,3,25,110,8,22,158,130,38,163,8,217, -200,158,76,156,210,117,128,153,203,210,70,46,137,187,18,27,164,187,201,209, -130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,197,13,49,122,8,196,24, -71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,79,104,209,144,168,105, -6,207,251,209,104,209,125,212,227,66,127,235,191,239,232,180,90,52,95,69, -247,83,141,9,255,174,255,191,162,211,80,210,253,23,221,78,52,39,254,183, -254,254,139,72,105,126,139,238,167,26,19,255,91,255,127,69,166,129,191,69, -247,83,141,9,255,175,255,191,162,213,26,50,23,232,190,234,113,161,63,245, -115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,160,152,22,82,70,46,137, -44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,206,42,70,36,108,205,18, -74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,182,251,65,156,151,24,200, -33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,25,33,205,25,27,84,177, -195,234,220,1,144,105,99,135,217,16,17,17,208,72,199,179,60,93,100,146,49, -232,162,64,76,135,19,152,244,44,136,223,98,67,4,18,33,247,217,158,36,0,209, -190,156,13,26,201,21,111,165,67,64,180,100,145,62,250,32,45,100,33,55,214, -1,229,223,65,19,72,187,236,206,137,35,125,120,190,201,104,105,15,190,201, -212,136,136,125,246,160,137,27,83,239,171,37,200,218,159,125,168,34,192,61, -27,233,93,22,1,114,78,250,28,76,130,112,200,93,245,164,188,207,190,204,17, -49,38,109,246,160,93,8,119,185,13,153,34,96,208,165,36,85,190,206,32,17,6, -9,129,75,67,73,214,209,129,36,80,84,44,157,104,24,65,60,69,148,192,37,59, -179,60,93,110,207,15,39,73,24,186,39,232,232,169,129,228,18,6,120,146,20, -68,72,157,105,241,116,221,173,58,68,159,95,23,77,211,195,201,215,20,238, -179,122,162,98,73,35,104,194,68,19,35,134,69,146,100,235,226,231,146,51, -192,206,9,23,175,139,175,131,8,11,89,8,206,161,181,2,208,63,160,232,193,50, -23,246,254,187,235,190,187,247,69,241,95,18,31,160,15,214,11,235,126,192, -95,87,246,1,251,4,253,111,80,210,161,168,158,19,245,125,67,74,134,162,120, -71,80,210,161,168,158,12,224,164,130,153,165,56,161,166,51,104,192,146,39, -11,156,178,1,169,163,70,66,161,164,26,101,56,161,166,65,112,57,129,164,148, -35,49,201,13,44,93,70,140,209,3,70,230,13,238,176,216,134,141,128,184,214, -227,20,171,115,162,50,93,227,19,164,65,17,11,40,38,6,253,145,1,48,52,128, -146,26,64,9,210,24,3,34,250,80,140,254,200,254,148,35,63,177,215,217,11, -207,65,188,183,27,236,126,192,133,242,220,111,178,32,252,182,253,145,60, -182,253,143,216,7,164,59,9,41,0,196,35,64,194,21,13,125,38,84,52,100,185, -62,163,239,254,235,234,82,176,74,125,67,70,75,165,148,92,208,180,52,138,65, -154,232,147,162,4,136,105,58,145,17,9,50,74,100,37,200,37,205,222,51,39,47, -78,40,105,143,34,79,184,32,34,115,18,125,193,1,19,77,222,76,156,213,205, -222,68,157,47,78,40,105,151,55,122,147,20,189,56,161,166,116,137,63,82,98, -47,168,181,247,4,4,87,34,79,165,162,215,220,16,17,92,137,63,82,98,103,156, -217,157,18,36,250,199,54,103,84,137,63,82,98,31,129,50,30,68,159,70,9,145, -114,36,253,73,136,254,117,35,36,72,147,233,221,72,201,178,36,253,73,137, -158,67,105,50,73,82,36,250,196,54,147,36,155,34,79,212,152,165,226,9,205, -28,149,34,79,178,32,156,209,202,82,36,253,73,137,158,66,214,137,16,78,104, -228,249,18,125,98,22,180,72,130,115,71,35,200,147,236,208,194,68,196,159, -102,134,19,46,105,58,226,150,68,156,140,73,250,147,19,60,133,173,18,32,156, -209,201,230,36,250,196,45,104,145,4,230,142,77,49,39,234,76,82,241,4,230, -142,74,49,39,217,16,78,104,228,211,18,126,164,196,207,33,180,153,36,163,18, -125,98,27,73,146,75,49,39,234,76,71,243,169,25,32,196,159,78,234,70,73,49, -39,234,76,67,240,48,99,18,125,24,48,163,18,126,164,196,63,2,100,57,137,62, -140,19,34,204,73,250,147,19,60,230,204,232,49,39,214,57,179,59,140,73,250, -147,17,125,69,175,184,32,34,179,18,125,45,22,190,224,128,137,204,73,246, -104,97,37,55,117,110,16,22,78,205,12,39,101,56,161,166,148,221,213,184,64, -89,58,48,76,157,148,226,134,153,147,119,102,134,19,178,156,80,211,50,110, -232,193,50,118,83,138,26,97,181,214,31,169,49,21,224,140,136,185,187,175, -137,4,137,33,205,108,221,210,93,238,105,27,52,1,103,155,186,84,92,131,143, -158,233,34,104,169,52,134,149,13,68,241,31,52,134,4,209,82,105,13,42,26, -137,224,125,104,58,212,249,136,110,170,5,208,137,243,1,125,84,11,161,13,42, -6,83,137,39,20,50,51,119,86,225,1,100,237,30,242,71,162,4,136,185,187,180, -123,201,30,136,18,36,102,238,173,194,2,201,213,186,196,143,68,9,17,115,119, -86,235,18,61,16,36,68,202,129,148,226,134,152,178,122,209,51,72,128,136, -142,120,145,235,0,136,86,2,98,59,86,225,1,100,232,156,199,130,36,80,142,8, -244,78,25,58,9,152,71,4,122,9,176,177,115,58,35,130,61,19,134,69,196,131, -160,137,216,160,199,153,162,65,208,68,49,80,185,146,35,96,30,114,186,61,32, -4,114,73,204,33,73,82,71,11,88,37,62,161,163,37,250,226,157,13,25,47,215, -20,244,108,142,130,204,210,122,208,34,18,78,140,203,37,160,68,44,142,130, -204,241,37,73,25,16,143,164,142,55,185,228,75,144,211,9,205,16,38,116,75, -160,140,65,132,130,38,163,8,217,200,194,2,214,72,144,40,104,200,32,45,101, -3,222,188,81,241,115,201,25,227,168,151,72,218,48,145,0,86,70,162,93,124, -93,55,79,15,39,92,87,28,18,235,172,222,190,46,121,35,60,30,160,93,9,215,21, -211,119,86,225,1,100,236,167,20,52,200,155,187,41,197,13,50,196,230,202, -113,160,166,232,142,68,152,204,73,168,141,163,9,16,5,100,96,156,210,160, -212,136,2,178,34,209,68,192,21,144,181,2,232,66,40,152,147,17,46,146,243, -35,100,128,172,136,68,186,88,187,36,106,17,46,200,128,89,7,23,196,149,35, -103,210,94,100,108,144,230,200,197,137,9,146,18,68,2,224,50,21,13,39,95,23, -60,145,154,9,39,12,133,67,73,215,197,207,36,103,131,10,36,4,201,51,18,125, -117,155,215,197,207,36,103,142,180,12,36,176,98,79,174,179,122,248,185,228, -140,241,209,146,66,138,31,55,69,198,36,250,248,186,110,158,30,78,184,169, -124,93,55,79,15,33,150,70,154,103,40,22,72,204,175,138,27,52,81,164,144, -128,242,24,146,16,30,73,17,162,112,201,234,69,2,243,152,247,52,141,154,72, -209,56,100,245,34,137,12,130,112,201,234,69,2,243,152,247,52,141,154,70,65, -56,100,245,34,132,34,93,42,26,137,144,168,151,90,14,181,79,4,100,78,149, -110,4,208,240,70,68,234,27,50,18,160,90,61,72,160,158,140,93,20,246,120, -121,58,72,197,209,95,101,134,204,23,233,35,23,69,221,137,10,72,145,162,39, -73,24,186,42,236,64,211,19,164,140,93,20,244,149,2,250,72,197,209,40,98,64, -40,130,4,136,81,2,98,58,4,230,205,13,161,16,50,6,134,49,34,113,144,160,162, -230,97,145,100,153,4,55,16,139,145,14,84,52,11,94,6,87,69,5,163,69,52,57, -162,65,68,134,169,13,148,192,209,17,197,27,73,99,68,147,164,90,105,89,19, -17,201,51,162,69,153,226,235,14,113,193,167,135,145,197,29,65,18,85,200,25, -108,116,44,132,178,38,114,137,96,148,138,39,54,83,33,27,70,24,151,123,163, -51,146,243,35,71,35,33,143,116,102,89,81,228,137,27,69,172,147,141,8,82, -129,114,34,144,199,172,140,35,103,36,161,179,36,74,1,16,107,36,206,240,9, -64,49,14,248,162,160,153,18,248,186,100,20,200,51,62,129,90,4,105,76,19,64, -139,132,17,99, +DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = { +55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,50,11,164,109, +77,215,5,61,35,106,206,149,110,4,254,219,237,58,8,196,24,103,74,183,2,127, +103,246,93,4,98,12,47,180,67,103,246,127,101,208,70,32,194,186,134,207,236, +254,203,160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253, +143,219,116,17,136,49,30,209,13,159,220,116,75,3,30,65,244,17,136,48,174, +209,13,159,220,116,17,136,48,158,161,179,251,142,130,49,6,17,209,130,96, +237,80,75,47,160,140,65,142,134,133,41,34,110,134,133,41,34,3,25,110,8,22, +158,130,38,163,8,217,200,158,76,156,210,117,128,153,203,210,70,46,137,187, +18,27,164,187,201,209,130,100,55,91,70,4,145,63,66,231,44,128,105,187,41, +197,13,49,122,8,196,24,71,75,70,138,104,115,77,215,5,36,20,201,214,209,107, +79,104,209,144,168,105,6,207,251,209,104,209,125,212,227,66,127,235,191, +239,232,180,90,52,95,69,247,83,141,9,255,174,255,191,162,211,80,210,253,23, +221,78,52,39,254,183,254,254,139,72,105,126,139,238,167,26,19,255,91,255, +127,69,166,129,191,69,247,83,141,9,255,175,255,191,162,213,26,50,23,232, +190,234,113,161,63,245,115,119,86,227,118,83,138,26,98,9,110,48,86,22,148, +160,152,22,82,70,46,137,44,8,180,163,32,104,98,206,32,17,7,16,88,101,100, +206,42,70,36,108,205,18,74,140,33,196,230,60,2,152,146,33,38,230,8,36,79, +182,251,65,156,151,24,200,33,145,162,25,80,209,24,67,0,166,68,52,174,61,73, +25,33,205,25,27,84,177,195,234,220,1,144,105,99,135,217,16,17,17,208,72, +199,179,60,93,100,146,49,232,162,64,76,135,19,152,244,44,136,223,98,67,4, +18,33,247,217,158,36,0,209,190,156,13,26,201,21,111,165,67,64,180,100,145, +62,250,32,45,100,33,55,214,1,229,223,65,19,72,187,236,206,137,35,125,120, +190,201,104,105,15,190,201,212,136,136,125,246,160,137,27,83,239,171,37, +200,218,159,125,168,34,192,61,27,233,93,22,1,114,78,250,28,76,130,112,200, +93,245,164,188,207,190,204,17,49,38,109,246,160,93,8,119,185,13,153,34,173, +246,113,0,136,48,76,10,90,26,78,182,140,9,34,130,161,100,235,64,194,9,226, +44,166,1,41,221,153,226,235,118,120,121,58,72,197,209,63,71,69,76,15,34, +164,73,244,171,112,39,246,223,104,169,18,125,42,220,9,253,159,217,38,68, +159,104,134,207,236,254,201,18,36,250,134,207,236,254,201,50,36,251,68,54, +127,99,246,200,145,39,212,54,127,99,246,200,145,39,218,33,179,251,131,200, +147,234,27,63,184,81,137,62,149,110,4,254,219,237,20,98,79,165,91,129,63, +179,251,36,152,147,237,16,217,253,159,217,32,196,159,80,217,253,159,217,36, +196,159,104,134,207,236,126,217,6,36,250,134,207,236,126,217,6,36,251,68, +54,127,112,115,18,125,67,103,247,8,149,2,8,196,24,143,131,137,146,90,121, +35,162,44,140,35,102,160,226,100,235,138,89,18,102,13,10,82,68,200,151,106, +130,88,131,4,192,73,225,228,85,162,137,147,168,108,252,18,42,209,68,201, +212,54,126,89,23,104,162,100,245,17,230,207,193,34,237,20,76,158,162,60, +217,249,100,109,162,137,147,163,117,2,178,120,36,109,162,137,147,163,117,2, +178,121,100,101,162,137,147,165,91,129,63,4,140,180,81,50,116,171,112,39, +229,145,150,138,38,78,161,179,251,63,178,240,72,203,69,19,39,80,217,253, +159,217,121,100,109,162,137,147,212,71,155,63,179,251,47,4,141,180,81,50, +122,136,243,103,246,127,101,229,145,150,138,38,78,161,179,251,31,182,240, +72,203,69,19,39,80,217,253,143,219,121,100,109,162,137,147,212,71,155,63, +177,251,111,4,141,180,81,50,122,136,243,103,246,63,109,229,145,54,138,38, +78,161,179,251,133,90,40,153,61,68,121,179,251,132,196,128,31,80,217,248, +36,76,72,1,245,13,159,150,69,68,128,31,168,143,54,126,9,21,18,0,126,162,60, +217,249,100,100,72,1,244,110,160,86,79,4,140,137,0,62,141,212,10,201,229, +145,113,32,7,210,173,192,159,130,69,196,128,31,74,183,2,126,89,23,18,0,125, +67,103,246,127,101,224,145,113,32,7,212,54,127,103,246,94,89,25,18,0,126, +162,60,217,253,159,217,120,36,100,72,1,250,136,243,103,246,127,101,229,145, +113,32,7,212,54,127,99,246,222,9,23,18,0,125,67,103,246,63,109,229,145,145, +32,7,234,35,205,159,216,253,183,130,70,68,128,31,168,143,54,127,99,246,222, +89,17,18,0,125,67,103,247,9,137,0,63,81,30,108,254,224,130,115,240,98,66, +128,92,136,84,45,101,180,81,50,28,78,99,193,18,40,56,153,58,178,52,211,58, +17,46,134,133,41,34,164,75,164,104,156,52,52,199,37,222,232,206,66,64,207, +18,66,136,137,19,173,62,46,155,181,167,72,147,235,226,233,186,120,121,58, +226,157,214,111,84,76,73,36,109,24,72,130,100,112,200,178,76,157,124,92, +242,70,120,25,193,34,245,241,117,240,97,1,107,33,25,212,54,160,90,7,244,29, +24,38,66,254,223,215,125,119,215,126,232,190,43,226,67,244,1,250,193,125, +111,216,11,234,254,192,63,96,159,173,234,26,84,53,19,194,126,175,168,105, +80,212,79,8,234,26,84,53,19,193,156,20,144,83,52,167,20,52,198,109,24,18, +68,225,115,150,64,53,52,104,200,84,52,131,76,167,20,52,200,46,7,48,52,146, +132,102,57,33,165,139,168,209,154,32,104,220,193,189,214,27,16,209,176,23, +26,220,98,149,110,116,70,75,188,98,116,136,34,33,101,4,192,223,178,32,38,6, +144,18,67,72,1,58,67,0,100,95,74,17,159,217,31,210,132,103,246,58,251,33, +121,232,55,150,227,125,143,216,16,190,91,141,246,68,31,150,223,178,39,150, +223,177,251,0,244,135,97,37,32,24,132,104,24,66,161,175,164,202,134,140, +151,39,212,125,255,221,125,74,86,9,79,168,104,201,116,178,139,154,22,134, +145,72,51,93,18,116,64,145,13,39,82,34,33,38,73,76,132,185,4,185,187,198, +100,229,233,197,13,49,228,73,247,4,4,78,98,79,184,32,34,105,187,201,147, +154,185,187,200,147,165,233,197,13,50,230,239,82,98,151,167,20,52,206,145, +39,234,76,69,245,22,190,224,128,138,228,73,244,180,90,251,130,2,43,145,39, +234,76,76,243,155,51,162,68,159,88,230,204,234,145,39,234,76,67,240,38,67, +200,147,232,193,50,46,68,159,169,49,31,206,164,100,137,18,125,59,169,25,54, +68,159,169,49,51,200,109,38,73,42,68,159,88,134,210,100,147,100,73,250,147, +20,188,65,57,163,146,164,73,246,68,19,154,57,74,68,159,169,49,51,200,90, +209,34,9,205,28,159,34,79,172,66,214,137,16,78,104,228,121,18,125,154,24, +72,152,147,236,208,194,101,205,39,92,82,200,147,145,137,63,82,98,103,144, +181,162,68,19,154,57,60,196,159,88,133,173,18,32,156,209,201,166,36,253,73, +138,94,32,156,209,201,70,36,251,34,9,205,28,154,98,79,212,152,153,228,54, +147,36,148,98,79,172,67,105,50,73,102,36,253,73,136,254,117,35,36,24,147, +233,221,72,201,38,36,253,73,136,126,6,12,98,79,163,6,20,98,79,212,152,135, +224,76,135,49,39,209,130,100,89,137,63,82,98,103,156,217,157,6,36,250,199, +54,103,113,137,63,82,98,47,168,181,247,4,4,86,98,79,165,162,215,220,16,17, +57,137,62,205,12,36,166,238,173,194,2,201,217,161,132,236,167,20,52,210, +155,186,183,8,11,39,70,9,147,178,156,80,211,50,110,236,208,194,118,83,138, +26,102,77,221,24,38,78,202,113,67,76,54,186,195,245,38,34,188,17,145,23,55, +117,241,32,145,36,57,173,155,186,75,189,205,35,102,128,44,243,119,74,139, +144,113,243,221,36,77,21,38,144,210,161,168,158,35,230,144,192,154,42,77, +33,165,67,81,60,15,173,7,90,159,49,13,213,64,186,17,62,96,47,170,129,116, +33,165,64,202,113,36,226,134,70,110,234,220,32,44,157,163,222,72,244,64, +145,23,55,118,143,121,35,209,2,68,140,221,213,184,64,89,58,183,88,145,232, +129,34,46,110,234,221,98,71,162,4,136,153,80,50,156,80,211,22,79,90,38,105, +16,17,17,207,18,61,96,17,10,192,76,71,106,220,32,44,157,19,152,240,68,138, +17,193,30,137,195,39,65,51,8,224,143,65,54,22,46,103,68,112,71,162,112,200, +184,144,116,17,59,20,24,243,52,72,58,8,134,42,23,50,68,108,3,206,87,71,164, +0,142,73,57,132,41,42,72,225,107,4,167,212,52,100,191,92,83,161,163,37,250, +226,158,141,145,208,89,154,79,90,4,66,73,209,153,100,180,8,133,145,208,89, +158,36,169,35,34,17,244,145,198,247,60,137,114,26,97,57,162,4,206,137,116, +17,136,48,144,68,212,97,27,57,24,64,90,201,18,5,13,25,4,5,172,160,123,215, +138,62,46,121,35,60,117,18,233,27,70,18,32,10,200,212,75,175,139,166,233, +225,228,235,138,227,130,93,117,155,215,197,207,36,103,131,212,11,161,58, +226,186,110,234,220,32,44,157,148,226,134,153,19,119,101,56,161,166,88,156, +217,78,52,20,221,17,200,147,25,137,53,17,180,97,34,0,172,140,19,154,84,26, +145,0,86,68,90,40,152,2,178,22,160,93,8,69,19,18,98,37,210,94,100,108,144, +21,145,8,151,75,23,100,141,66,37,217,16,11,32,226,248,146,164,108,250,75, +204,141,146,28,217,24,177,33,50,66,72,128,92,6,66,161,164,235,226,231,146, +51,65,36,225,144,168,105,58,248,185,228,140,240,97,68,128,153,38,98,79,174, +179,122,248,185,228,140,241,214,129,132,150,12,73,245,214,111,95,23,60,145, +158,58,50,72,81,67,230,232,184,196,159,95,23,77,211,195,201,215,21,47,139, +166,233,225,228,50,200,211,76,229,2,201,25,149,241,67,102,138,52,146,16,30, +67,18,66,3,201,34,52,78,25,61,72,160,94,115,30,230,145,179,73,26,39,12,158, +164,81,33,144,78,25,61,72,160,94,115,30,230,145,179,72,200,39,12,158,164, +80,132,75,165,67,81,50,21,18,235,65,214,169,224,140,137,210,173,192,154,30, +8,200,157,67,102,66,84,11,71,169,20,19,209,139,162,158,207,15,39,73,24,186, +43,236,176,217,130,253,36,98,232,187,177,33,73,18,52,68,233,35,23,69,93, +136,26,98,116,145,139,162,158,146,160,95,73,24,186,37,12,72,5,16,64,145,10, +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, }; /* to convert a heap stridx to a token number, subtract * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED. */ -/* native functions: 128 */ -DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { +/* native functions: 147 */ +DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = { duk_bi_array_constructor, duk_bi_array_constructor_is_array, duk_bi_array_prototype_concat, @@ -10152,10 +11676,17 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_array_prototype_splice, duk_bi_array_prototype_to_string, duk_bi_array_prototype_unshift, + duk_bi_arraybuffer_constructor, + duk_bi_arraybuffer_isview, duk_bi_boolean_constructor, duk_bi_boolean_prototype_tostring_shared, + duk_bi_buffer_compare_shared, duk_bi_buffer_constructor, duk_bi_buffer_prototype_tostring_shared, + duk_bi_buffer_readfield, + duk_bi_buffer_slice_shared, + duk_bi_buffer_writefield, + duk_bi_dataview_constructor, duk_bi_date_constructor, duk_bi_date_constructor_now, duk_bi_date_constructor_parse, @@ -10210,6 +11741,16 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_math_object_onearg_shared, duk_bi_math_object_random, duk_bi_math_object_twoarg_shared, + duk_bi_nodejs_buffer_byte_length, + duk_bi_nodejs_buffer_concat, + duk_bi_nodejs_buffer_constructor, + duk_bi_nodejs_buffer_copy, + duk_bi_nodejs_buffer_fill, + duk_bi_nodejs_buffer_is_buffer, + duk_bi_nodejs_buffer_is_encoding, + duk_bi_nodejs_buffer_tojson, + duk_bi_nodejs_buffer_tostring, + duk_bi_nodejs_buffer_write, duk_bi_number_constructor, duk_bi_number_prototype_to_exponential, duk_bi_number_prototype_to_fixed, @@ -10264,68 +11805,97 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_thread_resume, duk_bi_thread_yield, duk_bi_type_error_thrower, + duk_bi_typedarray_constructor, + duk_bi_typedarray_set, }; -DUK_INTERNAL const duk_uint8_t duk_builtins_data[1341] = { -105,195,74,136,77,40,105,44,9,124,104,45,3,3,72,0,71,225,65,165,168,33,243, -6,145,0,122,24,210,148,14,249,35,120,160,55,226,13,76,192,196,177,164,152, -22,192,4,202,52,147,72,152,0,169,70,146,105,11,0,23,40,210,77,32,96,3,37, -26,73,163,236,0,108,163,73,52,121,128,14,148,105,38,142,176,1,242,144,56, -208,254,84,6,166,82,242,80,210,246,1,250,67,72,144,15,232,13,44,96,47,162, -52,160,128,62,80,160,255,253,102,76,0,0,0,0,0,0,15,135,243,84,0,0,0,0,0,0, -15,7,243,124,64,153,132,18,49,2,38,48,64,200,7,153,64,227,48,26,103,3,13,0, -89,165,34,53,36,38,180,128,216,143,155,81,227,114,58,111,2,142,0,73,194,94, -56,202,167,33,209,195,114,70,206,209,26,58,36,100,228,145,131,130,69,204, -137,22,51,36,84,208,145,67,82,68,205,137,18,62,36,68,240,122,32,120,62,0,2, -87,61,39,255,254,9,46,24,0,10,31,224,29,13,91,40,0,9,101,137,32,0,48,197, -84,66,214,9,10,82,68,37,81,144,133,52,65,214,137,6,90,40,0,12,21,100,144, -69,114,64,213,202,0,3,2,86,36,5,96,160,0,63,254,16,37,135,91,98,25,242,192, -7,194,248,30,236,32,123,46,17,234,186,71,162,241,5,23,240,0,15,241,1,70,74, -3,8,249,49,3,204,185,15,35,3,231,137,121,240,163,254,0,46,224,18,7,248,192, -42,249,14,3,224,20,32,0,46,208,35,231,96,41,29,96,192,117,3,159,58,66,64, -232,10,3,156,45,14,96,194,57,67,87,156,129,231,206,48,51,240,0,23,16,25, -255,255,251,132,16,209,192,8,106,0,2,223,4,53,0,2,111,2,26,128,1,183,65,13, -64,1,27,129,7,224,0,45,176,131,255,255,241,73,252,0,91,77,103,193,254,64, -36,200,64,101,31,47,32,123,188,129,178,218,70,195,113,29,173,231,206,55,3, -71,19,129,168,0,11,93,196,141,103,34,53,92,208,212,116,35,157,213,13,55, -100,52,158,16,209,108,3,65,176,12,246,192,128,0,179,155,2,0,2,205,122,3,49, -221,2,151,248,0,7,249,64,147,35,4,249,17,8,0,11,220,68,2,155,248,172,184, -31,255,255,255,255,255,253,239,236,168,0,32,0,0,0,0,0,0,12,152,0,0,0,0,0,0, -31,15,236,120,0,0,0,0,0,0,30,15,236,136,0,0,0,0,0,0,30,31,224,7,249,128, -147,32,0,0,0,0,0,0,0,0,12,249,79,35,225,52,143,117,0,49,147,8,197,75,35,17, -56,130,159,248,1,176,197,136,194,23,254,96,138,128,63,206,4,153,32,0,0,0,0, -0,3,225,254,215,200,232,24,3,161,0,1,95,142,132,0,9,240,58,16,0,53,240,232, -64,1,23,163,161,0,5,77,142,132,0,25,52,58,16,0,116,200,225,30,227,192,94, -15,1,118,48,16,0,133,208,192,64,2,87,35,1,0,10,92,12,4,0,45,110,48,16,0, -197,176,192,64,3,86,163,1,0,14,90,12,4,0,61,102,48,16,1,5,144,192,64,4,86, -35,1,0,18,88,12,4,0,77,94,48,16,1,69,112,192,64,5,85,163,1,0,22,86,12,4,0, -93,86,50,5,80,217,21,35,69,0,24,84,13,20,0,101,78,52,190,0,52,166,26,95,0, -27,82,141,63,128,14,41,6,159,192,7,84,99,83,224,3,202,33,169,240,1,245,8, -209,64,8,20,3,69,0,33,79,141,47,128,17,39,134,151,192,8,211,163,79,224,4, -137,193,167,240,2,84,192,192,64,9,146,227,69,0,39,21,31,192,0,63,208,24, -147,4,12,0,32,41,56,72,240,60,100,148,100,140,100,132,128,0,0,0,0,0,0,0,0, -210,172,228,74,52,17,242,210,1,83,252,0,3,253,33,81,132,11,69,144,24,166, -229,69,37,23,39,41,40,57,65,72,47,146,176,10,175,224,0,159,234,4,140,41,18, -44,128,192,10,191,224,0,159,235,4,140,41,10,44,128,192,10,207,224,0,159, -236,4,140,41,2,44,128,192,10,223,224,0,159,237,4,140,40,250,44,128,192,10, -239,224,0,159,238,4,140,40,242,44,128,192,10,255,224,0,159,239,4,140,40, -234,44,128,192,7,255,228,34,160,52,171,138,69,133,95,130,160,34,96,11,42, -218,221,216,181,129,32,34,32,119,156,253,127,33,23,115,31,161,224,127,65, -21,178,163,138,251,159,161,160,7,114,147,10,189,229,237,159,161,96,12,22, -162,42,125,144,132,160,33,32,102,157,191,179,79,80,115,31,160,224,102,157, -191,179,79,80,123,31,164,130,71,34,5,28,160,0,40,4,114,128,1,31,209,202,0, -6,126,73,65,245,28,160,0,135,196,114,128,2,158,209,202,0,12,122,71,40,0,57, -229,28,160,1,7,132,85,227,186,50,241,217,37,32,0,39,84,128,29,17,202,0,18, -115,71,40,0,81,201,28,160,1,103,20,114,128,6,7,255,224,4,195,63,65,193,1, -130,255,248,0,11,255,224,0,31,255,138,52,128,0,0,0,1,1,219,134,128,3,57, -192,71,72,4,229,0,29,99,140,201,72,50,31,32,196,144,131,2,49,225,121,16, -240,184,132,120,82,64,65,102,252,0,233,239,200,20,62,176,78,248,0,255,148, -0,5,163,240,0,15,249,192,9,242,38,16,0,23,184,152,5,171,240,0,15,250,64,9, -242,200,16,0,23,187,32,5,179,240,0,15,250,194,15,72,0,0,0,0,0,0,0,64,15, -201,4,195,187,126,226,4,200,68,18,162,16,72,134,60,35,67,31,0,1,25,161,143, -128,1,8,144,199,192,0,196,40,99,224,0,130,4,49,240,0,84,255,252,36,100,16, -184,155,250,226,217,150,47,46,91,249,34,224,139,229,229,203,127,36,26,119, -32,203,203,150,254,72,52,97,221,147,102,157,217,192, +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, +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, +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, +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, +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, +12,62,16,0,184,40,248,64,3,32,131,225,0,13,129,143,132,0,58,4,62,16,0,248, +8,248,64,4,32,3,225,0,17,127,143,132,0,73,252,62,16,1,55,232,248,64,5,31, +131,225,0,21,125,143,132,0,89,244,62,16,1,119,201,0,31,4,68,123,144,148,0, +97,236,66,80,1,151,169,10,248,0,211,208,133,124,0,109,230,66,254,0,56,242, +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, +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, +255,242,27,16,26,85,197,34,194,175,193,80,26,240,5,149,109,110,236,90,192, +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,1,220,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, }; #ifdef DUK_USE_BUILTIN_INITJS DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = { @@ -10341,108 +11911,141 @@ DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = { }; #endif /* DUK_USE_BUILTIN_INITJS */ #elif defined(DUK_USE_DOUBLE_BE) -DUK_INTERNAL const duk_uint8_t duk_strings_data[1943] = { -55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,26,20,164,137, -186,50,11,164,109,77,215,5,61,35,106,3,25,110,8,22,158,130,38,163,8,217, -200,158,76,156,210,117,128,153,203,210,70,46,137,187,18,27,164,187,201,209, -130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,197,13,49,122,8,196,24, -71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,79,104,209,144,168,105, -6,207,251,209,104,209,125,212,227,66,127,235,191,239,232,180,90,52,95,69, -247,83,141,9,255,174,255,191,162,211,80,210,253,23,221,78,52,39,254,183, -254,254,139,72,105,126,139,238,167,26,19,255,91,255,127,69,166,129,191,69, -247,83,141,9,255,175,255,191,162,213,26,50,23,232,190,234,113,161,63,245, -115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,160,152,22,82,70,46,137, -44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,206,42,70,36,108,205,18, -74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,182,251,65,156,151,24,200, -33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,25,33,205,25,27,84,177, -195,234,220,1,144,105,99,135,217,16,17,17,208,72,199,179,60,93,100,146,49, -232,162,64,76,135,19,152,244,44,136,223,98,67,4,18,33,247,217,158,36,0,209, -190,156,13,26,201,21,111,165,67,64,180,100,145,62,250,32,45,100,33,55,214, -1,229,223,65,19,72,187,236,206,137,35,125,120,190,201,104,105,15,190,201, -212,136,136,125,246,160,137,27,83,239,171,37,200,218,159,125,168,34,192,61, -27,233,93,22,1,114,78,250,28,76,130,112,200,93,245,164,188,207,190,204,17, -49,38,109,246,160,93,8,119,185,13,153,34,96,208,165,36,85,190,206,32,17,6, -9,129,75,67,73,214,209,129,36,80,84,44,157,104,24,65,60,69,148,192,37,59, -179,60,93,110,207,15,39,73,24,186,39,232,232,169,129,228,18,6,120,146,20, -68,72,157,105,241,116,221,173,58,68,159,95,23,77,211,195,201,215,20,238, -179,122,162,98,73,35,104,194,68,19,35,134,69,146,100,235,226,231,146,51, -192,206,9,23,175,139,175,131,8,11,89,8,206,161,181,2,208,63,160,232,193,50, -23,246,254,187,235,190,187,247,69,241,95,18,31,160,15,214,11,235,126,192, -95,87,246,1,251,4,253,111,80,210,161,168,158,19,245,125,67,74,134,162,120, -71,80,210,161,168,158,12,224,164,130,153,165,56,161,166,51,104,192,146,39, -11,156,178,1,169,163,70,66,161,164,26,101,56,161,166,65,112,57,129,164,148, -35,49,201,13,44,93,70,140,209,3,70,230,13,238,176,216,134,141,128,184,214, -227,20,171,115,162,50,93,227,19,164,65,17,11,40,38,6,253,145,1,48,52,128, -146,26,64,9,210,24,3,34,250,80,140,254,200,254,148,35,63,177,215,217,11, -207,65,188,183,27,236,126,192,133,242,220,111,178,32,252,182,253,145,60, -182,253,143,216,7,164,59,9,41,0,196,35,64,194,21,13,125,38,84,52,100,185, -62,163,239,254,235,234,82,176,74,125,67,70,75,165,148,92,208,180,52,138,65, -154,232,147,162,4,136,105,58,145,17,9,50,74,100,37,200,37,205,222,51,39,47, -78,40,105,143,34,79,184,32,34,115,18,125,193,1,19,77,222,76,156,213,205, -222,68,157,47,78,40,105,151,55,122,147,20,189,56,161,166,116,137,63,82,98, -47,168,181,247,4,4,87,34,79,165,162,215,220,16,17,92,137,63,82,98,103,156, -217,157,18,36,250,199,54,103,84,137,63,82,98,31,129,50,30,68,159,70,9,145, -114,36,253,73,136,254,117,35,36,72,147,233,221,72,201,178,36,253,73,137, -158,67,105,50,73,82,36,250,196,54,147,36,155,34,79,212,152,165,226,9,205, -28,149,34,79,178,32,156,209,202,82,36,253,73,137,158,66,214,137,16,78,104, -228,249,18,125,98,22,180,72,130,115,71,35,200,147,236,208,194,68,196,159, -102,134,19,46,105,58,226,150,68,156,140,73,250,147,19,60,133,173,18,32,156, -209,201,230,36,250,196,45,104,145,4,230,142,77,49,39,234,76,82,241,4,230, -142,74,49,39,217,16,78,104,228,211,18,126,164,196,207,33,180,153,36,163,18, -125,98,27,73,146,75,49,39,234,76,71,243,169,25,32,196,159,78,234,70,73,49, -39,234,76,67,240,48,99,18,125,24,48,163,18,126,164,196,63,2,100,57,137,62, -140,19,34,204,73,250,147,19,60,230,204,232,49,39,214,57,179,59,140,73,250, -147,17,125,69,175,184,32,34,179,18,125,45,22,190,224,128,137,204,73,246, -104,97,37,55,117,110,16,22,78,205,12,39,101,56,161,166,148,221,213,184,64, -89,58,48,76,157,148,226,134,153,147,119,102,134,19,178,156,80,211,50,110, -232,193,50,118,83,138,26,97,181,214,31,169,49,21,224,140,136,185,187,175, -137,4,137,33,205,108,221,210,93,238,105,27,52,1,103,155,186,84,92,131,143, -158,233,34,104,169,52,134,149,13,68,241,31,52,134,4,209,82,105,13,42,26, -137,224,125,104,58,212,249,136,110,170,5,208,137,243,1,125,84,11,161,13,42, -6,83,137,39,20,50,51,119,86,225,1,100,237,30,242,71,162,4,136,185,187,180, -123,201,30,136,18,36,102,238,173,194,2,201,213,186,196,143,68,9,17,115,119, -86,235,18,61,16,36,68,202,129,148,226,134,152,178,122,209,51,72,128,136, -142,120,145,235,0,136,86,2,98,59,86,225,1,100,232,156,199,130,36,80,142,8, -244,78,25,58,9,152,71,4,122,9,176,177,115,58,35,130,61,19,134,69,196,131, -160,137,216,160,199,153,162,65,208,68,49,80,185,146,35,96,30,114,186,61,32, -4,114,73,204,33,73,82,71,11,88,37,62,161,163,37,250,226,157,13,25,47,215, -20,244,108,142,130,204,210,122,208,34,18,78,140,203,37,160,68,44,142,130, -204,241,37,73,25,16,143,164,142,55,185,228,75,144,211,9,205,16,38,116,75, -160,140,65,132,130,38,163,8,217,200,194,2,214,72,144,40,104,200,32,45,101, -3,222,188,81,241,115,201,25,227,168,151,72,218,48,145,0,86,70,162,93,124, -93,55,79,15,39,92,87,28,18,235,172,222,190,46,121,35,60,30,160,93,9,215,21, -211,119,86,225,1,100,236,167,20,52,200,155,187,41,197,13,50,196,230,202, -113,160,166,232,142,68,152,204,73,168,141,163,9,16,5,100,96,156,210,160, -212,136,2,178,34,209,68,192,21,144,181,2,232,66,40,152,147,17,46,146,243, -35,100,128,172,136,68,186,88,187,36,106,17,46,200,128,89,7,23,196,149,35, -103,210,94,100,108,144,230,200,197,137,9,146,18,68,2,224,50,21,13,39,95,23, -60,145,154,9,39,12,133,67,73,215,197,207,36,103,131,10,36,4,201,51,18,125, -117,155,215,197,207,36,103,142,180,12,36,176,98,79,174,179,122,248,185,228, -140,241,209,146,66,138,31,55,69,198,36,250,248,186,110,158,30,78,184,169, -124,93,55,79,15,33,150,70,154,103,40,22,72,204,175,138,27,52,81,164,144, -128,242,24,146,16,30,73,17,162,112,201,234,69,2,243,152,247,52,141,154,72, -209,56,100,245,34,137,12,130,112,201,234,69,2,243,152,247,52,141,154,70,65, -56,100,245,34,132,34,93,42,26,137,144,168,151,90,14,181,79,4,100,78,149, -110,4,208,240,70,68,234,27,50,18,160,90,61,72,160,158,140,93,20,246,120, -121,58,72,197,209,95,101,134,204,23,233,35,23,69,221,137,10,72,145,162,39, -73,24,186,42,236,64,211,19,164,140,93,20,244,149,2,250,72,197,209,40,98,64, -40,130,4,136,81,2,98,58,4,230,205,13,161,16,50,6,134,49,34,113,144,160,162, -230,97,145,100,153,4,55,16,139,145,14,84,52,11,94,6,87,69,5,163,69,52,57, -162,65,68,134,169,13,148,192,209,17,197,27,73,99,68,147,164,90,105,89,19, -17,201,51,162,69,153,226,235,14,113,193,167,135,145,197,29,65,18,85,200,25, -108,116,44,132,178,38,114,137,96,148,138,39,54,83,33,27,70,24,151,123,163, -51,146,243,35,71,35,33,143,116,102,89,81,228,137,27,69,172,147,141,8,82, -129,114,34,144,199,172,140,35,103,36,161,179,36,74,1,16,107,36,206,240,9, -64,49,14,248,162,160,153,18,248,186,100,20,200,51,62,129,90,4,105,76,19,64, -139,132,17,99, +DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = { +55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,50,11,164,109, +77,215,5,61,35,106,206,149,110,4,254,219,237,58,8,196,24,103,74,183,2,127, +103,246,93,4,98,12,47,180,67,103,246,127,101,208,70,32,194,186,134,207,236, +254,203,160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253, +143,219,116,17,136,49,30,209,13,159,220,116,75,3,30,65,244,17,136,48,174, +209,13,159,220,116,17,136,48,158,161,179,251,142,130,49,6,17,209,130,96, +237,80,75,47,160,140,65,142,134,133,41,34,110,134,133,41,34,3,25,110,8,22, +158,130,38,163,8,217,200,158,76,156,210,117,128,153,203,210,70,46,137,187, +18,27,164,187,201,209,130,100,55,91,70,4,145,63,66,231,44,128,105,187,41, +197,13,49,122,8,196,24,71,75,70,138,104,115,77,215,5,36,20,201,214,209,107, +79,104,209,144,168,105,6,207,251,209,104,209,125,212,227,66,127,235,191, +239,232,180,90,52,95,69,247,83,141,9,255,174,255,191,162,211,80,210,253,23, +221,78,52,39,254,183,254,254,139,72,105,126,139,238,167,26,19,255,91,255, +127,69,166,129,191,69,247,83,141,9,255,175,255,191,162,213,26,50,23,232, +190,234,113,161,63,245,115,119,86,227,118,83,138,26,98,9,110,48,86,22,148, +160,152,22,82,70,46,137,44,8,180,163,32,104,98,206,32,17,7,16,88,101,100, +206,42,70,36,108,205,18,74,140,33,196,230,60,2,152,146,33,38,230,8,36,79, +182,251,65,156,151,24,200,33,145,162,25,80,209,24,67,0,166,68,52,174,61,73, +25,33,205,25,27,84,177,195,234,220,1,144,105,99,135,217,16,17,17,208,72, +199,179,60,93,100,146,49,232,162,64,76,135,19,152,244,44,136,223,98,67,4, +18,33,247,217,158,36,0,209,190,156,13,26,201,21,111,165,67,64,180,100,145, +62,250,32,45,100,33,55,214,1,229,223,65,19,72,187,236,206,137,35,125,120, +190,201,104,105,15,190,201,212,136,136,125,246,160,137,27,83,239,171,37, +200,218,159,125,168,34,192,61,27,233,93,22,1,114,78,250,28,76,130,112,200, +93,245,164,188,207,190,204,17,49,38,109,246,160,93,8,119,185,13,153,34,173, +246,113,0,136,48,76,10,90,26,78,182,140,9,34,130,161,100,235,64,194,9,226, +44,166,1,41,221,153,226,235,118,120,121,58,72,197,209,63,71,69,76,15,34, +164,73,244,171,112,39,246,223,104,169,18,125,42,220,9,253,159,217,38,68, +159,104,134,207,236,254,201,18,36,250,134,207,236,254,201,50,36,251,68,54, +127,99,246,200,145,39,212,54,127,99,246,200,145,39,218,33,179,251,131,200, +147,234,27,63,184,81,137,62,149,110,4,254,219,237,20,98,79,165,91,129,63, +179,251,36,152,147,237,16,217,253,159,217,32,196,159,80,217,253,159,217,36, +196,159,104,134,207,236,126,217,6,36,250,134,207,236,126,217,6,36,251,68, +54,127,112,115,18,125,67,103,247,8,149,2,8,196,24,143,131,137,146,90,121, +35,162,44,140,35,102,160,226,100,235,138,89,18,102,13,10,82,68,200,151,106, +130,88,131,4,192,73,225,228,85,162,137,147,168,108,252,18,42,209,68,201, +212,54,126,89,23,104,162,100,245,17,230,207,193,34,237,20,76,158,162,60, +217,249,100,109,162,137,147,163,117,2,178,120,36,109,162,137,147,163,117,2, +178,121,100,101,162,137,147,165,91,129,63,4,140,180,81,50,116,171,112,39, +229,145,150,138,38,78,161,179,251,63,178,240,72,203,69,19,39,80,217,253, +159,217,121,100,109,162,137,147,212,71,155,63,179,251,47,4,141,180,81,50, +122,136,243,103,246,127,101,229,145,150,138,38,78,161,179,251,31,182,240, +72,203,69,19,39,80,217,253,143,219,121,100,109,162,137,147,212,71,155,63, +177,251,111,4,141,180,81,50,122,136,243,103,246,63,109,229,145,54,138,38, +78,161,179,251,133,90,40,153,61,68,121,179,251,132,196,128,31,80,217,248, +36,76,72,1,245,13,159,150,69,68,128,31,168,143,54,126,9,21,18,0,126,162,60, +217,249,100,100,72,1,244,110,160,86,79,4,140,137,0,62,141,212,10,201,229, +145,113,32,7,210,173,192,159,130,69,196,128,31,74,183,2,126,89,23,18,0,125, +67,103,246,127,101,224,145,113,32,7,212,54,127,103,246,94,89,25,18,0,126, +162,60,217,253,159,217,120,36,100,72,1,250,136,243,103,246,127,101,229,145, +113,32,7,212,54,127,99,246,222,9,23,18,0,125,67,103,246,63,109,229,145,145, +32,7,234,35,205,159,216,253,183,130,70,68,128,31,168,143,54,127,99,246,222, +89,17,18,0,125,67,103,247,9,137,0,63,81,30,108,254,224,130,115,240,98,66, +128,92,136,84,45,101,180,81,50,28,78,99,193,18,40,56,153,58,178,52,211,58, +17,46,134,133,41,34,164,75,164,104,156,52,52,199,37,222,232,206,66,64,207, +18,66,136,137,19,173,62,46,155,181,167,72,147,235,226,233,186,120,121,58, +226,157,214,111,84,76,73,36,109,24,72,130,100,112,200,178,76,157,124,92, +242,70,120,25,193,34,245,241,117,240,97,1,107,33,25,212,54,160,90,7,244,29, +24,38,66,254,223,215,125,119,215,126,232,190,43,226,67,244,1,250,193,125, +111,216,11,234,254,192,63,96,159,173,234,26,84,53,19,194,126,175,168,105, +80,212,79,8,234,26,84,53,19,193,156,20,144,83,52,167,20,52,198,109,24,18, +68,225,115,150,64,53,52,104,200,84,52,131,76,167,20,52,200,46,7,48,52,146, +132,102,57,33,165,139,168,209,154,32,104,220,193,189,214,27,16,209,176,23, +26,220,98,149,110,116,70,75,188,98,116,136,34,33,101,4,192,223,178,32,38,6, +144,18,67,72,1,58,67,0,100,95,74,17,159,217,31,210,132,103,246,58,251,33, +121,232,55,150,227,125,143,216,16,190,91,141,246,68,31,150,223,178,39,150, +223,177,251,0,244,135,97,37,32,24,132,104,24,66,161,175,164,202,134,140, +151,39,212,125,255,221,125,74,86,9,79,168,104,201,116,178,139,154,22,134, +145,72,51,93,18,116,64,145,13,39,82,34,33,38,73,76,132,185,4,185,187,198, +100,229,233,197,13,49,228,73,247,4,4,78,98,79,184,32,34,105,187,201,147, +154,185,187,200,147,165,233,197,13,50,230,239,82,98,151,167,20,52,206,145, +39,234,76,69,245,22,190,224,128,138,228,73,244,180,90,251,130,2,43,145,39, +234,76,76,243,155,51,162,68,159,88,230,204,234,145,39,234,76,67,240,38,67, +200,147,232,193,50,46,68,159,169,49,31,206,164,100,137,18,125,59,169,25,54, +68,159,169,49,51,200,109,38,73,42,68,159,88,134,210,100,147,100,73,250,147, +20,188,65,57,163,146,164,73,246,68,19,154,57,74,68,159,169,49,51,200,90, +209,34,9,205,28,159,34,79,172,66,214,137,16,78,104,228,121,18,125,154,24, +72,152,147,236,208,194,101,205,39,92,82,200,147,145,137,63,82,98,103,144, +181,162,68,19,154,57,60,196,159,88,133,173,18,32,156,209,201,166,36,253,73, +138,94,32,156,209,201,70,36,251,34,9,205,28,154,98,79,212,152,153,228,54, +147,36,148,98,79,172,67,105,50,73,102,36,253,73,136,254,117,35,36,24,147, +233,221,72,201,38,36,253,73,136,126,6,12,98,79,163,6,20,98,79,212,152,135, +224,76,135,49,39,209,130,100,89,137,63,82,98,103,156,217,157,6,36,250,199, +54,103,113,137,63,82,98,47,168,181,247,4,4,86,98,79,165,162,215,220,16,17, +57,137,62,205,12,36,166,238,173,194,2,201,217,161,132,236,167,20,52,210, +155,186,183,8,11,39,70,9,147,178,156,80,211,50,110,236,208,194,118,83,138, +26,102,77,221,24,38,78,202,113,67,76,54,186,195,245,38,34,188,17,145,23,55, +117,241,32,145,36,57,173,155,186,75,189,205,35,102,128,44,243,119,74,139, +144,113,243,221,36,77,21,38,144,210,161,168,158,35,230,144,192,154,42,77, +33,165,67,81,60,15,173,7,90,159,49,13,213,64,186,17,62,96,47,170,129,116, +33,165,64,202,113,36,226,134,70,110,234,220,32,44,157,163,222,72,244,64, +145,23,55,118,143,121,35,209,2,68,140,221,213,184,64,89,58,183,88,145,232, +129,34,46,110,234,221,98,71,162,4,136,153,80,50,156,80,211,22,79,90,38,105, +16,17,17,207,18,61,96,17,10,192,76,71,106,220,32,44,157,19,152,240,68,138, +17,193,30,137,195,39,65,51,8,224,143,65,54,22,46,103,68,112,71,162,112,200, +184,144,116,17,59,20,24,243,52,72,58,8,134,42,23,50,68,108,3,206,87,71,164, +0,142,73,57,132,41,42,72,225,107,4,167,212,52,100,191,92,83,161,163,37,250, +226,158,141,145,208,89,154,79,90,4,66,73,209,153,100,180,8,133,145,208,89, +158,36,169,35,34,17,244,145,198,247,60,137,114,26,97,57,162,4,206,137,116, +17,136,48,144,68,212,97,27,57,24,64,90,201,18,5,13,25,4,5,172,160,123,215, +138,62,46,121,35,60,117,18,233,27,70,18,32,10,200,212,75,175,139,166,233, +225,228,235,138,227,130,93,117,155,215,197,207,36,103,131,212,11,161,58, +226,186,110,234,220,32,44,157,148,226,134,153,19,119,101,56,161,166,88,156, +217,78,52,20,221,17,200,147,25,137,53,17,180,97,34,0,172,140,19,154,84,26, +145,0,86,68,90,40,152,2,178,22,160,93,8,69,19,18,98,37,210,94,100,108,144, +21,145,8,151,75,23,100,141,66,37,217,16,11,32,226,248,146,164,108,250,75, +204,141,146,28,217,24,177,33,50,66,72,128,92,6,66,161,164,235,226,231,146, +51,65,36,225,144,168,105,58,248,185,228,140,240,97,68,128,153,38,98,79,174, +179,122,248,185,228,140,241,214,129,132,150,12,73,245,214,111,95,23,60,145, +158,58,50,72,81,67,230,232,184,196,159,95,23,77,211,195,201,215,21,47,139, +166,233,225,228,50,200,211,76,229,2,201,25,149,241,67,102,138,52,146,16,30, +67,18,66,3,201,34,52,78,25,61,72,160,94,115,30,230,145,179,73,26,39,12,158, +164,81,33,144,78,25,61,72,160,94,115,30,230,145,179,72,200,39,12,158,164, +80,132,75,165,67,81,50,21,18,235,65,214,169,224,140,137,210,173,192,154,30, +8,200,157,67,102,66,84,11,71,169,20,19,209,139,162,158,207,15,39,73,24,186, +43,236,176,217,130,253,36,98,232,187,177,33,73,18,52,68,233,35,23,69,93, +136,26,98,116,145,139,162,158,146,160,95,73,24,186,37,12,72,5,16,64,145,10, +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, }; /* to convert a heap stridx to a token number, subtract * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED. */ -/* native functions: 128 */ -DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { +/* native functions: 147 */ +DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = { duk_bi_array_constructor, duk_bi_array_constructor_is_array, duk_bi_array_prototype_concat, @@ -10459,10 +12062,17 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_array_prototype_splice, duk_bi_array_prototype_to_string, duk_bi_array_prototype_unshift, + duk_bi_arraybuffer_constructor, + duk_bi_arraybuffer_isview, duk_bi_boolean_constructor, duk_bi_boolean_prototype_tostring_shared, + duk_bi_buffer_compare_shared, duk_bi_buffer_constructor, duk_bi_buffer_prototype_tostring_shared, + duk_bi_buffer_readfield, + duk_bi_buffer_slice_shared, + duk_bi_buffer_writefield, + duk_bi_dataview_constructor, duk_bi_date_constructor, duk_bi_date_constructor_now, duk_bi_date_constructor_parse, @@ -10517,6 +12127,16 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_math_object_onearg_shared, duk_bi_math_object_random, duk_bi_math_object_twoarg_shared, + duk_bi_nodejs_buffer_byte_length, + duk_bi_nodejs_buffer_concat, + duk_bi_nodejs_buffer_constructor, + duk_bi_nodejs_buffer_copy, + duk_bi_nodejs_buffer_fill, + duk_bi_nodejs_buffer_is_buffer, + duk_bi_nodejs_buffer_is_encoding, + duk_bi_nodejs_buffer_tojson, + duk_bi_nodejs_buffer_tostring, + duk_bi_nodejs_buffer_write, duk_bi_number_constructor, duk_bi_number_prototype_to_exponential, duk_bi_number_prototype_to_fixed, @@ -10571,68 +12191,96 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_thread_resume, duk_bi_thread_yield, duk_bi_type_error_thrower, + duk_bi_typedarray_constructor, + duk_bi_typedarray_set, }; -DUK_INTERNAL const duk_uint8_t duk_builtins_data[1341] = { -105,195,74,136,77,40,105,44,9,124,104,45,3,3,72,0,71,225,65,165,168,33,243, -6,145,0,122,24,210,148,14,249,35,120,160,55,226,13,76,192,196,177,164,152, -22,192,4,202,52,147,72,152,0,169,70,146,105,11,0,23,40,210,77,32,96,3,37, -26,73,163,236,0,108,163,73,52,121,128,14,148,105,38,142,176,1,242,144,56, -208,254,84,6,166,82,242,80,210,246,1,250,67,72,144,15,232,13,44,96,47,162, -52,160,128,62,80,160,255,253,102,76,7,255,128,0,0,0,0,0,3,84,7,255,0,0,0,0, -0,0,3,124,64,153,132,18,49,2,38,48,64,200,7,153,64,227,48,26,103,3,13,0,89, -165,34,53,36,38,180,128,216,143,155,81,227,114,58,111,2,142,0,73,194,94,56, -202,167,33,209,195,114,70,206,209,26,58,36,100,228,145,131,130,69,204,137, -22,51,36,84,208,145,67,82,68,205,137,18,62,36,68,240,122,32,120,62,0,2,87, -61,39,255,254,9,46,24,0,10,31,224,29,13,91,40,0,9,101,137,32,0,48,197,84, -66,214,9,10,82,68,37,81,144,133,52,65,214,137,6,90,40,0,12,21,100,144,69, -114,64,213,202,0,3,2,86,36,5,96,160,0,63,254,16,37,135,91,98,25,242,192,7, -194,248,30,236,32,123,46,17,234,186,71,162,241,5,23,240,0,15,241,1,70,74,3, -8,249,49,3,204,185,15,35,3,231,137,121,240,163,254,0,46,224,18,7,248,192, -42,249,14,3,224,20,32,0,46,208,35,231,96,41,29,96,192,117,3,159,58,66,64, -232,10,3,156,45,14,96,194,57,67,87,156,129,231,206,48,51,240,0,23,16,25, -255,255,251,132,16,209,192,8,106,0,2,223,4,53,0,2,111,2,26,128,1,183,65,13, -64,1,27,129,7,224,0,45,176,131,255,255,241,73,252,0,91,77,103,193,254,64, -36,200,64,101,31,47,32,123,188,129,178,218,70,195,113,29,173,231,206,55,3, -71,19,129,168,0,11,93,196,141,103,34,53,92,208,212,116,35,157,213,13,55, -100,52,158,16,209,108,3,65,176,12,246,192,128,0,179,155,2,0,2,205,122,3,49, -221,2,151,248,0,7,249,64,147,35,4,249,17,8,0,11,220,68,2,155,248,172,184, -15,253,255,255,255,255,255,255,236,168,0,0,0,0,0,0,0,0,44,152,15,255,0,0,0, -0,0,0,12,120,15,254,0,0,0,0,0,0,12,136,31,254,0,0,0,0,0,0,0,7,249,128,147, -32,0,0,0,0,0,0,0,0,12,249,79,35,225,52,143,117,0,49,147,8,197,75,35,17,56, -130,159,248,1,176,197,136,194,23,254,96,138,128,63,206,4,153,33,255,224,0, -0,0,0,0,2,215,200,232,24,3,161,0,1,95,142,132,0,9,240,58,16,0,53,240,232, -64,1,23,163,161,0,5,77,142,132,0,25,52,58,16,0,116,200,225,30,227,192,94, -15,1,118,48,16,0,133,208,192,64,2,87,35,1,0,10,92,12,4,0,45,110,48,16,0, -197,176,192,64,3,86,163,1,0,14,90,12,4,0,61,102,48,16,1,5,144,192,64,4,86, -35,1,0,18,88,12,4,0,77,94,48,16,1,69,112,192,64,5,85,163,1,0,22,86,12,4,0, -93,86,50,5,80,217,21,35,69,0,24,84,13,20,0,101,78,52,190,0,52,166,26,95,0, -27,82,141,63,128,14,41,6,159,192,7,84,99,83,224,3,202,33,169,240,1,245,8, -209,64,8,20,3,69,0,33,79,141,47,128,17,39,134,151,192,8,211,163,79,224,4, -137,193,167,240,2,84,192,192,64,9,146,227,69,0,39,21,31,192,0,63,208,24, -147,4,12,0,32,41,56,72,240,60,100,148,100,140,100,132,128,0,0,0,0,0,0,0,0, -210,172,228,74,52,17,242,210,1,83,252,0,3,253,33,81,132,11,69,144,24,166, -229,69,37,23,39,41,40,57,65,72,47,146,176,10,175,224,0,159,234,4,140,41,18, -44,128,192,10,191,224,0,159,235,4,140,41,10,44,128,192,10,207,224,0,159, -236,4,140,41,2,44,128,192,10,223,224,0,159,237,4,140,40,250,44,128,192,10, -239,224,0,159,238,4,140,40,242,44,128,192,10,255,224,0,159,239,4,140,40, -234,44,128,192,7,255,228,34,160,32,2,223,133,69,138,43,180,162,96,32,1,53, -216,221,218,170,139,34,32,31,243,23,33,127,125,28,247,161,224,31,251,138, -163,178,149,193,127,33,160,31,237,229,189,138,147,114,135,33,96,32,4,144, -253,170,34,22,140,33,32,31,243,80,79,51,63,157,230,160,224,31,251,80,79,51, -63,157,230,164,130,71,34,5,28,160,0,40,4,114,128,1,31,209,202,0,6,126,73, -65,245,28,160,0,135,196,114,128,2,158,209,202,0,12,122,71,40,0,57,229,28, -160,1,7,132,85,227,186,50,241,217,37,32,0,39,84,128,29,17,202,0,18,115,71, -40,0,81,201,28,160,1,103,20,114,128,6,7,255,224,4,195,63,65,193,1,130,255, -248,0,11,255,224,0,31,255,138,52,128,129,135,219,0,0,0,0,0,3,57,192,71,72, -4,229,0,29,99,140,201,72,50,31,32,196,144,131,2,49,225,121,16,240,184,132, -120,82,64,65,102,252,0,233,239,200,20,62,176,78,248,0,255,148,0,5,163,240, -0,15,249,192,9,242,38,16,0,23,184,152,5,171,240,0,15,250,64,9,242,200,16,0, -23,187,32,5,179,240,0,15,250,194,15,72,64,0,0,0,0,0,0,0,15,201,4,195,187, -126,226,4,200,68,18,162,16,72,134,60,35,67,31,0,1,25,161,143,128,1,8,144, -199,192,0,196,40,99,224,0,130,4,49,240,0,84,255,252,36,100,16,184,155,250, -226,217,150,47,46,91,249,34,224,139,229,229,203,127,36,26,119,32,203,203, -150,254,72,52,97,221,147,102,157,217,192, +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, +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, +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, +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, +12,62,16,0,184,40,248,64,3,32,131,225,0,13,129,143,132,0,58,4,62,16,0,248, +8,248,64,4,32,3,225,0,17,127,143,132,0,73,252,62,16,1,55,232,248,64,5,31, +131,225,0,21,125,143,132,0,89,244,62,16,1,119,201,0,31,4,68,123,144,148,0, +97,236,66,80,1,151,169,10,248,0,211,208,133,124,0,109,230,66,254,0,56,242, +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, +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, +255,242,27,16,16,1,111,194,162,197,21,218,90,240,16,0,154,236,110,237,85, +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,65,216,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, }; #ifdef DUK_USE_BUILTIN_INITJS DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = { @@ -10648,108 +12296,141 @@ DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = { }; #endif /* DUK_USE_BUILTIN_INITJS */ #elif defined(DUK_USE_DOUBLE_ME) -DUK_INTERNAL const duk_uint8_t duk_strings_data[1943] = { -55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,26,20,164,137, -186,50,11,164,109,77,215,5,61,35,106,3,25,110,8,22,158,130,38,163,8,217, -200,158,76,156,210,117,128,153,203,210,70,46,137,187,18,27,164,187,201,209, -130,100,55,91,70,4,145,63,66,231,44,128,105,187,41,197,13,49,122,8,196,24, -71,75,70,138,104,115,77,215,5,36,20,201,214,209,107,79,104,209,144,168,105, -6,207,251,209,104,209,125,212,227,66,127,235,191,239,232,180,90,52,95,69, -247,83,141,9,255,174,255,191,162,211,80,210,253,23,221,78,52,39,254,183, -254,254,139,72,105,126,139,238,167,26,19,255,91,255,127,69,166,129,191,69, -247,83,141,9,255,175,255,191,162,213,26,50,23,232,190,234,113,161,63,245, -115,119,86,227,118,83,138,26,98,9,110,48,86,22,148,160,152,22,82,70,46,137, -44,8,180,163,32,104,98,206,32,17,7,16,88,101,100,206,42,70,36,108,205,18, -74,140,33,196,230,60,2,152,146,33,38,230,8,36,79,182,251,65,156,151,24,200, -33,145,162,25,80,209,24,67,0,166,68,52,174,61,73,25,33,205,25,27,84,177, -195,234,220,1,144,105,99,135,217,16,17,17,208,72,199,179,60,93,100,146,49, -232,162,64,76,135,19,152,244,44,136,223,98,67,4,18,33,247,217,158,36,0,209, -190,156,13,26,201,21,111,165,67,64,180,100,145,62,250,32,45,100,33,55,214, -1,229,223,65,19,72,187,236,206,137,35,125,120,190,201,104,105,15,190,201, -212,136,136,125,246,160,137,27,83,239,171,37,200,218,159,125,168,34,192,61, -27,233,93,22,1,114,78,250,28,76,130,112,200,93,245,164,188,207,190,204,17, -49,38,109,246,160,93,8,119,185,13,153,34,96,208,165,36,85,190,206,32,17,6, -9,129,75,67,73,214,209,129,36,80,84,44,157,104,24,65,60,69,148,192,37,59, -179,60,93,110,207,15,39,73,24,186,39,232,232,169,129,228,18,6,120,146,20, -68,72,157,105,241,116,221,173,58,68,159,95,23,77,211,195,201,215,20,238, -179,122,162,98,73,35,104,194,68,19,35,134,69,146,100,235,226,231,146,51, -192,206,9,23,175,139,175,131,8,11,89,8,206,161,181,2,208,63,160,232,193,50, -23,246,254,187,235,190,187,247,69,241,95,18,31,160,15,214,11,235,126,192, -95,87,246,1,251,4,253,111,80,210,161,168,158,19,245,125,67,74,134,162,120, -71,80,210,161,168,158,12,224,164,130,153,165,56,161,166,51,104,192,146,39, -11,156,178,1,169,163,70,66,161,164,26,101,56,161,166,65,112,57,129,164,148, -35,49,201,13,44,93,70,140,209,3,70,230,13,238,176,216,134,141,128,184,214, -227,20,171,115,162,50,93,227,19,164,65,17,11,40,38,6,253,145,1,48,52,128, -146,26,64,9,210,24,3,34,250,80,140,254,200,254,148,35,63,177,215,217,11, -207,65,188,183,27,236,126,192,133,242,220,111,178,32,252,182,253,145,60, -182,253,143,216,7,164,59,9,41,0,196,35,64,194,21,13,125,38,84,52,100,185, -62,163,239,254,235,234,82,176,74,125,67,70,75,165,148,92,208,180,52,138,65, -154,232,147,162,4,136,105,58,145,17,9,50,74,100,37,200,37,205,222,51,39,47, -78,40,105,143,34,79,184,32,34,115,18,125,193,1,19,77,222,76,156,213,205, -222,68,157,47,78,40,105,151,55,122,147,20,189,56,161,166,116,137,63,82,98, -47,168,181,247,4,4,87,34,79,165,162,215,220,16,17,92,137,63,82,98,103,156, -217,157,18,36,250,199,54,103,84,137,63,82,98,31,129,50,30,68,159,70,9,145, -114,36,253,73,136,254,117,35,36,72,147,233,221,72,201,178,36,253,73,137, -158,67,105,50,73,82,36,250,196,54,147,36,155,34,79,212,152,165,226,9,205, -28,149,34,79,178,32,156,209,202,82,36,253,73,137,158,66,214,137,16,78,104, -228,249,18,125,98,22,180,72,130,115,71,35,200,147,236,208,194,68,196,159, -102,134,19,46,105,58,226,150,68,156,140,73,250,147,19,60,133,173,18,32,156, -209,201,230,36,250,196,45,104,145,4,230,142,77,49,39,234,76,82,241,4,230, -142,74,49,39,217,16,78,104,228,211,18,126,164,196,207,33,180,153,36,163,18, -125,98,27,73,146,75,49,39,234,76,71,243,169,25,32,196,159,78,234,70,73,49, -39,234,76,67,240,48,99,18,125,24,48,163,18,126,164,196,63,2,100,57,137,62, -140,19,34,204,73,250,147,19,60,230,204,232,49,39,214,57,179,59,140,73,250, -147,17,125,69,175,184,32,34,179,18,125,45,22,190,224,128,137,204,73,246, -104,97,37,55,117,110,16,22,78,205,12,39,101,56,161,166,148,221,213,184,64, -89,58,48,76,157,148,226,134,153,147,119,102,134,19,178,156,80,211,50,110, -232,193,50,118,83,138,26,97,181,214,31,169,49,21,224,140,136,185,187,175, -137,4,137,33,205,108,221,210,93,238,105,27,52,1,103,155,186,84,92,131,143, -158,233,34,104,169,52,134,149,13,68,241,31,52,134,4,209,82,105,13,42,26, -137,224,125,104,58,212,249,136,110,170,5,208,137,243,1,125,84,11,161,13,42, -6,83,137,39,20,50,51,119,86,225,1,100,237,30,242,71,162,4,136,185,187,180, -123,201,30,136,18,36,102,238,173,194,2,201,213,186,196,143,68,9,17,115,119, -86,235,18,61,16,36,68,202,129,148,226,134,152,178,122,209,51,72,128,136, -142,120,145,235,0,136,86,2,98,59,86,225,1,100,232,156,199,130,36,80,142,8, -244,78,25,58,9,152,71,4,122,9,176,177,115,58,35,130,61,19,134,69,196,131, -160,137,216,160,199,153,162,65,208,68,49,80,185,146,35,96,30,114,186,61,32, -4,114,73,204,33,73,82,71,11,88,37,62,161,163,37,250,226,157,13,25,47,215, -20,244,108,142,130,204,210,122,208,34,18,78,140,203,37,160,68,44,142,130, -204,241,37,73,25,16,143,164,142,55,185,228,75,144,211,9,205,16,38,116,75, -160,140,65,132,130,38,163,8,217,200,194,2,214,72,144,40,104,200,32,45,101, -3,222,188,81,241,115,201,25,227,168,151,72,218,48,145,0,86,70,162,93,124, -93,55,79,15,39,92,87,28,18,235,172,222,190,46,121,35,60,30,160,93,9,215,21, -211,119,86,225,1,100,236,167,20,52,200,155,187,41,197,13,50,196,230,202, -113,160,166,232,142,68,152,204,73,168,141,163,9,16,5,100,96,156,210,160, -212,136,2,178,34,209,68,192,21,144,181,2,232,66,40,152,147,17,46,146,243, -35,100,128,172,136,68,186,88,187,36,106,17,46,200,128,89,7,23,196,149,35, -103,210,94,100,108,144,230,200,197,137,9,146,18,68,2,224,50,21,13,39,95,23, -60,145,154,9,39,12,133,67,73,215,197,207,36,103,131,10,36,4,201,51,18,125, -117,155,215,197,207,36,103,142,180,12,36,176,98,79,174,179,122,248,185,228, -140,241,209,146,66,138,31,55,69,198,36,250,248,186,110,158,30,78,184,169, -124,93,55,79,15,33,150,70,154,103,40,22,72,204,175,138,27,52,81,164,144, -128,242,24,146,16,30,73,17,162,112,201,234,69,2,243,152,247,52,141,154,72, -209,56,100,245,34,137,12,130,112,201,234,69,2,243,152,247,52,141,154,70,65, -56,100,245,34,132,34,93,42,26,137,144,168,151,90,14,181,79,4,100,78,149, -110,4,208,240,70,68,234,27,50,18,160,90,61,72,160,158,140,93,20,246,120, -121,58,72,197,209,95,101,134,204,23,233,35,23,69,221,137,10,72,145,162,39, -73,24,186,42,236,64,211,19,164,140,93,20,244,149,2,250,72,197,209,40,98,64, -40,130,4,136,81,2,98,58,4,230,205,13,161,16,50,6,134,49,34,113,144,160,162, -230,97,145,100,153,4,55,16,139,145,14,84,52,11,94,6,87,69,5,163,69,52,57, -162,65,68,134,169,13,148,192,209,17,197,27,73,99,68,147,164,90,105,89,19, -17,201,51,162,69,153,226,235,14,113,193,167,135,145,197,29,65,18,85,200,25, -108,116,44,132,178,38,114,137,96,148,138,39,54,83,33,27,70,24,151,123,163, -51,146,243,35,71,35,33,143,116,102,89,81,228,137,27,69,172,147,141,8,82, -129,114,34,144,199,172,140,35,103,36,161,179,36,74,1,16,107,36,206,240,9, -64,49,14,248,162,160,153,18,248,186,100,20,200,51,62,129,90,4,105,76,19,64, -139,132,17,99, +DUK_INTERNAL const duk_uint8_t duk_strings_data[2624] = { +55,86,227,24,145,55,102,120,144,3,63,94,228,54,100,137,186,50,11,164,109, +77,215,5,61,35,106,206,149,110,4,254,219,237,58,8,196,24,103,74,183,2,127, +103,246,93,4,98,12,47,180,67,103,246,127,101,208,70,32,194,186,134,207,236, +254,203,160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253, +143,219,116,17,136,49,30,209,13,159,220,116,75,3,30,65,244,17,136,48,174, +209,13,159,220,116,17,136,48,158,161,179,251,142,130,49,6,17,209,130,96, +237,80,75,47,160,140,65,142,134,133,41,34,110,134,133,41,34,3,25,110,8,22, +158,130,38,163,8,217,200,158,76,156,210,117,128,153,203,210,70,46,137,187, +18,27,164,187,201,209,130,100,55,91,70,4,145,63,66,231,44,128,105,187,41, +197,13,49,122,8,196,24,71,75,70,138,104,115,77,215,5,36,20,201,214,209,107, +79,104,209,144,168,105,6,207,251,209,104,209,125,212,227,66,127,235,191, +239,232,180,90,52,95,69,247,83,141,9,255,174,255,191,162,211,80,210,253,23, +221,78,52,39,254,183,254,254,139,72,105,126,139,238,167,26,19,255,91,255, +127,69,166,129,191,69,247,83,141,9,255,175,255,191,162,213,26,50,23,232, +190,234,113,161,63,245,115,119,86,227,118,83,138,26,98,9,110,48,86,22,148, +160,152,22,82,70,46,137,44,8,180,163,32,104,98,206,32,17,7,16,88,101,100, +206,42,70,36,108,205,18,74,140,33,196,230,60,2,152,146,33,38,230,8,36,79, +182,251,65,156,151,24,200,33,145,162,25,80,209,24,67,0,166,68,52,174,61,73, +25,33,205,25,27,84,177,195,234,220,1,144,105,99,135,217,16,17,17,208,72, +199,179,60,93,100,146,49,232,162,64,76,135,19,152,244,44,136,223,98,67,4, +18,33,247,217,158,36,0,209,190,156,13,26,201,21,111,165,67,64,180,100,145, +62,250,32,45,100,33,55,214,1,229,223,65,19,72,187,236,206,137,35,125,120, +190,201,104,105,15,190,201,212,136,136,125,246,160,137,27,83,239,171,37, +200,218,159,125,168,34,192,61,27,233,93,22,1,114,78,250,28,76,130,112,200, +93,245,164,188,207,190,204,17,49,38,109,246,160,93,8,119,185,13,153,34,173, +246,113,0,136,48,76,10,90,26,78,182,140,9,34,130,161,100,235,64,194,9,226, +44,166,1,41,221,153,226,235,118,120,121,58,72,197,209,63,71,69,76,15,34, +164,73,244,171,112,39,246,223,104,169,18,125,42,220,9,253,159,217,38,68, +159,104,134,207,236,254,201,18,36,250,134,207,236,254,201,50,36,251,68,54, +127,99,246,200,145,39,212,54,127,99,246,200,145,39,218,33,179,251,131,200, +147,234,27,63,184,81,137,62,149,110,4,254,219,237,20,98,79,165,91,129,63, +179,251,36,152,147,237,16,217,253,159,217,32,196,159,80,217,253,159,217,36, +196,159,104,134,207,236,126,217,6,36,250,134,207,236,126,217,6,36,251,68, +54,127,112,115,18,125,67,103,247,8,149,2,8,196,24,143,131,137,146,90,121, +35,162,44,140,35,102,160,226,100,235,138,89,18,102,13,10,82,68,200,151,106, +130,88,131,4,192,73,225,228,85,162,137,147,168,108,252,18,42,209,68,201, +212,54,126,89,23,104,162,100,245,17,230,207,193,34,237,20,76,158,162,60, +217,249,100,109,162,137,147,163,117,2,178,120,36,109,162,137,147,163,117,2, +178,121,100,101,162,137,147,165,91,129,63,4,140,180,81,50,116,171,112,39, +229,145,150,138,38,78,161,179,251,63,178,240,72,203,69,19,39,80,217,253, +159,217,121,100,109,162,137,147,212,71,155,63,179,251,47,4,141,180,81,50, +122,136,243,103,246,127,101,229,145,150,138,38,78,161,179,251,31,182,240, +72,203,69,19,39,80,217,253,143,219,121,100,109,162,137,147,212,71,155,63, +177,251,111,4,141,180,81,50,122,136,243,103,246,63,109,229,145,54,138,38, +78,161,179,251,133,90,40,153,61,68,121,179,251,132,196,128,31,80,217,248, +36,76,72,1,245,13,159,150,69,68,128,31,168,143,54,126,9,21,18,0,126,162,60, +217,249,100,100,72,1,244,110,160,86,79,4,140,137,0,62,141,212,10,201,229, +145,113,32,7,210,173,192,159,130,69,196,128,31,74,183,2,126,89,23,18,0,125, +67,103,246,127,101,224,145,113,32,7,212,54,127,103,246,94,89,25,18,0,126, +162,60,217,253,159,217,120,36,100,72,1,250,136,243,103,246,127,101,229,145, +113,32,7,212,54,127,99,246,222,9,23,18,0,125,67,103,246,63,109,229,145,145, +32,7,234,35,205,159,216,253,183,130,70,68,128,31,168,143,54,127,99,246,222, +89,17,18,0,125,67,103,247,9,137,0,63,81,30,108,254,224,130,115,240,98,66, +128,92,136,84,45,101,180,81,50,28,78,99,193,18,40,56,153,58,178,52,211,58, +17,46,134,133,41,34,164,75,164,104,156,52,52,199,37,222,232,206,66,64,207, +18,66,136,137,19,173,62,46,155,181,167,72,147,235,226,233,186,120,121,58, +226,157,214,111,84,76,73,36,109,24,72,130,100,112,200,178,76,157,124,92, +242,70,120,25,193,34,245,241,117,240,97,1,107,33,25,212,54,160,90,7,244,29, +24,38,66,254,223,215,125,119,215,126,232,190,43,226,67,244,1,250,193,125, +111,216,11,234,254,192,63,96,159,173,234,26,84,53,19,194,126,175,168,105, +80,212,79,8,234,26,84,53,19,193,156,20,144,83,52,167,20,52,198,109,24,18, +68,225,115,150,64,53,52,104,200,84,52,131,76,167,20,52,200,46,7,48,52,146, +132,102,57,33,165,139,168,209,154,32,104,220,193,189,214,27,16,209,176,23, +26,220,98,149,110,116,70,75,188,98,116,136,34,33,101,4,192,223,178,32,38,6, +144,18,67,72,1,58,67,0,100,95,74,17,159,217,31,210,132,103,246,58,251,33, +121,232,55,150,227,125,143,216,16,190,91,141,246,68,31,150,223,178,39,150, +223,177,251,0,244,135,97,37,32,24,132,104,24,66,161,175,164,202,134,140, +151,39,212,125,255,221,125,74,86,9,79,168,104,201,116,178,139,154,22,134, +145,72,51,93,18,116,64,145,13,39,82,34,33,38,73,76,132,185,4,185,187,198, +100,229,233,197,13,49,228,73,247,4,4,78,98,79,184,32,34,105,187,201,147, +154,185,187,200,147,165,233,197,13,50,230,239,82,98,151,167,20,52,206,145, +39,234,76,69,245,22,190,224,128,138,228,73,244,180,90,251,130,2,43,145,39, +234,76,76,243,155,51,162,68,159,88,230,204,234,145,39,234,76,67,240,38,67, +200,147,232,193,50,46,68,159,169,49,31,206,164,100,137,18,125,59,169,25,54, +68,159,169,49,51,200,109,38,73,42,68,159,88,134,210,100,147,100,73,250,147, +20,188,65,57,163,146,164,73,246,68,19,154,57,74,68,159,169,49,51,200,90, +209,34,9,205,28,159,34,79,172,66,214,137,16,78,104,228,121,18,125,154,24, +72,152,147,236,208,194,101,205,39,92,82,200,147,145,137,63,82,98,103,144, +181,162,68,19,154,57,60,196,159,88,133,173,18,32,156,209,201,166,36,253,73, +138,94,32,156,209,201,70,36,251,34,9,205,28,154,98,79,212,152,153,228,54, +147,36,148,98,79,172,67,105,50,73,102,36,253,73,136,254,117,35,36,24,147, +233,221,72,201,38,36,253,73,136,126,6,12,98,79,163,6,20,98,79,212,152,135, +224,76,135,49,39,209,130,100,89,137,63,82,98,103,156,217,157,6,36,250,199, +54,103,113,137,63,82,98,47,168,181,247,4,4,86,98,79,165,162,215,220,16,17, +57,137,62,205,12,36,166,238,173,194,2,201,217,161,132,236,167,20,52,210, +155,186,183,8,11,39,70,9,147,178,156,80,211,50,110,236,208,194,118,83,138, +26,102,77,221,24,38,78,202,113,67,76,54,186,195,245,38,34,188,17,145,23,55, +117,241,32,145,36,57,173,155,186,75,189,205,35,102,128,44,243,119,74,139, +144,113,243,221,36,77,21,38,144,210,161,168,158,35,230,144,192,154,42,77, +33,165,67,81,60,15,173,7,90,159,49,13,213,64,186,17,62,96,47,170,129,116, +33,165,64,202,113,36,226,134,70,110,234,220,32,44,157,163,222,72,244,64, +145,23,55,118,143,121,35,209,2,68,140,221,213,184,64,89,58,183,88,145,232, +129,34,46,110,234,221,98,71,162,4,136,153,80,50,156,80,211,22,79,90,38,105, +16,17,17,207,18,61,96,17,10,192,76,71,106,220,32,44,157,19,152,240,68,138, +17,193,30,137,195,39,65,51,8,224,143,65,54,22,46,103,68,112,71,162,112,200, +184,144,116,17,59,20,24,243,52,72,58,8,134,42,23,50,68,108,3,206,87,71,164, +0,142,73,57,132,41,42,72,225,107,4,167,212,52,100,191,92,83,161,163,37,250, +226,158,141,145,208,89,154,79,90,4,66,73,209,153,100,180,8,133,145,208,89, +158,36,169,35,34,17,244,145,198,247,60,137,114,26,97,57,162,4,206,137,116, +17,136,48,144,68,212,97,27,57,24,64,90,201,18,5,13,25,4,5,172,160,123,215, +138,62,46,121,35,60,117,18,233,27,70,18,32,10,200,212,75,175,139,166,233, +225,228,235,138,227,130,93,117,155,215,197,207,36,103,131,212,11,161,58, +226,186,110,234,220,32,44,157,148,226,134,153,19,119,101,56,161,166,88,156, +217,78,52,20,221,17,200,147,25,137,53,17,180,97,34,0,172,140,19,154,84,26, +145,0,86,68,90,40,152,2,178,22,160,93,8,69,19,18,98,37,210,94,100,108,144, +21,145,8,151,75,23,100,141,66,37,217,16,11,32,226,248,146,164,108,250,75, +204,141,146,28,217,24,177,33,50,66,72,128,92,6,66,161,164,235,226,231,146, +51,65,36,225,144,168,105,58,248,185,228,140,240,97,68,128,153,38,98,79,174, +179,122,248,185,228,140,241,214,129,132,150,12,73,245,214,111,95,23,60,145, +158,58,50,72,81,67,230,232,184,196,159,95,23,77,211,195,201,215,21,47,139, +166,233,225,228,50,200,211,76,229,2,201,25,149,241,67,102,138,52,146,16,30, +67,18,66,3,201,34,52,78,25,61,72,160,94,115,30,230,145,179,73,26,39,12,158, +164,81,33,144,78,25,61,72,160,94,115,30,230,145,179,72,200,39,12,158,164, +80,132,75,165,67,81,50,21,18,235,65,214,169,224,140,137,210,173,192,154,30, +8,200,157,67,102,66,84,11,71,169,20,19,209,139,162,158,207,15,39,73,24,186, +43,236,176,217,130,253,36,98,232,187,177,33,73,18,52,68,233,35,23,69,93, +136,26,98,116,145,139,162,158,146,160,95,73,24,186,37,12,72,5,16,64,145,10, +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, }; /* to convert a heap stridx to a token number, subtract * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED. */ -/* native functions: 128 */ -DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { +/* native functions: 147 */ +DUK_INTERNAL const duk_c_function duk_bi_native_functions[147] = { duk_bi_array_constructor, duk_bi_array_constructor_is_array, duk_bi_array_prototype_concat, @@ -10766,10 +12447,17 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_array_prototype_splice, duk_bi_array_prototype_to_string, duk_bi_array_prototype_unshift, + duk_bi_arraybuffer_constructor, + duk_bi_arraybuffer_isview, duk_bi_boolean_constructor, duk_bi_boolean_prototype_tostring_shared, + duk_bi_buffer_compare_shared, duk_bi_buffer_constructor, duk_bi_buffer_prototype_tostring_shared, + duk_bi_buffer_readfield, + duk_bi_buffer_slice_shared, + duk_bi_buffer_writefield, + duk_bi_dataview_constructor, duk_bi_date_constructor, duk_bi_date_constructor_now, duk_bi_date_constructor_parse, @@ -10824,6 +12512,16 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_math_object_onearg_shared, duk_bi_math_object_random, duk_bi_math_object_twoarg_shared, + duk_bi_nodejs_buffer_byte_length, + duk_bi_nodejs_buffer_concat, + duk_bi_nodejs_buffer_constructor, + duk_bi_nodejs_buffer_copy, + duk_bi_nodejs_buffer_fill, + duk_bi_nodejs_buffer_is_buffer, + duk_bi_nodejs_buffer_is_encoding, + duk_bi_nodejs_buffer_tojson, + duk_bi_nodejs_buffer_tostring, + duk_bi_nodejs_buffer_write, duk_bi_number_constructor, duk_bi_number_prototype_to_exponential, duk_bi_number_prototype_to_fixed, @@ -10878,68 +12576,97 @@ DUK_INTERNAL const duk_c_function duk_bi_native_functions[128] = { duk_bi_thread_resume, duk_bi_thread_yield, duk_bi_type_error_thrower, + duk_bi_typedarray_constructor, + duk_bi_typedarray_set, }; -DUK_INTERNAL const duk_uint8_t duk_builtins_data[1341] = { -105,195,74,136,77,40,105,44,9,124,104,45,3,3,72,0,71,225,65,165,168,33,243, -6,145,0,122,24,210,148,14,249,35,120,160,55,226,13,76,192,196,177,164,152, -22,192,4,202,52,147,72,152,0,169,70,146,105,11,0,23,40,210,77,32,96,3,37, -26,73,163,236,0,108,163,73,52,121,128,14,148,105,38,142,176,1,242,144,56, -208,254,84,6,166,82,242,80,210,246,1,250,67,72,144,15,232,13,44,96,47,162, -52,160,128,62,80,160,255,253,102,76,0,0,15,135,240,0,0,0,3,84,0,0,15,7,240, -0,0,0,3,124,64,153,132,18,49,2,38,48,64,200,7,153,64,227,48,26,103,3,13,0, -89,165,34,53,36,38,180,128,216,143,155,81,227,114,58,111,2,142,0,73,194,94, -56,202,167,33,209,195,114,70,206,209,26,58,36,100,228,145,131,130,69,204, -137,22,51,36,84,208,145,67,82,68,205,137,18,62,36,68,240,122,32,120,62,0,2, -87,61,39,255,254,9,46,24,0,10,31,224,29,13,91,40,0,9,101,137,32,0,48,197, -84,66,214,9,10,82,68,37,81,144,133,52,65,214,137,6,90,40,0,12,21,100,144, -69,114,64,213,202,0,3,2,86,36,5,96,160,0,63,254,16,37,135,91,98,25,242,192, -7,194,248,30,236,32,123,46,17,234,186,71,162,241,5,23,240,0,15,241,1,70,74, -3,8,249,49,3,204,185,15,35,3,231,137,121,240,163,254,0,46,224,18,7,248,192, -42,249,14,3,224,20,32,0,46,208,35,231,96,41,29,96,192,117,3,159,58,66,64, -232,10,3,156,45,14,96,194,57,67,87,156,129,231,206,48,51,240,0,23,16,25, -255,255,251,132,16,209,192,8,106,0,2,223,4,53,0,2,111,2,26,128,1,183,65,13, -64,1,27,129,7,224,0,45,176,131,255,255,241,73,252,0,91,77,103,193,254,64, -36,200,64,101,31,47,32,123,188,129,178,218,70,195,113,29,173,231,206,55,3, -71,19,129,168,0,11,93,196,141,103,34,53,92,208,212,116,35,157,213,13,55, -100,52,158,16,209,108,3,65,176,12,246,192,128,0,179,155,2,0,2,205,122,3,49, -221,2,151,248,0,7,249,64,147,35,4,249,17,8,0,11,220,68,2,155,248,172,184, -31,255,253,239,255,255,255,255,236,168,0,0,0,0,0,32,0,0,12,152,0,0,31,15, -224,0,0,0,12,120,0,0,30,15,224,0,0,0,12,136,0,0,30,31,224,0,0,0,0,7,249, -128,147,32,0,0,0,0,0,0,0,0,12,249,79,35,225,52,143,117,0,49,147,8,197,75, -35,17,56,130,159,248,1,176,197,136,194,23,254,96,138,128,63,206,4,153,32,0, -3,225,252,0,0,0,2,215,200,232,24,3,161,0,1,95,142,132,0,9,240,58,16,0,53, -240,232,64,1,23,163,161,0,5,77,142,132,0,25,52,58,16,0,116,200,225,30,227, -192,94,15,1,118,48,16,0,133,208,192,64,2,87,35,1,0,10,92,12,4,0,45,110,48, -16,0,197,176,192,64,3,86,163,1,0,14,90,12,4,0,61,102,48,16,1,5,144,192,64, -4,86,35,1,0,18,88,12,4,0,77,94,48,16,1,69,112,192,64,5,85,163,1,0,22,86,12, -4,0,93,86,50,5,80,217,21,35,69,0,24,84,13,20,0,101,78,52,190,0,52,166,26, -95,0,27,82,141,63,128,14,41,6,159,192,7,84,99,83,224,3,202,33,169,240,1, -245,8,209,64,8,20,3,69,0,33,79,141,47,128,17,39,134,151,192,8,211,163,79, -224,4,137,193,167,240,2,84,192,192,64,9,146,227,69,0,39,21,31,192,0,63,208, -24,147,4,12,0,32,41,56,72,240,60,100,148,100,140,100,132,128,0,0,0,0,0,0,0, -0,210,172,228,74,52,17,242,210,1,83,252,0,3,253,33,81,132,11,69,144,24,166, -229,69,37,23,39,41,40,57,65,72,47,146,176,10,175,224,0,159,234,4,140,41,18, -44,128,192,10,191,224,0,159,235,4,140,41,10,44,128,192,10,207,224,0,159, -236,4,140,41,2,44,128,192,10,223,224,0,159,237,4,140,40,250,44,128,192,10, -239,224,0,159,238,4,140,40,242,44,128,192,10,255,224,0,159,239,4,140,40, -234,44,128,192,7,255,228,34,160,5,95,130,160,52,171,138,69,162,96,88,181, -129,32,11,42,218,221,162,32,33,23,115,31,247,156,253,127,33,224,35,138,251, -159,255,65,21,178,161,160,61,229,237,159,135,114,147,10,161,96,125,144,132, -160,12,22,162,42,33,32,79,80,115,31,230,157,191,179,32,224,79,80,123,31, -230,157,191,179,36,130,71,34,5,28,160,0,40,4,114,128,1,31,209,202,0,6,126, -73,65,245,28,160,0,135,196,114,128,2,158,209,202,0,12,122,71,40,0,57,229, -28,160,1,7,132,85,227,186,50,241,217,37,32,0,39,84,128,29,17,202,0,18,115, -71,40,0,81,201,28,160,1,103,20,114,128,6,7,255,224,4,195,63,65,193,1,130, -255,248,0,11,255,224,0,31,255,138,52,129,1,219,134,128,0,0,0,0,3,57,192,71, -72,4,229,0,29,99,140,201,72,50,31,32,196,144,131,2,49,225,121,16,240,184, -132,120,82,64,65,102,252,0,233,239,200,20,62,176,78,248,0,255,148,0,5,163, -240,0,15,249,192,9,242,38,16,0,23,184,152,5,171,240,0,15,250,64,9,242,200, -16,0,23,187,32,5,179,240,0,15,250,194,15,72,0,0,0,64,0,0,0,0,15,201,4,195, -187,126,226,4,200,68,18,162,16,72,134,60,35,67,31,0,1,25,161,143,128,1,8, -144,199,192,0,196,40,99,224,0,130,4,49,240,0,84,255,252,36,100,16,184,155, -250,226,217,150,47,46,91,249,34,224,139,229,229,203,127,36,26,119,32,203, -203,150,254,72,52,97,221,147,102,157,217,192, +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, +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, +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, +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, +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, +12,62,16,0,184,40,248,64,3,32,131,225,0,13,129,143,132,0,58,4,62,16,0,248, +8,248,64,4,32,3,225,0,17,127,143,132,0,73,252,62,16,1,55,232,248,64,5,31, +131,225,0,21,125,143,132,0,89,244,62,16,1,119,201,0,31,4,68,123,144,148,0, +97,236,66,80,1,151,169,10,248,0,211,208,133,124,0,109,230,66,254,0,56,242, +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, +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, +255,242,27,16,2,175,193,80,26,85,197,34,218,240,44,90,192,144,5,149,109, +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,1,220,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, }; #ifdef DUK_USE_BUILTIN_INITJS DUK_INTERNAL const duk_uint8_t duk_initjs_data[187] = { @@ -11126,6 +12853,28 @@ DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) { } } +#if defined(DUK_USE_ASSERTIONS) +DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) { + duk_uint_fast32_t x = (duk_uint_fast32_t) cp; + if (x < 0x80UL) { + /* 7 bits */ + return 1; + } else if (x < 0x800UL) { + /* 11 bits */ + return 2; + } else if (x < 0x10000UL) { + /* 16 bits */ + return 3; + } else { + /* Encoded as surrogate pair, each encoding to 3 bytes for + * 6 bytes total. Codepoints above U+10FFFF encode as 6 bytes + * too, see duk_unicode_encode_cesu8(). + */ + return 3 + 3; + } +} +#endif /* DUK_USE_ASSERTIONS */ + DUK_INTERNAL duk_uint8_t duk_unicode_xutf8_markers[7] = { 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe }; @@ -11753,7 +13502,7 @@ DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) { DUK_LOCAL duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, - duk_hbuffer_dynamic *buf, + duk_bufwriter_ctx *bw, duk_codepoint_t cp, duk_bitdecoder_ctx *bd_ctx) { duk_small_int_t skip = 0; @@ -11764,6 +13513,9 @@ duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, duk_codepoint_t start_i; duk_codepoint_t start_o; + DUK_UNREF(thr); + DUK_ASSERT(bd_ctx != NULL); + DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp)); /* range conversion with a "skip" */ @@ -11819,11 +13571,10 @@ duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t)); if (cp == start_i) { DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint")); - if (buf) { + if (bw != NULL) { while (t--) { tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16); - DUK_ASSERT(buf != NULL); - duk_hbuffer_append_xutf8(thr, buf, (duk_ucodepoint_t) tmp_cp); + DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp); } } return -1; @@ -11839,8 +13590,8 @@ duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, /* fall through */ single: - if (buf) { - duk_hbuffer_append_xutf8(thr, buf, cp); + if (bw != NULL) { + DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp); } return cp; } @@ -11857,7 +13608,7 @@ duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, */ DUK_LOCAL duk_codepoint_t duk__case_transform_helper(duk_hthread *thr, - duk_hbuffer_dynamic *buf, + duk_bufwriter_ctx *bw, duk_codepoint_t cp, duk_codepoint_t prev, duk_codepoint_t next, @@ -11881,7 +13632,11 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr, cp = cp - 'A' + 'a'; } } - goto singlechar; + + if (bw != NULL) { + DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp); + } + return cp; } /* context and locale specific rules which cannot currently be represented @@ -11922,11 +13677,11 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr, bd_ctx.data = (duk_uint8_t *) duk_unicode_caseconv_lc; bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc); } - return duk__slow_case_conversion(thr, buf, cp, &bd_ctx); + return duk__slow_case_conversion(thr, bw, cp, &bd_ctx); singlechar: - if (buf) { - duk_hbuffer_append_xutf8(thr, buf, cp); + if (bw != NULL) { + DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp); } return cp; @@ -11944,20 +13699,16 @@ duk_codepoint_t duk__case_transform_helper(duk_hthread *thr, DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_int_t uppercase) { duk_context *ctx = (duk_context *) thr; duk_hstring *h_input; - duk_hbuffer_dynamic *h_buf; + duk_bufwriter_ctx bw_alloc; + duk_bufwriter_ctx *bw; const duk_uint8_t *p, *p_start, *p_end; duk_codepoint_t prev, curr, next; h_input = duk_require_hstring(ctx, -1); DUK_ASSERT(h_input != NULL); - /* XXX: should init the buffer with a spare of at least h_input->blen - * to avoid unnecessary growth steps. - */ - duk_push_dynamic_buffer(ctx, 0); - h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf)); + bw = &bw_alloc; + DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* [ ... input buffer ] */ @@ -11983,9 +13734,15 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_in /* on first round, skip */ if (curr >= 0) { - /* may generate any number of output codepoints */ + /* XXX: could add a fast path to process chunks of input codepoints, + * but relative benefit would be quite small. + */ + + /* Ensure space for maximum multi-character result; estimate is overkill. */ + DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH); + duk__case_transform_helper(thr, - h_buf, + bw, (duk_codepoint_t) curr, prev, next, @@ -11993,6 +13750,7 @@ DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_in } } + DUK_BW_COMPACT(thr, bw); duk_to_string(ctx, -1); /* invalidates h_buf pointer */ duk_remove(ctx, -2); } @@ -12010,7 +13768,7 @@ DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t y; y = duk__case_transform_helper(thr, - NULL, /* buf */ + NULL, /* NULL is allowed, no output */ cp, /* curr char */ -1, /* prev char */ -1, /* next char */ @@ -12252,7 +14010,6 @@ DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) { /* include removed: duk_internal.h */ -/* Maybe better to check these elsewhere */ #if (DUK_STRIDX_UC_ARGUMENTS > 255) #error constant too large #endif @@ -12292,6 +14049,54 @@ DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) { #if (DUK_STRIDX_GLOBAL > 255) #error constant too large #endif +#if (DUK_STRIDX_OBJ_ENV > 255) +#error constant too large +#endif +#if (DUK_STRIDX_DEC_ENV > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UC_BUFFER > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UC_POINTER > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UC_THREAD > 255) +#error constant too large +#endif +#if (DUK_STRIDX_ARRAY_BUFFER > 255) +#error constant too large +#endif +#if (DUK_STRIDX_DATA_VIEW > 255) +#error constant too large +#endif +#if (DUK_STRIDX_INT8_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UINT8_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_INT16_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UINT16_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_INT32_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_UINT32_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_FLOAT32_ARRAY > 255) +#error constant too large +#endif +#if (DUK_STRIDX_FLOAT64_ARRAY > 255) +#error constant too large +#endif #if (DUK_STRIDX_EMPTY_STRING > 255) #error constant too large #endif @@ -12316,18 +14121,18 @@ DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = { DUK_STRIDX_DEC_ENV, DUK_STRIDX_UC_BUFFER, DUK_STRIDX_UC_POINTER, - DUK_STRIDX_UC_THREAD, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ - DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ + DUK_STRIDX_UC_THREAD, + DUK_STRIDX_ARRAY_BUFFER, + DUK_STRIDX_DATA_VIEW, + DUK_STRIDX_INT8_ARRAY, + DUK_STRIDX_UINT8_ARRAY, + DUK_STRIDX_UINT8_CLAMPED_ARRAY, + DUK_STRIDX_INT16_ARRAY, + DUK_STRIDX_UINT16_ARRAY, + DUK_STRIDX_INT32_ARRAY, + DUK_STRIDX_UINT32_ARRAY, + DUK_STRIDX_FLOAT32_ARRAY, + DUK_STRIDX_FLOAT64_ARRAY, DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */ }; @@ -12375,7 +14180,7 @@ DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size duk_hthread *thr = (duk_hthread *) ctx; duk_hbuffer_dynamic *h; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index); DUK_ASSERT(h != NULL); @@ -12385,10 +14190,764 @@ DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size } /* maximum size check is handled by callee */ - duk_hbuffer_resize(thr, h, new_size, new_size); /* snug */ + duk_hbuffer_resize(thr, h, new_size); return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h); } + +DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { + duk_hthread *thr = (duk_hthread *) ctx; + duk_hbuffer_dynamic *h; + void *ptr; + duk_size_t sz; + + DUK_ASSERT(ctx != NULL); + + h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index); + DUK_ASSERT(h != NULL); + + if (!DUK_HBUFFER_HAS_DYNAMIC(h)) { + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_BUFFER_NOT_DYNAMIC); + } + + /* Forget the previous allocation, setting size to 0 and alloc to + * NULL. Caller is responsible for freeing the previous allocation. + * Getting the allocation and clearing it is done in the same API + * call to avoid any chance of a realloc. + */ + ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h); + sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h); + if (out_size) { + *out_size = sz; + } + DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h); + DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0); + + return ptr; +} +#line 1 "duk_api_bytecode.c" +/* + * Bytecode dump/load + * + * The bytecode load primitive is more important performance-wise than the + * dump primitive. + * + * Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be + * memory safe for invalid arguments - caller beware! There's little point + * in trying to achieve memory safety unless bytecode instructions are also + * validated which is not easy to do with indirect register references etc. + */ + +/* include removed: duk_internal.h */ + +#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT) + +#define DUK__SER_MARKER 0xff +#define DUK__SER_VERSION 0x00 +#define DUK__SER_STRING 0x00 +#define DUK__SER_NUMBER 0x01 +#define DUK__BYTECODE_INITIAL_ALLOC 256 + +/* + * Dump/load helpers, xxx_raw() helpers do no buffer checks + */ + +DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) { + duk_uint32_t len; + + len = DUK_RAW_READ_U32_BE(p); + duk_push_lstring(ctx, (const char *) p, len); + p += len; + return p; +} + +DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) { + duk_uint32_t len; + duk_uint8_t *buf; + + len = DUK_RAW_READ_U32_BE(p); + buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); + DUK_ASSERT(buf != NULL); + DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len); + p += len; + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) { + duk_size_t len; + duk_uint32_t tmp32; + + DUK_ASSERT(h != NULL); + + len = DUK_HSTRING_GET_BYTELEN(h); + DUK_ASSERT(len <= 0xffffffffUL); /* string limits */ + tmp32 = (duk_uint32_t) len; + DUK_RAW_WRITE_U32_BE(p, tmp32); + DUK_MEMCPY((void *) p, + (const void *) DUK_HSTRING_GET_DATA(h), + len); + p += len; + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) { + duk_size_t len; + duk_uint32_t tmp32; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(h != NULL); + DUK_UNREF(thr); + + len = DUK_HBUFFER_GET_SIZE(h); + DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */ + tmp32 = (duk_uint32_t) len; + DUK_RAW_WRITE_U32_BE(p, tmp32); + DUK_MEMCPY((void *) p, + (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h), + len); + p += len; + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) { + duk_hstring *h_str; + duk_tval *tv; + + tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx)); + if (tv != NULL && DUK_TVAL_IS_STRING(tv)) { + h_str = DUK_TVAL_GET_STRING(tv); + DUK_ASSERT(h_str != NULL); + } else { + h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr); + DUK_ASSERT(h_str != NULL); + } + DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p); + p = duk__dump_hstring_raw(p, h_str); + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) { + duk_tval *tv; + + tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx)); + if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) { + duk_hbuffer *h_buf; + h_buf = DUK_TVAL_GET_BUFFER(tv); + DUK_ASSERT(h_buf != NULL); + DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p); + p = duk__dump_hbuffer_raw(thr, p, h_buf); + } else { + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); + DUK_RAW_WRITE_U32_BE(p, 0); + } + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value) { + duk_tval *tv; + duk_uint32_t val; + + tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx)); + if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) { + val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv); + } else { + val = def_value; + } + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); + DUK_RAW_WRITE_U32_BE(p, val); + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) { + duk_tval *tv; + + tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr)); + if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) { + duk_hobject *h; + duk_uint_fast32_t i; + + h = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h != NULL); + + /* We know _Varmap only has own properties so walk property + * table directly. We also know _Varmap is dense and all + * values are numbers; assert for these. GC and finalizers + * shouldn't affect _Varmap so side effects should be fine. + */ + for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) { + duk_hstring *key; + duk_tval *tv_val; + duk_uint32_t val; + + key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i); + DUK_ASSERT(key != NULL); /* _Varmap is dense */ + DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)); + tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i); + DUK_ASSERT(tv_val != NULL); + DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */ +#if defined(DUK_USE_FASTINT) + DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val)); + DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */ + val = DUK_TVAL_GET_FASTINT_U32(tv_val); +#else + val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val); +#endif + + DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p); + p = duk__dump_hstring_raw(p, key); + DUK_RAW_WRITE_U32_BE(p, val); + } + } + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); + DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Varmap */ + return p; +} + +DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) { + duk_tval *tv; + + tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr)); + if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) { + duk_hobject *h; + duk_uint_fast32_t i; + + h = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h != NULL); + + /* We know _Formals is dense and all entries will be in the + * array part. GC and finalizers shouldn't affect _Formals + * so side effects should be fine. + */ + for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) { + duk_tval *tv_val; + duk_hstring *varname; + + tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i); + DUK_ASSERT(tv_val != NULL); + if (DUK_TVAL_IS_STRING(tv_val)) { + /* Array is dense and contains only strings, but ASIZE may + * be larger than used part and there are UNUSED entries. + */ + varname = DUK_TVAL_GET_STRING(tv_val); + DUK_ASSERT(varname != NULL); + + DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p); + p = duk__dump_hstring_raw(p, varname); + } + } + } + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p); + DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Formals */ + return p; +} + +static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) { + duk_hthread *thr; + duk_tval *tv, *tv_end; + duk_instr_t *ins, *ins_end; + duk_hobject **fn, **fn_end; + duk_hstring *h_str; + duk_uint32_t count_instr; + duk_uint32_t tmp32; + duk_uint16_t tmp16; + duk_double_t d; + + thr = (duk_hthread *) ctx; + DUK_UNREF(ctx); + DUK_UNREF(thr); + + DUK_DD(DUK_DDPRINT("dumping function %p to %p: " + "consts=[%p,%p[ (%ld bytes, %ld items), " + "funcs=[%p,%p[ (%ld bytes, %ld items), " + "code=[%p,%p[ (%ld bytes, %ld items)", + (void *) func, + (void *) p, + (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func), + (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func), + (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(thr->heap, func), + (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func), + (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func), + (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func), + (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func), + (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func), + (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func), + (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func), + (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func), + (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func))); + + DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */ + count_instr = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func); + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p); + + /* Fixed header info. */ + tmp32 = count_instr; + DUK_RAW_WRITE_U32_BE(p, tmp32); + tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func); + DUK_RAW_WRITE_U32_BE(p, tmp32); + tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func); + DUK_RAW_WRITE_U32_BE(p, tmp32); + tmp16 = func->nregs; + DUK_RAW_WRITE_U16_BE(p, tmp16); + tmp16 = func->nargs; + DUK_RAW_WRITE_U16_BE(p, tmp16); +#if defined(DUK_USE_DEBUGGER_SUPPORT) + tmp32 = func->start_line; + DUK_RAW_WRITE_U32_BE(p, tmp32); + tmp32 = func->end_line; + DUK_RAW_WRITE_U32_BE(p, tmp32); +#else + DUK_RAW_WRITE_U32_BE(p, 0); + DUK_RAW_WRITE_U32_BE(p, 0); +#endif + tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK; + DUK_RAW_WRITE_U32_BE(p, tmp32); + + /* Bytecode instructions: endian conversion needed unless + * platform is big endian. + */ + ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func); + ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func); + DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr); +#if defined(DUK_USE_INTEGER_BE) + DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins)); + p += (size_t) (ins_end - ins); +#else + while (ins != ins_end) { + tmp32 = (duk_uint32_t) (*ins); + DUK_RAW_WRITE_U32_BE(p, tmp32); + ins++; + } +#endif + + /* Constants: variable size encoding. */ + tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func); + tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func); + while (tv != tv_end) { + /* constants are strings or numbers now */ + DUK_ASSERT(DUK_TVAL_IS_STRING(tv) || + DUK_TVAL_IS_NUMBER(tv)); + + if (DUK_TVAL_IS_STRING(tv)) { + h_str = DUK_TVAL_GET_STRING(tv); + DUK_ASSERT(h_str != NULL); + DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */ + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p), + *p++ = DUK__SER_STRING; + p = duk__dump_hstring_raw(p, h_str); + } else { + DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); + p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p); + *p++ = DUK__SER_NUMBER; + d = DUK_TVAL_GET_NUMBER(tv); + DUK_RAW_WRITE_DOUBLE_BE(p, d); + } + tv++; + } + + /* Inner functions recursively. */ + fn = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func); + fn_end = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func); + while (fn != fn_end) { + /* XXX: This causes recursion up to inner function depth + * which is normally not an issue, e.g. mark-and-sweep uses + * a recursion limiter to avoid C stack issues. Avoiding + * this would mean some sort of a work list or just refusing + * to serialize deep functions. + */ + DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(*fn)); + p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, p); + fn++; + } + + /* Object extra properties. + * + * There are some difference between function templates and functions. + * For example, function templates don't have .length and nargs is + * normally used to instantiate the functions. + */ + + p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs); + p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME); + p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME); + p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE); + p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func); + p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func); + + DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p)); + + return p; +} + +/* Load a function from bytecode. The function object returned here must + * match what is created by duk_js_push_closure() with respect to its flags, + * properties, etc. + * + * NOTE: there are intentionally no input buffer length / bound checks. + * Adding them would be easy but wouldn't ensure memory safety as untrusted + * or broken bytecode is unsafe during execution unless the opcodes themselves + * are validated (which is quite complex, especially for indirect opcodes). + */ + +#define DUK__ASSERT_LEFT(n) do { \ + DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \ + } while (0) + +static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) { + duk_hthread *thr; + duk_hcompiledfunction *h_fun; + duk_hbuffer *h_data; + duk_size_t data_size; + duk_uint32_t count_instr, count_const, count_funcs; + duk_uint32_t n; + duk_uint32_t tmp32; + duk_small_uint_t const_type; + duk_uint8_t *fun_data; + duk_uint8_t *q; + duk_idx_t idx_base; + duk_tval *tv; + duk_uarridx_t arr_idx; + + /* XXX: There's some overlap with duk_js_closure() here, but + * seems difficult to share code. Ensure that the final function + * looks the same as created by duk_js_closure(). + */ + + DUK_ASSERT(ctx != NULL); + thr = (duk_hthread *) ctx; + + DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end)); + + DUK__ASSERT_LEFT(3 * 4); + count_instr = DUK_RAW_READ_U32_BE(p); + count_const = DUK_RAW_READ_U32_BE(p); + count_funcs = DUK_RAW_READ_U32_BE(p); + + data_size = sizeof(duk_tval) * count_const + + sizeof(duk_hobject *) * count_funcs + + sizeof(duk_instr_t) * count_instr; + + DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld", + (long) count_instr, (long) count_const, + (long) count_const, (long) data_size)); + + /* Value stack is used to ensure reachability of constants and + * inner functions being loaded. Require enough space to handle + * large functions correctly. + */ + duk_require_stack(ctx, 2 + count_const + count_funcs); + idx_base = duk_get_top(ctx); + + /* Push function object, init flags etc. This must match + * duk_js_push_closure() quite carefully. + */ + duk_push_compiledfunction(ctx); + h_fun = duk_get_hcompiledfunction(ctx, -1); + DUK_ASSERT(h_fun != NULL); + DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) h_fun)); + DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun) == NULL); + DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, h_fun) == NULL); + DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, h_fun) == NULL); + + h_fun->nregs = DUK_RAW_READ_U16_BE(p); + h_fun->nargs = DUK_RAW_READ_U16_BE(p); +#if defined(DUK_USE_DEBUGGER_SUPPORT) + h_fun->start_line = DUK_RAW_READ_U32_BE(p); + h_fun->end_line = DUK_RAW_READ_U32_BE(p); +#else + p += 8; /* skip line info */ +#endif + + /* duk_hcompiledfunction flags; quite version specific */ + tmp32 = DUK_RAW_READ_U32_BE(p); + DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32); + + /* standard prototype */ + DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]); + + /* assert just a few critical flags */ + DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT); + DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&h_fun->obj)); + DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(&h_fun->obj)); + DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(&h_fun->obj)); + DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&h_fun->obj)); + DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj)); + DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj)); + DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj)); + + /* Create function 'data' buffer but don't attach it yet. */ + fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size); + DUK_ASSERT(fun_data != NULL); + + /* Load bytecode instructions. */ + DUK_ASSERT(sizeof(duk_instr_t) == 4); + DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t)); +#if defined(DUK_USE_INTEGER_BE) + q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs; + DUK_MEMCPY((void *) q, + (const void *) p, + sizeof(duk_instr_t) * count_instr); + p += sizeof(duk_instr_t) * count_instr; +#else + q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs; + for (n = count_instr; n > 0; n--) { + *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p); + q += sizeof(duk_instr_t); + } +#endif + + /* Load constants onto value stack but don't yet copy to buffer. */ + for (n = count_const; n > 0; n--) { + DUK__ASSERT_LEFT(1); + const_type = DUK_RAW_READ_U8(p); + switch (const_type) { + case DUK__SER_STRING: { + p = duk__load_string_raw(ctx, p); + break; + } + case DUK__SER_NUMBER: { + duk_double_t val; + DUK__ASSERT_LEFT(8); + val = DUK_RAW_READ_DOUBLE_BE(p); + duk_push_number(ctx, val); + break; + } + default: { + goto format_error; + } + } + } + + /* Load inner functions to value stack, but don't yet copy to buffer. */ + for (n = count_funcs; n > 0; n--) { + p = duk__load_func(ctx, p, p_end); + if (p == NULL) { + goto format_error; + } + } + + /* With constants and inner functions on value stack, we can now + * atomically finish the function 'data' buffer, bump refcounts, + * etc. + * + * Here we take advantage of the value stack being just a duk_tval + * array: we can just memcpy() the constants as long as we incref + * them afterwards. + */ + + h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1); + DUK_ASSERT(h_data != NULL); + DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data)); + DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data); + DUK_HBUFFER_INCREF(thr, h_data); + + tv = duk_get_tval(ctx, idx_base + 2); /* may be NULL if no constants or inner funcs */ + DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv != NULL); + + q = fun_data; + if (count_const > 0) { + /* Explicit zero size check to avoid NULL 'tv'. */ + DUK_MEMCPY((void *) q, (const void *) tv, sizeof(duk_tval) * count_const); + for (n = count_const; n > 0; n--) { + DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */ + q += sizeof(duk_tval); + } + tv += count_const; + } + + DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q); + for (n = count_funcs; n > 0; n--) { + duk_hobject *h_obj; + + DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv)); + h_obj = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h_obj != NULL); + tv++; + DUK_HOBJECT_INCREF(thr, h_obj); + + *((duk_hobject **) (void *) q) = h_obj; + q += sizeof(duk_hobject *); + } + + DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q); + + /* The function object is now reachable and refcounts are fine, + * so we can pop off all the temporaries. + */ + DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base))); + duk_set_top(ctx, idx_base + 1); + + /* Setup function properties. */ + tmp32 = DUK_RAW_READ_U32_BE(p); + duk_push_u32(ctx, tmp32); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); + + p = duk__load_string_raw(ctx, p); + if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) { + /* Original function instance/template had NAMEBINDING. + * Must create a lexical environment on loading to allow + * recursive functions like 'function foo() { foo(); }'. + */ + duk_hobject *proto; + + proto = thr->builtins[DUK_BIDX_GLOBAL_ENV]; + (void) duk_push_object_helper_proto(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV), + proto); + duk_dup(ctx, -2); /* -> [ func funcname env funcname ] */ + duk_dup(ctx, idx_base); /* -> [ func funcname env funcname func ] */ + duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */ + duk_xdef_prop_stridx(ctx, idx_base, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC); + /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it + * will be ignored anyway + */ + } + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); + + p = duk__load_string_raw(ctx, p); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC); + + duk_push_object(ctx); + duk_dup(ctx, -2); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */ + duk_compact(ctx, -1); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); + + p = duk__load_buffer_raw(ctx, p); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC); + + duk_push_object(ctx); /* _Varmap */ + for (;;) { + /* XXX: awkward */ + p = duk__load_string_raw(ctx, p); + if (duk_get_length(ctx, -1) == 0) { + duk_pop(ctx); + break; + } + tmp32 = DUK_RAW_READ_U32_BE(p); + duk_push_u32(ctx, tmp32); + duk_put_prop(ctx, -3); + } + duk_compact(ctx, -1); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE); + + duk_push_array(ctx); /* _Formals */ + for (arr_idx = 0; ; arr_idx++) { + /* XXX: awkward */ + p = duk__load_string_raw(ctx, p); + if (duk_get_length(ctx, -1) == 0) { + duk_pop(ctx); + break; + } + duk_put_prop_index(ctx, -2, arr_idx); + } + duk_compact(ctx, -1); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE); + + /* Return with final function pushed on stack top. */ + DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1))); + DUK_ASSERT_TOP(ctx, idx_base + 1); + return p; + + format_error: + return NULL; +} + +DUK_EXTERNAL void duk_dump_function(duk_context *ctx) { + duk_hthread *thr; + duk_hcompiledfunction *func; + duk_bufwriter_ctx bw_ctx_alloc; + duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc; + duk_uint8_t *p; + + DUK_ASSERT(ctx != NULL); + thr = (duk_hthread *) ctx; + + /* Bound functions don't have all properties so we'd either need to + * lookup the non-bound target function or reject bound functions. + * For now, bound functions are rejected. + */ + func = duk_require_hcompiledfunction(ctx, -1); + DUK_ASSERT(func != NULL); + DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&func->obj)); + + /* Estimating the result size beforehand would be costly, so + * start with a reasonable size and extend as needed. + */ + DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC); + p = DUK_BW_GET_PTR(thr, bw_ctx); + *p++ = DUK__SER_MARKER; + *p++ = DUK__SER_VERSION; + p = duk__dump_func(ctx, func, bw_ctx, p); + DUK_BW_SET_PTR(thr, bw_ctx, p); + DUK_BW_COMPACT(thr, bw_ctx); + + DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1))); + + duk_remove(ctx, -2); /* [ ... func buf ] -> [ ... buf ] */ +} + +DUK_EXTERNAL void duk_load_function(duk_context *ctx) { + duk_hthread *thr; + duk_uint8_t *p_buf, *p, *p_end; + duk_size_t sz; + + DUK_ASSERT(ctx != NULL); + thr = (duk_hthread *) ctx; + DUK_UNREF(ctx); + + p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz); + DUK_ASSERT(p_buf != NULL); + + /* The caller is responsible for being sure that bytecode being loaded + * is valid and trusted. Invalid bytecode can cause memory unsafe + * behavior directly during loading or later during bytecode execution + * (instruction validation would be quite complex to implement). + * + * This signature check is the only sanity check for detecting + * accidental invalid inputs. The initial 0xFF byte ensures no + * ordinary string will be accepted by accident. + */ + p = p_buf; + p_end = p_buf + sz; + if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) { + goto format_error; + } + p += 2; + + p = duk__load_func(ctx, p, p_end); + if (p == NULL) { + goto format_error; + } + + duk_remove(ctx, -2); /* [ ... buf func ] -> [ ... func ] */ + return; + + format_error: + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED); +} + +#undef DUK__SER_MARKER +#undef DUK__SER_VERSION +#undef DUK__SER_STRING +#undef DUK__SER_NUMBER +#undef DUK__BYTECODE_INITIAL_ALLOC + +#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */ + +DUK_EXTERNAL void duk_dump_function(duk_context *ctx) { + DUK_ERROR((duk_hthread *) ctx, DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); +} + +DUK_EXTERNAL void duk_load_function(duk_context *ctx) { + DUK_ERROR((duk_hthread *) ctx, DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); +} + +#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */ #line 1 "duk_api_call.c" /* * Calls. @@ -12402,6 +14961,8 @@ DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size * May currently throw an error e.g. when getting the property. */ DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) { + DUK_ASSERT_CTX_VALID(ctx); + DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld", (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx))); @@ -12431,7 +14992,7 @@ DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) { duk_idx_t idx_func; duk_int_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); idx_func = duk_get_top(ctx) - nargs - 1; @@ -12460,7 +15021,7 @@ DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs) { duk_idx_t idx_func; duk_int_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */ @@ -12485,6 +15046,8 @@ DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t * is now done "in-place", so this is not a trivial change. */ + DUK_ASSERT_CTX_VALID(ctx); + obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */ duk__call_prop_prep_stack(ctx, obj_index, nargs); @@ -12498,7 +15061,7 @@ DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) { duk_idx_t idx_func; duk_int_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); idx_func = duk_get_top(ctx) - nargs - 1; /* must work for nargs <= 0 */ @@ -12536,7 +15099,7 @@ DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) { duk_idx_t idx_func; duk_int_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */ @@ -12563,6 +15126,8 @@ DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx) { * index so the stack must have the same top when we use it. */ + DUK_ASSERT_CTX_VALID(ctx); + obj_index = (duk_idx_t) duk_get_int(ctx, -2); nargs = (duk_idx_t) duk_get_int(ctx, -1); duk_pop_2(ctx); @@ -12579,6 +15144,8 @@ DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk * and property lookup, not just the call itself. */ + DUK_ASSERT_CTX_VALID(ctx); + duk_push_idx(ctx, obj_index); duk_push_idx(ctx, nargs); @@ -12593,7 +15160,7 @@ DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function fu duk_hthread *thr = (duk_hthread *) ctx; duk_int_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); if (duk_get_top(ctx) < nargs || nrets < 0) { @@ -12657,6 +15224,8 @@ DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) { duk_small_uint_t call_flags; duk_int_t rc; + DUK_ASSERT_CTX_VALID(ctx); + /* [... constructor arg1 ... argN] */ idx_cons = duk_require_normalize_index(ctx, -nargs - 1); @@ -12792,7 +15361,7 @@ DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_activation *act; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT_DISABLE(thr->callstack_top >= 0); @@ -12814,7 +15383,7 @@ DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx) { * the internal call sites. */ - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT_DISABLE(thr->callstack_top >= 0); @@ -12835,7 +15404,7 @@ DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx) { duk_activation *act; duk_hobject *func; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT_DISABLE(thr->callstack_top >= 0); @@ -12863,7 +15432,7 @@ DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index) { duk_tval *tv; duk_hobject *h; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); if (DUK_TVAL_IS_OBJECT(tv)) { @@ -12887,7 +15456,7 @@ DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index) { DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic) { duk_hnativefunction *nf; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); nf = duk_require_hnativefunction(ctx, index); DUK_ASSERT(nf != NULL); @@ -13081,6 +15650,8 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) { duk_uint8_t *dst; const char *ret; + DUK_ASSERT_CTX_VALID(ctx); + /* XXX: optimize for string inputs: no need to coerce to a buffer * which makes a copy of the input. */ @@ -13108,7 +15679,7 @@ DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) { return ret; type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_BASE64_ENCODE_FAILED); + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_ENCODE_FAILED); return NULL; /* never here */ } @@ -13121,6 +15692,8 @@ DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) { duk_uint8_t *dst_final; duk_bool_t retval; + DUK_ASSERT_CTX_VALID(ctx); + /* XXX: optimize for buffer inputs: no need to coerce to a string * which causes an unnecessary interning. */ @@ -13152,7 +15725,7 @@ DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) { return; type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_BASE64_DECODE_FAILED); + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED); } DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) { @@ -13163,6 +15736,8 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) { duk_uint8_t *buf; const char *ret; + DUK_ASSERT_CTX_VALID(ctx); + index = duk_require_normalize_index(ctx, index); inp = duk__prep_codec_arg(ctx, index, &len); DUK_ASSERT(inp != NULL || len == 0); @@ -13180,9 +15755,9 @@ DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) { /* XXX: Using a string return value forces a string intern which is * not always necessary. As a rough performance measure, hex encode - * time for perf-testcases/test-hex-encode.js dropped from ~35s to - * ~15s without string coercion. Change to returning a buffer and - * let the caller coerce to string if necessary? + * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s + * without string coercion. Change to returning a buffer and let the + * caller coerce to string if necessary? */ ret = duk_to_string(ctx, -1); @@ -13198,6 +15773,8 @@ DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) { duk_small_int_t t; duk_uint8_t *buf; + DUK_ASSERT_CTX_VALID(ctx); + index = duk_require_normalize_index(ctx, index); inp = duk__prep_codec_arg(ctx, index, &len); DUK_ASSERT(inp != NULL || len == 0); @@ -13227,15 +15804,20 @@ DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) { return; type_error: - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_HEX_DECODE_FAILED); + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_DECODE_FAILED); } DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t index) { #ifdef DUK_USE_ASSERTIONS - duk_idx_t top_at_entry = duk_get_top(ctx); + duk_idx_t top_at_entry; #endif const char *ret; + DUK_ASSERT_CTX_VALID(ctx); +#ifdef DUK_USE_ASSERTIONS + top_at_entry = duk_get_top(ctx); +#endif + index = duk_require_normalize_index(ctx, index); duk_bi_json_stringify_helper(ctx, index /*idx_value*/, @@ -13253,7 +15835,12 @@ DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t index) { DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index) { #ifdef DUK_USE_ASSERTIONS - duk_idx_t top_at_entry = duk_get_top(ctx); + duk_idx_t top_at_entry; +#endif + + DUK_ASSERT_CTX_VALID(ctx); +#ifdef DUK_USE_ASSERTIONS + top_at_entry = duk_get_top(ctx); #endif index = duk_require_normalize_index(ctx, index); @@ -13284,11 +15871,13 @@ DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, du duk_uint_t comp_flags; duk_int_t rc; + DUK_ASSERT_CTX_VALID(ctx); + /* Note: strictness is *not* inherited from the current Duktape/C. * This would be confusing because the current strictness state * depends on whether we're running inside a Duktape/C activation * (= strict mode) or outside of any activation (= non-strict mode). - * See api-testcases/test-eval-strictness.c for more discussion. + * See tests/api/test-eval-strictness.c for more discussion. */ /* [ ... source? filename ] (depends on flags) */ @@ -13329,10 +15918,12 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx) { duk_small_uint_t comp_flags; duk_hcompiledfunction *h_templ; + DUK_ASSERT_CTX_VALID(ctx); + /* Note: strictness is not inherited from the current Duktape/C * context. Otherwise it would not be possible to compile * non-strict code inside a Duktape/C activation (which is - * always strict now). See api-testcases/test-eval-strictness.c + * always strict now). See tests/api/test-eval-strictness.c * for discussion. */ @@ -13349,7 +15940,7 @@ DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx) { h_sourcecode = duk_get_hstring(ctx, -2); if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */ - (h_sourcecode == NULL)) { /* e.g. duk_push_file_string_raw() pushed undefined */ + (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */ /* XXX: when this error is caused by a nonexistent * file given to duk_peval_file() or similar, the * error message is not the best possible. @@ -13406,6 +15997,8 @@ DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk__compile_raw_args comp_args_alloc; duk__compile_raw_args *comp_args = &comp_args_alloc; + DUK_ASSERT_CTX_VALID(ctx); + if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) { /* String length is computed here to avoid multiple evaluation * of a macro argument in the calling side. @@ -13449,6 +16042,8 @@ DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) { duk_idx_t idx; duk_idx_t top; + DUK_ASSERT_CTX_VALID(ctx); + /* We don't duk_require_stack() here now, but rely on the caller having * enough space. */ @@ -13492,7 +16087,7 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx, const char *str; duk_size_t len; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(read_cb != NULL); DUK_ASSERT(write_cb != NULL); /* Other callbacks are optional. */ @@ -13536,8 +16131,8 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx, DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) { duk_hthread *thr; + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->heap != NULL); @@ -13549,8 +16144,8 @@ DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) { duk_hthread *thr; duk_bool_t processed_messages; + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->heap != NULL); @@ -13581,6 +16176,7 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx, duk_debug_write_flush_function write_flush_cb, duk_debug_detached_function detached_cb, void *udata) { + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(read_cb); DUK_UNREF(write_cb); DUK_UNREF(peek_cb); @@ -13592,11 +16188,13 @@ DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx, } DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); duk_error(ctx, DUK_ERR_API_ERROR, "no debugger support"); } DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) { /* nop */ + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(ctx); } @@ -13748,6 +16346,8 @@ DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, DUK_STRIDX_LC_WARN, DUK_STRIDX_LC_ERROR, DUK_STRIDX_LC_FATAL }; + DUK_ASSERT_CTX_VALID(ctx); + if (level < 0) { level = 0; } else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) { @@ -13775,6 +16375,8 @@ DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) { va_list ap; + DUK_ASSERT_CTX_VALID(ctx); + va_start(ap, fmt); duk_log_va(ctx, level, fmt, ap); va_end(ap); @@ -13789,7 +16391,7 @@ DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, .. DUK_EXTERNAL void *duk_alloc_raw(duk_context *ctx, duk_size_t size) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return DUK_ALLOC_RAW(thr->heap, size); } @@ -13797,7 +16399,7 @@ DUK_EXTERNAL void *duk_alloc_raw(duk_context *ctx, duk_size_t size) { DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_FREE_RAW(thr->heap, ptr); } @@ -13805,7 +16407,7 @@ DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) { DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return DUK_REALLOC_RAW(thr->heap, ptr, size); } @@ -13813,7 +16415,7 @@ DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return DUK_ALLOC(thr->heap, size); } @@ -13821,7 +16423,7 @@ DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) { DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_FREE(thr->heap, ptr); } @@ -13829,7 +16431,7 @@ DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) { DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* * Note: since this is an exposed API call, there should be @@ -13848,7 +16450,7 @@ DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_function duk_hthread *thr = (duk_hthread *) ctx; duk_heap *heap; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(out_funcs != NULL); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->heap != NULL); @@ -13867,9 +16469,11 @@ DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) { DUK_UNREF(flags); + /* NULL accepted */ if (!ctx) { return; } + DUK_ASSERT_CTX_VALID(ctx); heap = thr->heap; DUK_ASSERT(heap != NULL); @@ -13902,7 +16506,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) { duk_tval *tv_key; duk_bool_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* Note: copying tv_obj and tv_key to locals to shield against a valstack * resize is not necessary for a property get right now. @@ -13920,7 +16524,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) { } DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(key != NULL); obj_index = duk_require_normalize_index(ctx, obj_index); @@ -13929,7 +16533,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_inde } DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj_index = duk_require_normalize_index(ctx, obj_index); duk_push_uarridx(ctx, arr_index); @@ -13939,7 +16543,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); @@ -13951,7 +16555,7 @@ DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_inde DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop) { duk_bool_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); @@ -13973,7 +16577,7 @@ DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index) { duk_small_int_t throw_flag; duk_bool_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* Note: copying tv_obj and tv_key to locals to shield against a valstack * resize is not necessary for a property put right now (putprop protects @@ -13993,7 +16597,7 @@ DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index) { } DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(key != NULL); obj_index = duk_require_normalize_index(ctx, obj_index); @@ -14003,7 +16607,7 @@ DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_inde } DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj_index = duk_require_normalize_index(ctx, obj_index); duk_push_uarridx(ctx, arr_index); @@ -14014,7 +16618,7 @@ DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_index DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); @@ -14031,7 +16635,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) { duk_small_int_t throw_flag; duk_bool_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* Note: copying tv_obj and tv_key to locals to shield against a valstack * resize is not necessary for a property delete right now. @@ -14049,7 +16653,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) { } DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(key != NULL); obj_index = duk_require_normalize_index(ctx, obj_index); @@ -14058,7 +16662,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_inde } DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj_index = duk_require_normalize_index(ctx, obj_index); duk_push_uarridx(ctx, arr_index); @@ -14068,7 +16672,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); @@ -14083,7 +16687,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) { duk_tval *tv_key; duk_bool_t rc; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* Note: copying tv_obj and tv_key to locals to shield against a valstack * resize is not necessary for a property existence check right now. @@ -14100,7 +16704,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) { } DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(key != NULL); obj_index = duk_require_normalize_index(ctx, obj_index); @@ -14109,7 +16713,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_inde } DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj_index = duk_require_normalize_index(ctx, obj_index); duk_push_uarridx(ctx, arr_index); @@ -14119,7 +16723,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); @@ -14138,7 +16742,7 @@ DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small duk_hobject *obj; duk_hstring *key; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj = duk_require_hobject(ctx, obj_index); DUK_ASSERT(obj != NULL); @@ -14155,7 +16759,7 @@ DUK_INTERNAL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk duk_hthread *thr = (duk_hthread *) ctx; duk_hobject *obj; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj = duk_require_hobject(ctx, obj_index); DUK_ASSERT(obj != NULL); @@ -14169,7 +16773,7 @@ DUK_INTERNAL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, du duk_hobject *obj; duk_hstring *key; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); @@ -14188,7 +16792,7 @@ DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_i duk_hobject *obj; duk_hstring *key; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(stridx >= 0); DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); DUK_ASSERT_DISABLE(builtin_idx >= 0); @@ -14228,6 +16832,8 @@ DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t duk_uint_t is_data_desc; duk_uint_t is_acc_desc; + DUK_ASSERT_CTX_VALID(ctx); + obj = duk_require_hobject(ctx, obj_index); is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE); @@ -14311,7 +16917,7 @@ DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) { duk_hthread *thr = (duk_hthread *) ctx; duk_hobject *obj; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj = duk_get_hobject(ctx, obj_index); if (obj) { @@ -14323,7 +16929,7 @@ DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) { /* XXX: the duk_hobject_enum.c stack APIs should be reworked */ DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); duk_dup(ctx, obj_index); duk_require_hobject_or_lfunc_coerce(ctx, -1); @@ -14331,7 +16937,7 @@ DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enu } DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); duk_require_hobject(ctx, enum_index); duk_dup(ctx, enum_index); @@ -14345,7 +16951,7 @@ DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_boo DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs) { const duk_function_list_entry *ent = funcs; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj_index = duk_require_normalize_index(ctx, obj_index); if (ent != NULL) { @@ -14360,7 +16966,7 @@ DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, c DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) { const duk_number_list_entry *ent = numbers; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj_index = duk_require_normalize_index(ctx, obj_index); if (ent != NULL) { @@ -14380,7 +16986,7 @@ DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) duk_hthread *thr = (duk_hthread *) ctx; duk_bool_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); /* XXX: direct implementation */ @@ -14395,7 +17001,7 @@ DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) duk_hthread *thr = (duk_hthread *) ctx; duk_bool_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL); /* XXX: direct implementation */ @@ -14416,7 +17022,7 @@ DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t index) { duk_hobject *obj; duk_hobject *proto; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); obj = duk_require_hobject(ctx, index); @@ -14436,7 +17042,7 @@ DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index) { duk_hobject *obj; duk_hobject *proto; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj = duk_require_hobject(ctx, index); DUK_ASSERT(obj != NULL); @@ -14460,10 +17066,14 @@ DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index) { * now (just set it to undefined). */ DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); + duk_get_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER); } DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); + duk_put_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER); } #line 1 "duk_api_stack.c" @@ -14650,7 +17260,7 @@ DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t vs_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); /* Care must be taken to avoid pointer wrapping in the index @@ -14690,7 +17300,7 @@ DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t i duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t vs_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); @@ -14721,7 +17331,7 @@ DUK_INTERNAL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t vs_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); @@ -14748,7 +17358,7 @@ DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t vs_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); @@ -14777,7 +17387,9 @@ DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) { /* Non-critical. */ DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); + return (duk_normalize_index(ctx, index) >= 0); } @@ -14785,7 +17397,7 @@ DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index) { DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); if (duk_normalize_index(ctx, index) < 0) { @@ -14800,7 +17412,7 @@ DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index) { DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); } @@ -14814,7 +17426,7 @@ DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index) { duk_tval tv_tmp; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(DUK_INVALID_INDEX < 0); vs_size = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); @@ -14896,7 +17508,7 @@ DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1; if (DUK_UNLIKELY(ret < 0)) { @@ -14913,7 +17525,7 @@ DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1; if (DUK_UNLIKELY(ret < 0)) { @@ -14958,7 +17570,7 @@ DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) duk_tval *p; duk_size_t new_alloc_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->valstack_bottom >= thr->valstack); DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); @@ -15021,8 +17633,8 @@ DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) #endif thr->valstack = new_valstack; thr->valstack_end = new_valstack + new_size; - thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_valstack + old_bottom_offset); - thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_valstack + old_top_offset); + thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset); + thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset); DUK_ASSERT(thr->valstack_bottom >= thr->valstack); DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); @@ -15052,7 +17664,7 @@ DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) (void *) thr->valstack_bottom, (void *) thr->valstack_top)); /* init newly allocated slots (only) */ - p = (duk_tval *) ((duk_uint8_t *) thr->valstack + old_end_offset_post); + p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post); while (p < thr->valstack_end) { /* never executed if new size is smaller */ DUK_TVAL_SET_UNDEFINED_UNUSED(p); @@ -15091,7 +17703,7 @@ duk_bool_t duk_valstack_resize_raw(duk_context *ctx, (long) (thr->valstack_bottom - thr->valstack), (int) shrink_flag, (int) compact_flag, (int) throw_flag)); - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->valstack_bottom >= thr->valstack); DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom); @@ -15170,7 +17782,7 @@ DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) { duk_hthread *thr = (duk_hthread *) ctx; duk_size_t min_new_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); if (DUK_UNLIKELY(extra < 0)) { @@ -15192,7 +17804,7 @@ DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra) { duk_hthread *thr = (duk_hthread *) ctx; duk_size_t min_new_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); if (DUK_UNLIKELY(extra < 0)) { @@ -15213,7 +17825,7 @@ DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra) { DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) { duk_size_t min_new_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); if (DUK_UNLIKELY(top < 0)) { /* Clamping to zero makes the API more robust to calling code @@ -15233,7 +17845,7 @@ DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) { DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top) { duk_size_t min_new_size; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); if (DUK_UNLIKELY(top < 0)) { /* Clamping to zero makes the API more robust to calling code @@ -15259,7 +17871,7 @@ DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) duk_tval *tv2; duk_tval tv_tmp; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv1 = duk_require_tval(ctx, index1); DUK_ASSERT(tv1 != NULL); @@ -15273,7 +17885,7 @@ DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) } DUK_EXTERNAL void duk_swap_top(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); duk_swap(ctx, index, -1); } @@ -15283,7 +17895,7 @@ DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index) { duk_tval *tv_from; duk_tval *tv_to; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); @@ -15300,7 +17912,7 @@ DUK_EXTERNAL void duk_dup_top(duk_context *ctx) { duk_tval *tv_from; duk_tval *tv_to; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); @@ -15321,7 +17933,7 @@ DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) { duk_tval tv_tmp; duk_size_t nbytes; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); p = duk_require_tval(ctx, to_index); DUK_ASSERT(p != NULL); @@ -15361,7 +17973,7 @@ DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index) { duk_tval *tv2; duk_tval tv_tmp; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv1 = duk_require_tval(ctx, -1); DUK_ASSERT(tv1 != NULL); @@ -15385,10 +17997,9 @@ DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_ duk_tval *tv2; duk_tval tv_tmp; + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); /* w/o refcounting */ - DUK_ASSERT(ctx != NULL); - tv1 = duk_require_tval(ctx, from_index); DUK_ASSERT(tv1 != NULL); tv2 = duk_require_tval(ctx, to_index); @@ -15411,7 +18022,7 @@ DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index) { #endif duk_size_t nbytes; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); p = duk_require_tval(ctx, index); DUK_ASSERT(p != NULL); @@ -15456,6 +18067,8 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, /* XXX: several pointer comparison issues here */ + DUK_ASSERT_CTX_VALID(to_ctx); + DUK_ASSERT_CTX_VALID(from_ctx); DUK_ASSERT(to_ctx != NULL); DUK_ASSERT(from_ctx != NULL); @@ -15490,7 +18103,7 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, DUK_MEMCPY((void *) to_thr->valstack_top, src, nbytes); p = to_thr->valstack_top; - to_thr->valstack_top = (duk_tval *) (((duk_uint8_t *) p) + nbytes); + to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes); if (is_copy) { /* incref copies, keep originals */ @@ -15502,7 +18115,7 @@ DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, } else { /* no net refcount change */ p = from_thr->valstack_top; - q = (duk_tval *) (((duk_uint8_t *) p) - nbytes); + q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes); from_thr->valstack_top = q; /* elements above stack top are kept UNUSED */ @@ -15523,7 +18136,7 @@ DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_UNDEFINED(tv)) { @@ -15537,7 +18150,7 @@ DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_NULL(tv)) { @@ -15551,7 +18164,7 @@ DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index) { duk_bool_t ret = 0; /* default: false */ duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_BOOLEAN(tv)) { @@ -15566,7 +18179,7 @@ DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_BOOLEAN(tv)) { @@ -15583,7 +18196,7 @@ DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index) { duk_double_union ret; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); ret.d = DUK_DOUBLE_NAN; /* default: NaN */ tv = duk_get_tval(ctx, index); @@ -15604,7 +18217,7 @@ DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_NUMBER(tv)) { @@ -15626,21 +18239,25 @@ DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index) { /* Custom coercion for API */ + DUK_ASSERT_CTX_VALID(ctx); return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/); } DUK_EXTERNAL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index) { /* Custom coercion for API */ + DUK_ASSERT_CTX_VALID(ctx); return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/); } DUK_EXTERNAL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index) { /* Custom coercion for API */ + DUK_ASSERT_CTX_VALID(ctx); return (duk_int_t) duk__api_coerce_d2i(ctx, index, 1 /*require*/); } DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index) { /* Custom coercion for API */ + DUK_ASSERT_CTX_VALID(ctx); return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 1 /*require*/); } @@ -15648,7 +18265,7 @@ DUK_EXTERNAL const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_ const char *ret; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* default: NULL, length 0 */ ret = NULL; @@ -15676,7 +18293,7 @@ DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_hthread *thr = (duk_hthread *) ctx; const char *ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* Note: this check relies on the fact that even a zero-size string * has a non-NULL pointer. @@ -15691,13 +18308,13 @@ DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, } DUK_EXTERNAL const char *duk_get_string(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk_get_lstring(ctx, index, NULL); } DUK_EXTERNAL const char *duk_require_string(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk_require_lstring(ctx, index, NULL); } @@ -15705,7 +18322,7 @@ DUK_EXTERNAL const char *duk_require_string(duk_context *ctx, duk_idx_t index) { DUK_EXTERNAL void *duk_get_pointer(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_POINTER(tv)) { @@ -15720,7 +18337,7 @@ DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* Note: here we must be wary of the fact that a pointer may be * valid and be a NULL. @@ -15739,7 +18356,7 @@ DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) { DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) { @@ -15752,11 +18369,11 @@ DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) { } #endif -DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { +DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); if (out_size != NULL) { @@ -15773,35 +18390,80 @@ DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */ } + if (throw_flag) { + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); + } return NULL; } +DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { + return duk__get_buffer_helper(ctx, index, out_size, 0 /*throw_flag*/); +} + DUK_EXTERNAL void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { + return duk__get_buffer_helper(ctx, index, out_size, 1 /*throw_flag*/); +} + +DUK_LOCAL void *duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); + DUK_UNREF(thr); if (out_size != NULL) { *out_size = 0; } - /* Note: here we must be wary of the fact that a data pointer may - * be a NULL for a zero-size buffer. - */ - tv = duk_get_tval(ctx, index); - if (tv && DUK_TVAL_IS_BUFFER(tv)) { + if (tv == NULL) { + goto fail; + } + + if (DUK_TVAL_IS_BUFFER(tv)) { duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); DUK_ASSERT(h != NULL); if (out_size) { *out_size = DUK_HBUFFER_GET_SIZE(h); } return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */ + } else if (DUK_TVAL_IS_OBJECT(tv)) { + duk_hobject *h = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h != NULL); + if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { + /* XXX: this is probably a useful shared helper: for a + * duk_hbufferobject, get a validated buffer pointer/length. + */ + duk_hbufferobject *h_bufobj = (duk_hbufferobject *) h; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + if (h_bufobj->buf != NULL && + DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) { + duk_uint8_t *p; + + p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf); + if (out_size != NULL) { + *out_size = (duk_size_t) h_bufobj->length; + } + return (void *) (p + h_bufobj->offset); + } + /* if slice not fully valid, treat as error */ + } } - DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); - return NULL; /* not reachable */ + fail: + if (throw_flag) { + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); + } + return NULL; +} + +DUK_EXTERNAL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { + return duk__get_buffer_data_helper(ctx, index, out_size, 0 /*throw_flag*/); +} + +DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) { + return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/); } /* Raw helper for getting a value from the stack, checking its tag, and possible its object class. @@ -15812,7 +18474,7 @@ DUK_INTERNAL duk_heaphdr *duk_get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t duk_tval *tv; duk_small_uint_t tag = flags_and_tag & 0xffffU; /* tags can be up to 16 bits */ - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) { @@ -15900,7 +18562,6 @@ DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, return (duk_hcompiledfunction *) h; } -#if 0 /*unused*/ 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); @@ -15910,7 +18571,6 @@ DUK_INTERNAL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *c } return (duk_hcompiledfunction *) h; } -#endif 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); @@ -15935,7 +18595,7 @@ DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index duk_hobject *h; duk_hnativefunction *f; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (!tv) { @@ -15960,7 +18620,7 @@ DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t i duk_hthread *thr = (duk_hthread *) ctx; duk_c_function ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); ret = duk_get_c_function(ctx, index); if (!ret) { @@ -15970,10 +18630,14 @@ DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t i } DUK_EXTERNAL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); + return (duk_context *) duk_get_hthread(ctx, index); } DUK_EXTERNAL duk_context *duk_require_context(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); + return (duk_context *) duk_require_hthread(ctx, index); } @@ -15981,7 +18645,7 @@ DUK_EXTERNAL void *duk_get_heapptr(duk_context *ctx, duk_idx_t index) { duk_tval *tv; void *ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) { @@ -15998,7 +18662,7 @@ DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index) { duk_tval *tv; void *ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16028,7 +18692,7 @@ duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) { duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16049,7 +18713,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16071,7 +18735,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); if (DUK_TVAL_IS_OBJECT(tv)) { @@ -16088,7 +18752,7 @@ DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (!tv) { @@ -16137,7 +18801,7 @@ DUK_INTERNAL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t l duk_hthread *thr = (duk_hthread *) ctx; duk_hobject *h; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); h = duk_get_hobject(ctx, index); if (!h) { @@ -16180,7 +18844,7 @@ DUK_EXTERNAL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int /* inline initializer for coercers[] is not allowed by old compilers like BCC */ duk_small_int_t coercers[2]; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); coercers[0] = DUK_STRIDX_VALUE_OF; @@ -16218,7 +18882,7 @@ DUK_EXTERNAL void duk_to_undefined(duk_context *ctx, duk_idx_t index) { duk_tval *tv; duk_tval tv_tmp; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); tv = duk_require_tval(ctx, index); @@ -16233,7 +18897,7 @@ DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t index) { duk_tval *tv; duk_tval tv_tmp; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); tv = duk_require_tval(ctx, index); @@ -16245,7 +18909,7 @@ DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t index) { /* E5 Section 9.1 */ DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING); index = duk_require_normalize_index(ctx, index); @@ -16265,7 +18929,7 @@ DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index) { duk_tval tv_tmp; duk_bool_t val; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); index = duk_require_normalize_index(ctx, index); @@ -16290,7 +18954,7 @@ DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index) { duk_tval tv_tmp; duk_double_t d; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16317,7 +18981,7 @@ DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t index duk_tval tv_tmp; duk_double_t d; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16337,6 +19001,7 @@ DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index) { /* Value coercion (in stack): ToInteger(), E5 Section 9.4 * API return value coercion: custom */ + DUK_ASSERT_CTX_VALID(ctx); (void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger); return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/); } @@ -16345,6 +19010,7 @@ DUK_EXTERNAL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index) { /* Value coercion (in stack): ToInteger(), E5 Section 9.4 * API return value coercion: custom */ + DUK_ASSERT_CTX_VALID(ctx); (void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger); return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/); } @@ -16355,7 +19021,7 @@ DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index) { duk_tval tv_tmp; duk_int32_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16382,7 +19048,7 @@ DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index) { duk_tval tv_tmp; duk_uint32_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16409,7 +19075,7 @@ DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index) { duk_tval tv_tmp; duk_uint16_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16430,17 +19096,58 @@ DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index) { return ret; } +/* Special coercion for Uint8ClampedArray. */ +DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index) { + duk_double_t d; + duk_double_t t; + duk_uint8_t ret; + + /* XXX: Simplify this algorithm, should be possible to come up with + * a shorter and faster algorithm by inspecting IEEE representation + * directly. + */ + + d = duk_to_number(ctx, index); + if (d <= 0.0) { + return 0; + } else if (d >= 255) { + return 255; + } else if (DUK_ISNAN(d)) { + /* Avoid NaN-to-integer coercion as it is compiler specific. */ + return 0; + } + + t = d - DUK_FLOOR(d); + if (t == 0.5) { + /* Exact halfway, round to even. */ + ret = (duk_uint8_t) d; + ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4 + * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4 + */ + } else { + /* Not halfway, round to nearest. */ + ret = (duk_uint8_t) (d + 0.5); + } + return ret; +} + DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { + DUK_ASSERT_CTX_VALID(ctx); + (void) duk_to_string(ctx, index); return duk_require_lstring(ctx, index, out_len); } DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); + duk_to_string(ctx, -1); return 1; } DUK_EXTERNAL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) { + DUK_ASSERT_CTX_VALID(ctx); + index = duk_require_normalize_index(ctx, index); /* We intentionally ignore the duk_safe_call() return value and only @@ -16478,7 +19185,7 @@ DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t res; duk_bool_t clamped = 0; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_require_tval(ctx, index); DUK_ASSERT(tv != NULL); @@ -16544,7 +19251,7 @@ DUK_EXTERNAL const char *duk_to_string(duk_context *ctx, duk_idx_t index) { duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); index = duk_require_normalize_index(ctx, index); @@ -16629,7 +19336,7 @@ DUK_EXTERNAL const char *duk_to_string(duk_context *ctx, duk_idx_t index) { DUK_INTERNAL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index) { duk_hstring *ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); duk_to_string(ctx, index); ret = duk_get_hstring(ctx, index); DUK_ASSERT(ret != NULL); @@ -16643,6 +19350,7 @@ DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size duk_size_t src_size; duk_uint8_t *dst_data; + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(thr); index = duk_require_normalize_index(ctx, index); @@ -16696,7 +19404,7 @@ DUK_EXTERNAL void *duk_to_pointer(duk_context *ctx, duk_idx_t index) { duk_tval *tv; void *res; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); index = duk_require_normalize_index(ctx, index); @@ -16747,7 +19455,7 @@ DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index) { duk_uint_t flags = 0; /* shared flags for a subset of types */ duk_small_int_t proto = 0; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); index = duk_require_normalize_index(ctx, index); @@ -16778,11 +19486,35 @@ DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index) { break; } case DUK_TAG_BUFFER: { - flags = DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER); - proto = DUK_BIDX_BUFFER_PROTOTYPE; - goto create_object; + /* A plain buffer coerces to a Duktape.Buffer because it's the + * object counterpart of the plain buffer value. But it might + * still make more sense to produce an ArrayBuffer here? + */ + + duk_hbufferobject *h_bufobj; + duk_hbuffer *h_val; + + h_val = DUK_TVAL_GET_BUFFER(tv); + DUK_ASSERT(h_val != NULL); + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), + DUK_BIDX_BUFFER_PROTOTYPE); + DUK_ASSERT(h_bufobj != NULL); + DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE((duk_hobject *) h_bufobj)); + DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)); + + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + DUK_ASSERT(h_bufobj->offset == 0); + h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val); + DUK_ASSERT(h_bufobj->shift == 0); + DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); + + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + goto replace_value; } case DUK_TAG_POINTER: { flags = DUK_HOBJECT_FLAG_EXTENSIBLE | @@ -16885,7 +19617,7 @@ DUK_LOCAL duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t index, duk_uint_t flag_mask) { duk_hobject *obj; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj = duk_get_hobject(ctx, index); if (obj) { @@ -16897,6 +19629,8 @@ DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) { duk_tval *tv; + DUK_ASSERT_CTX_VALID(ctx); + tv = duk_get_tval(ctx, index); if (!tv) { return DUK_TYPE_NONE; @@ -16930,12 +19664,16 @@ DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) { } DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) { + DUK_ASSERT_CTX_VALID(ctx); + return (duk_get_type(ctx, index) == type) ? 1 : 0; } DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) { duk_tval *tv; + DUK_ASSERT_CTX_VALID(ctx); + tv = duk_get_tval(ctx, index); if (!tv) { return DUK_TYPE_MASK_NONE; @@ -16970,7 +19708,9 @@ DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) { DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + + DUK_ASSERT_CTX_VALID(ctx); + if (duk_get_type_mask(ctx, index) & mask) { return 1; } @@ -16982,12 +19722,12 @@ DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, d } DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_UNDEFINED); } DUK_EXTERNAL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_NULL); } @@ -16995,6 +19735,8 @@ DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t ind duk_tval *tv; duk_small_uint_t tag; + DUK_ASSERT_CTX_VALID(ctx); + tv = duk_get_tval(ctx, index); if (!tv) { return 0; @@ -17004,14 +19746,14 @@ DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t ind } DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_BOOLEAN); } DUK_EXTERNAL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* * Number is special because it doesn't have a specific @@ -17036,6 +19778,8 @@ DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) { duk_tval *tv; + DUK_ASSERT_CTX_VALID(ctx); + tv = duk_get_tval(ctx, index); if (!tv || !DUK_TVAL_IS_NUMBER(tv)) { return 0; @@ -17044,34 +19788,34 @@ DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) { } DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_STRING); } DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_OBJECT); } DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_BUFFER); } DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_POINTER); } DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); return duk__tag_check(ctx, index, DUK_TAG_LIGHTFUNC); } DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) { duk_hobject *obj; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); obj = duk_get_hobject(ctx, index); if (obj) { @@ -17081,7 +19825,11 @@ DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) { } DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) { - duk_tval *tv = duk_get_tval(ctx, index); + duk_tval *tv; + + DUK_ASSERT_CTX_VALID(ctx); + + tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_LIGHTFUNC(tv)) { return 1; } @@ -17093,24 +19841,28 @@ DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) { } DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); return duk__obj_flag_any_default_false(ctx, index, DUK_HOBJECT_FLAG_NATIVEFUNCTION); } DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); return duk__obj_flag_any_default_false(ctx, index, DUK_HOBJECT_FLAG_COMPILEDFUNCTION); } DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); return duk__obj_flag_any_default_false(ctx, index, DUK_HOBJECT_FLAG_BOUND); } DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) { + DUK_ASSERT_CTX_VALID(ctx); return duk__obj_flag_any_default_false(ctx, index, DUK_HOBJECT_FLAG_THREAD); @@ -17118,13 +19870,14 @@ DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) { 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_dynamic_buffer(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_BUFFER(tv)) { @@ -17138,7 +19891,7 @@ DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index) DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index) { duk_tval *tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); tv = duk_get_tval(ctx, index); if (tv && DUK_TVAL_IS_BUFFER(tv)) { @@ -17151,7 +19904,8 @@ DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index) { /* XXX: make macro in API */ DUK_EXTERNAL duk_bool_t duk_is_primitive(duk_context *ctx, duk_idx_t index) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); + return !duk_is_object(ctx, index); } @@ -17160,7 +19914,8 @@ DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index) duk_hobject *h; duk_uint_t sanity; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); + h = duk_get_hobject(ctx, index); sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY; @@ -17204,7 +19959,7 @@ DUK_INTERNAL void duk_push_tval(duk_context *ctx, duk_tval *tv) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(tv != NULL); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); @@ -17219,7 +19974,7 @@ DUK_INTERNAL void duk_push_unused(duk_context *ctx) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17231,7 +19986,7 @@ DUK_EXTERNAL void duk_push_undefined(duk_context *ctx) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17242,7 +19997,7 @@ DUK_EXTERNAL void duk_push_null(duk_context *ctx) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17254,7 +20009,7 @@ DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val) { duk_tval *tv_slot; duk_small_int_t b; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */ @@ -17266,7 +20021,7 @@ DUK_EXTERNAL void duk_push_true(duk_context *ctx) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17277,7 +20032,7 @@ DUK_EXTERNAL void duk_push_false(duk_context *ctx) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17290,7 +20045,7 @@ DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val) { duk_tval *tv_slot; duk_double_union du; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); du.d = val; @@ -17304,7 +20059,7 @@ DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17323,7 +20078,7 @@ DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val) { duk_tval *tv_slot; duk_double_t d; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); d = (duk_double_t) val; @@ -17337,7 +20092,7 @@ DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17357,7 +20112,7 @@ DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val) { duk_tval *tv_slot; duk_double_t d; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); d = (duk_double_t) val; @@ -17371,7 +20126,7 @@ DUK_EXTERNAL void duk_push_nan(duk_context *ctx) { duk_tval *tv_slot; duk_double_union du; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); DUK_DBLUNION_SET_NAN(&du); @@ -17385,7 +20140,7 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk duk_hstring *h; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* check stack before interning (avoid hanging temp) */ if (thr->valstack_top >= thr->valstack_end) { @@ -17417,7 +20172,7 @@ DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk } DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); if (str) { return duk_push_lstring(ctx, str, DUK_STRLEN(str)); @@ -17438,7 +20193,8 @@ DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char * char *buf; long sz; /* ANSI C typing */ - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); + if (!path) { goto fail; } @@ -17482,7 +20238,7 @@ DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char * #else DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(path); if (flags != 0) { @@ -17500,7 +20256,7 @@ DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) { duk_hthread *thr; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); thr = (duk_hthread *) ctx; DUK__CHECK_SPACE(); tv_slot = thr->valstack_top++; @@ -17515,7 +20271,7 @@ DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t flags) { duk_hthread *thr = (duk_hthread *) ctx; DUK_ASSERT(thr != NULL); - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */ DUK_ASSERT(thr->callstack_top <= thr->callstack_size); @@ -17554,15 +20310,22 @@ DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t flags) { } DUK_EXTERNAL void duk_push_this(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); + duk__push_this_helper(ctx, 0 /*flags*/); } DUK_INTERNAL void duk_push_this_check_object_coercible(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); + duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC /*flags*/); } DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) { duk_hobject *h; + + DUK_ASSERT_CTX_VALID(ctx); + duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC | DUK__PUSH_THIS_FLAG_TO_OBJECT /*flags*/); h = duk_get_hobject(ctx, -1); @@ -17572,6 +20335,9 @@ DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) { DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) { duk_hstring *h; + + DUK_ASSERT_CTX_VALID(ctx); + duk__push_this_helper(ctx, DUK__PUSH_THIS_FLAG_CHECK_COERC | DUK__PUSH_THIS_FLAG_TO_STRING /*flags*/); h = duk_get_hstring(ctx, -1); @@ -17579,12 +20345,25 @@ DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) { return h; } +DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx) { + duk_hthread *thr; + + DUK_ASSERT(ctx != NULL); + thr = (duk_hthread *) ctx; + + DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */ + DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */ + DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */ + + return thr->valstack_bottom - 1; +} + DUK_EXTERNAL void duk_push_current_function(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_activation *act; + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); - DUK_ASSERT(ctx != NULL); DUK_ASSERT_DISABLE(thr->callstack_top >= 0); DUK_ASSERT(thr->callstack_top <= thr->callstack_size); @@ -17599,8 +20378,8 @@ DUK_EXTERNAL void duk_push_current_function(duk_context *ctx) { DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); - DUK_ASSERT(ctx != NULL); if (thr->heap->curr_thread) { duk_push_hobject(ctx, (duk_hobject *) thr->heap->curr_thread); @@ -17610,14 +20389,14 @@ DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx) { } DUK_EXTERNAL void duk_push_global_object(duk_context *ctx) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL); } /* XXX: size optimize */ DUK_LOCAL void duk__push_stash(duk_context *ctx) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE)) { DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use")); duk_pop(ctx); @@ -17631,7 +20410,7 @@ DUK_LOCAL void duk__push_stash(duk_context *ctx) { DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; duk_heap *heap; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); heap = thr->heap; DUK_ASSERT(heap->heap_object != NULL); duk_push_hobject(ctx, heap->heap_object); @@ -17639,14 +20418,14 @@ DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx) { } DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx) { - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); duk_push_global_object(ctx); duk__push_stash(ctx); } DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); if (!target_ctx) { DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CALL_ARGS); return; /* not reached */ @@ -17659,6 +20438,7 @@ DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ct DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) { duk_int_t len; + DUK_ASSERT_CTX_VALID(ctx); DUK_UNREF(ctx); /* NUL terminator handling doesn't matter here */ @@ -17681,7 +20461,7 @@ DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va duk_int_t len; /* XXX: duk_ssize_t */ const char *res; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* special handling of fmt==NULL */ if (!fmt) { @@ -17742,6 +20522,8 @@ DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ... va_list ap; const char *ret; + DUK_ASSERT_CTX_VALID(ctx); + /* allow fmt==NULL */ va_start(ap, fmt); ret = duk_push_vsprintf(ctx, fmt, ap); @@ -17756,7 +20538,7 @@ DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobje duk_hobject *h; duk_idx_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(prototype_bidx == -1 || (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS)); @@ -17767,7 +20549,7 @@ DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobje h = duk_hobject_alloc(thr->heap, hobject_flags_and_class); if (!h) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_OBJECT_ALLOC_FAILED); + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); } DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags)); @@ -17795,6 +20577,8 @@ DUK_INTERNAL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t duk_idx_t ret; duk_hobject *h; + DUK_ASSERT_CTX_VALID(ctx); + ret = duk_push_object_helper(ctx, hobject_flags_and_class, -1); h = duk_get_hobject(ctx, -1); DUK_ASSERT(h != NULL); @@ -17804,6 +20588,8 @@ DUK_INTERNAL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t } DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); + return duk_push_object_helper(ctx, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT), @@ -17815,6 +20601,8 @@ DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx) { duk_hobject *obj; duk_idx_t ret; + DUK_ASSERT_CTX_VALID(ctx); + ret = duk_push_object_helper(ctx, DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_ARRAY_PART | @@ -17852,7 +20640,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) { duk_idx_t ret; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* check stack first */ if (thr->valstack_top >= thr->valstack_end) { @@ -17864,7 +20652,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) { DUK_HOBJECT_FLAG_THREAD | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD)); if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_THREAD_ALLOC_FAILED); + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); } obj->state = DUK_HTHREAD_STATE_INACTIVE; #if defined(DUK_USE_HEAPPTR16) @@ -17883,7 +20671,7 @@ DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) { /* important to do this *after* pushing, to make the thread reachable for gc */ if (!duk_hthread_init_stacks(thr->heap, obj)) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_THREAD_ALLOC_FAILED); + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); } /* initialize built-ins - either by copying or creating new ones */ @@ -17911,7 +20699,7 @@ DUK_INTERNAL duk_idx_t duk_push_compiledfunction(duk_context *ctx) { duk_idx_t ret; duk_tval *tv_slot; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* check stack first */ if (thr->valstack_top >= thr->valstack_end) { @@ -17928,7 +20716,7 @@ DUK_INTERNAL duk_idx_t duk_push_compiledfunction(duk_context *ctx) { DUK_HOBJECT_FLAG_COMPILEDFUNCTION | DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION)); if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_FUNC_ALLOC_FAILED); + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); } DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags)); @@ -17952,7 +20740,7 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function fu duk_tval *tv_slot; duk_uint16_t func_nargs; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* check stack first */ if (thr->valstack_top >= thr->valstack_end) { @@ -17971,7 +20759,7 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function fu obj = duk_hnativefunction_alloc(thr->heap, flags); if (!obj) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_FUNC_ALLOC_FAILED); + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); } obj->func = func; @@ -17999,6 +20787,8 @@ DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function fu DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs) { duk_uint_t flags; + DUK_ASSERT_CTX_VALID(ctx); + flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE | DUK_HOBJECT_FLAG_NATIVEFUNCTION | @@ -18014,6 +20804,8 @@ DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func DUK_INTERNAL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) { duk_uint_t flags; + DUK_ASSERT_CTX_VALID(ctx); + flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE | DUK_HOBJECT_FLAG_NATIVEFUNCTION | @@ -18028,6 +20820,8 @@ DUK_INTERNAL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function DUK_INTERNAL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) { duk_uint_t flags; + DUK_ASSERT_CTX_VALID(ctx); + flags = DUK_HOBJECT_FLAG_EXTENSIBLE | DUK_HOBJECT_FLAG_NATIVEFUNCTION | DUK_HOBJECT_FLAG_NEWENV | @@ -18043,7 +20837,7 @@ DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function fun duk_tval tv_tmp; duk_small_uint_t lf_flags; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* check stack first */ if (thr->valstack_top >= thr->valstack_end) { @@ -18075,6 +20869,35 @@ DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function fun return 0; /* not reached */ } +DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) { + duk_hthread *thr = (duk_hthread *) ctx; + duk_hbufferobject *obj; + duk_tval *tv_slot; + + DUK_ASSERT(ctx != NULL); + DUK_ASSERT(prototype_bidx >= 0); + + /* check stack first */ + if (thr->valstack_top >= thr->valstack_end) { + DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK); + } + + obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class); + if (!obj) { + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); + } + + DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]); + DUK_ASSERT_HBUFFEROBJECT_VALID(obj); + + tv_slot = thr->valstack_top; + DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj); + DUK_HOBJECT_INCREF(thr, obj); + thr->valstack_top++; + + return obj; +} + DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t ret; @@ -18083,7 +20906,7 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcod duk_bool_t noblame_fileline; #endif - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_UNREF(filename); DUK_UNREF(line); @@ -18135,6 +20958,8 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t va_list ap; duk_idx_t ret; + DUK_ASSERT_CTX_VALID(ctx); + va_start(ap, fmt); ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); va_end(ap); @@ -18148,6 +20973,8 @@ DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode va_list ap; duk_idx_t ret; + DUK_ASSERT_CTX_VALID(ctx); + duk_api_global_filename = NULL; duk_api_global_line = 0; va_start(ap, fmt); @@ -18162,7 +20989,7 @@ DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_sm duk_tval *tv_slot; duk_hbuffer *h; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); /* check stack first */ if (thr->valstack_top >= thr->valstack_end) { @@ -18176,7 +21003,7 @@ DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_sm h = duk_hbuffer_alloc(thr->heap, size, flags); if (!h) { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_BUFFER_ALLOC_FAILED); + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, DUK_STR_ALLOC_FAILED); } tv_slot = thr->valstack_top; @@ -18191,7 +21018,7 @@ DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) { duk_hthread *thr = (duk_hthread *) ctx; duk_idx_t ret; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom); @@ -18228,7 +21055,7 @@ DUK_INTERNAL duk_idx_t duk_push_object_internal(duk_context *ctx) { DUK_INTERNAL void duk_push_hstring(duk_context *ctx, duk_hstring *h) { duk_tval tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(h != NULL); DUK_TVAL_SET_STRING(&tv, h); duk_push_tval(ctx, &tv); @@ -18242,7 +21069,7 @@ DUK_INTERNAL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stri DUK_INTERNAL void duk_push_hobject(duk_context *ctx, duk_hobject *h) { duk_tval tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(h != NULL); DUK_TVAL_SET_OBJECT(&tv, h); duk_push_tval(ctx, &tv); @@ -18250,7 +21077,7 @@ DUK_INTERNAL void duk_push_hobject(duk_context *ctx, duk_hobject *h) { DUK_INTERNAL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) { duk_tval tv; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(h != NULL); DUK_TVAL_SET_BUFFER(&tv, h); duk_push_tval(ctx, &tv); @@ -18258,7 +21085,7 @@ DUK_INTERNAL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) { DUK_INTERNAL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS); DUK_ASSERT(thr->builtins[builtin_idx] != NULL); @@ -18271,7 +21098,8 @@ DUK_INTERNAL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builti DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + + DUK_ASSERT_CTX_VALID(ctx); if (count < 0) { DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT); @@ -18320,14 +21148,17 @@ DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) { } DUK_EXTERNAL void duk_pop(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); duk_pop_n(ctx, 1); } DUK_EXTERNAL void duk_pop_2(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); duk_pop_n(ctx, 2); } DUK_EXTERNAL void duk_pop_3(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); duk_pop_n(ctx, 3); } @@ -18371,7 +21202,7 @@ DUK_EXTERNAL void duk_throw(duk_context *ctx) { DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) { duk_hthread *thr = (duk_hthread *) ctx; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); DUK_ASSERT(thr != NULL); DUK_ASSERT(thr->heap != NULL); DUK_ASSERT(thr->heap->fatal_func != NULL); @@ -18389,12 +21220,17 @@ DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char } DUK_EXTERNAL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) { + DUK_ASSERT_CTX_VALID(ctx); + duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); duk_throw(ctx); } DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) { va_list ap; + + DUK_ASSERT_CTX_VALID(ctx); + va_start(ap, fmt); duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap); va_end(ap); @@ -18407,6 +21243,8 @@ DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, cons duk_int_t line; va_list ap; + DUK_ASSERT_CTX_VALID(ctx); + filename = duk_api_global_filename; line = duk_api_global_line; duk_api_global_filename = NULL; @@ -18427,12 +21265,11 @@ DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t duk_hthread *thr = (duk_hthread *) ctx; duk_tval *tv1, *tv2; + DUK_ASSERT_CTX_VALID(ctx); + tv1 = duk_get_tval(ctx, index1); - if (!tv1) { - return 0; - } tv2 = duk_get_tval(ctx, index2); - if (!tv2) { + if ((tv1 == NULL) || (tv2 == NULL)) { return 0; } @@ -18445,12 +21282,11 @@ DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) { duk_tval *tv1, *tv2; + DUK_ASSERT_CTX_VALID(ctx); + tv1 = duk_get_tval(ctx, index1); - if (!tv1) { - return 0; - } tv2 = duk_get_tval(ctx, index2); - if (!tv2) { + if ((tv1 == NULL) || (tv2 == NULL)) { return 0; } @@ -18458,6 +21294,29 @@ DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, du return duk_js_strict_equals(tv1, tv2); } +/* + * instanceof + */ + +DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) { + duk_tval *tv1, *tv2; + + DUK_ASSERT_CTX_VALID(ctx); + + /* Index validation is strict, which differs from duk_equals(). + * The strict behavior mimics how instanceof itself works, e.g. + * it is a TypeError if rval is not a -callable- object. It would + * be somewhat inconsistent if rval would be allowed to be + * non-existent without a TypeError. + */ + tv1 = duk_require_tval(ctx, index1); + DUK_ASSERT(tv1 != NULL); + tv2 = duk_require_tval(ctx, index2); + DUK_ASSERT(tv2 != NULL); + + return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2); +} + /* * Lightfunc */ @@ -18546,7 +21405,7 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_hstring *h; duk_uint8_t *buf; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); if (DUK_UNLIKELY(count_in <= 0)) { if (count_in < 0) { @@ -18640,10 +21499,14 @@ DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, } DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) { + DUK_ASSERT_CTX_VALID(ctx); + duk__concat_and_join_helper(ctx, count, 0 /*is_join*/); } DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) { + DUK_ASSERT_CTX_VALID(ctx); + duk__concat_and_join_helper(ctx, count, 1 /*is_join*/); } @@ -18657,6 +21520,8 @@ DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decod const duk_uint8_t *p, *p_start, *p_end; duk_codepoint_t cp; + DUK_ASSERT_CTX_VALID(ctx); + h_input = duk_require_hstring(ctx, index); DUK_ASSERT(h_input != NULL); @@ -18676,35 +21541,41 @@ DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decod DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata) { duk_hthread *thr = (duk_hthread *) ctx; duk_hstring *h_input; - duk_hbuffer_dynamic *h_buf; + duk_bufwriter_ctx bw_alloc; + duk_bufwriter_ctx *bw; const duk_uint8_t *p, *p_start, *p_end; duk_codepoint_t cp; + DUK_ASSERT_CTX_VALID(ctx); + index = duk_normalize_index(ctx, index); h_input = duk_require_hstring(ctx, index); DUK_ASSERT(h_input != NULL); - /* XXX: should init with a spare of at least h_input->blen? */ - duk_push_dynamic_buffer(ctx, 0); - h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf)); + bw = &bw_alloc; + DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* reasonable output estimate */ p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input); p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input); p = p_start; for (;;) { + /* XXX: could write output in chunks with fewer ensure calls, + * but relative benefit would be small here. + */ + if (p >= p_end) { break; } cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end); cp = callback(udata, cp); - duk_hbuffer_append_xutf8(thr, h_buf, cp); + + DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp); } - duk_to_string(ctx, -1); /* invalidates h_buf pointer */ + DUK_BW_COMPACT(thr, bw); + duk_to_string(ctx, -1); duk_replace(ctx, index); } @@ -18715,7 +21586,7 @@ DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t st duk_size_t start_byte_offset; duk_size_t end_byte_offset; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); index = duk_require_normalize_index(ctx, index); h = duk_require_hstring(ctx, index); @@ -18762,6 +21633,8 @@ DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index) { const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */ duk_codepoint_t cp; + DUK_ASSERT_CTX_VALID(ctx); + index = duk_require_normalize_index(ctx, index); h = duk_require_hstring(ctx, index); DUK_ASSERT(h != NULL); @@ -18833,6 +21706,8 @@ DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_hstring *h; duk_ucodepoint_t cp; + DUK_ASSERT_CTX_VALID(ctx); + h = duk_require_hstring(ctx, index); DUK_ASSERT(h != NULL); @@ -18858,7 +21733,7 @@ DUK_EXTERNAL void duk_get_var(duk_context *ctx) { duk_hstring *h_varname; duk_small_int_t throw_flag = 1; /* always throw ReferenceError for unresolvable */ - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); h_varname = duk_require_hstring(ctx, -1); /* XXX: tostring? */ DUK_ASSERT(h_varname != NULL); @@ -18892,7 +21767,7 @@ DUK_EXTERNAL void duk_put_var(duk_context *ctx) { duk_tval *tv_val; duk_small_int_t throw_flag; - DUK_ASSERT(ctx != NULL); + DUK_ASSERT_CTX_VALID(ctx); h_varname = duk_require_hstring(ctx, -2); /* XXX: tostring? */ DUK_ASSERT(h_varname != NULL); @@ -18920,11 +21795,15 @@ DUK_EXTERNAL void duk_put_var(duk_context *ctx) { } DUK_EXTERNAL duk_bool_t duk_del_var(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); + DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED); return 0; } DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx) { + DUK_ASSERT_CTX_VALID(ctx); + DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED); return 0; } @@ -20371,6 +23250,14 @@ DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) { type_error: return DUK_RET_TYPE_ERROR; } + +#undef DUK__ARRAY_MID_JOIN_LIMIT + +#undef DUK__ITER_EVERY +#undef DUK__ITER_SOME +#undef DUK__ITER_FOREACH +#undef DUK__ITER_MAP +#undef DUK__ITER_FILTER #line 1 "duk_bi_boolean.c" /* * Boolean built-ins @@ -20442,21 +23329,468 @@ DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) { } #line 1 "duk_bi_buffer.c" /* - * Buffer built-ins + * Duktape.Buffer, Node.js Buffer, and Khronos/ES6 TypedArray built-ins */ /* include removed: duk_internal.h */ /* - * Constructor + * Misc helpers + */ + +/* Map DUK_HBUFFEROBJECT_ELEM_xxx to duk_hobject class number. + * Sync with duk_hbufferobject.h and duk_hobject.h. + */ +static const duk_uint8_t duk__buffer_class_from_elemtype[9] = { + DUK_HOBJECT_CLASS_UINT8ARRAY, + DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, + DUK_HOBJECT_CLASS_INT8ARRAY, + DUK_HOBJECT_CLASS_UINT16ARRAY, + DUK_HOBJECT_CLASS_INT16ARRAY, + DUK_HOBJECT_CLASS_UINT32ARRAY, + DUK_HOBJECT_CLASS_INT32ARRAY, + DUK_HOBJECT_CLASS_FLOAT32ARRAY, + DUK_HOBJECT_CLASS_FLOAT64ARRAY +}; + +/* Map DUK_HBUFFEROBJECT_ELEM_xxx to prototype object built-in index. + * Sync with duk_hbufferobject.h. + */ +static const duk_uint16_t duk__buffer_proto_from_elemtype[9] = { + DUK_BIDX_UINT8ARRAY_PROTOTYPE, + DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, + DUK_BIDX_INT8ARRAY_PROTOTYPE, + DUK_BIDX_UINT16ARRAY_PROTOTYPE, + DUK_BIDX_INT16ARRAY_PROTOTYPE, + DUK_BIDX_UINT32ARRAY_PROTOTYPE, + DUK_BIDX_INT32ARRAY_PROTOTYPE, + DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, + DUK_BIDX_FLOAT64ARRAY_PROTOTYPE +}; + +/* Map DUK_HBUFFEROBJECT_ELEM_xxx to byte size. + */ +static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = { + 1, /* DUK__FLD_8BIT */ + 2, /* DUK__FLD_16BIT */ + 4, /* DUK__FLD_32BIT */ + 4, /* DUK__FLD_FLOAT */ + 8, /* DUK__FLD_DOUBLE */ + 0 /* DUK__FLD_VARINT; not relevant here */ +}; + +/* Bitfield for each DUK_HBUFFEROBJECT_ELEM_xxx indicating which element types + * are compatible with a blind byte copy for the TypedArray set() method (also + * used for TypedArray constructor). Array index is target buffer elem type, + * bitfield indicates compatible source types. The types must have same byte + * size and they must be coercion compatible. + */ +static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = { + /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8 */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT8) | + (1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) | + (1U << DUK_HBUFFEROBJECT_ELEM_INT8), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED + * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00. + */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT8) | + (1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT8 */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT8) | + (1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) | + (1U << DUK_HBUFFEROBJECT_ELEM_INT8), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT16 */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT16) | + (1U << DUK_HBUFFEROBJECT_ELEM_INT16), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT16 */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT16) | + (1U << DUK_HBUFFEROBJECT_ELEM_INT16), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT32 */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT32) | + (1U << DUK_HBUFFEROBJECT_ELEM_INT32), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT32 */ + (1U << DUK_HBUFFEROBJECT_ELEM_UINT32) | + (1U << DUK_HBUFFEROBJECT_ELEM_INT32), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT32 */ + (1U << DUK_HBUFFEROBJECT_ELEM_FLOAT32), + + /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT64 */ + (1U << DUK_HBUFFEROBJECT_ELEM_FLOAT64) +}; + +/* Shared helper. */ +DUK_LOCAL duk_hbufferobject *duk__getrequire_bufobj_this(duk_context *ctx, duk_bool_t throw_flag) { + duk_hthread *thr; + duk_tval *tv; + duk_hbufferobject *h_this; + + DUK_ASSERT(ctx != NULL); + thr = (duk_hthread *) ctx; + + tv = duk_get_borrowed_this_tval(ctx); + DUK_ASSERT(tv != NULL); + if (DUK_TVAL_IS_OBJECT(tv)) { + h_this = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h_this != NULL); + if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_this)) { + DUK_ASSERT_HBUFFEROBJECT_VALID(h_this); + return h_this; + } + } + + if (throw_flag) { + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); + } + return NULL; +} + +/* Check that 'this' is a duk_hbufferobject and return a pointer to it. */ +DUK_LOCAL duk_hbufferobject *duk__get_bufobj_this(duk_context *ctx) { + return duk__getrequire_bufobj_this(ctx, 0); +} + +/* Check that 'this' is a duk_hbufferobject and return a pointer to it + * (NULL if not). + */ +DUK_LOCAL duk_hbufferobject *duk__require_bufobj_this(duk_context *ctx) { + return duk__getrequire_bufobj_this(ctx, 1); +} + +/* Check that value is a duk_hbufferobject and return a pointer to it. */ +DUK_LOCAL duk_hbufferobject *duk__require_bufobj_value(duk_context *ctx, duk_idx_t index) { + duk_hthread *thr; + duk_tval *tv; + duk_hbufferobject *h_obj; + + thr = (duk_hthread *) ctx; + + /* Don't accept relative indices now. */ + DUK_ASSERT(index >= 0); + + tv = duk_require_tval(ctx, index); + DUK_ASSERT(tv != NULL); + if (DUK_TVAL_IS_OBJECT(tv)) { + h_obj = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h_obj != NULL); + if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_obj)) { + DUK_ASSERT_HBUFFEROBJECT_VALID(h_obj); + return h_obj; + } + } + + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_BUFFER); +} + +DUK_LOCAL void duk__set_bufobj_buffer(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_hbuffer *h_val) { + duk_hthread *thr; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + DUK_ASSERT(ctx != NULL); + DUK_ASSERT(h_bufobj != NULL); + DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */ + DUK_ASSERT(h_val != NULL); + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val); + DUK_ASSERT(h_bufobj->shift == 0); + DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); + + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); +} + +DUK_LOCAL duk_hbufferobject *duk__push_arraybuffer_with_length(duk_context *ctx, duk_uint_t len) { + duk_hbuffer *h_val; + duk_hbufferobject *h_bufobj; + + (void) duk_push_fixed_buffer(ctx, (duk_size_t) len); + h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1); + DUK_ASSERT(h_val != NULL); + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER), + DUK_BIDX_ARRAYBUFFER_PROTOTYPE); + DUK_ASSERT(h_bufobj != NULL); + + duk__set_bufobj_buffer(ctx, h_bufobj, h_val); + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + return h_bufobj; +} + +/* Shared offset/length coercion helper. */ +DUK_LOCAL void duk__resolve_offset_opt_length(duk_context *ctx, + duk_hbufferobject *h_bufarg, + duk_idx_t idx_offset, + duk_idx_t idx_length, + duk_uint_t *out_offset, + duk_uint_t *out_length, + duk_bool_t throw_flag) { + duk_hthread *thr; + duk_int_t offset_signed; + duk_int_t length_signed; + duk_uint_t offset; + duk_uint_t length; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + offset_signed = duk_to_int(ctx, idx_offset); + if (offset_signed < 0) { + goto fail_range; + } + offset = (duk_uint_t) offset_signed; + if (offset > h_bufarg->length) { + goto fail_range; + } + DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */ + DUK_ASSERT(offset <= h_bufarg->length); + + if (duk_is_undefined(ctx, idx_length)) { + DUK_ASSERT(h_bufarg->length >= offset); + length = h_bufarg->length - offset; /* >= 0 */ + } else { + length_signed = duk_to_int(ctx, idx_length); + if (length_signed < 0) { + goto fail_range; + } + length = (duk_uint_t) length_signed; + DUK_ASSERT(h_bufarg->length >= offset); + if (length > h_bufarg->length - offset) { + /* Unlike for negative arguments, some call sites + * want length to be clamped if it's positive. + */ + if (throw_flag) { + goto fail_range; + } else { + length = h_bufarg->length - offset; + } + } + } + DUK_ASSERT_DISABLE(length >= 0); /* unsigned */ + DUK_ASSERT(offset + length <= h_bufarg->length); + + *out_offset = offset; + *out_length = length; + return; + + fail_range: + duk_error(thr, DUK_ERR_RANGE_ERROR, DUK_STR_INVALID_CALL_ARGS); +} + +/* Shared lenient buffer length clamping helper. No negative indices, no + * element/byte shifting. + */ +DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_context *ctx, + duk_hbufferobject *h_bufobj, + duk_idx_t idx_start, + duk_idx_t idx_end, + duk_int_t *out_start_offset, + duk_int_t *out_end_offset) { + duk_int_t buffer_length; + duk_int_t start_offset; + duk_int_t end_offset; + + DUK_ASSERT(out_start_offset != NULL); + DUK_ASSERT(out_end_offset != NULL); + + buffer_length = (duk_int_t) h_bufobj->length; + + /* undefined coerces to zero which is correct */ + start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length); + if (duk_is_undefined(ctx, idx_end)) { + end_offset = buffer_length; + } else { + end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length); + } + + DUK_ASSERT(start_offset >= 0); + DUK_ASSERT(start_offset <= buffer_length); + DUK_ASSERT(end_offset >= 0); + DUK_ASSERT(end_offset <= buffer_length); + DUK_ASSERT(start_offset <= end_offset); + + *out_start_offset = start_offset; + *out_end_offset = end_offset; +} + +/* Shared lenient buffer length clamping helper. Indices are treated as + * element indices (though output values are byte offsets) which only + * really matters for TypedArray views as other buffer object have a zero + * shift. Negative indices are counted from end of input slice; crossed + * indices are clamped to zero length; and final indices are clamped + * against input slice. Used for e.g. ArrayBuffer slice(). + */ +DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx, + duk_hbufferobject *h_bufobj, + duk_idx_t idx_start, + duk_idx_t idx_end, + duk_int_t *out_start_offset, + duk_int_t *out_end_offset) { + duk_int_t buffer_length; + duk_int_t start_offset; + duk_int_t end_offset; + + DUK_ASSERT(out_start_offset != NULL); + DUK_ASSERT(out_end_offset != NULL); + + buffer_length = (duk_int_t) h_bufobj->length; + buffer_length >>= h_bufobj->shift; /* as elements */ + + /* Resolve start/end offset as element indices first; arguments + * at idx_start/idx_end are element offsets. Working with element + * indices first also avoids potential for wrapping. + */ + + start_offset = duk_to_int(ctx, idx_start); + if (start_offset < 0) { + start_offset = buffer_length + start_offset; + } + if (duk_is_undefined(ctx, idx_end)) { + end_offset = buffer_length; + } else { + end_offset = duk_to_int(ctx, idx_end); + if (end_offset < 0) { + end_offset = buffer_length + end_offset; + } + } + /* Note: start_offset/end_offset can still be < 0 here. */ + + if (start_offset < 0) { + start_offset = 0; + } else if (start_offset > buffer_length) { + start_offset = buffer_length; + } + if (end_offset < start_offset) { + end_offset = start_offset; + } else if (end_offset > buffer_length) { + end_offset = buffer_length; + } + DUK_ASSERT(start_offset >= 0); + DUK_ASSERT(start_offset <= buffer_length); + DUK_ASSERT(end_offset >= 0); + DUK_ASSERT(end_offset <= buffer_length); + DUK_ASSERT(start_offset <= end_offset); + + /* Convert indices to byte offsets. */ + start_offset <<= h_bufobj->shift; + end_offset <<= h_bufobj->shift; + + *out_start_offset = start_offset; + *out_end_offset = end_offset; +} + +/* + * Indexed read/write helpers (also used from outside this file) + */ + +DUK_INTERNAL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) { + duk_double_union du; + + DUK_MEMCPY((void *) du.uc, (const void *) p, elem_size); + + switch (h_bufobj->elem_type) { + case DUK_HBUFFEROBJECT_ELEM_UINT8: + case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED: + duk_push_uint(ctx, (duk_uint_t) du.uc[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_INT8: + duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_UINT16: + duk_push_uint(ctx, (duk_uint_t) du.us[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_INT16: + duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_UINT32: + duk_push_uint(ctx, (duk_uint_t) du.ui[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_INT32: + duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_FLOAT32: + duk_push_number(ctx, (duk_double_t) du.f[0]); + break; + case DUK_HBUFFEROBJECT_ELEM_FLOAT64: + duk_push_number(ctx, (duk_double_t) du.d); + break; + default: + DUK_UNREACHABLE(); + } +} + +DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) { + duk_double_union du; + + /* NOTE! Caller must ensure that any side effects from the + * coercions below are safe. If that cannot be guaranteed + * (which is normally the case), caller must coerce the + * argument using duk_to_number() before any pointer + * validations; the result of duk_to_number() always coerces + * without side effects here. + */ + + switch (h_bufobj->elem_type) { + case DUK_HBUFFEROBJECT_ELEM_UINT8: + du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED: + du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_INT8: + du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_UINT16: + du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_INT16: + du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_UINT32: + du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_INT32: + du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_FLOAT32: + du.f[0] = (duk_float_t) duk_to_number(ctx, -1); + break; + case DUK_HBUFFEROBJECT_ELEM_FLOAT64: + du.d = (duk_double_t) duk_to_number(ctx, -1); + break; + default: + DUK_UNREACHABLE(); + } + + DUK_MEMCPY((void *) p, (const void *) du.uc, elem_size); +} + +/* + * Duktape.Buffer: constructor */ DUK_INTERNAL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) { + duk_hthread *thr; duk_size_t buf_size; duk_small_int_t buf_dynamic; duk_uint8_t *buf_data; const duk_uint8_t *src_data; - duk_hobject *h_obj; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); /* * Constructor arguments are currently somewhat compatible with @@ -20471,54 +23805,75 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) { buf_dynamic = duk_get_boolean(ctx, 1); /* default to false */ switch (duk_get_type(ctx, 0)) { - case DUK_TYPE_NUMBER: + case DUK_TYPE_NUMBER: { /* new buffer of specified size */ buf_size = (duk_size_t) duk_to_int(ctx, 0); (void) duk_push_buffer(ctx, buf_size, buf_dynamic); break; - case DUK_TYPE_BUFFER: - /* return input buffer, converted to a Buffer object if called as a - * constructor (no change if called as a function). + } + case DUK_TYPE_BUFFER: { + /* return input buffer, converted to a Duktape.Buffer object + * if called as a constructor (no change if called as a + * function). */ duk_set_top(ctx, 1); break; - case DUK_TYPE_STRING: + } + case DUK_TYPE_STRING: { /* new buffer with string contents */ src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size); DUK_ASSERT(src_data != NULL); /* even for zero-length string */ buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic); DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size); break; - case DUK_TYPE_OBJECT: - /* Buffer object: get the plain buffer inside. If called as as - * constructor, a new Buffer object pointing to the same plain - * buffer is created below. + } + case DUK_TYPE_OBJECT: { + /* For all duk_hbufferobjects, get the plain buffer inside + * without making a copy. This is compatible with Duktape 1.2 + * but means that a slice/view information is ignored and the + * full underlying buffer is returned. + * + * If called as a constructor, a new Duktape.Buffer object + * pointing to the same plain buffer is created below. */ - h_obj = duk_get_hobject(ctx, 0); - DUK_ASSERT(h_obj != NULL); - if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) != DUK_HOBJECT_CLASS_BUFFER) { + duk_hbufferobject *h_bufobj; + h_bufobj = (duk_hbufferobject *) duk_get_hobject(ctx, 0); + DUK_ASSERT(h_bufobj != NULL); + if (!DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)) { + return DUK_RET_TYPE_ERROR; + } + if (h_bufobj->buf == NULL) { return DUK_RET_TYPE_ERROR; } - duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_VALUE); - DUK_ASSERT(duk_is_buffer(ctx, -1)); + duk_push_hbuffer(ctx, h_bufobj->buf); break; + } case DUK_TYPE_NONE: - default: + default: { return DUK_RET_TYPE_ERROR; } + } + DUK_ASSERT(duk_is_buffer(ctx, -1)); /* stack is unbalanced, but: [ buf ] */ if (duk_is_constructor_call(ctx)) { - duk_push_object_helper(ctx, - DUK_HOBJECT_FLAG_EXTENSIBLE | - DUK_HOBJECT_FLAG_EXOTIC_BUFFEROBJ | - DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), - DUK_BIDX_BUFFER_PROTOTYPE); + duk_hbufferobject *h_bufobj; + duk_hbuffer *h_val; - /* Buffer object internal value is immutable */ - duk_dup(ctx, -2); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); + h_val = duk_get_hbuffer(ctx, -1); + DUK_ASSERT(h_val != NULL); + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), + DUK_BIDX_BUFFER_PROTOTYPE); + DUK_ASSERT(h_bufobj != NULL); + + duk__set_bufobj_buffer(ctx, h_bufobj, h_val); + + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); } /* Note: unbalanced stack on purpose */ @@ -20526,29 +23881,633 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) { } /* - * toString(), valueOf() + * Node.js Buffer: constructor + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) { + /* Internal class is Object: Object.prototype.toString.call(new Buffer(0)) + * prints "[object Object]". + */ + duk_int_t len; + duk_int_t i; + duk_uint8_t *buf; + duk_hbuffer *h_buf; + duk_hbufferobject *h_bufobj; + duk_size_t buf_size; + + switch (duk_get_type(ctx, 0)) { + case DUK_TYPE_BUFFER: { + /* Custom behavior: plain buffer is used as internal buffer + * without making a copy (matches Duktape.Buffer). + */ + duk_set_top(ctx, 1); /* -> [ buffer ] */ + break; + } + case DUK_TYPE_NUMBER: { + len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX); + buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); + break; + } + case DUK_TYPE_OBJECT: { + (void) duk_get_prop_string(ctx, 0, "length"); + len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX); + duk_pop(ctx); + buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); + for (i = 0; i < len; i++) { + /* XXX: fast path for array arguments? */ + duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); + buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU); + duk_pop(ctx); + } + break; + } + case DUK_TYPE_STRING: { + /* ignore encoding for now */ + duk_dup(ctx, 0); + buf = (duk_uint8_t *) duk_to_buffer(ctx, -1, &buf_size); + break; + } + default: + return DUK_RET_TYPE_ERROR; + } + + DUK_ASSERT(duk_is_buffer(ctx, -1)); + h_buf = duk_get_hbuffer(ctx, -1); + DUK_ASSERT(h_buf != NULL); + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), + DUK_BIDX_NODEJS_BUFFER_PROTOTYPE); + DUK_ASSERT(h_bufobj != NULL); + + h_bufobj->buf = h_buf; + DUK_HBUFFER_INCREF(thr, h_buf); + DUK_ASSERT(h_bufobj->offset == 0); + h_bufobj->length = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_buf); + DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); + + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + return 1; +} + +/* + * ArrayBuffer, DataView, and TypedArray constructors + */ + +DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) { + duk_hbufferobject *h_bufobj; + duk_hbuffer *h_val; + + /* XXX: function flag to make this automatic? */ + if (!duk_is_constructor_call(ctx)) { + return DUK_RET_TYPE_ERROR; + } + + if (duk_is_buffer(ctx, 0)) { + /* Custom behavior: plain buffer is used as internal buffer + * without making a copy (matches Duktape.Buffer). + */ + + h_val = duk_get_hbuffer(ctx, 0); + DUK_ASSERT(h_val != NULL); + + /* XXX: accept any duk_hbufferobject type as an input also? */ + } else { + duk_int_t len; + len = duk_to_int(ctx, 0); + if (len < 0) { + goto fail_length; + } + (void) duk_push_fixed_buffer(ctx, (duk_size_t) len); + h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1); + DUK_ASSERT(h_val != NULL); + } + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER), + DUK_BIDX_ARRAYBUFFER_PROTOTYPE); + DUK_ASSERT(h_bufobj != NULL); + + duk__set_bufobj_buffer(ctx, h_bufobj, h_val); + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + return 1; + + fail_length: + return DUK_RET_RANGE_ERROR; +} + +/* Format of magic, bits: + * 0...1: elem size shift (0-3) + * 2...5: elem type (DUK_HBUFFEROBJECT_ELEM_xxx) + */ + +DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) { + duk_hthread *thr; + duk_tval *tv; + duk_hobject *h_obj; + duk_hbufferobject *h_bufobj = NULL; + duk_hbufferobject *h_bufarr = NULL; + duk_hbufferobject *h_bufarg = NULL; + duk_hbuffer *h_val; + duk_small_uint_t magic; + duk_small_uint_t shift; + duk_small_uint_t elem_type; + duk_small_uint_t elem_size; + duk_small_uint_t class_num; + duk_small_uint_t proto_bidx; + duk_uint_t align_mask; + duk_uint_t elem_length; + duk_int_t elem_length_signed; + duk_uint_t byte_length; + duk_small_uint_t copy_mode; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + /* XXX: function flag to make this automatic? */ + if (!duk_is_constructor_call(ctx)) { + return DUK_RET_TYPE_ERROR; + } + + /* We could fit built-in index into magic but that'd make the magic + * number dependent on built-in numbering (genbuiltins.py doesn't + * handle that yet). So map both class and prototype from the + * element type. + */ + magic = duk_get_current_magic(ctx); + shift = magic & 0x03; /* bits 0...1: shift */ + elem_type = (magic >> 2) & 0x0f; /* bits 2...5: type */ + elem_size = 1 << shift; + align_mask = elem_size - 1; + DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t)); + proto_bidx = duk__buffer_proto_from_elemtype[elem_type]; + DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS); + DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t)); + class_num = duk__buffer_class_from_elemtype[elem_type]; + + DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, " + "elem_size=%d, proto_bidx=%d, class_num=%d", + (int) magic, (int) shift, (int) elem_type, (int) elem_size, + (int) proto_bidx, (int) class_num)); + + /* Argument variants. When the argument is an ArrayBuffer a view to + * the same buffer is created; otherwise a new ArrayBuffer is always + * created. + */ + + tv = duk_get_tval(ctx, 0); + DUK_ASSERT(tv != NULL); /* arg count */ + if (DUK_TVAL_IS_OBJECT(tv)) { + h_obj = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h_obj != NULL); + + if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) { + /* ArrayBuffer: unlike any other argument variant, create + * a view into the existing buffer. + */ + + duk_int_t byte_offset_signed; + duk_uint_t byte_offset; + + h_bufarg = (duk_hbufferobject *) h_obj; + + byte_offset_signed = duk_to_int(ctx, 1); + if (byte_offset_signed < 0) { + goto fail_arguments; + } + byte_offset = (duk_uint_t) byte_offset_signed; + if (byte_offset > h_bufarg->length || + (byte_offset & align_mask) != 0) { + /* Must be >= 0 and multiple of element size. */ + goto fail_arguments; + } + if (duk_is_undefined(ctx, 2)) { + DUK_ASSERT(h_bufarg->length >= byte_offset); + byte_length = h_bufarg->length - byte_offset; + if ((byte_length & align_mask) != 0) { + /* Must be element size multiple from + * start offset to end of buffer. + */ + goto fail_arguments; + } + elem_length = (byte_length >> shift); + } else { + elem_length_signed = duk_to_int(ctx, 2); + if (elem_length_signed < 0) { + goto fail_arguments; + } + elem_length = (duk_uint_t) elem_length_signed; + byte_length = elem_length << shift; + if ((byte_length >> shift) != elem_length) { + /* Byte length would overflow. */ + /* XXX: easier check with less code? */ + goto fail_arguments; + } + DUK_ASSERT(h_bufarg->length >= byte_offset); + if (byte_length > h_bufarg->length - byte_offset) { + /* Not enough data. */ + goto fail_arguments; + } + } + DUK_ASSERT_DISABLE(byte_offset >= 0); + DUK_ASSERT(byte_offset <= h_bufarg->length); + DUK_ASSERT_DISABLE(byte_length >= 0); + DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length); + DUK_ASSERT((elem_length << shift) == byte_length); + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(class_num), + proto_bidx); + h_val = h_bufarg->buf; + if (h_val == NULL) { + return DUK_RET_TYPE_ERROR; + } + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + h_bufobj->offset = h_bufarg->offset + byte_offset; + h_bufobj->length = byte_length; + h_bufobj->shift = shift; + h_bufobj->elem_type = elem_type; + h_bufobj->is_view = 1; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + /* Set .buffer to the argument ArrayBuffer. */ + duk_dup(ctx, 0); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); + duk_compact(ctx, -1); + return 1; + } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) { + /* TypedArray (or other non-ArrayBuffer duk_hbufferobject). + * Conceptually same behavior as for an Array-like argument, + * with a few fast paths. + */ + + h_bufarg = (duk_hbufferobject *) h_obj; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg); + elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift); + if (h_bufarg->buf == NULL) { + return DUK_RET_TYPE_ERROR; + } + + /* Select copy mode. Must take into account element + * compatibility and validity of the underlying source + * buffer. + */ + + DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, " + "src byte_length=%ld, src shift=%d, " + "src/dst elem_length=%ld; " + "dst shift=%d -> dst byte_length=%ld", + (long) h_bufarg->length, (int) h_bufarg->shift, + (long) elem_length_signed, (int) shift, + (long) (elem_length_signed << shift))); + + copy_mode = 2; /* default is explicit index read/write copy */ + DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t)); + if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) { + if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) { + DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy")); + DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */ + copy_mode = 0; + } else { + DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy")); + copy_mode = 1; + } + } + } else { + /* Array or Array-like */ + elem_length_signed = (duk_int_t) duk_get_length(ctx, 0); + copy_mode = 2; + } + } else { + /* Non-object argument is simply int coerced, matches + * V8 behavior (except for "null", which we coerce to + * 0 but V8 TypeErrors). + */ + elem_length_signed = duk_to_int(ctx, 0); + copy_mode = 3; + } + if (elem_length_signed < 0) { + goto fail_arguments; + } + elem_length = (duk_uint_t) elem_length_signed; + byte_length = (duk_uint_t) (elem_length << shift); + if ((byte_length >> shift) != elem_length) { + /* Byte length would overflow. */ + /* XXX: easier check with less code? */ + goto fail_arguments; + } + + DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld", + (long) elem_length, (long) byte_length)); + + /* ArrayBuffer argument is handled specially above; the rest of the + * argument variants are handled by shared code below. + */ + + /* Push a new ArrayBuffer (becomes view .buffer) */ + h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length); + DUK_ASSERT(h_bufarr != NULL); + h_val = h_bufarr->buf; + DUK_ASSERT(h_val != NULL); + + /* Push the resulting view object and attach the ArrayBuffer. */ + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(class_num), + proto_bidx); + + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + DUK_ASSERT(h_bufobj->offset == 0); + h_bufobj->length = byte_length; + h_bufobj->shift = shift; + h_bufobj->elem_type = elem_type; + h_bufobj->is_view = 1; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + + /* Set .buffer */ + duk_dup(ctx, -2); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); + duk_compact(ctx, -1); + + /* Copy values, the copy method depends on the arguments. + * + * Copy mode decision may depend on the validity of the underlying + * buffer of the source argument; there must be no harmful side effects + * from there to here for copy_mode to still be valid. + */ + DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode)); + switch (copy_mode) { + case 0: { + /* Use byte copy. */ + + duk_uint8_t *p_src; + duk_uint8_t *p_dst; + + DUK_ASSERT(h_bufobj != NULL); + DUK_ASSERT(h_bufobj->buf != NULL); + DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)); + DUK_ASSERT(h_bufarg != NULL); + DUK_ASSERT(h_bufarg->buf != NULL); + DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)); + + p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj); + p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg); + + DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld", + (void *) p_src, (void *) p_dst, (long) byte_length)); + + DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length); + break; + } + case 1: { + /* Copy values through direct validated reads and writes. */ + + duk_small_uint_t src_elem_size; + duk_small_uint_t dst_elem_size; + duk_uint8_t *p_src; + duk_uint8_t *p_src_end; + duk_uint8_t *p_dst; + + DUK_ASSERT(h_bufobj != NULL); + DUK_ASSERT(h_bufobj->buf != NULL); + DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)); + DUK_ASSERT(h_bufarg != NULL); + DUK_ASSERT(h_bufarg->buf != NULL); + DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)); + + src_elem_size = 1 << h_bufarg->shift; + dst_elem_size = elem_size; + + p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg); + p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj); + p_src_end = p_src + h_bufarg->length; + + DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, " + "src_elem_size=%d, dst_elem_size=%d", + (void *) p_src, (void *) p_src_end, (void *) p_dst, + (int) src_elem_size, (int) dst_elem_size)); + + while (p_src != p_src_end) { + DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: " + "p_src=%p, p_src_end=%p, p_dst=%p", + (void *) p_src, (void *) p_src_end, (void *) p_dst)); + /* A validated read() is always a number, so it's write coercion + * is always side effect free an won't invalidate pointers etc. + */ + duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size); + duk_hbufferobject_validated_write(ctx, h_bufobj, p_dst, dst_elem_size); + duk_pop(ctx); + p_src += src_elem_size; + p_dst += dst_elem_size; + } + break; + } + case 2: { + /* Copy values by index reads and writes. Let virtual + * property handling take care of coercion. + */ + duk_uint_t i; + + DUK_DDD(DUK_DDDPRINT("using slow copy")); + + for (i = 0; i < elem_length; i++) { + duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); + duk_put_prop_index(ctx, -2, (duk_uarridx_t) i); + } + break; + } + default: + case 3: { + /* No copy, leave zero bytes in the buffer. There's no + * ambiguity with Float32/Float64 because zero bytes also + * represent 0.0. + */ + + DUK_DDD(DUK_DDDPRINT("using no copy")); + break; + } + } + + return 1; + + fail_arguments: + return DUK_RET_RANGE_ERROR; +} + +DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) { + duk_hbufferobject *h_bufarg; + duk_hbufferobject *h_bufobj; + duk_hbuffer *h_val; + duk_uint_t offset; + duk_uint_t length; + + /* XXX: function flag to make this automatic? */ + if (!duk_is_constructor_call(ctx)) { + return DUK_RET_TYPE_ERROR; + } + + h_bufarg = duk__require_bufobj_value(ctx, 0); + DUK_ASSERT(h_bufarg != NULL); + + duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/); + DUK_ASSERT(offset <= h_bufarg->length); + DUK_ASSERT(offset + length <= h_bufarg->length); + + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW), + DUK_BIDX_DATAVIEW_PROTOTYPE); + + h_val = h_bufarg->buf; + if (h_val == NULL) { + return DUK_RET_TYPE_ERROR; + } + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + h_bufobj->offset = h_bufarg->offset + offset; + h_bufobj->length = length; + DUK_ASSERT(h_bufobj->shift == 0); + DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8); + h_bufobj->is_view = 1; + + /* The DataView .buffer property is ordinarily set to the argument + * which is an ArrayBuffer. We accept any duk_hbufferobject as + * an argument and .buffer will be set to the argument regardless + * of what it is. This may be a bit confusing if the argument + * is e.g. a DataView or another TypedArray view. + * + * XXX: Copy .buffer property from a DataView/TypedArray argument? + * Create a fresh ArrayBuffer for Duktape.Buffer and Node.js Buffer + * arguments? See: test-bug-dataview-buffer-prop.js. + */ + + duk_dup(ctx, 0); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); + duk_compact(ctx, -1); + + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + return 1; +} + +/* + * ArrayBuffer.isView() + */ + +DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) { + duk_hobject *h_obj; + duk_bool_t ret = 0; + + h_obj = duk_get_hobject(ctx, 0); + if (h_obj != NULL && DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) { + ret = ((duk_hbufferobject *) h_obj)->is_view; + } + duk_push_boolean(ctx, ret); + return 1; +} + +/* + * Node.js Buffer: toString([encoding], [start], [end]) + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) { + duk_hthread *thr; + duk_hbufferobject *h_this; + duk_int_t start_offset, end_offset; + duk_uint8_t *buf_slice; + duk_size_t slice_length; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + h_this = duk__get_bufobj_this(ctx); + if (h_this == NULL) { + /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */ + duk_push_string(ctx, "[object Object]"); + return 1; + } + DUK_ASSERT_HBUFFEROBJECT_VALID(h_this); + + /* ignore encoding for now */ + + duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &start_offset, &end_offset); + + slice_length = (duk_size_t) (end_offset - start_offset); + buf_slice = (duk_uint8_t *) duk_push_fixed_buffer(ctx, slice_length); + DUK_ASSERT(buf_slice != NULL); + + if (h_this->buf == NULL) { + goto type_error; + } + + if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) { + DUK_MEMCPY((void *) buf_slice, + (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset), + slice_length); + } else { + /* not covered, return all zeroes */ + ; + } + + duk_to_string(ctx, -1); + return 1; + + type_error: + return DUK_RET_TYPE_ERROR; +} + +/* + * Duktape.Buffer: toString(), valueOf() */ DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) { + duk_hthread *thr; duk_tval *tv; duk_small_int_t to_string = duk_get_current_magic(ctx); - duk_push_this(ctx); - tv = duk_require_tval(ctx, -1); + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + tv = duk_get_borrowed_this_tval(ctx); DUK_ASSERT(tv != NULL); if (DUK_TVAL_IS_BUFFER(tv)) { - /* nop */ + duk_hbuffer *h_buf; + h_buf = DUK_TVAL_GET_BUFFER(tv); + DUK_ASSERT(h_buf != NULL); + duk_push_hbuffer(ctx, h_buf); } else if (DUK_TVAL_IS_OBJECT(tv)) { - duk_hobject *h = DUK_TVAL_GET_OBJECT(tv); - DUK_ASSERT(h != NULL); + duk_hobject *h; + duk_hbufferobject *h_bufobj; - /* Must be a "buffer object", i.e. class "Buffer" */ - if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_BUFFER) { + /* Accept any duk_hbufferobject, though we're only normally + * called for Duktape.Buffer values. + */ + h = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h != NULL); + if (!DUK_HOBJECT_IS_BUFFEROBJECT(h)) { + DUK_DD(DUK_DDPRINT("toString/valueOf() called for a non-bufferobject object")); goto type_error; } + h_bufobj = (duk_hbufferobject *) h; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); + if (h_bufobj->buf == NULL) { + DUK_DD(DUK_DDPRINT("toString/valueOf() called for a bufferobject with NULL buf")); + goto type_error; + } + duk_push_hbuffer(ctx, h_bufobj->buf); } else { goto type_error; } @@ -20561,120 +24520,1510 @@ DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) type_error: return DUK_RET_TYPE_ERROR; } -#line 1 "duk_bi_date.c" -/* - * Date built-ins - * - * Unlike most built-ins, Date has a lot of platform dependencies for - * getting UTC time, converting between UTC and local time, and parsing - * and formatting time values. - * - * See doc/datetime.txt. - * - * Platform specific links: - * - * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx - */ - -/* include removed: duk_internal.h */ /* - * Platform specific includes and defines - * - * Note that necessary system headers (like ) are included - * by duk_internal.h (or duk_features.h, which is included by duk_internal.h) - * because the header locations vary between systems and we don't want - * that clutter here. + * Node.js Buffer.prototype: toJSON() */ -#define DUK__GET_NOW_TIMEVAL duk_bi_date_get_now -#define DUK__GET_LOCAL_TZOFFSET duk__get_local_tzoffset - -/* Buffer sizes for some UNIX calls. Larger than strictly necessary - * to avoid Valgrind errors. +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) { + duk_hthread *thr; + duk_hbufferobject *h_this; + duk_uint8_t *buf; + duk_uint_t i; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + h_this = duk__require_bufobj_this(ctx); + DUK_ASSERT(h_this != NULL); + + if (h_this->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) { + /* Serialize uncovered backing buffer as a null; doesn't + * really matter as long we're memory safe. + */ + duk_push_null(ctx); + return 1; + } + + duk_push_object(ctx); + duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_BUFFER); + duk_put_prop_stridx(ctx, -2, DUK_STRIDX_TYPE); + + duk_push_array(ctx); + for (i = 0; i < h_this->length; i++) { + /* XXX: regetting the pointer may be overkill - we're writing + * to a side-effect free array here. + */ + DUK_ASSERT(h_this->buf != NULL); + buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this); + duk_push_uint(ctx, (duk_uint_t) buf[i]); + duk_put_prop_index(ctx, -2, (duk_idx_t) i); + } + duk_put_prop_stridx(ctx, -2, DUK_STRIDX_DATA); + + return 1; +} + +/* + * Node.js Buffer.prototype.equals() + * Node.js Buffer.prototype.compare() + * Node.js Buffer.compare() */ -#define DUK__STRPTIME_BUF_SIZE 64 -#define DUK__STRFTIME_BUF_SIZE 64 + +DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) { + duk_hthread *thr; + duk_small_uint_t magic; + duk_hbufferobject *h_bufarg1; + duk_hbufferobject *h_bufarg2; + duk_small_int_t comp_res; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + magic = duk_get_current_magic(ctx); + if (magic & 0x02) { + /* Static call style. */ + h_bufarg1 = duk__require_bufobj_value(ctx, 0); + h_bufarg2 = duk__require_bufobj_value(ctx, 1); + } else { + h_bufarg1 = duk__require_bufobj_this(ctx); + h_bufarg2 = duk__require_bufobj_value(ctx, 0); + } + DUK_ASSERT(h_bufarg1 != NULL); + DUK_ASSERT(h_bufarg2 != NULL); + + /* We want to compare the slice/view areas of the arguments. + * If either slice/view is invalid (underlying buffer is shorter) + * ensure equals() is false, but otherwise the only thing that + * matters is to be memory safe. + */ + + if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg1) && + DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg2)) { + comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset, + (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset, + (duk_size_t) h_bufarg1->length, + (duk_size_t) h_bufarg2->length); + } else { + comp_res = -1; /* either nonzero value is ok */ + } + + if (magic & 0x01) { + /* compare: similar to string comparison but for buffer data. */ + duk_push_int(ctx, comp_res); + } else { + /* equals */ + duk_push_boolean(ctx, (comp_res == 0)); + } + + return 1; +} /* - * Other file level defines + * Node.js Buffer.prototype.fill() + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) { + duk_hthread *thr; + duk_hbufferobject *h_this; + const duk_uint8_t *fill_str_ptr; + duk_size_t fill_str_len; + duk_uint8_t fill_value; + duk_int_t fill_offset; + duk_int_t fill_end; + duk_size_t fill_length; + duk_uint8_t *p; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + h_this = duk__require_bufobj_this(ctx); + DUK_ASSERT(h_this != NULL); + if (h_this->buf == NULL) { + return DUK_RET_TYPE_ERROR; + } + + /* [ value offset end ] */ + + if (duk_is_string(ctx, 0)) { + fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len); + DUK_ASSERT(fill_str_ptr != NULL); + } else { + fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0); + fill_str_ptr = (const duk_uint8_t *) &fill_value; + fill_str_len = 1; + } + + /* Fill offset handling is more lenient than in Node.js. */ + + duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &fill_offset, &fill_end); + + DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld", + (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length)); + + DUK_ASSERT(fill_end - fill_offset >= 0); + DUK_ASSERT(h_this->buf != NULL); + + p = (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + fill_offset); + fill_length = (duk_size_t) (fill_end - fill_offset); + if (fill_str_len == 1) { + /* Handle single character fills as memset() even when + * the fill data comes from a one-char argument. + */ + DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length); + } else if (fill_str_len > 1) { + duk_size_t i, n, t; + + for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) { + p[i] = fill_str_ptr[t++]; + if (t >= fill_str_len) { + t = 0; + } + } + } else { + DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently")); + } + + /* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */ + duk_push_this(ctx); + return 1; +} + +/* + * Node.js Buffer.prototype.write(string, [offset], [length], [encoding]) + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) { + duk_hthread *thr; + duk_hbufferobject *h_this; + duk_uint_t offset; + duk_uint_t length; + const duk_uint8_t *str_data; + duk_size_t str_len; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + h_this = duk__require_bufobj_this(ctx); + DUK_ASSERT(h_this != NULL); + + /* Argument must be a string, e.g. a buffer is not allowed. */ + str_data = (const duk_uint8_t *) duk_require_lstring(ctx, 0, &str_len); + + duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/); + DUK_ASSERT(offset <= h_this->length); + DUK_ASSERT(offset + length <= h_this->length); + + /* XXX: encoding is ignored now. */ + + if (length > str_len) { + length = (duk_uint_t) str_len; + } + + if (DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) { + /* Cannot overlap. */ + DUK_MEMCPY((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset), + (const void *) str_data, + (size_t) length); + } else { + DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore")); + } + + duk_push_uint(ctx, length); + return 1; +} + +/* + * Node.js Buffer.prototype.copy() + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) { + duk_hthread *thr; + duk_hbufferobject *h_this; + duk_hbufferobject *h_bufarg; + duk_int_t source_length; + duk_int_t target_length; + duk_int_t target_start, source_start, source_end; + duk_uint_t target_ustart, source_ustart, source_uend; + duk_uint_t copy_size = 0; + + /* [ targetBuffer targetStart sourceStart sourceEnd ] */ + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + h_this = duk__require_bufobj_this(ctx); + h_bufarg = duk__require_bufobj_value(ctx, 0); + DUK_ASSERT(h_this != NULL); + DUK_ASSERT(h_bufarg != NULL); + source_length = (duk_int_t) h_this->length; + target_length = (duk_int_t) h_bufarg->length; + + target_start = duk_to_int(ctx, 1); + source_start = duk_to_int(ctx, 2); + if (duk_is_undefined(ctx, 3)) { + source_end = source_length; + } else { + source_end = duk_to_int(ctx, 3); + } + + DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, " + "source_start=%ld, source_end=%ld, source_length=%ld", + (long) target_start, (long) h_bufarg->length, + (long) source_start, (long) source_end, (long) source_length)); + + /* This behavior mostly mimics Node.js now. */ + + if (source_start < 0 || source_end < 0 || target_start < 0) { + /* Negative offsets cause a RangeError. */ + goto fail_bounds; + } + source_ustart = (duk_uint_t) source_start; + source_uend = (duk_uint_t) source_end; + target_ustart = (duk_uint_t) target_start; + if (source_ustart >= source_uend || /* crossed offsets or zero size */ + source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */ + target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */ + goto silent_ignore; + } + if (source_uend >= (duk_uint_t) source_length) { + /* Source end clamped silently to available length. */ + source_uend = source_length; + } + copy_size = source_uend - source_ustart; + if (target_ustart + copy_size > (duk_uint_t) target_length) { + /* Clamp to target's end if too long. + * + * NOTE: there's no overflow possibility in the comparison; + * both target_ustart and copy_size are >= 0 and based on + * values in duk_int_t range. Adding them as duk_uint_t + * values is then guaranteed not to overflow. + */ + DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */ + DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */ + copy_size = (duk_uint_t) target_length - target_ustart; + } + + DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu", + (unsigned long) target_ustart, (unsigned long) source_ustart, + (unsigned long) copy_size)); + + DUK_ASSERT(copy_size >= 1); + DUK_ASSERT(source_ustart <= (duk_uint_t) source_length); + DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length); + DUK_ASSERT(target_ustart <= (duk_uint_t) target_length); + DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length); + + /* Ensure copy is covered by underlying buffers. */ + DUK_ASSERT(h_bufarg->buf != NULL); /* length check */ + DUK_ASSERT(h_this->buf != NULL); /* length check */ + if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) && + DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) { + /* Must use memmove() because copy area may overlap (source and target + * buffer may be the same, or from different slices. + */ + DUK_MEMMOVE((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart), + (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + source_ustart), + (size_t) copy_size); + } else { + DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring")); + } + + silent_ignore: + /* Return value is like write(), number of bytes written. + * The return value matters because of code like: + * "off += buf.copy(...)". + */ + duk_push_uint(ctx, copy_size); + return 1; + + fail_bounds: + return DUK_RET_RANGE_ERROR; +} + +/* + * TypedArray.prototype.set() + * + * TypedArray set() is pretty interesting to implement because: + * + * - The source argument may be a plain array or a typedarray. If the + * source is a TypedArray, values are decoded and re-encoded into the + * target (not as a plain byte copy). This may happen even when the + * element byte size is the same, e.g. integer values may be re-encoded + * into floats. + * + * - Source and target may refer to the same underlying buffer, so that + * the set() operation may overlap. The specification requires that this + * must work as if a copy was made before the operation. Note that this + * is NOT a simple memmove() situation because the source and target + * byte sizes may be different -- e.g. a 4-byte source (Int8Array) may + * expand to a 16-byte target (Uint32Array) so that the target overlaps + * the source both from beginning and the end (unlike in typical memmove). + * + * - Even if 'buf' pointers of the source and target differ, there's no + * guarantee that their memory areas don't overlap. This may be the + * case with external buffers. + * + * Even so, it is nice to optimize for the common case: + * + * - Source and target separate buffers or non-overlapping. + * + * - Source and target have a compatible type so that a plain byte copy + * is possible. Note that while e.g. uint8 and int8 are compatible + * (coercion one way or another doesn't change the byte representation), + * e.g. int8 and uint8clamped are NOT compatible when writing int8 + * values into uint8clamped typedarray (-1 would clamp to 0 for instance). + * + * See test-bi-typedarray-proto-set.js. + */ + +DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) { + duk_hthread *thr; + duk_hbufferobject *h_this; + duk_hobject *h_obj; + duk_uarridx_t i, n; + duk_int_t offset_signed; + duk_uint_t offset_elems; + duk_uint_t offset_bytes; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + h_this = duk__require_bufobj_this(ctx); + DUK_ASSERT(h_this != NULL); + DUK_ASSERT_HBUFFEROBJECT_VALID(h_this); + + if (h_this->buf == NULL) { + DUK_DDD(DUK_DDDPRINT("source neutered, skip copy")); + return 0; + } + + h_obj = duk_require_hobject(ctx, 0); + DUK_ASSERT(h_obj != NULL); + + /* XXX: V8 throws a TypeError for negative values. Would it + * be more useful to interpret negative offsets here from the + * end of the buffer too? + */ + offset_signed = duk_to_int(ctx, 1); + if (offset_signed < 0) { + return DUK_RET_TYPE_ERROR; + } + offset_elems = (duk_uint_t) offset_signed; + offset_bytes = offset_elems << h_this->shift; + if ((offset_bytes >> h_this->shift) != offset_elems) { + /* Byte length would overflow. */ + /* XXX: easier check with less code? */ + return DUK_RET_RANGE_ERROR; + } + if (offset_bytes > h_this->length) { + /* Equality may be OK but >length not. Checking + * this explicitly avoids some overflow cases + * below. + */ + return DUK_RET_RANGE_ERROR; + } + DUK_ASSERT(offset_bytes <= h_this->length); + + /* Fast path: source is a TypedArray (or any bufferobject). */ + + if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) { + duk_hbufferobject *h_bufarg; + duk_uint16_t comp_mask; + duk_small_int_t no_overlap = 0; + duk_uint_t src_length; + duk_uint_t dst_length; + duk_uint_t dst_length_elems; + duk_uint8_t *p_src_base; + duk_uint8_t *p_src_end; + duk_uint8_t *p_src; + duk_uint8_t *p_dst_base; + duk_uint8_t *p_dst; + duk_small_uint_t src_elem_size; + duk_small_uint_t dst_elem_size; + + h_bufarg = (duk_hbufferobject *) h_obj; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg); + + if (h_bufarg->buf == NULL) { + DUK_DDD(DUK_DDDPRINT("target neutered, skip copy")); + return 0; + } + + /* Nominal size check. */ + src_length = h_bufarg->length; /* bytes in source */ + dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */ + dst_length = dst_length_elems << h_this->shift; /* bytes in dest */ + if ((dst_length >> h_this->shift) != dst_length_elems) { + /* Byte length would overflow. */ + /* XXX: easier check with less code? */ + return DUK_RET_RANGE_ERROR; + } + DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld", + (long) src_length, (long) dst_length)); + DUK_ASSERT(offset_bytes <= h_this->length); + if (dst_length > h_this->length - offset_bytes) { + /* Overflow not an issue because subtraction is used on the right + * side and guaranteed to be >= 0. + */ + DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length")); + return DUK_RET_RANGE_ERROR; + } + if (!DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) { + DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore")); + return 0; + } + + p_src_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg); + p_dst_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes; + + /* Check actual underlying buffers for validity and that they + * cover the copy. No side effects are allowed after the check + * so that the validity status doesn't change. + */ + if (!DUK_HBUFFEROBJECT_VALID_SLICE(h_this) || + !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) { + /* The condition could be more narrow and check for the + * copy area only, but there's no need for fine grained + * behavior when the underlying buffer is misconfigured. + */ + DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy")); + return 0; + } + + /* We want to do a straight memory copy if possible: this is + * an important operation because .set() is the TypedArray + * way to copy chunks of memory. However, because set() + * conceptually works in terms of elements, not all views are + * compatible with direct byte copying. + * + * If we do manage a direct copy, the "overlap issue" handled + * below can just be solved using memmove() because the source + * and destination element sizes are necessarily equal. + */ + + DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t)); + comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type]; + if (comp_mask & (1 << h_bufarg->elem_type)) { + DUK_ASSERT(src_length == dst_length); + + DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible")); + DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length); + return 0; + } + DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item")); + + /* We want to avoid making a copy to process set() but that's + * not always possible: the source and the target may overlap + * and because element sizes are different, the overlap cannot + * always be handled with a memmove() or choosing the copy + * direction in a certain way. For example, if source type is + * uint8 and target type is uint32, the target area may exceed + * the source area from both ends! + * + * Note that because external buffers may point to the same + * memory areas, we must ultimately make this check using + * pointers. + * + * NOTE: careful with side effects: any side effect may cause + * a buffer resize (or external buffer pointer/length update)! + */ + + DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, " + "p_dst_base=%p, dst_length=%ld", + (void *) p_src_base, (long) src_length, + (void *) p_dst_base, (long) dst_length)); + + if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */ + p_src_base + src_length < p_dst_base) { /* source ends before dest starts */ + no_overlap = 1; + } + + if (!no_overlap) { + /* There's overlap: the desired end result is that + * conceptually a copy is made to avoid "trampling" + * of source data by destination writes. We make + * an actual temporary copy to handle this case. + */ + duk_uint8_t *p_src_copy; + + DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source")); + p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_length); + DUK_ASSERT(p_src_copy != NULL); + DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length); + + p_src_base = p_src_copy; /* use p_src_base from now on */ + } + /* Value stack intentionally mixed size here. */ + + DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, " + "p_dst_base=%p, dst_length=%ld, valstack top=%ld", + (void *) p_src_base, (long) src_length, + (void *) p_dst_base, (long) dst_length, + (long) duk_get_top(ctx))); + + /* Ready to make the copy. We must proceed element by element + * and must avoid any side effects that might cause the buffer + * validity check above to become invalid. + * + * Although we work through the value stack here, only plain + * numbers are handled which should be side effect safe. + */ + + src_elem_size = 1 << h_bufarg->shift; + dst_elem_size = 1 << h_this->shift; + p_src = p_src_base; + p_dst = p_dst_base; + p_src_end = p_src_base + src_length; + + while (p_src != p_src_end) { + DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: " + "p_src=%p, p_src_end=%p, p_dst=%p", + (void *) p_src, (void *) p_src_end, (void *) p_dst)); + /* A validated read() is always a number, so it's write coercion + * is always side effect free an won't invalidate pointers etc. + */ + duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size); + duk_hbufferobject_validated_write(ctx, h_this, p_dst, dst_elem_size); + duk_pop(ctx); + p_src += src_elem_size; + p_dst += dst_elem_size; + } + + return 0; + } else { + /* Slow path: quite slow, but we save space by using the property code + * to write coerce target values. We don't need to worry about overlap + * here because the source is not a TypedArray. + * + * We could use the bufferobject write coercion helper but since the + * property read may have arbitrary side effects, full validity checks + * would be needed for every element anyway. + */ + + n = (duk_uarridx_t) duk_get_length(ctx, 0); + DUK_ASSERT(offset_bytes <= h_this->length); + if ((n << h_this->shift) > h_this->length - offset_bytes) { + /* Overflow not an issue because subtraction is used on the right + * side and guaranteed to be >= 0. + */ + DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length")); + return DUK_RET_RANGE_ERROR; + } + + /* There's no need to check for buffer validity status for the + * target here: the property access code will do that for each + * element. Moreover, if we did check the validity here, side + * effects from reading the source argument might invalidate + * the results anyway. + */ + + DUK_ASSERT_TOP(ctx, 2); + duk_push_this(ctx); + + for (i = 0; i < n; i++) { + duk_get_prop_index(ctx, 0, i); + duk_put_prop_index(ctx, 2, offset_elems + i); + } + } + + return 0; +} + +/* + * Node.js Buffer.prototype.slice([start], [end]) + * ArrayBuffer.prototype.slice(begin, [end]) + * TypedArray.prototype.slice(begin, [end]) + * + * The API calls are almost identical; negative indices are counted from end + * of buffer, and final indices are clamped (allowing crossed indices). Main + * differences: + * + * - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create + * views, ArrayBuffer .slice() creates a copy + * + * - Resulting object has a different class and prototype depending on the + * call (or 'this' argument) + * + * - TypedArray .subarray() arguments are element indices, not byte offsets + */ + +DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) { + duk_hthread *thr; + duk_small_int_t magic; + duk_small_uint_t res_class_num; + duk_hobject *res_proto; + duk_hbufferobject *h_this; + duk_hbufferobject *h_bufobj; + duk_hbuffer *h_val; + duk_int_t start_offset, end_offset; + duk_uint_t slice_length; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + /* [ start end ] */ + + magic = duk_get_current_magic(ctx); + h_this = duk__require_bufobj_this(ctx); + + /* Slice offsets are element (not byte) offsets, which only matters + * for TypedArray views, Node.js Buffer and ArrayBuffer have shift + * zero so byte and element offsets are the same. Negative indices + * are counted from end of slice, crossed indices are allowed (and + * result in zero length result), and final values are clamped + * against the current slice. There's intentionally no check + * against the underlying buffer here. + */ + + duk__clamp_startend_negidx_shifted(ctx, h_this, 0 /*idx_start*/, 1 /*idx_end*/, &start_offset, &end_offset); + DUK_ASSERT(end_offset >= start_offset); + slice_length = (duk_uint_t) (end_offset - start_offset); + + /* The resulting buffer object gets the same class and prototype as + * the buffer in 'this', e.g. if the input is a Node.js Buffer the + * result is a Node.js Buffer; if the input is a Float32Array, the + * result is a Float32Array. + * + * For the class number this seems correct. The internal prototype + * is not so clear: if 'this' is a bufferobject with a non-standard + * prototype object, that value gets copied over into the result + * (instead of using the standard prototype for that object type). + */ + + res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this); + h_bufobj = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num), + DUK_BIDX_OBJECT_PROTOTYPE); /* replaced */ + DUK_ASSERT(h_bufobj != NULL); + res_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_this); /* may be NULL */ + DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_bufobj, res_proto); + + h_bufobj->length = slice_length; + h_bufobj->shift = h_this->shift; /* inherit */ + h_bufobj->elem_type = h_this->elem_type; /* inherit */ + h_bufobj->is_view = magic & 0x01; + DUK_ASSERT(h_bufobj->is_view == 0 || h_bufobj->is_view == 1); + + h_val = h_this->buf; + if (h_val == NULL) { + return DUK_RET_TYPE_ERROR; + } + + if (magic & 0x02) { + /* non-zero: make copy */ + duk_uint8_t *p_copy; + duk_size_t copy_length; + + p_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) slice_length); + DUK_ASSERT(p_copy != NULL); + + /* Copy slice, respecting underlying buffer limits; remainder + * is left as zero. + */ + copy_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, slice_length); + DUK_MEMCPY((void *) p_copy, + (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset), + copy_length); + + h_val = duk_get_hbuffer(ctx, -1); + DUK_ASSERT(h_val != NULL); + + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + DUK_ASSERT(h_bufobj->offset == 0); + + duk_pop(ctx); /* reachable so pop OK */ + } else { + h_bufobj->buf = h_val; + DUK_HBUFFER_INCREF(thr, h_val); + h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset); + + /* Copy the .buffer property, needed for TypedArray.prototype.subarray(). + * + * XXX: limit copy only for TypedArray classes specifically? + */ + + duk_push_this(ctx); + if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LC_BUFFER)) { + duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE); + duk_pop(ctx); + } else { + duk_pop_2(ctx); + } + } + /* unbalanced stack on purpose */ + + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + return 1; +} + +/* + * Node.js Buffer.isEncoding() + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) { + const char *encoding; + + /* only accept lowercase 'utf8' now. */ + + encoding = duk_to_string(ctx, 0); + DUK_ASSERT(duk_is_string(ctx, 0)); /* guaranteed by duk_to_string() */ + duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0); + return 1; +} + +/* + * Node.js Buffer.isBuffer() + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) { + duk_hthread *thr; + duk_tval *tv; + duk_hobject *h; + duk_hobject *h_proto; + duk_bool_t ret = 0; + + thr = (duk_hthread *) ctx; + + DUK_ASSERT(duk_get_top(ctx) >= 1); /* nargs */ + tv = duk_get_tval(ctx, 0); + DUK_ASSERT(tv != NULL); + + if (DUK_TVAL_IS_OBJECT(tv)) { + h = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(h != NULL); + + h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE]; + DUK_ASSERT(h_proto != NULL); + + h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h); + if (h) { + ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/); + } + } + + duk_push_boolean(ctx, ret); + return 1; +} + +/* + * Node.js Buffer.byteLength() + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) { + const char *str; + duk_size_t len; + + /* At the moment Buffer() will just use the string bytes as + * is (ignoring encoding), so we return the string length here + * unconditionally. + */ + + str = duk_to_lstring(ctx, 0, &len); + DUK_UNREF(str); + duk_push_size_t(ctx, len); + return 1; +} + +/* + * Node.js Buffer.concat() + */ + +DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) { + duk_hthread *thr; + duk_hobject *h_arg; + duk_int_t total_length = 0; + duk_hbufferobject *h_bufobj; + duk_hbufferobject *h_bufres; + duk_hbuffer *h_val; + duk_uint_t i, n; + duk_uint8_t *p; + duk_size_t space_left; + duk_size_t copy_size; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + /* Node.js accepts only actual Arrays. */ + h_arg = duk_require_hobject(ctx, 0); + if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) { + return DUK_RET_TYPE_ERROR; + } + + /* Compute result length and validate argument buffers. */ + n = (duk_uint_t) duk_get_length(ctx, 0); + for (i = 0; i < n; i++) { + /* Neutered checks not necessary here: neutered buffers have + * zero 'length' so we'll effectively skip them. + */ + DUK_ASSERT_TOP(ctx, 2); /* [ array totalLength ] */ + duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */ + h_bufobj = duk__require_bufobj_value(ctx, 2); + DUK_ASSERT(h_bufobj != NULL); + total_length += h_bufobj->length; + duk_pop(ctx); + } + if (n == 1) { + /* For the case n==1 Node.js doesn't seem to type check + * the sole member but we do it before returning it. + * For this case only the original buffer object is + * returned (not a copy). + */ + duk_get_prop_index(ctx, 0, 0); + return 1; + } + + /* User totalLength overrides a computed length, but we'll check + * every copy in the copy loop. Note that duk_to_uint() can + * technically have arbitrary side effects so we need to recheck + * the buffers in the copy loop. + */ + if (!duk_is_undefined(ctx, 1) && n > 0) { + /* For n == 0, Node.js ignores totalLength argument and + * returns a zero length buffer. + */ + total_length = duk_to_int(ctx, 1); + } + if (total_length < 0) { + return DUK_RET_RANGE_ERROR; + } + + h_bufres = duk_push_bufferobject(ctx, + DUK_HOBJECT_FLAG_EXTENSIBLE | + DUK_HOBJECT_FLAG_BUFFEROBJECT | + DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER), + DUK_BIDX_NODEJS_BUFFER_PROTOTYPE); + DUK_ASSERT(h_bufres != NULL); + + p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, total_length); + DUK_ASSERT(p != NULL); + space_left = total_length; + + for (i = 0; i < n; i++) { + DUK_ASSERT_TOP(ctx, 4); /* [ array totalLength bufres buf ] */ + + duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); + h_bufobj = duk__require_bufobj_value(ctx, 4); + DUK_ASSERT(h_bufobj != NULL); + + copy_size = h_bufobj->length; + if (copy_size > space_left) { + copy_size = space_left; + } + + if (h_bufobj->buf != NULL && + DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) { + DUK_MEMCPY((void *) p, + (const void *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj), + copy_size); + } else { + /* Just skip, leaving zeroes in the result. */ + ; + } + p += copy_size; + space_left -= copy_size; + + duk_pop(ctx); + } + + h_val = duk_get_hbuffer(ctx, -1); + DUK_ASSERT(h_val != NULL); + + duk__set_bufobj_buffer(ctx, h_bufres, h_val); + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufres); + + duk_pop(ctx); /* pop plain buffer, now reachable through h_bufres */ + + return 1; /* return h_bufres */ +} + +/* + * Shared readfield and writefield methods + * + * The readfield/writefield methods need support for endianness and field + * types. All offsets are byte based so no offset shifting is needed. + */ + +/* Format of magic, bits: + * 0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused + * 3: endianness: 0=little, 1=big + * 4: signed: 1=yes, 0=no + * 5: typedarray: 1=yes, 0=no + */ +#define DUK__FLD_8BIT 0 +#define DUK__FLD_16BIT 1 +#define DUK__FLD_32BIT 2 +#define DUK__FLD_FLOAT 3 +#define DUK__FLD_DOUBLE 4 +#define DUK__FLD_VARINT 5 +#define DUK__FLD_BIGENDIAN (1 << 3) +#define DUK__FLD_SIGNED (1 << 4) +#define DUK__FLD_TYPEDARRAY (1 << 5) + +/* XXX: split into separate functions for each field type? */ +DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) { + duk_hthread *thr; + duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx); + duk_small_int_t magic_ftype; + duk_small_int_t magic_bigendian; + duk_small_int_t magic_signed; + duk_small_int_t magic_typedarray; + duk_small_int_t endswap; + duk_hbufferobject *h_this; + duk_bool_t no_assert; + duk_int_t offset_signed; + duk_uint_t offset; + duk_uint_t buffer_length; + duk_uint_t check_length; + duk_uint8_t *buf; + duk_double_union du; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + magic_ftype = magic & 0x0007; + magic_bigendian = magic & 0x0008; + magic_signed = magic & 0x0010; + magic_typedarray = magic & 0x0020; + + h_this = duk__require_bufobj_this(ctx); + DUK_ASSERT(h_this != NULL); + buffer_length = h_this->length; + + /* [ offset noAssert ], when ftype != DUK__FLD_VARINT */ + /* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */ + /* [ offset littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */ + + /* Handle TypedArray vs. Node.js Buffer arg differences */ + if (magic_typedarray) { + no_assert = 0; +#if defined(DUK_USE_INTEGER_LE) + endswap = !duk_to_boolean(ctx, 1); /* 1=little endian */ +#else + endswap = duk_to_boolean(ctx, 1); /* 1=little endian */ +#endif + } else { + no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1); +#if defined(DUK_USE_INTEGER_LE) + endswap = magic_bigendian; +#else + endswap = !magic_bigendian; +#endif + } + + /* Offset is coerced first to signed integer range and then to unsigned. + * This ensures we can add a small byte length (1-8) to the offset in + * bound checks and not wrap. + */ + offset_signed = duk_to_int(ctx, 0); + offset = (duk_uint_t) offset_signed; + if (offset_signed < 0) { + goto fail_bounds; + } + + DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, " + "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, " + "endswap=%d", + (long) buffer_length, (long) offset, (int) no_assert, + (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3), + (int) (magic_signed >> 4), (int) endswap)); + + /* Update 'buffer_length' to be the effective, safe limit which + * takes into account the underlying buffer. This value will be + * potentially invalidated by any side effect. + */ + check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length); + DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", + (long) buffer_length, (long) check_length)); + + if (h_this->buf) { + buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this); + } else { + /* neutered, value doesn't matter because check_length is 0. */ + DUK_ASSERT(check_length == 0); + buf = NULL; + } + + switch (magic_ftype) { + case DUK__FLD_8BIT: { + duk_uint8_t tmp; + if (offset + 1U > check_length) { + goto fail_bounds; + } + tmp = buf[offset]; + if (magic_signed) { + duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp)); + } else { + duk_push_uint(ctx, (duk_uint_t) tmp); + } + break; + } + case DUK__FLD_16BIT: { + duk_uint16_t tmp; + if (offset + 2U > check_length) { + goto fail_bounds; + } + DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2); + tmp = du.us[0]; + if (endswap) { + tmp = DUK_BSWAP16(tmp); + } + if (magic_signed) { + duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp)); + } else { + duk_push_uint(ctx, (duk_uint_t) tmp); + } + break; + } + case DUK__FLD_32BIT: { + duk_uint32_t tmp; + if (offset + 4U > check_length) { + goto fail_bounds; + } + DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4); + tmp = du.ui[0]; + if (endswap) { + tmp = DUK_BSWAP32(tmp); + } + if (magic_signed) { + duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp)); + } else { + duk_push_uint(ctx, (duk_uint_t) tmp); + } + break; + } + case DUK__FLD_FLOAT: { + duk_uint32_t tmp; + if (offset + 4U > check_length) { + goto fail_bounds; + } + DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4); + if (endswap) { + tmp = du.ui[0]; + tmp = DUK_BSWAP32(tmp); + du.ui[0] = tmp; + } + duk_push_number(ctx, (duk_double_t) du.f[0]); + break; + } + case DUK__FLD_DOUBLE: { + if (offset + 8U > check_length) { + goto fail_bounds; + } + DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8); + if (endswap) { + DUK_DBLUNION_BSWAP64(&du); + } + duk_push_number(ctx, (duk_double_t) du.d); + break; + } + case DUK__FLD_VARINT: { + /* Node.js Buffer variable width integer field. We don't really + * care about speed here, so aim for shortest algorithm. + */ + duk_int_t field_bytelen; + duk_int_t i, i_step, i_end; +#if defined(DUK_USE_64BIT_OPS) + duk_int64_t tmp; + duk_small_uint_t shift_tmp; +#else + duk_double_t tmp; + duk_small_int_t highbyte; +#endif + const duk_uint8_t *p; + + field_bytelen = duk_get_int(ctx, 1); /* avoid side effects! */ + if (field_bytelen < 1 || field_bytelen > 6) { + goto fail_field_length; + } + if (offset + (duk_uint_t) field_bytelen > check_length) { + goto fail_bounds; + } + p = (const duk_uint8_t *) (buf + offset); + + /* Slow gathering of value using either 64-bit arithmetic + * or IEEE doubles if 64-bit types not available. Handling + * of negative numbers is a bit non-obvious in both cases. + */ + + if (magic_bigendian) { + /* Gather in big endian */ + i = 0; + i_step = 1; + i_end = field_bytelen; /* one i_step over */ + } else { + /* Gather in little endian */ + i = field_bytelen - 1; + i_step = -1; + i_end = -1; /* one i_step over */ + } + +#if defined(DUK_USE_64BIT_OPS) + tmp = 0; + do { + DUK_ASSERT(i >= 0 && i < field_bytelen); + tmp = (tmp << 8) + (duk_int64_t) p[i]; + i += i_step; + } while (i != i_end); + + if (magic_signed) { + /* Shift to sign extend. */ + shift_tmp = 64 - (field_bytelen * 8); + tmp = (tmp << shift_tmp) >> shift_tmp; + } + + duk_push_i64(ctx, tmp); +#else + highbyte = p[i]; + if (magic_signed && (highbyte & 0x80) != 0) { + /* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */ + tmp = (duk_double_t) (highbyte - 256); + } else { + tmp = (duk_double_t) highbyte; + } + for (;;) { + i += i_step; + if (i == i_end) { + break; + } + DUK_ASSERT(i >= 0 && i < field_bytelen); + tmp = (tmp * 256.0) + (duk_double_t) p[i]; + } + + duk_push_number(ctx, tmp); +#endif + break; + } + default: { /* should never happen but default here */ + goto fail_bounds; + } + } + + return 1; + + fail_field_length: + fail_bounds: + if (no_assert) { + /* Node.js return value for noAssert out-of-bounds reads is + * usually (but not always) NaN. Return NaN consistently. + */ + duk_push_nan(ctx); + return 1; + } + + return DUK_RET_RANGE_ERROR; +} + +/* XXX: split into separate functions for each field type? */ +DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) { + duk_hthread *thr; + duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx); + duk_small_int_t magic_ftype; + duk_small_int_t magic_bigendian; + duk_small_int_t magic_signed; + duk_small_int_t magic_typedarray; + duk_small_int_t endswap; + duk_hbufferobject *h_this; + duk_bool_t no_assert; + duk_int_t offset_signed; + duk_uint_t offset; + duk_uint_t buffer_length; + duk_uint_t check_length; + duk_uint8_t *buf; + duk_double_union du; + duk_int_t nbytes = 0; + + thr = (duk_hthread *) ctx; + DUK_UNREF(thr); + + magic_ftype = magic & 0x0007; + magic_bigendian = magic & 0x0008; + magic_signed = magic & 0x0010; + magic_typedarray = magic & 0x0020; + DUK_UNREF(magic_signed); + + h_this = duk__require_bufobj_this(ctx); + DUK_ASSERT(h_this != NULL); + buffer_length = h_this->length; + + /* [ value offset noAssert ], when ftype != DUK__FLD_VARINT */ + /* [ value offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */ + /* [ offset value littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */ + + /* Handle TypedArray vs. Node.js Buffer arg differences */ + if (magic_typedarray) { + no_assert = 0; +#if defined(DUK_USE_INTEGER_LE) + endswap = !duk_to_boolean(ctx, 2); /* 1=little endian */ +#else + endswap = duk_to_boolean(ctx, 2); /* 1=little endian */ +#endif + duk_swap(ctx, 0, 1); /* offset/value order different from Node.js */ + } else { + no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2); +#if defined(DUK_USE_INTEGER_LE) + endswap = magic_bigendian; +#else + endswap = !magic_bigendian; +#endif + } + + /* Offset is coerced first to signed integer range and then to unsigned. + * This ensures we can add a small byte length (1-8) to the offset in + * bound checks and not wrap. + */ + offset_signed = duk_to_int(ctx, 1); + offset = (duk_uint_t) offset_signed; + + /* We need 'nbytes' even for a failed offset; return value must be + * (offset + nbytes) even when write fails due to invalid offset. + */ + if (magic_ftype != DUK__FLD_VARINT) { + DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t))); + nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype]; + } else { + nbytes = duk_get_int(ctx, 2); + if (nbytes < 1 || nbytes > 6) { + goto fail_field_length; + } + } + DUK_ASSERT(nbytes >= 1 && nbytes <= 8); + + /* Now we can check offset validity. */ + if (offset_signed < 0) { + goto fail_bounds; + } + + DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, " + "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, " + "endswap=%d", + duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert, + (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3), + (int) (magic_signed >> 4), (int) endswap)); + + /* Coerce value to a number before computing check_length, so that + * the field type specific coercion below can't have side effects + * that would invalidate check_length. + */ + duk_to_number(ctx, 0); + + /* Update 'buffer_length' to be the effective, safe limit which + * takes into account the underlying buffer. This value will be + * potentially invalidated by any side effect. + */ + check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length); + DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld", + (long) buffer_length, (long) check_length)); + + if (h_this->buf) { + buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this); + } else { + /* neutered, value doesn't matter because check_length is 0. */ + DUK_ASSERT(check_length == 0); + buf = NULL; + } + + switch (magic_ftype) { + case DUK__FLD_8BIT: { + if (offset + 1U > check_length) { + goto fail_bounds; + } + /* sign doesn't matter when writing */ + buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0); + break; + } + case DUK__FLD_16BIT: { + duk_uint16_t tmp; + if (offset + 2U > check_length) { + goto fail_bounds; + } + tmp = (duk_uint16_t) duk_to_uint32(ctx, 0); + if (endswap) { + tmp = DUK_BSWAP16(tmp); + } + du.us[0] = tmp; + /* sign doesn't matter when writing */ + DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2); + break; + } + case DUK__FLD_32BIT: { + duk_uint32_t tmp; + if (offset + 4U > check_length) { + goto fail_bounds; + } + tmp = (duk_uint32_t) duk_to_uint32(ctx, 0); + if (endswap) { + tmp = DUK_BSWAP32(tmp); + } + du.ui[0] = tmp; + /* sign doesn't matter when writing */ + DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4); + break; + } + case DUK__FLD_FLOAT: { + duk_uint32_t tmp; + if (offset + 4U > check_length) { + goto fail_bounds; + } + du.f[0] = (duk_float_t) duk_to_number(ctx, 0); + if (endswap) { + tmp = du.ui[0]; + tmp = DUK_BSWAP32(tmp); + du.ui[0] = tmp; + } + /* sign doesn't matter when writing */ + DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4); + break; + } + case DUK__FLD_DOUBLE: { + if (offset + 8U > check_length) { + goto fail_bounds; + } + du.d = (duk_double_t) duk_to_number(ctx, 0); + if (endswap) { + DUK_DBLUNION_BSWAP64(&du); + } + /* sign doesn't matter when writing */ + DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8); + break; + } + case DUK__FLD_VARINT: { + /* Node.js Buffer variable width integer field. We don't really + * care about speed here, so aim for shortest algorithm. + */ + duk_int_t field_bytelen; + duk_int_t i, i_step, i_end; +#if defined(DUK_USE_64BIT_OPS) + duk_int64_t tmp; +#else + duk_double_t tmp; +#endif + duk_uint8_t *p; + + field_bytelen = (duk_int_t) nbytes; + if (offset + (duk_uint_t) field_bytelen > check_length) { + goto fail_bounds; + } + + /* Slow writing of value using either 64-bit arithmetic + * or IEEE doubles if 64-bit types not available. There's + * no special sign handling when writing varints. + */ + + if (magic_bigendian) { + /* Write in big endian */ + i = field_bytelen; /* one i_step added at top of loop */ + i_step = -1; + i_end = 0; + } else { + /* Write in little endian */ + i = -1; /* one i_step added at top of loop */ + i_step = 1; + i_end = field_bytelen - 1; + } + + /* XXX: The duk_to_number() cast followed by integer coercion + * is platform specific so NaN, +/- Infinity, and out-of-bounds + * values result in platform specific output now. + * See: test-bi-nodejs-buffer-proto-varint-special.js + */ + +#if defined(DUK_USE_64BIT_OPS) + tmp = (duk_int64_t) duk_to_number(ctx, 0); + p = (duk_uint8_t *) (buf + offset); + do { + i += i_step; + DUK_ASSERT(i >= 0 && i < field_bytelen); + p[i] = (duk_uint8_t) (tmp & 0xff); + tmp = tmp >> 8; /* unnecessary shift for last byte */ + } while (i != i_end); +#else + tmp = duk_to_number(ctx, 0); + p = (duk_uint8_t *) (buf + offset); + do { + i += i_step; + tmp = DUK_FLOOR(tmp); + DUK_ASSERT(i >= 0 && i < field_bytelen); + p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0)); + tmp = tmp / 256.0; /* unnecessary div for last byte */ + } while (i != i_end); +#endif + break; + } + default: { /* should never happen but default here */ + goto fail_bounds; + } + } + + /* Node.js Buffer: return offset + #bytes written (i.e. next + * write offset). + */ + if (magic_typedarray) { + /* For TypedArrays 'undefined' return value is specified + * by ES6 (matches V8). + */ + return 0; + } + duk_push_uint(ctx, offset + nbytes); + return 1; + + fail_field_length: + fail_bounds: + if (no_assert) { + /* Node.js return value for failed writes is offset + #bytes + * that would have been written. + */ + /* XXX: for negative input offsets, 'offset' will be a large + * positive value so the result here is confusing. + */ + if (magic_typedarray) { + return 0; + } + duk_push_uint(ctx, offset + nbytes); + return 1; + } + return DUK_RET_RANGE_ERROR; +} + +#undef DUK__FLD_8BIT +#undef DUK__FLD_16BIT +#undef DUK__FLD_32BIT +#undef DUK__FLD_FLOAT +#undef DUK__FLD_DOUBLE +#undef DUK__FLD_VARINT +#undef DUK__FLD_BIGENDIAN +#undef DUK__FLD_SIGNED +#undef DUK__FLD_TYPEDARRAY +#line 1 "duk_bi_date.c" +/* + * Date built-ins + * + * Unlike most built-ins, Date has some platform dependencies for getting + * UTC time, converting between UTC and local time, and parsing and + * formatting time values. These are all abstracted behind DUK_USE_xxx + * config options. There are built-in platform specific providers for + * POSIX and Windows, but external providers can also be used. + * + * See doc/datetime.rst. + * + */ + +/* include removed: duk_internal.h */ + +/* + * Forward declarations */ -/* Forward declarations. */ DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset); DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags); -DUK_LOCAL_DECL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags); -DUK_LOCAL_DECL duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags); DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val); -DUK_LOCAL_DECL duk_bool_t duk__is_leap_year(duk_int_t year); -DUK_LOCAL_DECL duk_bool_t duk__timeval_in_valid_range(duk_double_t x); -DUK_LOCAL_DECL duk_bool_t duk__timeval_in_leeway_range(duk_double_t x); -DUK_LOCAL_DECL duk_bool_t duk__year_in_valid_range(duk_double_t year); - -/* Millisecond count constants. */ -#define DUK__MS_SECOND 1000L -#define DUK__MS_MINUTE (60L * 1000L) -#define DUK__MS_HOUR (60L * 60L * 1000L) -#define DUK__MS_DAY (24L * 60L * 60L * 1000L) - -/* Ecmascript date range is 100 million days from Epoch: - * > 100e6 * 24 * 60 * 60 * 1000 // 100M days in millisecs - * 8640000000000000 - * (= 8.64e15) - */ -#define DUK__MS_100M_DAYS (8.64e15) -#define DUK__MS_100M_DAYS_LEEWAY (8.64e15 + 24 * 3600e3) - -/* Ecmascript year range: - * > new Date(100e6 * 24 * 3600e3).toISOString() - * '+275760-09-13T00:00:00.000Z' - * > new Date(-100e6 * 24 * 3600e3).toISOString() - * '-271821-04-20T00:00:00.000Z' - */ -#define DUK__MIN_ECMA_YEAR (-271821) -#define DUK__MAX_ECMA_YEAR 275760 - -/* Part indices for internal breakdowns. Part order from DUK__IDX_YEAR to - * DUK__IDX_MILLISECOND matches argument ordering of Ecmascript API calls - * (like Date constructor call). A few functions in this file depend - * on the specific ordering, so change with care. 16 bits are not enough - * for all parts (year, specifically). - * - * (Must be in-sync with genbuiltins.py.) - */ -#define DUK__IDX_YEAR 0 /* year */ -#define DUK__IDX_MONTH 1 /* month: 0 to 11 */ -#define DUK__IDX_DAY 2 /* day within month: 0 to 30 */ -#define DUK__IDX_HOUR 3 -#define DUK__IDX_MINUTE 4 -#define DUK__IDX_SECOND 5 -#define DUK__IDX_MILLISECOND 6 -#define DUK__IDX_WEEKDAY 7 /* weekday: 0 to 6, 0=sunday, 1=monday, etc */ -#define DUK__NUM_PARTS 8 - -/* Internal API call flags, used for various functions in this file. - * Certain flags are used by only certain functions, but since the flags - * don't overlap, a single flags value can be passed around to multiple - * functions. - * - * The unused top bits of the flags field are also used to pass values - * to helpers (duk__get_part_helper() and duk__set_part_helper()). - * - * (Must be in-sync with genbuiltins.py.) - */ -#define DUK__FLAG_NAN_TO_ZERO (1 << 0) /* timeval breakdown: internal time value NaN -> zero */ -#define DUK__FLAG_NAN_TO_RANGE_ERROR (1 << 1) /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */ -#define DUK__FLAG_ONEBASED (1 << 2) /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */ -#define DUK__FLAG_EQUIVYEAR (1 << 3) /* timeval breakdown: replace year with equivalent year in the [1971,2037] range for DST calculations */ -#define DUK__FLAG_LOCALTIME (1 << 4) /* convert time value to local time */ -#define DUK__FLAG_SUB1900 (1 << 5) /* getter: subtract 1900 from year when getting year part */ -#define DUK__FLAG_TOSTRING_DATE (1 << 6) /* include date part in string conversion result */ -#define DUK__FLAG_TOSTRING_TIME (1 << 7) /* include time part in string conversion result */ -#define DUK__FLAG_TOSTRING_LOCALE (1 << 8) /* use locale specific formatting if available */ -#define DUK__FLAG_TIMESETTER (1 << 9) /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */ -#define DUK__FLAG_YEAR_FIXUP (1 << 10) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */ -#define DUK__FLAG_SEP_T (1 << 11) /* string conversion: use 'T' instead of ' ' as a separator */ -#define DUK__FLAG_VALUE_SHIFT 12 /* additional values begin at bit 12 */ +DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags); + +/* + * Other file level defines + */ /* Debug macro to print all parts and dparts (used manually because of debug level). */ #define DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts) do { \ @@ -20740,409 +26089,6 @@ DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = { }; #undef DUK__YEAR -/* - * Platform specific helpers - */ - -#ifdef DUK_USE_DATE_NOW_GETTIMEOFDAY -/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */ -DUK_INTERNAL duk_double_t duk_bi_date_get_now(duk_context *ctx) { - duk_hthread *thr = (duk_hthread *) ctx; - struct timeval tv; - duk_double_t d; - - if (gettimeofday(&tv, NULL) != 0) { - DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "gettimeofday failed"); - } - - d = ((duk_double_t) tv.tv_sec) * 1000.0 + - ((duk_double_t) (tv.tv_usec / 1000)); - DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions */ - - return d; -} -#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */ - -#ifdef 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(duk_context *ctx) { - time_t t = time(NULL); - return ((duk_double_t) t) * 1000.0; -} -#endif /* DUK_USE_DATE_NOW_TIME */ - -#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) -/* Shared Windows helpers. */ -DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) { - FILETIME ft; - if (SystemTimeToFileTime(st, &ft) == 0) { - DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0")); - res->QuadPart = 0; - } else { - res->LowPart = ft.dwLowDateTime; - res->HighPart = ft.dwHighDateTime; - } -} -DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) { - DUK_MEMZERO((void *) st, sizeof(*st)); - st->wYear = 1970; - st->wMonth = 1; - st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */ - st->wDay = 1; - DUK_ASSERT(st->wHour == 0); - DUK_ASSERT(st->wMinute == 0); - DUK_ASSERT(st->wSecond == 0); - DUK_ASSERT(st->wMilliseconds == 0); -} -#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */ - -#ifdef DUK_USE_DATE_NOW_WINDOWS -DUK_INTERNAL duk_double_t duk_bi_date_get_now(duk_context *ctx) { - /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx - */ - SYSTEMTIME st1, st2; - ULARGE_INTEGER tmp1, tmp2; - - DUK_UNREF(ctx); - - GetSystemTime(&st1); - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1); - - duk__set_systime_jan1970(&st2); - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2); - - /* Difference is in 100ns units, convert to milliseconds w/o fractions */ - return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL); -} -#endif /* DUK_USE_DATE_NOW_WINDOWS */ - -#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) -/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */ -DUK_LOCAL duk_int_t duk__get_local_tzoffset(duk_double_t d) { - time_t t, t1, t2; - duk_int_t parts[DUK__NUM_PARTS]; - duk_double_t dparts[DUK__NUM_PARTS]; - struct tm tms[2]; -#ifdef DUK_USE_DATE_TZO_GMTIME - struct tm *tm_ptr; -#endif - - /* For NaN/inf, the return value doesn't matter. */ - if (!DUK_ISFINITE(d)) { - return 0; - } - - /* If not within Ecmascript range, some integer time calculations - * won't work correctly (and some asserts will fail), so bail out - * if so. This fixes test-bug-date-insane-setyear.js. There is - * a +/- 24h leeway in this range check to avoid a test262 corner - * case documented in test-bug-date-timeval-edges.js. - */ - if (!duk__timeval_in_leeway_range(d)) { - DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows")); - return 0; - } - - /* - * This is a bit tricky to implement portably. The result depends - * on the timestamp (specifically, DST depends on the timestamp). - * If e.g. UNIX APIs are used, they'll have portability issues with - * very small and very large years. - * - * Current approach: - * - * - Stay within portable UNIX limits by using equivalent year mapping. - * Avoid year 1970 and 2038 as some conversions start to fail, at - * least on some platforms. Avoiding 1970 means that there are - * currently DST discrepancies for 1970. - * - * - Create a UTC and local time breakdowns from 't'. Then create - * a time_t using gmtime() and localtime() and compute the time - * difference between the two. - * - * Equivalent year mapping (E5 Section 15.9.1.8): - * - * If the host environment provides functionality for determining - * daylight saving time, the implementation of ECMAScript is free - * to map the year in question to an equivalent year (same - * leap-year-ness and same starting week day for the year) for which - * the host environment provides daylight saving time information. - * The only restriction is that all equivalent years should produce - * the same result. - * - * This approach is quite reasonable but not entirely correct, e.g. - * the specification also states (E5 Section 15.9.1.8): - * - * The implementation of ECMAScript should not try to determine - * whether the exact time was subject to daylight saving time, but - * just whether daylight saving time would have been in effect if - * the _current daylight saving time algorithm_ had been used at the - * time. This avoids complications such as taking into account the - * years that the locale observed daylight saving time year round. - * - * Since we rely on the platform APIs for conversions between local - * time and UTC, we can't guarantee the above. Rather, if the platform - * has historical DST rules they will be applied. This seems to be the - * general preferred direction in Ecmascript standardization (or at least - * implementations) anyway, and even the equivalent year mapping should - * be disabled if the platform is known to handle DST properly for the - * full Ecmascript range. - * - * The following has useful discussion and links: - * - * https://bugzilla.mozilla.org/show_bug.cgi?id=351066 - */ - - duk__timeval_to_parts(d, parts, dparts, DUK__FLAG_EQUIVYEAR /*flags*/); - DUK_ASSERT(parts[DUK__IDX_YEAR] >= 1970 && parts[DUK__IDX_YEAR] <= 2038); - - d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/); - DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */ - t = (time_t) (d / 1000.0); - DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t)); - - t1 = t; - - DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2); - -#if defined(DUK_USE_DATE_TZO_GMTIME_R) - (void) gmtime_r(&t, &tms[0]); - (void) localtime_r(&t, &tms[1]); -#elif defined(DUK_USE_DATE_TZO_GMTIME) - tm_ptr = gmtime(&t); - DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm)); - tm_ptr = localtime(&t); - DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm)); -#else -#error internal error -#endif - DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," - "wday:%ld,yday:%ld,isdst:%ld}", - (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour, - (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year, - (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst)); - DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," - "wday:%ld,yday:%ld,isdst:%ld}", - (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour, - (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year, - (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst)); - - t1 = mktime(&tms[0]); /* UTC */ - t2 = mktime(&tms[1]); /* local */ - if (t1 == (time_t) -1 || t2 == (time_t) -1) { - /* This check used to be for (t < 0) but on some platforms - * time_t is unsigned and apparently the proper way to detect - * an mktime() error return is the cast above. See e.g.: - * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html - */ - goto error; - } - if (tms[1].tm_isdst > 0) { - t2 += 3600; - } else if (tms[1].tm_isdst < 0) { - DUK_D(DUK_DPRINT("tm_isdst is negative: %d", (int) tms[1].tm_isdst)); - } - DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2)); - - /* Compute final offset in seconds, positive if local time ahead of - * UTC (returned value is UTC-to-local offset). - * - * difftime() returns a double, so coercion to int generates quite - * a lot of code. Direct subtraction is not portable, however. - * XXX: allow direct subtraction on known platforms. - */ -#if 0 - return (duk_int_t) (t2 - t1); -#endif - return (duk_int_t) difftime(t2, t1); - - error: - /* XXX: return something more useful, so that caller can throw? */ - DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d)); - return 0; -} -#endif /* DUK_USE_DATE_TZO_GMTIME */ - -#if defined(DUK_USE_DATE_TZO_WINDOWS) -DUK_LOCAL duk_int_t duk__get_local_tzoffset(duk_double_t d) { - SYSTEMTIME st1; - SYSTEMTIME st2; - SYSTEMTIME st3; - ULARGE_INTEGER tmp1; - ULARGE_INTEGER tmp2; - ULARGE_INTEGER tmp3; - FILETIME ft1; - - /* XXX: handling of timestamps outside Windows supported range. - * How does Windows deal with dates before 1600? Does windows - * support all Ecmascript years (like -200000 and +200000)? - * Should equivalent year mapping be used here too? If so, use - * a shared helper (currently integrated into timeval-to-parts). - */ - - /* Use the approach described in "Remarks" of FileTimeToLocalFileTime: - * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx - */ - - duk__set_systime_jan1970(&st1); - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1); - tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */ - tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */ - - ft1.dwLowDateTime = tmp2.LowPart; - ft1.dwHighDateTime = tmp2.HighPart; - FileTimeToSystemTime((const FILETIME *) &ft1, &st2); - if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) { - DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0")); - return 0; - } - duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3); - - /* Positive if local time ahead of UTC. */ - return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */ -} -#endif /* DUK_USE_DATE_TZO_WINDOWS */ - -#ifdef DUK_USE_DATE_PRS_STRPTIME -#ifdef HAVE_STRPTIME -DUK_LOCAL duk_bool_t duk__parse_string_strptime(duk_context *ctx, const char *str) { - struct tm tm; - time_t t; - char buf[DUK__STRPTIME_BUF_SIZE]; - - /* copy to buffer with spare to avoid Valgrind gripes from strptime */ - DUK_ASSERT(str != NULL); - DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */ - DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str); - buf[sizeof(buf) - 1] = (char) 0; - - DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf)); - - DUK_MEMZERO(&tm, sizeof(tm)); - if (strptime((const char *) buf, "%c", &tm) != NULL) { - DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," - "wday:%ld,yday:%ld,isdst:%ld}", - (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour, - (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year, - (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst)); - tm.tm_isdst = -1; /* negative: dst info not available */ - - t = mktime(&tm); - DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t)); - if (t >= 0) { - duk_push_number(ctx, ((duk_double_t) t) * 1000.0); - return 1; - } - } - - return 0; -} -#else -#include "utils/config.h" -#include "utils/errors.h" -#include "utils/time.h" -DUK_LOCAL duk_bool_t duk__parse_string_strptime(duk_context *ctx, const char *str) { - time_t t; - char buf[DUK__STRPTIME_BUF_SIZE]; - - /* copy to buffer with spare to avoid Valgrind gripes from strptime */ - DUK_ASSERT(str != NULL); - DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */ - DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str); - buf[sizeof(buf) - 1] = (char) 0; - - DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf)); - - if (nsc_snptimet(buf, strlen(buf), &t) == NSERROR_OK) { - duk_push_number(ctx, ((duk_double_t) t) * 1000.0); - return 1; - } - - return 0; -} -#endif /* HAVE_STRPTIME */ -#endif /* DUK_USE_DATE_PRS_STRPTIME */ - -#ifdef DUK_USE_DATE_PRS_GETDATE -DUK_LOCAL duk_bool_t duk__parse_string_getdate(duk_context *ctx, const char *str) { - struct tm tm; - duk_small_int_t rc; - time_t t; - - /* For this to work, DATEMSK must be set, so this is not very - * convenient for an embeddable interpreter. - */ - - DUK_MEMZERO(&tm, sizeof(struct tm)); - rc = (duk_small_int_t) getdate_r(str, &tm); - DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc)); - - if (rc == 0) { - t = mktime(&tm); - DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t)); - if (t >= 0) { - duk_push_number(ctx, (duk_double_t) t); - return 1; - } - } - - return 0; -} -#endif /* DUK_USE_DATE_PRS_GETDATE */ - -#ifdef DUK_USE_DATE_FMT_STRFTIME -DUK_LOCAL duk_bool_t duk__format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) { - char buf[DUK__STRFTIME_BUF_SIZE]; - struct tm tm; - const char *fmt; - - DUK_UNREF(tzoffset); - - /* If the platform doesn't support the entire Ecmascript range, we need - * to return 0 so that the caller can fall back to the default formatter. - * - * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript - * range is supported. For smaller time_t values (4 bytes in practice), - * assumes that the signed 32-bit range is supported. - * - * XXX: detect this more correctly per platform. The size of time_t is - * probably not an accurate guarantee of strftime() supporting or not - * supporting a large time range (the full Ecmascript range). - */ - if (sizeof(time_t) < 8 && - (parts[DUK__IDX_YEAR] < 1970 || parts[DUK__IDX_YEAR] > 2037)) { - /* be paranoid for 32-bit time values (even avoiding negative ones) */ - return 0; - } - - DUK_MEMZERO(&tm, sizeof(tm)); - tm.tm_sec = parts[DUK__IDX_SECOND]; - tm.tm_min = parts[DUK__IDX_MINUTE]; - tm.tm_hour = parts[DUK__IDX_HOUR]; - tm.tm_mday = parts[DUK__IDX_DAY]; /* already one-based */ - tm.tm_mon = parts[DUK__IDX_MONTH] - 1; /* one-based -> zero-based */ - tm.tm_year = parts[DUK__IDX_YEAR] - 1900; - tm.tm_wday = parts[DUK__IDX_WEEKDAY]; - tm.tm_isdst = 0; - - DUK_MEMZERO(buf, sizeof(buf)); - if ((flags & DUK__FLAG_TOSTRING_DATE) && (flags & DUK__FLAG_TOSTRING_TIME)) { - fmt = "%c"; - } else if (flags & DUK__FLAG_TOSTRING_DATE) { - fmt = "%x"; - } else { - DUK_ASSERT(flags & DUK__FLAG_TOSTRING_TIME); - fmt = "%X"; - } - (void) strftime(buf, sizeof(buf) - 1, fmt, &tm); - DUK_ASSERT(buf[sizeof(buf) - 1] == 0); - - duk_push_string(ctx, buf); - return 1; -} -#endif /* DUK_USE_DATE_FMT_STRFTIME */ - /* * ISO 8601 subset parser. */ @@ -21240,7 +26186,7 @@ DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = { DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str) { duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS]; - duk_double_t dparts[DUK__NUM_PARTS]; + duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; duk_double_t d; const duk_uint8_t *p; duk_small_uint_t part_idx = 0; @@ -21253,9 +26199,9 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const ch /* During parsing, month and day are one-based; set defaults here. */ DUK_MEMZERO(parts, sizeof(parts)); - DUK_ASSERT(parts[DUK__IDX_YEAR] == 0); /* don't care value, year is mandatory */ - parts[DUK__IDX_MONTH] = 1; - parts[DUK__IDX_DAY] = 1; + DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */ + parts[DUK_DATE_IDX_MONTH] = 1; + parts[DUK_DATE_IDX_DAY] = 1; /* Special handling for year sign. */ p = (const duk_uint8_t *) str; @@ -21401,17 +26347,17 @@ DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const ch /* Use double parts, they tolerate unnormalized time. * - * Note: DUK__IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR) - * on purpose. It won't be actually used by duk__get_timeval_from_dparts(), + * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR) + * on purpose. It won't be actually used by duk_bi_date_get_timeval_from_dparts(), * but will make the value initialized just in case, and avoid any * potential for Valgrind issues. */ - for (i = 0; i < DUK__NUM_PARTS; i++) { + for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) { DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i])); dparts[i] = parts[i]; } - d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/); + d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/); duk_push_number(ctx, d); return 1; } @@ -21448,12 +26394,13 @@ DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) { return 1; } -#if defined(DUK_USE_DATE_PRS_STRPTIME) - if (duk__parse_string_strptime(ctx, str) != 0) { - return 1; - } -#elif defined(DUK_USE_DATE_PRS_GETDATE) - if (duk__parse_string_getdate(ctx, str) != 0) { +#if defined(DUK_USE_DATE_PARSE_STRING) + /* Contract, either: + * - Push value on stack and return 1 + * - Don't push anything on stack and return 0 + */ + + if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) { return 1; } #else @@ -21492,7 +26439,7 @@ DUK_LOCAL duk_uint8_t duk__days_in_month[12] = { */ #define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */ -DUK_LOCAL duk_bool_t duk__is_leap_year(duk_int_t year) { +DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) { if ((year % 4) != 0) { return 0; } @@ -21505,16 +26452,16 @@ DUK_LOCAL duk_bool_t duk__is_leap_year(duk_int_t year) { return 1; } -DUK_LOCAL duk_bool_t duk__timeval_in_valid_range(duk_double_t x) { - return (x >= -DUK__MS_100M_DAYS && x <= DUK__MS_100M_DAYS); +DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) { + return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS); } -DUK_LOCAL duk_bool_t duk__timeval_in_leeway_range(duk_double_t x) { - return (x >= -DUK__MS_100M_DAYS_LEEWAY && x <= DUK__MS_100M_DAYS_LEEWAY); +DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) { + return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY); } -DUK_LOCAL duk_bool_t duk__year_in_valid_range(duk_double_t x) { - return (x >= DUK__MIN_ECMA_YEAR && x <= DUK__MAX_ECMA_YEAR); +DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) { + return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR); } DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) { @@ -21522,7 +26469,7 @@ DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) { return DUK_DOUBLE_NAN; } - if (!duk__timeval_in_valid_range(x)) { + if (!duk_bi_date_timeval_in_valid_range(x)) { return DUK_DOUBLE_NAN; } @@ -21581,7 +26528,7 @@ DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_w DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld", (long) year, (long) *out_day_within_year)); DUK_ASSERT(*out_day_within_year >= 0); - DUK_ASSERT(*out_day_within_year < (duk__is_leap_year(year) ? 366 : 365)); + DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365)); return year; } @@ -21634,12 +26581,12 @@ DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_ * This fixes test-bug-setyear-overflow.js. */ - if (!duk__year_in_valid_range(year)) { + if (!duk_bi_date_year_in_valid_range(year)) { DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year)); return DUK_DOUBLE_NAN; } day_num = duk__day_from_year((duk_int_t) year); - is_leap = duk__is_leap_year((duk_int_t) year); + is_leap = duk_bi_date_is_leap_year((duk_int_t) year); n = (duk_small_int_t) month; for (i = 0; i < n; i++) { @@ -21657,7 +26604,7 @@ DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_ * one, i.e. finite, no fractions. Possible local time adjustment has already * been applied when reading the time value. */ -DUK_LOCAL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) { +DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) { duk_double_t d1, d2; duk_int_t t1, t2; duk_int_t day_since_epoch; @@ -21681,19 +26628,19 @@ DUK_LOCAL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_doubl * the value. In other words, although the UTC time is within the * Ecmascript range, the local part values can be just outside of it. */ - DUK_UNREF(duk__timeval_in_leeway_range); - DUK_ASSERT(duk__timeval_in_leeway_range(d)); + DUK_UNREF(duk_bi_date_timeval_in_leeway_range); + DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d)); /* these computations are guaranteed to be exact for the valid * E5 time value range, assuming milliseconds without fractions. */ - d1 = (duk_double_t) DUK_FMOD(d, (double) DUK__MS_DAY); + d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY); if (d1 < 0.0) { /* deal with negative values */ - d1 += (duk_double_t) DUK__MS_DAY; + d1 += (duk_double_t) DUK_DATE_MSEC_DAY; } - d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK__MS_DAY)); - DUK_ASSERT(d2 * ((duk_double_t) DUK__MS_DAY) + d1 == d); + d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY)); + DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d); /* now expected to fit into a 32-bit integer */ t1 = (duk_int_t) d1; t2 = (duk_int_t) d2; @@ -21705,32 +26652,32 @@ DUK_LOCAL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_doubl * t2 = day number from epoch (fits 32 bit, may be negative) */ - parts[DUK__IDX_MILLISECOND] = t1 % 1000; t1 /= 1000; - parts[DUK__IDX_SECOND] = t1 % 60; t1 /= 60; - parts[DUK__IDX_MINUTE] = t1 % 60; t1 /= 60; - parts[DUK__IDX_HOUR] = t1; - DUK_ASSERT(parts[DUK__IDX_MILLISECOND] >= 0 && parts[DUK__IDX_MILLISECOND] <= 999); - DUK_ASSERT(parts[DUK__IDX_SECOND] >= 0 && parts[DUK__IDX_SECOND] <= 59); - DUK_ASSERT(parts[DUK__IDX_MINUTE] >= 0 && parts[DUK__IDX_MINUTE] <= 59); - DUK_ASSERT(parts[DUK__IDX_HOUR] >= 0 && parts[DUK__IDX_HOUR] <= 23); + parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000; + parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60; + parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60; + parts[DUK_DATE_IDX_HOUR] = t1; + DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999); + DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59); + DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59); + DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23); DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld", (double) d, (double) d1, (double) d2, (long) t1, (long) t2, - (long) parts[DUK__IDX_HOUR], - (long) parts[DUK__IDX_MINUTE], - (long) parts[DUK__IDX_SECOND], - (long) parts[DUK__IDX_MILLISECOND])); + (long) parts[DUK_DATE_IDX_HOUR], + (long) parts[DUK_DATE_IDX_MINUTE], + (long) parts[DUK_DATE_IDX_SECOND], + (long) parts[DUK_DATE_IDX_MILLISECOND])); /* This assert depends on the input parts representing time inside * the Ecmascript range. */ DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0); - parts[DUK__IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */ - DUK_ASSERT(parts[DUK__IDX_WEEKDAY] >= 0 && parts[DUK__IDX_WEEKDAY] <= 6); + parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */ + DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6); year = duk__year_from_day(t2, &day_in_year); day = day_in_year; - is_leap = duk__is_leap_year(year); + is_leap = duk_bi_date_is_leap_year(year); for (month = 0; month < 12; month++) { dim = duk__days_in_month[month]; if (month == 1 && is_leap) { @@ -21759,7 +26706,7 @@ DUK_LOCAL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_doubl * which breaks some DST computations for 1970 right now, see e.g. * test-bi-date-tzoffset-brute-fi.js. */ - if ((flags & DUK__FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) { + if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) { DUK_ASSERT(is_leap == 0 || is_leap == 1); jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */ @@ -21780,17 +26727,17 @@ DUK_LOCAL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_doubl (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year)); } - parts[DUK__IDX_YEAR] = year; - parts[DUK__IDX_MONTH] = month; - parts[DUK__IDX_DAY] = day; + parts[DUK_DATE_IDX_YEAR] = year; + parts[DUK_DATE_IDX_MONTH] = month; + parts[DUK_DATE_IDX_DAY] = day; - if (flags & DUK__FLAG_ONEBASED) { - parts[DUK__IDX_MONTH]++; /* zero-based -> one-based */ - parts[DUK__IDX_DAY]++; /* -""- */ + if (flags & DUK_DATE_FLAG_ONEBASED) { + parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */ + parts[DUK_DATE_IDX_DAY]++; /* -""- */ } if (dparts != NULL) { - for (i = 0; i < DUK__NUM_PARTS; i++) { + for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) { dparts[i] = (duk_double_t) parts[i]; } } @@ -21802,7 +26749,7 @@ DUK_LOCAL void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_doubl * wildly out of range (but may cancel each other and still come out in * the valid Date range). */ -DUK_LOCAL duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) { +DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) { #if defined(DUK_USE_PARANOID_DATE_COMPUTATION) /* See comments below on MakeTime why these are volatile. */ volatile duk_double_t tmp_time; @@ -21823,10 +26770,10 @@ DUK_LOCAL duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_sm * zero. If ToInteger() has already been called, this has no side * effects and is idempotent. * - * Don't read dparts[DUK__IDX_WEEKDAY]; it will cause Valgrind issues - * if the value is uninitialized. + * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind + * issues if the value is uninitialized. */ - for (i = 0; i <= DUK__IDX_MILLISECOND; i++) { + for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) { /* SCANBUILD: scan-build complains here about assigned value * being garbage or undefined. This is correct but operating * on undefined values has no ill effect and is ignored by the @@ -21855,26 +26802,26 @@ DUK_LOCAL duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_sm /* MakeTime */ tmp_time = 0.0; - tmp_time += dparts[DUK__IDX_HOUR] * ((duk_double_t) DUK__MS_HOUR); - tmp_time += dparts[DUK__IDX_MINUTE] * ((duk_double_t) DUK__MS_MINUTE); - tmp_time += dparts[DUK__IDX_SECOND] * ((duk_double_t) DUK__MS_SECOND); - tmp_time += dparts[DUK__IDX_MILLISECOND]; + tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR); + tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE); + tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND); + tmp_time += dparts[DUK_DATE_IDX_MILLISECOND]; /* MakeDay */ - tmp_day = duk__make_day(dparts[DUK__IDX_YEAR], dparts[DUK__IDX_MONTH], dparts[DUK__IDX_DAY]); + tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]); /* MakeDate */ - d = tmp_day * ((duk_double_t) DUK__MS_DAY) + tmp_time; + d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time; DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf", (double) tmp_time, (double) tmp_day, (double) d)); /* Optional UTC conversion. */ - if (flags & DUK__FLAG_LOCALTIME) { - /* DUK__GET_LOCAL_TZOFFSET() needs to be called with a time - * value computed from UTC parts. At this point we only have - * 'd' which is a time value computed from local parts, so it - * is off by the UTC-to-local time offset which we don't know + if (flags & DUK_DATE_FLAG_LOCALTIME) { + /* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a + * time value computed from UTC parts. At this point we only + * have 'd' which is a time value computed from local parts, so + * it is off by the UTC-to-local time offset which we don't know * yet. The current solution for computing the UTC-to-local * time offset is to iterate a few times and detect a fixed * point or a two-cycle loop (or a sanity iteration limit), @@ -21883,12 +26830,12 @@ DUK_LOCAL duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_sm * E5.1 Section 15.9.1.9: * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA) * - * For NaN/inf, DUK__GET_LOCAL_TZOFFSET() returns 0. + * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0. */ #if 0 /* Old solution: don't iterate, incorrect */ - tzoff = DUK__GET_LOCAL_TZOFFSET(d); + tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff)); d -= tzoff * 1000L; DUK_UNREF(tzoffprev1); @@ -21901,7 +26848,7 @@ DUK_LOCAL duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_sm for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) { tzoffprev2 = tzoffprev1; tzoffprev1 = tzoff; - tzoff = DUK__GET_LOCAL_TZOFFSET(d - tzoff * 1000L); + tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L); DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld", (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2)); if (tzoff == tzoffprev1) { @@ -21957,21 +26904,21 @@ DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk duk_pop(ctx); if (DUK_ISNAN(d)) { - if (flags & DUK__FLAG_NAN_TO_ZERO) { + if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) { d = 0.0; } - if (flags & DUK__FLAG_NAN_TO_RANGE_ERROR) { + if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) { DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "Invalid Date"); } } /* if no NaN handling flag, may still be NaN here, but not Inf */ DUK_ASSERT(!DUK_ISINF(d)); - if (flags & DUK__FLAG_LOCALTIME) { + if (flags & DUK_DATE_FLAG_LOCALTIME) { /* Note: DST adjustment is determined using UTC time. * If 'd' is NaN, tzoffset will be 0. */ - tzoffset = DUK__GET_LOCAL_TZOFFSET(d); /* seconds */ + tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */ d += tzoffset * 1000L; } if (out_tzoffset) { @@ -21995,7 +26942,7 @@ DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_doub /* [ ... this ] */ - d = duk__get_timeval_from_dparts(dparts, flags); + d = duk_bi_date_get_timeval_from_dparts(dparts, flags); duk_push_number(ctx, d); /* -> [ ... this timeval_new ] */ duk_dup_top(ctx); /* -> [ ... this timeval_new timeval_new ] */ duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE); @@ -22008,23 +26955,23 @@ DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_doub DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) { char yearstr[8]; /* "-123456\0" */ char tzstr[8]; /* "+11:22\0" */ - char sep = (flags & DUK__FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE; + char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE; - DUK_ASSERT(parts[DUK__IDX_MONTH] >= 1 && parts[DUK__IDX_MONTH] <= 12); - DUK_ASSERT(parts[DUK__IDX_DAY] >= 1 && parts[DUK__IDX_DAY] <= 31); - DUK_ASSERT(parts[DUK__IDX_YEAR] >= -999999 && parts[DUK__IDX_YEAR] <= 999999); + DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12); + DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31); + DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999); /* Note: %06d for positive value, %07d for negative value to include * sign and 6 digits. */ DUK_SNPRINTF(yearstr, sizeof(yearstr), - (parts[DUK__IDX_YEAR] >= 0 && parts[DUK__IDX_YEAR] <= 9999) ? "%04ld" : - ((parts[DUK__IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"), - (long) parts[DUK__IDX_YEAR]); + (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" : + ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"), + (long) parts[DUK_DATE_IDX_YEAR]); yearstr[sizeof(yearstr) - 1] = (char) 0; - if (flags & DUK__FLAG_LOCALTIME) { + if (flags & DUK_DATE_FLAG_LOCALTIME) { /* tzoffset seconds are dropped; 16 bits suffice for * time offset in minutes */ @@ -22044,19 +26991,19 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d /* Unlike year, the other parts fit into 16 bits so %d format * is portable. */ - if ((flags & DUK__FLAG_TOSTRING_DATE) && (flags & DUK__FLAG_TOSTRING_TIME)) { + if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) { DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s", - (const char *) yearstr, (int) parts[DUK__IDX_MONTH], (int) parts[DUK__IDX_DAY], (int) sep, - (int) parts[DUK__IDX_HOUR], (int) parts[DUK__IDX_MINUTE], - (int) parts[DUK__IDX_SECOND], (int) parts[DUK__IDX_MILLISECOND], (const char *) tzstr); - } else if (flags & DUK__FLAG_TOSTRING_DATE) { + (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep, + (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE], + (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr); + } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) { DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d", - (const char *) yearstr, (int) parts[DUK__IDX_MONTH], (int) parts[DUK__IDX_DAY]); + (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]); } else { - DUK_ASSERT(flags & DUK__FLAG_TOSTRING_TIME); + DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME); DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s", - (int) parts[DUK__IDX_HOUR], (int) parts[DUK__IDX_MINUTE], - (int) parts[DUK__IDX_SECOND], (int) parts[DUK__IDX_MILLISECOND], + (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE], + (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr); } } @@ -22067,7 +27014,7 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d */ DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags) { duk_double_t d; - duk_int_t parts[DUK__NUM_PARTS]; + duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */ duk_bool_t rc; duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE]; @@ -22082,17 +27029,22 @@ DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t fla DUK_ASSERT(DUK_ISFINITE(d)); /* formatters always get one-based month/day-of-month */ - duk__timeval_to_parts(d, parts, NULL, DUK__FLAG_ONEBASED); - DUK_ASSERT(parts[DUK__IDX_MONTH] >= 1 && parts[DUK__IDX_MONTH] <= 12); - DUK_ASSERT(parts[DUK__IDX_DAY] >= 1 && parts[DUK__IDX_DAY] <= 31); + duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED); + DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12); + DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31); - if (flags & DUK__FLAG_TOSTRING_LOCALE) { + if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) { /* try locale specific formatter; if it refuses to format the * string, fall back to an ISO 8601 formatted value in local * time. */ -#ifdef DUK_USE_DATE_FMT_STRFTIME - rc = duk__format_parts_strftime(ctx, parts, tzoffset, flags); +#if defined(DUK_USE_DATE_FORMAT_STRING) + /* Contract, either: + * - Push string to value stack and return 1 + * - Don't push anything and return 0 + */ + + rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags); if (rc != 0) { return 1; } @@ -22118,11 +27070,11 @@ DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t fla */ DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) { duk_double_t d; - duk_int_t parts[DUK__NUM_PARTS]; - duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK__FLAG_VALUE_SHIFT); /* unpack args */ + duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; + duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */ DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */ - DUK_ASSERT(idx_part < DUK__NUM_PARTS); + DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS); d = duk__push_this_get_timeval(ctx, flags_and_idx); if (DUK_ISNAN(d)) { @@ -22131,13 +27083,13 @@ DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flag } DUK_ASSERT(DUK_ISFINITE(d)); - duk__timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */ + duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */ /* Setter APIs detect special year numbers (0...99) and apply a +1900 * only in certain cases. The legacy getYear() getter applies -1900 * unconditionally. */ - duk_push_int(ctx, (flags_and_idx & DUK__FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]); + duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]); return 1; } @@ -22150,10 +27102,10 @@ DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flag */ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs) { duk_double_t d; - duk_int_t parts[DUK__NUM_PARTS]; - duk_double_t dparts[DUK__NUM_PARTS]; + duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; + duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; duk_idx_t nargs; - duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK__FLAG_VALUE_SHIFT); /* unpack args */ + duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */ duk_small_uint_t idx_first, idx; duk_small_uint_t i; @@ -22162,7 +27114,7 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flag DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d)); if (DUK_ISFINITE(d)) { - duk__timeval_to_parts(d, parts, dparts, flags_and_maxnargs); + duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs); } else { /* NaN timevalue: we need to coerce the arguments, but * the resulting internal timestamp needs to remain NaN. @@ -22176,7 +27128,7 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flag * stack arguments is a bit complicated, but important to factor * out from setters themselves for compactness. * - * If DUK__FLAG_TIMESETTER, maxnargs indicates setter type: + * If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type: * * 1 -> millisecond * 2 -> second, [millisecond] @@ -22193,15 +27145,15 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flag * components to override. We rely on part index ordering. */ - if (flags_and_maxnargs & DUK__FLAG_TIMESETTER) { + if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) { DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4); - idx_first = DUK__IDX_MILLISECOND - (maxnargs - 1); + idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1); } else { DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3); - idx_first = DUK__IDX_DAY - (maxnargs - 1); + idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1); } DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */ - DUK_ASSERT(idx_first < DUK__NUM_PARTS); + DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS); for (i = 0; i < maxnargs; i++) { if ((duk_idx_t) i >= nargs) { @@ -22210,15 +27162,15 @@ DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flag } idx = idx_first + i; DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */ - DUK_ASSERT(idx < DUK__NUM_PARTS); + DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS); - if (idx == DUK__IDX_YEAR && (flags_and_maxnargs & DUK__FLAG_YEAR_FIXUP)) { + if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) { duk__twodigit_year_fixup(ctx, (duk_idx_t) i); } dparts[idx] = duk_to_number(ctx, i); - if (idx == DUK__IDX_DAY) { + if (idx == DUK_DATE_IDX_DAY) { /* Day-of-month is one-based in the API, but zero-based * internally, so fix here. Note that month is zero-based * both in the API and internally. @@ -22284,15 +27236,15 @@ DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk__twodigit_year_fixup(ctx, 0); /* There are at most 7 args, but we use 8 here so that also - * DUK__IDX_WEEKDAY gets initialized (to zero) to avoid the potential + * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential * for any Valgrind gripes later. */ for (i = 0; i < 8; i++) { /* Note: rely on index ordering */ - idx = DUK__IDX_YEAR + i; + idx = DUK_DATE_IDX_YEAR + i; if ((duk_idx_t) i < nargs) { d = duk_to_number(ctx, (duk_idx_t) i); - if (idx == DUK__IDX_DAY) { + if (idx == DUK_DATE_IDX_DAY) { /* Convert day from one-based to zero-based (internal). This may * cause the day part to be negative, which is OK. */ @@ -22321,18 +27273,18 @@ DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, */ DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) { - duk_int_t parts[DUK__NUM_PARTS]; + duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; - duk__timeval_to_parts(timeval, - parts, - NULL, - DUK__FLAG_ONEBASED); + duk_bi_date_timeval_to_parts(timeval, + parts, + NULL, + DUK_DATE_FLAG_ONEBASED); duk__format_parts_iso8601(parts, 0 /*tzoffset*/, - DUK__FLAG_TOSTRING_DATE | - DUK__FLAG_TOSTRING_TIME | - DUK__FLAG_SEP_T /*flags*/, + DUK_DATE_FLAG_TOSTRING_DATE | + DUK_DATE_FLAG_TOSTRING_TIME | + DUK_DATE_FLAG_SEP_T /*flags*/, out_buf); } @@ -22349,124 +27301,124 @@ DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t * static duk_uint16_t duk__date_magics[] = { /* 0: toString */ - DUK__FLAG_TOSTRING_DATE + DUK__FLAG_TOSTRING_TIME + DUK__FLAG_LOCALTIME, + DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME, /* 1: toDateString */ - DUK__FLAG_TOSTRING_DATE + DUK__FLAG_LOCALTIME, + DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME, /* 2: toTimeString */ - DUK__FLAG_TOSTRING_TIME + DUK__FLAG_LOCALTIME, + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME, /* 3: toLocaleString */ - DUK__FLAG_TOSTRING_DATE + DUK__FLAG_TOSTRING_TIME + DUK__FLAG_TOSTRING_LOCALE + DUK__FLAG_LOCALTIME, + DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME, /* 4: toLocaleDateString */ - DUK__FLAG_TOSTRING_DATE + DUK__FLAG_TOSTRING_LOCALE + DUK__FLAG_LOCALTIME, + DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME, /* 5: toLocaleTimeString */ - DUK__FLAG_TOSTRING_TIME + DUK__FLAG_TOSTRING_LOCALE + DUK__FLAG_LOCALTIME, + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME, /* 6: toUTCString */ - DUK__FLAG_TOSTRING_DATE + DUK__FLAG_TOSTRING_TIME, + DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME, /* 7: toISOString */ - DUK__FLAG_TOSTRING_DATE + DUK__FLAG_TOSTRING_TIME + DUK__FLAG_NAN_TO_RANGE_ERROR + DUK__FLAG_SEP_T, + DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T, /* 8: getFullYear */ - DUK__FLAG_LOCALTIME + (DUK__IDX_YEAR << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT), /* 9: getUTCFullYear */ - 0 + (DUK__IDX_YEAR << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT), /* 10: getMonth */ - DUK__FLAG_LOCALTIME + (DUK__IDX_MONTH << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT), /* 11: getUTCMonth */ - 0 + (DUK__IDX_MONTH << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT), /* 12: getDate */ - DUK__FLAG_ONEBASED + DUK__FLAG_LOCALTIME + (DUK__IDX_DAY << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT), /* 13: getUTCDate */ - DUK__FLAG_ONEBASED + (DUK__IDX_DAY << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT), /* 14: getDay */ - DUK__FLAG_LOCALTIME + (DUK__IDX_WEEKDAY << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT), /* 15: getUTCDay */ - 0 + (DUK__IDX_WEEKDAY << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT), /* 16: getHours */ - DUK__FLAG_LOCALTIME + (DUK__IDX_HOUR << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT), /* 17: getUTCHours */ - 0 + (DUK__IDX_HOUR << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT), /* 18: getMinutes */ - DUK__FLAG_LOCALTIME + (DUK__IDX_MINUTE << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT), /* 19: getUTCMinutes */ - 0 + (DUK__IDX_MINUTE << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT), /* 20: getSeconds */ - DUK__FLAG_LOCALTIME + (DUK__IDX_SECOND << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT), /* 21: getUTCSeconds */ - 0 + (DUK__IDX_SECOND << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT), /* 22: getMilliseconds */ - DUK__FLAG_LOCALTIME + (DUK__IDX_MILLISECOND << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT), /* 23: getUTCMilliseconds */ - 0 + (DUK__IDX_MILLISECOND << DUK__FLAG_VALUE_SHIFT), + 0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT), /* 24: setMilliseconds */ - DUK__FLAG_TIMESETTER + DUK__FLAG_LOCALTIME + (1 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT), /* 25: setUTCMilliseconds */ - DUK__FLAG_TIMESETTER + (1 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT), /* 26: setSeconds */ - DUK__FLAG_TIMESETTER + DUK__FLAG_LOCALTIME + (2 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT), /* 27: setUTCSeconds */ - DUK__FLAG_TIMESETTER + (2 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT), /* 28: setMinutes */ - DUK__FLAG_TIMESETTER + DUK__FLAG_LOCALTIME + (3 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT), /* 29: setUTCMinutes */ - DUK__FLAG_TIMESETTER + (3 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT), /* 30: setHours */ - DUK__FLAG_TIMESETTER + DUK__FLAG_LOCALTIME + (4 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT), /* 31: setUTCHours */ - DUK__FLAG_TIMESETTER + (4 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT), /* 32: setDate */ - DUK__FLAG_LOCALTIME + (1 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT), /* 33: setUTCDate */ - 0 + (1 << DUK__FLAG_VALUE_SHIFT), + 0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT), /* 34: setMonth */ - DUK__FLAG_LOCALTIME + (2 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT), /* 35: setUTCMonth */ - 0 + (2 << DUK__FLAG_VALUE_SHIFT), + 0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT), /* 36: setFullYear */ - DUK__FLAG_NAN_TO_ZERO + DUK__FLAG_LOCALTIME + (3 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT), /* 37: setUTCFullYear */ - DUK__FLAG_NAN_TO_ZERO + (3 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT), /* 38: getYear */ - DUK__FLAG_LOCALTIME + DUK__FLAG_SUB1900 + (DUK__IDX_YEAR << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT), /* 39: setYear */ - DUK__FLAG_NAN_TO_ZERO + DUK__FLAG_YEAR_FIXUP + (3 << DUK__FLAG_VALUE_SHIFT), + DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT), }; DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx) { @@ -22482,7 +27434,7 @@ DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx) { DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) { duk_idx_t nargs = duk_get_top(ctx); duk_bool_t is_cons = duk_is_constructor_call(ctx); - duk_double_t dparts[DUK__NUM_PARTS]; + duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; duk_double_t d; DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons)); @@ -22497,7 +27449,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) { */ if (nargs == 0 || !is_cons) { - d = duk__timeclip(DUK__GET_NOW_TIMEVAL(ctx)); + d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx)); duk_push_number(ctx, d); duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W); if (!is_cons) { @@ -22521,7 +27473,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) { /* Parts are in local time, convert when setting. */ - (void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK__FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */ + (void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */ duk_pop(ctx); /* -> [ ... this ] */ return 1; } @@ -22532,7 +27484,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx) { DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) { duk_idx_t nargs = duk_get_top(ctx); - duk_double_t dparts[DUK__NUM_PARTS]; + duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; duk_double_t d; /* Behavior for nargs < 2 is implementation dependent: currently we'll @@ -22543,7 +27495,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) { duk_push_nan(ctx); } else { duk__set_parts_from_args(ctx, dparts, nargs); - d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/); + d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/); duk_push_number(ctx, d); } return 1; @@ -22552,7 +27504,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) { DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) { duk_double_t d; - d = DUK__GET_NOW_TIMEVAL(ctx); + d = DUK_USE_DATE_GET_NOW(ctx); DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */ duk_push_number(ctx, d); return 1; @@ -22704,7 +27656,7 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ct duk_push_nan(ctx); } else { DUK_ASSERT(DUK_ISFINITE(d)); - tzoffset = DUK__GET_LOCAL_TZOFFSET(d); + tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); duk_push_int(ctx, -tzoffset / 60); } return 1; @@ -22775,6 +27727,412 @@ DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) { return 1; } +#line 1 "duk_bi_date_unix.c" +/* + * Unix-like Date providers + * + * Generally useful Unix / POSIX / ANSI Date providers. + */ + +/* include removed: duk_internal.h */ + +/* The necessary #includes are in place in duk_config.h. */ + +/* Buffer sizes for some UNIX calls. Larger than strictly necessary + * to avoid Valgrind errors. + */ +#define DUK__STRPTIME_BUF_SIZE 64 +#define DUK__STRFTIME_BUF_SIZE 64 + +#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY) +/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */ +DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) { + duk_hthread *thr = (duk_hthread *) ctx; + struct timeval tv; + duk_double_t d; + + if (gettimeofday(&tv, NULL) != 0) { + DUK_ERROR(thr, DUK_ERR_INTERNAL_ERROR, "gettimeofday failed"); + } + + d = ((duk_double_t) tv.tv_sec) * 1000.0 + + ((duk_double_t) (tv.tv_usec / 1000)); + DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions */ + + return d; +} +#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */ + +#if defined(DUK_USE_DATE_NOW_TIME) +/* Not a very good provider: only full seconds are available. */ +DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(duk_context *ctx) { + time_t t = time(NULL); + return ((duk_double_t) t) * 1000.0; +} +#endif /* DUK_USE_DATE_NOW_TIME */ + +#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) +/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */ +DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) { + time_t t, t1, t2; + duk_int_t parts[DUK_DATE_IDX_NUM_PARTS]; + duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS]; + struct tm tms[2]; +#ifdef DUK_USE_DATE_TZO_GMTIME + struct tm *tm_ptr; +#endif + + /* For NaN/inf, the return value doesn't matter. */ + if (!DUK_ISFINITE(d)) { + return 0; + } + + /* If not within Ecmascript range, some integer time calculations + * won't work correctly (and some asserts will fail), so bail out + * if so. This fixes test-bug-date-insane-setyear.js. There is + * a +/- 24h leeway in this range check to avoid a test262 corner + * case documented in test-bug-date-timeval-edges.js. + */ + if (!duk_bi_date_timeval_in_leeway_range(d)) { + DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows")); + return 0; + } + + /* + * This is a bit tricky to implement portably. The result depends + * on the timestamp (specifically, DST depends on the timestamp). + * If e.g. UNIX APIs are used, they'll have portability issues with + * very small and very large years. + * + * Current approach: + * + * - Stay within portable UNIX limits by using equivalent year mapping. + * Avoid year 1970 and 2038 as some conversions start to fail, at + * least on some platforms. Avoiding 1970 means that there are + * currently DST discrepancies for 1970. + * + * - Create a UTC and local time breakdowns from 't'. Then create + * a time_t using gmtime() and localtime() and compute the time + * difference between the two. + * + * Equivalent year mapping (E5 Section 15.9.1.8): + * + * If the host environment provides functionality for determining + * daylight saving time, the implementation of ECMAScript is free + * to map the year in question to an equivalent year (same + * leap-year-ness and same starting week day for the year) for which + * the host environment provides daylight saving time information. + * The only restriction is that all equivalent years should produce + * the same result. + * + * This approach is quite reasonable but not entirely correct, e.g. + * the specification also states (E5 Section 15.9.1.8): + * + * The implementation of ECMAScript should not try to determine + * whether the exact time was subject to daylight saving time, but + * just whether daylight saving time would have been in effect if + * the _current daylight saving time algorithm_ had been used at the + * time. This avoids complications such as taking into account the + * years that the locale observed daylight saving time year round. + * + * Since we rely on the platform APIs for conversions between local + * time and UTC, we can't guarantee the above. Rather, if the platform + * has historical DST rules they will be applied. This seems to be the + * general preferred direction in Ecmascript standardization (or at least + * implementations) anyway, and even the equivalent year mapping should + * be disabled if the platform is known to handle DST properly for the + * full Ecmascript range. + * + * The following has useful discussion and links: + * + * https://bugzilla.mozilla.org/show_bug.cgi?id=351066 + */ + + duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/); + DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038); + + d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/); + DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */ + t = (time_t) (d / 1000.0); + DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t)); + + t1 = t; + + DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2); + +#if defined(DUK_USE_DATE_TZO_GMTIME_R) + (void) gmtime_r(&t, &tms[0]); + (void) localtime_r(&t, &tms[1]); +#elif defined(DUK_USE_DATE_TZO_GMTIME) + tm_ptr = gmtime(&t); + DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm)); + tm_ptr = localtime(&t); + DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm)); +#else +#error internal error +#endif + DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," + "wday:%ld,yday:%ld,isdst:%ld}", + (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour, + (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year, + (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst)); + DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," + "wday:%ld,yday:%ld,isdst:%ld}", + (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour, + (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year, + (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst)); + + t1 = mktime(&tms[0]); /* UTC */ + t2 = mktime(&tms[1]); /* local */ + if (t1 == (time_t) -1 || t2 == (time_t) -1) { + /* This check used to be for (t < 0) but on some platforms + * time_t is unsigned and apparently the proper way to detect + * an mktime() error return is the cast above. See e.g.: + * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html + */ + goto error; + } + if (tms[1].tm_isdst > 0) { + t2 += 3600; + } else if (tms[1].tm_isdst < 0) { + DUK_D(DUK_DPRINT("tm_isdst is negative: %d", (int) tms[1].tm_isdst)); + } + DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2)); + + /* Compute final offset in seconds, positive if local time ahead of + * UTC (returned value is UTC-to-local offset). + * + * difftime() returns a double, so coercion to int generates quite + * a lot of code. Direct subtraction is not portable, however. + * XXX: allow direct subtraction on known platforms. + */ +#if 0 + return (duk_int_t) (t2 - t1); +#endif + return (duk_int_t) difftime(t2, t1); + + error: + /* XXX: return something more useful, so that caller can throw? */ + DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d)); + return 0; +} +#endif /* DUK_USE_DATE_TZO_GMTIME */ + +#if defined(DUK_USE_DATE_PRS_STRPTIME) +DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) { + struct tm tm; + time_t t; + char buf[DUK__STRPTIME_BUF_SIZE]; + + /* copy to buffer with spare to avoid Valgrind gripes from strptime */ + DUK_ASSERT(str != NULL); + DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */ + DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str); + buf[sizeof(buf) - 1] = (char) 0; + + DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf)); + + DUK_MEMZERO(&tm, sizeof(tm)); + if (strptime((const char *) buf, "%c", &tm) != NULL) { + DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld," + "wday:%ld,yday:%ld,isdst:%ld}", + (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour, + (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year, + (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst)); + tm.tm_isdst = -1; /* negative: dst info not available */ + + t = mktime(&tm); + DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t)); + if (t >= 0) { + duk_push_number(ctx, ((duk_double_t) t) * 1000.0); + return 1; + } + } + + return 0; +} +#endif /* DUK_USE_DATE_PRS_STRPTIME */ + +#if defined(DUK_USE_DATE_PRS_GETDATE) +DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) { + struct tm tm; + duk_small_int_t rc; + time_t t; + + /* For this to work, DATEMSK must be set, so this is not very + * convenient for an embeddable interpreter. + */ + + DUK_MEMZERO(&tm, sizeof(struct tm)); + rc = (duk_small_int_t) getdate_r(str, &tm); + DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc)); + + if (rc == 0) { + t = mktime(&tm); + DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t)); + if (t >= 0) { + duk_push_number(ctx, (duk_double_t) t); + return 1; + } + } + + return 0; +} +#endif /* DUK_USE_DATE_PRS_GETDATE */ + +#if defined(DUK_USE_DATE_FMT_STRFTIME) +DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) { + char buf[DUK__STRFTIME_BUF_SIZE]; + struct tm tm; + const char *fmt; + + DUK_UNREF(tzoffset); + + /* If the platform doesn't support the entire Ecmascript range, we need + * to return 0 so that the caller can fall back to the default formatter. + * + * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript + * range is supported. For smaller time_t values (4 bytes in practice), + * assumes that the signed 32-bit range is supported. + * + * XXX: detect this more correctly per platform. The size of time_t is + * probably not an accurate guarantee of strftime() supporting or not + * supporting a large time range (the full Ecmascript range). + */ + if (sizeof(time_t) < 8 && + (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) { + /* be paranoid for 32-bit time values (even avoiding negative ones) */ + return 0; + } + + DUK_MEMZERO(&tm, sizeof(tm)); + tm.tm_sec = parts[DUK_DATE_IDX_SECOND]; + tm.tm_min = parts[DUK_DATE_IDX_MINUTE]; + tm.tm_hour = parts[DUK_DATE_IDX_HOUR]; + tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */ + tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */ + tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900; + tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY]; + tm.tm_isdst = 0; + + DUK_MEMZERO(buf, sizeof(buf)); + if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) { + fmt = "%c"; + } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) { + fmt = "%x"; + } else { + DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME); + fmt = "%X"; + } + (void) strftime(buf, sizeof(buf) - 1, fmt, &tm); + DUK_ASSERT(buf[sizeof(buf) - 1] == 0); + + duk_push_string(ctx, buf); + return 1; +} +#endif /* DUK_USE_DATE_FMT_STRFTIME */ + +#undef DUK__STRPTIME_BUF_SIZE +#undef DUK__STRFTIME_BUF_SIZE +#line 1 "duk_bi_date_windows.c" +/* + * Windows Date providers + * + * Platform specific links: + * + * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx + */ + +/* include removed: duk_internal.h */ + +/* The necessary #includes are in place in duk_config.h. */ + +#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) +/* Shared Windows helpers. */ +DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) { + FILETIME ft; + if (SystemTimeToFileTime(st, &ft) == 0) { + DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0")); + res->QuadPart = 0; + } else { + res->LowPart = ft.dwLowDateTime; + res->HighPart = ft.dwHighDateTime; + } +} +DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) { + DUK_MEMZERO((void *) st, sizeof(*st)); + st->wYear = 1970; + st->wMonth = 1; + st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */ + st->wDay = 1; + DUK_ASSERT(st->wHour == 0); + DUK_ASSERT(st->wMinute == 0); + DUK_ASSERT(st->wSecond == 0); + DUK_ASSERT(st->wMilliseconds == 0); +} +#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */ + +#ifdef DUK_USE_DATE_NOW_WINDOWS +DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) { + /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx + */ + SYSTEMTIME st1, st2; + ULARGE_INTEGER tmp1, tmp2; + + DUK_UNREF(ctx); + + GetSystemTime(&st1); + duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1); + + duk__set_systime_jan1970(&st2); + duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2); + + /* Difference is in 100ns units, convert to milliseconds w/o fractions */ + return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL); +} +#endif /* DUK_USE_DATE_NOW_WINDOWS */ + + +#if defined(DUK_USE_DATE_TZO_WINDOWS) +DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) { + SYSTEMTIME st1; + SYSTEMTIME st2; + SYSTEMTIME st3; + ULARGE_INTEGER tmp1; + ULARGE_INTEGER tmp2; + ULARGE_INTEGER tmp3; + FILETIME ft1; + + /* XXX: handling of timestamps outside Windows supported range. + * How does Windows deal with dates before 1600? Does windows + * support all Ecmascript years (like -200000 and +200000)? + * Should equivalent year mapping be used here too? If so, use + * a shared helper (currently integrated into timeval-to-parts). + */ + + /* Use the approach described in "Remarks" of FileTimeToLocalFileTime: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx + */ + + duk__set_systime_jan1970(&st1); + duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1); + tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */ + tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */ + + ft1.dwLowDateTime = tmp2.LowPart; + ft1.dwHighDateTime = tmp2.HighPart; + FileTimeToSystemTime((const FILETIME *) &ft1, &st2); + if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) { + DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0")); + return 0; + } + duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3); + + /* Positive if local time ahead of UTC. */ + return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */ +} +#endif /* DUK_USE_DATE_TZO_WINDOWS */ #line 1 "duk_bi_duktape.c" /* * Duktape built-ins @@ -22881,7 +28239,7 @@ DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) { */ duk_hbuffer_dynamic *h_dyn = (duk_hbuffer_dynamic *) h; duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_dynamic))); - duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(h_dyn))); + duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_DYNAMIC_GET_SIZE(h_dyn))); } else { duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1)); } @@ -23786,6 +29144,11 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) { * Encoding/decoding helpers */ +/* XXX: Could add fast path (for each transform callback) with direct byte + * lookups (no shifting) and no explicit check for x < 0x80 before table + * lookup. + */ + /* Macros for creating and checking bitmasks for character encoding. * Bit number is a bit counterintuitive, but minimizes code size. */ @@ -23857,10 +29220,12 @@ DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = { }; #endif /* DUK_USE_SECTION_B */ +#undef DUK__MKBITS + typedef struct { duk_hthread *thr; duk_hstring *h_str; - duk_hbuffer_dynamic *h_buf; + duk_bufwriter_ctx bw; const duk_uint8_t *p; const duk_uint8_t *p_start; const duk_uint8_t *p_end; @@ -23897,10 +29262,7 @@ DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback ca tfm_ctx->h_str = duk_to_hstring(ctx, 0); DUK_ASSERT(tfm_ctx->h_str != NULL); - (void) duk_push_dynamic_buffer(ctx, 0); - tfm_ctx->h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(tfm_ctx->h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(tfm_ctx->h_buf)); + DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */ tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str); tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str); @@ -23911,22 +29273,29 @@ DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback ca callback(tfm_ctx, udata, cp); } + DUK_BW_COMPACT(thr, &tfm_ctx->bw); + duk_to_string(ctx, -1); return 1; } DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, void *udata, duk_codepoint_t cp) { duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH]; - duk_uint8_t buf[3]; duk_small_int_t len; duk_codepoint_t cp1, cp2; duk_small_int_t i, t; const duk_uint8_t *unescaped_table = (duk_uint8_t *) udata; + /* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes. + * Codepoint range is restricted so this is a slightly too large + * but doesn't matter. + */ + DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH); + if (cp < 0) { goto uri_error; } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) { - duk_hbuffer_append_byte(tfm_ctx->thr, tfm_ctx->h_buf, (duk_uint8_t) cp); + DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp); return; } else if (cp >= 0xdc00L && cp <= 0xdfffL) { goto uri_error; @@ -23950,19 +29319,22 @@ DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ct goto uri_error; } else { /* Non-BMP characters within valid UTF-8 range: encode as is. - * They'll decode back into surrogate pairs. + * They'll decode back into surrogate pairs if the escaped + * output is decoded. */ ; } len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf); - buf[0] = (duk_uint8_t) '%'; for (i = 0; i < len; i++) { t = (int) xutf8_buf[i]; - buf[1] = (duk_uint8_t) duk_uc_nybbles[t >> 4]; - buf[2] = (duk_uint8_t) duk_uc_nybbles[t & 0x0f]; - duk_hbuffer_append_bytes(tfm_ctx->thr, tfm_ctx->h_buf, buf, 3); + DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, + &tfm_ctx->bw, + DUK_ASC_PERCENT, + (duk_uint8_t) duk_uc_nybbles[t >> 4], + (duk_uint8_t) duk_uc_nybbles[t & 0x0f]); } + return; uri_error: @@ -23976,6 +29348,14 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct duk_small_int_t t; /* must be signed */ duk_small_uint_t i; + /* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH, + * percent escape path writes max two times CESU-8 encoded BMP length. + */ + DUK_BW_ENSURE(tfm_ctx->thr, + &tfm_ctx->bw, + (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ? + DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH)); + if (cp == (duk_codepoint_t) '%') { const duk_uint8_t *p = tfm_ctx->p; duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */ @@ -23996,9 +29376,13 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct if (DUK__CHECK_BITMASK(reserved_table, t)) { /* decode '%xx' to '%xx' if decoded char in reserved set */ DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start); - duk_hbuffer_append_bytes(tfm_ctx->thr, tfm_ctx->h_buf, (duk_uint8_t *) (p - 1), 3); + DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, + &tfm_ctx->bw, + DUK_ASC_PERCENT, + p[0], + p[1]); } else { - duk_hbuffer_append_byte(tfm_ctx->thr, tfm_ctx->h_buf, (duk_uint8_t) t); + DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t); } tfm_ctx->p += 2; return; @@ -24080,13 +29464,14 @@ DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ct if (cp >= 0x10000L) { cp -= 0x10000L; DUK_ASSERT(cp < 0x100000L); - duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) ((cp >> 10) + 0xd800L)); - duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) ((cp & 0x03ffUL) + 0xdc00L)); + + DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L)); + DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L)); } else { - duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) cp); + DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp); } } else { - duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, (duk_ucodepoint_t) cp); + DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp); } return; @@ -24096,29 +29481,29 @@ 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_uint8_t buf[6]; - duk_small_int_t len; - DUK_UNREF(udata); + DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6); + if (cp < 0) { goto esc_error; } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) { - buf[0] = (duk_uint8_t) cp; - len = 1; + DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp); } else if (cp < 0x100L) { - buf[0] = (duk_uint8_t) '%'; - buf[1] = (duk_uint8_t) duk_uc_nybbles[cp >> 4]; - buf[2] = (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]; - len = 3; + DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr, + &tfm_ctx->bw, + (duk_uint8_t) DUK_ASC_PERCENT, + (duk_uint8_t) duk_uc_nybbles[cp >> 4], + (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]); } else if (cp < 0x10000L) { - buf[0] = (duk_uint8_t) '%'; - buf[1] = (duk_uint8_t) 'u'; - buf[2] = (duk_uint8_t) duk_uc_nybbles[cp >> 12]; - buf[3] = (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f]; - buf[4] = (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f]; - buf[5] = (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]; - len = 6; + DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr, + &tfm_ctx->bw, + (duk_uint8_t) DUK_ASC_PERCENT, + (duk_uint8_t) DUK_ASC_LC_U, + (duk_uint8_t) duk_uc_nybbles[cp >> 12], + (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f], + (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f], + (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]); } else { /* Characters outside BMP cannot be escape()'d. We could * encode them as surrogate pairs (for codepoints inside @@ -24128,7 +29513,6 @@ DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, v goto esc_error; } - duk_hbuffer_append_bytes(tfm_ctx->thr, tfm_ctx->h_buf, buf, len); return; esc_error: @@ -24155,7 +29539,7 @@ DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, } } - duk_hbuffer_append_xutf8(tfm_ctx->thr, tfm_ctx->h_buf, cp); + DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp); } #endif /* DUK_USE_SECTION_B */ @@ -24736,6 +30120,7 @@ DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *re DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { const char *str_req_id; /* requested identifier */ const char *str_mod_id; /* require.id of current module */ + duk_int_t pcall_rc; /* NOTE: we try to minimize code size by avoiding unnecessary pops, * so the stack looks a bit cluttered in this function. DUK_ASSERT_TOP() @@ -24789,6 +30174,7 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */ DUK_DD(DUK_DDPRINT("module already loaded: %!T", (duk_tval *) duk_get_tval(ctx, 3))); + duk_get_prop_stridx(ctx, -1, DUK_STRIDX_EXPORTS); /* return module.exports */ return 1; } @@ -24819,19 +30205,30 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { duk_dup(ctx, 3); duk_xdef_prop_stridx(ctx, 7, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_C); /* a fresh require() with require.id = resolved target module id */ - /* Exports table. */ - duk_push_object(ctx); - - /* Module table: module.id is non-writable and non-configurable, as - * the CommonJS spec suggests this if possible. + /* Module table: + * - module.exports: initial exports table (may be replaced by user) + * - module.id is non-writable and non-configurable, as the CommonJS + * spec suggests this if possible. */ - duk_push_object(ctx); + duk_push_object(ctx); /* exports */ + duk_push_object(ctx); /* module */ + duk_dup(ctx, -2); + duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS, DUK_PROPDESC_FLAGS_WC); /* module.exports = exports */ duk_dup(ctx, 3); /* resolved id: require(id) must return this same module */ - duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE); + duk_xdef_prop_stridx(ctx, 9, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE); /* module.id = resolved_id */ + duk_compact(ctx, 9); /* module table remains registered to modLoaded, minimize its size */ /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module ] */ DUK_ASSERT_TOP(ctx, 10); + /* Register the module table early to modLoaded[] so that we can + * support circular references even in modSearch(). If an error + * is thrown, we'll delete the reference. + */ + duk_dup(ctx, 3); + duk_dup(ctx, 9); + duk_put_prop(ctx, 5); /* Duktape.modLoaded[resolved_id] = module */ + /* * Call user provided module search function and build the wrapped * module source code (if necessary). The module search function @@ -24844,11 +30241,9 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { * is returned the module is assumed to be a pure C one). If a module * cannot be found, an error must be thrown by the user callback. * - * NOTE: the current arrangement allows C modules to be implemented - * but since the exports table is registered to Duktape.modLoaded only - * after the search function returns, circular requires / partially - * loaded modules don't work for C modules. This is rarely an issue, - * as C modules usually simply expose a set of helper functions. + * Because Duktape.modLoaded[] already contains the module being + * loaded, circular references for C modules should also work + * (although expected to be quite rare). */ duk_push_string(ctx, "(function(require,exports,module){"); @@ -24859,23 +30254,23 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { duk_dup(ctx, 7); duk_dup(ctx, 8); duk_dup(ctx, 9); /* [ ... Duktape.modSearch resolved_id fresh_require exports module ] */ - duk_call(ctx, 4 /*nargs*/); /* -> [ ... source ] */ + pcall_rc = duk_pcall(ctx, 4 /*nargs*/); /* -> [ ... source ] */ DUK_ASSERT_TOP(ctx, 12); - /* Because user callback did not throw an error, remember exports table. */ - duk_dup(ctx, 3); - duk_dup(ctx, 8); - duk_xdef_prop(ctx, 5, DUK_PROPDESC_FLAGS_EC); /* Duktape.modLoaded[resolved_id] = exports */ + if (pcall_rc != DUK_EXEC_SUCCESS) { + /* Delete entry in Duktape.modLoaded[] and rethrow. */ + goto delete_rethrow; + } /* If user callback did not return source code, module loading * is finished (user callback initialized exports table directly). */ if (!duk_is_string(ctx, 11)) { - /* User callback did not return source code, so - * module loading is finished. + /* User callback did not return source code, so module loading + * is finished: just update modLoaded with final module.exports + * and we're done. */ - duk_dup(ctx, 8); - return 1; + goto return_exports; } /* Finish the wrapped module source. Force resolved module ID as the @@ -24900,6 +30295,9 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { /* * Call the wrapped module function. + * + * Use a protected call so that we can update Duktape.modLoaded[resolved_id] + * even if the module throws an error. */ /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */ @@ -24907,19 +30305,35 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { duk_dup(ctx, 8); /* exports (this binding) */ duk_dup(ctx, 7); /* fresh require (argument) */ - duk_dup(ctx, 8); /* exports (argument) */ + duk_get_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS); /* relookup exports from module.exports in case it was changed by modSearch */ duk_dup(ctx, 9); /* module (argument) */ /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */ DUK_ASSERT_TOP(ctx, 15); - duk_call_method(ctx, 3 /*nargs*/); + pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/); + if (pcall_rc != DUK_EXEC_SUCCESS) { + /* Module loading failed. Node.js will forget the module + * registration so that another require() will try to load + * the module again. Mimic that behavior. + */ + goto delete_rethrow; + } /* [ requested_id require require.id resolved_id Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */ DUK_ASSERT_TOP(ctx, 11); - duk_pop_2(ctx); - return 1; /* return exports */ + /* fall through */ + + return_exports: + duk_get_prop_stridx(ctx, 9, DUK_STRIDX_EXPORTS); + return 1; /* return module.exports */ + + delete_rethrow: + duk_dup(ctx, 3); + duk_del_prop(ctx, 5); /* delete Duktape.modLoaded[resolved_id] */ + duk_throw(ctx); /* rethrow original error */ + return 0; /* not reachable */ } #else DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { @@ -24931,10 +30345,17 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { /* * JSON built-ins. * - * See doc/json.txt. + * See doc/json.rst. * * Codepoints are handled as duk_uint_fast32_t to ensure that the full * unsigned 32-bit range is supported. This matters to e.g. JX. + * + * Input parsing doesn't do an explicit end-of-input check at all. This is + * safe: input string data is always NUL-terminated (0x00) and valid JSON + * inputs never contain plain NUL characters, so that as long as syntax checks + * are correct, we'll never read past the NUL. This approach reduces code size + * and improves parsing performance, but it's critical that syntax checks are + * indeed correct! */ /* include removed: duk_internal.h */ @@ -24943,11 +30364,17 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) { * Local defines and forward declarations. */ +#define DUK__JSON_DECSTR_BUFSIZE 128 +#define DUK__JSON_DECSTR_CHUNKSIZE 64 +#define DUK__JSON_ENCSTR_CHUNKSIZE 64 +#define DUK__JSON_STRINGIFY_BUFSIZE 128 +#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */ + DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx); DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_small_int_t duk__dec_peek(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_small_int_t duk__dec_get(duk_json_dec_ctx *js_ctx); -DUK_LOCAL_DECL duk_small_int_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx); +DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx); DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n); DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx); DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx); @@ -24965,14 +30392,16 @@ DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx); DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx); DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch); -DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast16_t packed_chars); -DUK_LOCAL_DECL void duk__emit_esc_auto(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp); -DUK_LOCAL_DECL void duk__emit_xutf8(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp); +DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2); +#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) +DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx); +#endif DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h); #if defined(DUK_USE_JX) || defined(DUK_USE_JC) DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p); #endif DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx); +DUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q); DUK_LOCAL_DECL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key); DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str); DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_stepback, duk_hstring **h_indent, duk_idx_t *entry_top); @@ -24982,6 +30411,120 @@ DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx); DUK_LOCAL_DECL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder); DUK_LOCAL_DECL void duk__enc_value2(duk_json_enc_ctx *js_ctx); DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv); +DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx); +#if defined(DUK_USE_FASTINT) +DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv); +#endif + +/* + * Helper tables + */ + +#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH) +DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = { + /* 0x00 ... 0x7f: as is + * 0x80: escape generically + * 0x81: slow path + * 0xa0 ... 0xff: backslash + one char + */ + + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81 +}; +#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ +DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = { + DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, + DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, + DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL, + DUK_ASC_LC_F, DUK_ASC_LC_R +}; +#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ + +#if defined(DUK_USE_JSON_DECSTRING_FASTPATH) +DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = { + /* 0x00: slow path + * other: as is + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; +#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */ + +#if defined(DUK_USE_JSON_EATWHITE_FASTPATH) +DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = { + /* 0x00: finish (non-white) + * 0x01: continue + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */ + +#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH) +DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = { + /* 0x00: finish (not part of number) + * 0x01: continue + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */ /* * Parsing implementation. @@ -25006,39 +30549,46 @@ DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) { } DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) { - duk_small_uint_t t; + const duk_uint8_t *p; + duk_uint8_t t; + + p = js_ctx->p; for (;;) { - if (js_ctx->p >= js_ctx->p_end) { + DUK_ASSERT(p <= js_ctx->p_end); + t = *p; + +#if defined(DUK_USE_JSON_EATWHITE_FASTPATH) + /* This fast path is pretty marginal in practice. + * XXX: candidate for removal. + */ + DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */ + if (duk__json_eatwhite_lookup[t] == 0) { break; } - t = (*js_ctx->p); +#else /* DUK_USE_JSON_EATWHITE_FASTPATH */ if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) { + /* NUL also comes here. Comparison order matters, 0x20 + * is most common whitespace. + */ break; } - js_ctx->p++; +#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */ + p++; } + js_ctx->p = p; } -DUK_LOCAL duk_small_int_t duk__dec_peek(duk_json_dec_ctx *js_ctx) { - if (js_ctx->p >= js_ctx->p_end) { - return -1; - } else { - return (duk_small_int_t) (*js_ctx->p); - } +DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) { + DUK_ASSERT(js_ctx->p <= js_ctx->p_end); + return *js_ctx->p; } -DUK_LOCAL duk_small_int_t duk__dec_get(duk_json_dec_ctx *js_ctx) { - /* Multiple EOFs will now be supplied to the caller. This could also be - * changed so that reading the second EOF would cause an error automatically. - */ - if (js_ctx->p >= js_ctx->p_end) { - return -1; - } else { - return (duk_small_int_t) (*js_ctx->p++); - } +DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) { + DUK_ASSERT(js_ctx->p <= js_ctx->p_end); + return *js_ctx->p++; } -DUK_LOCAL duk_small_int_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) { +DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) { duk__dec_eat_white(js_ctx); return duk__dec_get(js_ctx); } @@ -25047,21 +30597,21 @@ DUK_LOCAL duk_small_int_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) { DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) { duk_small_uint_t i; duk_uint_fast32_t res = 0; - duk_small_int_t x; + duk_uint8_t x; + duk_small_int_t t; for (i = 0; i < n; i++) { /* XXX: share helper from lexer; duk_lexer.c / hexval(). */ x = duk__dec_get(js_ctx); - DUK_ASSERT((x >= 0 && x <= 0xff) || (x == -1)); - DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld", (long) i, (long) n, (long) res, (long) x)); - /* x == -1 will map to 0xff, dectab returns -1 which causes syntax_error */ - x = duk_hex_dectab[x & 0xff]; - if (DUK_LIKELY(x >= 0)) { - res = (res * 16) + x; + /* x == 0x00 (EOF) causes syntax_error */ + DUK_ASSERT(duk_hex_dectab[0] == -1); + t = duk_hex_dectab[x & 0xff]; + if (DUK_LIKELY(t >= 0)) { + res = (res * 16) + t; } else { /* catches EOF and invalid digits */ goto syntax_error; @@ -25080,27 +30630,29 @@ 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; - duk_uint8_t *p_end; - duk_small_int_t x; + duk_uint8_t x, y; - /* First character has already been eaten and checked by the caller. */ + /* First character has already been eaten and checked by the caller. + * We can scan until a NUL in stridx string because no built-in strings + * have internal NULs. + */ DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */ DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx); DUK_ASSERT(h != NULL); - p = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h); - p_end = ((duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + - DUK_HSTRING_GET_BYTELEN(h); + p = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1; + DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */ - DUK_ASSERT(*(js_ctx->p - 1) == *p); /* first character has been matched */ - p++; /* first char */ - - while (p < p_end) { - x = duk__dec_get(js_ctx); - if ((duk_small_int_t) (*p) != x) { - /* catches EOF */ + for (;;) { + x = *p; + if (x == 0) { + break; + } + y = duk__dec_get(js_ctx); + if (x != y) { + /* Catches EOF of JSON input. */ goto syntax_error; } p++; @@ -25113,12 +30665,61 @@ DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t st DUK_UNREACHABLE(); } +DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) { + duk_uint_fast32_t cp; + + /* EOF (-1) will be cast to an unsigned value first + * and then re-cast for the switch. In any case, it + * will match the default case (syntax error). + */ + cp = (duk_uint_fast32_t) duk__dec_get(js_ctx); + switch ((int) cp) { + case DUK_ASC_BACKSLASH: break; + case DUK_ASC_DOUBLEQUOTE: break; + case DUK_ASC_SLASH: break; + case DUK_ASC_LC_T: cp = 0x09; break; + case DUK_ASC_LC_N: cp = 0x0a; break; + case DUK_ASC_LC_R: cp = 0x0d; break; + case DUK_ASC_LC_F: cp = 0x0c; break; + case DUK_ASC_LC_B: cp = 0x08; break; + case DUK_ASC_LC_U: { + cp = duk__dec_decode_hex_escape(js_ctx, 4); + break; + } +#ifdef DUK_USE_JX + case DUK_ASC_UC_U: { + if (js_ctx->flag_ext_custom) { + cp = duk__dec_decode_hex_escape(js_ctx, 8); + } else { + return 1; /* syntax error */ + } + break; + } + case DUK_ASC_LC_X: { + if (js_ctx->flag_ext_custom) { + cp = duk__dec_decode_hex_escape(js_ctx, 2); + } else { + return 1; /* syntax error */ + } + break; + } +#endif /* DUK_USE_JX */ + default: + /* catches EOF (0x00) */ + return 1; /* syntax error */ + } + + DUK_RAW_WRITE_XUTF8(*ext_p, cp); + + return 0; +} + DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; duk_context *ctx = (duk_context *) thr; - duk_hbuffer_dynamic *h_buf; - duk_small_int_t x; - duk_uint_fast32_t cp; + duk_bufwriter_ctx bw_alloc; + duk_bufwriter_ctx *bw; + duk_uint8_t *q; /* '"' was eaten by caller */ @@ -25127,65 +30728,87 @@ DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) { * so they'll simply pass through (valid UTF-8 or not). */ - duk_push_dynamic_buffer(ctx, 0); - h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf)); + bw = &bw_alloc; + DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE); + q = DUK_BW_GET_PTR(js_ctx->thr, bw); +#if defined(DUK_USE_JSON_DECSTRING_FASTPATH) for (;;) { - x = duk__dec_get(js_ctx); - if (x == DUK_ASC_DOUBLEQUOTE) { - break; - } else if (x == DUK_ASC_BACKSLASH) { - /* EOF (-1) will be cast to an unsigned value first - * and then re-cast for the switch. In any case, it - * will match the default case (syntax error). - */ - cp = (duk_uint_fast32_t) duk__dec_get(js_ctx); - switch ((int) cp) { - case DUK_ASC_BACKSLASH: break; - case DUK_ASC_DOUBLEQUOTE: break; - case DUK_ASC_SLASH: break; - case DUK_ASC_LC_T: cp = 0x09; break; - case DUK_ASC_LC_N: cp = 0x0a; break; - case DUK_ASC_LC_R: cp = 0x0d; break; - case DUK_ASC_LC_F: cp = 0x0c; break; - case DUK_ASC_LC_B: cp = 0x08; break; - case DUK_ASC_LC_U: { - cp = duk__dec_decode_hex_escape(js_ctx, 4); - break; - } -#ifdef DUK_USE_JX - case DUK_ASC_UC_U: { - if (js_ctx->flag_ext_custom) { - cp = duk__dec_decode_hex_escape(js_ctx, 8); - } else { - goto syntax_error; - } + duk_small_uint_t safe; + duk_uint8_t b, x; + const duk_uint8_t *p; + + /* Select a safe loop count where no output checks are + * needed assuming we won't encounter escapes. Input + * bound checks are not necessary as a NUL (guaranteed) + * will cause a SyntaxError before we read out of bounds. + */ + + safe = DUK__JSON_DECSTR_CHUNKSIZE; + + /* Ensure space for 1:1 output plus one escape. */ + q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q); + + p = js_ctx->p; /* temp copy, write back for next loop */ + for (;;) { + if (safe == 0) { + js_ctx->p = p; break; } - case DUK_ASC_LC_X: { - if (js_ctx->flag_ext_custom) { - cp = duk__dec_decode_hex_escape(js_ctx, 2); - } else { + safe--; + + /* End of input (NUL) goes through slow path and causes SyntaxError. */ + DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00); + + b = *p++; + x = (duk_small_int_t) duk__json_decstr_lookup[b]; + if (DUK_LIKELY(x != 0)) { + /* Fast path, decode as is. */ + *q++ = b; + } else if (b == DUK_ASC_DOUBLEQUOTE) { + js_ctx->p = p; + goto found_quote; + } else if (b == DUK_ASC_BACKSLASH) { + /* We've ensured space for one escaped input; then + * bail out and recheck (this makes escape handling + * quite slow but it's uncommon). + */ + js_ctx->p = p; + if (duk__dec_string_escape(js_ctx, &q) != 0) { goto syntax_error; } break; + } else { + js_ctx->p = p; + goto syntax_error; } -#endif /* DUK_USE_JX */ - default: - /* catches EOF (-1) */ + } + } + found_quote: +#else /* DUK_USE_JSON_DECSTRING_FASTPATH */ + for (;;) { + duk_uint8_t x; + + q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q); + + x = duk__dec_get(js_ctx); + + if (x == DUK_ASC_DOUBLEQUOTE) { + break; + } else if (x == DUK_ASC_BACKSLASH) { + if (duk__dec_string_escape(js_ctx, &q) != 0) { goto syntax_error; } - duk_hbuffer_append_xutf8(thr, h_buf, (duk_uint32_t) cp); } else if (x < 0x20) { - /* catches EOF (-1) */ + /* catches EOF (NUL) */ goto syntax_error; } else { - duk_hbuffer_append_byte(thr, h_buf, (duk_uint8_t) x); + *q++ = (duk_uint8_t) x; } } +#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */ + DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q); duk_to_string(ctx, -1); /* [ ... str ] */ @@ -25341,44 +30964,50 @@ DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) { DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) { duk_context *ctx = (duk_context *) js_ctx->thr; const duk_uint8_t *p_start; - duk_small_int_t x; + const duk_uint8_t *p; + duk_uint8_t x; duk_small_uint_t s2n_flags; DUK_DDD(DUK_DDDPRINT("parse_number")); - /* Caller has already eaten the first character so backtrack one - * byte. This is correct because the first character is either - * '-' or a digit (i.e. an ASCII character). - */ - - js_ctx->p--; /* safe */ p_start = js_ctx->p; /* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a * string for strict number parsing. */ + p = js_ctx->p; for (;;) { - x = duk__dec_peek(js_ctx); + x = *p; DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld", - (void *) p_start, (void *) js_ctx->p, + (void *) p_start, (void *) p, (void *) js_ctx->p_end, (long) x)); +#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH) + /* This fast path is pretty marginal in practice. + * XXX: candidate for removal. + */ + DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */ + if (duk__json_decnumber_lookup[x] == 0) { + break; + } +#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */ if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E || x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) { /* Plus sign must be accepted for positive exponents - * (e.g. '1.5e+2'). + * (e.g. '1.5e+2'). This clause catches NULs. */ break; } - - js_ctx->p++; /* safe, because matched char */ +#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */ + p++; /* safe, because matched (NUL causes a break) */ } + js_ctx->p = p; DUK_ASSERT(js_ctx->p > p_start); - duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (js_ctx->p - p_start)); + duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start)); s2n_flags = DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */ @@ -25422,7 +31051,7 @@ DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) { DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { duk_context *ctx = (duk_context *) js_ctx->thr; duk_int_t key_count; /* XXX: a "first" flag would suffice */ - duk_small_int_t x; + duk_uint8_t x; DUK_DDD(DUK_DDDPRINT("parse_object")); @@ -25454,7 +31083,7 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { */ ; } else { - /* catches EOF (and initial comma) */ + /* catches EOF (NUL) and initial comma */ goto syntax_error; } @@ -25505,7 +31134,7 @@ DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) { DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { duk_context *ctx = (duk_context *) js_ctx->thr; duk_uarridx_t arr_idx; - duk_small_int_t x; + duk_uint8_t x; DUK_DDD(DUK_DDDPRINT("parse_array")); @@ -25537,7 +31166,7 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { */ js_ctx->p--; /* backtrack (safe) */ } else { - /* catches EOF (and initial comma) */ + /* catches EOF (NUL) and initial comma */ goto syntax_error; } @@ -25572,7 +31201,7 @@ DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) { DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) { duk_context *ctx = (duk_context *) js_ctx->thr; - duk_small_int_t x; + duk_uint8_t x; x = duk__dec_get_nonwhite(js_ctx); @@ -25591,7 +31220,8 @@ DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) { #else { /* unconditional block */ #endif - /* We already ate 'x', so duk__dec_number() will back up one byte. */ + /* We already ate 'x', so backup one byte. */ + js_ctx->p--; /* safe */ duk__dec_number(js_ctx); } } else if (x == DUK_ASC_LC_T) { @@ -25623,7 +31253,7 @@ DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) { } else if (x == DUK_ASC_LBRACKET) { duk__dec_array(js_ctx); } else { - /* catches EOF */ + /* catches EOF (NUL) */ goto syntax_error; } @@ -25735,36 +31365,65 @@ DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) { */ #define DUK__EMIT_1(js_ctx,ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch)) -#define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (((duk_uint_fast16_t)(ch1)) << 8) + (duk_uint_fast16_t)(ch2)) -#define DUK__EMIT_ESC_AUTO(js_ctx,cp) duk__emit_esc_auto((js_ctx), (cp)) -#define DUK__EMIT_XUTF8(js_ctx,cp) duk__emit_xutf8((js_ctx), (cp)) +#define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2)) #define DUK__EMIT_HSTR(js_ctx,h) duk__emit_hstring((js_ctx), (h)) #if defined(DUK_USE_JX) || defined(DUK_USE_JC) #define DUK__EMIT_CSTR(js_ctx,p) duk__emit_cstring((js_ctx), (p)) #endif #define DUK__EMIT_STRIDX(js_ctx,i) duk__emit_stridx((js_ctx), (i)) +#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) +#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx)) +#endif DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) { - duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, (duk_uint8_t) ch); + DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch); } -DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast16_t packed_chars) { - duk_uint8_t buf[2]; - buf[0] = (duk_uint8_t) (packed_chars >> 8); - buf[1] = (duk_uint8_t) (packed_chars & 0xff); - duk_hbuffer_append_bytes(js_ctx->thr, js_ctx->h_buf, (duk_uint8_t *) buf, 2); +DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) { + DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2); +} + +DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) { + DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h); +} + +#if defined(DUK_USE_JX) || defined(DUK_USE_JC) +DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) { + DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str); } +#endif + +DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) { + duk_hstring *h; + + DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */ + DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); + h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx); + DUK_ASSERT(h != NULL); + + DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h); +} + +#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) +DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) { + DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1); + DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1); +} +#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */ #define DUK__MKESC(nybbles,esc1,esc2) \ (((duk_uint_fast32_t) (nybbles)) << 16) | \ (((duk_uint_fast32_t) (esc1)) << 8) | \ ((duk_uint_fast32_t) (esc2)) -DUK_LOCAL void duk__emit_esc_auto(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp) { - duk_uint8_t buf[2]; +DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) { duk_uint_fast32_t tmp; duk_small_uint_t dig; + DUK_UNREF(js_ctx); + + /* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */ + /* Select appropriate escape format automatically, and set 'tmp' to a * value encoding both the escape format character and the nybble count: * @@ -25798,41 +31457,17 @@ DUK_LOCAL void duk__emit_esc_auto(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp } } - buf[0] = (duk_uint8_t) ((tmp >> 8) & 0xff); - buf[1] = (duk_uint8_t) (tmp & 0xff); - duk_hbuffer_append_bytes(js_ctx->thr, js_ctx->h_buf, buf, 2); + *q++ = (duk_uint8_t) ((tmp >> 8) & 0xff); + *q++ = (duk_uint8_t) (tmp & 0xff); tmp = tmp >> 16; while (tmp > 0) { tmp--; dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f); - duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, duk_lc_digits[dig]); + *q++ = duk_lc_digits[dig]; } -} -DUK_LOCAL void duk__emit_xutf8(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp) { - (void) duk_hbuffer_append_xutf8(js_ctx->thr, js_ctx->h_buf, cp); -} - -DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) { - DUK_ASSERT(h != NULL); - duk_hbuffer_append_bytes(js_ctx->thr, - js_ctx->h_buf, - (duk_uint8_t *) DUK_HSTRING_GET_DATA(h), - (duk_size_t) DUK_HSTRING_GET_BYTELEN(h)); -} - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) -DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p) { - DUK_ASSERT(p != NULL); - (void) duk_hbuffer_append_cstring(js_ctx->thr, js_ctx->h_buf, p); -} -#endif - -DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) { - DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */ - DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS); - duk__emit_hstring(js_ctx, DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx)); + return q; } /* Check whether key quotes would be needed (custom encoding). */ @@ -25882,16 +31517,10 @@ DUK_LOCAL duk_bool_t duk__enc_key_quotes_needed(duk_hstring *h_key) { * Stack policy: [ ] -> [ ]. */ -DUK_LOCAL duk_uint8_t duk__quote_esc[14] = { - DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, - DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, - DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL, - DUK_ASC_LC_F, DUK_ASC_LC_R -}; - DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) { duk_hthread *thr = js_ctx->thr; - const duk_uint8_t *p, *p_start, *p_end, *p_tmp; + const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp; + duk_uint8_t *q; duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */ DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str)); @@ -25903,72 +31532,217 @@ DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_st DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE); + /* Encode string in small chunks, estimating the maximum expansion so that + * there's no need to ensure space while processing the chunk. + */ + while (p < p_end) { - cp = *p; + duk_size_t left, now, space; - if (DUK_LIKELY(cp <= 0x7f)) { - /* ascii fast path: avoid decoding utf-8 */ - p++; - if (cp == 0x22 || cp == 0x5c) { - /* double quote or backslash */ - DUK__EMIT_2(js_ctx, DUK_ASC_BACKSLASH, cp); - } else if (cp < 0x20) { - duk_uint_fast8_t esc_char; - - /* This approach is a bit shorter than a straight - * if-else-ladder and also a bit faster. - */ - if (cp < (sizeof(duk__quote_esc) / sizeof(duk_uint8_t)) && - (esc_char = duk__quote_esc[cp]) != 0) { - DUK__EMIT_2(js_ctx, DUK_ASC_BACKSLASH, esc_char); + left = (duk_size_t) (p_end - p); + now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ? + DUK__JSON_ENCSTR_CHUNKSIZE : left); + + /* Maximum expansion per input byte is 6: + * - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6). + * - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3). + * - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5). + */ + space = now * 6; + q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space); + + p_now = p + now; + + while (p < p_now) { +#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH) + duk_uint8_t b; + + b = duk__json_quotestr_lookup[*p++]; + if (DUK_LIKELY(b < 0x80)) { + /* Most input bytes go through here. */ + *q++ = b; + } else if (b >= 0xa0) { + *q++ = DUK_ASC_BACKSLASH; + *q++ = (duk_uint8_t) (b - 0x80); + } else if (b == 0x80) { + cp = (duk_ucodepoint_t) (*(p - 1)); + q = duk__emit_esc_auto_fast(js_ctx, cp, q); + } else if (b == 0x7f && js_ctx->flag_ascii_only) { + /* 0x7F is special */ + DUK_ASSERT(b == 0x81); + cp = (duk_ucodepoint_t) 0x7f; + q = duk__emit_esc_auto_fast(js_ctx, cp, q); + } else { + DUK_ASSERT(b == 0x81); + p--; + + /* slow path is shared */ +#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ + cp = *p; + + if (DUK_LIKELY(cp <= 0x7f)) { + /* ascii fast path: avoid decoding utf-8 */ + p++; + if (cp == 0x22 || cp == 0x5c) { + /* double quote or backslash */ + *q++ = DUK_ASC_BACKSLASH; + *q++ = (duk_uint8_t) cp; + } else if (cp < 0x20) { + duk_uint_fast8_t esc_char; + + /* This approach is a bit shorter than a straight + * if-else-ladder and also a bit faster. + */ + if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) && + (esc_char = duk__json_quotestr_esc[cp]) != 0) { + *q++ = DUK_ASC_BACKSLASH; + *q++ = (duk_uint8_t) esc_char; + } else { + q = duk__emit_esc_auto_fast(js_ctx, cp, q); + } + } else if (cp == 0x7f && js_ctx->flag_ascii_only) { + q = duk__emit_esc_auto_fast(js_ctx, cp, q); } else { - DUK__EMIT_ESC_AUTO(js_ctx, cp); + /* any other printable -> as is */ + *q++ = (duk_uint8_t) cp; } - } else if (cp == 0x7f && js_ctx->flag_ascii_only) { - DUK__EMIT_ESC_AUTO(js_ctx, cp); } else { - /* any other printable -> as is */ - DUK__EMIT_1(js_ctx, cp); - } - } else { - /* slow path decode */ - - /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly - * and go forward one byte. This is of course very lossy, but allows some kind - * of output to be produced even for internal strings which don't conform to - * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior - * does not violate the Ecmascript specification. The behavior is applied to - * all modes, including Ecmascript standard JSON. Because the current XUTF-8 - * decoding is not very strict, this behavior only really affects initial bytes - * and truncated codepoints. - * - * XXX: another alternative would be to scan forwards to start of next codepoint - * (or end of input) and emit just one replacement codepoint. - */ + /* slow path is shared */ +#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */ + + /* slow path decode */ + + /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly + * and go forward one byte. This is of course very lossy, but allows some kind + * of output to be produced even for internal strings which don't conform to + * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior + * does not violate the Ecmascript specification. The behavior is applied to + * all modes, including Ecmascript standard JSON. Because the current XUTF-8 + * decoding is not very strict, this behavior only really affects initial bytes + * and truncated codepoints. + * + * Another alternative would be to scan forwards to start of next codepoint + * (or end of input) and emit just one replacement codepoint. + */ - p_tmp = p; - if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) { - /* Decode failed. */ - cp = *p_tmp; - p = p_tmp + 1; - } + p_tmp = p; + if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) { + /* Decode failed. */ + cp = *p_tmp; + p = p_tmp + 1; + } #ifdef DUK_USE_NONSTD_JSON_ESC_U2028_U2029 - if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) { + if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) { #else - if (js_ctx->flag_ascii_only) { + if (js_ctx->flag_ascii_only) { #endif - DUK__EMIT_ESC_AUTO(js_ctx, cp); - } else { - /* as is */ - DUK__EMIT_XUTF8(js_ctx, cp); + q = duk__emit_esc_auto_fast(js_ctx, cp, q); + } else { + /* as is */ + DUK_RAW_WRITE_XUTF8(q, cp); + } } } + + DUK_BW_SET_PTR(thr, &js_ctx->bw, q); } DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE); } +/* Encode a double (checked by caller) from stack top. Stack top may be + * replaced by serialized string but is not popped (caller does that). + */ +DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) { + duk_context *ctx; + duk_tval *tv; + duk_double_t d; + duk_small_int_t c; + duk_small_int_t s; + duk_small_uint_t stridx; + duk_small_uint_t n2s_flags; + duk_hstring *h_str; + + DUK_ASSERT(js_ctx != NULL); + ctx = (duk_context *) js_ctx->thr; + DUK_ASSERT(ctx != NULL); + + /* Caller must ensure 'tv' is indeed a double and not a fastint! */ + tv = duk_get_tval(ctx, -1); + DUK_ASSERT(tv != NULL); + DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv)); + d = DUK_TVAL_GET_DOUBLE(tv); + + c = (duk_small_int_t) DUK_FPCLASSIFY(d); + s = (duk_small_int_t) DUK_SIGNBIT(d); + DUK_UNREF(s); + + if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) { + DUK_ASSERT(DUK_ISFINITE(d)); + +#if defined(DUK_USE_JX) || defined(DUK_USE_JC) + /* Negative zero needs special handling in JX/JC because + * it would otherwise serialize to '0', not '-0'. + */ + if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 && + (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible))) { + duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO); /* '-0' */ + } else +#endif /* DUK_USE_JX || DUK_USE_JC */ + { + n2s_flags = 0; + /* [ ... number ] -> [ ... string ] */ + duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags); + } + h_str = duk_to_hstring(ctx, -1); + DUK_ASSERT(h_str != NULL); + DUK__EMIT_HSTR(js_ctx, h_str); + return; + } + +#if defined(DUK_USE_JX) || defined(DUK_USE_JC) + if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | + DUK_JSON_FLAG_EXT_COMPATIBLE))) { + stridx = DUK_STRIDX_LC_NULL; + } else if (c == DUK_FP_NAN) { + stridx = js_ctx->stridx_custom_nan; + } else if (s == 0) { + stridx = js_ctx->stridx_custom_posinf; + } else { + stridx = js_ctx->stridx_custom_neginf; + } +#else + stridx = DUK_STRIDX_LC_NULL; +#endif + DUK__EMIT_STRIDX(js_ctx, stridx); +} + +#if defined(DUK_USE_FASTINT) +/* Encode a fastint from duk_tval ptr, no value stack effects. */ +DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) { + duk_int64_t v; + + /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328 + * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808 + * (20 chars long). Alloc space for 64-bit range to be safe. + */ + duk_uint8_t buf[20 + 1]; + + /* Caller must ensure 'tv' is indeed a fastint! */ + DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv)); + v = DUK_TVAL_GET_FASTINT(tv); + + /* XXX: There are no format strings in duk_config.h yet, could add + * one for formatting duk_int64_t. For now, assumes "%lld" and that + * "long long" type exists. Could also rely on C99 directly but that + * won't work for older MSVC. + */ + DUK_SPRINTF((char *) buf, "%lld", (long long) v); + DUK__EMIT_CSTR(js_ctx, (const char *) buf); +} +#endif + /* Shared entry handling for object/array serialization: indent/stepback, * loop detection. */ @@ -25984,8 +31758,12 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_hstring **h_s h_target = duk_get_hobject(ctx, -1); /* object or array */ DUK_ASSERT(h_target != NULL); - duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target); + /* 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); @@ -26061,8 +31839,9 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_hstring **h_st h_target = duk_get_hobject(ctx, *entry_top - 1); /* original target at entry_top - 1 */ DUK_ASSERT(h_target != NULL); - duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target); + /* XXX: this check is very expensive */ + duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target); duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */ /* restore stack top after unbalanced code paths */ @@ -26257,6 +32036,7 @@ DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) { */ DUK_LOCAL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) { duk_context *ctx = (duk_context *) js_ctx->thr; + duk_hthread *thr = (duk_hthread *) ctx; duk_hobject *h; duk_tval *tv; duk_small_int_t c; @@ -26265,6 +32045,8 @@ DUK_LOCAL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hol (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder), (duk_tval *) duk_get_tval(ctx, -1))); + DUK_UNREF(thr); + duk_dup_top(ctx); /* -> [ ... key key ] */ duk_get_prop(ctx, idx_holder); /* -> [ ... key val ] */ @@ -26311,25 +32093,52 @@ DUK_LOCAL duk_bool_t duk__enc_value1(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hol h = DUK_TVAL_GET_OBJECT(tv); DUK_ASSERT(h != NULL); - c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h); - switch ((int) c) { - case DUK_HOBJECT_CLASS_NUMBER: - DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()")); - duk_to_number(ctx, -1); - break; - case DUK_HOBJECT_CLASS_STRING: - DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()")); - duk_to_string(ctx, -1); - break; + if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { + duk_hbufferobject *h_bufobj; + h_bufobj = (duk_hbufferobject *) h; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) { + duk_push_null(ctx); + } else if (DUK_HBUFFEROBJECT_FULL_SLICE(h_bufobj)) { + duk_push_hbuffer(ctx, h_bufobj->buf); + } else { + /* This is not very good because we're making a copy + * for serialization, but only for proper views. + * Better support would be to serialize slices + * directly but since we only push a raw buffer + * here we can't convey the slice offset/length. + */ + duk_uint8_t *p_buf; + + p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, h_bufobj->length); + DUK_MEMCPY((void *) p_buf, + (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj)), + h_bufobj->length); + } + duk_remove(ctx, -2); + } else { + c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h); + switch ((int) c) { + case DUK_HOBJECT_CLASS_NUMBER: { + DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()")); + duk_to_number(ctx, -1); + break; + } + case DUK_HOBJECT_CLASS_STRING: { + DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()")); + duk_to_string(ctx, -1); + break; + } #if defined(DUK_USE_JX) || defined(DUK_USE_JC) - case DUK_HOBJECT_CLASS_BUFFER: - case DUK_HOBJECT_CLASS_POINTER: + case DUK_HOBJECT_CLASS_POINTER: #endif - case DUK_HOBJECT_CLASS_BOOLEAN: - DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value")); - duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); - duk_remove(ctx, -2); - break; + case DUK_HOBJECT_CLASS_BOOLEAN: { + DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value")); + duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE); + duk_remove(ctx, -2); + break; + } + } /* end switch */ } } @@ -26487,18 +32296,28 @@ DUK_LOCAL void duk__enc_value2(duk_json_enc_ctx *js_ctx) { 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); - DUK__EMIT_1(js_ctx, DUK_ASC_PIPE); + + 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++; - duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, duk_lc_digits[(x >> 4) & 0x0f]); - duk_hbuffer_append_byte(js_ctx->thr, js_ctx->h_buf, duk_lc_digits[x & 0x0f]); + *q++ = duk_lc_digits[(x >> 4) & 0x0f]; + *q++ = duk_lc_digits[x & 0x0f]; } - DUK__EMIT_1(js_ctx, DUK_ASC_PIPE); + *q++ = DUK_ASC_PIPE; + + DUK_BW_SET_PTR(thr, &js_ctx->bw, q); } #endif #if defined(DUK_USE_JX) && defined(DUK_USE_JC) @@ -26529,60 +32348,18 @@ DUK_LOCAL void duk__enc_value2(duk_json_enc_ctx *js_ctx) { } #if defined(DUK_USE_FASTINT) case DUK_TAG_FASTINT: + /* Number serialization has a significant impact relative to + * other fast path code, so careful fast path for fastints. + */ + duk__enc_fastint_tval(js_ctx, tv); + break; #endif default: { /* number */ - duk_double_t d; - duk_small_int_t c; - duk_small_int_t s; - duk_small_uint_t stridx; - duk_small_uint_t n2s_flags; - duk_hstring *h_str; - - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); - d = DUK_TVAL_GET_NUMBER(tv); - c = (duk_small_int_t) DUK_FPCLASSIFY(d); - s = (duk_small_int_t) DUK_SIGNBIT(d); - DUK_UNREF(s); - - if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) { - DUK_ASSERT(DUK_ISFINITE(d)); - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - /* Negative zero needs special handling in JX/JC because - * it would otherwise serialize to '0', not '-0'. - */ - if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 && - (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible))) { - duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO); /* '-0' */ - } else -#endif /* DUK_USE_JX || DUK_USE_JC */ - { - n2s_flags = 0; - /* [ ... number ] -> [ ... string ] */ - duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags); - } - h_str = duk_to_hstring(ctx, -1); - DUK_ASSERT(h_str != NULL); - DUK__EMIT_HSTR(js_ctx, h_str); - break; - } - -#if defined(DUK_USE_JX) || defined(DUK_USE_JC) - if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | - DUK_JSON_FLAG_EXT_COMPATIBLE))) { - stridx = DUK_STRIDX_LC_NULL; - } else if (c == DUK_FP_NAN) { - stridx = js_ctx->stridx_custom_nan; - } else if (s == 0) { - stridx = js_ctx->stridx_custom_posinf; - } else { - stridx = js_ctx->stridx_custom_neginf; - } -#else - stridx = DUK_STRIDX_LC_NULL; -#endif - DUK__EMIT_STRIDX(js_ctx, stridx); + /* XXX: A fast path for usual integers would be useful when + * fastint support is not enabled. + */ + duk__enc_double(js_ctx); break; } } @@ -26612,6 +32389,365 @@ DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) { return 0; } +/* + * JSON.stringify() fast path + */ + +#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) +DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) { + duk_uint_fast32_t i, n; + + DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv)); + + DUK_ASSERT(js_ctx != NULL); + DUK_ASSERT(js_ctx->thr != NULL); +#if defined(DUK_USE_JX) + DUK_ASSERT(js_ctx->flag_ext_custom == 0); +#endif +#if defined(DUK_USE_JC) + DUK_ASSERT(js_ctx->flag_ext_compatible == 0); +#endif + + restart_match: + DUK_ASSERT(tv != NULL); + + switch (DUK_TVAL_GET_TAG(tv)) { + case DUK_TAG_UNDEFINED: { + goto emit_undefined; + } + case DUK_TAG_NULL: { + DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); + break; + } + case DUK_TAG_BOOLEAN: { + DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ? + DUK_STRIDX_TRUE : DUK_STRIDX_FALSE); + break; + } + case DUK_TAG_STRING: { + duk_hstring *h; + + h = DUK_TVAL_GET_STRING(tv); + DUK_ASSERT(h != NULL); + duk__enc_quote_string(js_ctx, h); + break; + } + case DUK_TAG_OBJECT: { + duk_hobject *obj; + duk_tval *tv_val; + duk_bool_t emitted = 0; + duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef, c_object; + + /* For objects JSON.stringify() only looks for own, enumerable + * properties which is nice for the fast path here. + * + * For arrays JSON.stringify() uses [[Get]] so it will actually + * inherit properties during serialization! This fast path + * supports gappy arrays as long as there's no actual inherited + * property (which might be a getter etc). + * + * Since recursion only happens for objects, we can have both + * recursion and loop checks here. We use a simple, depth-limited + * loop check in the fast path because the object-based tracking + * is very slow (when tested, it accounted for 50% of fast path + * execution time for input data with a lot of small objects!). + */ + + obj = DUK_TVAL_GET_OBJECT(tv); + DUK_ASSERT(obj != NULL); + + /* We rely on a few object flag / class number relationships here, + * assert for them. + */ + DUK_ASSERT_HOBJECT_VALID(obj); + + /* Once recursion depth is increased, exit path must decrease + * it (though it's OK to abort the fast path). + */ + + DUK_ASSERT(js_ctx->recursion_depth >= 0); + DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); + if (js_ctx->recursion_depth >= js_ctx->recursion_limit) { + DUK_DD(DUK_DDPRINT("fast path recursion limit")); + DUK_ERROR(js_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_JSONDEC_RECLIMIT); + } + + for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) { + if (js_ctx->visiting[i] == obj) { + DUK_DD(DUK_DDPRINT("fast path loop detect")); + DUK_ERROR(js_ctx->thr, DUK_ERR_TYPE_ERROR, DUK_STR_CYCLIC_INPUT); + } + } + + /* Guaranteed by recursion_limit setup so we don't have to + * check twice. + */ + DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY); + js_ctx->visiting[js_ctx->recursion_depth] = obj; + js_ctx->recursion_depth++; + + /* If object has a .toJSON() property, we can't be certain + * that it wouldn't mutate any value arbitrarily, so bail + * out of the fast path. + */ + if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) { + DUK_DD(DUK_DDPRINT("object has a .toJSON property, abort fast path")); + goto abort_fastpath; + } + + /* We could use a switch-case for the class number but it turns out + * a small if-else ladder on class masks is better. The if-ladder + * should be in order of relevancy. + */ + + DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31); + c_all = DUK_HOBJECT_CMASK_ALL; + c_array = DUK_HOBJECT_CMASK_ARRAY; + c_unbox = DUK_HOBJECT_CMASK_NUMBER | + DUK_HOBJECT_CMASK_STRING | + DUK_HOBJECT_CMASK_BOOLEAN; + c_undef = DUK_HOBJECT_CMASK_FUNCTION | + DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS; + c_object = c_all & ~(c_array | c_unbox | c_undef); + + c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj); + if (c_bit & c_object) { + /* All other object types. */ + DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY); + + /* A non-Array object should not have an array part in practice. + * But since it is supported internally (and perhaps used at some + * point), check and abandon if that's the case. + */ + if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) { + DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path")); + goto abort_fastpath; + } + + for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) { + duk_hstring *k; + duk_size_t prev_size; + + k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i); + if (!k) { + continue; + } + if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) { + continue; + } + if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) { + /* Getter might have arbitrary side effects, + * so bail out. + */ + DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path")); + goto abort_fastpath; + } + if (DUK_HSTRING_HAS_INTERNAL(k)) { + continue; + } + + tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i); + + prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw); + duk__enc_quote_string(js_ctx, k); + DUK__EMIT_1(js_ctx, DUK_ASC_COLON); + if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) { + DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon")); + DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size); + } else { + DUK__EMIT_1(js_ctx, DUK_ASC_COMMA); + emitted = 1; + } + } + + /* If any non-Array value had enumerable virtual own + * properties, they should be serialized here. Standard + * types don't. + */ + + if (emitted) { + DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ + } + DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY); + } else if (c_bit & c_array) { + duk_uint_fast32_t arr_len; + duk_uint_fast32_t asize; + + DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET); + + /* Assume arrays are dense in the fast path. */ + if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) { + DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path")); + goto abort_fastpath; + } + + arr_len = (duk_uint_fast32_t) duk_hobject_get_length(js_ctx->thr, obj); + asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj); + if (arr_len > asize) { + /* Array length is larger than 'asize'. This shouldn't + * happen in practice. Bail out just in case. + */ + DUK_DD(DUK_DDPRINT("arr_len > asize, abort fast path")); + goto abort_fastpath; + } + /* Array part may be larger than 'length'; if so, iterate + * only up to array 'length'. + */ + for (i = 0; i < arr_len; i++) { + DUK_ASSERT(i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj)); + + tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i); + + if (DUK_UNLIKELY(DUK_TVAL_IS_UNDEFINED_UNUSED(tv_val))) { + /* Gap in array; check for inherited property, + * bail out if one exists. This should be enough + * to support gappy arrays for all practical code. + */ + duk_hstring *h_tmp; + duk_bool_t has_inherited; + + /* XXX: refactor into an internal helper, pretty awkward */ + duk_push_uint((duk_context *) js_ctx->thr, (duk_uint_t) i); + h_tmp = duk_to_hstring((duk_context *) js_ctx->thr, -1); + DUK_ASSERT(h_tmp != NULL); + has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp); + duk_pop((duk_context *) js_ctx->thr); + + if (has_inherited) { + DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path")); + goto abort_fastpath; + } + + /* Ordinary gap, undefined encodes to 'null' in + * standard JSON (and no JX/JC support here now). + */ + DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path")); + DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); + } else { + if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) { + DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL); + } + } + DUK__EMIT_1(js_ctx, DUK_ASC_COMMA); + emitted = 1; + } + + if (emitted) { + DUK__UNEMIT_1(js_ctx); /* eat trailing comma */ + } + DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET); + } else if (c_bit & c_unbox) { + /* These three boxed types are required to go through + * automatic unboxing. Rely on internal value being + * sane (to avoid infinite recursion). + */ + duk_tval *tv_internal; + + DUK_DD(DUK_DDPRINT("auto unboxing in fast path")); + + tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj); + DUK_ASSERT(tv_internal != NULL); + DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) || + DUK_TVAL_IS_NUMBER(tv_internal) || + DUK_TVAL_IS_BOOLEAN(tv_internal)); + + /* XXX: for JX/JC, special handling for Pointer, and Buffer? */ + tv = tv_internal; + goto restart_match; + } else { + DUK_ASSERT((c_bit & c_undef) != 0); + + /* Function objects are treated as "undefined" by JSON. + * + * The slow path replaces a buffer object automatically with + * the binary data which then gets treated like "undefined". + * Since we don't support buffers here now, treat as "undefined". + */ + + /* Must decrease recursion depth before returning. */ + DUK_ASSERT(js_ctx->recursion_depth > 0); + DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); + js_ctx->recursion_depth--; + goto emit_undefined; + } + + DUK_ASSERT(js_ctx->recursion_depth > 0); + DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit); + js_ctx->recursion_depth--; + break; + } + case DUK_TAG_BUFFER: { + goto emit_undefined; + } + case DUK_TAG_POINTER: { + goto emit_undefined; + } + case DUK_TAG_LIGHTFUNC: { + /* A lightfunc might also inherit a .toJSON() so just bail out. */ + DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path")); + goto abort_fastpath; + } +#if defined(DUK_USE_FASTINT) + case DUK_TAG_FASTINT: { + /* Number serialization has a significant impact relative to + * other fast path code, so careful fast path for fastints. + */ + duk__enc_fastint_tval(js_ctx, tv); + break; + } +#endif + default: { + /* XXX: A fast path for usual integers would be useful when + * fastint support is not enabled. + */ + /* XXX: Stack discipline is annoying, could be changed in numconv. */ + duk_push_tval((duk_context *) js_ctx->thr, tv); + duk__enc_double(js_ctx); + duk_pop((duk_context *) js_ctx->thr); + +#if 0 + /* Could also rely on native sprintf(), but it will handle + * values like NaN, Infinity, -0, exponent notation etc in + * a JSON-incompatible way. + */ + duk_double_t d; + char buf[64]; + + DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv)); + d = DUK_TVAL_GET_DOUBLE(tv); + DUK_SPRINTF(buf, "%lg", d); + DUK__EMIT_CSTR(js_ctx, buf); +#endif + } + } + return 1; /* not undefined */ + + emit_undefined: + return 0; /* value was undefined/unsupported */ + + abort_fastpath: + /* Error message doesn't matter: the error is ignored anyway. */ + DUK_DD(DUK_DDPRINT("aborting fast path")); + DUK_ERROR(js_ctx->thr, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR); + return 0; /* unreachable */ +} + +DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx) { + duk_json_enc_ctx *js_ctx; + + DUK_ASSERT(ctx != NULL); + js_ctx = (duk_json_enc_ctx *) duk_get_pointer(ctx, -2); + DUK_ASSERT(js_ctx != NULL); + + if (duk__json_stringify_fast_value(js_ctx, duk_get_tval((duk_context *) (js_ctx->thr), -1)) == 0) { + DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path")); + return DUK_RET_ERROR; /* error message doesn't matter, ignored anyway */ + } + + return 0; +} +#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */ + /* * Top level wrappers */ @@ -26645,6 +32781,7 @@ void duk_bi_json_parse_helper(duk_context *ctx, /* nothing now */ #endif js_ctx->recursion_limit = DUK_JSON_DEC_RECURSION_LIMIT; + DUK_ASSERT(js_ctx->recursion_depth == 0); /* Flag handling currently assumes that flags are consistent. This is OK * because the call sites are now strictly controlled. @@ -26661,10 +32798,15 @@ void duk_bi_json_parse_helper(duk_context *ctx, h_text = duk_to_hstring(ctx, idx_value); /* coerce in-place */ DUK_ASSERT(h_text != NULL); + /* JSON parsing code is allowed to read [p_start,p_end]: p_end is + * valid and points to the string NUL terminator (which is always + * guaranteed for duk_hstrings. + */ js_ctx->p_start = (duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text); js_ctx->p = js_ctx->p_start; js_ctx->p_end = ((duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) + DUK_HSTRING_GET_BYTELEN(h_text); + DUK_ASSERT(*(js_ctx->p_end) == 0x00); duk__dec_value(js_ctx); /* -> [ ... value ] */ @@ -26750,7 +32892,6 @@ void duk_bi_json_stringify_helper(duk_context *ctx, js_ctx->h_indent = NULL; #endif js_ctx->idx_proplist = -1; - js_ctx->recursion_limit = DUK_JSON_ENC_RECURSION_LIMIT; /* Flag handling currently assumes that flags are consistent. This is OK * because the call sites are now strictly controlled. @@ -26810,10 +32951,7 @@ void duk_bi_json_stringify_helper(duk_context *ctx, DUK_TYPE_MASK_LIGHTFUNC; } - (void) duk_push_dynamic_buffer(ctx, 0); - js_ctx->h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(js_ctx->h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(js_ctx->h_buf)); + DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE); js_ctx->idx_loop = duk_push_object_internal(ctx); DUK_ASSERT(js_ctx->idx_loop >= 0); @@ -26924,6 +33062,76 @@ void duk_bi_json_stringify_helper(duk_context *ctx, /* [ ... buf loop (proplist) (gap) ] */ + /* + * Fast path: assume no mutation, iterate object property tables + * directly; bail out if that assumption doesn't hold. + */ + +#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) + /* For now fast path is limited to plain JSON (no JX/JC). This would + * be easy to fix but must go through value type handling in the fast + * path. + */ + if (flags == 0 && + js_ctx->h_replacer == NULL && + js_ctx->idx_proplist == -1 && + js_ctx->h_gap == NULL && + js_ctx->h_indent == NULL) { + duk_int_t pcall_rc; +#ifdef DUK_USE_MARK_AND_SWEEP + duk_small_uint_t prev_mark_and_sweep_base_flags; +#endif + + DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path")); + + /* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[] + * array so we don't need two counter checks in the fast path. The + * slow path has a much larger recursion limit which we'll use if + * necessary. + */ + DUK_ASSERT(DUK_JSON_ENC_RECURSION_LIMIT >= DUK_JSON_ENC_LOOPARRAY); + js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY; + DUK_ASSERT(js_ctx->recursion_depth == 0); + + /* Execute the fast path in a protected call. If any error is thrown, + * fall back to the slow path. This includes e.g. recursion limit + * because the fast path has a smaller recursion limit (and simpler, + * limited loop detection). + */ + + duk_push_pointer(ctx, (void *) js_ctx); + duk_dup(ctx, idx_value); + +#if defined(DUK_USE_MARK_AND_SWEEP) + /* Must prevent finalizers which may have arbitrary side effects. */ + prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags; + thr->heap->mark_and_sweep_base_flags |= + DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */ + DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact any objects */ +#endif + + pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, 2 /*nargs*/, 0 /*nret*/); + +#if defined(DUK_USE_MARK_AND_SWEEP) + thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags; +#endif + if (pcall_rc == DUK_EXEC_SUCCESS) { + DUK_DD(DUK_DDPRINT("fast path successful")); + DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw); + goto replace_finished; + } + + /* We come here for actual aborts (like encountering .toJSON()) + * but also for recursion/loop errors. Bufwriter size can be + * kept because we'll probably need at least as much as we've + * allocated so far. + */ + DUK_DD(DUK_DDPRINT("fast path failed, serialize using slow path instead")); + DUK_BW_RESET_SIZE(thr, &js_ctx->bw); + js_ctx->recursion_depth = 0; + } +#endif + /* * Create wrapper object and serialize */ @@ -26932,10 +33140,9 @@ void duk_bi_json_stringify_helper(duk_context *ctx, duk_dup(ctx, idx_value); duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING); - DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, buf=%!O, loop=%!T, replacer=%!O, " + DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, " "proplist=%!T, gap=%!O, indent=%!O, holder=%!T", (unsigned long) js_ctx->flags, - (duk_heaphdr *) js_ctx->h_buf, (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), @@ -26949,12 +33156,13 @@ void duk_bi_json_stringify_helper(duk_context *ctx, /* [ ... buf loop (proplist) (gap) holder "" ] */ + js_ctx->recursion_limit = DUK_JSON_ENC_RECURSION_LIMIT; + DUK_ASSERT(js_ctx->recursion_depth == 0); undef = duk__enc_value1(js_ctx, idx_holder); /* [ ... holder key ] -> [ ... holder key val ] */ - DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, buf=%!O, loop=%!T, replacer=%!O, " + DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, " "proplist=%!T, gap=%!O, indent=%!O, holder=%!T", (unsigned long) js_ctx->flags, - (duk_heaphdr *) js_ctx->h_buf, (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), @@ -26974,15 +33182,17 @@ void duk_bi_json_stringify_helper(duk_context *ctx, */ duk__enc_value2(js_ctx); /* [ ... key val ] -> [ ... ] */ - DUK_ASSERT(js_ctx->h_buf != NULL); - duk_push_hbuffer(ctx, (duk_hbuffer *) js_ctx->h_buf); - duk_to_string(ctx, -1); + + DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw); } /* The stack has a variable shape here, so force it to the * desired one explicitly. */ +#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH) + replace_finished: +#endif duk_replace(ctx, entry_top); duk_set_top(ctx, entry_top + 1); @@ -27018,6 +33228,12 @@ DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) { 0 /*flags*/); return 1; } + +#undef DUK__JSON_DECSTR_BUFSIZE +#undef DUK__JSON_DECSTR_CHUNKSIZE +#undef DUK__JSON_ENCSTR_CHUNKSIZE +#undef DUK__JSON_STRINGIFY_BUFSIZE +#undef DUK__JSON_MAX_ESC_LEN #line 1 "duk_bi_logger.c" /* * Logging support @@ -27158,6 +33374,7 @@ DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) { duk_small_int_t rc; DUK_ASSERT(entry_lev >= 0 && entry_lev <= 5); + DUK_UNREF(thr); /* XXX: sanitize to printable (and maybe ASCII) */ /* XXX: better multiline */ @@ -27195,7 +33412,7 @@ DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) { } /* log level could be popped but that's not necessary */ - now = duk_bi_date_get_now(ctx); + now = DUK_USE_DATE_GET_NOW(ctx); duk_bi_date_format_timeval(now, date_buf); date_len = DUK_STRLEN((const char *) date_buf); @@ -27251,33 +33468,15 @@ DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) { * Pass 2 */ - if (tot_len <= DUK_BI_LOGGER_SHORT_MSG_LIMIT) { - duk_hbuffer_dynamic *h_buf; - - DUK_DDD(DUK_DDDPRINT("reuse existing small log message buffer, tot_len %ld", (long) tot_len)); - - /* We can assert for all buffer properties because user code - * never has access to heap->log_buffer. - */ - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(thr->heap != NULL); - h_buf = thr->heap->log_buffer; - DUK_ASSERT(h_buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_buf)); - DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(h_buf) == DUK_BI_LOGGER_SHORT_MSG_LIMIT); - - /* Set buffer 'visible size' to actual message length and - * push it to the stack. - */ + /* XXX: There used to be a shared log buffer here, but it was removed + * when dynamic buffer spare was removed. The problem with using + * bufwriter is that, without the spare, the buffer gets passed on + * as an argument to the raw() call so it'd need to be resized + * (reallocated) anyway. If raw() call convention is changed, this + * could be made more efficient. + */ - DUK_HBUFFER_SET_SIZE((duk_hbuffer *) h_buf, tot_len); - duk_push_hbuffer(ctx, (duk_hbuffer *) h_buf); - buf = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf); - } else { - DUK_DDD(DUK_DDDPRINT("use a one-off large log message buffer, tot_len %ld", (long) tot_len)); - buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len); - } + buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len); DUK_ASSERT(buf != NULL); p = buf; @@ -27969,7 +34168,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_context *ctx) { /* Shared helper to implement Object.getPrototypeOf and the ES6 * Object.prototype.__proto__ getter. * - * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__ + * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__ */ DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; @@ -28009,8 +34208,8 @@ DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) { /* Shared helper to implement ES6 Object.setPrototypeOf and * Object.prototype.__proto__ setter. * - * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__ - * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.setprototypeof + * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__ + * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof */ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; @@ -28053,7 +34252,6 @@ DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) { DUK_ASSERT(h_obj != NULL); /* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */ - /* NOTE: steps 7-8 seem to be a cut-paste bug in the E6 draft */ /* TODO: implement Proxy object support here */ if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) { @@ -28599,7 +34797,7 @@ DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx } #line 1 "duk_bi_proxy.c" /* - * Proxy built-in (ES6 draft) + * Proxy built-in (ES6) */ /* include removed: duk_internal.h */ @@ -28631,7 +34829,7 @@ DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) { return DUK_RET_TYPE_ERROR; } - /* XXX: the returned value is exotic in ES6 (draft), but we use a + /* XXX: the returned value is exotic in ES6, but we use a * simple object here with no prototype. Without a prototype, * [[DefaultValue]] coercion fails which is abit confusing. * No callable check/handling in the current Proxy subset. @@ -28643,13 +34841,18 @@ DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) { NULL); DUK_ASSERT_TOP(ctx, 3); + /* Make _Target and _Handler non-configurable and non-writable. + * They can still be forcibly changed by C code (both user and + * Duktape internal), but not by Ecmascript code. + */ + /* Proxy target */ duk_dup(ctx, 0); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_WC); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE); /* Proxy handler */ duk_dup(ctx, 1); - duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_WC); + duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_NONE); return 1; /* replacement handler */ } @@ -28920,7 +35123,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_context *ctx) { DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx) { duk_hthread *thr = (duk_hthread *) ctx; - duk_hbuffer_dynamic *h; + duk_bufwriter_ctx bw_alloc; + duk_bufwriter_ctx *bw; duk_idx_t i, n; duk_ucodepoint_t cp; @@ -28931,24 +35135,31 @@ DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx */ n = duk_get_top(ctx); - duk_push_dynamic_buffer(ctx, 0); /* XXX: initial spare size estimate from 'n' */ - h = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); + + bw = &bw_alloc; + DUK_BW_INIT_PUSHBUF(thr, bw, n); /* initial estimate for ASCII only codepoints */ for (i = 0; i < n; i++) { + /* XXX: could improve bufwriter handling to write multiple codepoints + * with one ensure call but the relative benefit would be quite small. + */ + #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT) /* ToUint16() coercion is mandatory in the E5.1 specification, but * this non-compliant behavior makes more sense because we support * non-BMP codepoints. Don't use CESU-8 because that'd create * surrogate pairs. */ + cp = (duk_ucodepoint_t) duk_to_uint32(ctx, i); - duk_hbuffer_append_xutf8(thr, h, cp); + DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp); #else - cp = (duk_ucodepoint_t) duk_to_uint16(ctx, i); - duk_hbuffer_append_cesu8(thr, h, cp); + cp = (duk_ucodepoint_t) duk_to_uint32(ctx, i); + DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp); #endif } + DUK_BW_COMPACT(thr, bw); duk_to_string(ctx, -1); return 1; } @@ -29294,7 +35505,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { duk_hstring *h_match; duk_hstring *h_search; duk_hobject *h_re; - duk_hbuffer_dynamic *h_buf; + duk_bufwriter_ctx bw_alloc; + duk_bufwriter_ctx *bw; #ifdef DUK_USE_REGEXP_SUPPORT duk_bool_t is_regexp; duk_bool_t is_global; @@ -29306,13 +35518,15 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { #endif duk_uint32_t prev_match_end_boff; const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */ + duk_size_t tmp_sz; DUK_ASSERT_TOP(ctx, 2); h_input = duk_push_this_coercible_to_string(ctx); DUK_ASSERT(h_input != NULL); - duk_push_dynamic_buffer(ctx, 0); - h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(h_buf != NULL); + + bw = &bw_alloc; + DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */ + DUK_ASSERT_TOP(ctx, 4); /* stack[0] = search value @@ -29481,10 +35695,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff); - duk_hbuffer_append_bytes(thr, - h_buf, - DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, - (duk_size_t) (match_start_boff - prev_match_end_boff)); + tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff); + DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz); prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match); @@ -29520,7 +35732,9 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { duk_call(ctx, duk_get_top(ctx) - idx_args); h_repl = duk_to_hstring(ctx, -1); /* -> [ ... repl_value ] */ DUK_ASSERT(h_repl != NULL); - duk_hbuffer_append_hstring(thr, h_buf, h_repl); + + DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl); + duk_pop(ctx); /* repl_value */ } else { r = r_start; @@ -29550,15 +35764,13 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { goto repl_write; } case DUK_ASC_AMP: { - duk_hbuffer_append_hstring(thr, h_buf, h_match); + DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match); r++; continue; } case DUK_ASC_GRAVE: { - duk_hbuffer_append_bytes(thr, - h_buf, - DUK_HSTRING_GET_DATA(h_input), - match_start_boff); + tmp_sz = (duk_size_t) match_start_boff; + DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz); r++; continue; } @@ -29572,10 +35784,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { h_input, match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match)); - duk_hbuffer_append_bytes(thr, - h_buf, - DUK_HSTRING_GET_DATA(h_input) + match_end_boff, - DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff); + tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff); + DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz); r++; continue; } @@ -29613,8 +35823,12 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { /* regexp res_obj is at offset 4 */ duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum); if (duk_is_string(ctx, -1)) { - DUK_ASSERT(duk_get_hstring(ctx, -1) != NULL); - duk_hbuffer_append_hstring(thr, h_buf, duk_get_hstring(ctx, -1)); + duk_hstring *h_tmp_str; + + h_tmp_str = duk_get_hstring(ctx, -1); + DUK_ASSERT(h_tmp_str != NULL); + + DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str); } else { /* undefined -> skip (replaced with empty) */ } @@ -29632,7 +35846,8 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { repl_write: /* ch1 = (r_increment << 8) + byte */ - duk_hbuffer_append_byte(thr, h_buf, (duk_uint8_t) (ch1 & 0xff)); + + DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff)); r += ch1 >> 8; } /* while repl */ } /* if (is_repl_func) */ @@ -29649,12 +35864,11 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) { } /* trailer */ - duk_hbuffer_append_bytes(thr, - h_buf, - DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, - (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff)); + tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff); + DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz); DUK_ASSERT_TOP(ctx, 4); + DUK_BW_COMPACT(thr, bw); duk_to_string(ctx, -1); return 1; } @@ -31328,7 +37542,7 @@ DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) { } else { ; } - if (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(h)) { + if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { DUK__COMMA(); duk_fb_sprintf(fb, "__special_bufferobj:true"); } else { ; @@ -31356,6 +37570,14 @@ DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) { DUK__COMMA(); duk_fb_sprintf(fb, "__func:"); duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func)); DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs); + } else if (st->internal && DUK_HOBJECT_IS_BUFFEROBJECT(h)) { + duk_hbufferobject *b = (duk_hbufferobject *) h; + DUK__COMMA(); duk_fb_sprintf(fb, "__buf:"); + duk__print_hbuffer(st, (duk_hbuffer *) b->buf); + DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset); + DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length); + DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift); + DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type); } else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) { duk_hthread *t = (duk_hthread *) h; DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict); @@ -31440,10 +37662,9 @@ DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) { if (DUK_HBUFFER_HAS_DYNAMIC(h)) { duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h; - duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld:%ld", + duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g), - (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g), - (long) DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(g)); + (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g)); } else { duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h)); } @@ -32194,7 +38415,7 @@ DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) { DUK_ASSERT(sizeof(du.uc) == 8); duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc)); - DUK_DBLUNION_BSWAP(&du); + DUK_DBLUNION_DOUBLE_NTOH(&du); return du.d; } @@ -32570,7 +38791,7 @@ DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) { /* Numbers are normalized to big (network) endian. */ DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); du.d = DUK_TVAL_GET_NUMBER(tv); - DUK_DBLUNION_BSWAP(&du); + DUK_DBLUNION_DOUBLE_HTON(&du); duk_debug_write_byte(thr, 0x1a); duk_debug_write_bytes(thr, (const duk_uint8_t *) du.uc, sizeof(du.uc)); @@ -33201,11 +39422,6 @@ DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_hea duk_hbuffer *h = (duk_hbuffer *) hdr; duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h)); - if (DUK_HBUFFER_HAS_DYNAMIC(h)) { - duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE((duk_hbuffer_dynamic *) h)); - } else { - duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h)); - } duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h)); break; } @@ -33765,7 +39981,7 @@ DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_c /* [ ... errval ] */ } -#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRHANDLE */ +#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */ /* * Add tracedata to an error on the stack top. @@ -34300,6 +40516,7 @@ DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t r /* XXX: this generates quite large code - perhaps select the error * class based on the code and then just use the error 'name'? */ + /* XXX: shared strings */ code = -rc; @@ -34397,7 +40614,6 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk } DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr); - DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(h, size); /* snug */ } else { #if defined(DUK_USE_EXPLICIT_NULL_INIT) #if defined(DUK_USE_HEAPPTR16) @@ -34407,7 +40623,6 @@ DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk #endif #endif DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL); - DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(h) == 0); } } @@ -34454,34 +40669,19 @@ DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) { * Resizing */ -DUK_LOCAL duk_size_t duk__add_spare(duk_size_t size) { - duk_size_t spare = (size / DUK_HBUFFER_SPARE_DIVISOR) + DUK_HBUFFER_SPARE_ADD; - duk_size_t res; - - res = size + spare; - if (res < size) { - /* XXX: handle corner cases where size is close to size limit (wraparound) */ - DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "duk_size_t wrapped"); - } - DUK_ASSERT(res >= size); - - return res; -} - -DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size, duk_size_t new_alloc_size) { +DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) { void *res; - duk_size_t prev_alloc_size; + duk_size_t prev_size; DUK_ASSERT(thr != NULL); DUK_ASSERT(buf != NULL); - DUK_ASSERT(new_alloc_size >= new_size); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); /* * Maximum size check */ - if (new_alloc_size > DUK_HBUFFER_MAX_BYTELEN) { + if (new_size > DUK_HBUFFER_MAX_BYTELEN) { DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "buffer too long"); } @@ -34491,48 +40691,40 @@ DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, * collection. */ - res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_alloc_size); - if (res != NULL || new_alloc_size == 0) { + res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size); + if (res != NULL || new_size == 0) { /* 'res' may be NULL if new allocation size is 0. */ - DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld:%ld -> %p:%ld:%ld", + DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf), (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf), - (long) DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(buf), (void *) res, - (long) new_size, - (long) new_alloc_size)); + (long) new_size)); /* * The entire allocated buffer area, regardless of actual used * size, is kept zeroed in resizes for simplicity. If the buffer - * is grown, zero the new part. Another policy would be to - * ensure data is zeroed as the used part is extended. The - * current approach is much more simple and is not a big deal - * because the spare part is relatively small. + * is grown, zero the new part. */ - prev_alloc_size = DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(buf); - if (new_alloc_size > prev_alloc_size) { - DUK_ASSERT(new_alloc_size - prev_alloc_size > 0); + prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf); + if (new_size > prev_size) { + DUK_ASSERT(new_size - prev_size > 0); #ifdef DUK_USE_ZERO_BUFFER_DATA - DUK_MEMZERO((void *) ((char *) res + prev_alloc_size), - new_alloc_size - prev_alloc_size); + DUK_MEMZERO((void *) ((char *) res + prev_size), + (duk_size_t) (new_size - prev_size)); #endif } DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size); - DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(buf, new_alloc_size); DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res); } else { - DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "buffer resize failed: %ld:%ld to %ld:%ld", + DUK_ERROR(thr, DUK_ERR_ALLOC_ERROR, "buffer resize failed: %ld to %ld", (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf), - (long) DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(buf), - (long) new_size, - (long) new_alloc_size); + (long) new_size); } - DUK_ASSERT(res != NULL || new_alloc_size == 0); + DUK_ASSERT(res != NULL || new_size == 0); } DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) { @@ -34540,415 +40732,26 @@ DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) DUK_ASSERT(buf != NULL); DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - duk_hbuffer_resize(thr, buf, 0, 0); + duk_hbuffer_resize(thr, buf, 0); } +/* include removed: duk_internal.h */ +#line 2 "duk_hbufferobject_misc.c" -#if 0 /*unused*/ -DUK_INTERNAL void duk_hbuffer_compact(duk_hthread *thr, duk_hbuffer_dynamic *buf) { - duk_size_t curr_size; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - curr_size = DUK_HBUFFER_GET_SIZE(buf); - duk_hbuffer_resize(thr, buf, curr_size, curr_size); -} -#endif - -/* - * Inserts - */ - -DUK_INTERNAL void duk_hbuffer_insert_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, const duk_uint8_t *data, duk_size_t length) { - duk_uint8_t *p; - - /* XXX: allow inserts with offset > curr_size? i.e., insert zeroes automatically? */ - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT_DISABLE(offset >= 0); /* unsigned, so always true */ - DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf)); /* equality is OK (= append) */ - DUK_ASSERT(data != NULL); - DUK_ASSERT_DISABLE(length >= 0); /* unsigned, so always true */ - - if (length == 0) { - return; - } - - if (DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) < length) { - duk_hbuffer_resize(thr, - buf, - DUK_HBUFFER_GET_SIZE(buf), - duk__add_spare(DUK_HBUFFER_GET_SIZE(buf) + length)); - } - DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) >= length); - - p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf); - if (offset < DUK_HBUFFER_GET_SIZE(buf)) { - /* not an append */ - - DUK_ASSERT(DUK_HBUFFER_GET_SIZE(buf) - offset > 0); - DUK_MEMMOVE((void *) (p + offset + length), - (void *) (p + offset), - DUK_HBUFFER_GET_SIZE(buf) - offset); - } - - DUK_ASSERT(length > 0); - DUK_MEMCPY((void *) (p + offset), - data, - length); - - DUK_HBUFFER_DYNAMIC_ADD_SIZE(buf, length); -} - -#if 0 /*unused*/ -DUK_INTERNAL void duk_hbuffer_insert_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_uint8_t byte) { - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - duk_hbuffer_insert_bytes(thr, buf, offset, &byte, 1); -} -#endif - -#if 0 /*unused*/ -DUK_INTERNAL duk_size_t duk_hbuffer_insert_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, const char *str) { - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(str != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - len = DUK_STRLEN(str); - duk_hbuffer_insert_bytes(thr, buf, offset, (duk_uint8_t *) str, len); - return len; -} -#endif - -#if 0 /*unused*/ -DUK_INTERNAL duk_size_t duk_hbuffer_insert_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_hstring *str) { - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(str != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - len = DUK_HSTRING_GET_BYTELEN(str); - duk_hbuffer_insert_bytes(thr, buf, offset, (duk_uint8_t *) DUK_HSTRING_GET_DATA(str), len); - return len; -} -#endif - -DUK_INTERNAL duk_size_t duk_hbuffer_insert_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint) { - duk_uint8_t tmp[DUK_UNICODE_MAX_XUTF8_LENGTH]; - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - /* No range assertion for 'codepoint' */ - - /* Intentionally no fast path: insertion is not that central */ - - len = (duk_size_t) duk_unicode_encode_xutf8(codepoint, tmp); - duk_hbuffer_insert_bytes(thr, buf, offset, tmp, len); - return len; -} - -/* Append a Unicode codepoint to the buffer in CESU-8 format, i.e., convert - * non-BMP characters to surrogate pairs which are then "UTF-8" encoded. - * If the codepoint is initially a surrogate, it is also encoded into CESU-8. - * Codepoints above valid Unicode range (> U+10FFFF) are mangled. - */ - -#if 0 /*unused*/ -DUK_INTERNAL duk_size_t duk_hbuffer_insert_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_ucodepoint_t codepoint) { - duk_uint8_t tmp[DUK_UNICODE_MAX_CESU8_LENGTH]; - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT_DISABLE(codepoint >= 0); /* unsigned */ - DUK_ASSERT(codepoint <= 0x10ffff); /* if not in this range, results are garbage (but no crash) */ - - /* Intentionally no fast path: insertion is not that central */ - - len = (duk_size_t) duk_unicode_encode_cesu8(codepoint, tmp); - duk_hbuffer_insert_bytes(thr, buf, offset, tmp, len); - return len; -} -#endif - -/* - * Appends - * - * Note: an optimized duk_hbuffer_append_bytes() could be implemented, but - * it is more compact to use duk_hbuffer_insert_bytes() instead. The - * important fast paths bypass these functions. anyway. - */ - -DUK_INTERNAL void duk_hbuffer_append_bytes(duk_hthread *thr, duk_hbuffer_dynamic *buf, const duk_uint8_t *data, duk_size_t length) { - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT(data != NULL); - - duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), data, length); -} - -DUK_INTERNAL void duk_hbuffer_append_byte(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint8_t byte) { - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), &byte, 1); -} - -DUK_INTERNAL duk_size_t duk_hbuffer_append_cstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, const char *str) { - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(str != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - len = DUK_STRLEN(str); - duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), (duk_uint8_t *) str, len); - return len; -} - -DUK_INTERNAL duk_size_t duk_hbuffer_append_hstring(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_hstring *str) { - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(str != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - - len = DUK_HSTRING_GET_BYTELEN(str); - duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), (duk_uint8_t *) DUK_HSTRING_GET_DATA(str), len); - return len; -} - -/* Append a Unicode codepoint to the buffer in extended UTF-8 format, i.e. - * allow codepoints above standard Unicode range (> U+10FFFF) up to seven - * byte encoding (36 bits, but argument type is 32 bits). In particular, - * allows encoding of all unsigned 32-bit integers. If the codepoint is - * initially a surrogate, it is encoded without checking (and will become, - * effectively, CESU-8 encoded). - */ - -DUK_INTERNAL duk_size_t duk_hbuffer_append_xutf8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint) { - duk_uint8_t tmp[DUK_UNICODE_MAX_XUTF8_LENGTH]; - duk_size_t len; - duk_size_t sz; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - /* No range assertion for 'codepoint' */ - - if (DUK_LIKELY(codepoint < 0x80 && DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) > 0)) { - /* fast path: ASCII and there is spare */ - duk_uint8_t *p = ((duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf)); - sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf); - p[sz++] = (duk_uint8_t) codepoint; - DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, sz); - return 1; - } - - len = (duk_size_t) duk_unicode_encode_xutf8(codepoint, tmp); - duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), tmp, len); - return len; -} - -/* Append a Unicode codepoint to the buffer in CESU-8 format, i.e., convert - * non-BMP characters to surrogate pairs which are then "UTF-8" encoded. - * If the codepoint is initially a surrogate, it is also encoded into CESU-8. - * Codepoints above valid Unicode range (> U+10FFFF) are mangled. - */ - -DUK_INTERNAL duk_size_t duk_hbuffer_append_cesu8(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_ucodepoint_t codepoint) { - duk_uint8_t tmp[DUK_UNICODE_MAX_CESU8_LENGTH]; - duk_size_t len; - duk_size_t sz; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT_DISABLE(codepoint >= 0); /* unsigned */ - DUK_ASSERT(codepoint <= 0x10ffff); /* if not in this range, results are garbage (but no crash) */ - - if (DUK_LIKELY(codepoint < 0x80 && DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) > 0)) { - /* fast path: ASCII and there is spare */ - duk_uint8_t *p = ((duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf)); - sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf); - p[sz++] = (duk_uint8_t) codepoint; - DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, sz); - return 1; - } - - len = (duk_size_t) duk_unicode_encode_cesu8(codepoint, tmp); - duk_hbuffer_insert_bytes(thr, buf, DUK_HBUFFER_GET_SIZE(buf), tmp, len); - return len; -} - -/* Append an duk_uint32_t in native byte order. */ -#if 0 /*unused*/ -DUK_INTERNAL void duk_hbuffer_append_native_u32(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_uint32_t val) { - /* relies on duk_uint32_t being exactly right size */ - DUK_ASSERT(sizeof(val) == 4); - duk_hbuffer_insert_bytes(thr, - buf, - DUK_HBUFFER_GET_SIZE(buf), - (duk_uint8_t *) &val, - sizeof(duk_uint32_t)); -} -#endif - -/* - * In-buffer "slices" - * - * Slices are identified with an offset+length pair, referring to the current - * buffer data. A caller cannot otherwise reliably refer to existing data, - * because the buffer may be reallocated before a data pointer is referenced. - */ - -DUK_INTERNAL void duk_hbuffer_remove_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t offset, duk_size_t length) { - duk_uint8_t *p; - duk_size_t end_offset; - - DUK_UNREF(thr); - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT_DISABLE(offset >= 0); /* always true */ - DUK_ASSERT(offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - DUK_ASSERT_DISABLE(length >= 0); /* always true */ - DUK_ASSERT(offset + length <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - - if (length == 0) { - return; - } - - p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf); - - end_offset = offset + length; - - if (end_offset < DUK_HBUFFER_GET_SIZE(buf)) { - /* not strictly from end of buffer; need to shuffle data */ - DUK_ASSERT(DUK_HBUFFER_GET_SIZE(buf) - end_offset > 0); - DUK_MEMMOVE(p + offset, - p + end_offset, - DUK_HBUFFER_GET_SIZE(buf) - end_offset); - } - - /* Here we want to zero data even with automatic buffer zeroing - * disabled as we depend on this internally too. - */ - DUK_ASSERT(length > 0); - DUK_MEMZERO(p + DUK_HBUFFER_GET_SIZE(buf) - length, - length); - - DUK_HBUFFER_DYNAMIC_SUB_SIZE(buf, length); - - /* Note: no shrink check, intentional */ -} - -DUK_INTERNAL void duk_hbuffer_insert_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t dst_offset, duk_size_t src_offset, duk_size_t length) { - duk_uint8_t *p; - duk_size_t src_end_offset; /* source end (exclusive) in initial buffer */ - duk_size_t len; - - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT_DISABLE(dst_offset >= 0); /* always true */ - DUK_ASSERT(dst_offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - DUK_ASSERT_DISABLE(src_offset >= 0); /* always true */ - DUK_ASSERT(src_offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - DUK_ASSERT_DISABLE(length >= 0); /* always true */ - DUK_ASSERT(src_offset + length <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - - if (length == 0) { - return; - } - - if (DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) < length) { - duk_hbuffer_resize(thr, - buf, - DUK_HBUFFER_GET_SIZE(buf), - duk__add_spare(DUK_HBUFFER_GET_SIZE(buf) + length)); - } - DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_SPARE_SIZE(buf) >= length); +DUK_INTERNAL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len) { + duk_uint_t buf_size; + duk_uint_t buf_avail; - p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf); - DUK_ASSERT(p != NULL); /* must be the case because length > 0, and buffer has been resized if necessary */ + DUK_ASSERT(h_bufobj != NULL); + DUK_ASSERT(h_bufobj->buf != NULL); - /* - * src_offset and dst_offset refer to the state of the buffer - * before any changes are made. This must be taken into account - * when moving data around; in particular, the source data may - * "straddle" the dst_offset, so the insert may need to be handled - * in two pieces. - */ - - src_end_offset = src_offset + length; - - /* create a hole for the insert */ - len = DUK_HBUFFER_GET_SIZE(buf) - dst_offset; - DUK_MEMMOVE(p + dst_offset + length, - p + dst_offset, - len); /* zero size is not an issue: pointers are valid */ - - if (src_offset < dst_offset) { - if (src_end_offset <= dst_offset) { - /* entire source is before 'dst_offset' */ - DUK_MEMCPY(p + dst_offset, - p + src_offset, - length); - } else { - /* part of the source is before 'dst_offset'; straddles */ - len = dst_offset - src_offset; - DUK_ASSERT(len >= 1 && len < length); - DUK_ASSERT(length - len >= 1); - DUK_MEMCPY(p + dst_offset, - p + src_offset, - len); - DUK_MEMCPY(p + dst_offset + len, - p + src_offset + length + len, /* take above memmove() into account */ - length - len); - } - } else { - /* entire source is after 'dst_offset' */ - DUK_MEMCPY(p + dst_offset, - p + src_offset + length, /* take above memmove() into account */ - length); + buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf); + if (h_bufobj->offset > buf_size) { + /* Slice starting point is beyond current length. */ + return 0; } + buf_avail = buf_size - h_bufobj->offset; - DUK_HBUFFER_DYNAMIC_ADD_SIZE(buf, length); -} - -DUK_INTERNAL void duk_hbuffer_append_slice(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t src_offset, duk_size_t length) { - DUK_ASSERT(thr != NULL); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_ASSERT_DISABLE(src_offset >= 0); /* always true */ - DUK_ASSERT(src_offset <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - DUK_ASSERT_DISABLE(length >= 0); /* always true */ - DUK_ASSERT(src_offset + length <= DUK_HBUFFER_GET_SIZE(buf)); /* allow equality */ - - duk_hbuffer_insert_slice(thr, - buf, - DUK_HBUFFER_GET_SIZE(buf), - src_offset, - length); + return buf_avail >= len ? len : buf_avail; } #line 1 "duk_heap_alloc.c" /* @@ -35203,8 +41006,8 @@ DUK_INTERNAL void duk_heap_free(duk_heap *heap) { #endif duk__free_run_finalizers(heap); - /* Note: heap->heap_thread, heap->curr_thread, heap->heap_object, - * and heap->log_buffer are on the heap allocated list. + /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object + * are on the heap allocated list. */ DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap)); @@ -35582,6 +41385,9 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, duk_fatal_function fatal_func) { duk_heap *res = NULL; + /* Silence a few global unused warnings here. */ + DUK_UNREF(duk_str_unsupported); + DUK_D(DUK_DPRINT("allocate heap")); /* @@ -35663,7 +41469,6 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, res->heap_thread = NULL; res->curr_thread = NULL; res->heap_object = NULL; - res->log_buffer = NULL; #if defined(DUK_USE_STRTAB_CHAIN) /* nothing to NULL */ #elif defined(DUK_USE_STRTAB_PROBE) @@ -35722,12 +41527,6 @@ 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; -#ifdef DUK_USE_INTERRUPT_COUNTER - /* zero value causes an interrupt before executing first instruction */ - DUK_ASSERT(res->interrupt_counter == 0); - DUK_ASSERT(res->interrupt_init == 0); -#endif - #ifdef DUK_USE_EXPLICIT_NULL_INIT res->lj.jmpbuf_ptr = NULL; #endif @@ -35848,19 +41647,6 @@ duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, } DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object); - /* - * Init log buffer - */ - - DUK_DD(DUK_DDPRINT("HEAP: INIT LOG BUFFER")); - res->log_buffer = (duk_hbuffer_dynamic *) duk_hbuffer_alloc(res, - DUK_BI_LOGGER_SHORT_MSG_LIMIT, - DUK_BUF_FLAG_DYNAMIC /*flags*/); - if (!res->log_buffer) { - goto error; - } - DUK_HBUFFER_INCREF(res->heap_thread, res->log_buffer); - /* * All done */ @@ -36028,7 +41814,7 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) { if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) { duk_hcompiledfunction *f = (duk_hcompiledfunction *) h; duk_tval *tv, *tv_end; - duk_hobject **funcs, **funcs_end; + duk_hobject **fn, **fn_end; /* 'data' is reachable through every compiled function which * contains a reference. @@ -36043,16 +41829,19 @@ DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) { tv++; } - funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, f); - funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f); - while (funcs < funcs_end) { - duk__mark_heaphdr(heap, (duk_heaphdr *) *funcs); - funcs++; + fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, f); + fn_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f); + while (fn < fn_end) { + duk__mark_heaphdr(heap, (duk_heaphdr *) *fn); + fn++; } } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) { duk_hnativefunction *f = (duk_hnativefunction *) h; DUK_UNREF(f); /* nothing to mark */ + } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { + duk_hbufferobject *b = (duk_hbufferobject *) h; + duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf); } else if (DUK_HOBJECT_IS_THREAD(h)) { duk_hthread *t = (duk_hthread *) h; duk_tval *tv; @@ -36152,7 +41941,6 @@ DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) { duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread); duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object); - duk__mark_heaphdr(heap, (duk_heaphdr *) heap->log_buffer); for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) { duk_hstring *h = DUK_HEAP_GET_STRING(heap, i); @@ -37688,14 +43476,35 @@ DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphd #ifdef DUK_USE_INTERRUPT_COUNTER DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) { - /* Copy currently active interrupt counter from the active thread - * back to the heap structure. It doesn't need to be copied to - * the target thread, as the bytecode executor does that when it - * resumes execution for a new thread. - */ - if (heap->curr_thread != NULL) { - heap->interrupt_counter = heap->curr_thread->interrupt_counter; + duk_hthread *curr_thr; + + DUK_ASSERT(heap != NULL); + + if (new_thr != NULL) { + curr_thr = heap->curr_thread; + if (curr_thr == NULL) { + /* For initial entry use default value; zero forces an + * interrupt before executing the first insturction. + */ + DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter")); + new_thr->interrupt_counter = 0; + new_thr->interrupt_init = 0; + } else { + /* Copy interrupt counter/init value state to new thread (if any). + * It's OK for new_thr to be the same as curr_thr. + */ +#if defined(DUK_USE_DEBUG) + if (new_thr != curr_thr) { + DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter")); + } +#endif + new_thr->interrupt_counter = curr_thr->interrupt_counter; + new_thr->interrupt_init = curr_thr->interrupt_init; + } + } else { + DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes")); } + heap->curr_thread = new_thr; /* may be NULL */ } #endif /* DUK_USE_INTERRUPT_COUNTER */ @@ -37809,6 +43618,11 @@ DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) duk_hnativefunction *f = (duk_hnativefunction *) h; DUK_UNREF(f); /* nothing to finalize */ + } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) { + duk_hbufferobject *b = (duk_hbufferobject *) h; + if (b->buf) { + duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf); + } } else if (DUK_HOBJECT_IS_THREAD(h)) { duk_hthread *t = (duk_hthread *) h; duk_tval *tv; @@ -39726,6 +45540,25 @@ DUK_INTERNAL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_ return res; } +DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) { + duk_hbufferobject *res; + + res = (duk_hbufferobject *) DUK_ALLOC(heap, sizeof(duk_hbufferobject)); + if (!res) { + return NULL; + } + DUK_MEMZERO(res, sizeof(duk_hbufferobject)); + + duk__init_object_parts(heap, &res->obj, hobject_flags); + +#ifdef DUK_USE_EXPLICIT_NULL_INIT + res->buf = NULL; +#endif + + DUK_ASSERT_HBUFFEROBJECT_VALID(res); + return res; +} + /* * Allocate a new thread. * @@ -39814,6 +45647,13 @@ DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t /* must match exactly the number of internal properties inserted to enumerator */ #define DUK__ENUM_START_INDEX 2 +DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[] = { + DUK_STRIDX_LENGTH, + DUK_STRIDX_BYTE_LENGTH, + DUK_STRIDX_BYTE_OFFSET, + DUK_STRIDX_BYTES_PER_ELEMENT +}; + /* * Helper to sort array index keys. The keys are in the enumeration object * entry part, starting from DUK__ENUM_START_INDEX, and the entry part is dense. @@ -40038,7 +45878,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint * * For keys, we simply skip non-string keys which seems to be * consistent with how e.g. Object.keys() will process proxy trap - * results (ES6 draft, Section 19.1.2.14). + * results (ES6, Section 19.1.2.14). */ if (duk_get_prop_index(ctx, -1, i) && duk_is_string(ctx, -1)) { /* [ ... enum_target res trap_result val ] */ @@ -40078,7 +45918,7 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint */ if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || - DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr)) { + DUK_HOBJECT_IS_BUFFEROBJECT(curr)) { /* String and buffer enumeration behavior is identical now, * so use shared handler. */ @@ -40088,11 +45928,20 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */ len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val); } else { - duk_hbuffer *h_val; - DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr)); - h_val = duk_hobject_get_internal_value_buffer(thr->heap, curr); - DUK_ASSERT(h_val != NULL); /* buffer objects must not created without internal value */ - len = (duk_uint_fast32_t) DUK_HBUFFER_GET_SIZE(h_val); + duk_hbufferobject *h_bufobj; + DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT(curr)); + h_bufobj = (duk_hbufferobject *) curr; + if (h_bufobj == NULL) { + /* Neutered buffer, zero length seems + * like good behavior here. + */ + len = 0; + } else { + /* There's intentionally no check for + * current underlying buffer length. + */ + len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift); + } } for (i = 0; i < len; i++) { @@ -40109,14 +45958,28 @@ DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint /* [enum_target res] */ } - /* 'length' property is not enumerable, but is included if - * non-enumerable properties are requested. + /* 'length' and other virtual properties are not + * enumerable, but are included if non-enumerable + * properties are requested. */ if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) { - duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH); - duk_push_true(ctx); - duk_put_prop(ctx, -3); + duk_uint_fast32_t n; + + if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) { + n = sizeof(duk__bufferobject_virtual_props) / sizeof(duk_uint16_t); + } else { + DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)); + DUK_ASSERT(duk__bufferobject_virtual_props[0] == DUK_STRIDX_LENGTH); + n = 1; /* only 'length' */ + } + + for (i = 0; i < n; i++) { + duk_push_hstring_stridx(ctx, duk__bufferobject_virtual_props[i]); + duk_push_true(ctx); + duk_put_prop(ctx, -3); + } + } } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) { if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) { @@ -40573,7 +46436,7 @@ DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr curr_pc = 0U; while (curr_pc < length) { new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH); - duk_hbuffer_resize(thr, h_buf, new_size, new_size); + duk_hbuffer_resize(thr, h_buf, new_size); hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf); DUK_ASSERT(hdr != NULL); @@ -40640,7 +46503,7 @@ DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr /* compact */ new_size = (duk_size_t) curr_offset; - duk_hbuffer_resize(thr, h_buf, new_size, new_size); + duk_hbuffer_resize(thr, h_buf, new_size); (void) duk_to_fixed_buffer(ctx, -1, NULL); @@ -40681,7 +46544,7 @@ DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk goto error; } - hdr = (duk_uint32_t *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf); + hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf); pc_limit = hdr[0]; if (pc >= pc_limit) { /* Note: pc is unsigned and cannot be negative */ @@ -40864,6 +46727,7 @@ DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hob DUK_LOCAL_DECL duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags); DUK_LOCAL_DECL duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags); DUK_LOCAL_DECL duk_bool_t duk__get_own_property_desc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags); +DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc); /* * Misc helpers @@ -41134,7 +46998,37 @@ DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *o return 1; } -#endif +#endif /* DUK_USE_ES6_PROXY */ + +/* Get Proxy target object. If the argument is not a Proxy, return it as is. + * If a Proxy is revoked, an error is thrown. + */ +#if defined(DUK_USE_ES6_PROXY) +DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj) { + duk_hobject *h_target; + duk_hobject *h_handler; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(obj != NULL); + + /* Resolve Proxy targets until Proxy chain ends. No explicit check for + * a Proxy loop: user code cannot create such a loop without tweaking + * internal properties directly. + */ + + while (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) { + if (duk_hobject_proxy_check(thr, obj, &h_target, &h_handler)) { + DUK_ASSERT(h_target != NULL); + obj = h_target; + } else { + break; + } + } + + DUK_ASSERT(obj != NULL); + return obj; +} +#endif /* DUK_USE_ES6_PROXY */ #if defined(DUK_USE_ES6_PROXY) DUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target) { @@ -41349,7 +47243,7 @@ void duk__realloc_props(duk_hthread *thr, #ifdef DUK_USE_MARK_AND_SWEEP prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags; thr->heap->mark_and_sweep_base_flags |= - DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */ + DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */ DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact the current object */ #endif @@ -41633,15 +47527,7 @@ void duk__realloc_props(duk_hthread *thr, * so it would be nice to free it forcibly even with only * mark-and-sweep enabled. Not a big issue though. */ - duk_hbuffer_dynamic *buf; - DUK_ASSERT(new_alloc_size > 0); - DUK_ASSERT(duk_is_buffer(ctx, -1)); - buf = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, -1); - DUK_ASSERT(buf != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf)); - DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, buf); - DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, 0); /* these size resets are not strictly necessary, but nice for consistency */ - DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(buf, 0); + (void) duk_steal_buffer(ctx, -1, NULL); duk_pop(ctx); } else { DUK_ASSERT(new_alloc_size == 0); @@ -42115,22 +48001,6 @@ DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, return NULL; } -DUK_INTERNAL duk_hbuffer *duk_hobject_get_internal_value_buffer(duk_heap *heap, duk_hobject *obj) { - duk_tval tv; - - DUK_ASSERT(heap != NULL); - DUK_ASSERT(obj != NULL); - - if (duk_hobject_get_internal_value(heap, obj, &tv)) { - duk_hbuffer *h; - DUK_ASSERT(DUK_TVAL_IS_BUFFER(&tv)); - h = DUK_TVAL_GET_BUFFER(&tv); - return h; - } - - return NULL; -} - /* * Arguments handling helpers (argument map mainly). * @@ -42478,26 +48348,35 @@ DUK_LOCAL duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobjec DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)); return 1; /* cannot be arguments exotic */ } - } else if (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj)) { - DUK_DDD(DUK_DDDPRINT("buffer object exotic property get for key: %!O, arr_idx: %ld", + } else if (DUK_HOBJECT_IS_BUFFEROBJECT(obj)) { + duk_hbufferobject *h_bufobj; + duk_uint_t byte_off; + duk_small_uint_t elem_size; + + h_bufobj = (duk_hbufferobject *) obj; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); + DUK_DDD(DUK_DDDPRINT("bufferobject property get for key: %!O, arr_idx: %ld", (duk_heaphdr *) key, (long) arr_idx)); if (arr_idx != DUK__NO_ARRAY_INDEX) { - duk_hbuffer *h_val; - DUK_DDD(DUK_DDDPRINT("array index exists")); - h_val = duk_hobject_get_internal_value_buffer(thr->heap, obj); - DUK_ASSERT(h_val); - /* SCANBUILD: h_val is known to be non-NULL but scan-build cannot - * know it, so it produces NULL pointer dereference warnings for - * 'h_val'. + /* Careful with wrapping: arr_idx upshift may easily wrap, whereas + * length downshift won't. */ - - if (arr_idx < DUK_HBUFFER_GET_SIZE(h_val)) { - DUK_DDD(DUK_DDDPRINT("-> found, array index inside buffer")); + if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) { + byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */ + elem_size = 1 << h_bufobj->shift; if (flags & DUK__DESC_FLAG_PUSH_VALUE) { - duk_push_int(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val))[arr_idx]); + duk_uint8_t *data; + + if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) { + data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off; + duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size); + } else { + DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)")); + duk_push_uint(ctx, 0); + } } out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE | @@ -42510,24 +48389,42 @@ DUK_LOCAL duk_bool_t duk__get_own_property_desc_raw(duk_hthread *thr, duk_hobjec DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property")); } } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) { - duk_hbuffer *h_val; - DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior")); - /* XXX: buffer length should be writable and have exotic behavior - * like arrays. For now, make it read-only and use explicit methods - * to operate on buffer length. - */ - - h_val = duk_hobject_get_internal_value_buffer(thr->heap, obj); - DUK_ASSERT(h_val != NULL); if (flags & DUK__DESC_FLAG_PUSH_VALUE) { - duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val)); + /* Length in elements: take into account shift, but + * intentionally don't check the underlying buffer here. + */ + duk_push_uint(ctx, h_bufobj->length >> h_bufobj->shift); } out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)); return 1; /* cannot be arguments exotic */ + } else if (key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) { + /* If neutered must return 0; length is zeroed during + * neutering. + */ + if (flags & DUK__DESC_FLAG_PUSH_VALUE) { + duk_push_uint(ctx, h_bufobj->length); + } + out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; + return 1; /* cannot be arguments exotic */ + } else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) { + /* If neutered must return 0; offset is zeroed during + * neutering. + */ + if (flags & DUK__DESC_FLAG_PUSH_VALUE) { + duk_push_uint(ctx, h_bufobj->offset); + } + out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; + return 1; /* cannot be arguments exotic */ + } else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) { + if (flags & DUK__DESC_FLAG_PUSH_VALUE) { + duk_push_uint(ctx, 1 << h_bufobj->shift); + } + out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; + return 1; /* cannot be arguments exotic */ } } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj)) { DUK_DDD(DUK_DDDPRINT("duktape/c object exotic property get for key: %!O, arr_idx: %ld", @@ -42703,46 +48600,7 @@ DUK_LOCAL duk_bool_t duk__get_property_desc(duk_hthread *thr, duk_hobject *obj, * standard Array objects. */ -#if 0 /* XXX: unused now */ -DUK_LOCAL duk_tval *duk__shallow_fast_path_array_check_u32(duk_hobject *obj, duk_uint32_t key_idx) { - duk_tval *tv; - - if ((!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) && - (!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) && - (!DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj)) && - (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) && - (DUK_HOBJECT_HAS_ARRAY_PART(obj)) && - (key_idx < obj->a_size)) { - /* technically required to check, but obj->a_size check covers this */ - DUK_ASSERT(key_idx != 0xffffffffUL); - - DUK_DDD(DUK_DDDPRINT("fast path attempt (key is an array index, no exotic " - "string/arguments/buffer behavior, object has array part, key " - "inside array size)")); - - DUK_ASSERT(obj->a_size > 0); /* true even for key_idx == 0 */ - tv = DUK_HOBJECT_A_GET_VALUE_PTR(obj, key_idx); - if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) { - DUK_DDD(DUK_DDDPRINT("-> fast path successful")); - return tv; - } - - /* - * Not found, fall back to slow path. - * - * Note: this approach has the unfortunate side effect that accesses - * to undefined entries (or entries outside valid array range) cause - * a string intern operation. - */ - - DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path")); - } - - return NULL; -} -#endif - -DUK_LOCAL duk_tval *duk__shallow_fast_path_array_check_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *key_tv) { +DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) { duk_tval *tv; duk_uint32_t idx; @@ -42751,7 +48609,7 @@ DUK_LOCAL duk_tval *duk__shallow_fast_path_array_check_tval(duk_hthread *thr, du if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) && !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) && !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) && - !DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(obj) && + !DUK_HOBJECT_IS_BUFFEROBJECT(obj) && !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) { /* Must have array part and no conflicting exotic behaviors. * Doesn't need to have array special behavior, e.g. Arguments @@ -42766,49 +48624,224 @@ DUK_LOCAL duk_tval *duk__shallow_fast_path_array_check_tval(duk_hthread *thr, du "behavior, object has array part)")); #if defined(DUK_USE_FASTINT) - if (DUK_TVAL_IS_FASTINT(key_tv)) { - idx = duk__tval_fastint_to_arr_idx(key_tv); + if (DUK_TVAL_IS_FASTINT(tv_key)) { + idx = duk__tval_fastint_to_arr_idx(tv_key); } else #endif - if (DUK_TVAL_IS_NUMBER(key_tv)) { - idx = duk__tval_number_to_arr_idx(key_tv); + if (DUK_TVAL_IS_DOUBLE(tv_key)) { + idx = duk__tval_number_to_arr_idx(tv_key); } else { DUK_DDD(DUK_DDDPRINT("key is not a number")); return NULL; } - if (idx != DUK__NO_ARRAY_INDEX) { - /* Note: idx is not necessarily a valid array index (0xffffffffUL is not valid) */ - DUK_ASSERT_DISABLE(idx >= 0); /* disabled because idx is duk_uint32_t so always true */ - DUK_ASSERT_DISABLE(idx <= 0xffffffffUL); /* same */ + /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which + * is 0xffffffffUL. We don't need to check for that explicitly + * because 0xffffffffUL will never be inside object 'a_size'. + */ - if (idx < DUK_HOBJECT_GET_ASIZE(obj)) { - /* technically required to check, but obj->a_size check covers this */ - DUK_ASSERT(idx != 0xffffffffUL); + if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { + DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part")); + return NULL; + } + DUK_ASSERT(idx != 0xffffffffUL); + DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX); - /* XXX: for array instances we could take a shortcut here and assume - * Array.prototype doesn't contain an array index property. - */ + /* XXX: for array instances we could take a shortcut here and assume + * Array.prototype doesn't contain an array index property. + */ - DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part")); - tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx); - if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) { - DUK_DDD(DUK_DDDPRINT("-> fast path successful")); - return tv; - } - } else { - DUK_DDD(DUK_DDDPRINT("key is outside array part")); + DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part")); + tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx); + if (!DUK_TVAL_IS_UNDEFINED_UNUSED(tv)) { + DUK_DDD(DUK_DDDPRINT("-> fast path successful")); + return tv; + } + + DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path")); + return NULL; +} + +DUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val, duk_propdesc *temp_desc) { + duk_tval *tv; + duk_uint32_t idx; + duk_tval tv_tmp; + duk_uint32_t old_len, new_len; + + if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) && + DUK_HOBJECT_HAS_ARRAY_PART(obj) && + DUK_HOBJECT_HAS_EXTENSIBLE(obj))) { + return 0; + } + +#if defined(DUK_USE_FASTINT) + if (DUK_TVAL_IS_FASTINT(tv_key)) { + idx = duk__tval_fastint_to_arr_idx(tv_key); + } else +#endif + if (DUK_TVAL_IS_DOUBLE(tv_key)) { + idx = duk__tval_number_to_arr_idx(tv_key); + } else { + DUK_DDD(DUK_DDDPRINT("key is not a number")); + return 0; + } + + /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which + * is 0xffffffffUL. We don't need to check for that explicitly + * because 0xffffffffUL will never be inside object 'a_size'. + */ + + if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */ + return 0; + } + DUK_ASSERT(idx != 0xffffffffUL); + DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX); + + old_len = duk__get_old_array_length(thr, obj, temp_desc); + + if (idx >= old_len) { + DUK_DDD(DUK_DDDPRINT("write new array entry requires length update " + "(arr_idx=%ld, old_len=%ld)", + (long) idx, (long) old_len)); + if (!(temp_desc->flags & DUK_PROPDESC_FLAG_WRITABLE)) { + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_NOT_WRITABLE); + return 0; /* not reachable */ } + new_len = idx + 1; + + /* No resize has occurred so temp_desc->e_idx is still OK */ + tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx); + DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); +#if defined(DUK_USE_FASTINT) + DUK_TVAL_SET_FASTINT_U32(tv, new_len); /* no need for decref/incref because value is a number */ +#else + DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_len); /* no need for decref/incref because value is a number */ +#endif } else { - DUK_DDD(DUK_DDDPRINT("key is not a valid array index")); + ; } - /* - * Not found in array part, use slow path. + tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx); + DUK_TVAL_SET_TVAL(&tv_tmp, tv); + DUK_TVAL_SET_TVAL(tv, tv_val); + DUK_TVAL_INCREF(thr, tv); + DUK_TVAL_DECREF(thr, &tv_tmp); /* note: may trigger gc and props compaction, must be last */ + + DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx)); + return 1; +} + +/* + * Fast path for bufferobject getprop/putprop + */ + +DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) { + duk_context *ctx; + duk_uint32_t idx; + duk_hbufferobject *h_bufobj; + duk_uint_t byte_off; + duk_small_uint_t elem_size; + duk_uint8_t *data; + + ctx = (duk_context *) thr; + + if (!DUK_HOBJECT_IS_BUFFEROBJECT(obj)) { + return 0; + } + h_bufobj = (duk_hbufferobject *) obj; + +#if defined(DUK_USE_FASTINT) + if (DUK_TVAL_IS_FASTINT(tv_key)) { + idx = duk__tval_fastint_to_arr_idx(tv_key); + } else +#endif + if (DUK_TVAL_IS_DOUBLE(tv_key)) { + idx = duk__tval_number_to_arr_idx(tv_key); + } else { + return 0; + } + + /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which + * is 0xffffffffUL. We don't need to check for that explicitly + * because 0xffffffffUL will never be inside bufferobject length. */ - DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path")); - return NULL; + /* Careful with wrapping (left shifting idx would be unsafe). */ + if (idx >= (h_bufobj->length >> h_bufobj->shift)) { + return 0; + } + DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX); + + byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */ + elem_size = 1 << h_bufobj->shift; + + if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) { + data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off; + duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size); + } else { + DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)")); + duk_push_uint(ctx, 0); + } + + return 1; +} + +DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) { + duk_context *ctx; + duk_uint32_t idx; + duk_hbufferobject *h_bufobj; + duk_uint_t byte_off; + duk_small_uint_t elem_size; + duk_uint8_t *data; + + ctx = (duk_context *) thr; + + if (!(DUK_HOBJECT_IS_BUFFEROBJECT(obj) && + DUK_TVAL_IS_NUMBER(tv_val))) { + return 0; + } + h_bufobj = (duk_hbufferobject *) obj; + +#if defined(DUK_USE_FASTINT) + if (DUK_TVAL_IS_FASTINT(tv_key)) { + idx = duk__tval_fastint_to_arr_idx(tv_key); + } else +#endif + if (DUK_TVAL_IS_DOUBLE(tv_key)) { + idx = duk__tval_number_to_arr_idx(tv_key); + } else { + return 0; + } + + /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which + * is 0xffffffffUL. We don't need to check for that explicitly + * because 0xffffffffUL will never be inside bufferobject length. + */ + + /* Careful with wrapping (left shifting idx would be unsafe). */ + if (idx >= (h_bufobj->length >> h_bufobj->shift)) { + return 0; + } + DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX); + + byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */ + elem_size = 1 << h_bufobj->shift; + + /* Value is required to be a number in the fast path so there + * are no side effects in write coercion. + */ + duk_push_tval(ctx, tv_val); + DUK_ASSERT(duk_is_number(ctx, -1)); + + if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) { + data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off; + duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size); + } else { + DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)")); + } + + duk_pop(ctx); + return 1; } /* @@ -42937,6 +48970,24 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, curr = DUK_TVAL_GET_OBJECT(tv_obj); DUK_ASSERT(curr != NULL); + tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key); + if (tmp) { + duk_push_tval(ctx, tmp); + + DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part " + "fast path)", + (duk_tval *) duk_get_tval(ctx, -1))); + return 1; + } + + if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) { + /* Read value pushed on stack. */ + DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufferobject " + "fast path)", + (duk_tval *) duk_get_tval(ctx, -1))); + return 1; + } + #if defined(DUK_USE_ES6_PROXY) if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(curr))) { duk_hobject *h_target; @@ -42992,16 +49043,6 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, } #endif /* DUK_USE_ES6_PROXY */ - tmp = duk__shallow_fast_path_array_check_tval(thr, curr, tv_key); - if (tmp) { - duk_push_tval(ctx, tmp); - - DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part " - "fast path)", - (duk_tval *) duk_get_tval(ctx, -1))); - return 1; - } - if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) { arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key); DUK_ASSERT(key != NULL); @@ -43059,7 +49100,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, if (arr_idx != DUK__NO_ARRAY_INDEX && arr_idx < DUK_HBUFFER_GET_SIZE(h)) { duk_pop_n(ctx, pop_count); - duk_push_int(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]); + duk_push_uint(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]); DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length " "after coercion -> return byte as number)", @@ -43078,12 +49119,29 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx)); } - if (key == DUK_HTHREAD_STRING_LENGTH(thr)) { + if (key == DUK_HTHREAD_STRING_LENGTH(thr) || + key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) { duk_pop(ctx); /* [key] -> [] */ duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */ - DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' after coercion -> " - "return buffer length)", + DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' or 'byteLength' " + "after coercion -> return buffer length)", + (duk_tval *) duk_get_tval(ctx, -1))); + return 1; + } else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) { + duk_pop(ctx); /* [key] -> [] */ + duk_push_uint(ctx, 0); /* [] -> [res] */ + + DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'byteOffset' after coercion -> " + "return 0 for consistency with Buffer objects)", + (duk_tval *) duk_get_tval(ctx, -1))); + return 1; + } else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) { + duk_pop(ctx); /* [key] -> [] */ + duk_push_uint(ctx, 1); /* [] -> [res] */ + + DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'BYTES_PER_ELEMENT' after coercion -> " + "return 1 for consistency with Buffer objects)", (duk_tval *) duk_get_tval(ctx, -1))); return 1; } @@ -43924,54 +49982,17 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, * one as far as writes are concerned. * * The fast path behavior is documented in more detail here: - * ecmascript-testcases/test-misc-array-fast-write.js + * tests/ecmascript/test-misc-array-fast-write.js */ - if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) && - DUK_HOBJECT_HAS_ARRAY_PART(orig) && - DUK_HOBJECT_HAS_EXTENSIBLE(orig) && - DUK_TVAL_IS_NUMBER(tv_key)) { - arr_idx = duk__tval_number_to_arr_idx(tv_key); - if (arr_idx != DUK__NO_ARRAY_INDEX && - arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) { /* for resizing of array part, use slow path */ - duk_tval tv_tmp; - duk_uint32_t old_len, new_len; - - DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig)); - - old_len = duk__get_old_array_length(thr, orig, &desc); - - if (arr_idx >= old_len) { - DUK_DDD(DUK_DDDPRINT("write new array entry requires length update " - "(arr_idx=%ld, old_len=%ld)", - (long) arr_idx, (long) old_len)); - if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) { - DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable")); - goto fail_not_writable; - } - new_len = arr_idx + 1; - - /* No resize has occurred so desc.e_idx is still OK */ - tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx); - DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); -#if defined(DUK_USE_FASTINT) - DUK_TVAL_SET_FASTINT_U32(tv, new_len); /* no need for decref/incref because value is a number */ -#else - DUK_TVAL_SET_NUMBER(tv, (duk_double_t) new_len); /* no need for decref/incref because value is a number */ -#endif - } else { - ; - } - - tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx); - DUK_TVAL_SET_TVAL(&tv_tmp, tv); - DUK_TVAL_SET_TVAL(tv, tv_val); - DUK_TVAL_INCREF(thr, tv); - DUK_TVAL_DECREF(thr, &tv_tmp); /* note: may trigger gc and props compaction, must be last */ + if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val, &desc) != 0) { + DUK_DDD(DUK_DDDPRINT("array fast path success")); + return 1; + } - DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) arr_idx)); - return 1; - } + if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) { + DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufferobject fast path")); + return 1; } #if defined(DUK_USE_ES6_PROXY) @@ -44085,7 +50106,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, #endif { duk_push_tval(ctx, tv_val); - data[arr_idx] = (duk_uint8_t) duk_to_int(ctx, -1); + data[arr_idx] = (duk_uint8_t) duk_to_uint32(ctx, -1); pop_count++; } @@ -44105,7 +50126,10 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx)); } - if (key == DUK_HTHREAD_STRING_LENGTH(thr)) { + if (key == DUK_HTHREAD_STRING_LENGTH(thr) || + key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr) || + key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr) || + key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) { goto fail_not_writable; } @@ -44237,23 +50261,41 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, } if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) { DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable")); - if (DUK_HOBJECT_HAS_EXOTIC_BUFFEROBJ(curr)) { - duk_hbuffer *h; + if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) { + duk_hbufferobject *h_bufobj; + duk_uint_t byte_off; + duk_small_uint_t elem_size; + + h_bufobj = (duk_hbufferobject *) curr; + DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj); DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object")); - h = duk_hobject_get_internal_value_buffer(thr->heap, curr); - DUK_ASSERT(h != NULL); - if (arr_idx != DUK__NO_ARRAY_INDEX && - arr_idx < DUK_HBUFFER_GET_SIZE(h)) { + /* Careful with wrapping: arr_idx upshift may easily wrap, whereas + * length downshift won't. + */ + if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) { duk_uint8_t *data; DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx)); - data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); - duk_push_tval(ctx, tv_val); - /* XXX: duk_to_int() ensures we'll get 8 lowest bits as - * as input is within duk_int_t range (capped outside it). + + DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */ + byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */ + elem_size = 1 << h_bufobj->shift; + + /* Coerce to number before validating pointers etc so that the + * number coercions in duk_hbufferobject_validated_write() are + * guaranteed to be side effect free and not invalidate the + * pointer checks we do here. */ - data[arr_idx] = (duk_uint8_t) duk_to_int(ctx, -1); + duk_push_tval(ctx, tv_val); + duk_to_number(ctx, -1); + + if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) { + data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off; + duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size); + } else { + DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)")); + } duk_pop(ctx); goto success_no_arguments_exotic; } @@ -46671,7 +52713,7 @@ DUK_INTERNAL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) { */ #define DUK__CLASS_BITS 5 -#define DUK__BIDX_BITS 6 +#define DUK__BIDX_BITS 7 #define DUK__STRIDX_BITS 9 /* XXX: try to optimize to 8 */ #define DUK__NATIDX_BITS 8 #define DUK__NUM_NORMAL_PROPS_BITS 6 @@ -46686,7 +52728,7 @@ DUK_INTERNAL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) { #define DUK__NARGS_VARARGS_MARKER 0x07 #define DUK__NO_CLASS_MARKER 0x00 /* 0 = DUK_HOBJECT_CLASS_UNUSED */ -#define DUK__NO_BIDX_MARKER 0x3f +#define DUK__NO_BIDX_MARKER 0x7f #define DUK__NO_STRIDX_MARKER 0xff #define DUK__PROP_TYPE_DOUBLE 0 @@ -47262,12 +53304,14 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { #endif " " /* Alignment guarantee */ -#if defined(DUK_USE_ALIGN_4) +#if (DUK_USE_ALIGN_BY == 4) "a4" -#elif defined(DUK_USE_ALIGN_8) +#elif (DUK_USE_ALIGN_BY == 8) "a8" -#else +#elif (DUK_USE_ALIGN_BY == 1) "a1" +#else +#error invalid DUK_USE_ALIGN_BY #endif " " /* Architecture, OS, and compiler strings */ @@ -47867,6 +53911,41 @@ DUK_INTERNAL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new /* include removed: duk_internal.h */ +/* + * Misc + */ + +#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG) +DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) { + /* XXX: Currently the bytecode executor and executor interrupt + * instruction counts are off because we don't execute the + * interrupt handler when we're about to exit from the initial + * user call into Duktape. + * + * If we were to execute the interrupt handler here, the counts + * would match. You can enable this block manually to check + * that this is the case. + */ + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(thr->heap != NULL); + +#if 0 + if (entry_curr_thread == NULL) { + thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter; + thr->heap->inst_count_interrupt += thr->interrupt_init; + DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to " + "user code, instruction counts: executor=%ld, interrupt=%ld", + (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt)); + DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt); + } +#else + DUK_UNREF(thr); + DUK_UNREF(entry_curr_thread); +#endif +} +#endif + /* * Arguments object creation. * @@ -48230,7 +54309,7 @@ void duk__handle_bound_chain_for_call(duk_hthread *thr, /* [ ... func this arg1 ... argN ] */ if (is_constructor_call) { - /* See: ecmascript-testcases/test-spec-bound-constructor.js */ + /* See: tests/ecmascript/test-spec-bound-constructor.js */ DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding")); } else { duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_THIS); @@ -49342,7 +55421,7 @@ duk_int_t duk_handle_call(duk_hthread *thr, goto shrink_and_finished; shrink_and_finished: -#if defined(DUK_OPT_FASTINT) +#if defined(DUK_USE_FASTINT) /* Explicit check for fastint downgrade. */ { duk_tval *tv_fi; @@ -49397,6 +55476,10 @@ duk_int_t duk_handle_call(duk_hthread *thr, thr->heap->call_recursion_depth = entry_call_recursion_depth; +#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG) + duk__interrupt_fixup(thr, entry_curr_thread); +#endif + return retval; thread_state_error: @@ -49770,6 +55853,10 @@ duk_int_t duk_handle_safe_call(duk_hthread *thr, /* stack discipline consistency check */ DUK_ASSERT(duk_get_top(ctx) == idx_retbase + num_stack_rets); +#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG) + duk__interrupt_fixup(thr, entry_curr_thread); +#endif + return retval; thread_state_error: @@ -50277,6 +56364,9 @@ duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr, #define DUK__MAX_FUNCS DUK_BC_BC_MAX #define DUK__MAX_TEMPS 0xffffL +/* Initial bytecode size allocation. */ +#define DUK__BC_INITIAL_INSTS 256 + #define DUK__RECURSION_INCREASE(comp_ctx,thr) do { \ DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \ duk__recursion_increase((comp_ctx)); \ @@ -50346,7 +56436,7 @@ DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx); DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc); DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc); DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc); -DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags); +DUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags); DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst); DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst); DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx); @@ -50412,8 +56502,8 @@ DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_iva DUK_LOCAL_DECL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags); #if 0 /* unused */ DUK_LOCAL_DECL duk_reg_t duk__exprtop_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags); -DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg); #endif +DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg); DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags); #if 0 /* unused */ DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags); @@ -50495,8 +56585,6 @@ DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, d DUK_LOCAL const duk_uint8_t duk__token_lbp[] = { DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */ - DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LINETERM */ - DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COMMENT */ DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_IDENTIFIER */ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */ DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */ @@ -50721,7 +56809,6 @@ DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) { DUK_MEMZERO(func, sizeof(*func)); /* intentional overlap with earlier memzero */ #ifdef DUK_USE_EXPLICIT_NULL_INIT func->h_name = NULL; - func->h_code = NULL; func->h_consts = NULL; func->h_funcs = NULL; func->h_decls = NULL; @@ -50733,13 +56820,8 @@ DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) { duk_require_stack(ctx, DUK__FUNCTION_INIT_REQUIRE_SLOTS); - /* XXX: getter for dynamic buffer */ - - duk_push_dynamic_buffer(ctx, 0); - func->code_idx = entry_top + 0; - func->h_code = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 0); - DUK_ASSERT(func->h_code != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_code)); + DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr)); + /* code_idx = entry_top + 0 */ duk_push_array(ctx); func->consts_idx = entry_top + 1; @@ -50785,9 +56867,11 @@ DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) { duk_hthread *thr = comp_ctx->thr; duk_context *ctx = (duk_context *) thr; - /* XXX: reset buffers while keeping existing spare */ + /* reset bytecode buffer but keep current size; pass 2 will + * require same amount or more. + */ + DUK_BW_RESET_SIZE(thr, &func->bw_code); - duk_hbuffer_reset(thr, func->h_code); duk_hobject_set_length_zero(thr, func->h_consts); /* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */ func->fnum_next = 0; @@ -50876,10 +56960,6 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo duk_tval *tv; DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template")); - DUK_DD(DUK_DDPRINT("code=%!xO consts=%!O funcs=%!O", - (duk_heaphdr *) func->h_code, - (duk_heaphdr *) func->h_consts, - (duk_heaphdr *) func->h_funcs)); /* * Push result object and init its flags @@ -50946,9 +57026,9 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo * so the building process is atomic. */ - consts_count = duk_hobject_get_length(comp_ctx->thr, func->h_consts); - funcs_count = duk_hobject_get_length(comp_ctx->thr, func->h_funcs) / 3; - code_count = DUK_HBUFFER_GET_SIZE(func->h_code) / sizeof(duk_compiler_instr); + consts_count = duk_hobject_get_length(thr, func->h_consts); + funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3; + code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr); code_size = code_count * sizeof(duk_instr_t); data_size = consts_count * sizeof(duk_tval) + @@ -50969,7 +57049,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data); DUK_HEAPHDR_INCREF(thr, h_data); - p_const = (duk_tval *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data); + p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data); for (i = 0; i < consts_count; i++) { DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */ tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i); @@ -51003,8 +57083,7 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_res, p_instr); /* copy bytecode instructions one at a time */ - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_code)); - q_instr = (duk_compiler_instr *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, func->h_code); + q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code); for (i = 0; i < code_count; i++) { p_instr[i] = q_instr[i].ins; } @@ -51249,34 +57328,25 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo /* XXX: macro smaller than call? */ DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) { - return (duk_int_t) (DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_code) / sizeof(duk_compiler_instr)); + duk_compiler_func *func; + func = &comp_ctx->curr_func; + return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr)); } DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) { - duk_compiler_func *f = &comp_ctx->curr_func; - duk_uint8_t *p; - duk_compiler_instr *code_begin, *code_end; - - p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, f->h_code); - code_begin = (duk_compiler_instr *) p; - code_end = (duk_compiler_instr *) (p + DUK_HBUFFER_GET_SIZE(f->h_code)); - DUK_UNREF(code_end); - DUK_ASSERT(pc >= 0); - DUK_ASSERT((duk_size_t) pc < (duk_size_t) (code_end - code_begin)); - - return code_begin + pc; + DUK_ASSERT((duk_size_t) pc < (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr))); + return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc; } /* emit instruction; could return PC but that's not needed in the majority * of cases. */ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) { - duk_hbuffer_dynamic *h; #if defined(DUK_USE_PC2LINE) duk_int_t line; #endif - duk_compiler_instr instr; + duk_compiler_instr *instr; DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I", (unsigned long) ins, @@ -51285,7 +57355,9 @@ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) { (long) duk__get_current_pc(comp_ctx), (duk_instr_t) ins)); - h = comp_ctx->curr_func.h_code; + instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr)); + DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr)); + #if defined(DUK_USE_PC2LINE) /* The line number tracking is a bit inconsistent right now, which * affects debugger accuracy. Mostly call sites emit opcodes when @@ -51302,9 +57374,9 @@ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) { } #endif - instr.ins = ins; + instr->ins = ins; #if defined(DUK_USE_PC2LINE) - instr.line = line; + instr->line = line; #endif #if defined(DUK_USE_DEBUGGER_SUPPORT) if (line < comp_ctx->curr_func.min_line) { @@ -51316,21 +57388,26 @@ DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) { #endif /* Limit checks for bytecode byte size and line number. */ + if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) { + goto fail_bc_limit; + } #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS) #if defined(DUK_USE_BUFLEN16) /* Buffer length is bounded to 0xffff automatically, avoid compile warning. */ if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) { - DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT); + goto fail_bc_limit; } #else - if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER || - DUK_HBUFFER_GET_SIZE((duk_hbuffer *) h) > DUK_USE_ESBC_MAX_BYTES)) { - DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT); + if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) { + goto fail_bc_limit; } #endif #endif - duk_hbuffer_append_bytes(comp_ctx->thr, h, (duk_uint8_t *) &instr, sizeof(instr)); + return; + + fail_bc_limit: + DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT); } /* Update function min/max line from current token. Needed to improve @@ -51792,12 +57869,10 @@ DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_re #endif DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) { - duk_hbuffer_dynamic *h; duk_int_t curr_pc; duk_int_t offset; - h = comp_ctx->curr_func.h_code; - curr_pc = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h) / sizeof(duk_compiler_instr)); + curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)); offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1; DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN); DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX); @@ -51816,26 +57891,35 @@ DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) { * currently needed for compiling for-in. */ DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) { - duk_hbuffer_dynamic *h; #if defined(DUK_USE_PC2LINE) duk_int_t line; #endif - duk_compiler_instr instr; + duk_compiler_instr *instr; duk_size_t offset; - h = comp_ctx->curr_func.h_code; + offset = jump_pc * sizeof(duk_compiler_instr), + instr = (duk_compiler_instr *) (void *) + DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr, + &comp_ctx->curr_func.bw_code, + offset, + sizeof(duk_compiler_instr)); + #if defined(DUK_USE_PC2LINE) line = comp_ctx->curr_token.start_line; /* approximation, close enough */ #endif - - instr.ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0); + instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0); #if defined(DUK_USE_PC2LINE) - instr.line = line; + instr->line = line; #endif - offset = jump_pc * sizeof(duk_compiler_instr); + DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr)); + if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) { + goto fail_bc_limit; + } + return; - duk_hbuffer_insert_bytes(comp_ctx->thr, h, offset, (duk_uint8_t *) &instr, sizeof(instr)); + fail_bc_limit: + DUK_ERROR(comp_ctx->thr, DUK_ERR_RANGE_ERROR, DUK_STR_BYTECODE_LIMIT); } /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional @@ -51869,31 +57953,42 @@ DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_p duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx)); } -DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) { +DUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) { duk_compiler_instr *instr; - instr = duk__get_instr_ptr(comp_ctx, trycatch_pc); - DUK_ASSERT(instr != NULL); - - DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN); - DUK_ASSERT(flags <= DUK_BC_A_MAX); - DUK_ASSERT((reg_catch & DUK__CONST_MARKER) == 0); - const_varname = const_varname & (~DUK__CONST_MARKER); - if (reg_catch > DUK_BC_B_MAX || const_varname > DUK_BC_C_MAX) { - /* Catch attempts to use out-of-range reg/const. Without this - * check Duktape 0.12.0 could generate invalid code which caused - * an assert failure on execution. This error is triggered e.g. - * for functions with a lot of constants and a try-catch statement. - * Shuffling or opcode semantics change is needed to fix the issue. - * See: test-bug-trycatch-many-constants.js. + + instr = duk__get_instr_ptr(comp_ctx, ldconst_pc); + DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST); + DUK_ASSERT(instr != NULL); + if (const_varname & DUK__CONST_MARKER) { + /* Have a catch variable. */ + const_varname = const_varname & (~DUK__CONST_MARKER); + if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) { + /* Catch attempts to use out-of-range reg/const. Without this + * check Duktape 0.12.0 could generate invalid code which caused + * an assert failure on execution. This error is triggered e.g. + * for functions with a lot of constants and a try-catch statement. + * Shuffling or opcode semantics change is needed to fix the issue. + * See: test-bug-trycatch-many-constants.js. + */ + DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)", + (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname)); + DUK_ERROR(comp_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_REG_LIMIT); + } + instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname); + } else { + /* No catch variable, e.g. a try-finally; replace LDCONST with + * NOP to avoid a bogus LDCONST. */ - DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)", - (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname)); - DUK_ERROR(comp_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_REG_LIMIT); + instr->ins = DUK_ENC_OP_A(DUK_OP_EXTRA, DUK_EXTRAOP_NOP); } - instr->ins = DUK_ENC_OP_A_B_C(DUK_OP_TRYCATCH, flags, reg_catch, const_varname); + instr = duk__get_instr_ptr(comp_ctx, trycatch_pc); + DUK_ASSERT(instr != NULL); + DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN); + DUK_ASSERT(flags <= DUK_BC_A_MAX); + instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch); } DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) { @@ -51924,23 +58019,18 @@ DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) { */ DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) { - duk_hbuffer_dynamic *h; duk_compiler_instr *bc; duk_small_uint_t iter; duk_int_t i, n; duk_int_t count_opt; - h = comp_ctx->curr_func.h_code; - DUK_ASSERT(h != NULL); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h)); - - bc = (duk_compiler_instr *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, h); + bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code); #if defined(DUK_USE_BUFLEN16) /* No need to assert, buffer size maximum is 0xffff. */ #else - DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h) / sizeof(duk_compiler_instr) <= DUK_INT_MAX); /* bytecode limits */ + DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <= (duk_size_t) DUK_INT_MAX); /* bytecode limits */ #endif - n = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h) / sizeof(duk_compiler_instr)); + n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)); for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) { count_opt = 0; @@ -52737,8 +58827,8 @@ DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, */ p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos); - li_start = (duk_labelinfo *) p; - li = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); + li_start = (duk_labelinfo *) (void *) p; + li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); n = (duk_size_t) (li - li_start); while (li > li_start) { @@ -52754,14 +58844,14 @@ DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, (void) duk_put_prop_index(ctx, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n); new_size = (n + 1) * sizeof(duk_labelinfo); - duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size, new_size); + duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size); /* XXX: spare handling, slow now */ /* relookup after possible realloc */ p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos); - li_start = (duk_labelinfo *) p; + li_start = (duk_labelinfo *) (void *) p; DUK_UNREF(li_start); /* silence scan-build warning */ - li = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); + li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); li--; /* Labels can be used for iteration statements but also for other statements, @@ -52788,8 +58878,8 @@ DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t lab duk_labelinfo *li_start, *li; p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos); - li_start = (duk_labelinfo *) p; - li = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); + li_start = (duk_labelinfo *) (void *) p; + li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); /* Match labels starting from latest; once label_id no longer matches, we can * safely exit without checking the rest of the labels (only the topmost labels @@ -52837,8 +58927,8 @@ DUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring DUK_UNREF(ctx); p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos); - li_start = (duk_labelinfo *) p; - li_end = (duk_labelinfo *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); + li_start = (duk_labelinfo *) (void *) p; + li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos)); li = li_end; /* Match labels starting from latest label because there can be duplicate empty @@ -52906,7 +58996,7 @@ DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t new_size = sizeof(duk_labelinfo) * (duk_size_t) len; duk_push_int(ctx, len); duk_put_prop_stridx(ctx, comp_ctx->curr_func.labelnames_idx, DUK_STRIDX_LENGTH); - duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size, new_size); /* XXX: spare handling */ + duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size); } /* @@ -54919,13 +61009,11 @@ DUK_LOCAL duk_reg_t duk__exprtop_totempreg(duk_compiler_ctx *comp_ctx, duk_ivalu } #endif -#if 0 /* unused */ DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) { DUK_ASSERT(forced_reg >= 0); duk__exprtop(comp_ctx, res, rbp_flags); duk__ivalue_toforcedreg(comp_ctx, res, forced_reg); } -#endif DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) { duk__exprtop(comp_ctx, res, rbp_flags); @@ -55941,6 +62029,7 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) duk_reg_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */ duk_regconst_t rc_varname = 0; duk_small_uint_t trycatch_flags = 0; + duk_int_t pc_ldconst = -1; duk_int_t pc_trycatch = -1; duk_int_t pc_catch = -1; duk_int_t pc_finally = -1; @@ -55968,6 +62057,14 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2); + /* The target for this LDCONST may need output shuffling, but we assume + * that 'pc_ldconst' will be the LDCONST that we can patch later. This + * should be the case because there's no input shuffling. (If there's + * no catch clause, this LDCONST will be replaced with a NOP.) + */ + pc_ldconst = duk__get_current_pc(comp_ctx); + duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/); + pc_trycatch = duk__get_current_pc(comp_ctx); duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */ duk__emit_invalid(comp_ctx); /* jump for 'catch' case */ @@ -56129,7 +62226,13 @@ DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) goto syntax_error; } + /* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch() + * will replace the LDCONST with a NOP. For any actual constant (including + * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname. + */ + duk__patch_trycatch(comp_ctx, + pc_ldconst, pc_trycatch, reg_catch, rc_varname, @@ -56159,7 +62262,6 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) duk_int_t pc_trycatch; duk_int_t pc_finished; duk_reg_t reg_catch; - duk_regconst_t rc_target; duk_small_uint_t trycatch_flags; if (comp_ctx->curr_func.is_strict) { @@ -56173,23 +62275,15 @@ DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2); duk__advance_expect(comp_ctx, DUK_TOK_LPAREN); - rc_target = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); + duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch); duk__advance_expect(comp_ctx, DUK_TOK_RPAREN); - /* XXX: the trycatch shuffle flags are now very limiting and a fix - * is needed to allow trycatch to work in functions with a very large - * number of temporaries or constants. - */ - pc_trycatch = duk__get_current_pc(comp_ctx); trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING; - duk__emit_a_b_c(comp_ctx, - DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A - | DUK__EMIT_FLAG_NO_SHUFFLE_B - | DUK__EMIT_FLAG_NO_SHUFFLE_C, + duk__emit_a_bc(comp_ctx, + DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A, (duk_regconst_t) trycatch_flags /*a*/, - (duk_regconst_t) reg_catch /*b*/, - rc_target /*c*/); + (duk_regconst_t) reg_catch /*bc*/); duk__emit_invalid(comp_ctx); /* catch jump */ duk__emit_invalid(comp_ctx); /* finished jump */ @@ -57921,7 +64015,7 @@ DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer /* include removed: duk_internal.h */ /* - * Local forward declarations + * Local declarations */ DUK_LOCAL_DECL void duk__reconfig_valstack(duk_hthread *thr, duk_size_t act_idx, duk_small_uint_t retval_count); @@ -59416,7 +65510,7 @@ duk_bool_t duk__handle_fast_return(duk_hthread *thr, * work accurately even when single stepping. */ -#ifdef DUK_USE_INTERRUPT_COUNTER +#if defined(DUK_USE_INTERRUPT_COUNTER) #define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */ #define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */ @@ -59515,7 +65609,8 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_ process_messages = 0; } - thr->heap->dbg_exec_counter += thr->heap->interrupt_init; + /* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */ + thr->heap->dbg_exec_counter += thr->interrupt_init; if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) { /* Overflow of the execution counter is fine and doesn't break * anything here. @@ -59524,7 +65619,7 @@ DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_ duk_double_t now, diff_last; thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter; - now = duk_bi_date_get_now(ctx); + now = DUK_USE_DATE_GET_NOW(ctx); diff_last = now - thr->heap->dbg_last_time; if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) { @@ -59603,11 +65698,20 @@ DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) { duk_small_uint_t retval; DUK_ASSERT(thr != NULL); + DUK_ASSERT(thr->heap != NULL); DUK_ASSERT(thr->callstack != NULL); DUK_ASSERT(thr->callstack_top > 0); +#if defined(DUK_USE_DEBUG) + thr->heap->inst_count_interrupt += thr->interrupt_init; + DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, " + "instruction counts: executor=%ld, interrupt=%ld", + (long) thr->interrupt_counter, (long) thr->interrupt_init, + (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt)); +#endif + retval = DUK__INT_NOACTION; - ctr = DUK_HEAP_INTCTR_DEFAULT; + ctr = DUK_HTHREAD_INTCTR_DEFAULT; /* * Avoid nested calls. Concretely this happens during debugging, e.g. @@ -59620,8 +65724,7 @@ DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) { /* Set a high interrupt counter; the original executor * interrupt invocation will rewrite before exiting. */ - thr->heap->interrupt_init = ctr; - thr->heap->interrupt_counter = ctr - 1; + thr->interrupt_init = ctr; thr->interrupt_counter = ctr - 1; return DUK__INT_NOACTION; } @@ -59647,8 +65750,7 @@ DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) { * until we've fully bubbled out of Duktape. */ DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError")); - thr->heap->interrupt_init = 0; - thr->heap->interrupt_counter = 0; + thr->interrupt_init = 0; thr->interrupt_counter = 0; DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap); DUK_ERROR(thr, DUK_ERR_RANGE_ERROR, "execution timeout"); @@ -59676,10 +65778,10 @@ DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) { /* The counter value is one less than the init value: init value should * indicate how many instructions are executed before interrupt. To - * execute 1 instruction, counter must be 0. + * execute 1 instruction (after interrupt handler return), counter must + * be 0. */ - thr->heap->interrupt_init = ctr; - thr->heap->interrupt_counter = ctr - 1; + thr->interrupt_init = ctr; thr->interrupt_counter = ctr - 1; DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap); @@ -59810,6 +65912,13 @@ DUK_LOCAL void duk__executor_handle_debugger(duk_hthread *thr, duk_activation *a thr->heap->dbg_paused || (thr->heap->dbg_step_type != DUK_STEP_TYPE_OUT && thr->heap->dbg_step_csindex == thr->callstack_top - 1)) { + /* We'll need to interrupt early so recompute the init + * counter to reflect the number of bytecode instructions + * executed so that step counts for e.g. debugger rate + * limiting are accurate. + */ + DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init); + thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter; thr->interrupt_counter = 0; } } @@ -60024,9 +66133,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))); -#ifdef DUK_USE_INTERRUPT_COUNTER - thr->interrupt_counter = thr->heap->interrupt_counter; -#endif + /* Assume interrupt init/counter are properly initialized here. */ /* assume that thr->valstack_bottom has been set-up before getting here */ act = thr->callstack + thr->callstack_top - 1; @@ -60123,6 +66230,9 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { } } #endif +#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG) + thr->heap->inst_count_exec++; +#endif /* Because ANY DECREF potentially invalidates 'act' now (through * finalization), we need to re-lookup 'act' in almost every case. @@ -61085,7 +67195,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { if (a & DUK_BC_RETURN_FLAG_HAVE_RETVAL) { tv_val = DUK__REGCONSTP(b); -#if defined(DUK_OPT_FASTINT) +#if defined(DUK_USE_FASTINT) /* Explicit check for fastint downgrade. Do * it also for consts for now, which is odd * but harmless. @@ -61281,34 +67391,40 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { duk_catcher *cat; duk_tval *tv1; duk_small_uint_fast_t a; - duk_small_uint_fast_t b; - duk_small_uint_fast_t c; + duk_uint_fast_t bc; /* A -> flags - * B -> reg_catch; base register for 2 regs - * C -> semantics depend on flags: var_name or with_target + * BC -> reg_catch; base register for two registers used both during + * trycatch setup and when catch is triggered * * If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set: - * C is constant index for catch binding variable name. + * reg_catch + 0: catch binding variable name (string). * Automatic declarative environment is established for * the duration of the 'catch' clause. * * If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set: - * C is reg/const index for with 'target value', which - * is coerced to an object and then used as a binding - * object for an environment record. The binding is - * initialized here, for the 'try' clause. + * reg_catch + 0: with 'target value', which is coerced to + * an object and then used as a bindind object for an + * environment record. The binding is initialized here, for + * the 'try' clause. * * Note that a TRYCATCH generated for a 'with' statement has no * catch or finally parts. */ + /* XXX: TRYCATCH handling should be reworked to avoid creating + * an explicit scope unless it is actually needed (e.g. function + * instances or eval is executed inside the catch block). This + * rework is not trivial because the compiler doesn't have an + * intermediate representation. When the rework is done, the + * opcode format can also be made more straightforward. + */ + /* XXX: side effect handling is quite awkward here */ - DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, var_name/with_target=%ld, have_catch=%ld, " + DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, " "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)", - (long) DUK_DEC_B(ins), - (long) DUK_DEC_C(ins), + (long) DUK_DEC_BC(ins), (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0), (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0), (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0), @@ -61316,8 +67432,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { (unsigned long) DUK_DEC_A(ins))); a = DUK_DEC_A(ins); - b = DUK_DEC_B(ins); - c = DUK_DEC_C(ins); + bc = DUK_DEC_BC(ins); DUK_ASSERT(thr->callstack_top >= 1); @@ -61343,7 +67458,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV), -1); /* no prototype, updated below */ - duk_push_tval(ctx, DUK__REGCONSTP(c)); + duk_push_tval(ctx, DUK__REGP(bc)); duk_to_object(ctx, -1); duk_dup(ctx, -1); @@ -61378,8 +67493,13 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) { DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher")); cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; - tv1 = DUK__CONSTP(c); + tv1 = DUK__REGP(bc); DUK_ASSERT(DUK_TVAL_IS_STRING(tv1)); + + /* borrowed reference; although 'tv1' comes from a register, + * its value was loaded using LDCONST so the constant will + * also exist and be reachable. + */ cat->h_varname = DUK_TVAL_GET_STRING(tv1); } else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) { /* env created above to stack top */ @@ -61408,7 +67528,7 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) { cat = thr->catchstack + thr->catchstack_top - 1; /* relookup (side effects) */ cat->callstack_index = thr->callstack_top - 1; cat->pc_base = act->pc; /* pre-incremented, points to first jump slot */ - cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + b; + cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc; DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, " "idx_base=%ld, h_varname=%!O", @@ -63048,28 +69168,11 @@ DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, d * needs to push stuff on the stack anyway... */ -DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) { - /* - * String comparison (E5 Section 11.8.5, step 4), which - * needs to compare codepoint by codepoint. - * - * However, UTF-8 allows us to use strcmp directly: the shared - * prefix will be encoded identically (UTF-8 has unique encoding) - * and the first differing character can be compared with a simple - * unsigned byte comparison (which strcmp does). - * - * This will not work properly for non-xutf-8 strings, but this - * is not an issue for compliance. - */ - - duk_size_t h1_len, h2_len, prefix_len; +DUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2) { + duk_size_t prefix_len; duk_small_int_t rc; - DUK_ASSERT(h1 != NULL); - DUK_ASSERT(h2 != NULL); - h1_len = DUK_HSTRING_GET_BYTELEN(h1); - h2_len = DUK_HSTRING_GET_BYTELEN(h2); - prefix_len = (h1_len <= h2_len ? h1_len : h2_len); + 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 @@ -63080,8 +69183,8 @@ DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring if (prefix_len == 0) { rc = 0; } else { - rc = DUK_MEMCMP((const char *) DUK_HSTRING_GET_DATA(h1), - (const char *) DUK_HSTRING_GET_DATA(h2), + rc = DUK_MEMCMP((const char *) buf1, + (const char *) buf2, prefix_len); } @@ -63092,16 +69195,54 @@ DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring } /* prefix matches, lengths matter now */ - if (h1_len < h2_len) { + if (len1 < len2) { /* e.g. "x" < "xx" */ return -1; - } else if (h1_len > h2_len) { + } else if (len1 > len2) { return 1; } return 0; } +DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) { + /* + * String comparison (E5 Section 11.8.5, step 4), which + * needs to compare codepoint by codepoint. + * + * However, UTF-8 allows us to use strcmp directly: the shared + * prefix will be encoded identically (UTF-8 has unique encoding) + * and the first differing character can be compared with a simple + * unsigned byte comparison (which strcmp does). + * + * This will not work properly for non-xutf-8 strings, but this + * is not an issue for compliance. + */ + + DUK_ASSERT(h1 != NULL); + DUK_ASSERT(h2 != NULL); + + return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1), + (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2), + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1), + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2)); +} + +#if 0 /* unused */ +DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) { + /* Similar to String comparison. */ + + DUK_ASSERT(h1 != NULL); + DUK_ASSERT(h2 != NULL); + DUK_UNREF(heap); + + return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1), + (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2), + (duk_size_t) DUK_HBUFFER_GET_SIZE(h1), + (duk_size_t) DUK_HBUFFER_GET_SIZE(h2)); +} +#endif + DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) { duk_context *ctx = (duk_context *) thr; duk_double_t d1, d2; @@ -63291,6 +69432,9 @@ DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, * E5 Section 15.3.4.5.3 * * For other objects, a TypeError is thrown. + * + * Limited Proxy support: don't support 'getPrototypeOf' trap but + * continue lookup in Proxy target if the value is a Proxy. */ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) { @@ -63380,6 +69524,13 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ proto = duk_require_hobject(ctx, -1); duk_pop(ctx); /* -> [ ... lval rval ] */ + DUK_ASSERT(val != NULL); + +#if defined(DUK_USE_ES6_PROXY) + val = duk_hobject_resolve_proxy_target(thr, val); + DUK_ASSERT(val != NULL); +#endif + sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY; do { /* @@ -63400,11 +69551,19 @@ DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_ * also the built-in Function prototype, the result is true. */ + DUK_ASSERT(val != NULL); val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val); if (!val) { goto pop_and_false; - } else if (val == proto) { + } + + DUK_ASSERT(val != NULL); +#if defined(DUK_USE_ES6_PROXY) + val = duk_hobject_resolve_proxy_target(thr, val); +#endif + + if (val == proto) { goto pop_and_true; } @@ -63794,7 +69953,13 @@ void duk_js_push_closure(duk_hthread *thr, DUK_HOBJECT_SET_NOTAIL(&fun_clos->obj); } /* DUK_HOBJECT_FLAG_NEWENV: handled below */ - DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)); + if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) { + /* Although NAMEBINDING is not directly needed for using + * function instances, it's needed by bytecode dump/load + * so copy it too. + */ + DUK_HOBJECT_SET_NAMEBINDING(&fun_clos->obj); + } if (DUK_HOBJECT_HAS_CREATEARGS(&fun_temp->obj)) { DUK_HOBJECT_SET_CREATEARGS(&fun_clos->obj); } @@ -65421,7 +71586,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * checks (such as access outside the end of the input), which keeps the * tokenization code small at the cost of performance. * - * Character data in tokens (such as identifier names and string literals) + * Character data in tokens, such as identifier names and string literals, * is encoded into CESU-8 format on-the-fly while parsing the token in * question. The string data is made reachable to garbage collection by * placing the token-related values in value stack entries allocated for @@ -65447,12 +71612,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * * Future work: * - * * Make the input window a circular array to avoid copying. This would - * not necessarily complicate the tokenizer much, although it would make - * the window fetches more expensive (one AND). - * - * * Make line number tracking optional, as it consumes space. Also, is - * tracking end line really useful for tokens? + * * Make line number tracking optional, as it consumes space. * * * Add a feature flag for disabling UTF-8 decoding of input, as most * source code is ASCII. Because of Unicode escapes written in ASCII, @@ -65477,7 +71637,8 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * not after tokens have been formed (as is done now). However, the fix * is not trivial because two characters are decoded from one codepoint. * - * * Optimize for speed as well as size. Large if-else ladders are slow. + * * Optimize for speed as well as size. Large if-else ladders are (at + * least potentially) slow. */ /* include removed: duk_internal.h */ @@ -65489,11 +71650,6 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, #define DUK__MAX_RE_DECESC_DIGITS 9 #define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */ -#define DUK__LOOKUP(lex_ctx,index) ((lex_ctx)->window[(index)]) -#define DUK__ADVANCE(lex_ctx,count) duk__advance_chars((lex_ctx), (count)) -#define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx)) -#define DUK__APPENDBUFFER(lex_ctx,x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x)) - /* whether to use macros or helper function depends on call count */ #define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9) #define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x)) @@ -65501,6 +71657,13 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, #define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3) #define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7) +/* lexer character window helpers */ +#define DUK__LOOKUP(lex_ctx,index) ((lex_ctx)->window[(index)].codepoint) +#define DUK__ADVANCECHARS(lex_ctx,count) duk__advance_bytes((lex_ctx), (count) * sizeof(duk_lexer_codepoint)) +#define DUK__ADVANCEBYTES(lex_ctx,count) duk__advance_bytes((lex_ctx), (count)) +#define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx)) +#define DUK__APPENDBUFFER(lex_ctx,x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x)) + /* lookup shorthands (note: assume context variable is named 'lex_ctx') */ #define DUK__L0() DUK__LOOKUP(lex_ctx, 0) #define DUK__L1() DUK__LOOKUP(lex_ctx, 1) @@ -65510,10 +71673,23 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, #define DUK__L5() DUK__LOOKUP(lex_ctx, 5) /* packed advance/token number macro used by multiple functions */ -#define DUK__ADVTOK(adv,tok) (((adv) << 8) + (tok)) +#define DUK__ADVTOK(advbytes,tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok)) /* - * Read a character from the window leading edge and update the line counter. + * Advance lookup window by N characters, filling in new characters as + * necessary. After returning caller is guaranteed a character window of + * at least DUK_LEXER_WINDOW_SIZE characters. + * + * The main function duk__advance_bytes() is called at least once per every + * token so it has a major lexer/compiler performance impact. There are two + * variants for the main duk__advance_bytes() algorithm: a sliding window + * approach which is slightly faster at the cost of larger code footprint, + * and a simple copying one. + * + * Decoding directly from the source string would be another lexing option. + * But the lookup window based approach has the advantage of hiding the + * source string and its encoding effectively which gives more flexibility + * going forward to e.g. support chunked streaming of source from flash. * * Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to * U+10FFFF, causing an error if the input is unparseable. Leniency means: @@ -65563,16 +71739,192 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr, * * * Is checking against maximum 0x10ffff really useful? 4-byte encoding * imposes a certain limit anyway. + * + * * Support chunked streaming of source code. Can be implemented either + * by streaming chunks of bytes or chunks of codepoints. */ +#if defined(DUK_USE_LEXER_SLIDING_WINDOW) +DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) { + duk_lexer_codepoint *cp, *cp_end; + duk_ucodepoint_t x; + duk_small_uint_t contlen; + const duk_uint8_t *p, *p_end; +#ifdef DUK_USE_STRICT_UTF8_SOURCE + duk_ucodepoint_t mincp; +#endif + duk_int_t input_line; + + /* Use temporaries and update lex_ctx only when finished. */ + input_line = lex_ctx->input_line; + p = lex_ctx->input + lex_ctx->input_offset; + p_end = lex_ctx->input + lex_ctx->input_length; + + cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes); + cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE; + + for (; cp != cp_end; cp++) { + cp->offset = (duk_size_t) (p - lex_ctx->input); + cp->line = input_line; + + /* XXX: potential issue with signed pointers, p_end < p. */ + if (DUK_UNLIKELY(p >= p_end)) { + /* If input_offset were assigned a negative value, it would + * result in a large positive value. Most likely it would be + * larger than input_length and be caught here. In any case + * no memory unsafe behavior would happen. + */ + cp->codepoint = -1; + continue; + } + + x = (duk_ucodepoint_t) (*p++); + + /* Fast path. */ + + if (DUK_LIKELY(x < 0x80UL)) { + DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */ + if (DUK_UNLIKELY(x <= 0x000dUL)) { + if ((x == 0x000aUL) || + ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) { + /* lookup for 0x000a above assumes shortest encoding now */ + + /* E5 Section 7.3, treat the following as newlines: + * LF + * CR [not followed by LF] + * LS + * PS + * + * For CR LF, CR is ignored if it is followed by LF, and the LF will bump + * the line number. + */ + input_line++; + } + } + + cp->codepoint = (duk_codepoint_t) x; + continue; + } + + /* Slow path. */ + + if (x < 0xc0UL) { + /* 10xx xxxx -> invalid */ + goto error_encoding; + } else if (x < 0xe0UL) { + /* 110x xxxx 10xx xxxx */ + contlen = 1; +#ifdef DUK_USE_STRICT_UTF8_SOURCE + mincp = 0x80UL; +#endif + x = x & 0x1fUL; + } else if (x < 0xf0UL) { + /* 1110 xxxx 10xx xxxx 10xx xxxx */ + contlen = 2; +#ifdef DUK_USE_STRICT_UTF8_SOURCE + mincp = 0x800UL; +#endif + x = x & 0x0fUL; + } else if (x < 0xf8UL) { + /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */ + contlen = 3; +#ifdef DUK_USE_STRICT_UTF8_SOURCE + mincp = 0x10000UL; +#endif + x = x & 0x07UL; + } else { + /* no point in supporting encodings of 5 or more bytes */ + goto error_encoding; + } + + DUK_ASSERT(p_end >= p); + if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) { + goto error_clipped; + } + + while (contlen > 0) { + duk_small_uint_t y; + y = *p++; + if ((y & 0xc0U) != 0x80U) { + /* check that byte has the form 10xx xxxx */ + goto error_encoding; + } + x = x << 6; + x += y & 0x3fUL; + contlen--; + } + + /* check final character validity */ + + if (x > 0x10ffffUL) { + goto error_encoding; + } +#ifdef DUK_USE_STRICT_UTF8_SOURCE + if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) { + goto error_encoding; + } +#endif + + DUK_ASSERT(x != 0x000aUL && x != 0x000dUL); + if ((x == 0x2028UL) || (x == 0x2029UL)) { + input_line++; + } + + cp->codepoint = (duk_codepoint_t) x; + } + + lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input); + lex_ctx->input_line = input_line; + return; + + error_clipped: /* clipped codepoint */ + error_encoding: /* invalid codepoint encoding or codepoint */ + lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input); + lex_ctx->input_line = input_line; + + DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "char decode failed"); +} + +DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) { + duk_small_uint_t used_bytes, avail_bytes; + + DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */ + DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))); + DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer); + DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE); + DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint)); + + /* Zero 'count' is also allowed to make call sites easier. + * Arithmetic in bytes generates better code in GCC. + */ + + lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */ + used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer); + avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes; + if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) { + /* Not enough data to provide a full window, so "scroll" window to + * start of buffer and fill up the rest. + */ + DUK_MEMMOVE((void *) lex_ctx->buffer, + (const void *) lex_ctx->window, + (size_t) avail_bytes); + lex_ctx->window = lex_ctx->buffer; + duk__fill_lexer_buffer(lex_ctx, avail_bytes); + } +} + +DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) { + lex_ctx->window = lex_ctx->buffer; + duk__fill_lexer_buffer(lex_ctx, 0); +} +#else /* DUK_USE_LEXER_SLIDING_WINDOW */ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) { - /* attempting to reduce size of 'len' and/or 'i' resulted in larger code */ - duk_codepoint_t x; - duk_small_int_t len; - duk_small_int_t i; + duk_ucodepoint_t x; + duk_small_uint_t len; + duk_small_uint_t i; const duk_uint8_t *p; #ifdef DUK_USE_STRICT_UTF8_SOURCE - duk_codepoint_t mincp; + duk_ucodepoint_t mincp; #endif duk_size_t input_offset; @@ -65587,36 +71939,63 @@ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) { } p = lex_ctx->input + input_offset; - x = (int) *p++; + x = (duk_ucodepoint_t) (*p); - if (x < 0x80L) { + if (DUK_LIKELY(x < 0x80UL)) { /* 0xxx xxxx -> fast path */ - len = 1; - goto fastpath; - } else if (x < 0xc0L) { + + /* input offset tracking */ + lex_ctx->input_offset++; + + DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */ + if (DUK_UNLIKELY(x <= 0x000dUL)) { + if ((x == 0x000aUL) || + ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length || + lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) { + /* lookup for 0x000a above assumes shortest encoding now */ + + /* E5 Section 7.3, treat the following as newlines: + * LF + * CR [not followed by LF] + * LS + * PS + * + * For CR LF, CR is ignored if it is followed by LF, and the LF will bump + * the line number. + */ + lex_ctx->input_line++; + } + } + + return (duk_codepoint_t) x; + } + + /* Slow path. */ + + if (x < 0xc0UL) { /* 10xx xxxx -> invalid */ goto error_encoding; - } else if (x < 0xe0L) { + } else if (x < 0xe0UL) { /* 110x xxxx 10xx xxxx */ len = 2; #ifdef DUK_USE_STRICT_UTF8_SOURCE - mincp = 0x80L; + mincp = 0x80UL; #endif - x = x & 0x1fL; - } else if (x < 0xf0L) { + x = x & 0x1fUL; + } else if (x < 0xf0UL) { /* 1110 xxxx 10xx xxxx 10xx xxxx */ len = 3; #ifdef DUK_USE_STRICT_UTF8_SOURCE - mincp = 0x800L; + mincp = 0x800UL; #endif - x = x & 0x0fL; - } else if (x < 0xf8L) { + x = x & 0x0fUL; + } else if (x < 0xf8UL) { /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */ len = 4; #ifdef DUK_USE_STRICT_UTF8_SOURCE - mincp = 0x10000L; + mincp = 0x10000UL; #endif - x = x & 0x07; + x = x & 0x07UL; } else { /* no point in supporting encodings of 5 or more bytes */ goto error_encoding; @@ -65627,54 +72006,39 @@ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) { goto error_clipped; } + p++; for (i = 1; i < len; i++) { - duk_small_int_t y = *p++; - if ((y & 0xc0) != 0x80) { + duk_small_uint_t y; + y = *p++; + if ((y & 0xc0U) != 0x80U) { /* check that byte has the form 10xx xxxx */ goto error_encoding; } x = x << 6; - x += y & 0x3f; + x += y & 0x3fUL; } /* check final character validity */ - if (x > 0x10ffffL) { + if (x > 0x10ffffUL) { goto error_encoding; } #ifdef DUK_USE_STRICT_UTF8_SOURCE - if (x < mincp || (x >= 0xd800L && x <= 0xdfffL) || x == 0xfffeL) { + if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) { goto error_encoding; } #endif - /* fall through */ - - fastpath: /* input offset tracking */ lex_ctx->input_offset += len; /* line tracking */ - if ((x == 0x000aL) || - ((x == 0x000dL) && (lex_ctx->input_offset >= lex_ctx->input_length || - lex_ctx->input[lex_ctx->input_offset] != 0x000aL)) || - (x == 0x2028L) || - (x == 0x2029L)) { - /* lookup for 0x000a above assumes shortest encoding now */ - - /* E5 Section 7.3, treat the following as newlines: - * LF - * CR [not followed by LF] - * LS - * PS - * - * For CR LF, CR is ignored if it is followed by LF, and the LF will bump - * the line number. - */ + DUK_ASSERT(x != 0x000aUL && x != 0x000dUL); + if ((x == 0x2028UL) || (x == 0x2029UL)) { lex_ctx->input_line++; } - return x; + return (duk_codepoint_t) x; error_clipped: /* clipped codepoint */ error_encoding: /* invalid codepoint encoding or codepoint */ @@ -65682,53 +72046,34 @@ DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) { return 0; } -/* - * Advance lookup window by N characters. Also used to fill the window - * after position is changed (call with count == DUK_LEXER_WINDOW_SIZE). - * - * XXX: A lot of copying now, perhaps change to circular array or at - * least use memcpy(). For memcpy(), putting all elements of the - * window (code point, offset, line) into a struct would allow one - * memcpy() to slide the window, instead of three separate copys. - */ +DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) { + duk_small_uint_t keep_bytes; + duk_lexer_codepoint *cp, *cp_end; -DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_int_t count) { - duk_small_int_t i, n; + DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */ + DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))); - DUK_ASSERT(count >= 0 && count <= DUK_LEXER_WINDOW_SIZE); + /* Zero 'count' is also allowed to make call sites easier. */ - /* Without this check, gcc -O4 will complain the following for the - * first for-loop below: - * - * duk_lexer.c:301:19: error: array subscript is above array bounds [-Werror=array-bounds] - * - * Check for range explicitly; this also protects against legitimate - * internal errors and avoids memory unsafe behavior in such cases. - */ - if (DUK_UNLIKELY(!(count >= 0 && count <= DUK_LEXER_WINDOW_SIZE))) { - DUK_D(DUK_DPRINT("invalid count: %ld, should not happen", (long) count)); - DUK_ERROR(lex_ctx->thr, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR); - return; /* never here */ - } + 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); - if (count == 0) { - /* allowing zero count makes some special caller flows easier */ - return; - } - - n = DUK_LEXER_WINDOW_SIZE - count; - for (i = 0; i < n; i++) { - lex_ctx->offsets[i] = lex_ctx->offsets[i + count]; - lex_ctx->lines[i] = lex_ctx->lines[i + count]; - lex_ctx->window[i] = lex_ctx->window[i + count]; + cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes); + cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE; + for (; cp != cp_end; cp++) { + cp->offset = lex_ctx->input_offset; + cp->line = lex_ctx->input_line; + cp->codepoint = duk__read_char(lex_ctx); } +} - for (; i < DUK_LEXER_WINDOW_SIZE; i++) { - lex_ctx->offsets[i] = lex_ctx->input_offset; - lex_ctx->lines[i] = lex_ctx->input_line; - lex_ctx->window[i] = duk__read_char(lex_ctx); - } +DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) { + /* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */ + duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */ } +#endif /* DUK_USE_LEXER_SLIDING_WINDOW */ /* * (Re)initialize the temporary byte buffer. May be called extra times @@ -65736,12 +72081,14 @@ DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_int_t count) */ DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) { - if (DUK_HBUFFER_DYNAMIC_GET_ALLOC_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) { - /* Resize (zero) without realloc. */ - DUK_HBUFFER_DYNAMIC_SET_SIZE(lex_ctx->buf, 0); + /* Reuse buffer as is unless buffer has grown large. */ + if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) { + /* Keep current size */ } else { - duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, 0, DUK_LEXER_TEMP_BUF_LIMIT); + duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT); } + + DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf); } /* @@ -65763,7 +72110,7 @@ DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) { DUK_ASSERT(x >= 0 && x <= 0x10ffff); - duk_hbuffer_append_cesu8(lex_ctx->thr, lex_ctx->buf, (duk_ucodepoint_t) x); + DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x); } /* @@ -65776,8 +72123,7 @@ DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx); - duk_dup(ctx, lex_ctx->buf_idx); - duk_to_string(ctx, -1); + DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw); duk_replace(ctx, valstack_idx); } @@ -65790,6 +72136,9 @@ DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) { DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx)); #ifdef DUK_USE_EXPLICIT_NULL_INIT +#if defined(DUK_USE_LEXER_SLIDING_WINDOW) + lex_ctx->window = NULL; +#endif lex_ctx->thr = NULL; lex_ctx->input = NULL; lex_ctx->buf = NULL; @@ -65807,7 +72156,7 @@ DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt DUK_ASSERT(pt->line >= 1); lex_ctx->input_offset = pt->offset; lex_ctx->input_line = pt->line; - duk__advance_chars(lex_ctx, DUK_LEXER_WINDOW_SIZE); /* fill window */ + duk__init_lexer_window(lex_ctx); } /* @@ -65843,43 +72192,33 @@ DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) { DUK_LOCAL duk_codepoint_t duk__decode_hexesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) { /* validation performed by duk__hexval */ - return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset]) << 4) | - (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1])); + return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 4) | + (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint)); } DUK_LOCAL duk_codepoint_t duk__decode_uniesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) { /* validation performed by duk__hexval */ - return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset]) << 12) | - (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1]) << 8) | - (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2]) << 4) | - (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3])); -} - -/* - * Eat input characters until first character of window is not - * a white space (may be -1 if EOF encountered). - */ -DUK_LOCAL void duk__eat_whitespace(duk_lexer_ctx *lex_ctx) { - /* guaranteed to finish, as EOF (-1) is not a whitespace */ - while (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) { - DUK__ADVANCE(lex_ctx, 1); - } + return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 12) | + (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint) << 8) | + (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2].codepoint) << 4) | + (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3].codepoint)); } /* * Parse Ecmascript source InputElementDiv or InputElementRegExp - * (E5 Section 7). + * (E5 Section 7), skipping whitespace, comments, and line terminators. * * Possible results are: * (1) a token - * (2) a line terminator - * (3) a comment + * (2) a line terminator (skipped) + * (3) a comment (skipped) * (4) EOF * * White space is automatically skipped from the current position (but * not after the input element). If input has already ended, returns * DUK_TOK_EOF indefinitely. If a parse error occurs, uses an DUK_ERROR() * macro call (and hence a longjmp through current heap longjmp context). + * Comments and line terminator tokens are automatically skipped. * * The input element being matched is determined by regexp_mode; if set, * parses a InputElementRegExp, otherwise a InputElementDiv. The @@ -65924,43 +72263,46 @@ DUK_LOCAL void duk__eat_whitespace(duk_lexer_ctx *lex_ctx) { * number of escapes. Directive detection can then check that the * number of escapes is zero. * - * * Comments are expressed as DUK_TOK_COMMENT tokens, with the type - * (single- or multi-line) and contents of the comments lost. - * Furthermore, multi-line comments with one or more internal - * LineTerminator are treated as DUK_TOK_LINETERM to comply with - * automatic semicolon insertion and to avoid complicating the - * tokenization process. See E5 Section 7.4. + * * Multi-line comments with one or more internal LineTerminator are + * treated like a line terminator to comply with automatic semicolon + * insertion. */ -DUK_LOCAL -void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, - duk_token *out_token, - duk_bool_t strict_mode, - duk_bool_t regexp_mode) { - duk_codepoint_t x, y; /* temporaries, must be signed and 32-bit to hold Unicode code points */ +DUK_INTERNAL +void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, + duk_token *out_token, + duk_bool_t strict_mode, + duk_bool_t regexp_mode) { + duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */ duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end, * init is unnecessary but suppresses "may be used uninitialized" warnings. */ + duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */ if (++lex_ctx->token_count >= lex_ctx->token_limit) { DUK_ERROR(lex_ctx->thr, DUK_ERR_RANGE_ERROR, "token limit"); return; /* unreachable */ } - duk__eat_whitespace(lex_ctx); - out_token->t = DUK_TOK_EOF; out_token->t_nores = -1; /* marker: copy t if not changed */ +#if 0 /* not necessary to init, disabled for faster parsing */ out_token->num = DUK_DOUBLE_NAN; out_token->str1 = NULL; out_token->str2 = NULL; +#endif out_token->num_escapes = 0; - out_token->start_line = lex_ctx->lines[0]; - out_token->start_offset = lex_ctx->offsets[0]; /* out_token->lineterm set by caller */ + /* This would be nice, but parsing is faster without resetting the + * value slots. The only side effect is that references to temporary + * string values may linger until lexing is finished; they're then + * freed normally. + */ +#if 0 duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx); +#endif /* 'advtok' indicates how much to advance and which token id to assign * at the end. This shared functionality minimizes code size. All @@ -65982,57 +72324,66 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, * The order does not matter as long as the longest match is * always correctly identified. There are order dependencies * in the clauses, so it's not trivial to convert to a switch. - * - * XXX: This is quite inefficient. Maybe change to a switch - * statement which handles all single character cases and then - * use a followup if-else chain? Switch matches need to use - * goto to bypass the if-else chain. */ + restart_lineupdate: + out_token->start_line = lex_ctx->window[0].line; + + restart: + out_token->start_offset = lex_ctx->window[0].offset; + x = DUK__L0(); - y = DUK__L1(); - if (x == '/') { - if (y == '/') { + switch (x) { + case DUK_ASC_SPACE: + case DUK_ASC_HT: /* fast paths for space and tab */ + DUK__ADVANCECHARS(lex_ctx, 1); + goto restart; + case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */ + DUK__ADVANCECHARS(lex_ctx, 1); + got_lineterm = 1; + goto restart_lineupdate; + case DUK_ASC_SLASH: /* '/' */ + if (DUK__L1() == '/') { /* * E5 Section 7.4, allow SourceCharacter (which is any 16-bit * code point). */ - /* DUK__ADVANCE(lex_ctx, 2) would be correct here, but it unnecessary */ + /* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but it unnecessary */ for (;;) { x = DUK__L0(); if (x < 0 || duk_unicode_is_line_terminator(x)) { break; } - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); } - advtok = DUK__ADVTOK(0, DUK_TOK_COMMENT); - } else if (y == '*') { + goto restart; /* line terminator will be handled on next round */ + } else if (DUK__L1() == '*') { /* * E5 Section 7.4. If the multi-line comment contains a newline, - * it is treated like a single DUK_TOK_LINETERM to facilitate - * automatic semicolon insertion. + * it is treated like a single line terminator for automatic + * semicolon insertion. */ duk_bool_t last_asterisk = 0; - advtok = DUK__ADVTOK(0, DUK_TOK_COMMENT); - DUK__ADVANCE(lex_ctx, 2); + DUK__ADVANCECHARS(lex_ctx, 2); for (;;) { x = DUK__L0(); if (x < 0) { DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "eof while parsing multiline comment"); } - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); if (last_asterisk && x == '/') { break; } if (duk_unicode_is_line_terminator(x)) { - advtok = DUK__ADVTOK(0, DUK_TOK_LINETERM); + got_lineterm = 1; } last_asterisk = (x == '*'); } + goto restart_lineupdate; } else if (regexp_mode) { #ifdef DUK_USE_REGEXP_SUPPORT /* @@ -66096,7 +72447,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, DUK__INITBUFFER(lex_ctx); for (;;) { - DUK__ADVANCE(lex_ctx, 1); /* skip opening slash on first loop */ + DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */ x = DUK__L0(); if (x < 0 || duk_unicode_is_line_terminator(x)) { DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, @@ -66105,7 +72456,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, x = DUK__L0(); /* re-read to avoid spill / fetch */ if (state == 0) { if (x == '/') { - DUK__ADVANCE(lex_ctx, 1); /* eat closing slash */ + DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */ break; } else if (x == '\\') { state = 1; @@ -66138,7 +72489,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, } x = DUK__L0(); /* re-read to avoid spill / fetch */ DUK__APPENDBUFFER(lex_ctx, x); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); } duk__internbuffer(lex_ctx, lex_ctx->slot2_idx); out_token->str2 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx); @@ -66151,139 +72502,325 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, #else DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "regexp support disabled"); #endif - } else if (y == '=') { + } else if (DUK__L1() == '=') { /* "/=" and not in regexp mode */ advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ); } else { /* "/" and not in regexp mode */ advtok = DUK__ADVTOK(1, DUK_TOK_DIV); } - } else if (x == '{') { + break; + case DUK_ASC_LCURLY: /* '{' */ advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY); - } else if (x == '}') { + break; + case DUK_ASC_RCURLY: /* '}' */ advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY); - } else if (x == '(') { + break; + case DUK_ASC_LPAREN: /* '(' */ advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN); - } else if (x == ')') { + break; + case DUK_ASC_RPAREN: /* ')' */ advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN); - } else if (x == '[') { + break; + case DUK_ASC_LBRACKET: /* '[' */ advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET); - } else if (x == ']') { + break; + case DUK_ASC_RBRACKET: /* ']' */ advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET); - } else if (x == '.' && !DUK__ISDIGIT(y)) { - /* Note: period followed by a digit can only start DecimalLiteral (captured below) */ + break; + case DUK_ASC_PERIOD: /* '.' */ + if (DUK__ISDIGIT(DUK__L1())) { + /* Period followed by a digit can only start DecimalLiteral + * (handled in slow path). We could jump straight into the + * DecimalLiteral handling but should avoid goto to inside + * a block. + */ + goto slow_path; + } advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD); - } else if (x == ';') { + break; + case DUK_ASC_SEMICOLON: /* ';' */ advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON); - } else if (x == ',') { + break; + case DUK_ASC_COMMA: /* ',' */ advtok = DUK__ADVTOK(1, DUK_TOK_COMMA); - } else if (x == '<') { - if (y == '<' && DUK__L2() == '=') { + break; + case DUK_ASC_LANGLE: /* '<' */ + if (DUK__L1() == '<' && DUK__L2() == '=') { advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_LE); - } else if (y == '<') { + } else if (DUK__L1() == '<') { advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT); } else { advtok = DUK__ADVTOK(1, DUK_TOK_LT); } - } else if (x == '>') { - if (y == '>' && DUK__L2() == '>' && DUK__L3() == '=') { + break; + case DUK_ASC_RANGLE: /* '>' */ + if (DUK__L1() == '>' && DUK__L2() == '>' && DUK__L3() == '=') { advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ); - } else if (y == '>' && DUK__L2() == '>') { + } else if (DUK__L1() == '>' && DUK__L2() == '>') { advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT); - } else if (y == '>' && DUK__L2() == '=') { + } else if (DUK__L1() == '>' && DUK__L2() == '=') { advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_GE); - } else if (y == '>') { + } else if (DUK__L1() == '>') { advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT); } else { advtok = DUK__ADVTOK(1, DUK_TOK_GT); } - } else if (x == '=') { - if (y == '=' && DUK__L2() == '=') { + break; + case DUK_ASC_EQUALS: /* '=' */ + if (DUK__L1() == '=' && DUK__L2() == '=') { advtok = DUK__ADVTOK(3, DUK_TOK_SEQ); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN); } - } else if (x == '!') { - if (y == '=' && DUK__L2() == '=') { + break; + case DUK_ASC_EXCLAMATION: /* '!' */ + if (DUK__L1() == '=' && DUK__L2() == '=') { advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_NEQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_LNOT); } - } else if (x == '+') { - if (y == '+') { + break; + case DUK_ASC_PLUS: /* '+' */ + if (DUK__L1() == '+') { advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_ADD); } - } else if (x == '-') { - if (y == '-') { + break; + case DUK_ASC_MINUS: /* '-' */ + if (DUK__L1() == '-') { advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_SUB); } - } else if (x == '*') { - if (y == '=') { + break; + case DUK_ASC_STAR: /* '*' */ + if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_MUL); } - } else if (x == '%') { - if (y == '=') { + break; + case DUK_ASC_PERCENT: /* '%' */ + if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_MOD); } - } else if (x == '&') { - if (y == '&') { + break; + case DUK_ASC_AMP: /* '&' */ + if (DUK__L1() == '&') { advtok = DUK__ADVTOK(2, DUK_TOK_LAND); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_BAND); } - } else if (x == '|') { - if (y == '|') { + break; + case DUK_ASC_PIPE: /* '|' */ + if (DUK__L1() == '|') { advtok = DUK__ADVTOK(2, DUK_TOK_LOR); - } else if (y == '=') { + } else if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_BOR); } - } else if (x == '^') { - if (y == '=') { + break; + case DUK_ASC_CARET: /* '^' */ + if (DUK__L1() == '=') { advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ); } else { advtok = DUK__ADVTOK(1, DUK_TOK_BXOR); } - } else if (x == '~') { + break; + case DUK_ASC_TILDE: /* '~' */ advtok = DUK__ADVTOK(1, DUK_TOK_BNOT); - } else if (x == '?') { + break; + case DUK_ASC_QUESTION: /* '?' */ advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION); - } else if (x == ':') { + break; + case DUK_ASC_COLON: /* ':' */ advtok = DUK__ADVTOK(1, DUK_TOK_COLON); - } else if (duk_unicode_is_line_terminator(x)) { - if (x == 0x000d && y == 0x000a) { + break; + case DUK_ASC_DOUBLEQUOTE: /* '"' */ + case DUK_ASC_SINGLEQUOTE: { /* '\'' */ + duk_small_int_t quote = x; /* Note: duk_uint8_t type yields larger code */ + duk_small_int_t adv; + + DUK__INITBUFFER(lex_ctx); + for (;;) { + DUK__ADVANCECHARS(lex_ctx, 1); /* eat opening quote on first loop */ + x = DUK__L0(); + if (x < 0 || duk_unicode_is_line_terminator(x)) { + DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, + "eof or line terminator while parsing string literal"); + } + if (x == quote) { + DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */ + break; + } + if (x == '\\') { + /* DUK__L0 -> '\' char + * DUK__L1 ... DUK__L5 -> more lookup + */ + + x = DUK__L1(); + + /* How much to advance before next loop; note that next loop + * will advance by 1 anyway, so -1 from the total escape + * length (e.g. len('\uXXXX') - 1 = 6 - 1). As a default, + * 1 is good. + */ + adv = 2 - 1; /* note: long live range */ + + if (x < 0) { + DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, + "eof while parsing string literal"); + } + if (duk_unicode_is_line_terminator(x)) { + /* line continuation */ + if (x == 0x000d && DUK__L2() == 0x000a) { + /* CR LF again a special case */ + adv = 3 - 1; + } + } else if (x == '\'') { + DUK__APPENDBUFFER(lex_ctx, 0x0027); + } else if (x == '"') { + DUK__APPENDBUFFER(lex_ctx, 0x0022); + } else if (x == '\\') { + DUK__APPENDBUFFER(lex_ctx, 0x005c); + } else if (x == 'b') { + DUK__APPENDBUFFER(lex_ctx, 0x0008); + } else if (x == 'f') { + DUK__APPENDBUFFER(lex_ctx, 0x000c); + } else if (x == 'n') { + DUK__APPENDBUFFER(lex_ctx, 0x000a); + } else if (x == 'r') { + DUK__APPENDBUFFER(lex_ctx, 0x000d); + } else if (x == 't') { + DUK__APPENDBUFFER(lex_ctx, 0x0009); + } else if (x == 'v') { + DUK__APPENDBUFFER(lex_ctx, 0x000b); + } else if (x == 'x') { + adv = 4 - 1; + DUK__APPENDBUFFER(lex_ctx, duk__decode_hexesc_from_window(lex_ctx, 2)); + } else if (x == 'u') { + adv = 6 - 1; + DUK__APPENDBUFFER(lex_ctx, duk__decode_uniesc_from_window(lex_ctx, 2)); + } else if (DUK__ISDIGIT(x)) { + duk_codepoint_t ch = 0; /* initialized to avoid warnings of unused var */ + + /* + * Octal escape or zero escape: + * \0 (lookahead not DecimalDigit) + * \1 ... \7 (lookahead not DecimalDigit) + * \ZeroToThree OctalDigit (lookahead not DecimalDigit) + * \FourToSeven OctalDigit (no lookahead restrictions) + * \ZeroToThree OctalDigit OctalDigit (no lookahead restrictions) + * + * Zero escape is part of the standard syntax. Octal escapes are + * defined in E5 Section B.1.2, and are only allowed in non-strict mode. + * Any other productions starting with a decimal digit are invalid. + */ + + if (x == '0' && !DUK__ISDIGIT(DUK__L2())) { + /* Zero escape (also allowed in non-strict mode) */ + ch = 0; + /* adv = 2 - 1 default OK */ +#ifdef DUK_USE_OCTAL_SUPPORT + } else if (strict_mode) { + /* No other escape beginning with a digit in strict mode */ + DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, + "invalid escape while parsing string literal"); + } else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(DUK__L2()) && DUK__ISOCTDIGIT(DUK__L3())) { + /* Three digit octal escape, digits validated. */ + adv = 4 - 1; + ch = (duk__hexval(lex_ctx, x) << 6) + + (duk__hexval(lex_ctx, DUK__L2()) << 3) + + duk__hexval(lex_ctx, DUK__L3()); + } else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) && + DUK__ISOCTDIGIT(DUK__L2())) { + /* Two digit octal escape, digits validated. + * + * The if-condition is a bit tricky. We could catch e.g. + * '\039' in the three-digit escape and fail it there (by + * validating the digits), but we want to avoid extra + * additional validation code. + */ + adv = 3 - 1; + ch = (duk__hexval(lex_ctx, x) << 3) + + duk__hexval(lex_ctx, DUK__L2()); + } else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(DUK__L2())) { + /* One digit octal escape, digit validated. */ + /* adv = 2 default OK */ + ch = duk__hexval(lex_ctx, x); +#else + /* fall through to error */ +#endif + } else { + DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, + "invalid escape while parsing string literal"); + } + + DUK__APPENDBUFFER(lex_ctx, ch); + } else { + /* escaped NonEscapeCharacter */ + DUK__APPENDBUFFER(lex_ctx, x); + } + DUK__ADVANCECHARS(lex_ctx, adv); + + /* Track number of escapes; count not really needed but directive + * prologues need to detect whether there were any escapes or line + * continuations or not. + */ + out_token->num_escapes++; + } else { + /* part of string */ + DUK__APPENDBUFFER(lex_ctx, x); + } + } + + duk__internbuffer(lex_ctx, lex_ctx->slot1_idx); + out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); + + DUK__INITBUFFER(lex_ctx); /* free some memory */ + + advtok = DUK__ADVTOK(0, DUK_TOK_STRING); + break; + } + default: + goto slow_path; + } /* switch */ + + goto skip_slow_path; + + slow_path: + if (duk_unicode_is_line_terminator(x)) { + if (x == 0x000d && DUK__L1() == 0x000a) { /* * E5 Section 7.3: CR LF is detected as a single line terminator for * line numbers. Here we also detect it as a single line terminator * token. */ - advtok = DUK__ADVTOK(2, DUK_TOK_LINETERM); + DUK__ADVANCECHARS(lex_ctx, 2); } else { - advtok = DUK__ADVTOK(1, DUK_TOK_LINETERM); + DUK__ADVANCECHARS(lex_ctx, 1); } + got_lineterm = 1; + goto restart_lineupdate; } else if (duk_unicode_is_identifier_start(x) || x == '\\') { /* * Parse an identifier and then check whether it is: @@ -66340,7 +72877,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, "invalid unicode escaped character while parsing identifier"); } DUK__APPENDBUFFER(lex_ctx, ch); - DUK__ADVANCE(lex_ctx, 6); + DUK__ADVANCECHARS(lex_ctx, 6); /* Track number of escapes: necessary for proper keyword * detection. @@ -66356,7 +72893,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, break; } DUK__APPENDBUFFER(lex_ctx, DUK__L0()); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); } first = 0; } @@ -66435,12 +72972,14 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, * 3=after exp and exp sign */ duk_small_uint_t s2n_flags; + duk_codepoint_t y; DUK__INITBUFFER(lex_ctx); + y = DUK__L1(); if (x == '0' && (y == 'x' || y == 'X')) { DUK__APPENDBUFFER(lex_ctx, x); DUK__APPENDBUFFER(lex_ctx, y); - DUK__ADVANCE(lex_ctx, 2); + DUK__ADVANCECHARS(lex_ctx, 2); int_only = 1; allow_hex = 1; #ifdef DUK_USE_OCTAL_SUPPORT @@ -66453,7 +72992,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, */ DUK__APPENDBUFFER(lex_ctx, x); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); int_only = 1; #endif } @@ -66493,7 +73032,7 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, break; } DUK__APPENDBUFFER(lex_ctx, x); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); } /* XXX: better coercion */ @@ -66528,215 +73067,32 @@ void duk__parse_input_element_raw(duk_lexer_ctx *lex_ctx, out_token->num = val; advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER); - } else if (x == '"' || x == '\'') { - duk_small_int_t quote = x; /* Note: duk_uint8_t type yields larger code */ - duk_small_int_t adv; - - DUK__INITBUFFER(lex_ctx); - for (;;) { - DUK__ADVANCE(lex_ctx, 1); /* eat opening quote on first loop */ - x = DUK__L0(); - if (x < 0 || duk_unicode_is_line_terminator(x)) { - DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, - "eof or line terminator while parsing string literal"); - } - if (x == quote) { - DUK__ADVANCE(lex_ctx, 1); /* eat closing quote */ - break; - } - if (x == '\\') { - /* DUK__L0 -> '\' char - * DUK__L1 ... DUK__L5 -> more lookup - */ - - x = DUK__L1(); - y = DUK__L2(); - - /* How much to advance before next loop; note that next loop - * will advance by 1 anyway, so -1 from the total escape - * length (e.g. len('\uXXXX') - 1 = 6 - 1). As a default, - * 1 is good. - */ - adv = 2 - 1; /* note: long live range */ - - if (x < 0) { - DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, - "eof while parsing string literal"); - } - if (duk_unicode_is_line_terminator(x)) { - /* line continuation */ - if (x == 0x000d && y == 0x000a) { - /* CR LF again a special case */ - adv = 3 - 1; - } - } else if (x == '\'') { - DUK__APPENDBUFFER(lex_ctx, 0x0027); - } else if (x == '"') { - DUK__APPENDBUFFER(lex_ctx, 0x0022); - } else if (x == '\\') { - DUK__APPENDBUFFER(lex_ctx, 0x005c); - } else if (x == 'b') { - DUK__APPENDBUFFER(lex_ctx, 0x0008); - } else if (x == 'f') { - DUK__APPENDBUFFER(lex_ctx, 0x000c); - } else if (x == 'n') { - DUK__APPENDBUFFER(lex_ctx, 0x000a); - } else if (x == 'r') { - DUK__APPENDBUFFER(lex_ctx, 0x000d); - } else if (x == 't') { - DUK__APPENDBUFFER(lex_ctx, 0x0009); - } else if (x == 'v') { - DUK__APPENDBUFFER(lex_ctx, 0x000b); - } else if (x == 'x') { - adv = 4 - 1; - DUK__APPENDBUFFER(lex_ctx, duk__decode_hexesc_from_window(lex_ctx, 2)); - } else if (x == 'u') { - adv = 6 - 1; - DUK__APPENDBUFFER(lex_ctx, duk__decode_uniesc_from_window(lex_ctx, 2)); - } else if (DUK__ISDIGIT(x)) { - duk_codepoint_t ch = 0; /* initialized to avoid warnings of unused var */ - - /* - * Octal escape or zero escape: - * \0 (lookahead not DecimalDigit) - * \1 ... \7 (lookahead not DecimalDigit) - * \ZeroToThree OctalDigit (lookahead not DecimalDigit) - * \FourToSeven OctalDigit (no lookahead restrictions) - * \ZeroToThree OctalDigit OctalDigit (no lookahead restrictions) - * - * Zero escape is part of the standard syntax. Octal escapes are - * defined in E5 Section B.1.2, and are only allowed in non-strict mode. - * Any other productions starting with a decimal digit are invalid. - */ - - if (x == '0' && !DUK__ISDIGIT(y)) { - /* Zero escape (also allowed in non-strict mode) */ - ch = 0; - /* adv = 2 - 1 default OK */ -#ifdef DUK_USE_OCTAL_SUPPORT - } else if (strict_mode) { - /* No other escape beginning with a digit in strict mode */ - DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, - "invalid escape while parsing string literal"); - } else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(y) && DUK__ISOCTDIGIT(DUK__L3())) { - /* Three digit octal escape, digits validated. */ - adv = 4 - 1; - ch = (duk__hexval(lex_ctx, x) << 6) + - (duk__hexval(lex_ctx, y) << 3) + - duk__hexval(lex_ctx, DUK__L3()); - } else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) && - DUK__ISOCTDIGIT(y)) { - /* Two digit octal escape, digits validated. - * - * The if-condition is a bit tricky. We could catch e.g. - * '\039' in the three-digit escape and fail it there (by - * validating the digits), but we want to avoid extra - * additional validation code. - */ - adv = 3 - 1; - ch = (duk__hexval(lex_ctx, x) << 3) + - duk__hexval(lex_ctx, y); - } else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(y)) { - /* One digit octal escape, digit validated. */ - /* adv = 2 default OK */ - ch = duk__hexval(lex_ctx, x); -#else - /* fall through to error */ -#endif - } else { - DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, - "invalid escape while parsing string literal"); - } - - DUK__APPENDBUFFER(lex_ctx, ch); - } else { - /* escaped NonEscapeCharacter */ - DUK__APPENDBUFFER(lex_ctx, x); - } - DUK__ADVANCE(lex_ctx, adv); - - /* Track number of escapes; count not really needed but directive - * prologues need to detect whether there were any escapes or line - * continuations or not. - */ - out_token->num_escapes++; - } else { - /* part of string */ - DUK__APPENDBUFFER(lex_ctx, x); - } - } - - duk__internbuffer(lex_ctx, lex_ctx->slot1_idx); - out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); - - DUK__INITBUFFER(lex_ctx); /* free some memory */ - - advtok = DUK__ADVTOK(0, DUK_TOK_STRING); + } else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) { + DUK__ADVANCECHARS(lex_ctx, 1); + goto restart; } else if (x < 0) { advtok = DUK__ADVTOK(0, DUK_TOK_EOF); } else { DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "error parsing token"); } + skip_slow_path: /* * Shared exit path */ - DUK__ADVANCE(lex_ctx, advtok >> 8); + DUK__ADVANCEBYTES(lex_ctx, advtok >> 8); out_token->t = advtok & 0xff; if (out_token->t_nores < 0) { out_token->t_nores = out_token->t; } -} - -/* - * Tokenize input until a non-whitespace, non-lineterm token is found. - * Note in the output token whether a lineterm token preceded the starting - * point (inclusive) and the result token. This information is needed for - * automatic semicolon insertion. - * - * Future work: - * - * * Merge with duk__parse_input_element_raw() because only this function is - * called in practice. - */ - -/* XXX: change mode flags into one flags argument? */ - -DUK_INTERNAL -void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx, - duk_token *out_token, - duk_bool_t strict_mode, - duk_bool_t regexp_mode) { - duk_small_int_t tok; - duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */ - - for (;;) { - duk__parse_input_element_raw(lex_ctx, out_token, strict_mode, regexp_mode); - tok = out_token->t; - - DUK_DDD(DUK_DDDPRINT("RAWTOKEN: %ld (line %ld)", - (long) tok, (long) out_token->start_line)); - - if (tok == DUK_TOK_COMMENT) { - /* single-line comment or multi-line comment without an internal lineterm */ - continue; - } else if (tok == DUK_TOK_LINETERM) { - /* lineterm or multi-line comment with an internal lineterm */ - got_lineterm = 1; - continue; - } else { - break; - } - } - out_token->lineterm = got_lineterm; /* Automatic semicolon insertion is allowed if a token is preceded * by line terminator(s), or terminates a statement list (right curly * or EOF). */ - if (got_lineterm || tok == DUK_TOK_RCURLY || tok == DUK_TOK_EOF) { + if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) { out_token->allow_auto_semi = 1; } else { out_token->allow_auto_semi = 0; @@ -66825,7 +73181,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token duk_uint_fast32_t val2 = DUK_RE_QUANTIFIER_INFINITE; duk_small_int_t digits = 0; for (;;) { - DUK__ADVANCE(lex_ctx, 1); /* eat '{' on entry */ + DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */ x = DUK__L0(); if (DUK__ISDIGIT(x)) { if (digits >= DUK__MAX_RE_QUANT_DIGITS) { @@ -66847,7 +73203,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token } out_token->qmin = val1; out_token->qmax = DUK_RE_QUANTIFIER_INFINITE; - DUK__ADVANCE(lex_ctx, 2); + DUK__ADVANCECHARS(lex_ctx, 2); break; } val2 = val1; @@ -66867,7 +73223,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token out_token->qmin = val1; out_token->qmax = val1; } - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); break; } else { DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, @@ -66876,7 +73232,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token } if (DUK__L0() == '?') { out_token->greedy = 0; - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); } else { out_token->greedy = 1; } @@ -66957,7 +73313,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token DUK_ERROR(lex_ctx->thr, DUK_ERR_SYNTAX_ERROR, "invalid regexp escape (decimal escape too long)"); } - DUK__ADVANCE(lex_ctx, 1); /* eat backslash on entry */ + DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */ x = DUK__L0(); if (!DUK__ISDIGIT(x)) { break; @@ -67047,7 +73403,7 @@ DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token * Shared exit path */ - DUK__ADVANCE(lex_ctx, advtok >> 8); + DUK__ADVANCEBYTES(lex_ctx, advtok >> 8); out_token->t = advtok & 0xff; } @@ -67099,7 +73455,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range for (;;) { x = DUK__L0(); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */ DUK_UNREF(ch); @@ -67132,7 +73488,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range */ x = DUK__L0(); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); if (x == 'b') { /* Note: '\b' in char class is different than outside (assertion), @@ -67152,7 +73508,7 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range ch = 0x000b; } else if (x == 'c') { x = DUK__L0(); - DUK__ADVANCE(lex_ctx, 1); + DUK__ADVANCECHARS(lex_ctx, 1); if ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')) { ch = (x % 32); @@ -67165,10 +73521,10 @@ DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range } } else if (x == 'x') { ch = duk__decode_hexesc_from_window(lex_ctx, 0); - DUK__ADVANCE(lex_ctx, 2); + DUK__ADVANCECHARS(lex_ctx, 2); } else if (x == 'u') { ch = duk__decode_uniesc_from_window(lex_ctx, 0); - DUK__ADVANCE(lex_ctx, 4); + DUK__ADVANCECHARS(lex_ctx, 4); } else if (x == 'd') { duk__emit_u16_direct_ranges(lex_ctx, gen_range, @@ -68294,7 +74650,7 @@ DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) { tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1)); duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */ - tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (&nc_ctx->high_ok ? 0 : 1)); + tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)); DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2)); } else { @@ -69574,11 +75930,11 @@ DUK_INTERNAL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk * Helper macros */ -#ifdef DUK__BUFLEN -#undef DUK__BUFLEN -#endif +#define DUK__RE_INITIAL_BUFSIZE 64 -#define DUK__BUFLEN(re_ctx) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) re_ctx->buf) +#undef DUK__RE_BUFLEN +#define DUK__RE_BUFLEN(re_ctx) \ + DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw) /* * Disjunction struct: result of parsing a disjunction @@ -69631,20 +75987,30 @@ DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) { * maximum size. */ DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) { - return (duk_uint32_t) duk_hbuffer_insert_xutf8(re_ctx->thr, re_ctx->buf, offset, x); + duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH]; + duk_small_int_t len; + + len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf); + DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len); + return (duk_uint32_t) len; } DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) { - return (duk_uint32_t) duk_hbuffer_append_xutf8(re_ctx->thr, re_ctx->buf, x); + duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH]; + duk_small_int_t len; + + len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf); + DUK_BW_WRITE_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, buf, len); + return (duk_uint32_t) len; } DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) { - return (duk_uint32_t) duk_hbuffer_insert_xutf8(re_ctx->thr, re_ctx->buf, offset, duk__encode_i32(x)); + return duk__insert_u32(re_ctx, offset, duk__encode_i32(x)); } #if 0 /* unused */ DUK_LOCAL duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) { - return duk_hbuffer_append_xutf8(re_ctx->thr, re_ctx->buf, duk__encode_i32(x)); + return duk__append_u32(re_ctx, duk__encode_i32(x)); } #endif @@ -69658,15 +76024,15 @@ DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, duk_uint16_t *v } DUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length) { - duk_hbuffer_insert_slice(re_ctx->thr, re_ctx->buf, offset, data_offset, (duk_size_t) data_length); + DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length); } DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) { - duk_hbuffer_append_slice(re_ctx->thr, re_ctx->buf, data_offset, (duk_size_t) data_length); + DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length); } -DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t length) { - duk_hbuffer_remove_slice(re_ctx->thr, re_ctx->buf, offset, (duk_size_t) length); +DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) { + DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length); } /* @@ -69698,7 +76064,7 @@ DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_ } DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) { - return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__BUFLEN(re_ctx), skip); + return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip); } /* @@ -69827,7 +76193,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */ duk_int32_t unpatched_disjunction_split = -1; duk_int32_t unpatched_disjunction_jump = -1; - duk_uint32_t entry_offset = (duk_uint32_t) DUK__BUFLEN(re_ctx); + duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */ duk__re_disjunction_info tmp_disj; @@ -69885,7 +76251,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex offset = unpatched_disjunction_jump; offset += duk__insert_jump_offset(re_ctx, offset, - (duk_int32_t) (DUK__BUFLEN(re_ctx) - offset)); + (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset)); /* offset is now target of the pending split (right after jump) */ duk__insert_jump_offset(re_ctx, unpatched_disjunction_split, @@ -69900,7 +76266,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex /* add a new pending match jump for latest finished alternative */ duk__append_u32(re_ctx, DUK_REOP_JUMP); - unpatched_disjunction_jump = (duk_int32_t) DUK__BUFLEN(re_ctx); + unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); /* 'taint' result as complex */ res_charlen = -1; @@ -69945,7 +76311,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex } duk__append_u32(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */ - atom_code_length = (duk_int32_t) (DUK__BUFLEN(re_ctx) - atom_start_offset); + atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - atom_start_offset); offset = atom_start_offset; if (re_ctx->curr_token.greedy) { @@ -70001,7 +76367,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex (long) atom_start_captures)); } - atom_code_length = (duk_int32_t) DUK__BUFLEN(re_ctx) - atom_start_offset; + atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset; /* insert the required matches (qmin) by copying the atom */ tmp_qmin = re_ctx->curr_token.qmin; @@ -70050,7 +76416,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex * ... * LSEQ: */ - duk_uint32_t offset = (duk_uint32_t) DUK__BUFLEN(re_ctx); + duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); while (tmp_qmax > 0) { duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length); if (re_ctx->curr_token.greedy) { @@ -70060,7 +76426,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex } duk__insert_jump_offset(re_ctx, offset + 1, /* +1 for opcode */ - (duk_int32_t) (DUK__BUFLEN(re_ctx) - (offset + 1))); + (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1))); tmp_qmax--; } } @@ -70095,14 +76461,14 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ? DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG; - offset = (duk_uint32_t) DUK__BUFLEN(re_ctx); + offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); duk__parse_disjunction(re_ctx, 0, &tmp_disj); duk__append_u32(re_ctx, DUK_REOP_MATCH); (void) duk__insert_u32(re_ctx, offset, opcode); (void) duk__insert_jump_offset(re_ctx, offset + 1, /* +1 for opcode */ - (duk_int32_t) (DUK__BUFLEN(re_ctx) - (offset + 1))); + (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1))); /* 'taint' result as complex -- this is conservative, * as lookaheads do not backtrack. @@ -70112,7 +76478,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex } case DUK_RETOK_ATOM_PERIOD: { new_atom_char_length = 1; - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, DUK_REOP_PERIOD); break; } @@ -70124,7 +76490,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex duk_uint32_t ch; new_atom_char_length = 1; - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, DUK_REOP_CHAR); ch = re_ctx->curr_token.num; if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) { @@ -70136,7 +76502,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex case DUK_RETOK_ATOM_DIGIT: case DUK_RETOK_ATOM_NOT_DIGIT: { new_atom_char_length = 1; - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, (re_ctx->curr_token.t == DUK_RETOK_ATOM_DIGIT) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES); @@ -70147,7 +76513,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex case DUK_RETOK_ATOM_WHITE: case DUK_RETOK_ATOM_NOT_WHITE: { new_atom_char_length = 1; - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, (re_ctx->curr_token.t == DUK_RETOK_ATOM_WHITE) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES); @@ -70158,7 +76524,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex case DUK_RETOK_ATOM_WORD_CHAR: case DUK_RETOK_ATOM_NOT_WORD_CHAR: { new_atom_char_length = 1; - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, (re_ctx->curr_token.t == DUK_RETOK_ATOM_WORD_CHAR) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES); @@ -70172,7 +76538,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex re_ctx->highest_backref = backref; } new_atom_char_length = -1; /* mark as complex */ - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, DUK_REOP_BACKREFERENCE); duk__append_u32(re_ctx, backref); break; @@ -70181,7 +76547,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex duk_uint32_t cap; new_atom_char_length = -1; /* mark as complex (capture handling) */ - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); cap = ++re_ctx->captures; duk__append_u32(re_ctx, DUK_REOP_SAVE); duk__append_u32(re_ctx, cap * 2); @@ -70191,7 +76557,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex break; } case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: { - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__parse_disjunction(re_ctx, 0, &tmp_disj); new_atom_char_length = tmp_disj.charlen; break; @@ -70228,11 +76594,11 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex /* insert ranges instruction, range count patched in later */ new_atom_char_length = 1; - new_atom_start_offset = (duk_int32_t) DUK__BUFLEN(re_ctx); + new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx); duk__append_u32(re_ctx, (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES); - offset = (duk_uint32_t) DUK__BUFLEN(re_ctx); /* patch in range count later */ + offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */ /* parse ranges until character class ends */ re_ctx->nranges = 0; /* note: ctx-wide temporary */ @@ -70288,7 +76654,7 @@ DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t ex offset = unpatched_disjunction_jump; offset += duk__insert_jump_offset(re_ctx, offset, - (duk_int32_t) (DUK__BUFLEN(re_ctx) - offset)); + (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset)); /* offset is now target of the pending split (right after jump) */ duk__insert_jump_offset(re_ctx, unpatched_disjunction_split, @@ -70379,8 +76745,10 @@ DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) { duk_context *ctx = (duk_context *) thr; duk_hstring *h; - duk_hbuffer_dynamic *buf; const duk_uint8_t *p; + duk_bufwriter_ctx bw_alloc; + duk_bufwriter_ctx *bw; + duk_uint8_t *q; duk_size_t i, n; duk_uint_fast8_t c_prev, c; @@ -70395,26 +76763,29 @@ DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) { return; } - duk_push_dynamic_buffer(ctx, 0); - buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); - DUK_ASSERT(buf != NULL); + bw = &bw_alloc; + DUK_BW_INIT_PUSHBUF(thr, bw, n); + q = DUK_BW_GET_PTR(thr, bw); c_prev = (duk_uint_fast8_t) 0; for (i = 0; i < n; i++) { c = p[i]; + q = DUK_BW_ENSURE_RAW(thr, bw, 2, q); + if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') { /* Unescaped '/' ANYWHERE in the regexp (in disjunction, * inside a character class, ...) => same escape works. */ - duk_hbuffer_append_byte(thr, buf, (duk_uint8_t) '\\'); + *q++ = DUK_ASC_BACKSLASH; } - duk_hbuffer_append_byte(thr, buf, (duk_uint8_t) c); + *q++ = (duk_uint8_t) c; c_prev = c; } + DUK_BW_SETPTR_AND_COMPACT(thr, bw, q); duk_to_string(ctx, -1); /* -> [ ... escaped_source ] */ } @@ -70439,7 +76810,6 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { duk_lexer_point lex_point; duk_hstring *h_pattern; duk_hstring *h_flags; - duk_hbuffer_dynamic *h_buffer; duk__re_disjunction_info ign_disj; DUK_ASSERT(thr != NULL); @@ -70467,10 +76837,6 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { * Init compilation context */ - duk_push_dynamic_buffer(ctx, 0); - h_buffer = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, -1); - DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buffer)); - /* [ ... pattern flags escaped_source buffer ] */ DUK_MEMZERO(&re_ctx, sizeof(re_ctx)); @@ -70480,10 +76846,11 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern); re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern); re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT; - re_ctx.buf = h_buffer; re_ctx.recursion_limit = DUK_RE_COMPILE_RECURSION_LIMIT; re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags); + DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE); + DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld", (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit)); @@ -70508,9 +76875,6 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { duk__append_u32(&re_ctx, 1); duk__append_u32(&re_ctx, DUK_REOP_MATCH); - DUK_D(DUK_DPRINT("regexp bytecode size (before header) is %ld bytes", - (long) DUK_HBUFFER_GET_SIZE(re_ctx.buf))); - /* * Check for invalid backreferences; note that it is NOT an error * to back-reference a capture group which has not yet been introduced @@ -70532,12 +76896,9 @@ DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) { duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2); duk__insert_u32(&re_ctx, 0, re_ctx.re_flags); - DUK_D(DUK_DPRINT("regexp bytecode size (after header) is %ld bytes", - (long) DUK_HBUFFER_GET_SIZE(re_ctx.buf))); - DUK_DDD(DUK_DDDPRINT("compiled regexp: %!xO", (duk_heaphdr *) re_ctx.buf)); - /* [ ... pattern flags escaped_source buffer ] */ + DUK_BW_COMPACT(thr, &re_ctx.bw); duk_to_string(ctx, -1); /* coerce to string */ /* [ ... pattern flags escaped_source bytecode ] */ @@ -70613,7 +76974,7 @@ DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) { /* [ ... regexp_object ] */ } -#undef DUK__BUFLEN +#undef DUK__RE_BUFLEN #else /* DUK_USE_REGEXP_SUPPORT */ @@ -71872,7 +78233,7 @@ DUK_LOCAL void duk__selftest_bswap_macros(void) { du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22; du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66; - DUK_DBLUNION_BSWAP(&du); + DUK_DBLUNION_DOUBLE_NTOH(&du); du_diff = du.d - 2.008366013071895; #if 0 DUK_FPRINTF(DUK_STDERR, "du_diff: %lg\n", (double) du_diff); @@ -71883,13 +78244,13 @@ DUK_LOCAL void duk__selftest_bswap_macros(void) { * Linux gcc-4.8 -m32 at least). */ #if 0 - DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_BSWAP: %02x %02x %02x %02x %02x %02x %02x %02x\n", + DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n", (unsigned int) du.uc[0], (unsigned int) du.uc[1], (unsigned int) du.uc[2], (unsigned int) du.uc[3], (unsigned int) du.uc[4], (unsigned int) du.uc[5], (unsigned int) du.uc[6], (unsigned int) du.uc[7]); #endif - DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_BSWAP"); + DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_DOUBLE_NTOH"); } } @@ -71964,16 +78325,18 @@ DUK_LOCAL void duk__selftest_double_zero_sign(void) { */ DUK_LOCAL void duk__selftest_struct_align(void) { -#if defined(DUK_USE_ALIGN_4) +#if (DUK_USE_ALIGN_BY == 4) if ((sizeof(duk_hbuffer_fixed) % 4) != 0) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4"); } -#elif defined(DUK_USE_ALIGN_8) +#elif (DUK_USE_ALIGN_BY == 8) if ((sizeof(duk_hbuffer_fixed) % 8) != 0) { DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8"); } -#else +#elif (DUK_USE_ALIGN_BY == 1) /* no check */ +#else +#error invalid DUK_USE_ALIGN_BY #endif } @@ -72593,6 +78956,373 @@ DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) { } DUK_ASSERT(ctx->currbits == 0); } +#line 1 "duk_util_bufwriter.c" +/* + * Fast buffer writer with spare management. + */ + +/* include removed: duk_internal.h */ + +/* + * Macro support functions (use only macros in calling code) + */ + +DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length) { + duk_uint8_t *p; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw_ctx != NULL); + DUK_UNREF(thr); + + p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf); + DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0)); + bw_ctx->p = p + curr_offset; + bw_ctx->p_base = p; + bw_ctx->p_limit = p + new_length; +} + +DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) { + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw_ctx != NULL); + DUK_ASSERT(h_buf != NULL); + DUK_UNREF(thr); + + bw_ctx->buf = h_buf; + duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf)); +} + +DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) { + duk_context *ctx; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw_ctx != NULL); + ctx = (duk_context *) thr; + + (void) duk_push_dynamic_buffer(ctx, buf_size); + bw_ctx->buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1); + duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size); +} + +/* Resize target buffer for requested size. Called by the macro only when the + * fast path test (= there is space) fails. + */ +DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) { + duk_size_t curr_off; + duk_size_t add_sz; + duk_size_t new_sz; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw_ctx != NULL); + + /* We could do this operation without caller updating bw_ctx->ptr, + * but by writing it back here we can share code better. + */ + + curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base); + add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD; + new_sz = curr_off + sz + add_sz; + if (new_sz < curr_off) { + /* overflow */ + DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_BUFFER_TOO_LONG); + return NULL; /* not reachable */ + } +#if 0 /* for manual torture testing: tight allocation, useful with valgrind */ + new_sz = curr_off + sz; +#endif + + /* This is important to ensure dynamic buffer data pointer is not + * NULL (which is possible if buffer size is zero), which in turn + * causes portability issues with e.g. memmove() and memcpy(). + */ + DUK_ASSERT(new_sz >= 1); + + DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz)); + + duk_hbuffer_resize(thr, bw_ctx->buf, new_sz); + duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz); + return bw_ctx->p; +} + +/* Make buffer compact, matching current written size. */ +DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) { + duk_size_t len; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw_ctx != NULL); + DUK_UNREF(thr); + + len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base); + duk_hbuffer_resize(thr, bw_ctx->buf, len); + duk__bw_update_ptrs(thr, bw_ctx, len, len); +} + +DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) { + duk_uint8_t *p_base; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + p_base = bw->p_base; + DUK_MEMCPY((void *) bw->p, + (const void *) (p_base + src_off), + (duk_size_t) len); + bw->p += len; +} + +DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) { + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + DUK_BW_ENSURE(thr, bw, len); + duk_bw_write_raw_slice(thr, bw, src_off, len); +} + +DUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) { + duk_uint8_t *p_base; + duk_size_t buf_sz, move_sz; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(buf != NULL); + DUK_UNREF(thr); + + p_base = bw->p_base; + buf_sz = bw->p - p_base; + move_sz = buf_sz - dst_off; + + 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); + DUK_MEMCPY((void *) (p_base + dst_off), + (const void *) buf, + (duk_size_t) len); + bw->p += len; +} + +DUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) { + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(buf != NULL); + DUK_UNREF(thr); + + DUK_BW_ENSURE(thr, bw, len); + duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len); +} + +DUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) { + duk_uint8_t *p_base; + duk_size_t buf_sz, move_sz; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + p_base = bw->p_base; + + /* Don't support "straddled" source now. */ + DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len); + + if (dst_off <= src_off) { + /* Target is before source. Source offset is expressed as + * a "before change" offset. Account for the memmove. + */ + src_off += len; + } + + buf_sz = bw->p - p_base; + move_sz = buf_sz - dst_off; + + 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); + DUK_MEMCPY((void *) (p_base + dst_off), + (const void *) (p_base + src_off), + (duk_size_t) len); + bw->p += len; +} + +DUK_INTERNAL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) { + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + /* Don't support "straddled" source now. */ + DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len); + + DUK_BW_ENSURE(thr, bw, len); + duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len); +} + +DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) { + duk_uint8_t *p_base, *p_dst, *p_src; + duk_size_t buf_sz, move_sz; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + p_base = bw->p_base; + buf_sz = bw->p - p_base; + 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); + return p_src; /* point to start of 'reserved area' */ +} + +DUK_INTERNAL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) { + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + DUK_BW_ENSURE(thr, bw, len); + return duk_bw_insert_raw_area(thr, bw, off, len); +} + +DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) { + duk_size_t move_sz; + + duk_uint8_t *p_base; + duk_uint8_t *p_src; + duk_uint8_t *p_dst; + + DUK_ASSERT(thr != NULL); + DUK_ASSERT(bw != NULL); + DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw)); + DUK_UNREF(thr); + + p_base = bw->p_base; + p_dst = p_base + off; + p_src = p_dst + len; + move_sz = (duk_size_t) (bw->p - p_src); + DUK_MEMMOVE((void *) p_dst, + (const void *) p_src, + move_sz); + bw->p -= len; +} + +/* + * Macro support functions for reading/writing raw data. + * + * These are done using mempcy to ensure they're valid even for unaligned + * reads/writes on platforms where alignment counts. On x86 at least gcc + * is able to compile these into a bswap+mov. "Always inline" is used to + * ensure these macros compile to minimal code. + * + * Not really bufwriter related, but currently used together. + */ + +DUK_ALWAYS_INLINE +DUK_INTERNAL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) { + union { + duk_uint8_t b[2]; + duk_uint16_t x; + } u; + + DUK_MEMCPY((void *) u.b, (const void *) (*p), 2); + u.x = DUK_NTOH16(u.x); + *p += 2; + return u.x; +} + +DUK_ALWAYS_INLINE +DUK_INTERNAL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) { + union { + duk_uint8_t b[4]; + duk_uint32_t x; + } u; + + DUK_MEMCPY((void *) u.b, (const void *) (*p), 4); + u.x = DUK_NTOH32(u.x); + *p += 4; + return u.x; +} + +DUK_ALWAYS_INLINE +DUK_INTERNAL duk_double_t duk_raw_read_double_be(duk_uint8_t **p) { + duk_double_union du; + union { + duk_uint8_t b[4]; + duk_uint32_t x; + } u; + + DUK_MEMCPY((void *) u.b, (const void *) (*p), 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); + u.x = DUK_NTOH32(u.x); + du.ui[DUK_DBL_IDX_UI1] = u.x; + *p += 8; + + return du.d; +} + +DUK_ALWAYS_INLINE +DUK_INTERNAL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) { + union { + duk_uint8_t b[2]; + duk_uint16_t x; + } u; + + u.x = DUK_HTON16(val); + DUK_MEMCPY((void *) (*p), (const void *) u.b, 2); + *p += 2; +} + +DUK_ALWAYS_INLINE +DUK_INTERNAL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) { + union { + duk_uint8_t b[4]; + duk_uint32_t x; + } u; + + u.x = DUK_HTON32(val); + DUK_MEMCPY((void *) (*p), (const void *) u.b, 4); + *p += 4; +} + +DUK_ALWAYS_INLINE +DUK_INTERNAL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) { + duk_double_union du; + union { + duk_uint8_t b[4]; + duk_uint32_t x; + } u; + + 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); + u.x = du.ui[DUK_DBL_IDX_UI1]; + u.x = DUK_HTON32(u.x); + DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, 4); + *p += 8; +} #line 1 "duk_util_hashbytes.c" /* * Hash function duk_util_hashbytes(). @@ -72619,7 +79349,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 *) data); + duk_uint32_t k = *((duk_uint32_t *) (void *) data); #else duk_uint32_t k = ((duk_uint32_t) data[0]) | (((duk_uint32_t) data[1]) << 8) | diff --git a/javascript/duktape/duktape.h b/javascript/duktape/duktape.h index 6baa7da30..8d4c31312 100644 --- a/javascript/duktape/duktape.h +++ b/javascript/duktape/duktape.h @@ -1,11 +1,11 @@ /* - * Duktape public API for Duktape 1.2.3. + * Duktape public API for Duktape 1.2.99. * See the API reference for documentation on call semantics. * The exposed API is inside the DUK_API_PUBLIC_H_INCLUDED * include guard. Other parts of the header are Duktape * internal and related to platform/compiler/feature detection. * - * Git commit 0605a18660dbae486c62a42a33fabd034c8623ff (v1.2.3). + * Git commit 2a41d0a38eef5edfe8691cf09427b6ee8a3ad5c9 (v1.2.0-310-g2a41d0a). * * See Duktape AUTHORS.rst and LICENSE.txt for copyright and * licensing information. @@ -38,3076 +38,87 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * - */ - -/* AUTHORS.rst */ -/* - * =============== - * Duktape authors - * =============== - * - * Copyright - * ========= - * - * Duktape copyrights are held by its authors. Each author has a copyright - * to their contribution, and agrees to irrevocably license the contribution - * under the Duktape ``LICENSE.txt``. - * - * Authors - * ======= - * - * Please include an e-mail address, a link to your GitHub profile, or something - * similar to allow your contribution to be identified accurately. - * - * The following people have contributed code and agreed to irrevocably license - * their contributions under the Duktape ``LICENSE.txt`` (in order of appearance): - * - * * Sami Vaarala - * * Niki Dobrev - * * Andreas \u00d6man - * * L\u00e1szl\u00f3 Lang\u00f3 - * * Legimet - * - * Other contributions - * =================== - * - * The following people have contributed something other than code (e.g. reported - * bugs, provided ideas, etc; roughly in order of appearance): - * - * * Greg Burns - * * Anthony Rabine - * * Carlos Costa - * * Aur\u00e9lien Bouilland - * * Preet Desai (Pris Matic) - * * judofyr (http://www.reddit.com/user/judofyr) - * * Jason Woofenden - * * Micha\u0142 Przyby\u015b - * * Anthony Howe - * * Conrad Pankoff - * * Jim Schimpf - * * Rajaran Gaunker (https://github.com/zimbabao) - * * Andreas \u00d6man - * * Doug Sanden - * * Josh Engebretson (https://github.com/JoshEngebretson) - * * Remo Eichenberger (https://github.com/remoe) - * * Mamod Mehyar (https://github.com/mamod) - * * David Demelier (https://github.com/hftmarkand) - * * Tim Caswell (https://github.com/creationix) - * * Mitchell Blank Jr (https://github.com/mitchblank) - * * https://github.com/yushli - * * Seo Sanghyeon (https://github.com/sanxiyn) - * * Han ChoongWoo (https://github.com/tunz) - * * Joshua Peek (https://github.com/josh) - * * Bruce E. Pascoe (https://github.com/fatcerberus) - * * https://github.com/Kelledin - * * https://github.com/sstruchtrup - * - * If you are accidentally missing from this list, send me an e-mail - * (``sami.vaarala@iki.fi``) and I'll fix the omission. - */ - -#ifndef DUKTAPE_H_INCLUDED -#define DUKTAPE_H_INCLUDED - -#define DUK_SINGLE_FILE - -/* - * 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). - * - * 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. - * - * 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 - * - * DUK_F_XXX are internal feature detection macros which should not be - * used outside this header. - * - * Useful resources: - * - * 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 - = 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 - */ - -/* 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_RDTSC_AVAILABLE 1 -#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_RDTSC_AVAILABLE 1 -#else -/* not available */ -#undef DUK_RDTSC_AVAILABLE -#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 -#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 -#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 -#endif - -/* ARM */ -#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) -#define DUK_F_ARM -#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 -#endif - -/* SuperH */ -#if defined(__sh__) || \ - defined(__sh1__) || defined(__SH1__) || \ - defined(__sh2__) || defined(__SH2__) || \ - defined(__sh3__) || defined(__SH3__) || \ - defined(__sh4__) || defined(__SH4__) || \ - defined(__sh5__) || defined(__SH5__) -#define DUK_F_SUPERH -#endif - -/* Motorola 68K. Not defined by VBCC, so user must define one of these - * manually when using VBCC. - */ -#if defined(__m68k__) || defined(M68000) || defined(__MC68K__) -#define DUK_F_M68K -#endif - -/* PowerPC */ -#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__) -#define DUK_F_PPC -#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 -#endif - -/* OpenBSD */ -#if defined(__OpenBSD__) || defined(__OpenBSD) -#define DUK_F_OPENBSD -#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 - -/* Generic Unix (includes Cygwin) */ -#if defined(__unix) || defined(__unix__) || defined(unix) || \ - defined(DUK_F_LINUX) || defined(DUK_F_BSD) -#define DUK_F_UNIX -#endif - -/* Cygwin */ -#if defined(__CYGWIN__) -#define DUK_F_CYGWIN -#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 -#endif - -#if defined(__APPLE__) -#define DUK_F_APPLE -#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 -#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 -#endif - -/* Flash player (e.g. Crossbridge) */ -#if defined(__FLASHPLAYER__) -#define DUK_F_FLASHPLAYER -#endif - -/* Emscripten (provided explicitly by user), improve if possible */ -#if defined(EMSCRIPTEN) -#define DUK_F_EMSCRIPTEN -#endif - -/* QNX */ -#if defined(__QNX__) -#define DUK_F_QNX -#endif - -/* TI-Nspire (using Ndless) */ -#if defined(_TINSPIRE) -#define DUK_F_TINSPIRE -#endif - -/* GCC and GCC version convenience define. */ -#if defined(__GNUC__) -#define DUK_F_GCC -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */ -#define DUK_F_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__) -#else -#error cannot figure out gcc version -#endif -#endif - -/* 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 -#endif - -/* MSVC */ -#if defined(_MSC_VER) -/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx - * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g. - * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp - */ -#define DUK_F_MSVC -#if defined(_MSC_FULL_VER) -#if (_MSC_FULL_VER > 100000000) -#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER -#else -#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10) -#endif -#endif -#endif /* _MSC_VER */ - -/* 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 -#endif - -#if defined(__VBCC__) -#define DUK_F_VBCC -#endif - -#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. - */ -#define DUK_F_ULL_CONSTS -#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 -#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. - */ -#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 , - * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366 - */ -#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS) -#define __STDC_LIMIT_MACROS -#endif -#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) -#define __STDC_CONSTANT_MACROS -#endif - -#if defined(__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 -#include -#include -#include -#include -#include -#elif defined(DUK_F_OPENBSD) -/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */ -#define DUK_USE_DATE_NOW_GETTIMEOFDAY -#define DUK_USE_DATE_TZO_GMTIME_R -#define DUK_USE_DATE_PRS_STRPTIME -#define DUK_USE_DATE_FMT_STRFTIME -#include -#include -#include -#include -#include -#include -#elif defined(DUK_F_BSD) -/* other 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 -#include -#include -#include -#include -#include -#elif defined(DUK_F_TOS) -/* Atari ST TOS */ -#define DUK_USE_DATE_NOW_TIME -#define DUK_USE_DATE_TZO_GMTIME -/* no parsing (not an error) */ -#define DUK_USE_DATE_FMT_STRFTIME -#include -#include -#elif defined(DUK_F_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 -#include -#elif defined(DUK_F_PPC) -/* AmigaOS on PowerPC */ -#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 -#include -#ifndef UINTPTR_MAX -#define UINTPTR_MAX UINT_MAX -#endif -#else -#error AmigaOS but not M68K/PPC, not supported now -#endif -#elif defined(DUK_F_WINDOWS) -/* Windows 32-bit and 64-bit are currently the same. */ -/* MSVC does not have sys/param.h */ -#define DUK_USE_DATE_NOW_WINDOWS -#define DUK_USE_DATE_TZO_WINDOWS -/* Note: PRS and FMT are intentionally left undefined for now. This means - * there is no platform specific date parsing/formatting but there is still - * the ISO 8601 standard format. - */ -#include -#include -#elif defined(DUK_F_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 -#include -#include -#include -#include -#elif defined(DUK_F_QNX) -#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 -#include -#include -#include -#include -#elif defined(DUK_F_TINSPIRE) -#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 -#include -#include -#include -#include -#elif defined(DUK_F_LINUX) -#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 -#if defined(DUK_F_BCC) -/* no endian.h */ -#else -#include -#endif /* DUK_F_BCC */ -#include -#include -#include -#include -#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 -#include -#include -#include -#include -#include -#include -#elif defined(DUK_F_CYGWIN) -/* Cygwin -- don't use strptime() for now */ -#define DUK_USE_DATE_NOW_GETTIMEOFDAY -#define DUK_USE_DATE_TZO_GMTIME_R -#define DUK_USE_DATE_FMT_STRFTIME -#include -#include -#include -#include -#include -#include -#else -/* Other UNIX, hopefully others */ -#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 -#if defined(DUK_F_BCC) -/* no endian.h */ -#else -#include -#endif /* DUK_F_BCC */ -#include -#include -#include -#include -#endif - -/* Shared includes */ -#include -#include -#include -#include /* varargs */ -#include -#include /* e.g. ptrdiff_t */ -#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). - */ -#include -#endif -#include - -/* - * Detection for specific libc variants (like uclibc) and other libc specific - * features. Potentially depends on the #includes above. - */ - -#if defined(__UCLIBC__) -#define DUK_F_UCLIBC -#endif - -/* - * Wrapper typedefs and constants for integer types, also sanity check types. - * - * C99 typedefs are quite good but not always available, and we want to avoid - * forcibly redefining the C99 typedefs. So, there are Duktape wrappers for - * all C99 typedefs and Duktape code should only use these typedefs. Type - * detection when C99 is not supported is best effort and may end up detecting - * some types incorrectly. - * - * Pointer sizes are a portability problem: pointers to different types may - * have a different size and function pointers are very difficult to manage - * portably. - * - * http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types - * - * Note: there's an interesting corner case when trying to define minimum - * signed integer value constants which leads to the current workaround of - * defining e.g. -0x80000000 as (-0x7fffffffL - 1L). See doc/code-issues.txt - * for a longer discussion. - * - * Note: avoid typecasts and computations in macro integer constants as they - * can then no longer be used in macro relational expressions (such as - * #if DUK_SIZE_MAX < 0xffffffffUL). There is internal code which relies on - * being able to compare DUK_SIZE_MAX against a limit. - */ - -/* XXX: add feature options to force basic types from outside? */ - -#if !defined(INT_MAX) -#error INT_MAX not defined -#endif - -/* Check that architecture is two's complement, standard C allows e.g. - * INT_MIN to be -2**31+1 (instead of -2**31). - */ -#if defined(INT_MAX) && defined(INT_MIN) -#if INT_MAX != -(INT_MIN + 1) -#error platform does not seem complement of two -#endif -#else -#error cannot check complement of two -#endif - -/* Pointer size determination based on architecture. - * XXX: unsure about BCC correctness. - */ -#if defined(DUK_F_X86) || defined(DUK_F_X32) || \ - defined(DUK_F_BCC) || \ - (defined(__WORDSIZE) && (__WORDSIZE == 32)) -#define DUK_F_32BIT_PTRS -#elif defined(DUK_F_X64) || \ - (defined(__WORDSIZE) && (__WORDSIZE == 64)) -#define DUK_F_64BIT_PTRS -#else -/* not sure, not needed with C99 anyway */ -#endif - -/* Intermediate define for 'have inttypes.h' */ -#undef DUK_F_HAVE_INTTYPES -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)) -/* vbcc + AmigaOS has C99 but no inttypes.h */ -#define DUK_F_HAVE_INTTYPES -#elif defined(__cplusplus) && (__cplusplus >= 201103L) -/* C++11 apparently ratified stdint.h */ -#define DUK_F_HAVE_INTTYPES -#endif - -/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise - * through automatic detection. - */ -#if defined(DUK_F_HAVE_INTTYPES) -/* C99 or compatible */ - -#define DUK_F_HAVE_64BIT -#include - -typedef uint8_t duk_uint8_t; -typedef int8_t duk_int8_t; -typedef uint16_t duk_uint16_t; -typedef int16_t duk_int16_t; -typedef uint32_t duk_uint32_t; -typedef int32_t duk_int32_t; -typedef uint64_t duk_uint64_t; -typedef int64_t duk_int64_t; -typedef uint_least8_t duk_uint_least8_t; -typedef int_least8_t duk_int_least8_t; -typedef uint_least16_t duk_uint_least16_t; -typedef int_least16_t duk_int_least16_t; -typedef uint_least32_t duk_uint_least32_t; -typedef int_least32_t duk_int_least32_t; -typedef uint_least64_t duk_uint_least64_t; -typedef int_least64_t duk_int_least64_t; -typedef uint_fast8_t duk_uint_fast8_t; -typedef int_fast8_t duk_int_fast8_t; -typedef uint_fast16_t duk_uint_fast16_t; -typedef int_fast16_t duk_int_fast16_t; -typedef uint_fast32_t duk_uint_fast32_t; -typedef int_fast32_t duk_int_fast32_t; -typedef uint_fast64_t duk_uint_fast64_t; -typedef int_fast64_t duk_int_fast64_t; -typedef uintptr_t duk_uintptr_t; -typedef intptr_t duk_intptr_t; -typedef uintmax_t duk_uintmax_t; -typedef intmax_t duk_intmax_t; - -#define DUK_UINT8_MIN 0 -#define DUK_UINT8_MAX UINT8_MAX -#define DUK_INT8_MIN INT8_MIN -#define DUK_INT8_MAX INT8_MAX -#define DUK_UINT_LEAST8_MIN 0 -#define DUK_UINT_LEAST8_MAX UINT_LEAST8_MAX -#define DUK_INT_LEAST8_MIN INT_LEAST8_MIN -#define DUK_INT_LEAST8_MAX INT_LEAST8_MAX -#define DUK_UINT_FAST8_MIN 0 -#define DUK_UINT_FAST8_MAX UINT_FAST8_MAX -#define DUK_INT_FAST8_MIN INT_FAST8_MIN -#define DUK_INT_FAST8_MAX INT_FAST8_MAX -#define DUK_UINT16_MIN 0 -#define DUK_UINT16_MAX UINT16_MAX -#define DUK_INT16_MIN INT16_MIN -#define DUK_INT16_MAX INT16_MAX -#define DUK_UINT_LEAST16_MIN 0 -#define DUK_UINT_LEAST16_MAX UINT_LEAST16_MAX -#define DUK_INT_LEAST16_MIN INT_LEAST16_MIN -#define DUK_INT_LEAST16_MAX INT_LEAST16_MAX -#define DUK_UINT_FAST16_MIN 0 -#define DUK_UINT_FAST16_MAX UINT_FAST16_MAX -#define DUK_INT_FAST16_MIN INT_FAST16_MIN -#define DUK_INT_FAST16_MAX INT_FAST16_MAX -#define DUK_UINT32_MIN 0 -#define DUK_UINT32_MAX UINT32_MAX -#define DUK_INT32_MIN INT32_MIN -#define DUK_INT32_MAX INT32_MAX -#define DUK_UINT_LEAST32_MIN 0 -#define DUK_UINT_LEAST32_MAX UINT_LEAST32_MAX -#define DUK_INT_LEAST32_MIN INT_LEAST32_MIN -#define DUK_INT_LEAST32_MAX INT_LEAST32_MAX -#define DUK_UINT_FAST32_MIN 0 -#define DUK_UINT_FAST32_MAX UINT_FAST32_MAX -#define DUK_INT_FAST32_MIN INT_FAST32_MIN -#define DUK_INT_FAST32_MAX INT_FAST32_MAX -#define DUK_UINT64_MIN 0 -#define DUK_UINT64_MAX UINT64_MAX -#define DUK_INT64_MIN INT64_MIN -#define DUK_INT64_MAX INT64_MAX -#define DUK_UINT_LEAST64_MIN 0 -#define DUK_UINT_LEAST64_MAX UINT_LEAST64_MAX -#define DUK_INT_LEAST64_MIN INT_LEAST64_MIN -#define DUK_INT_LEAST64_MAX INT_LEAST64_MAX -#define DUK_UINT_FAST64_MIN 0 -#define DUK_UINT_FAST64_MAX UINT_FAST64_MAX -#define DUK_INT_FAST64_MIN INT_FAST64_MIN -#define DUK_INT_FAST64_MAX INT_FAST64_MAX - -#define DUK_UINTPTR_MIN 0 -#define DUK_UINTPTR_MAX UINTPTR_MAX -#define DUK_INTPTR_MIN INTPTR_MIN -#define DUK_INTPTR_MAX INTPTR_MAX - -#define DUK_UINTMAX_MIN 0 -#define DUK_UINTMAX_MAX UINTMAX_MAX -#define DUK_INTMAX_MIN INTMAX_MIN -#define DUK_INTMAX_MAX INTMAX_MAX - -#define DUK_SIZE_MIN 0 -#define DUK_SIZE_MAX SIZE_MAX - -#else /* C99 types */ - -/* When C99 types are not available, we use heuristic detection to get - * the basic 8, 16, 32, and (possibly) 64 bit types. The fast/least - * types are then assumed to be exactly the same for now: these could - * be improved per platform but C99 types are very often now available. - * 64-bit types are not available on all platforms; this is OK at least - * on 32-bit platforms. - * - * This detection code is necessarily a bit hacky and can provide typedefs - * and defines that won't work correctly on some exotic platform. - */ - -#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \ - (defined(UCHAR_MAX) && (UCHAR_MAX == 255)) -typedef unsigned char duk_uint8_t; -typedef signed char duk_int8_t; -#else -#error cannot detect 8-bit type -#endif - -#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL) -typedef unsigned short duk_uint16_t; -typedef signed short duk_int16_t; -#elif defined(UINT_MAX) && (UINT_MAX == 65535UL) -/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */ -typedef unsigned int duk_uint16_t; -typedef signed int duk_int16_t; -#else -#error cannot detect 16-bit type -#endif - -#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL) -typedef unsigned int duk_uint32_t; -typedef signed int duk_int32_t; -#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL) -/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */ -typedef unsigned long duk_uint32_t; -typedef signed long duk_int32_t; -#else -#error cannot detect 32-bit type -#endif - -/* 64-bit type detection is a bit tricky. - * - * ULLONG_MAX is a standard define. __LONG_LONG_MAX__ and __ULONG_LONG_MAX__ - * are used by at least GCC (even if system headers don't provide ULLONG_MAX). - * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__. - * - * ULL / LL constants are rejected / warned about by some compilers, even if - * the compiler has a 64-bit type and the compiler/system headers provide an - * unsupported constant (ULL/LL)! Try to avoid using ULL / LL constants. - * As a side effect we can only check that e.g. ULONG_MAX is larger than 32 - * bits but can't be sure it is exactly 64 bits. Self tests will catch such - * cases. - */ -#undef DUK_F_HAVE_64BIT -#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX) -#if (ULONG_MAX > 4294967295UL) -#define DUK_F_HAVE_64BIT -typedef unsigned long duk_uint64_t; -typedef signed long duk_int64_t; -#endif -#endif -#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX) -#if (ULLONG_MAX > 4294967295UL) -#define DUK_F_HAVE_64BIT -typedef unsigned long long duk_uint64_t; -typedef signed long long duk_int64_t; -#endif -#endif -#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__) -#if (__ULONG_LONG_MAX__ > 4294967295UL) -#define DUK_F_HAVE_64BIT -typedef unsigned long long duk_uint64_t; -typedef signed long long duk_int64_t; -#endif -#endif -#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__) -#if (__LONG_LONG_MAX__ > 2147483647L) -#define DUK_F_HAVE_64BIT -typedef unsigned long long duk_uint64_t; -typedef signed long long duk_int64_t; -#endif -#endif -#if !defined(DUK_F_HAVE_64BIT) && \ - (defined(DUK_F_MINGW) || defined(DUK_F_MSVC)) -/* Both MinGW and MSVC have a 64-bit type. */ -#define DUK_F_HAVE_64BIT -typedef unsigned long duk_uint64_t; -typedef signed long duk_int64_t; -#endif -#if !defined(DUK_F_HAVE_64BIT) -/* cannot detect 64-bit type, not always needed so don't error */ -#endif - -typedef duk_uint8_t duk_uint_least8_t; -typedef duk_int8_t duk_int_least8_t; -typedef duk_uint16_t duk_uint_least16_t; -typedef duk_int16_t duk_int_least16_t; -typedef duk_uint32_t duk_uint_least32_t; -typedef duk_int32_t duk_int_least32_t; -typedef duk_uint8_t duk_uint_fast8_t; -typedef duk_int8_t duk_int_fast8_t; -typedef duk_uint16_t duk_uint_fast16_t; -typedef duk_int16_t duk_int_fast16_t; -typedef duk_uint32_t duk_uint_fast32_t; -typedef duk_int32_t duk_int_fast32_t; -#if defined(DUK_F_HAVE_64BIT) -typedef duk_uint64_t duk_uint_least64_t; -typedef duk_int64_t duk_int_least64_t; -typedef duk_uint64_t duk_uint_fast64_t; -typedef duk_int64_t duk_int_fast64_t; -#endif -#if defined(DUK_F_HAVE_64BIT) -typedef duk_uint64_t duk_uintmax_t; -typedef duk_int64_t duk_intmax_t; -#else -typedef duk_uint32_t duk_uintmax_t; -typedef duk_int32_t duk_intmax_t; -#endif - -/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and - * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are - * -not- portable. See code-issues.txt for a detailed discussion. - */ -#define DUK_UINT8_MIN 0UL -#define DUK_UINT8_MAX 0xffUL -#define DUK_INT8_MIN (-0x80L) -#define DUK_INT8_MAX 0x7fL -#define DUK_UINT_LEAST8_MIN 0UL -#define DUK_UINT_LEAST8_MAX 0xffUL -#define DUK_INT_LEAST8_MIN (-0x80L) -#define DUK_INT_LEAST8_MAX 0x7fL -#define DUK_UINT_FAST8_MIN 0UL -#define DUK_UINT_FAST8_MAX 0xffUL -#define DUK_INT_FAST8_MIN (-0x80L) -#define DUK_INT_FAST8_MAX 0x7fL -#define DUK_UINT16_MIN 0UL -#define DUK_UINT16_MAX 0xffffUL -#define DUK_INT16_MIN (-0x7fffL - 1L) -#define DUK_INT16_MAX 0x7fffL -#define DUK_UINT_LEAST16_MIN 0UL -#define DUK_UINT_LEAST16_MAX 0xffffUL -#define DUK_INT_LEAST16_MIN (-0x7fffL - 1L) -#define DUK_INT_LEAST16_MAX 0x7fffL -#define DUK_UINT_FAST16_MIN 0UL -#define DUK_UINT_FAST16_MAX 0xffffUL -#define DUK_INT_FAST16_MIN (-0x7fffL - 1L) -#define DUK_INT_FAST16_MAX 0x7fffL -#define DUK_UINT32_MIN 0UL -#define DUK_UINT32_MAX 0xffffffffUL -#define DUK_INT32_MIN (-0x7fffffffL - 1L) -#define DUK_INT32_MAX 0x7fffffffL -#define DUK_UINT_LEAST32_MIN 0UL -#define DUK_UINT_LEAST32_MAX 0xffffffffUL -#define DUK_INT_LEAST32_MIN (-0x7fffffffL - 1L) -#define DUK_INT_LEAST32_MAX 0x7fffffffL -#define DUK_UINT_FAST32_MIN 0UL -#define DUK_UINT_FAST32_MAX 0xffffffffUL -#define DUK_INT_FAST32_MIN (-0x7fffffffL - 1L) -#define DUK_INT_FAST32_MAX 0x7fffffffL - -/* 64-bit constants. Since LL / ULL constants are not always available, - * use computed values. These values can't be used in preprocessor - * comparisons; flag them as such. - */ -#if defined(DUK_F_HAVE_64BIT) -#define DUK_UINT64_MIN ((duk_uint64_t) 0) -#define DUK_UINT64_MAX ((duk_uint64_t) -1) -#define DUK_INT64_MIN ((duk_int64_t) (~(DUK_UINT64_MAX >> 1))) -#define DUK_INT64_MAX ((duk_int64_t) (DUK_UINT64_MAX >> 1)) -#define DUK_UINT_LEAST64_MIN DUK_UINT64_MIN -#define DUK_UINT_LEAST64_MAX DUK_UINT64_MAX -#define DUK_INT_LEAST64_MIN DUK_INT64_MIN -#define DUK_INT_LEAST64_MAX DUK_INT64_MAX -#define DUK_UINT_FAST64_MIN DUK_UINT64_MIN -#define DUK_UINT_FAST64_MAX DUK_UINT64_MAX -#define DUK_INT_FAST64_MIN DUK_INT64_MIN -#define DUK_INT_FAST64_MAX DUK_INT64_MAX -#define DUK_UINT64_MIN_COMPUTED -#define DUK_UINT64_MAX_COMPUTED -#define DUK_INT64_MIN_COMPUTED -#define DUK_INT64_MAX_COMPUTED -#define DUK_UINT_LEAST64_MIN_COMPUTED -#define DUK_UINT_LEAST64_MAX_COMPUTED -#define DUK_INT_LEAST64_MIN_COMPUTED -#define DUK_INT_LEAST64_MAX_COMPUTED -#define DUK_UINT_FAST64_MIN_COMPUTED -#define DUK_UINT_FAST64_MAX_COMPUTED -#define DUK_INT_FAST64_MIN_COMPUTED -#define DUK_INT_FAST64_MAX_COMPUTED -#endif - -#if defined(DUK_F_HAVE_64BIT) -#define DUK_UINTMAX_MIN DUK_UINT64_MIN -#define DUK_UINTMAX_MAX DUK_UINT64_MAX -#define DUK_INTMAX_MIN DUK_INT64_MIN -#define DUK_INTMAX_MAX DUK_INT64_MAX -#define DUK_UINTMAX_MIN_COMPUTED -#define DUK_UINTMAX_MAX_COMPUTED -#define DUK_INTMAX_MIN_COMPUTED -#define DUK_INTMAX_MAX_COMPUTED -#else -#define DUK_UINTMAX_MIN 0UL -#define DUK_UINTMAX_MAX 0xffffffffUL -#define DUK_INTMAX_MIN (-0x7fffffffL - 1L) -#define DUK_INTMAX_MAX 0x7fffffffL -#endif - -/* This detection is not very reliable. */ -#if defined(DUK_F_32BIT_PTRS) -typedef duk_int32_t duk_intptr_t; -typedef duk_uint32_t duk_uintptr_t; -#define DUK_UINTPTR_MIN DUK_UINT32_MIN -#define DUK_UINTPTR_MAX DUK_UINT32_MAX -#define DUK_INTPTR_MIN DUK_INT32_MIN -#define DUK_INTPTR_MAX DUK_INT32_MAX -#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT) -typedef duk_int64_t duk_intptr_t; -typedef duk_uint64_t duk_uintptr_t; -#define DUK_UINTPTR_MIN DUK_UINT64_MIN -#define DUK_UINTPTR_MAX DUK_UINT64_MAX -#define DUK_INTPTR_MIN DUK_INT64_MIN -#define DUK_INTPTR_MAX DUK_INT64_MAX -#define DUK_UINTPTR_MIN_COMPUTED -#define DUK_UINTPTR_MAX_COMPUTED -#define DUK_INTPTR_MIN_COMPUTED -#define DUK_INTPTR_MAX_COMPUTED -#else -#error cannot determine intptr type -#endif - -/* SIZE_MAX may be missing so use an approximate value for it. */ -#undef DUK_SIZE_MAX_COMPUTED -#if !defined(SIZE_MAX) -#define DUK_SIZE_MAX_COMPUTED -#define SIZE_MAX ((size_t) (-1)) -#endif -#define DUK_SIZE_MIN 0 -#define DUK_SIZE_MAX SIZE_MAX - -#endif /* C99 types */ - -/* A few types are assumed to always exist. */ -typedef size_t duk_size_t; -typedef ptrdiff_t duk_ptrdiff_t; - -/* The best type for an "all around int" in Duktape internals is "at least - * 32 bit signed integer" which is most convenient. Same for unsigned type. - * Prefer 'int' when large enough, as it is almost always a convenient type. - */ -#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL) -typedef int duk_int_t; -typedef unsigned int duk_uint_t; -#define DUK_INT_MIN INT_MIN -#define DUK_INT_MAX INT_MAX -#define DUK_UINT_MIN 0 -#define DUK_UINT_MAX UINT_MAX -#else -typedef duk_int_fast32_t duk_int_t; -typedef duk_uint_fast32_t duk_uint_t; -#define DUK_INT_MIN DUK_INT_FAST32_MIN -#define DUK_INT_MAX DUK_INT_FAST32_MAX -#define DUK_UINT_MIN DUK_UINT_FAST32_MIN -#define DUK_UINT_MAX DUK_UINT_FAST32_MAX -#endif - -/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this - * distinction matters for the CPU. These types are used mainly in the - * executor where it might really matter. - */ -typedef duk_int_fast32_t duk_int_fast_t; -typedef duk_uint_fast32_t duk_uint_fast_t; -#define DUK_INT_FAST_MIN DUK_INT_FAST32_MIN -#define DUK_INT_FAST_MAX DUK_INT_FAST32_MAX -#define DUK_UINT_FAST_MIN DUK_UINT_FAST32_MIN -#define DUK_UINT_FAST_MAX DUK_UINT_FAST32_MAX - -/* Small integers (16 bits or more) can fall back to the 'int' type, but - * have a typedef so they are marked "small" explicitly. - */ -typedef int duk_small_int_t; -typedef unsigned int duk_small_uint_t; -#define DUK_SMALL_INT_MIN INT_MIN -#define DUK_SMALL_INT_MAX INT_MAX -#define DUK_SMALL_UINT_MIN 0 -#define DUK_SMALL_UINT_MAX UINT_MAX - -/* Fast variants of small integers, again for really fast paths like the - * executor. - */ -typedef duk_int_fast16_t duk_small_int_fast_t; -typedef duk_uint_fast16_t duk_small_uint_fast_t; -#define DUK_SMALL_INT_FAST_MIN DUK_INT_FAST16_MIN -#define DUK_SMALL_INT_FAST_MAX DUK_INT_FAST16_MAX -#define DUK_SMALL_UINT_FAST_MIN DUK_UINT_FAST16_MIN -#define DUK_SMALL_UINT_FAST_MAX DUK_UINT_FAST16_MAX - -/* Boolean values are represented with the platform 'int'. */ -typedef duk_small_int_t duk_bool_t; -#define DUK_BOOL_MIN DUK_SMALL_INT_MIN -#define DUK_BOOL_MAX DUK_SMALL_INT_MAX - -/* Index values must have at least 32-bit signed range. */ -typedef duk_int_t duk_idx_t; -#define DUK_IDX_MIN DUK_INT_MIN -#define DUK_IDX_MAX DUK_INT_MAX - -/* Array index values, could be exact 32 bits. - * Currently no need for signed duk_arridx_t. - */ -typedef duk_uint_t duk_uarridx_t; -#define DUK_UARRIDX_MIN DUK_UINT_MIN -#define DUK_UARRIDX_MAX DUK_UINT_MAX - -/* Duktape/C function return value, platform int is enough for now to - * represent 0, 1, or negative error code. Must be compatible with - * assigning truth values (e.g. duk_ret_t rc = (foo == bar);). - */ -typedef duk_small_int_t duk_ret_t; -#define DUK_RET_MIN DUK_SMALL_INT_MIN -#define DUK_RET_MAX DUK_SMALL_INT_MAX - -/* Error codes are represented with platform int. High bits are used - * for flags and such, so 32 bits are needed. - */ -typedef duk_int_t duk_errcode_t; -#define DUK_ERRCODE_MIN DUK_INT_MIN -#define DUK_ERRCODE_MAX DUK_INT_MAX - -/* Codepoint type. Must be 32 bits or more because it is used also for - * internal codepoints. The type is signed because negative codepoints - * are used as internal markers (e.g. to mark EOF or missing argument). - * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to - * ensure duk_uint32_t casts back and forth nicely. Almost everything - * else uses the signed one. - */ -typedef duk_int_t duk_codepoint_t; -typedef duk_uint_t duk_ucodepoint_t; -#define DUK_CODEPOINT_MIN DUK_INT_MIN -#define DUK_CODEPOINT_MAX DUK_INT_MAX -#define DUK_UCODEPOINT_MIN DUK_UINT_MIN -#define DUK_UCODEPOINT_MAX DUK_UINT_MAX - -/* IEEE double typedef. */ -typedef double duk_double_t; - -/* We're generally assuming that we're working on a platform with a 32-bit - * address space. If DUK_SIZE_MAX is a typecast value (which is necessary - * if SIZE_MAX is missing), the check must be avoided because the - * preprocessor can't do a comparison. - */ -#if !defined(DUK_SIZE_MAX) -#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX -#elif !defined(DUK_SIZE_MAX_COMPUTED) -#if DUK_SIZE_MAX < 0xffffffffUL -/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value - * which seems incorrect if size_t is (at least) an unsigned 32-bit type. - * However, it doesn't seem useful to error out compilation if this is the - * case. - */ -#endif -#endif - -/* 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 -#endif - -/* - * Check whether we should use 64-bit integers - */ - -/* Quite incomplete now. Use 64-bit types if detected (C99 or other detection) - * unless they are known to be unreliable. For instance, 64-bit types are - * available on VBCC but seem to misbehave. - */ -#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC) -#define DUK_USE_64BIT_OPS -#else -#undef DUK_USE_64BIT_OPS -#endif - -/* - * 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. - */ - -#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE -#undef DUK_USE_ALIGN_4 -#undef DUK_USE_ALIGN_8 - -#if defined(DUK_F_EMSCRIPTEN) -/* Required on at least some targets, so use whenever Emscripten used, - * regardless of compilation target. - */ -#define DUK_USE_ALIGN_8 -#elif defined(DUK_F_ARM) -#define DUK_USE_ALIGN_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_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_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_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_UNALIGNED_ACCESSES_POSSIBLE -#else -/* Unknown, use safe default */ -#define DUK_USE_ALIGN_8 -#endif - -/* User forced alignment to 4 or 8. */ -#if defined(DUK_OPT_FORCE_ALIGN) -#undef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE -#undef DUK_USE_ALIGN_4 -#undef DUK_USE_ALIGN_8 -#if (DUK_OPT_FORCE_ALIGN == 4) -#define DUK_USE_ALIGN_4 -#elif (DUK_OPT_FORCE_ALIGN == 8) -#define DUK_USE_ALIGN_8 -#else -#error invalid DUK_OPT_FORCE_ALIGN value -#endif -#endif - -/* Compiler specific hackery needed to force struct size to match aligment, - * see e.g. duk_hbuffer.h. - * - * http://stackoverflow.com/questions/11130109/c-struct-size-alignment - * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment - */ -#if defined(DUK_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 -#endif - -#ifdef DUK_USE_UNALIGNED_ACCESSES_POSSIBLE -#define DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS -#else -#undef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS -#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) && \ - !defined(DUK_USE_ALIGN_4) && !defined(DUK_USE_ALIGN_8) -/* 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 - -/* - * Byte order and double memory layout detection - * - * Endianness detection is a major portability hassle because the macros - * and headers are not standardized. There's even variance across UNIX - * platforms. Even with "standard" headers, details like underscore count - * varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used - * (Crossbridge has a single underscore, for instance). - * - * The checks below are structured with this in mind: several approaches are - * used, and at the end we check if any of them worked. This allows generic - * approaches to be tried first, and platform/compiler specific hacks tried - * last. As a last resort, the user can force a specific endianness, as it's - * not likely that automatic detection will work on the most exotic platforms. - * - * Duktape supports little and big endian machines. There's also support - * for a hybrid used by some ARM machines where integers are little endian - * but IEEE double values use a mixed order (12345678 -> 43218765). This - * byte order for doubles is referred to as "mixed endian". - */ - -#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 - */ - -/* For custom platforms allow user to define byteorder explicitly. - * Since endianness headers are not standardized, this is a useful - * workaround for custom platforms for which endianness detection - * is not directly supported. Perhaps custom hardware is used and - * user cannot submit upstream patches. - */ -#if defined(DUK_OPT_FORCE_BYTEORDER) -#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 -#else -#error invalid DUK_OPT_FORCE_BYTEORDER value -#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 */ -#if !defined(DUK_F_BYTEORDER) && defined(DUK_F_AMIGAOS) -#if defined(DUK_F_M68K) || defined(DUK_F_PPC) -#define DUK_F_BYTEORDER 3 -#endif -#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 -#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 - - * | 0 | 1 | 2 | ..... - * ^-- p=3, points after last valid byte (2) - * - * 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). - */ -#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 - */ -#if defined(DUK_F_UCLIBC) -#define DUK_MEMCPY memmove -#else -#define DUK_MEMCPY memcpy -#endif - -#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 - -#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 - */ -#define DUK_SNPRINTF _snprintf -#else -#define DUK_SNPRINTF snprintf -#endif - -#define DUK_VSPRINTF vsprintf - -#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 -#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)) - -/* - * 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 - -/* - * 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. - */ - -#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. - * This is not the case on all platforms (it may be a single-array element, - * for instance). - */ -#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0) -#endif - -/* - * Miscellaneous ANSI C or other platform wrappers. - */ - -#define DUK_ABORT abort -#define DUK_EXIT exit - -/* - * 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_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"). - */ -#define DUK_NORETURN(decl) decl -#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_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) -#endif -#else -/* unknown */ -#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 */ -#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) - */ -#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) -#endif -#endif /* DUK_USE_BRANCH_HINTS */ - -#if !defined(DUK_LIKELY) -#define DUK_LIKELY(x) (x) -#endif -#if !defined(DUK_UNLIKELY) -#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. - */ - -#if defined(DUK_F_CLANG) -#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) -#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 - -/* - * 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 -#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 -#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_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 -#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_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. */ -#define DUK_LOCAL_DECL static -#define DUK_LOCAL static - -/* - * __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). - */ - -#define DUK_FILE_MACRO __FILE__ - -#define DUK_LINE_MACRO __LINE__ - -#if !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) -#define DUK_FUNC_MACRO __func__ -#else -#define DUK_FUNC_MACRO "unknown" -#endif - -/* - * Byteswap macros - * - * These are here so that inline assembly or other platform functions can be - * used if available. - */ - -#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)) - -#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_M68K) -#define DUK_USE_ARCH_STRING "m68k" -#elif defined(DUK_F_PPC) -#define DUK_USE_ARCH_STRING "ppc" -#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 - */ - -#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" -#else -#define DUK_USE_OS_STRING "ios-unknown" -#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" -#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" -#endif - -/* - * Long control transfer, setjmp/longjmp or alternatives - * - * Signal mask is not saved (when that can be communicated to the platform) - */ - -/* dummy non-zero value to be used as an argument for longjmp(), see man longjmp */ -#define DUK_LONGJMP_DUMMY_VALUE 1 - -#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 -#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 -#endif - -/* - * Target info string - */ - -#if defined(DUK_OPT_TARGET_INFO) -#define DUK_USE_TARGET_INFO DUK_OPT_TARGET_INFO -#else -#define DUK_USE_TARGET_INFO "unknown" -#endif - -/* - * Speed/size and other performance options - */ - -/* 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 - -/* 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 - -/* 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. - */ -#define DUK_USE_PREFER_SIZE - -/* - * Tagged type representation (duk_tval) - */ - -#undef DUK_USE_PACKED_TVAL - -#if defined(DUK_USE_PACKED_TVAL_POSSIBLE) && !defined(DUK_OPT_NO_PACKED_TVAL) -#define DUK_USE_PACKED_TVAL -#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 -#endif -#define DUK_USE_FASTINT -#endif - -/* - * Memory management options - */ - -#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_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? - */ -#endif - -#if defined(DUK_OPT_NO_MARK_AND_SWEEP) -#undef DUK_USE_MARK_AND_SWEEP -#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 -#endif -#endif - -#if !defined(DUK_USE_MARK_AND_SWEEP) && !defined(DUK_USE_REFERENCE_COUNTING) -#error must have either mark-and-sweep or reference counting enabled -#endif - -#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE) -#undef DUK_USE_MS_STRINGTABLE_RESIZE -#endif - -#undef DUK_USE_GC_TORTURE -#if defined(DUK_OPT_GC_TORTURE) -#define DUK_USE_GC_TORTURE -#endif - -/* - * String table options - */ - -#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 -#else -/* Default algorithm: open addressing (probing) */ -#define DUK_USE_STRTAB_PROBE -#endif - -/* - * Error handling options - */ - -#define DUK_USE_AUGMENT_ERROR_CREATE -#define DUK_USE_AUGMENT_ERROR_THROW -#define DUK_USE_TRACEBACKS -#define DUK_USE_ERRCREATE -#define DUK_USE_ERRTHROW - -#define DUK_USE_VERBOSE_ERRORS - -#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 -#endif - -#if defined(DUK_OPT_NO_VERBOSE_ERRORS) -#undef DUK_USE_VERBOSE_ERRORS -#endif - -#if defined(DUK_USE_TRACEBACKS) -#if defined(DUK_OPT_TRACEBACK_DEPTH) -#define DUK_USE_TRACEBACK_DEPTH DUK_OPT_TRACEBACK_DEPTH -#else -#define DUK_USE_TRACEBACK_DEPTH 10 -#endif -#endif - -/* Include messages in executor internal errors. */ -#define DUK_USE_VERBOSE_EXECUTOR_ERRORS - -/* - * Execution and debugger options - */ - -#undef DUK_USE_INTERRUPT_COUNTER -#if defined(DUK_OPT_INTERRUPT_COUNTER) -#define DUK_USE_INTERRUPT_COUNTER -#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)) -#endif - -#undef DUK_USE_DEBUGGER_SUPPORT -#if defined(DUK_OPT_DEBUGGER_SUPPORT) -#define DUK_USE_DEBUGGER_SUPPORT -#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 -#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 -#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 -#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 -#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_DEBUG -#undef DUK_USE_DPRINT -#undef DUK_USE_DDPRINT -#undef DUK_USE_DDDPRINT -#undef DUK_USE_DPRINT_RDTSC -#undef DUK_USE_ASSERTIONS - -/* 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 -#endif - -#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DPRINT) -#define DUK_USE_DPRINT -#endif -#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDPRINT) -#define DUK_USE_DDPRINT -#endif -#if defined(DUK_OPT_DEBUG) && defined(DUK_OPT_DDDPRINT) -#define DUK_USE_DDDPRINT -#endif - -#undef DUK_USE_DPRINT_COLORS -#if defined(DUK_OPT_DPRINT_COLORS) -#define DUK_USE_DPRINT_COLORS -#endif - -#if defined(DUK_RDTSC_AVAILABLE) && defined(DUK_OPT_DPRINT_RDTSC) -#define DUK_USE_DPRINT_RDTSC -#else -#undef DUK_USE_DPRINT_RDTSC -#endif - -#if defined(DUK_OPT_ASSERTIONS) -#define DUK_USE_ASSERTIONS -#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 -#else -#define DUK_USE_DEBUG_BUFSIZE 65536L -#endif - -/* - * Ecmascript features / compliance options - */ - -#if defined(DUK_F_BCC) -/* Math built-in is stubbed out on BCC to allow compiler torture testing. */ -#else -#define DUK_USE_MATH_BUILTIN -#endif - -#define DUK_USE_STRICT_DECL -#if defined(DUK_OPT_NO_STRICT_DECL) -#undef DUK_USE_STRICT_DECL -#endif - -#define DUK_USE_REGEXP_SUPPORT -#if defined(DUK_OPT_NO_REGEXP_SUPPORT) -#undef DUK_USE_REGEXP_SUPPORT -#endif - -#undef DUK_USE_STRICT_UTF8_SOURCE -#if defined(DUK_OPT_STRICT_UTF8_SOURCE) -#define DUK_USE_STRICT_UTF8_SOURCE -#endif - -#define DUK_USE_OCTAL_SUPPORT -#if defined(DUK_OPT_NO_OCTAL_SUPPORT) -#undef DUK_USE_OCTAL_SUPPORT -#endif - -#define DUK_USE_SOURCE_NONBMP -#if defined(DUK_OPT_NO_SOURCE_NONBMP) -#undef DUK_USE_SOURCE_NONBMP -#endif - -#define DUK_USE_BROWSER_LIKE -#if defined(DUK_OPT_NO_BROWSER_LIKE) -#undef DUK_USE_BROWSER_LIKE -#endif - -/* E5/E5.1 Section B features. */ -#define DUK_USE_SECTION_B -#if defined(DUK_OPT_NO_SECTION_B) -#undef DUK_USE_SECTION_B -#endif - -/* Non-standard regexp parsing features. */ -#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE - -/* 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 -#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 -#endif - -/* Array.prototype.concat() non-standard but real world compatible behavior - * for non-existent trailing elements. - */ -#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER -#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER) -#undef DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER -#endif - -/* Array.prototype.map() non-standard but real world compatible behavior - * for non-existent trailing elements. - */ -#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER -#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER) -#undef 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 draft), 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 draft), 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 -#endif - -/* Record pc-to-line information. */ -#define DUK_USE_PC2LINE -#if defined(DUK_OPT_NO_PC2LINE) -#undef DUK_USE_PC2LINE -#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 -#endif - -/* CommonJS modules */ -#define DUK_USE_COMMONJS_MODULES -#if defined(DUK_OPT_NO_COMMONJS_MODULES) -#undef DUK_USE_COMMONJS_MODULES -#endif - -/* Additional key argument to setter/getter calls when triggered by property - * accesses. - */ - -#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT -#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT -#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT) -#undef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT -#undef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT -#endif - -/* JSON escaping of U+2028 and U+2029. - */ - -#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029 -#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029) -#undef 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 -#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 -#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 -#endif - -/* - * Deep vs. shallow stack. - * - * Some embedded platforms have very shallow stack (e.g. 64kB); default to - * a shallow stack on unknown platforms or known embedded platforms. */ -#if defined(DUK_F_LINUX) || defined(DUK_F_BSD) || defined(DUK_F_WINDOWS) || \ - defined(DUK_OPT_DEEP_C_STACK) -#define DUK_USE_DEEP_C_STACK -#else -#undef DUK_USE_DEEP_C_STACK -#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 -#endif - -/* - * User panic handler, panic exit behavior for default panic handler - */ - -#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 -#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 -#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 -#endif - -/* - * Codecs - */ - -#define DUK_USE_JX -#if defined(DUK_OPT_NO_JX) -#undef DUK_USE_JX -#endif - -#define DUK_USE_JC -#if defined(DUK_OPT_NO_JC) -#undef DUK_USE_JC -#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) -#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 -#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)) -#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)) -#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 -#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)) -#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)) -#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)) -#endif - -#undef DUK_USE_REFCOUNT16 -#if defined(DUK_OPT_REFCOUNT16) -#define DUK_USE_REFCOUNT16 -#endif - -#undef DUK_USE_STRHASH16 -#if defined(DUK_OPT_STRHASH16) -#define DUK_USE_STRHASH16 -#endif - -#undef DUK_USE_STRLEN16 -#if defined(DUK_OPT_STRLEN16) -#define DUK_USE_STRLEN16 -#endif - -#undef DUK_USE_BUFLEN16 -#if defined(DUK_OPT_BUFLEN16) -#define DUK_USE_BUFLEN16 -#endif - -#undef DUK_USE_OBJSIZES16 -#if defined(DUK_OPT_OBJSIZES16) -#define DUK_USE_OBJSIZES16 -#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 -#endif - -/* - * Miscellaneous - */ - -#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS -#undef DUK_USE_EXPLICIT_NULL_INIT - -#if !defined(DUK_USE_PACKED_TVAL) -#define DUK_USE_EXPLICIT_NULL_INIT -#endif - -#define DUK_USE_ZERO_BUFFER_DATA -#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA) -#undef DUK_USE_ZERO_BUFFER_DATA -#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 -#endif -#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] - */ - -/* 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 -#else -#define DUK_USE_FLEX_ONESIZE -#endif - +/* AUTHORS.rst */ /* - * GCC pragmas - */ - -/* 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. + * =============== + * Duktape authors + * =============== + * + * Copyright + * ========= + * + * Duktape copyrights are held by its authors. Each author has a copyright + * to their contribution, and agrees to irrevocably license the contribution + * under the Duktape ``LICENSE.txt``. + * + * Authors + * ======= + * + * Please include an e-mail address, a link to your GitHub profile, or something + * similar to allow your contribution to be identified accurately. + * + * The following people have contributed code and agreed to irrevocably license + * their contributions under the Duktape ``LICENSE.txt`` (in order of appearance): + * + * * Sami Vaarala + * * Niki Dobrev + * * Andreas \u00d6man + * * L\u00e1szl\u00f3 Lang\u00f3 + * * Legimet + * * Karl Skomski + * + * Other contributions + * =================== + * + * The following people have contributed something other than code (e.g. reported + * bugs, provided ideas, etc; roughly in order of appearance): + * + * * Greg Burns + * * Anthony Rabine + * * Carlos Costa + * * Aur\u00e9lien Bouilland + * * Preet Desai (Pris Matic) + * * judofyr (http://www.reddit.com/user/judofyr) + * * Jason Woofenden + * * Micha\u0142 Przyby\u015b + * * Anthony Howe + * * Conrad Pankoff + * * Jim Schimpf + * * Rajaran Gaunker (https://github.com/zimbabao) + * * Andreas \u00d6man + * * Doug Sanden + * * Josh Engebretson (https://github.com/JoshEngebretson) + * * Remo Eichenberger (https://github.com/remoe) + * * Mamod Mehyar (https://github.com/mamod) + * * David Demelier (https://github.com/markand) + * * Tim Caswell (https://github.com/creationix) + * * Mitchell Blank Jr (https://github.com/mitchblank) + * * https://github.com/yushli + * * Seo Sanghyeon (https://github.com/sanxiyn) + * * Han ChoongWoo (https://github.com/tunz) + * * Joshua Peek (https://github.com/josh) + * * Bruce E. Pascoe (https://github.com/fatcerberus) + * * https://github.com/Kelledin + * * https://github.com/sstruchtrup + * * Michael Drake (https://github.com/tlsa) + * * https://github.com/chris-y + * + * If you are accidentally missing from this list, send me an e-mail + * (``sami.vaarala@iki.fi``) and I'll fix the omission. */ -/* 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 -#else -#undef DUK_USE_GCC_PRAGMAS -#endif -/* - * User declarations - */ +#ifndef DUKTAPE_H_INCLUDED +#define DUKTAPE_H_INCLUDED -#if defined(DUK_OPT_DECLARE) -#define DUK_USE_USER_DECLARE() DUK_OPT_DECLARE -#else -#define DUK_USE_USER_DECLARE() /* no user declarations */ -#endif +#define DUK_SINGLE_FILE -/* - * Alternative customization header - * - * If you want to modify the final DUK_USE_xxx flags directly (without - * using the available DUK_OPT_Xxx flags), define DUK_OPT_HAVE_CUSTOM_H - * and tweak the final flags there. +/* External duk_config.h provides platform/compiler/OS dependent + * typedefs and macros, and DUK_USE_xxx config options so that + * the rest of Duktape doesn't need to do any feature detection. */ - -#if defined(DUK_OPT_HAVE_CUSTOM_H) -#include "duk_custom.h" -#endif - -#endif /* DUK_FEATURES_H_INCLUDED */ +#include "duk_config.h" /* * BEGIN PUBLIC API @@ -3138,9 +149,6 @@ extern "C" { /* * Public API specific typedefs * - * (duk_context *) maps directly to internal type (duk_hthread *). - * Currently only primitive typedefs have a '_t' suffix. - * * Many types are wrapped by Duktape for portability to rare platforms * where e.g. 'int' is a 16-bit type. See practical typing discussion * in Duktape web documentation. @@ -3150,7 +158,9 @@ struct duk_memory_functions; struct duk_function_list_entry; struct duk_number_list_entry; -typedef void duk_context; +/* duk_context is now defined in duk_config.h because it may also be + * referenced there by prototypes. + */ typedef struct duk_memory_functions duk_memory_functions; typedef struct duk_function_list_entry duk_function_list_entry; typedef struct duk_number_list_entry duk_number_list_entry; @@ -3198,13 +208,13 @@ struct duk_number_list_entry { * have 99 for patch level (e.g. 0.10.99 would be a development version * after 0.10.0 but before the next official release). */ -#define DUK_VERSION 10203L +#define DUK_VERSION 10299L /* Git describe for Duktape build. Useful for non-official snapshot builds * so that application code can easily log which Duktape snapshot was used. * Not available in the Ecmascript environment. */ -#define DUK_GIT_DESCRIBE "v1.2.3" +#define DUK_GIT_DESCRIBE "v1.2.0-310-g2a41d0a" /* Duktape debug protocol version used by this build. */ #define DUK_DEBUG_PROTOCOL_VERSION 1 @@ -3612,6 +622,7 @@ DUK_EXTERNAL_DECL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index); DUK_EXTERNAL_DECL const char *duk_get_string(duk_context *ctx, duk_idx_t index); DUK_EXTERNAL_DECL const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len); DUK_EXTERNAL_DECL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size); +DUK_EXTERNAL_DECL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size); DUK_EXTERNAL_DECL void *duk_get_pointer(duk_context *ctx, duk_idx_t index); DUK_EXTERNAL_DECL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index); DUK_EXTERNAL_DECL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index); @@ -3635,6 +646,7 @@ DUK_EXTERNAL_DECL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index) DUK_EXTERNAL_DECL const char *duk_require_string(duk_context *ctx, duk_idx_t index); DUK_EXTERNAL_DECL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len); DUK_EXTERNAL_DECL void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size); +DUK_EXTERNAL_DECL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size); 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); @@ -3706,6 +718,7 @@ DUK_EXTERNAL_DECL void duk_json_decode(duk_context *ctx, duk_idx_t index); */ DUK_EXTERNAL_DECL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size); +DUK_EXTERNAL_DECL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size); /* * Property access @@ -3805,6 +818,7 @@ DUK_EXTERNAL_DECL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t i DUK_EXTERNAL_DECL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2); DUK_EXTERNAL_DECL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2); +DUK_EXTERNAL_DECL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2); /* * Function (method) calls @@ -3950,6 +964,13 @@ DUK_EXTERNAL_DECL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_bu (void) duk_push_string((ctx), (path)), \ duk_compile_raw((ctx), NULL, 0, (flags) | DUK_COMPILE_SAFE)) +/* + * Bytecode load/dump + */ + +DUK_EXTERNAL_DECL void duk_dump_function(duk_context *ctx); +DUK_EXTERNAL_DECL void duk_load_function(duk_context *ctx); + /* * Logging */ @@ -3996,131 +1017,98 @@ DUK_EXTERNAL_DECL void duk_debugger_detach(duk_context *ctx); DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx); /* - * C++ name mangling + * Date provider related constants + * + * NOTE: These are "semi public" - you should only use these if you write + * your own platform specific Date provider, see doc/datetime.rst. */ -#ifdef __cplusplus -/* end 'extern "C"' wrapper */ -} -#endif - -#endif /* DUK_API_PUBLIC_H_INCLUDED */ +/* Millisecond count constants. */ +#define DUK_DATE_MSEC_SECOND 1000L +#define DUK_DATE_MSEC_MINUTE (60L * 1000L) +#define DUK_DATE_MSEC_HOUR (60L * 60L * 1000L) +#define DUK_DATE_MSEC_DAY (24L * 60L * 60L * 1000L) -/* - * END PUBLIC API +/* Ecmascript date range is 100 million days from Epoch: + * > 100e6 * 24 * 60 * 60 * 1000 // 100M days in millisecs + * 8640000000000000 + * (= 8.64e15) */ +#define DUK_DATE_MSEC_100M_DAYS (8.64e15) +#define DUK_DATE_MSEC_100M_DAYS_LEEWAY (8.64e15 + 24 * 3600e3) -/* - * Sanity check for the final effective internal defines. This file also - * double checks user tweaks made by an optional duk_custom.h header. +/* Ecmascript year range: + * > new Date(100e6 * 24 * 3600e3).toISOString() + * '+275760-09-13T00:00:00.000Z' + * > new Date(-100e6 * 24 * 3600e3).toISOString() + * '-271821-04-20T00:00:00.000Z' */ +#define DUK_DATE_MIN_ECMA_YEAR (-271821L) +#define DUK_DATE_MAX_ECMA_YEAR 275760L -#ifndef DUK_FEATURES_SANITY_H_INCLUDED -#define DUK_FEATURES_SANITY_H_INCLUDED - -/* - * Deprecated feature options. +/* Part indices for internal breakdowns. Part order from DUK_DATE_IDX_YEAR + * to DUK_DATE_IDX_MILLISECOND matches argument ordering of Ecmascript API + * calls (like Date constructor call). Some functions in duk_bi_date.c + * depend on the specific ordering, so change with care. 16 bits are not + * enough for all parts (year, specifically). * - * Catch so that user more easily notices and updates build. + * (Must be in-sync with genbuiltins.py.) */ +#define DUK_DATE_IDX_YEAR 0 /* year */ +#define DUK_DATE_IDX_MONTH 1 /* month: 0 to 11 */ +#define DUK_DATE_IDX_DAY 2 /* day within month: 0 to 30 */ +#define DUK_DATE_IDX_HOUR 3 +#define DUK_DATE_IDX_MINUTE 4 +#define DUK_DATE_IDX_SECOND 5 +#define DUK_DATE_IDX_MILLISECOND 6 +#define DUK_DATE_IDX_WEEKDAY 7 /* weekday: 0 to 6, 0=sunday, 1=monday, etc */ +#define DUK_DATE_IDX_NUM_PARTS 8 -#if defined(DUK_OPT_NO_FUNC_STMT) -#error DUK_OPT_NO_FUNC_STMT is deprecated, use DUK_OPT_NO_NONSTD_FUNC_STMT -#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 -#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 -#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 -#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 -#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 -#endif - -#if defined(DUK_OPT_NO_JSONX) -#error DUK_OPT_NO_JSONX is deprecated, use DUK_OPT_NO_JX -#endif - -#if defined(DUK_OPT_NO_JSONC) -#error DUK_OPT_NO_JSONC is deprecated, use DUK_OPT_NO_JC -#endif - -/* - * Debug print consistency +/* Internal API call flags, used for various functions in this file. + * Certain flags are used by only certain functions, but since the flags + * don't overlap, a single flags value can be passed around to multiple + * functions. + * + * The unused top bits of the flags field are also used to pass values + * to helpers (duk__get_part_helper() and duk__set_part_helper()). + * + * (Must be in-sync with genbuiltins.py.) */ -#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG) -#error DUK_USE_DPRINT without DUK_USE_DEBUG -#endif - -#if defined(DUK_USE_DDPRINT) && !defined(DUK_USE_DEBUG) -#error DUK_USE_DDPRINT without DUK_USE_DEBUG -#endif - -#if defined(DUK_USE_DDDPRINT) && !defined(DUK_USE_DEBUG) -#error DUK_USE_DDDPRINT without DUK_USE_DEBUG -#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 -#endif - -/* - * Debugger consistency +/* NOTE: when writing a Date provider you only need a few specific + * flags from here, the rest are internal. Avoid using anything you + * don't need. */ -#if defined(DUK_USE_DEBUGGER_SUPPORT) -#if !defined(DUK_USE_INTERRUPT_COUNTER) -#error DUK_USE_INTERRUPT_COUNTER is needed when debugger support is enabled -#endif -#if !defined(DUK_USE_PC2LINE) -#error DUK_USE_PC2LINE is needed when debugger support is enabled -#endif -#endif +#define DUK_DATE_FLAG_NAN_TO_ZERO (1 << 0) /* timeval breakdown: internal time value NaN -> zero */ +#define DUK_DATE_FLAG_NAN_TO_RANGE_ERROR (1 << 1) /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */ +#define DUK_DATE_FLAG_ONEBASED (1 << 2) /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */ +#define DUK_DATE_FLAG_EQUIVYEAR (1 << 3) /* timeval breakdown: replace year with equivalent year in the [1971,2037] range for DST calculations */ +#define DUK_DATE_FLAG_LOCALTIME (1 << 4) /* convert time value to local time */ +#define DUK_DATE_FLAG_SUB1900 (1 << 5) /* getter: subtract 1900 from year when getting year part */ +#define DUK_DATE_FLAG_TOSTRING_DATE (1 << 6) /* include date part in string conversion result */ +#define DUK_DATE_FLAG_TOSTRING_TIME (1 << 7) /* include time part in string conversion result */ +#define DUK_DATE_FLAG_TOSTRING_LOCALE (1 << 8) /* use locale specific formatting if available */ +#define DUK_DATE_FLAG_TIMESETTER (1 << 9) /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */ +#define DUK_DATE_FLAG_YEAR_FIXUP (1 << 10) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */ +#define DUK_DATE_FLAG_SEP_T (1 << 11) /* string conversion: use 'T' instead of ' ' as a separator */ +#define DUK_DATE_FLAG_VALUE_SHIFT 12 /* additional values begin at bit 12 */ /* - * Garbage collection consistency + * C++ name mangling */ -#if defined(DUK_USE_REFERENCE_COUNTING) && !defined(DUK_USE_DOUBLE_LINKED_HEAP) -#error DUK_USE_REFERENCE_COUNTING defined without DUK_USE_DOUBLE_LINKED_HEAP +#ifdef __cplusplus +/* end 'extern "C"' wrapper */ +} #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 -#endif +#endif /* DUK_API_PUBLIC_H_INCLUDED */ /* - * Low memory feature consistency + * END PUBLIC API */ -#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 -#endif -#endif - -#if defined(DUK_USE_STRTAB_CHAIN) && defined(DUK_USE_STRTAB_PROBE) -#error both DUK_USE_STRTAB_CHAIN and DUK_USE_STRTAB_PROBE defined -#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 -#endif - -#endif /* DUK_FEATURES_SANITY_H_INCLUDED */ - /* * Union to access IEEE double memory representation, indexes for double * memory representation, and some macros for double manipulation. @@ -4180,6 +1168,7 @@ DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx); union duk_double_union { double d; + float f[2]; #ifdef DUK_USE_64BIT_OPS duk_uint64_t ull[1]; #endif @@ -4451,9 +1440,24 @@ typedef union duk_double_union duk_double_union; } while (0) #endif /* DUK_USE_PACKED_TVAL */ -/* Byteswap an (aligned) duk_double_union. */ +/* XXX: native 64-bit byteswaps when available */ + +/* 64-bit byteswap, same operation independent of target endianness. */ +#define DUK_DBLUNION_BSWAP64(u) do { \ + duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \ + duk__bswaptmp1 = (u)->ui[0]; \ + duk__bswaptmp2 = (u)->ui[1]; \ + duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \ + duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \ + (u)->ui[0] = duk__bswaptmp2; \ + (u)->ui[1] = duk__bswaptmp1; \ + } while (0) + +/* Byteswap an IEEE double in the duk_double_union from host to network + * order. For a big endian target this is a no-op. + */ #if defined(DUK_USE_DOUBLE_LE) -#define DUK_DBLUNION_BSWAP(u) do { \ +#define DUK_DBLUNION_DOUBLE_HTON(u) do { \ duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \ duk__bswaptmp1 = (u)->ui[0]; \ duk__bswaptmp2 = (u)->ui[1]; \ @@ -4463,7 +1467,7 @@ typedef union duk_double_union duk_double_union; (u)->ui[1] = duk__bswaptmp1; \ } while (0) #elif defined(DUK_USE_DOUBLE_ME) -#define DUK_DBLUNION_BSWAP(u) do { \ +#define DUK_DBLUNION_DOUBLE_HTON(u) do { \ duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \ duk__bswaptmp1 = (u)->ui[0]; \ duk__bswaptmp2 = (u)->ui[1]; \ @@ -4473,11 +1477,14 @@ typedef union duk_double_union duk_double_union; (u)->ui[1] = duk__bswaptmp2; \ } while (0) #elif defined(DUK_USE_DOUBLE_BE) -#define DUK_DBLUNION_BSWAP(u) do { } while (0) +#define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0) #else #error internal error, double endianness insane #endif +/* Reverse operation is the same. */ +#define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u)) + #endif /* DUK_DBLUNION_H_INCLUDED */ #endif /* DUKTAPE_H_INCLUDED */ -- cgit v1.2.3